openocd-0.9.0/0000755000175000017500000000000012526202234010146 500000000000000openocd-0.9.0/doc/0000755000175000017500000000000012526202227010715 500000000000000openocd-0.9.0/doc/version.texi0000644000175000017500000000013312526201705013212 00000000000000@set UPDATED 18 May 2015 @set UPDATED-MONTH May 2015 @set EDITION 0.9.0 @set VERSION 0.9.0 openocd-0.9.0/doc/openocd.info-10000644000175000017500000111223712526202221013300 00000000000000This is openocd.info, produced by makeinfo version 5.2 from openocd.texi. This User's Guide documents release 0.9.0, dated 18 May 2015, of the Open On-Chip Debugger (OpenOCD). * Copyright (C) 2008 The OpenOCD Project * Copyright (C) 2007-2008 Spencer Oliver * Copyright (C) 2008-2010 Oyvind Harboe * Copyright (C) 2008 Duane Ellis * Copyright (C) 2009-2010 David Brownell Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". INFO-DIR-SECTION Development START-INFO-DIR-ENTRY * OpenOCD: (openocd). OpenOCD User's Guide END-INFO-DIR-ENTRY  File: openocd.info, Node: Top, Next: About, Up: (dir) OpenOCD User's Guide ******************** This User's Guide documents release 0.9.0, dated 18 May 2015, of the Open On-Chip Debugger (OpenOCD). * Copyright (C) 2008 The OpenOCD Project * Copyright (C) 2007-2008 Spencer Oliver * Copyright (C) 2008-2010 Oyvind Harboe * Copyright (C) 2008 Duane Ellis * Copyright (C) 2009-2010 David Brownell Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". * Menu: * About:: About OpenOCD * Developers:: OpenOCD Developer Resources * Debug Adapter Hardware:: Debug Adapter Hardware * About Jim-Tcl:: About Jim-Tcl * Running:: Running OpenOCD * OpenOCD Project Setup:: OpenOCD Project Setup * Config File Guidelines:: Config File Guidelines * Daemon Configuration:: Daemon Configuration * Debug Adapter Configuration:: Debug Adapter Configuration * Reset Configuration:: Reset Configuration * TAP Declaration:: TAP Declaration * CPU Configuration:: CPU Configuration * Flash Commands:: Flash Commands * Flash Programming:: Flash Programming * PLD/FPGA Commands:: PLD/FPGA Commands * General Commands:: General Commands * Architecture and Core Commands:: Architecture and Core Commands * JTAG Commands:: JTAG Commands * Boundary Scan Commands:: Boundary Scan Commands * Utility Commands:: Utility Commands * TFTP:: TFTP * GDB and OpenOCD:: Using GDB and OpenOCD * Tcl Scripting API:: Tcl Scripting API * FAQ:: Frequently Asked Questions * Tcl Crash Course:: Tcl Crash Course * License:: GNU Free Documentation License * OpenOCD Concept Index:: Concept Index * Command and Driver Index:: Command and Driver Index  File: openocd.info, Node: About, Next: Developers, Prev: Top, Up: Top About ***** OpenOCD was created by Dominic Rath as part of a 2005 diploma thesis written at the University of Applied Sciences Augsburg (). Since that time, the project has grown into an active open-source project, supported by a diverse community of software and hardware developers from around the world. What is OpenOCD? ================ The Open On-Chip Debugger (OpenOCD) aims to provide debugging, in-system programming and boundary-scan testing for embedded target devices. It does so with the assistance of a "debug adapter", which is a small hardware module which helps provide the right kind of electrical signaling to the target being debugged. These are required since the debug host (on which OpenOCD runs) won't usually have native support for such signaling, or the connector needed to hook up to the target. Such debug adapters support one or more "transport" protocols, each of which involves different electrical signaling (and uses different messaging protocols on top of that signaling). There are many types of debug adapter, and little uniformity in what they are called. (There are also product naming differences.) These adapters are sometimes packaged as discrete dongles, which may generically be called "hardware interface dongles". Some development boards also integrate them directly, which may let the development board connect directly to the debug host over USB (and sometimes also to power it over USB). For example, a "JTAG Adapter" supports JTAG signaling, and is used to communicate with JTAG (IEEE 1149.1) compliant TAPs on your target board. A "TAP" is a "Test Access Port", a module which processes special instructions and data. TAPs are daisy-chained within and between chips and boards. JTAG supports debugging and boundary scan operations. There are also "SWD Adapters" that support Serial Wire Debug (SWD) signaling to communicate with some newer ARM cores, as well as debug adapters which support both JTAG and SWD transports. SWD supports only debugging, whereas JTAG also supports boundary scan operations. For some chips, there are also "Programming Adapters" supporting special transports used only to write code to flash memory, without support for on-chip debugging or boundary scan. (At this writing, OpenOCD does not support such non-debug adapters.) Dongles: OpenOCD currently supports many types of hardware dongles: USB-based, parallel port-based, and other standalone boxes that run OpenOCD internally. *Note Debug Adapter Hardware::. GDB Debug: It allows ARM7 (ARM7TDMI and ARM720t), ARM9 (ARM920T, ARM922T, ARM926EJ-S, ARM966E-S), XScale (PXA25x, IXP42x), Cortex-M3 (Stellaris LM3, ST STM32 and Energy Micro EFM32) and Intel Quark (x10xx) based cores to be debugged via the GDB protocol. Flash Programming: Flash writing is supported for external CFI-compatible NOR flashes (Intel and AMD/Spansion command set) and several internal flashes (LPC1700, LPC1800, LPC2000, LPC4300, AT91SAM7, AT91SAM3U, STR7x, STR9x, LM3, STM32x and EFM32). Preliminary support for various NAND flash controllers (LPC3180, Orion, S3C24xx, more) is included. OpenOCD Web Site ================ The OpenOCD web site provides the latest public news from the community: Latest User's Guide: ==================== The user's guide you are now reading may not be the latest one available. A version for more recent code may be available. Its HTML form is published regularly at: PDF form is likewise published at: OpenOCD User's Forum ==================== There is an OpenOCD forum (phpBB) hosted by SparkFun, which might be helpful to you. Note that if you want anything to come to the attention of developers, you should post it to the OpenOCD Developer Mailing List instead of this forum. OpenOCD User's Mailing List =========================== The OpenOCD User Mailing List provides the primary means of communication between users: OpenOCD IRC =========== Support can also be found on irc:  File: openocd.info, Node: Developers, Next: Debug Adapter Hardware, Prev: About, Up: Top 1 OpenOCD Developer Resources ***************************** If you are interested in improving the state of OpenOCD's debugging and testing support, new contributions will be welcome. Motivated developers can produce new target, flash or interface drivers, improve the documentation, as well as more conventional bug fixes and enhancements. The resources in this chapter are available for developers wishing to explore or expand the OpenOCD source code. 1.1 OpenOCD Git Repository ========================== During the 0.3.x release cycle, OpenOCD switched from Subversion to a Git repository hosted at SourceForge. The repository URL is: or via http You may prefer to use a mirror and the HTTP protocol: With standard Git tools, use 'git clone' to initialize a local repository, and 'git pull' to update it. There are also gitweb pages letting you browse the repository with a web browser, or download arbitrary snapshots without needing a Git client: The 'README' file contains the instructions for building the project from the repository or a snapshot. Developers that want to contribute patches to the OpenOCD system are strongly encouraged to work against mainline. Patches created against older versions may require additional work from their submitter in order to be updated for newer releases. 1.2 Doxygen Developer Manual ============================ During the 0.2.x release cycle, the OpenOCD project began providing a Doxygen reference manual. This document contains more technical information about the software internals, development processes, and similar documentation: This document is a work-in-progress, but contributions would be welcome to fill in the gaps. All of the source files are provided in-tree, listed in the Doxyfile configuration at the top of the source tree. 1.3 Gerrit Review System ======================== All changes in the OpenOCD Git repository go through the web-based Gerrit Code Review System: After a one-time registration and repository setup, anyone can push commits from their local Git repository directly into Gerrit. All users and developers are encouraged to review, test, discuss and vote for changes in Gerrit. The feedback provides the basis for a maintainer to eventually submit the change to the main Git repository. The 'HACKING' file, also available as the Patch Guide in the Doxygen Developer Manual, contains basic information about how to connect a repository to Gerrit, prepare and push patches. Patch authors are expected to maintain their changes while they're in Gerrit, respond to feedback and if necessary rework and push improved versions of the change. 1.4 OpenOCD Developer Mailing List ================================== The OpenOCD Developer Mailing List provides the primary means of communication between developers: 1.5 OpenOCD Bug Tracker ======================= The OpenOCD Bug Tracker is hosted on SourceForge:  File: openocd.info, Node: Debug Adapter Hardware, Next: About Jim-Tcl, Prev: Developers, Up: Top 2 Debug Adapter Hardware ************************ Defined: dongle: A small device that plugs into a computer and serves as an adapter .... [snip] In the OpenOCD case, this generally refers to a small adapter that attaches to your computer via USB or the parallel port. One exception is the Ultimate Solutions ZY1000, packaged as a small box you attach via an ethernet cable. The ZY1000 has the advantage that it does not require any drivers to be installed on the developer PC. It also has a built in web interface. It supports RTCK/RCLK or adaptive clocking and has a built-in relay to power cycle targets remotely. 2.1 Choosing a Dongle ===================== There are several things you should keep in mind when choosing a dongle. 1. Transport Does it support the kind of communication that you need? OpenOCD focusses mostly on JTAG. Your version may also support other ways to communicate with target devices. 2. Voltage What voltage is your target - 1.8, 2.8, 3.3, or 5V? Does your dongle support it? You might need a level converter. 3. Pinout What pinout does your target board use? Does your dongle support it? You may be able to use jumper wires, or an "octopus" connector, to convert pinouts. 4. Connection Does your computer have the USB, parallel, or Ethernet port needed? 5. RTCK Do you expect to use it with ARM chips and boards with RTCK support (also known as "adaptive clocking")? 2.2 Stand-alone JTAG Probe ========================== The ZY1000 from Ultimate Solutions is technically not a dongle but a stand-alone JTAG probe that, unlike most dongles, doesn't require any drivers running on the developer's host computer. Once installed on a network using DHCP or a static IP assignment, users can access the ZY1000 probe locally or remotely from any host with access to the IP address assigned to the probe. The ZY1000 provides an intuitive web interface with direct access to the OpenOCD debugger. Users may also run a GDBSERVER directly on the ZY1000 to take full advantage of GCC & GDB to debug any distribution of embedded Linux or NetBSD running on the target. The ZY1000 supports RTCK & RCLK or adaptive clocking and has a built-in relay to power cycle the target remotely. For more information, visit: ZY1000 See: 2.3 USB FT2232 Based ==================== There are many USB JTAG dongles on the market, many of them based on a chip from "Future Technology Devices International" (FTDI) known as the FTDI FT2232; this is a USB full speed (12 Mbps) chip. See: for more information. In summer 2009, USB high speed (480 Mbps) versions of these FTDI chips started to become available in JTAG adapters. Around 2012, a new variant appeared - FT232H - this is a single-channel version of FT2232H. (Adapters using those high speed FT2232H or FT232H chips may support adaptive clocking.) The FT2232 chips are flexible enough to support some other transport options, such as SWD or the SPI variants used to program some chips. They have two communications channels, and one can be used for a UART adapter at the same time the other one is used to provide a debug adapter. Also, some development boards integrate an FT2232 chip to serve as a built-in low-cost debug adapter and USB-to-serial solution. * usbjtag Link * jtagkey See: * jtagkey2 See: * oocdlink See: By Joern Kaipf * signalyzer See: * Stellaris Eval Boards See: - The Stellaris eval boards bundle FT2232-based JTAG and SWD support, which can be used to debug the Stellaris chips. Using separate JTAG adapters is optional. These boards can also be used in a "pass through" mode as JTAG adapters to other target boards, disabling the Stellaris chip. * TI/Luminary ICDI See: - TI/Luminary In-Circuit Debug Interface (ICDI) Boards are included in Stellaris LM3S9B9x Evaluation Kits. Like the non-detachable FT2232 support on the other Stellaris eval boards, they can be used to debug other target boards. * olimex-jtag See: * Flyswatter/Flyswatter2 See: * turtelizer2 See: Turtelizer 2 (http://www.ethernut.de/en/hardware/turtelizer/index.html), or * comstick Link: * stm32stick Link * axm0432_jtag Axiom AXM-0432 Link - NOTE: This JTAG does not appear to be available anymore as of April 2012. * cortino Link * dlp-usb1232h Link * digilent-hs1 Link * opendous Link FT2232H-based (OpenHardware). * JTAG-lock-pick Tiny 2 Link FT232H-based * GW16042 Link: FT2232H-based 2.4 USB-JTAG / Altera USB-Blaster compatibles ============================================= These devices also show up as FTDI devices, but are not protocol-compatible with the FT2232 devices. They are, however, protocol-compatible among themselves. USB-JTAG devices typically consist of a FT245 followed by a CPLD that understands a particular protocol, or emulates this protocol using some other hardware. They may appear under different USB VID/PID depending on the particular product. The driver can be configured to search for any VID/PID pair (see the section on driver commands). * USB-JTAG Kolja Waschk's USB Blaster-compatible adapter Link: * Altera USB-Blaster Link: 2.5 USB JLINK based =================== There are several OEM versions of the Segger JLINK adapter. It is an example of a micro controller based JTAG adapter, it uses an AT91SAM764 internally. * ATMEL SAMICE Only works with ATMEL chips! Link: * SEGGER JLINK Link: * IAR J-Link Link: 2.6 USB RLINK based =================== Raisonance has an adapter called RLink. It exists in a stripped-down form on the STM32 Primer, permanently attached to the JTAG lines. It also exists on the STM32 Primer2, but that is wired for SWD and not JTAG, thus not supported. * Raisonance RLink Link: * STM32 Primer Link: * STM32 Primer2 Link: 2.7 USB ST-LINK based ===================== ST Micro has an adapter called ST-LINK. They only work with ST Micro chips, notably STM32 and STM8. * ST-LINK This is available standalone and as part of some kits, eg. STM32VLDISCOVERY. Link: * ST-LINK/V2 This is available standalone and as part of some kits, eg. STM32F4DISCOVERY. Link: For info the original ST-LINK enumerates using the mass storage usb class; however, its implementation is completely broken. The result is this causes issues under Linux. The simplest solution is to get Linux to ignore the ST-LINK using one of the following methods: * modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i * add "options usb-storage quirks=483:3744:i" to /etc/modprobe.conf 2.8 USB TI/Stellaris ICDI based =============================== Texas Instruments has an adapter called ICDI. It is not to be confused with the FTDI based adapters that were originally fitted to their evaluation boards. This is the adapter fitted to the Stellaris LaunchPad. 2.9 USB CMSIS-DAP based ======================= ARM has released a interface standard called CMSIS-DAP that simplifies connecting debuggers to ARM Cortex based targets . 2.10 USB Other ============== * USBprog Link: - which uses an Atmel MEGA32 and a UBN9604 * USB - Presto Link: * Versaloon-Link Link: * ARM-JTAG-EW Link: * Buspirate Link: * opendous Link: - which uses an AT90USB162 * estick Link: * Keil ULINK v1 Link: 2.11 IBM PC Parallel Printer Port Based ======================================= The two well-known "JTAG Parallel Ports" cables are the Xilinx DLC5 and the Macraigor Wiggler. There are many clones and variations of these on the market. Note that parallel ports are becoming much less common, so if you have the choice you should probably avoid these adapters in favor of USB-based ones. * Wiggler - There are many clones of this. Link: * DLC5 - From XILINX - There are many clones of this Link: Search the web for: "XILINX DLC5" - it is no longer produced, PDF schematics are easily found and it is easy to make. * Amontec - JTAG Accelerator Link: * Wiggler2 Link: * Wiggler_ntrst_inverted Yet another variation - See the source code, src/jtag/parport.c * old_amt_wiggler Unknown - probably not on the market today * arm-jtag Link: Most likely [another wiggler clone] * chameleon Link: * Triton Unknown. * Lattice ispDownload from Lattice Semiconductor * flashlink From ST Microsystems; Link: 2.12 Other... ============= * ep93xx An EP93xx based Linux machine using the GPIO pins directly. * at91rm9200 Like the EP93xx - but an ATMEL AT91RM9200 based solution using the GPIO pins on the chip. * bcm2835gpio A BCM2835-based board (e.g. Raspberry Pi) using the GPIO pins of the expansion header. * jtag_vpi A JTAG driver acting as a client for the JTAG VPI server interface. Link:  File: openocd.info, Node: About Jim-Tcl, Next: Running, Prev: Debug Adapter Hardware, Up: Top 3 About Jim-Tcl *************** OpenOCD uses a small "Tcl Interpreter" known as Jim-Tcl. This programming language provides a simple and extensible command interpreter. All commands presented in this Guide are extensions to Jim-Tcl. You can use them as simple commands, without needing to learn much of anything about Tcl. Alternatively, you can write Tcl programs with them. You can learn more about Jim at its website, . There is an active and responsive community, get on the mailing list if you have any questions. Jim-Tcl maintainers also lurk on the OpenOCD mailing list. * Jim vs. Tcl Jim-Tcl is a stripped down version of the well known Tcl language, which can be found here: . Jim-Tcl has far fewer features. Jim-Tcl is several dozens of .C files and .H files and implements the basic Tcl command set. In contrast: Tcl 8.6 is a 4.2 MB .zip file containing 1540 files. * Missing Features Our practice has been: Add/clone the real Tcl feature if/when needed. We welcome Jim-Tcl improvements, not bloat. Also there are a large number of optional Jim-Tcl features that are not enabled in OpenOCD. * Scripts OpenOCD configuration scripts are Jim-Tcl Scripts. OpenOCD's command interpreter today is a mixture of (newer) Jim-Tcl commands, and the (older) original command interpreter. * Commands At the OpenOCD telnet command line (or via the GDB monitor command) one can type a Tcl for() loop, set variables, etc. Some of the commands documented in this guide are implemented as Tcl scripts, from a 'startup.tcl' file internal to the server. * Historical Note Jim-Tcl was introduced to OpenOCD in spring 2008. Fall 2010, before OpenOCD 0.5 release, OpenOCD switched to using Jim-Tcl as a Git submodule, which greatly simplified upgrading Jim-Tcl to benefit from new features and bugfixes in Jim-Tcl. * Need a crash course in Tcl? *Note Tcl Crash Course::.  File: openocd.info, Node: Running, Next: OpenOCD Project Setup, Prev: About Jim-Tcl, Up: Top 4 Running ********* Properly installing OpenOCD sets up your operating system to grant it access to the debug adapters. On Linux, this usually involves installing a file in '/etc/udev/rules.d,' so OpenOCD has permissions. An example rules file that works for many common adapters is shipped with OpenOCD in the 'contrib' directory. MS-Windows needs complex and confusing driver configuration for every peripheral. Such issues are unique to each operating system, and are not detailed in this User's Guide. Then later you will invoke the OpenOCD server, with various options to tell it how each debug session should work. The '--help' option shows: bash$ openocd --help --help | -h display this help --version | -v display OpenOCD version --file | -f use configuration file --search | -s dir to search for config files and scripts --debug | -d set debug level <0-3> --log_output | -l redirect log output to file --command | -c run If you don't give any '-f' or '-c' options, OpenOCD tries to read the configuration file 'openocd.cfg'. To specify one or more different configuration files, use '-f' options. For example: openocd -f config1.cfg -f config2.cfg -f config3.cfg Configuration files and scripts are searched for in 1. the current directory, 2. any search dir specified on the command line using the '-s' option, 3. any search dir specified using the 'add_script_search_dir' command, 4. '$HOME/.openocd' (not on Windows), 5. the site wide script library '$pkgdatadir/site' and 6. the OpenOCD-supplied script library '$pkgdatadir/scripts'. The first found file with a matching file name will be used. Note: Don't try to use configuration script names or paths which include the "#" character. That character begins Tcl comments. 4.1 Simple setup, no customization ================================== In the best case, you can use two scripts from one of the script libraries, hook up your JTAG adapter, and start the server ... and your JTAG setup will just work "out of the box". Always try to start by reusing those scripts, but assume you'll need more customization even if this works. *Note OpenOCD Project Setup::. If you find a script for your JTAG adapter, and for your board or target, you may be able to hook up your JTAG adapter then start the server with some variation of one of the following: openocd -f interface/ADAPTER.cfg -f board/MYBOARD.cfg openocd -f interface/ftdi/ADAPTER.cfg -f board/MYBOARD.cfg You might also need to configure which reset signals are present, using '-c 'reset_config trst_and_srst'' or something similar. If all goes well you'll see output something like Open On-Chip Debugger 0.4.0 (2010-01-14-15:06) For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : JTAG tap: lm3s.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Seeing that "tap/device found" message, and no warnings, means the JTAG communication is working. That's a key milestone, but you'll probably need more project-specific setup. 4.2 What OpenOCD does as it starts ================================== OpenOCD starts by processing the configuration commands provided on the command line or, if there were no '-c command' or '-f file.cfg' options given, in 'openocd.cfg'. *Note Configuration Stage: configurationstage. At the end of the configuration stage it verifies the JTAG scan chain defined using those commands; your configuration should ensure that this always succeeds. Normally, OpenOCD then starts running as a daemon. Alternatively, commands may be used to terminate the configuration stage early, perform work (such as updating some flash memory), and then shut down without acting as a daemon. Once OpenOCD starts running as a daemon, it waits for connections from clients (Telnet, GDB, Other) and processes the commands issued through those channels. If you are having problems, you can enable internal debug messages via the '-d' option. Also it is possible to interleave Jim-Tcl commands w/config scripts using the '-c' command line switch. To enable debug output (when reporting problems or working on OpenOCD itself), use the '-d' command line switch. This sets the 'debug_level' to "3", outputting the most information, including debug messages. The default setting is "2", outputting only informational messages, warnings and errors. You can also change this setting from within a telnet or gdb session using 'debug_level' (*note debug_level: debuglevel.). You can redirect all output from the daemon to a file using the '-l ' switch. Note! OpenOCD will launch the GDB & telnet server even if it can not establish a connection with the target. In general, it is possible for the JTAG controller to be unresponsive until the target is set up correctly via e.g. GDB monitor commands in a GDB init script.  File: openocd.info, Node: OpenOCD Project Setup, Next: Config File Guidelines, Prev: Running, Up: Top 5 OpenOCD Project Setup *********************** To use OpenOCD with your development projects, you need to do more than just connect the JTAG adapter hardware (dongle) to your development board and start the OpenOCD server. You also need to configure your OpenOCD server so that it knows about your adapter and board, and helps your work. You may also want to connect OpenOCD to GDB, possibly using Eclipse or some other GUI. 5.1 Hooking up the JTAG Adapter =============================== Today's most common case is a dongle with a JTAG cable on one side (such as a ribbon cable with a 10-pin or 20-pin IDC connector) and a USB cable on the other. Instead of USB, some cables use Ethernet; older ones may use a PC parallel port, or even a serial port. 1. _Start with power to your target board turned off_, and nothing connected to your JTAG adapter. If you're particularly paranoid, unplug power to the board. It's important to have the ground signal properly set up, unless you are using a JTAG adapter which provides galvanic isolation between the target board and the debugging host. 2. _Be sure it's the right kind of JTAG connector._ If your dongle has a 20-pin ARM connector, you need some kind of adapter (or octopus, see below) to hook it up to boards using 14-pin or 10-pin connectors ... or to 20-pin connectors which don't use ARM's pinout. In the same vein, make sure the voltage levels are compatible. Not all JTAG adapters have the level shifters needed to work with 1.2 Volt boards. 3. _Be certain the cable is properly oriented_ or you might damage your board. In most cases there are only two possible ways to connect the cable. Connect the JTAG cable from your adapter to the board. Be sure it's firmly connected. In the best case, the connector is keyed to physically prevent you from inserting it wrong. This is most often done using a slot on the board's male connector housing, which must match a key on the JTAG cable's female connector. If there's no housing, then you must look carefully and make sure pin 1 on the cable hooks up to pin 1 on the board. Ribbon cables are frequently all grey except for a wire on one edge, which is red. The red wire is pin 1. Sometimes dongles provide cables where one end is an "octopus" of color coded single-wire connectors, instead of a connector block. These are great when converting from one JTAG pinout to another, but are tedious to set up. Use these with connector pinout diagrams to help you match up the adapter signals to the right board pins. 4. _Connect the adapter's other end_ once the JTAG cable is connected. A USB, parallel, or serial port connector will go to the host which you are using to run OpenOCD. For Ethernet, consult the documentation and your network administrator. For USB-based JTAG adapters you have an easy sanity check at this point: does the host operating system see the JTAG adapter? If you're running Linux, try the 'lsusb' command. If that host is an MS-Windows host, you'll need to install a driver before OpenOCD works. 5. _Connect the adapter's power supply, if needed._ This step is primarily for non-USB adapters, but sometimes USB adapters need extra power. 6. _Power up the target board._ Unless you just let the magic smoke escape, you're now ready to set up the OpenOCD server so you can use JTAG to work with that board. Talk with the OpenOCD server using telnet ('telnet localhost 4444' on many systems) or GDB. *Note GDB and OpenOCD::. 5.2 Project Directory ===================== There are many ways you can configure OpenOCD and start it up. A simple way to organize them all involves keeping a single directory for your work with a given board. When you start OpenOCD from that directory, it searches there first for configuration files, scripts, files accessed through semihosting, and for code you upload to the target board. It is also the natural place to write files, such as log files and data you download from the board. 5.3 Configuration Basics ======================== There are two basic ways of configuring OpenOCD, and a variety of ways you can mix them. Think of the difference as just being how you start the server: * Many '-f file' or '-c command' options on the command line * No options, but a "user config file" in the current directory named 'openocd.cfg' Here is an example 'openocd.cfg' file for a setup using a Signalyzer FT2232-based JTAG adapter to talk to a board with an Atmel AT91SAM7X256 microcontroller: source [find interface/signalyzer.cfg] # GDB can also flash my flash! gdb_memory_map enable gdb_flash_program enable source [find target/sam7x256.cfg] Here is the command line equivalent of that configuration: openocd -f interface/signalyzer.cfg \ -c "gdb_memory_map enable" \ -c "gdb_flash_program enable" \ -f target/sam7x256.cfg You could wrap such long command lines in shell scripts, each supporting a different development task. One might re-flash the board with a specific firmware version. Another might set up a particular debugging or run-time environment. Important: At this writing (October 2009) the command line method has problems with how it treats variables. For example, after '-c "set VAR value"', or doing the same in a script, the variable VAR will have no value that can be tested in a later script. Here we will focus on the simpler solution: one user config file, including basic configuration plus any TCL procedures to simplify your work. 5.4 User Config Files ===================== A user configuration file ties together all the parts of a project in one place. One of the following will match your situation best: * Ideally almost everything comes from configuration files provided by someone else. For example, OpenOCD distributes a 'scripts' directory (probably in '/usr/share/openocd/scripts' on Linux). Board and tool vendors can provide these too, as can individual user sites; the '-s' command line option lets you say where to find these files. (*Note Running::.) The AT91SAM7X256 example above works this way. Three main types of non-user configuration file each have their own subdirectory in the 'scripts' directory: 1. interface - one for each different debug adapter; 2. board - one for each different board 3. target - the chips which integrate CPUs and other JTAG TAPs Best case: include just two files, and they handle everything else. The first is an interface config file. The second is board-specific, and it sets up the JTAG TAPs and their GDB targets (by deferring to some 'target.cfg' file), declares all flash memory, and leaves you nothing to do except meet your deadline: source [find interface/olimex-jtag-tiny.cfg] source [find board/csb337.cfg] Boards with a single microcontroller often won't need more than the target config file, as in the AT91SAM7X256 example. That's because there is no external memory (flash, DDR RAM), and the board differences are encapsulated by application code. * Maybe you don't know yet what your board looks like to JTAG. Once you know the 'interface.cfg' file to use, you may need help from OpenOCD to discover what's on the board. Once you find the JTAG TAPs, you can just search for appropriate target and board configuration files ... or write your own, from the bottom up. *Note Autoprobing: autoprobing. * You can often reuse some standard config files but need to write a few new ones, probably a 'board.cfg' file. You will be using commands described later in this User's Guide, and working with the guidelines in the next chapter. For example, there may be configuration files for your JTAG adapter and target chip, but you need a new board-specific config file giving access to your particular flash chips. Or you might need to write another target chip configuration file for a new chip built around the Cortex M3 core. Note: When you write new configuration files, please submit them for inclusion in the next OpenOCD release. For example, a 'board/newboard.cfg' file will help the next users of that board, and a 'target/newcpu.cfg' will help support users of any board using that chip. * You may may need to write some C code. It may be as simple as supporting a new FT2232 or parport based adapter; a bit more involved, like a NAND or NOR flash controller driver; or a big piece of work like supporting a new chip architecture. Reuse the existing config files when you can. Look first in the 'scripts/boards' area, then 'scripts/targets'. You may find a board configuration that's a good example to follow. When you write config files, separate the reusable parts (things every user of that interface, chip, or board needs) from ones specific to your environment and debugging approach. * For example, a 'gdb-attach' event handler that invokes the 'reset init' command will interfere with debugging early boot code, which performs some of the same actions that the 'reset-init' event handler does. * Likewise, the 'arm9 vector_catch' command (or its siblings 'xscale vector_catch' and 'cortex_m vector_catch') can be a timesaver during some debug sessions, but don't make everyone use that either. Keep those kinds of debugging aids in your user config file, along with messaging and tracing setup. (*Note Software Debug Messages and Tracing: softwaredebugmessagesandtracing.) * You might need to override some defaults. For example, you might need to move, shrink, or back up the target's work area if your application needs much SRAM. * TCP/IP port configuration is another example of something which is environment-specific, and should only appear in a user config file. *Note TCP/IP Ports: tcpipports. 5.5 Project-Specific Utilities ============================== A few project-specific utility routines may well speed up your work. Write them, and keep them in your project's user config file. For example, if you are making a boot loader work on a board, it's nice to be able to debug the "after it's loaded to RAM" parts separately from the finicky early code which sets up the DDR RAM controller and clocks. A script like this one, or a more GDB-aware sibling, may help: proc ramboot { } { # Reset, running the target's "reset-init" scripts # to initialize clocks and the DDR RAM controller. # Leave the CPU halted. reset init # Load CONFIG_SKIP_LOWLEVEL_INIT version into DDR RAM. load_image u-boot.bin 0x20000000 # Start running. resume 0x20000000 } Then once that code is working you will need to make it boot from NOR flash; a different utility would help. Alternatively, some developers write to flash using GDB. (You might use a similar script if you're working with a flash based microcontroller application instead of a boot loader.) proc newboot { } { # Reset, leaving the CPU halted. The "reset-init" event # proc gives faster access to the CPU and to NOR flash; # "reset halt" would be slower. reset init # Write standard version of U-Boot into the first two # sectors of NOR flash ... the standard version should # do the same lowlevel init as "reset-init". flash protect 0 0 1 off flash erase_sector 0 0 1 flash write_bank 0 u-boot.bin 0x0 flash protect 0 0 1 on # Reboot from scratch using that new boot loader. reset run } You may need more complicated utility procedures when booting from NAND. That often involves an extra bootloader stage, running from on-chip SRAM to perform DDR RAM setup so it can load the main bootloader code (which won't fit into that SRAM). Other helper scripts might be used to write production system images, involving considerably more than just a three stage bootloader. 5.6 Target Software Changes =========================== Sometimes you may want to make some small changes to the software you're developing, to help make JTAG debugging work better. For example, in C or assembly language code you might use '#ifdef JTAG_DEBUG' (or its converse) around code handling issues like: * Watchdog Timers... Watchog timers are typically used to automatically reset systems if some application task doesn't periodically reset the timer. (The assumption is that the system has locked up if the task can't run.) When a JTAG debugger halts the system, that task won't be able to run and reset the timer ... potentially causing resets in the middle of your debug sessions. It's rarely a good idea to disable such watchdogs, since their usage needs to be debugged just like all other parts of your firmware. That might however be your only option. Look instead for chip-specific ways to stop the watchdog from counting while the system is in a debug halt state. It may be simplest to set that non-counting mode in your debugger startup scripts. You may however need a different approach when, for example, a motor could be physically damaged by firmware remaining inactive in a debug halt state. That might involve a type of firmware mode where that "non-counting" mode is disabled at the beginning then re-enabled at the end; a watchdog reset might fire and complicate the debug session, but hardware (or people) would be protected.(1) * ARM Semihosting... When linked with a special runtime library provided with many toolchains(2), your target code can use I/O facilities on the debug host. That library provides a small set of system calls which are handled by OpenOCD. It can let the debugger provide your system console and a file system, helping with early debugging or providing a more capable environment for sometimes-complex tasks like installing system firmware onto NAND or SPI flash. * ARM Wait-For-Interrupt... Many ARM chips synchronize the JTAG clock using the core clock. Low power states which stop that core clock thus prevent JTAG access. Idle loops in tasking environments often enter those low power states via the 'WFI' instruction (or its coprocessor equivalent, before ARMv7). You may want to _disable that instruction_ in source code, or otherwise prevent using that state, to ensure you can get JTAG access at any time.(3) For example, the OpenOCD 'halt' command may not work for an idle processor otherwise. * Delay after reset... Not all chips have good support for debugger access right after reset; many LPC2xxx chips have issues here. Similarly, applications that reconfigure pins used for JTAG access as they start will also block debugger access. To work with boards like this, _enable a short delay loop_ the first thing after reset, before "real" startup activities. For example, one second's delay is usually more than enough time for a JTAG debugger to attach, so that early code execution can be debugged or firmware can be replaced. * Debug Communications Channel (DCC)... Some processors include mechanisms to send messages over JTAG. Many ARM cores support these, as do some cores from other vendors. (OpenOCD may be able to use this DCC internally, speeding up some operations like writing to memory.) Your application may want to deliver various debugging messages over JTAG, by _linking with a small library of code_ provided with OpenOCD and using the utilities there to send various kinds of message. *Note Software Debug Messages and Tracing: softwaredebugmessagesandtracing. 5.7 Target Hardware Setup ========================= Chip vendors often provide software development boards which are highly configurable, so that they can support all options that product boards may require. _Make sure that any jumpers or switches match the system configuration you are working with._ Common issues include: * JTAG setup ... Boards may support more than one JTAG configuration. Examples include jumpers controlling pullups versus pulldowns on the nTRST and/or nSRST signals, and choice of connectors (e.g. which of two headers on the base board, or one from a daughtercard). For some Texas Instruments boards, you may need to jumper the EMU0 and EMU1 signals (which OpenOCD won't currently control). * Boot Modes ... Complex chips often support multiple boot modes, controlled by external jumpers. Make sure this is set up correctly. For example many i.MX boards from NXP need to be jumpered to "ATX mode" to start booting using the on-chip ROM, when using second stage bootloader code stored in a NAND flash chip. Such explicit configuration is common, and not limited to booting from NAND. You might also need to set jumpers to start booting using code loaded from an MMC/SD card; external SPI flash; Ethernet, UART, or USB links; NOR flash; OneNAND flash; some external host; or various other sources. * Memory Addressing ... Boards which support multiple boot modes may also have jumpers to configure memory addressing. One board, for example, jumpers external chipselect 0 (used for booting) to address either a large SRAM (which must be pre-loaded via JTAG), NOR flash, or NAND flash. When it's jumpered to address NAND flash, that board must also be told to start booting from on-chip ROM. Your 'board.cfg' file may also need to be told this jumper configuration, so that it can know whether to declare NOR flash using 'flash bank' or instead declare NAND flash with 'nand device'; and likewise which probe to perform in its 'reset-init' handler. A closely related issue is bus width. Jumpers might need to distinguish between 8 bit or 16 bit bus access for the flash used to start booting. * Peripheral Access ... Development boards generally provide access to every peripheral on the chip, sometimes in multiple modes (such as by providing multiple audio codec chips). This interacts with software configuration of pin multiplexing, where for example a given pin may be routed either to the MMC/SD controller or the GPIO controller. It also often interacts with configuration jumpers. One jumper may be used to route signals to an MMC/SD card slot or an expansion bus (which might in turn affect booting); others might control which audio or video codecs are used. Plus you should of course have 'reset-init' event handlers which set up the hardware to match that jumper configuration. That includes in particular any oscillator or PLL used to clock the CPU, and any memory controllers needed to access external memory and peripherals. Without such handlers, you won't be able to access those resources without working target firmware which can do that setup ... this can be awkward when you're trying to debug that target firmware. Even if there's a ROM bootloader which handles a few issues, it rarely provides full access to all board-specific capabilities. ---------- Footnotes ---------- (1) Note that many systems support a "monitor mode" debug that is a somewhat cleaner way to address such issues. You can think of it as only halting part of the system, maybe just one task, instead of the whole thing. At this writing, January 2010, OpenOCD based debugging does not support monitor mode debug, only "halt mode" debug. (2) See chapter 8 "Semihosting" in ARM DUI 0203I (http://infocenter.arm.com/help/topic/com.arm.doc.dui0203i/DUI0203I_rvct_developer_guide.pdf), the "RealView Compilation Tools Developer Guide". The CodeSourcery EABI toolchain also includes a semihosting library. (3) As a more polite alternative, some processors have special debug-oriented registers which can be used to change various features including how the low power states are clocked while debugging. The STM32 DBGMCU_CR register is an example; at the cost of extra power consumption, JTAG can be used during low power states.  File: openocd.info, Node: Config File Guidelines, Next: Daemon Configuration, Prev: OpenOCD Project Setup, Up: Top 6 Config File Guidelines ************************ This chapter is aimed at any user who needs to write a config file, including developers and integrators of OpenOCD and any user who needs to get a new board working smoothly. It provides guidelines for creating those files. You should find the following directories under $(INSTALLDIR)/scripts, with config files maintained upstream. Use them as-is where you can; or as models for new files. * 'interface' ... These are for debug adapters. Files that specify configuration to use specific JTAG, SWD and other adapters go here. * 'board' ... Think Circuit Board, PWA, PCB, they go by many names. Board files contain initialization items that are specific to a board. They reuse target configuration files, since the same microprocessor chips are used on many boards, but support for external parts varies widely. For example, the SDRAM initialization sequence for the board, or the type of external flash and what address it uses. Any initialization sequence to enable that external flash or SDRAM should be found in the board file. Boards may also contain multiple targets: two CPUs; or a CPU and an FPGA. * 'target' ... Think chip. The "target" directory represents the JTAG TAPs on a chip which OpenOCD should control, not a board. Two common types of targets are ARM chips and FPGA or CPLD chips. When a chip has multiple TAPs (maybe it has both ARM and DSP cores), the target config file defines all of them. * _more_ ... browse for other library files which may be useful. For example, there are various generic and CPU-specific utilities. The 'openocd.cfg' user config file may override features in any of the above files by setting variables before sourcing the target file, or by adding commands specific to their situation. 6.1 Interface Config Files ========================== The user config file should be able to source one of these files with a command like this: source [find interface/FOOBAR.cfg] A preconfigured interface file should exist for every debug adapter in use today with OpenOCD. That said, perhaps some of these config files have only been used by the developer who created it. A separate chapter gives information about how to set these up. *Note Debug Adapter Configuration::. Read the OpenOCD source code (and Developer's Guide) if you have a new kind of hardware interface and need to provide a driver for it. 6.2 Board Config Files ====================== The user config file should be able to source one of these files with a command like this: source [find board/FOOBAR.cfg] The point of a board config file is to package everything about a given board that user config files need to know. In summary the board files should contain (if present) 1. One or more 'source [find target/...cfg]' statements 2. NOR flash configuration (*note NOR Configuration: norconfiguration.) 3. NAND flash configuration (*note NAND Configuration: nandconfiguration.) 4. Target 'reset' handlers for SDRAM and I/O configuration 5. JTAG adapter reset configuration (*note Reset Configuration::) 6. All things that are not "inside a chip" Generic things inside target chips belong in target config files, not board config files. So for example a 'reset-init' event handler should know board-specific oscillator and PLL parameters, which it passes to target-specific utility code. The most complex task of a board config file is creating such a 'reset-init' event handler. Define those handlers last, after you verify the rest of the board configuration works. 6.2.1 Communication Between Config files ---------------------------------------- In addition to target-specific utility code, another way that board and target config files communicate is by following a convention on how to use certain variables. The full Tcl/Tk language supports "namespaces", but Jim-Tcl does not. Thus the rule we follow in OpenOCD is this: Variables that begin with a leading underscore are temporary in nature, and can be modified and used at will within a target configuration file. Complex board config files can do the things like this, for a board with three chips: # Chip #1: PXA270 for network side, big endian set CHIPNAME network set ENDIAN big source [find target/pxa270.cfg] # on return: _TARGETNAME = network.cpu # other commands can refer to the "network.cpu" target. $_TARGETNAME configure .... events for this CPU.. # Chip #2: PXA270 for video side, little endian set CHIPNAME video set ENDIAN little source [find target/pxa270.cfg] # on return: _TARGETNAME = video.cpu # other commands can refer to the "video.cpu" target. $_TARGETNAME configure .... events for this CPU.. # Chip #3: Xilinx FPGA for glue logic set CHIPNAME xilinx unset ENDIAN source [find target/spartan3.cfg] That example is oversimplified because it doesn't show any flash memory, or the 'reset-init' event handlers to initialize external DRAM or (assuming it needs it) load a configuration into the FPGA. Such features are usually needed for low-level work with many boards, where "low level" implies that the board initialization software may not be working. (That's a common reason to need JTAG tools. Another is to enable working with microcontroller-based systems, which often have no debugging support except a JTAG connector.) Target config files may also export utility functions to board and user config files. Such functions should use name prefixes, to help avoid naming collisions. Board files could also accept input variables from user config files. For example, there might be a 'J4_JUMPER' setting used to identify what kind of flash memory a development board is using, or how to set up other clocks and peripherals. 6.2.2 Variable Naming Convention -------------------------------- Most boards have only one instance of a chip. However, it should be easy to create a board with more than one such chip (as shown above). Accordingly, we encourage these conventions for naming variables associated with different 'target.cfg' files, to promote consistency and so that board files can override target defaults. Inputs to target config files include: * 'CHIPNAME' ... This gives a name to the overall chip, and is used as part of tap identifier dotted names. While the default is normally provided by the chip manufacturer, board files may need to distinguish between instances of a chip. * 'ENDIAN' ... By default 'little' - although chips may hard-wire 'big'. Chips that can't change endianness don't need to use this variable. * 'CPUTAPID' ... When OpenOCD examines the JTAG chain, it can be told verify the chips against the JTAG IDCODE register. The target file will hold one or more defaults, but sometimes the chip in a board will use a different ID (perhaps a newer revision). Outputs from target config files include: * '_TARGETNAME' ... By convention, this variable is created by the target configuration script. The board configuration file may make use of this variable to configure things like a "reset init" script, or other things specific to that board and that target. If the chip has 2 targets, the names are '_TARGETNAME0', '_TARGETNAME1', ... etc. 6.2.3 The reset-init Event Handler ---------------------------------- Board config files run in the OpenOCD configuration stage; they can't use TAPs or targets, since they haven't been fully set up yet. This means you can't write memory or access chip registers; you can't even verify that a flash chip is present. That's done later in event handlers, of which the target 'reset-init' handler is one of the most important. Except on microcontrollers, the basic job of 'reset-init' event handlers is setting up flash and DRAM, as normally handled by boot loaders. Microcontrollers rarely use boot loaders; they run right out of their on-chip flash and SRAM memory. But they may want to use one of these handlers too, if just for developer convenience. Note: Because this is so very board-specific, and chip-specific, no examples are included here. Instead, look at the board config files distributed with OpenOCD. If you have a boot loader, its source code will help; so will configuration files for other JTAG tools (*note Translating Configuration Files: translatingconfigurationfiles.). Some of this code could probably be shared between different boards. For example, setting up a DRAM controller often doesn't differ by much except the bus width (16 bits or 32?) and memory timings, so a reusable TCL procedure loaded by the 'target.cfg' file might take those as parameters. Similarly with oscillator, PLL, and clock setup; and disabling the watchdog. Structure the code cleanly, and provide comments to help the next developer doing such work. (_You might be that next person_ trying to reuse init code!) The last thing normally done in a 'reset-init' handler is probing whatever flash memory was configured. For most chips that needs to be done while the associated target is halted, either because JTAG memory access uses the CPU or to prevent conflicting CPU access. 6.2.4 JTAG Clock Rate --------------------- Before your 'reset-init' handler has set up the PLLs and clocking, you may need to run with a low JTAG clock rate. *Note JTAG Speed: jtagspeed. Then you'd increase that rate after your handler has made it possible to use the faster JTAG clock. When the initial low speed is board-specific, for example because it depends on a board-specific oscillator speed, then you should probably set it up in the board config file; if it's target-specific, it belongs in the target config file. For most ARM-based processors the fastest JTAG clock(1) is one sixth of the CPU clock; or one eighth for ARM11 cores. Consult chip documentation to determine the peak JTAG clock rate, which might be less than that. Warning: On most ARMs, JTAG clock detection is coupled to the core clock, so software using a 'wait for interrupt' operation blocks JTAG access. Adaptive clocking provides a partial workaround, but a more complete solution just avoids using that instruction with JTAG debuggers. If both the chip and the board support adaptive clocking, use the 'jtag_rclk' command, in case your board is used with JTAG adapter which also supports it. Otherwise use 'adapter_khz'. Set the slow rate at the beginning of the reset sequence, and the faster rate as soon as the clocks are at full speed. 6.2.5 The init_board procedure ------------------------------ The concept of 'init_board' procedure is very similar to 'init_targets' (*Note The init_targets procedure: theinittargetsprocedure.) - it's a replacement of "linear" configuration scripts. This procedure is meant to be executed when OpenOCD enters run stage (*Note Entering the Run Stage: enteringtherunstage,) after 'init_targets'. The idea to have separate 'init_targets' and 'init_board' procedures is to allow the first one to configure everything target specific (internal flash, internal RAM, etc.) and the second one to configure everything board specific (reset signals, chip frequency, reset-init event handler, external memory, etc.). Additionally "linear" board config file will most likely fail when target config file uses 'init_targets' scheme ("linear" script is executed before 'init' and 'init_targets' - after), so separating these two configuration stages is very convenient, as the easiest way to overcome this problem is to convert board config file to use 'init_board' procedure. Board config scripts don't need to override 'init_targets' defined in target config files when they only need to add some specifics. Just as 'init_targets', the 'init_board' procedure can be overridden by "next level" script (which sources the original), allowing greater code reuse. ### board_file.cfg ### # source target file that does most of the config in init_targets source [find target/target.cfg] proc enable_fast_clock {} { # enables fast on-board clock source # configures the chip to use it } # initialize only board specifics - reset, clock, adapter frequency proc init_board {} { reset_config trst_and_srst trst_pulls_srst $_TARGETNAME configure -event reset-init { adapter_khz 1 enable_fast_clock adapter_khz 10000 } } 6.3 Target Config Files ======================= Board config files communicate with target config files using naming conventions as described above, and may source one or more target config files like this: source [find target/FOOBAR.cfg] The point of a target config file is to package everything about a given chip that board config files need to know. In summary the target files should contain 1. Set defaults 2. Add TAPs to the scan chain 3. Add CPU targets (includes GDB support) 4. CPU/Chip/CPU-Core specific features 5. On-Chip flash As a rule of thumb, a target file sets up only one chip. For a microcontroller, that will often include a single TAP, which is a CPU needing a GDB target, and its on-chip flash. More complex chips may include multiple TAPs, and the target config file may need to define them all before OpenOCD can talk to the chip. For example, some phone chips have JTAG scan chains that include an ARM core for operating system use, a DSP, another ARM core embedded in an image processing engine, and other processing engines. 6.3.1 Default Value Boiler Plate Code ------------------------------------- All target configuration files should start with code like this, letting board config files express environment-specific differences in how things should be set up. # Boards may override chip names, perhaps based on role, # but the default should match what the vendor uses if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam7x256 } # ONLY use ENDIAN with targets that can change it. if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # TAP identifiers may change as chips mature, for example with # new revision fields (the "3" here). Pick a good default; you # can pass several such identifiers to the "jtag newtap" command. if { [info exists CPUTAPID ] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } _Remember:_ Board config files may include multiple target config files, or the same target file multiple times (changing at least 'CHIPNAME'). Likewise, the target configuration file should define '_TARGETNAME' (or '_TARGETNAME0' etc) and use it later on when defining debug targets: set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME 6.3.2 Adding TAPs to the Scan Chain ----------------------------------- After the "defaults" are set up, add the TAPs on each chip to the JTAG scan chain. *Note TAP Declaration::, and the naming convention for taps. In the simplest case the chip has only one TAP, probably for a CPU or FPGA. The config file for the Atmel AT91SAM7X256 looks (in part) like this: jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID A board with two such at91sam7 chips would be able to source such a config file twice, with different values for 'CHIPNAME', so it adds a different TAP each time. If there are nonzero '-expected-id' values, OpenOCD attempts to verify the actual tap id against those values. It will issue error messages if there is mismatch, which can help to pinpoint problems in OpenOCD configurations. JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (Manufacturer: 0x787, Part: 0xf0f0, Version: 0x3) ERROR: Tap: sam7x256.cpu - Expected id: 0x12345678, Got: 0x3f0f0f0f ERROR: expected: mfg: 0x33c, part: 0x2345, ver: 0x1 ERROR: got: mfg: 0x787, part: 0xf0f0, ver: 0x3 There are more complex examples too, with chips that have multiple TAPs. Ones worth looking at include: * 'target/omap3530.cfg' - with disabled ARM and DSP, plus a JRC to enable them * 'target/str912.cfg' - with flash, CPU, and boundary scan * 'target/ti_dm355.cfg' - with ETM, ARM, and JRC (this JRC is not currently used) 6.3.3 Add CPU targets --------------------- After adding a TAP for a CPU, you should set it up so that GDB and other commands can use it. *Note CPU Configuration::. For the at91sam7 example above, the command can look like this; note that '$_ENDIAN' is not needed, since OpenOCD defaults to little endian, and this chip doesn't support changing that. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME Work areas are small RAM areas associated with CPU targets. They are used by OpenOCD to speed up downloads, and to download small snippets of code to program flash chips. If the chip includes a form of "on-chip-ram" - and many do - define a work area if you can. Again using the at91sam7 as an example, this can look like: $_TARGETNAME configure -work-area-phys 0x00200000 \ -work-area-size 0x4000 -work-area-backup 0 6.3.4 Define CPU targets working in SMP --------------------------------------- After setting targets, you can define a list of targets working in SMP. set _TARGETNAME_1 $_CHIPNAME.cpu1 set _TARGETNAME_2 $_CHIPNAME.cpu2 target create $_TARGETNAME_1 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase $_DAP_DBG1 target create $_TARGETNAME_2 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 1 -dbgbase $_DAP_DBG2 #define 2 targets working in smp. target smp $_CHIPNAME.cpu2 $_CHIPNAME.cpu1 In the above example on cortex_a, 2 cpus are working in SMP. In SMP only one GDB instance is created and : * a set of hardware breakpoint sets the same breakpoint on all targets in the list. * halt command triggers the halt of all targets in the list. * resume command triggers the write context and the restart of all targets in the list. * following a breakpoint: the target stopped by the breakpoint is displayed to the GDB session. * dedicated GDB serial protocol packets are implemented for switching/retrieving the target displayed by the GDB session *note Using OpenOCD SMP with GDB: usingopenocdsmpwithgdb. The SMP behaviour can be disabled/enabled dynamically. On cortex_a following command have been implemented. * cortex_a smp_on : enable SMP mode, behaviour is as described above. * cortex_a smp_off : disable SMP mode, the current target is the one displayed in the GDB session, only this target is now controlled by GDB session. This behaviour is useful during system boot up. * cortex_a smp_gdb : display/fix the core id displayed in GDB session see following example. >cortex_a smp_gdb gdb coreid 0 -> -1 #0 : coreid 0 is displayed to GDB , #-> -1 : next resume triggers a real resume > cortex_a smp_gdb 1 gdb coreid 0 -> 1 #0 :coreid 0 is displayed to GDB , #->1 : next resume displays coreid 1 to GDB > resume > cortex_a smp_gdb gdb coreid 1 -> 1 #1 :coreid 1 is displayed to GDB , #->1 : next resume displays coreid 1 to GDB > cortex_a smp_gdb -1 gdb coreid 1 -> -1 #1 :coreid 1 is displayed to GDB, #->-1 : next resume triggers a real resume 6.3.5 Chip Reset Setup ---------------------- As a rule, you should put the 'reset_config' command into the board file. Most things you think you know about a chip can be tweaked by the board. Some chips have specific ways the TRST and SRST signals are managed. In the unusual case that these are _chip specific_ and can never be changed by board wiring, they could go here. For example, some chips can't support JTAG debugging without both signals. Provide a 'reset-assert' event handler if you can. Such a handler uses JTAG operations to reset the target, letting this target config be used in systems which don't provide the optional SRST signal, or on systems where you don't want to reset all targets at once. Such a handler might write to chip registers to force a reset, use a JRC to do that (preferable - the target may be wedged!), or force a watchdog timer to trigger. (For Cortex-M targets, this is not necessary. The target driver knows how to use trigger an NVIC reset when SRST is not available.) Some chips need special attention during reset handling if they're going to be used with JTAG. An example might be needing to send some commands right after the target's TAP has been reset, providing a 'reset-deassert-post' event handler that writes a chip register to report that JTAG debugging is being done. Another would be reconfiguring the watchdog so that it stops counting while the core is halted in the debugger. JTAG clocking constraints often change during reset, and in some cases target config files (rather than board config files) are the right places to handle some of those issues. For example, immediately after reset most chips run using a slower clock than they will use later. That means that after reset (and potentially, as OpenOCD first starts up) they must use a slower JTAG clock rate than they will use later. *Note JTAG Speed: jtagspeed. Important: When you are debugging code that runs right after chip reset, getting these issues right is critical. In particular, if you see intermittent failures when OpenOCD verifies the scan chain after reset, look at how you are setting up JTAG clocking. 6.3.6 The init_targets procedure -------------------------------- Target config files can either be "linear" (script executed line-by-line when parsed in configuration stage, *Note Configuration Stage: configurationstage,) or they can contain a special procedure called 'init_targets', which will be executed when entering run stage (after parsing all config files or after 'init' command, *Note Entering the Run Stage: enteringtherunstage.) Such procedure can be overriden by "next level" script (which sources the original). This concept faciliates code reuse when basic target config files provide generic configuration procedures and 'init_targets' procedure, which can then be sourced and enchanced or changed in a "more specific" target config file. This is not possible with "linear" config scripts, because sourcing them executes every initialization commands they provide. ### generic_file.cfg ### proc setup_my_chip {chip_name flash_size ram_size} { # basic initialization procedure ... } proc init_targets {} { # initializes generic chip with 4kB of flash and 1kB of RAM setup_my_chip MY_GENERIC_CHIP 4096 1024 } ### specific_file.cfg ### source [find target/generic_file.cfg] proc init_targets {} { # initializes specific chip with 128kB of flash and 64kB of RAM setup_my_chip MY_CHIP_WITH_128K_FLASH_64KB_RAM 131072 65536 } The easiest way to convert "linear" config files to 'init_targets' version is to enclose every line of "code" (i.e. not 'source' commands, procedures, etc.) in this procedure. For an example of this scheme see LPC2000 target config files. The 'init_boards' procedure is a similar concept concerning board config files (*Note The init_board procedure: theinitboardprocedure.) 6.3.7 The init_target_events procedure -------------------------------------- A special procedure called 'init_target_events' is run just after 'init_targets' (*Note The init_targets procedure: theinittargetsprocedure.) and before 'init_board' (*Note The init_board procedure: theinitboardprocedure.) It is used to set up default target events for the targets that do not have those events already assigned. 6.3.8 ARM Core Specific Hacks ----------------------------- If the chip has a DCC, enable it. If the chip is an ARM9 with some special high speed download features - enable it. If present, the MMU, the MPU and the CACHE should be disabled. Some ARM cores are equipped with trace support, which permits examination of the instruction and data bus activity. Trace activity is controlled through an "Embedded Trace Module" (ETM) on one of the core's scan chains. The ETM emits voluminous data through a "trace port". (*Note ARM Hardware Tracing: armhardwaretracing.) If you are using an external trace port, configure it in your board config file. If you are using an on-chip "Embedded Trace Buffer" (ETB), configure it in your target config file. etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb 6.3.9 Internal Flash Configuration ---------------------------------- This applies ONLY TO MICROCONTROLLERS that have flash built in. Never ever in the "target configuration file" define any type of flash that is external to the chip. (For example a BOOT flash on Chip Select 0.) Such flash information goes in a board file - not the TARGET (chip) file. Examples: * at91sam7x256 - has 256K flash YES enable it. * str912 - has flash internal YES enable it. * imx27 - uses boot flash on CS0 - it goes in the board file. * pxa270 - again - CS0 flash - it goes in the board file. 6.4 Translating Configuration Files =================================== If you have a configuration file for another hardware debugger or toolset (Abatron, BDI2000, BDI3000, CCS, Lauterbach, Segger, Macraigor, etc.), translating it into OpenOCD syntax is often quite straightforward. The most tricky part of creating a configuration script is oftentimes the reset init sequence where e.g. PLLs, DRAM and the like is set up. One trick that you can use when translating is to write small Tcl procedures to translate the syntax into OpenOCD syntax. This can avoid manual translation errors and make it easier to convert other scripts later on. Example of transforming quirky arguments to a simple search and replace job: # Lauterbach syntax(?) # # Data.Set c15:0x042f %long 0x40000015 # # OpenOCD syntax when using procedure below. # # setc15 0x01 0x00050078 proc setc15 {regs value} { global TARGETNAME echo [format "set p15 0x%04x, 0x%08x" $regs $value] arm mcr 15 [expr ($regs>>12)&0x7] \ [expr ($regs>>0)&0xf] [expr ($regs>>4)&0xf] \ [expr ($regs>>8)&0x7] $value } ---------- Footnotes ---------- (1) A FAQ gives details.  File: openocd.info, Node: Daemon Configuration, Next: Debug Adapter Configuration, Prev: Config File Guidelines, Up: Top 7 Daemon Configuration ********************** The commands here are commonly found in the openocd.cfg file and are used to specify what TCP/IP ports are used, and how GDB should be supported. 7.1 Configuration Stage ======================= When the OpenOCD server process starts up, it enters a _configuration stage_ which is the only time that certain commands, _configuration commands_, may be issued. Normally, configuration commands are only available inside startup scripts. In this manual, the definition of a configuration command is presented as a _Config Command_, not as a _Command_ which may be issued interactively. The runtime 'help' command also highlights configuration commands, and those which may be issued at any time. Those configuration commands include declaration of TAPs, flash banks, the interface used for JTAG communication, and other basic setup. The server must leave the configuration stage before it may access or activate TAPs. After it leaves this stage, configuration commands may no longer be issued. 7.2 Entering the Run Stage ========================== The first thing OpenOCD does after leaving the configuration stage is to verify that it can talk to the scan chain (list of TAPs) which has been configured. It will warn if it doesn't find TAPs it expects to find, or finds TAPs that aren't supposed to be there. You should see no errors at this point. If you see errors, resolve them by correcting the commands you used to configure the server. Common errors include using an initial JTAG speed that's too fast, and not providing the right IDCODE values for the TAPs on the scan chain. Once OpenOCD has entered the run stage, a number of commands become available. A number of these relate to the debug targets you may have declared. For example, the 'mww' command will not be available until a target has been successfuly instantiated. If you want to use those commands, you may need to force entry to the run stage. -- Config Command: init This command terminates the configuration stage and enters the run stage. This helps when you need to have the startup scripts manage tasks such as resetting the target, programming flash, etc. To reset the CPU upon startup, add "init" and "reset" at the end of the config script or at the end of the OpenOCD command line using the '-c' command line switch. If this command does not appear in any startup/configuration file OpenOCD executes the command for you after processing all configuration files and/or command line options. NOTE: This command normally occurs at or near the end of your openocd.cfg file to force OpenOCD to "initialize" and make the targets ready. For example: If your openocd.cfg file needs to read/write memory on your target, 'init' must occur before the memory read/write commands. This includes 'nand probe'. -- Overridable Procedure: jtag_init This is invoked at server startup to verify that it can talk to the scan chain (list of TAPs) which has been configured. The default implementation first tries 'jtag arp_init', which uses only a lightweight JTAG reset before examining the scan chain. If that fails, it tries again, using a harder reset from the overridable procedure 'init_reset'. Implementations must have verified the JTAG scan chain before they return. This is done by calling 'jtag arp_init' (or 'jtag arp_init-reset'). 7.3 TCP/IP Ports ================ The OpenOCD server accepts remote commands in several syntaxes. Each syntax uses a different TCP/IP port, which you may specify only during configuration (before those ports are opened). For reasons including security, you may wish to prevent remote access using one or more of these ports. In such cases, just specify the relevant port number as zero. If you disable all access through TCP/IP, you will need to use the command line '-pipe' option. -- Command: gdb_port [number] Normally gdb listens to a TCP/IP port, but GDB can also communicate via pipes(stdin/out or named pipes). The name "gdb_port" stuck because it covers probably more than 90% of the normal use cases. No arguments reports GDB port. "pipe" means listen to stdin output to stdout, an integer is base port number, "disable" disables the gdb server. When using "pipe", also use log_output to redirect the log output to a file so as not to flood the stdin/out pipes. The -p/-pipe option is deprecated and a warning is printed as it is equivalent to passing in -c "gdb_port pipe; log_output openocd.log". Any other string is interpreted as named pipe to listen to. Output pipe is the same name as input pipe, but with 'o' appended, e.g. /var/gdb, /var/gdbo. The GDB port for the first target will be the base port, the second target will listen on gdb_port + 1, and so on. When not specified during the configuration stage, the port NUMBER defaults to 3333. -- Command: tcl_port [number] Specify or query the port used for a simplified RPC connection that can be used by clients to issue TCL commands and get the output from the Tcl engine. Intended as a machine interface. When not specified during the configuration stage, the port NUMBER defaults to 6666. -- Command: telnet_port [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. When not specified during the configuration stage, the port NUMBER defaults to 4444. When specified as zero, this port is not activated. 7.4 GDB Configuration ===================== You can reconfigure some GDB behaviors if needed. The ones listed here are static and global. *Note Target Configuration: targetconfiguration, about configuring individual targets. *Note Target Events: targetevents, about configuring target-specific event handling. -- Command: gdb_breakpoint_override ['hard'|'soft'|'disable'] Force breakpoint type for gdb 'break' commands. This option supports GDB GUIs which don't distinguish hard versus soft breakpoints, if the default OpenOCD and GDB behaviour is not sufficient. GDB normally uses hardware breakpoints if the memory map has been set up for flash regions. -- Config Command: gdb_flash_program ('enable'|'disable') Set to 'enable' to cause OpenOCD to program the flash memory when a vFlash packet is received. The default behaviour is 'enable'. -- Config Command: gdb_memory_map ('enable'|'disable') Set to 'enable' to cause OpenOCD to send the memory configuration to GDB when requested. GDB will then know when to set hardware breakpoints, and program flash using the GDB load command. 'gdb_flash_program enable' must also be enabled for flash programming to work. Default behaviour is 'enable'. *Note gdb_flash_program: gdbflashprogram. -- Config Command: gdb_report_data_abort ('enable'|'disable') Specifies whether data aborts cause an error to be reported by GDB memory read packets. The default behaviour is 'disable'; use 'enable' see these errors reported. -- Config Command: gdb_target_description ('enable'|'disable') Set to 'enable' to cause OpenOCD to send the target descriptions to gdb via qXfer:features:read packet. The default behaviour is 'enable'. -- Command: gdb_save_tdesc Saves the target descripton file to the local file system. The file name is target_name.xml. 7.5 Event Polling ================= Hardware debuggers are parts of asynchronous systems, where significant events can happen at any time. The OpenOCD server needs to detect some of these events, so it can report them to through TCL command line or to GDB. Examples of such events include: * One of the targets can stop running ... maybe it triggers a code breakpoint or data watchpoint, or halts itself. * Messages may be sent over "debug message" channels ... many targets support such messages sent over JTAG, for receipt by the person debugging or tools. * Loss of power ... some adapters can detect these events. * Resets not issued through JTAG ... such reset sources can include button presses or other system hardware, sometimes including the target itself (perhaps through a watchdog). * Debug instrumentation sometimes supports event triggering such as "trace buffer full" (so it can quickly be emptied) or other signals (to correlate with code behavior). None of those events are signaled through standard JTAG signals. However, most conventions for JTAG connectors include voltage level and system reset (SRST) signal detection. Some connectors also include instrumentation signals, which can imply events when those signals are inputs. In general, OpenOCD needs to periodically check for those events, either by looking at the status of signals on the JTAG connector or by sending synchronous "tell me your status" JTAG requests to the various active targets. There is a command to manage and monitor that polling, which is normally done in the background. -- Command: poll ['on'|'off'] Poll the current target for its current state. (Also, *note target curstate: targetcurstate.) If that target is in debug mode, architecture specific information about the current state is printed. An optional parameter allows background polling to be enabled and disabled. You could use this from the TCL command shell, or from GDB using 'monitor poll' command. Leave background polling enabled while you're using GDB. > poll background polling: on target state: halted target halted in ARM state due to debug-request, \ current mode: Supervisor cpsr: 0x800000d3 pc: 0x11081bfc MMU: disabled, D-Cache: disabled, I-Cache: enabled >  File: openocd.info, Node: Debug Adapter Configuration, Next: Reset Configuration, Prev: Daemon Configuration, Up: Top 8 Debug Adapter Configuration ***************************** Correctly installing OpenOCD includes making your operating system give OpenOCD access to debug adapters. Once that has been done, Tcl commands are used to select which one is used, and to configure how it is used. Note: Because OpenOCD started out with a focus purely on JTAG, you may find places where it wrongly presumes JTAG is the only transport protocol in use. Be aware that recent versions of OpenOCD are removing that limitation. JTAG remains more functional than most other transports. Other transports do not support boundary scan operations, or may be specific to a given chip vendor. Some might be usable only for programming flash memory, instead of also for debugging. Debug Adapters/Interfaces/Dongles are normally configured through commands in an interface configuration file which is sourced by your 'openocd.cfg' file, or through a command line '-f interface/....cfg' option. source [find interface/olimex-jtag-tiny.cfg] These commands tell OpenOCD what type of JTAG adapter you have, and how to talk to it. A few cases are so simple that you only need to say what driver to use: # jlink interface interface jlink Most adapters need a bit more configuration than that. 8.1 Interface Configuration =========================== The interface command tells OpenOCD what type of debug adapter you are using. Depending on the type of adapter, you may need to use one or more additional commands to further identify or configure the adapter. -- Config Command: interface name Use the interface driver NAME to connect to the target. -- Command: interface_list List the debug adapter drivers that have been built into the running copy of OpenOCD. -- Command: interface transports transport_name+ Specifies the transports supported by this debug adapter. The adapter driver builds-in similar knowledge; use this only when external configuration (such as jumpering) changes what the hardware can support. -- Command: adapter_name Returns the name of the debug adapter driver being used. 8.2 Interface Drivers ===================== Each of the interface drivers listed here must be explicitly enabled when OpenOCD is configured, in order to be made available at run time. -- Interface Driver: amt_jtagaccel Amontec Chameleon in its JTAG Accelerator configuration, connected to a PC's EPP mode parallel port. This defines some driver-specific commands: -- Config Command: parport_port number Specifies either the address of the I/O port (default: 0x378 for LPT1) or the number of the '/dev/parport' device. -- Config Command: rtck ['enable'|'disable'] Displays status of RTCK option. Optionally sets that option first. -- Interface Driver: arm-jtag-ew Olimex ARM-JTAG-EW USB adapter This has one driver-specific command: -- Command: armjtagew_info Logs some status -- Interface Driver: at91rm9200 Supports bitbanged JTAG from the local system, presuming that system is an Atmel AT91rm9200 and a specific set of GPIOs is used. -- Interface Driver: cmsis-dap ARM CMSIS-DAP compliant based adapter. -- Config Command: cmsis_dap_vid_pid [vid pid]+ The vendor ID and product ID of the CMSIS-DAP device. If not specified the driver will attempt to auto detect the CMSIS-DAP device. Currently, up to eight [VID, PID] pairs may be given, e.g. cmsis_dap_vid_pid 0xc251 0xf001 0x0d28 0x0204 -- Config Command: cmsis_dap_serial [serial] Specifies the SERIAL of the CMSIS-DAP device to use. If not specified, serial numbers are not considered. -- Command: cmsis-dap info Display various device information, like hardware version, firmware version, current bus status. -- Interface Driver: dummy A dummy software-only driver for debugging. -- Interface Driver: ep93xx Cirrus Logic EP93xx based single-board computer bit-banging (in development) -- Interface Driver: ft2232 FTDI FT2232 (USB) based devices over one of the userspace libraries. Note that this driver has several flaws and the 'ftdi' driver is recommended as its replacement. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: -- Config Command: ft2232_device_desc description Provides the USB device description (the _iProduct string_) of the FTDI FT2232 device. If not specified, the FTDI default value is used. This setting is only valid if compiled with FTD2XX support. -- Config Command: ft2232_serial serial-number Specifies the SERIAL-NUMBER of the FTDI FT2232 device to use, in case the vendor provides unique IDs and more than one FT2232 device is connected to the host. If not specified, serial numbers are not considered. (Note that USB serial numbers can be arbitrary Unicode strings, and are not restricted to containing only decimal digits.) -- Config Command: ft2232_layout name Each vendor's FT2232 device can use different GPIO signals to control output-enables, reset signals, and LEDs. Currently valid layout NAME values include: - axm0432_jtag Axiom AXM-0432 - comstick Hitex STR9 comstick - cortino Hitex Cortino JTAG interface - evb_lm3s811 TI/Luminary Micro EVB_LM3S811 as a JTAG interface, either for the local Cortex-M3 (SRST only) or in a passthrough mode (neither SRST nor TRST) This layout can not support the SWO trace mechanism, and should be used only for older boards (before rev C). - luminary_icdi This layout should be used with most TI/Luminary eval boards, including Rev C LM3S811 eval boards and the eponymous ICDI boards, to debug either the local Cortex-M3 or in passthrough mode to debug some other target. It can support the SWO trace mechanism. - flyswatter Tin Can Tools Flyswatter - icebear ICEbear JTAG adapter from Section 5 - jtagkey Amontec JTAGkey and JTAGkey-Tiny (and compatibles) - jtagkey2 Amontec JTAGkey2 (and compatibles) - m5960 American Microsystems M5960 - olimex-jtag Olimex ARM-USB-OCD and ARM-USB-Tiny - oocdlink OOCDLink - redbee-econotag Integrated with a Redbee development board. - redbee-usb Integrated with a Redbee USB-stick development board. - sheevaplug Marvell Sheevaplug development kit - signalyzer Xverve Signalyzer - stm32stick Hitex STM32 Performance Stick - turtelizer2 egnite Software turtelizer2 - usbjtag "USBJTAG-1" layout described in the OpenOCD diploma thesis -- Config Command: ft2232_vid_pid [vid pid]+ The vendor ID and product ID of the FTDI FT2232 device. If not specified, the FTDI default values are used. Currently, up to eight [VID, PID] pairs may be given, e.g. ft2232_vid_pid 0x0403 0xcff8 0x15ba 0x0003 -- Config Command: ft2232_latency ms On some systems using FT2232 based JTAG interfaces the FT_Read function call in ft2232_read() fails to return the expected number of bytes. This can be caused by USB communication delays and has proved hard to reproduce and debug. Setting the FT2232 latency timer to a larger value increases delays for short USB packets but it also reduces the risk of timeouts before receiving the expected number of bytes. The OpenOCD default value is 2 and for some systems a value of 10 has proved useful. -- Config Command: ft2232_channel channel Used to select the channel of the ft2232 chip to use (between 1 and 4). The default value is 1. For example, the interface config file for a Turtelizer JTAG Adapter looks something like this: interface ft2232 ft2232_device_desc "Turtelizer JTAG/RS232 Adapter" ft2232_layout turtelizer2 ft2232_vid_pid 0x0403 0xbdc8 -- Interface Driver: ftdi This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. It is a complete rewrite to address a large number of problems with the ft2232 interface driver. The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, bypassing intermediate libraries like libftdi of D2XX. Performance-wise it is consistently faster than the ft2232 driver, sometimes several times faster. A major improvement of this driver is that support for new FTDI based adapters can be added competely through configuration files, without the need to patch and rebuild OpenOCD. The driver uses a signal abstraction to enable Tcl configuration files to define outputs for one or several FTDI GPIO. These outputs can then be controlled using the 'ftdi_set_signal' command. Special signal names are reserved for nTRST, nSRST and LED (for blink) so that they, if defined, will be used for their customary purpose. Depending on the type of buffer attached to the FTDI GPIO, the outputs have to be controlled differently. In order to support tristateable signals such as nSRST, both a data GPIO and an output-enable GPIO can be specified for each signal. The following output buffer configurations are supported: - Push-pull with one FTDI output as (non-)inverted data line - Open drain with one FTDI output as (non-)inverted output-enable - Tristate with one FTDI output as (non-)inverted data line and another FTDI output as (non-)inverted output-enable - Unbuffered, using the FTDI GPIO as a tristate output directly by switching data and direction as necessary These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: -- Config Command: ftdi_vid_pid [vid pid]+ The vendor ID and product ID of the adapter. If not specified, the FTDI default values are used. Currently, up to eight [VID, PID] pairs may be given, e.g. ftdi_vid_pid 0x0403 0xcff8 0x15ba 0x0003 -- Config Command: ftdi_device_desc description Provides the USB device description (the _iProduct string_) of the adapter. If not specified, the device description is ignored during device selection. -- Config Command: ftdi_serial serial-number Specifies the SERIAL-NUMBER of the adapter to use, in case the vendor provides unique IDs and more than one adapter is connected to the host. If not specified, serial numbers are not considered. (Note that USB serial numbers can be arbitrary Unicode strings, and are not restricted to containing only decimal digits.) -- Config Command: ftdi_channel channel Selects the channel of the FTDI device to use for MPSSE operations. Most adapters use the default, channel 0, but there are exceptions. -- Config Command: ftdi_layout_init data direction Specifies the initial values of the FTDI GPIO data and direction registers. Each value is a 16-bit number corresponding to the concatenation of the high and low FTDI GPIO registers. The values should be selected based on the schematics of the adapter, such that all signals are set to safe levels with minimal impact on the target system. Avoid floating inputs, conflicting outputs and initially asserted reset signals. -- Config Command: ftdi_layout_signal name ['-data'|'-ndata' data_mask] ['-oe'|'-noe' oe_mask] ['-alias'|'-nalias' name] Creates a signal with the specified NAME, controlled by one or more FTDI GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO register bitmasks to tell the driver the connection and type of the output buffer driving the respective signal. DATA_MASK is the bitmask for the pin(s) connected to the data input of the output buffer. '-ndata' is used with inverting data inputs and '-data' with non-inverting inputs. The '-oe' (or '-noe') option tells where the output-enable (or not-output-enable) input to the output buffer is connected. Both DATA_MASK and OE_MASK need not be specified. For example, a simple open-collector transistor driver would be specified with '-oe' only. In that case the signal can only be set to drive low or to Hi-Z and the driver will complain if the signal is set to drive high. Which means that if it's a reset signal, 'reset_config' must be specified as 'srst_open_drain', not 'srst_push_pull'. A special case is provided when '-data' and '-oe' is set to the same bitmask. Then the FTDI pin is considered being connected straight to the target without any buffer. The FTDI pin is then switched between output and input as necessary to provide the full set of low, high and Hi-Z characteristics. In all other cases, the pins specified in a signal definition are always driven by the FTDI. If '-alias' or '-nalias' is used, the signal is created identical (or with data inverted) to an already specified signal NAME. -- Command: ftdi_set_signal name '0'|'1'|'z' Set a previously defined signal to the specified level. - '0', drive low - '1', drive high - 'z', set to high-impedance For example adapter definitions, see the configuration files shipped in the 'interface/ftdi' directory. -- Interface Driver: remote_bitbang Drive JTAG from a remote process. This sets up a UNIX or TCP socket connection with a remote process and sends ASCII encoded bitbang requests to that process instead of directly driving JTAG. The remote_bitbang driver is useful for debugging software running on processors which are being simulated. -- Config Command: remote_bitbang_port number Specifies the TCP port of the remote process to connect to or 0 to use UNIX sockets instead of TCP. -- Config Command: remote_bitbang_host hostname Specifies the hostname of the remote process to connect to using TCP, or the name of the UNIX socket to use if remote_bitbang_port is 0. For example, to connect remotely via TCP to the host foobar you might have something like: interface remote_bitbang remote_bitbang_port 3335 remote_bitbang_host foobar To connect to another process running locally via UNIX sockets with socket named mysocket: interface remote_bitbang remote_bitbang_port 0 remote_bitbang_host mysocket -- Interface Driver: usb_blaster USB JTAG/USB-Blaster compatibles over one of the userspace libraries for FTDI chips. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: -- Config Command: usb_blaster_device_desc description Provides the USB device description (the _iProduct string_) of the FTDI FT245 device. If not specified, the FTDI default value is used. This setting is only valid if compiled with FTD2XX support. -- Config Command: usb_blaster_vid_pid vid pid The vendor ID and product ID of the FTDI FT245 device. If not specified, default values are used. Currently, only one VID, PID pair may be given, e.g. for Altera USB-Blaster (default): usb_blaster_vid_pid 0x09FB 0x6001 The following VID/PID is for Kolja Waschk's USB JTAG: usb_blaster_vid_pid 0x16C0 0x06AD -- Command: usb_blaster_pin ('pin6'|'pin8') ('0'|'1'|'s'|'t') Sets the state or function of the unused GPIO pins on USB-Blasters (pins 6 and 8 on the female JTAG header). These pins can be used as SRST and/or TRST provided the appropriate connections are made on the target board. For example, to use pin 6 as SRST: usb_blaster_pin pin6 s reset_config srst_only -- Command: usb_blaster_lowlevel_driver ('ftdi'|'ftd2xx'|'ublast2') Chooses the low level access method for the adapter. If not specified, 'ftdi' is selected unless it wasn't enabled during the configure stage. USB-Blaster II needs 'ublast2'. -- Command: usb_blaster_firmware PATH This command specifies PATH to access USB-Blaster II firmware image. To be used with USB-Blaster II only. -- Interface Driver: gw16012 Gateworks GW16012 JTAG programmer. This has one driver-specific command: -- Config Command: parport_port [port_number] Display either the address of the I/O port (default: 0x378 for LPT1) or the number of the '/dev/parport' device. If a parameter is provided, first switch to use that port. This is a write-once setting. -- Interface Driver: jlink Segger J-Link family of USB adapters. It currently supports JTAG and SWD transports. Compatibility Note: Segger released many firmware versions for the many harware versions they produced. OpenOCD was extensively tested and intended to run on all of them, but some combinations were reported as incompatible. As a general recommendation, it is advisable to use the latest firmware version available for each hardware version. However the current V8 is a moving target, and Segger firmware versions released after the OpenOCD was released may not be compatible. In such cases it is recommended to revert to the last known functional version. For 0.5.0, this is from "Feb 8 2012 14:30:39", packed with 4.42c. For 0.6.0, the last known version is from "May 3 2012 18:36:22", packed with 4.46f. -- Command: jlink caps Display the device firmware capabilities. -- Command: jlink info Display various device information, like hardware version, firmware version, current bus status. -- Command: jlink hw_jtag ['2'|'3'] Set the JTAG protocol version to be used. Without argument, show the actual JTAG protocol version. -- Command: jlink config Display the J-Link configuration. -- Command: jlink config kickstart [val] Set the Kickstart power on JTAG-pin 19. Without argument, show the Kickstart configuration. -- Command: jlink config mac_address ['ff:ff:ff:ff:ff:ff'] Set the MAC address of the J-Link Pro. Without argument, show the MAC address. -- Command: jlink config ip ['A.B.C.D'('/E'|'F.G.H.I')] Set the IP configuration of the J-Link Pro, where A.B.C.D is the IP address, E the bit of the subnet mask and F.G.H.I the subnet mask. Without arguments, show the IP configuration. -- Command: jlink config usb_address ['0x00' to '0x03' or '0xff'] Set the USB address; this will also change the product id. Without argument, show the USB address. -- Command: jlink config reset Reset the current configuration. -- Command: jlink config save Save the current configuration to the internal persistent storage. -- Config: jlink pid val Set the USB PID of the interface. As a configuration command, it can be used only before 'init'. -- Config: jlink serial serial-number Set the SERIAL-NUMBER of the interface, in case more than one adapter is connected to the host. If not specified, serial numbers are not considered. Note that there may be leading zeros in the SERIAL-NUMBER string that will not show in the Segger software, but must be specified here. Debug level 3 output contains serial numbers if there is a mismatch. As a configuration command, it can be used only before 'init'. -- Interface Driver: parport Supports PC parallel port bit-banging cables: Wigglers, PLD download cable, and more. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: -- Config Command: parport_cable name Set the layout of the parallel port cable used to connect to the target. This is a write-once setting. Currently valid cable NAME values include: - altium Altium Universal JTAG cable. - arm-jtag Same as original wiggler except SRST and TRST connections reversed and TRST is also inverted. - chameleon The Amontec Chameleon's CPLD when operated in configuration mode. This is only used to program the Chameleon itself, not a connected target. - dlc5 The Xilinx Parallel cable III. - flashlink The ST Parallel cable. - lattice Lattice ispDOWNLOAD Cable - old_amt_wiggler The Wiggler configuration that comes with some versions of Amontec's Chameleon Programmer. The new version available from the website uses the original Wiggler layout ('WIGGLER') - triton The parallel port adapter found on the "Karo Triton 1 Development Board". This is also the layout used by the HollyGates design (see ). - wiggler The original Wiggler layout, also supported by several clones, such as the Olimex ARM-JTAG - wiggler2 Same as original wiggler except an led is fitted on D5. - wiggler_ntrst_inverted Same as original wiggler except TRST is inverted. -- Config Command: parport_port [port_number] Display either the address of the I/O port (default: 0x378 for LPT1) or the number of the '/dev/parport' device. If a parameter is provided, first switch to use that port. This is a write-once setting. When using PPDEV to access the parallel port, use the number of the parallel port: 'parport_port 0' (the default). If 'parport_port 0x378' is specified you may encounter a problem. -- Command: parport_toggling_time [nanoseconds] Displays how many nanoseconds the hardware needs to toggle TCK; the parport driver uses this value to obey the 'adapter_khz' configuration. When the optional NANOSECONDS parameter is given, that setting is changed before displaying the current value. The default setting should work reasonably well on commodity PC hardware. However, you may want to calibrate for your specific hardware. Tip: To measure the toggling time with a logic analyzer or a digital storage oscilloscope, follow the procedure below: > parport_toggling_time 1000 > adapter_khz 500 This sets the maximum JTAG clock speed of the hardware, but the actual speed probably deviates from the requested 500 kHz. Now, measure the time between the two closest spaced TCK transitions. You can use 'runtest 1000' or something similar to generate a large set of samples. Update the setting to match your measurement: > parport_toggling_time Now the clock speed will be a better match for 'adapter_khz rate' commands given in OpenOCD scripts and event handlers. You can do something similar with many digital multimeters, but note that you'll probably need to run the clock continuously for several seconds before it decides what clock rate to show. Adjust the toggling time up or down until the measured clock rate is a good match for the adapter_khz rate you specified; be conservative. -- Config Command: parport_write_on_exit ('on'|'off') This will configure the parallel driver to write a known cable-specific value to the parallel interface on exiting OpenOCD. For example, the interface configuration file for a classic "Wiggler" cable on LPT2 might look something like this: interface parport parport_port 0x278 parport_cable wiggler -- Interface Driver: presto ASIX PRESTO USB JTAG programmer. -- Config Command: presto_serial serial_string Configures the USB serial number of the Presto device to use. -- Interface Driver: rlink Raisonance RLink USB adapter -- Interface Driver: usbprog usbprog is a freely programmable USB adapter. -- Interface Driver: vsllink vsllink is part of Versaloon which is a versatile USB programmer. Note: This defines quite a few driver-specific commands, which are not currently documented here. -- Interface Driver: hla This is a driver that supports multiple High Level Adapters. This type of adapter does not expose some of the lower level api's that OpenOCD would normally use to access the target. Currently supported adapters include the ST STLINK and TI ICDI. STLINK firmware version >= V2.J21.S4 recommended due to issues with earlier versions of firmware where serial number is reset after first use. Suggest using ST firmware update utility to upgrade STLINK firmware even if current version reported is V2.J21.S4. -- Config Command: hla_device_desc description Currently Not Supported. -- Config Command: hla_serial serial Specifies the serial number of the adapter. -- Config Command: hla_layout ('stlink'|'icdi') Specifies the adapter layout to use. -- Config Command: hla_vid_pid vid pid The vendor ID and product ID of the device. -- Command: hla_command command Execute a custom adapter-specific command. The COMMAND string is passed as is to the underlying adapter layout handler. -- Interface Driver: opendous opendous-jtag is a freely programmable USB adapter. -- Interface Driver: ulink This is the Keil ULINK v1 JTAG debugger. -- Interface Driver: ZY1000 This is the Zylin ZY1000 JTAG debugger. Note: This defines some driver-specific commands, which are not currently documented here. -- Command: power ['on'|'off'] Turn power switch to target on/off. No arguments: print status. -- Interface Driver: bcm2835gpio This SoC is present in Raspberry Pi which is a cheap single-board computer exposing some GPIOs on its expansion header. The driver accesses memory-mapped GPIO peripheral registers directly for maximum performance, but the only possible race condition is for the pins' modes/muxing (which is highly unlikely), so it should be able to coexist nicely with both sysfs bitbanging and various peripherals' kernel drivers. The driver restores the previous configuration on exit. See 'interface/raspberrypi-native.cfg' for a sample config and pinout. 8.3 Transport Configuration =========================== As noted earlier, depending on the version of OpenOCD you use, and the debug adapter you are using, several transports may be available to communicate with debug targets (or perhaps to program flash memory). -- Command: transport list displays the names of the transports supported by this version of OpenOCD. -- Command: transport select 'transport_name' Select which of the supported transports to use in this OpenOCD session. When invoked with 'transport_name', attempts to select the named transport. The transport must be supported by the debug adapter hardware and by the version of OpenOCD you are using (including the adapter's driver). If no transport has been selected and no 'transport_name' is provided, 'transport select' auto-selects the first transport supported by the debug adapter. 'transport select' always returns the name of the session's selected transport, if any. 8.3.1 JTAG Transport -------------------- JTAG is the original transport supported by OpenOCD, and most of the OpenOCD commands support it. JTAG transports expose a chain of one or more Test Access Points (TAPs), each of which must be explicitly declared. JTAG supports both debugging and boundary scan testing. Flash programming support is built on top of debug support. JTAG transport is selected with the command 'transport select jtag'. Unless your adapter uses *note the hla interface driver: hla_interface, in which case the command is 'transport select hla_jtag'. 8.3.2 SWD Transport ------------------- SWD (Serial Wire Debug) is an ARM-specific transport which exposes one Debug Access Point (DAP, which must be explicitly declared. (SWD uses fewer signal wires than JTAG.) SWD is debug-oriented, and does not support boundary scan testing. Flash programming support is built on top of debug support. (Some processors support both JTAG and SWD.) SWD transport is selected with the command 'transport select swd'. Unless your adapter uses *note the hla interface driver: hla_interface, in which case the command is 'transport select hla_swd'. -- Command: swd newdap ... Declares a single DAP which uses SWD transport. Parameters are currently the same as "jtag newtap" but this is expected to change. -- Command: swd wcr trn prescale Updates TRN (turnaraound delay) and prescaling.fields of the Wire Control Register (WCR). No parameters: displays current settings. 8.3.3 SPI Transport ------------------- The Serial Peripheral Interface (SPI) is a general purpose transport which uses four wire signaling. Some processors use it as part of a solution for flash programming. 8.4 JTAG Speed ============== JTAG clock setup is part of system setup. It _does not belong with interface setup_ since any interface only knows a few of the constraints for the JTAG clock speed. Sometimes the JTAG speed is changed during the target initialization process: (1) slow at reset, (2) program the CPU clocks, (3) run fast. Both the "slow" and "fast" clock rates are functions of the oscillators used, the chip, the board design, and sometimes power management software that may be active. The speed used during reset, and the scan chain verification which follows reset, can be adjusted using a 'reset-start' target event handler. It can then be reconfigured to a faster speed by a 'reset-init' target event handler after it reprograms those CPU clocks, or manually (if something else, such as a boot loader, sets up those clocks). *Note Target Events: targetevents. When the initial low JTAG speed is a chip characteristic, perhaps because of a required oscillator speed, provide such a handler in the target config file. When that speed is a function of a board-specific characteristic such as which speed oscillator is used, it belongs in the board config file instead. In both cases it's safest to also set the initial JTAG clock rate to that same slow speed, so that OpenOCD never starts up using a clock speed that's faster than the scan chain can support. jtag_rclk 3000 $_TARGET.cpu configure -event reset-start { jtag_rclk 3000 } If your system supports adaptive clocking (RTCK), configuring JTAG to use that is probably the most robust approach. However, it introduces delays to synchronize clocks; so it may not be the fastest solution. NOTE: Script writers should consider using 'jtag_rclk' instead of 'adapter_khz', but only for (ARM) cores and boards which support adaptive clocking. -- Command: adapter_khz max_speed_kHz A non-zero speed is in KHZ. Hence: 3000 is 3mhz. JTAG interfaces usually support a limited number of speeds. The speed actually used won't be faster than the speed specified. Chip data sheets generally include a top JTAG clock rate. The actual rate is often a function of a CPU core clock, and is normally less than that peak rate. For example, most ARM cores accept at most one sixth of the CPU clock. Speed 0 (khz) selects RTCK method. *Note FAQ RTCK: faqrtck. If your system uses RTCK, you won't need to change the JTAG clocking after setup. Not all interfaces, boards, or targets support "rtck". If the interface device can not support it, an error is returned when you try to use RTCK. -- Function: jtag_rclk fallback_speed_kHz This Tcl proc (defined in 'startup.tcl') attempts to enable RTCK/RCLK. If that fails (maybe the interface, board, or target doesn't support it), falls back to the specified frequency. # Fall back to 3mhz if RTCK is not supported jtag_rclk 3000  File: openocd.info, Node: Reset Configuration, Next: TAP Declaration, Prev: Debug Adapter Configuration, Up: Top 9 Reset Configuration ********************* Every system configuration may require a different reset configuration. This can also be quite confusing. Resets also interact with RESET-INIT event handlers, which do things like setting up clocks and DRAM, and JTAG clock rates. (*Note JTAG Speed: jtagspeed.) They can also interact with JTAG routers. Please see the various board files for examples. Note: To maintainers and integrators: Reset configuration touches several things at once. Normally the board configuration file should define it and assume that the JTAG adapter supports everything that's wired up to the board's JTAG connector. However, the target configuration file could also make note of something the silicon vendor has done inside the chip, which will be true for most (or all) boards using that chip. And when the JTAG adapter doesn't support everything, the user configuration file will need to override parts of the reset configuration provided by other files. 9.1 Types of Reset ================== There are many kinds of reset possible through JTAG, but they may not all work with a given board and adapter. That's part of why reset configuration can be error prone. * _System Reset_ ... the _SRST_ hardware signal resets all chips connected to the JTAG adapter, such as processors, power management chips, and I/O controllers. Normally resets triggered with this signal behave exactly like pressing a RESET button. * _JTAG TAP Reset_ ... the _TRST_ hardware signal resets just the TAP controllers connected to the JTAG adapter. Such resets should not be visible to the rest of the system; resetting a device's TAP controller just puts that controller into a known state. * _Emulation Reset_ ... many devices can be reset through JTAG commands. These resets are often distinguishable from system resets, either explicitly (a "reset reason" register says so) or implicitly (not all parts of the chip get reset). * _Other Resets_ ... system-on-chip devices often support several other types of reset. You may need to arrange that a watchdog timer stops while debugging, preventing a watchdog reset. There may be individual module resets. In the best case, OpenOCD can hold SRST, then reset the TAPs via TRST and send commands through JTAG to halt the CPU at the reset vector before the 1st instruction is executed. Then when it finally releases the SRST signal, the system is halted under debugger control before any code has executed. This is the behavior required to support the 'reset halt' and 'reset init' commands; after 'reset init' a board-specific script might do things like setting up DRAM. (*Note Reset Command: resetcommand.) 9.2 SRST and TRST Issues ======================== Because SRST and TRST are hardware signals, they can have a variety of system-specific constraints. Some of the most common issues are: * _Signal not available_ ... Some boards don't wire SRST or TRST to the JTAG connector. Some JTAG adapters don't support such signals even if they are wired up. Use the 'reset_config' SIGNALS options to say when either of those signals is not connected. When SRST is not available, your code might not be able to rely on controllers having been fully reset during code startup. Missing TRST is not a problem, since JTAG-level resets can be triggered using with TMS signaling. * _Signals shorted_ ... Sometimes a chip, board, or adapter will connect SRST to TRST, instead of keeping them separate. Use the 'reset_config' COMBINATION options to say when those signals aren't properly independent. * _Timing_ ... Reset circuitry like a resistor/capacitor delay circuit, reset supervisor, or on-chip features can extend the effect of a JTAG adapter's reset for some time after the adapter stops issuing the reset. For example, there may be chip or board requirements that all reset pulses last for at least a certain amount of time; and reset buttons commonly have hardware debouncing. Use the 'adapter_nsrst_delay' and 'jtag_ntrst_delay' commands to say when extra delays are needed. * _Drive type_ ... Reset lines often have a pullup resistor, letting the JTAG interface treat them as open-drain signals. But that's not a requirement, so the adapter may need to use push/pull output drivers. Also, with weak pullups it may be advisable to drive signals to both levels (push/pull) to minimize rise times. Use the 'reset_config' TRST_TYPE and SRST_TYPE parameters to say how to drive reset signals. * _Special initialization_ ... Targets sometimes need special JTAG initialization sequences to handle chip-specific issues (not limited to errata). For example, certain JTAG commands might need to be issued while the system as a whole is in a reset state (SRST active) but the JTAG scan chain is usable (TRST inactive). Many systems treat combined assertion of SRST and TRST as a trigger for a harder reset than SRST alone. Such custom reset handling is discussed later in this chapter. There can also be other issues. Some devices don't fully conform to the JTAG specifications. Trivial system-specific differences are common, such as SRST and TRST using slightly different names. There are also vendors who distribute key JTAG documentation for their chips only to developers who have signed a Non-Disclosure Agreement (NDA). Sometimes there are chip-specific extensions like a requirement to use the normally-optional TRST signal (precluding use of JTAG adapters which don't pass TRST through), or needing extra steps to complete a TAP reset. In short, SRST and especially TRST handling may be very finicky, needing to cope with both architecture and board specific constraints. 9.3 Commands for Handling Resets ================================ -- Command: adapter_nsrst_assert_width milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nSRST (active-low system reset) before allowing it to be deasserted. -- Command: adapter_nsrst_delay milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nSRST (active-low system reset) before starting new JTAG operations. When a board has a reset button connected to SRST line it will probably have hardware debouncing, implying you should use this. -- Command: jtag_ntrst_assert_width milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nTRST (active-low JTAG TAP reset) before allowing it to be deasserted. -- Command: jtag_ntrst_delay milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nTRST (active-low JTAG TAP reset) before starting new JTAG operations. -- Command: reset_config mode_flag ... This command displays or modifies the reset configuration of your combination of JTAG board and target in target configuration scripts. Information earlier in this section describes the kind of problems the command is intended to address (*note SRST and TRST Issues: srstandtrstissues.). As a rule this command belongs only in board config files, describing issues like _board doesn't connect TRST_; or in user config files, addressing limitations derived from a particular combination of interface and board. (An unlikely example would be using a TRST-only adapter with a board that only wires up SRST.) The MODE_FLAG options can be specified in any order, but only one of each type - SIGNALS, COMBINATION, GATES, TRST_TYPE, SRST_TYPE and CONNECT_TYPE - may be specified at a time. If you don't provide a new value for a given type, its previous value (perhaps the default) is unchanged. For example, this means that you don't need to say anything at all about TRST just to declare that if the JTAG adapter should want to drive SRST, it must explicitly be driven high ('srst_push_pull'). * SIGNALS can specify which of the reset signals are connected. For example, If the JTAG interface provides SRST, but the board doesn't connect that signal properly, then OpenOCD can't use it. Possible values are 'none' (the default), 'trst_only', 'srst_only' and 'trst_and_srst'. Tip: If your board provides SRST and/or TRST through the JTAG connector, you must declare that so those signals can be used. * The COMBINATION is an optional value specifying broken reset signal implementations. The default behaviour if no option given is 'separate', indicating everything behaves normally. 'srst_pulls_trst' states that the test logic is reset together with the reset of the system (e.g. NXP LPC2000, "broken" board layout), 'trst_pulls_srst' says that the system is reset together with the test logic (only hypothetical, I haven't seen hardware with such a bug, and can be worked around). 'combined' implies both 'srst_pulls_trst' and 'trst_pulls_srst'. * The GATES tokens control flags that describe some cases where JTAG may be unvailable during reset. 'srst_gates_jtag' (default) indicates that asserting SRST gates the JTAG clock. This means that no communication can happen on JTAG while SRST is asserted. Its converse is 'srst_nogate', indicating that JTAG commands can safely be issued while SRST is active. * The CONNECT_TYPE tokens control flags that describe some cases where SRST is asserted while connecting to the target. 'srst_nogate' is required to use this option. 'connect_deassert_srst' (default) indicates that SRST will not be asserted while connecting to the target. Its converse is 'connect_assert_srst', indicating that SRST will be asserted before any target connection. Only some targets support this feature, STM32 and STR9 are examples. This feature is useful if you are unable to connect to your target due to incorrect options byte config or illegal program execution. The optional TRST_TYPE and SRST_TYPE parameters allow the driver mode of each reset line to be specified. These values only affect JTAG interfaces with support for different driver modes, like the Amontec JTAGkey and JTAG Accelerator. Also, they are necessarily ignored if the relevant signal (TRST or SRST) is not connected. * Possible TRST_TYPE driver modes for the test reset signal (TRST) are the default 'trst_push_pull', and 'trst_open_drain'. Most boards connect this signal to a pulldown, so the JTAG TAPs never leave reset unless they are hooked up to a JTAG adapter. * Possible SRST_TYPE driver modes for the system reset signal (SRST) are the default 'srst_open_drain', and 'srst_push_pull'. Most boards connect this signal to a pullup, and allow the signal to be pulled low by various events including system powerup and pressing a reset button. 9.4 Custom Reset Handling ========================= OpenOCD has several ways to help support the various reset mechanisms provided by chip and board vendors. The commands shown in the previous section give standard parameters. There are also _event handlers_ associated with TAPs or Targets. Those handlers are Tcl procedures you can provide, which are invoked at particular points in the reset sequence. _When SRST is not an option_ you must set up a 'reset-assert' event handler for your target. For example, some JTAG adapters don't include the SRST signal; and some boards have multiple targets, and you won't always want to reset everything at once. After configuring those mechanisms, you might still find your board doesn't start up or reset correctly. For example, maybe it needs a slightly different sequence of SRST and/or TRST manipulations, because of quirks that the 'reset_config' mechanism doesn't address; or asserting both might trigger a stronger reset, which needs special attention. Experiment with lower level operations, such as 'jtag_reset' and the 'jtag arp_*' operations shown here, to find a sequence of operations that works. *Note JTAG Commands::. When you find a working sequence, it can be used to override 'jtag_init', which fires during OpenOCD startup (*note Configuration Stage: configurationstage.); or 'init_reset', which fires during reset processing. You might also want to provide some project-specific reset schemes. For example, on a multi-target board the standard 'reset' command would reset all targets, but you may need the ability to reset only one target at time and thus want to avoid using the board-wide SRST signal. -- Overridable Procedure: init_reset mode This is invoked near the beginning of the 'reset' command, usually to provide as much of a cold (power-up) reset as practical. By default it is also invoked from 'jtag_init' if the scan chain does not respond to pure JTAG operations. The MODE parameter is the parameter given to the low level reset command ('halt', 'init', or 'run'), 'setup', or potentially some other value. The default implementation just invokes 'jtag arp_init-reset'. Replacements will normally build on low level JTAG operations such as 'jtag_reset'. Operations here must not address individual TAPs (or their associated targets) until the JTAG scan chain has first been verified to work. Implementations must have verified the JTAG scan chain before they return. This is done by calling 'jtag arp_init' (or 'jtag arp_init-reset'). -- Command: jtag arp_init This validates the scan chain using just the four standard JTAG signals (TMS, TCK, TDI, TDO). It starts by issuing a JTAG-only reset. Then it performs checks to verify that the scan chain configuration matches the TAPs it can observe. Those checks include checking IDCODE values for each active TAP, and verifying the length of their instruction registers using TAP '-ircapture' and '-irmask' values. If these tests all pass, TAP 'setup' events are issued to all TAPs with handlers for that event. -- Command: jtag arp_init-reset This uses TRST and SRST to try resetting everything on the JTAG scan chain (and anything else connected to SRST). It then invokes the logic of 'jtag arp_init'.  File: openocd.info, Node: TAP Declaration, Next: CPU Configuration, Prev: Reset Configuration, Up: Top 10 TAP Declaration ****************** _Test Access Ports_ (TAPs) are the core of JTAG. TAPs serve many roles, including: * Debug Target A CPU TAP can be used as a GDB debug target. * Flash Programming Some chips program the flash directly via JTAG. Others do it indirectly, making a CPU do it. * Program Download Using the same CPU support GDB uses, you can initialize a DRAM controller, download code to DRAM, and then start running that code. * Boundary Scan Most chips support boundary scan, which helps test for board assembly problems like solder bridges and missing connections. OpenOCD must know about the active TAPs on your board(s). Setting up the TAPs is the core task of your configuration files. Once those TAPs are set up, you can pass their names to code which sets up CPUs and exports them as GDB targets, probes flash memory, performs low-level JTAG operations, and more. 10.1 Scan Chains ================ TAPs are part of a hardware "scan chain", which is a daisy chain of TAPs. They also need to be added to OpenOCD's software mirror of that hardware list, giving each member a name and associating other data with it. Simple scan chains, with a single TAP, are common in systems with a single microcontroller or microprocessor. More complex chips may have several TAPs internally. Very complex scan chains might have a dozen or more TAPs: several in one chip, more in the next, and connecting to other boards with their own chips and TAPs. You can display the list with the 'scan_chain' command. (Don't confuse this with the list displayed by the 'targets' command, presented in the next chapter. That only displays TAPs for CPUs which are configured as debugging targets.) Here's what the scan chain might look like for a chip more than one TAP: TapName Enabled IdCode Expected IrLen IrCap IrMask -- ------------------ ------- ---------- ---------- ----- ----- ------ 0 omap5912.dsp Y 0x03df1d81 0x03df1d81 38 0x01 0x03 1 omap5912.arm Y 0x0692602f 0x0692602f 4 0x01 0x0f 2 omap5912.unknown Y 0x00000000 0x00000000 8 0x01 0x03 OpenOCD can detect some of that information, but not all of it. *Note Autoprobing: autoprobing. Unfortunately, those TAPs can't always be autoconfigured, because not all devices provide good support for that. JTAG doesn't require supporting IDCODE instructions, and chips with JTAG routers may not link TAPs into the chain until they are told to do so. The configuration mechanism currently supported by OpenOCD requires explicit configuration of all TAP devices using 'jtag newtap' commands, as detailed later in this chapter. A command like this would declare one tap and name it 'chip1.cpu': jtag newtap chip1 cpu -irlen 4 -expected-id 0x3ba00477 Each target configuration file lists the TAPs provided by a given chip. Board configuration files combine all the targets on a board, and so forth. Note that _the order in which TAPs are declared is very important._ That declaration order must match the order in the JTAG scan chain, both inside a single chip and between them. *Note FAQ TAP Order: faqtaporder. For example, the ST Microsystems STR912 chip has three separate TAPs(1). To configure those taps, 'target/str912.cfg' includes commands something like this: jtag newtap str912 flash ... params ... jtag newtap str912 cpu ... params ... jtag newtap str912 bs ... params ... Actual config files typically use a variable such as '$_CHIPNAME' instead of literals like 'str912', to support more than one chip of each type. *Note Config File Guidelines::. -- Command: jtag names Returns the names of all current TAPs in the scan chain. Use 'jtag cget' or 'jtag tapisenabled' to examine attributes and state of each TAP. foreach t [jtag names] { puts [format "TAP: %s\n" $t] } -- Command: scan_chain Displays the TAPs in the scan chain configuration, and their status. The set of TAPs listed by this command is fixed by exiting the OpenOCD configuration stage, but systems with a JTAG router can enable or disable TAPs dynamically. 10.2 TAP Names ============== When TAP objects are declared with 'jtag newtap', a "dotted.name" is created for the TAP, combining the name of a module (usually a chip) and a label for the TAP. For example: 'xilinx.tap', 'str912.flash', 'omap3530.jrc', 'dm6446.dsp', or 'stm32.cpu'. Many other commands use that dotted.name to manipulate or refer to the TAP. For example, CPU configuration uses the name, as does declaration of NAND or NOR flash banks. The components of a dotted name should follow "C" symbol name rules: start with an alphabetic character, then numbers and underscores are OK; while others (including dots!) are not. 10.3 TAP Declaration Commands ============================= -- Command: jtag newtap chipname tapname configparams... Declares a new TAP with the dotted name CHIPNAME.TAPNAME, and configured according to the various CONFIGPARAMS. The CHIPNAME is a symbolic name for the chip. Conventionally target config files use '$_CHIPNAME', defaulting to the model name given by the chip vendor but overridable. The TAPNAME reflects the role of that TAP, and should follow this convention: * 'bs' - For boundary scan if this is a separate TAP; * 'cpu' - The main CPU of the chip, alternatively 'arm' and 'dsp' on chips with both ARM and DSP CPUs, 'arm1' and 'arm2' on chips with two ARMs, and so forth; * 'etb' - For an embedded trace buffer (example: an ARM ETB11); * 'flash' - If the chip has a flash TAP, like the str912; * 'jrc' - For JTAG route controller (example: the ICEPick modules on many Texas Instruments chips, like the OMAP3530 on Beagleboards); * 'tap' - Should be used only for FPGA- or CPLD-like devices with a single TAP; * 'unknownN' - If you have no idea what the TAP is for (N is a number); * _when in doubt_ - Use the chip maker's name in their data sheet. For example, the Freescale i.MX31 has a SDMA (Smart DMA) with a JTAG TAP; that TAP should be named 'sdma'. Every TAP requires at least the following CONFIGPARAMS: * '-irlen' NUMBER The length in bits of the instruction register, such as 4 or 5 bits. A TAP may also provide optional CONFIGPARAMS: * '-disable' (or '-enable') Use the '-disable' parameter to flag a TAP which is not linked into the scan chain after a reset using either TRST or the JTAG state machine's RESET state. You may use '-enable' to highlight the default state (the TAP is linked in). *Note Enabling and Disabling TAPs: enablinganddisablingtaps. * '-expected-id' NUMBER A non-zero NUMBER represents a 32-bit IDCODE which you expect to find when the scan chain is examined. These codes are not required by all JTAG devices. _Repeat the option_ as many times as required if more than one ID code could appear (for example, multiple versions). Specify NUMBER as zero to suppress warnings about IDCODE values that were found but not included in the list. Provide this value if at all possible, since it lets OpenOCD tell when the scan chain it sees isn't right. These values are provided in vendors' chip documentation, usually a technical reference manual. Sometimes you may need to probe the JTAG hardware to find these values. *Note Autoprobing: autoprobing. * '-ignore-version' Specify this to ignore the JTAG version field in the '-expected-id' option. When vendors put out multiple versions of a chip, or use the same JTAG-level ID for several largely-compatible chips, it may be more practical to ignore the version field than to update config files to handle all of the various chip IDs. The version field is defined as bit 28-31 of the IDCODE. * '-ircapture' NUMBER The bit pattern loaded by the TAP into the JTAG shift register on entry to the IRCAPTURE state, such as 0x01. JTAG requires the two LSBs of this value to be 01. By default, '-ircapture' and '-irmask' are set up to verify that two-bit value. You may provide additional bits if you know them, or indicate that a TAP doesn't conform to the JTAG specification. * '-irmask' NUMBER A mask used with '-ircapture' to verify that instruction scans work correctly. Such scans are not used by OpenOCD except to verify that there seems to be no problems with JTAG scan chain operations. 10.4 Other TAP commands ======================= -- Command: jtag cget dotted.name '-event' event_name -- Command: jtag configure dotted.name '-event' event_name handler At this writing this TAP attribute mechanism is used only for event handling. (It is not a direct analogue of the 'cget'/'configure' mechanism for debugger targets.) See the next section for information about the available events. The 'configure' subcommand assigns an event handler, a TCL string which is evaluated when the event is triggered. The 'cget' subcommand returns that handler. 10.5 TAP Events =============== OpenOCD includes two event mechanisms. The one presented here applies to all JTAG TAPs. The other applies to debugger targets, which are associated with certain TAPs. The TAP events currently defined are: * post-reset The TAP has just completed a JTAG reset. The tap may still be in the JTAG RESET state. Handlers for these events might perform initialization sequences such as issuing TCK cycles, TMS sequences to ensure exit from the ARM SWD mode, and more. Because the scan chain has not yet been verified, handlers for these events _should not issue commands which scan the JTAG IR or DR registers_ of any particular target. NOTE: As this is written (September 2009), nothing prevents such access. * setup The scan chain has been reset and verified. This handler may enable TAPs as needed. * tap-disable The TAP needs to be disabled. This handler should implement 'jtag tapdisable' by issuing the relevant JTAG commands. * tap-enable The TAP needs to be enabled. This handler should implement 'jtag tapenable' by issuing the relevant JTAG commands. If you need some action after each JTAG reset which isn't actually specific to any TAP (since you can't yet trust the scan chain's contents to be accurate), you might: jtag configure CHIP.jrc -event post-reset { echo "JTAG Reset done" ... non-scan jtag operations to be done after reset } 10.6 Enabling and Disabling TAPs ================================ In some systems, a "JTAG Route Controller" (JRC) is used to enable and/or disable specific JTAG TAPs. Many ARM-based chips from Texas Instruments include an "ICEPick" module, which is a JRC. Such chips include DaVinci and OMAP3 processors. A given TAP may not be visible until the JRC has been told to link it into the scan chain; and if the JRC has been told to unlink that TAP, it will no longer be visible. Such routers address problems that JTAG "bypass mode" ignores, such as: * The scan chain can only go as fast as its slowest TAP. * Having many TAPs slows instruction scans, since all TAPs receive new instructions. * TAPs in the scan chain must be powered up, which wastes power and prevents debugging some power management mechanisms. The IEEE 1149.1 JTAG standard has no concept of a "disabled" tap, as implied by the existence of JTAG routers. However, the upcoming IEEE 1149.7 framework (layered on top of JTAG) does include a kind of JTAG router functionality. In OpenOCD, tap enabling/disabling is invoked by the Tcl commands shown below, and is implemented using TAP event handlers. So for example, when defining a TAP for a CPU connected to a JTAG router, your 'target.cfg' file should define TAP event handlers using code that looks something like this: jtag configure CHIP.cpu -event tap-enable { ... jtag operations using CHIP.jrc } jtag configure CHIP.cpu -event tap-disable { ... jtag operations using CHIP.jrc } Then you might want that CPU's TAP enabled almost all the time: jtag configure $CHIP.jrc -event setup "jtag tapenable $CHIP.cpu" Note how that particular setup event handler declaration uses quotes to evaluate '$CHIP' when the event is configured. Using brackets { } would cause it to be evaluated later, at runtime, when it might have a different value. -- Command: jtag tapdisable dotted.name If necessary, disables the tap by sending it a 'tap-disable' event. Returns the string "1" if the tap specified by DOTTED.NAME is enabled, and "0" if it is disabled. -- Command: jtag tapenable dotted.name If necessary, enables the tap by sending it a 'tap-enable' event. Returns the string "1" if the tap specified by DOTTED.NAME is enabled, and "0" if it is disabled. -- Command: jtag tapisenabled dotted.name Returns the string "1" if the tap specified by DOTTED.NAME is enabled, and "0" if it is disabled. Note: Humans will find the 'scan_chain' command more helpful for querying the state of the JTAG taps. 10.7 Autoprobing ================ TAP configuration is the first thing that needs to be done after interface and reset configuration. Sometimes it's hard finding out what TAPs exist, or how they are identified. Vendor documentation is not always easy to find and use. To help you get past such problems, OpenOCD has a limited _autoprobing_ ability to look at the scan chain, doing a "blind interrogation" and then reporting the TAPs it finds. To use this mechanism, start the OpenOCD server with only data that configures your JTAG interface, and arranges to come up with a slow clock (many devices don't support fast JTAG clocks right when they come out of reset). For example, your 'openocd.cfg' file might have: source [find interface/olimex-arm-usb-tiny-h.cfg] reset_config trst_and_srst jtag_rclk 8 When you start the server without any TAPs configured, it will attempt to autoconfigure the TAPs. There are two parts to this: 1. _TAP discovery_ ... After a JTAG reset (sometimes a system reset may be needed too), each TAP's data registers will hold the contents of either the IDCODE or BYPASS register. If JTAG communication is working, OpenOCD will see each TAP, and report what '-expected-id' to use with it. 2. _IR Length discovery_ ... Unfortunately JTAG does not provide a reliable way to find out the value of the '-irlen' parameter to use with a TAP that is discovered. If OpenOCD can discover the length of a TAP's instruction register, it will report it. Otherwise you may need to consult vendor documentation, such as chip data sheets or BSDL files. In many cases your board will have a simple scan chain with just a single device. Here's what OpenOCD reported with one board that's a bit more complex: clock speed 8 kHz There are no enabled taps. AUTO PROBING MIGHT NOT WORK!! AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x2b900f0f ..." AUTO auto1.tap - use "jtag newtap auto1 tap -expected-id 0x07926001 ..." AUTO auto2.tap - use "jtag newtap auto2 tap -expected-id 0x0b73b02f ..." AUTO auto0.tap - use "... -irlen 4" AUTO auto1.tap - use "... -irlen 4" AUTO auto2.tap - use "... -irlen 6" no gdb ports allocated as no target has been specified Given that information, you should be able to either find some existing config files to use, or create your own. If you create your own, you would configure from the bottom up: first a 'target.cfg' file with these TAPs, any targets associated with them, and any on-chip resources; then a 'board.cfg' with off-chip resources, clocking, and so forth. ---------- Footnotes ---------- (1) See the ST document titled: _STR91xFAxxx, Section 3.15 Jtag Interface, Page: 28/102, Figure 3: JTAG chaining inside the STR91xFA_.  File: openocd.info, Node: CPU Configuration, Next: Flash Commands, Prev: TAP Declaration, Up: Top 11 CPU Configuration ******************** This chapter discusses how to set up GDB debug targets for CPUs. You can also access these targets without GDB (*note Architecture and Core Commands::, and *note Target State handling: targetstatehandling.) and through various kinds of NAND and NOR flash commands. If you have multiple CPUs you can have multiple such targets. We'll start by looking at how to examine the targets you have, then look at how to add one more target and how to configure it. 11.1 Target List ================ All targets that have been set up are part of a list, where each member has a name. That name should normally be the same as the TAP name. You can display the list with the 'targets' (plural!) command. This display often has only one CPU; here's what it might look like with more than one: TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0* at91rm9200.cpu arm920t little at91rm9200.cpu running 1 MyTarget cortex_m little mychip.foo tap-disabled One member of that list is the "current target", which is implicitly referenced by many commands. It's the one marked with a '*' near the target name. In particular, memory addresses often refer to the address space seen by that current target. Commands like 'mdw' (memory display words) and 'flash erase_address' (erase NOR flash blocks) are examples; and there are many more. Several commands let you examine the list of targets: -- Command: target current Returns the name of the current target. -- Command: target names Lists the names of all current targets in the list. foreach t [target names] { puts [format "Target: %s\n" $t] } -- Command: targets [name] _Note: the name of this command is plural. Other target command names are singular._ With no parameter, this command displays a table of all known targets in a user friendly form. With a parameter, this command sets the current target to the given target with the given NAME; this is only relevant on boards which have more than one target. 11.2 Target CPU Types ===================== Each target has a "CPU type", as shown in the output of the 'targets' command. You need to specify that type when calling 'target create'. The CPU type indicates more than just the instruction set. It also indicates how that instruction set is implemented, what kind of debug support it integrates, whether it has an MMU (and if so, what kind), what core-specific commands may be available (*note Architecture and Core Commands::), and more. It's easy to see what target types are supported, since there's a command to list them. -- Command: target types Lists all supported target types. At this writing, the supported CPU types are: * 'arm11' - this is a generation of ARMv6 cores * 'arm720t' - this is an ARMv4 core with an MMU * 'arm7tdmi' - this is an ARMv4 core * 'arm920t' - this is an ARMv4 core with an MMU * 'arm926ejs' - this is an ARMv5 core with an MMU * 'arm966e' - this is an ARMv5 core * 'arm9tdmi' - this is an ARMv4 core * 'avr' - implements Atmel's 8-bit AVR instruction set. (Support for this is preliminary and incomplete.) * 'cortex_a' - this is an ARMv7 core with an MMU * 'cortex_m' - this is an ARMv7 core, supporting only the compact Thumb2 instruction set. * 'dragonite' - resembles arm966e * 'dsp563xx' - implements Freescale's 24-bit DSP. (Support for this is still incomplete.) * 'fa526' - resembles arm920 (w/o Thumb) * 'feroceon' - resembles arm926 * 'mips_m4k' - a MIPS core * 'xscale' - this is actually an architecture, not a CPU type. It is based on the ARMv5 architecture. * 'openrisc' - this is an OpenRISC 1000 core. The current implementation supports three JTAG TAP cores: - 'OpenCores TAP' (See: jtag (http://opencores.org/project)) - 'Altera Virtual JTAG TAP' (See: ) - 'Xilinx BSCAN_* virtual JTAG interface' (See: ) And two debug interfaces cores: - 'Advanced debug interface' (See: adv_debug_sys (http://opencores.org/project)) - 'SoC Debug Interface' (See: dbg_interface (http://opencores.org/project)) To avoid being confused by the variety of ARM based cores, remember this key point: _ARM is a technology licencing company_. (See: .) The CPU name used by OpenOCD will reflect the CPU design that was licenced, not a vendor brand which incorporates that design. Name prefixes like arm7, arm9, arm11, and cortex reflect design generations; while names like ARMv4, ARMv5, ARMv6, and ARMv7 reflect an architecture version implemented by a CPU design. 11.3 Target Configuration ========================= Before creating a "target", you must have added its TAP to the scan chain. When you've added that TAP, you will have a 'dotted.name' which is used to set up the CPU support. The chip-specific configuration file will normally configure its CPU(s) right after it adds all of the chip's TAPs to the scan chain. Although you can set up a target in one step, it's often clearer if you use shorter commands and do it in two steps: create it, then configure optional parts. All operations on the target after it's created will use a new command, created as part of target creation. The two main things to configure after target creation are a work area, which usually has target-specific defaults even if the board setup code overrides them later; and event handlers (*note Target Events: targetevents.), which tend to be much more board-specific. The key steps you use might look something like this target create MyTarget cortex_m -chain-position mychip.cpu $MyTarget configure -work-area-phys 0x08000 -work-area-size 8096 $MyTarget configure -event reset-deassert-pre { jtag_rclk 5 } $MyTarget configure -event reset-init { myboard_reinit } You should specify a working area if you can; typically it uses some on-chip SRAM. Such a working area can speed up many things, including bulk writes to target memory; flash operations like checking to see if memory needs to be erased; GDB memory checksumming; and more. Warning: On more complex chips, the work area can become inaccessible when application code (such as an operating system) enables or disables the MMU. For example, the particular MMU context used to acess the virtual address will probably matter ... and that context might not have easy access to other addresses needed. At this writing, OpenOCD doesn't have much MMU intelligence. It's often very useful to define a 'reset-init' event handler. For systems that are normally used with a boot loader, common tasks include updating clocks and initializing memory controllers. That may be needed to let you write the boot loader into flash, in order to "de-brick" your board; or to load programs into external DDR memory without having run the boot loader. -- Command: target create target_name type configparams... This command creates a GDB debug target that refers to a specific JTAG tap. It enters that target into a list, and creates a new command ('TARGET_NAME') which is used for various purposes including additional configuration. * TARGET_NAME ... is the name of the debug target. By convention this should be the same as the _dotted.name_ of the TAP associated with this target, which must be specified here using the '-chain-position DOTTED.NAME' configparam. This name is also used to create the target object command, referred to here as '$target_name', and in other places the target needs to be identified. * TYPE ... specifies the target type. *Note target types: targettypes. * CONFIGPARAMS ... all parameters accepted by '$target_name configure' are permitted. If the target is big-endian, set it here with '-endian big'. You _must_ set the '-chain-position DOTTED.NAME' here. -- Command: $target_name configure configparams... The options accepted by this command may also be specified as parameters to 'target create'. Their values can later be queried one at a time by using the '$target_name cget' command. _Warning:_ changing some of these after setup is dangerous. For example, moving a target from one TAP to another; and changing its endianness. * '-chain-position' DOTTED.NAME - names the TAP used to access this target. * '-endian' ('big'|'little') - specifies whether the CPU uses big or little endian conventions * '-event' EVENT_NAME EVENT_BODY - *Note Target Events: targetevents. Note that this updates a list of named event handlers. Calling this twice with two different event names assigns two different handlers, but calling it twice with the same event name assigns only one handler. * '-work-area-backup' ('0'|'1') - says whether the work area gets backed up; by default, _it is not backed up._ When possible, use a working_area that doesn't need to be backed up, since performing a backup slows down operations. For example, the beginning of an SRAM block is likely to be used by most build systems, but the end is often unused. * '-work-area-size' SIZE - specify work are size, in bytes. The same size applies regardless of whether its physical or virtual address is being used. * '-work-area-phys' ADDRESS - set the work area base ADDRESS to be used when no MMU is active. * '-work-area-virt' ADDRESS - set the work area base ADDRESS to be used when an MMU is active. _Do not specify a value for this except on targets with an MMU._ The value should normally correspond to a static mapping for the '-work-area-phys' address, set up by the current operating system. * '-rtos' RTOS_TYPE - enable rtos support for target, RTOS_TYPE can be one of 'auto'|'eCos'|'ThreadX'| 'FreeRTOS'|'linux'|'ChibiOS'|'embKernel'|'mqx' *Note RTOS Support: gdbrtossupport. 11.4 Other $target_name Commands ================================ The Tcl/Tk language has the concept of object commands, and OpenOCD adopts that same model for targets. A good Tk example is a on screen button. Once a button is created a button has a name (a path in Tk terms) and that name is useable as a first class command. For example in Tk, one can create a button and later configure it like this: # Create button .foobar -background red -command { foo } # Modify .foobar configure -foreground blue # Query set x [.foobar cget -background] # Report puts [format "The button is %s" $x] In OpenOCD's terms, the "target" is an object just like a Tcl/Tk button, and its object commands are invoked the same way. str912.cpu mww 0x1234 0x42 omap3530.cpu mww 0x5555 123 The commands supported by OpenOCD target objects are: -- Command: $target_name arp_examine -- Command: $target_name arp_halt -- Command: $target_name arp_poll -- Command: $target_name arp_reset -- Command: $target_name arp_waitstate Internal OpenOCD scripts (most notably 'startup.tcl') use these to deal with specific reset cases. They are not otherwise documented here. -- Command: $target_name array2mem arrayname width address count -- Command: $target_name mem2array arrayname width address count These provide an efficient script-oriented interface to memory. The 'array2mem' primitive writes bytes, halfwords, or words; while 'mem2array' reads them. In both cases, the TCL side uses an array, and the target side uses raw memory. The efficiency comes from enabling the use of bulk JTAG data transfer operations. The script orientation comes from working with data values that are packaged for use by TCL scripts; 'mdw' type primitives only print data they retrieve, and neither store nor return those values. * ARRAYNAME ... is the name of an array variable * WIDTH ... is 8/16/32 - indicating the memory access size * ADDRESS ... is the target memory address * COUNT ... is the number of elements to process -- Command: $target_name cget queryparm Each configuration parameter accepted by '$target_name configure' can be individually queried, to return its current value. The QUERYPARM is a parameter name accepted by that command, such as '-work-area-phys'. There are a few special cases: * '-event' EVENT_NAME - returns the handler for the event named EVENT_NAME. This is a special case because setting a handler requires two parameters. * '-type' - returns the target type. This is a special case because this is set using 'target create' and can't be changed using '$target_name configure'. For example, if you wanted to summarize information about all the targets you might use something like this: foreach name [target names] { set y [$name cget -endian] set z [$name cget -type] puts [format "Chip %d is %s, Endian: %s, type: %s" \ $x $name $y $z] } -- Command: $target_name curstate Displays the current target state: 'debug-running', 'halted', 'reset', 'running', or 'unknown'. (Also, *note Event Polling: eventpolling.) -- Command: $target_name eventlist Displays a table listing all event handlers currently associated with this target. *Note Target Events: targetevents. -- Command: $target_name invoke-event event_name Invokes the handler for the event named EVENT_NAME. (This is primarily intended for use by OpenOCD framework code, for example by the reset code in 'startup.tcl'.) -- Command: $target_name mdw addr [count] -- Command: $target_name mdh addr [count] -- Command: $target_name mdb addr [count] Display contents of address ADDR, as 32-bit words ('mdw'), 16-bit halfwords ('mdh'), or 8-bit bytes ('mdb'). If COUNT is specified, displays that many units. (If you want to manipulate the data instead of displaying it, see the 'mem2array' primitives.) -- Command: $target_name mww addr word -- Command: $target_name mwh addr halfword -- Command: $target_name mwb addr byte Writes the specified WORD (32 bits), HALFWORD (16 bits), or BYTE (8-bit) pattern, at the specified address ADDR. 11.5 Target Events ================== At various times, certain things can happen, or you want them to happen. For example: * What should happen when GDB connects? Should your target reset? * When GDB tries to flash the target, do you need to enable the flash via a special command? * Is using SRST appropriate (and possible) on your system? Or instead of that, do you need to issue JTAG commands to trigger reset? SRST usually resets everything on the scan chain, which can be inappropriate. * During reset, do you need to write to certain memory locations to set up system clocks or to reconfigure the SDRAM? How about configuring the watchdog timer, or other peripherals, to stop running while you hold the core stopped for debugging? All of the above items can be addressed by target event handlers. These are set up by '$target_name configure -event' or 'target create ... -event'. The programmer's model matches the '-command' option used in Tcl/Tk buttons and events. The two examples below act the same, but one creates and invokes a small procedure while the other inlines it. proc my_attach_proc { } { echo "Reset..." reset halt } mychip.cpu configure -event gdb-attach my_attach_proc mychip.cpu configure -event gdb-attach { echo "Reset..." # To make flash probe and gdb load to flash work # we need a reset init. reset init } The following target events are defined: * debug-halted The target has halted for debug reasons (i.e.: breakpoint) * debug-resumed The target has resumed (i.e.: gdb said run) * early-halted Occurs early in the halt process * examine-start Before target examine is called. * examine-end After target examine is called with no errors. * gdb-attach When GDB connects. This is before any communication with the target, so this can be used to set up the target so it is possible to probe flash. Probing flash is necessary during gdb connect if gdb load is to write the image to flash. Another use of the flash memory map is for GDB to automatically hardware/software breakpoints depending on whether the breakpoint is in RAM or read only memory. * gdb-detach When GDB disconnects * gdb-end When the target has halted and GDB is not doing anything (see early halt) * gdb-flash-erase-start Before the GDB flash process tries to erase the flash (default is 'reset init') * gdb-flash-erase-end After the GDB flash process has finished erasing the flash * gdb-flash-write-start Before GDB writes to the flash * gdb-flash-write-end After GDB writes to the flash (default is 'reset halt') * gdb-start Before the target steps, gdb is trying to start/resume the target * halted The target has halted * reset-assert-pre Issued as part of 'reset' processing after 'reset_init' was triggered but before either SRST alone is re-asserted on the scan chain, or 'reset-assert' is triggered. * reset-assert Issued as part of 'reset' processing after 'reset-assert-pre' was triggered. When such a handler is present, cores which support this event will use it instead of asserting SRST. This support is essential for debugging with JTAG interfaces which don't include an SRST line (JTAG doesn't require SRST), and for selective reset on scan chains that have multiple targets. * reset-assert-post Issued as part of 'reset' processing after 'reset-assert' has been triggered. or the target asserted SRST on the entire scan chain. * reset-deassert-pre Issued as part of 'reset' processing after 'reset-assert-post' has been triggered. * reset-deassert-post Issued as part of 'reset' processing after 'reset-deassert-pre' has been triggered and (if the target is using it) after SRST has been released on the scan chain. * reset-end Issued as the final step in 'reset' processing. * reset-init Used by reset init command for board-specific initialization. This event fires after _reset-deassert-post_. This is where you would configure PLLs and clocking, set up DRAM so you can download programs that don't fit in on-chip SRAM, set up pin multiplexing, and so on. (You may be able to switch to a fast JTAG clock rate here, after the target clocks are fully set up.) * reset-start Issued as part of 'reset' processing before 'reset_init' is called. This is the most robust place to use 'jtag_rclk' or 'adapter_khz' to switch to a low JTAG clock rate, when reset disables PLLs needed to use a fast clock. * resume-start Before any target is resumed * resume-end After all targets have resumed * resumed Target has resumed * trace-config After target hardware trace configuration was changed  File: openocd.info, Node: Flash Commands, Next: Flash Programming, Prev: CPU Configuration, Up: Top 12 Flash Commands ***************** OpenOCD has different commands for NOR and NAND flash; the "flash" command works with NOR flash, while the "nand" command works with NAND flash. This partially reflects different hardware technologies: NOR flash usually supports direct CPU instruction and data bus access, while data from a NAND flash must be copied to memory before it can be used. (SPI flash must also be copied to memory before use.) However, the documentation also uses "flash" as a generic term; for example, "Put flash configuration in board-specific files". Flash Steps: 1. Configure via the command 'flash bank' Do this in a board-specific configuration file, passing parameters as needed by the driver. 2. Operate on the flash via 'flash subcommand' Often commands to manipulate the flash are typed by a human, or run via a script in some automated way. Common tasks include writing a boot loader, operating system, or other data. 3. GDB Flashing Flashing via GDB requires the flash be configured via "flash bank", and the GDB flash features be enabled. *Note GDB Configuration: gdbconfiguration. Many CPUs have the ablity to "boot" from the first flash bank. This means that misprogramming that bank can "brick" a system, so that it can't boot. JTAG tools, like OpenOCD, are often then used to "de-brick" the board by (re)installing working boot firmware. 12.1 Flash Configuration Commands ================================= -- Config Command: flash bank name driver base size chip_width bus_width target [driver_options] Configures a flash bank which provides persistent storage for addresses from base to base + size - 1. These banks will often be visible to GDB through the target's memory map. In some cases, configuring a flash bank will activate extra commands; see the driver-specific documentation. * NAME ... may be used to reference the flash bank in other flash commands. A number is also available. * DRIVER ... identifies the controller driver associated with the flash bank being declared. This is usually 'cfi' for external flash, or else the name of a microcontroller with embedded flash memory. *Note Flash Driver List: flashdriverlist. * BASE ... Base address of the flash chip. * SIZE ... Size of the chip, in bytes. For some drivers, this value is detected from the hardware. * CHIP_WIDTH ... Width of the flash chip, in bytes; ignored for most microcontroller drivers. * BUS_WIDTH ... Width of the data bus used to access the chip, in bytes; ignored for most microcontroller drivers. * TARGET ... Names the target used to issue commands to the flash controller. * DRIVER_OPTIONS ... drivers may support, or require, additional parameters. See the driver-specific documentation for more information. Note: This command is not available after OpenOCD initialization has completed. Use it in board specific configuration files, not interactively. -- Command: flash banks Prints a one-line summary of each device that was declared using 'flash bank', numbered from zero. Note that this is the _plural_ form; the _singular_ form is a very different command. -- Command: flash list Retrieves a list of associative arrays for each device that was declared using 'flash bank', numbered from zero. This returned list can be manipulated easily from within scripts. -- Command: flash probe num Identify the flash, or validate the parameters of the configured flash. Operation depends on the flash type. The NUM parameter is a value shown by 'flash banks'. Most flash commands will implicitly _autoprobe_ the bank; flash drivers can distinguish between probing and autoprobing, but most don't bother. 12.2 Erasing, Reading, Writing to Flash ======================================= One feature distinguishing NOR flash from NAND or serial flash technologies is that for read access, it acts exactly like any other addressible memory. This means you can use normal memory read commands like 'mdw' or 'dump_image' with it, with no special 'flash' subcommands. *Note Memory access: memoryaccess, and *note Image access: imageaccess. Write access works differently. Flash memory normally needs to be erased before it's written. Erasing a sector turns all of its bits to ones, and writing can turn ones into zeroes. This is why there are special commands for interactive erasing and writing, and why GDB needs to know which parts of the address space hold NOR flash memory. Note: Most of these erase and write commands leverage the fact that NOR flash chips consume target address space. They implicitly refer to the current JTAG target, and map from an address in that target's address space back to a flash bank. A few commands use abstract addressing based on bank and sector numbers, and don't depend on searching the current target and its address space. Avoid confusing the two command models. Some flash chips implement software protection against accidental writes, since such buggy writes could in some cases "brick" a system. For such systems, erasing and writing may require sector protection to be disabled first. Examples include CFI flash such as "Intel Advanced Bootblock flash", and AT91SAM7 on-chip flash. *Note flash protect: flashprotect. -- Command: flash erase_sector num first last Erase sectors in bank NUM, starting at sector FIRST up to and including LAST. Sector numbering starts at 0. Providing a LAST sector of 'last' specifies "to the end of the flash bank". The NUM parameter is a value shown by 'flash banks'. -- Command: flash erase_address ['pad'] ['unlock'] address length Erase sectors starting at ADDRESS for LENGTH bytes. Unless 'pad' is specified, address must begin a flash sector, and address + length - 1 must end a sector. Specifying 'pad' erases extra data at the beginning and/or end of the specified region, as needed to erase only full sectors. The flash bank to use is inferred from the ADDRESS, and the specified length must stay within that bank. As a special case, when LENGTH is zero and ADDRESS is the start of the bank, the whole flash is erased. If 'unlock' is specified, then the flash is unprotected before erase starts. -- Command: flash fillw address word length -- Command: flash fillh address halfword length -- Command: flash fillb address byte length Fills flash memory with the specified WORD (32 bits), HALFWORD (16 bits), or BYTE (8-bit) pattern, starting at ADDRESS and continuing for LENGTH units (word/halfword/byte). No erasure is done before writing; when needed, that must be done before issuing this command. Writes are done in blocks of up to 1024 bytes, and each write is verified by reading back the data and comparing it to what was written. The flash bank to use is inferred from the ADDRESS of each block, and the specified length must stay within that bank. -- Command: flash write_bank num filename offset Write the binary 'filename' to flash bank NUM, starting at OFFSET bytes from the beginning of the bank. The NUM parameter is a value shown by 'flash banks'. -- Command: flash write_image [erase] [unlock] filename [offset] [type] Write the image 'filename' to the current target's flash bank(s). Only loadable sections from the image are written. A relocation OFFSET may be specified, in which case it is added to the base address for each section in the image. The file [TYPE] can be specified explicitly as 'bin' (binary), 'ihex' (Intel hex), 'elf' (ELF file), 's19' (Motorola s19). 'mem', or 'builder'. The relevant flash sectors will be erased prior to programming if the 'erase' parameter is given. If 'unlock' is provided, then the flash banks are unlocked before erase and program. The flash bank to use is inferred from the address of each image section. Warning: Be careful using the 'erase' flag when the flash is holding data you want to preserve. Portions of the flash outside those described in the image's sections might be erased with no notice. * When a section of the image being written does not fill out all the sectors it uses, the unwritten parts of those sectors are necessarily also erased, because sectors can't be partially erased. * Data stored in sector "holes" between image sections are also affected. For example, "'flash write_image erase ...'" of an image with one byte at the beginning of a flash bank and one byte at the end erases the entire bank - not just the two sectors being written. Also, when flash protection is important, you must re-apply it after it has been removed by the 'unlock' flag. 12.3 Other Flash commands ========================= -- Command: flash erase_check num Check erase state of sectors in flash bank NUM, and display that status. The NUM parameter is a value shown by 'flash banks'. -- Command: flash info num Print info about flash bank NUM The NUM parameter is a value shown by 'flash banks'. This command will first query the hardware, it does not print cached and possibly stale information. -- Command: flash protect num first last ('on'|'off') Enable ('on') or disable ('off') protection of flash sectors in flash bank NUM, starting at sector FIRST and continuing up to and including LAST. Providing a LAST sector of 'last' specifies "to the end of the flash bank". The NUM parameter is a value shown by 'flash banks'. -- Command: flash padded_value num value Sets the default value used for padding any image sections, This should normally match the flash bank erased value. If not specified by this comamnd or the flash driver then it defaults to 0xff. -- Command: program filename [verify] [reset] [exit] [offset] This is a helper script that simplifies using OpenOCD as a standalone programmer. The only required parameter is 'filename', the others are optional. *Note Flash Programming::. 12.4 Flash Driver List ====================== As noted above, the 'flash bank' command requires a driver name, and allows driver-specific options and behaviors. Some drivers also activate driver-specific commands. -- Flash Driver: virtual This is a special driver that maps a previously defined bank to another address. All bank settings will be copied from the master physical bank. The VIRTUAL driver defines one mandatory parameters, * MASTER_BANK The bank that this virtual address refers to. So in the following example addresses 0xbfc00000 and 0x9fc00000 refer to the flash bank defined at address 0x1fc00000. Any cmds executed on the virtual banks are actually performed on the physical banks. flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME flash bank vbank0 virtual 0xbfc00000 0 0 0 $_TARGETNAME $_FLASHNAME flash bank vbank1 virtual 0x9fc00000 0 0 0 $_TARGETNAME $_FLASHNAME 12.4.1 External Flash --------------------- -- Flash Driver: cfi The "Common Flash Interface" (CFI) is the main standard for external NOR flash chips, each of which connects to a specific external chip select on the CPU. Frequently the first such chip is used to boot the system. Your board's 'reset-init' handler might need to configure additional chip selects using other commands (like: 'mww' to configure a bus and its timings), or perhaps configure a GPIO pin that controls the "write protect" pin on the flash chip. The CFI driver can use a target-specific working area to significantly speed up operation. The CFI driver can accept the following optional parameters, in any order: * JEDEC_PROBE ... is used to detect certain non-CFI flash ROMs, like AM29LV010 and similar types. * X16_AS_X8 ... when a 16-bit flash is hooked up to an 8-bit bus. To configure two adjacent banks of 16 MBytes each, both sixteen bits (two bytes) wide on a sixteen bit bus: flash bank $_FLASHNAME cfi 0x00000000 0x01000000 2 2 $_TARGETNAME flash bank $_FLASHNAME cfi 0x01000000 0x01000000 2 2 $_TARGETNAME To configure one bank of 32 MBytes built from two sixteen bit (two byte) wide parts wired in parallel to create a thirty-two bit (four byte) bus with doubled throughput: flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME -- Flash Driver: lpcspifi NXP's LPC43xx and LPC18xx families include a proprietary SPI Flash Interface (SPIFI) peripheral that can drive and provide memory mapped access to external SPI flash devices. The lpcspifi driver initializes this interface and provides program and erase functionality for these serial flash devices. Use of this driver requires a working area of at least 1kB to be configured on the target device; more than this will significantly reduce flash programming times. The setup command only requires the BASE parameter. All other parameters are ignored, and the flash size and layout are configured by the driver. flash bank $_FLASHNAME lpcspifi 0x14000000 0 0 0 $_TARGETNAME -- Flash Driver: stmsmi Some devices form STMicroelectronics (e.g. STR75x MCU family, SPEAr MPU family) include a proprietary "Serial Memory Interface" (SMI) controller able to drive external SPI flash devices. Depending on specific device and board configuration, up to 4 external flash devices can be connected. SMI makes the flash content directly accessible in the CPU address space; each external device is mapped in a memory bank. CPU can directly read data, execute code and boot from SMI banks. Normal OpenOCD commands like 'mdw' can be used to display the flash content. The setup command only requires the BASE parameter in order to identify the memory bank. All other parameters are ignored. Additional information, like flash size, are detected automatically. flash bank $_FLASHNAME stmsmi 0xf8000000 0 0 0 $_TARGETNAME -- Flash Driver: mrvlqspi This driver supports QSPI flash controller of Marvell's Wireless Microcontroller platform. The flash size is autodetected based on the table of known JEDEC IDs hardcoded in the OpenOCD sources. flash bank $_FLASHNAME mrvlqspi 0x0 0 0 0 $_TARGETNAME 0x46010000 12.4.2 Internal Flash (Microcontrollers) ---------------------------------------- -- Flash Driver: aduc702x The ADUC702x analog microcontrollers from Analog Devices include internal flash and use ARM7TDMI cores. The aduc702x flash driver works with models ADUC7019 through ADUC7028. The setup command only requires the TARGET argument since all devices in this family have the same memory layout. flash bank $_FLASHNAME aduc702x 0 0 0 0 $_TARGETNAME -- Flash Driver: at91samd -- Command: at91samd chip-erase Issues a complete Flash erase via the Device Service Unit (DSU). This can be used to erase a chip back to its factory state and does not require the processor to be halted. -- Command: at91samd set-security Secures the Flash via the Set Security Bit (SSB) command. This prevents access to the Flash and can only be undone by using the chip-erase command which erases the Flash contents and turns off the security bit. Warning: at this time, openocd will not be able to communicate with a secured chip and it is therefore not possible to chip-erase it without using another tool. at91samd set-security enable -- Command: at91samd eeprom Shows or sets the EEPROM emulation size configuration, stored in the User Row of the Flash. When setting, the EEPROM size must be specified in bytes and it must be one of the permitted sizes according to the datasheet. Settings are written immediately but only take effect on MCU reset. EEPROM emulation requires additional firmware support and the minumum EEPROM size may not be the same as the minimum that the hardware supports. Set the EEPROM size to 0 in order to disable this feature. at91samd eeprom at91samd eeprom 1024 -- Command: at91samd bootloader Shows or sets the bootloader size configuration, stored in the User Row of the Flash. This is called the BOOTPROT region. When setting, the bootloader size must be specified in bytes and it must be one of the permitted sizes according to the datasheet. Settings are written immediately but only take effect on MCU reset. Setting the bootloader size to 0 disables bootloader protection. at91samd bootloader at91samd bootloader 16384 -- Flash Driver: at91sam3 All members of the AT91SAM3 microcontroller family from Atmel include internal flash and use ARM's Cortex-M3 core. The driver currently (6/22/09) recognizes the AT91SAM3U[1/2/4][C/E] chips. Note that the driver was orginaly developed and tested using the AT91SAM3U4E, using a SAM3U-EK eval board. Support for other chips in the family was cribbed from the data sheet. _Note to future readers/updaters: Please remove this worrysome comment after other chips are confirmed._ The AT91SAM3U4[E/C] (256K) chips have two flash banks; most other chips have one flash bank. In all cases the flash banks are at the following fixed locations: # Flash bank 0 - all chips flash bank $_FLASHNAME at91sam3 0x00080000 0 1 1 $_TARGETNAME # Flash bank 1 - only 256K chips flash bank $_FLASHNAME at91sam3 0x00100000 0 1 1 $_TARGETNAME Internally, the AT91SAM3 flash memory is organized as follows. Unlike the AT91SAM7 chips, these are not used as parameters to the 'flash bank' command: * _N-Banks:_ 256K chips have 2 banks, others have 1 bank. * _Bank Size:_ 128K/64K Per flash bank * _Sectors:_ 16 or 8 per bank * _SectorSize:_ 8K Per Sector * _PageSize:_ 256 bytes per page. Note that OpenOCD operates on 'sector' sizes, not page sizes. The AT91SAM3 driver adds some additional commands: -- Command: at91sam3 gpnvm -- Command: at91sam3 gpnvm clear number -- Command: at91sam3 gpnvm set number -- Command: at91sam3 gpnvm show ['all'|number] With no parameters, 'show' or 'show all', shows the status of all GPNVM bits. With 'show' NUMBER, displays that bit. With 'set' NUMBER or 'clear' NUMBER, modifies that GPNVM bit. -- Command: at91sam3 info This command attempts to display information about the AT91SAM3 chip. _First_ it read the 'CHIPID_CIDR' [address 0x400e0740, see Section 28.2.1, page 505 of the AT91SAM3U 29/may/2009 datasheet, document id: doc6430A] and decodes the values. _Second_ it reads the various clock configuration registers and attempts to display how it believes the chip is configured. By default, the SLOWCLK is assumed to be 32768 Hz, see the command 'at91sam3 slowclk'. -- Command: at91sam3 slowclk [value] This command shows/sets the slow clock frequency used in the 'at91sam3 info' command calculations above. -- Flash Driver: at91sam4 All members of the AT91SAM4 microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same cmd names/syntax as *Note at91sam3::. -- Flash Driver: at91sam4l All members of the AT91SAM4L microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same cmd names/syntax as *Note at91sam3::. The AT91SAM4L driver adds some additional commands: -- Command: at91sam4l smap_reset_deassert This command releases internal reset held by SMAP and prepares reset vector catch in case of reset halt. Command is used internally in event event reset-deassert-post. -- Flash Driver: at91sam7 All members of the AT91SAM7 microcontroller family from Atmel include internal flash and use ARM7TDMI cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME For chips which are not recognized by the controller driver, you must provide additional parameters in the following order: * CHIP_MODEL ... label used with 'flash info' * BANKS * SECTORS_PER_BANK * PAGES_PER_SECTOR * PAGES_SIZE * NUM_NVM_BITS * FREQ_KHZ ... required if an external clock is provided, optional (but recommended) when the oscillator frequency is known It is recommended that you provide zeroes for all of those values except the clock frequency, so that everything except that frequency will be autoconfigured. Knowing the frequency helps ensure correct timings for flash access. The flash controller handles erases automatically on a page (128/256 byte) basis, so explicit erase commands are not necessary for flash programming. However, there is an "EraseAll" command that can erase an entire flash plane (of up to 256KB), and it will be used automatically when you issue 'flash erase_sector' or 'flash erase_address' commands. -- Command: at91sam7 gpnvm bitnum ('set'|'clear') Set or clear a "General Purpose Non-Volatile Memory" (GPNVM) bit for the processor. Each processor has a number of such bits, used for controlling features such as brownout detection (so they are not truly general purpose). Note: This assumes that the first flash bank (number 0) is associated with the appropriate at91sam7 target. -- Flash Driver: avr The AVR 8-bit microcontrollers from Atmel integrate flash memory. _The current implementation is incomplete._ -- Flash Driver: efm32 All members of the EFM32 microcontroller family from Energy Micro include internal flash and use ARM Cortex M3 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME _The current implementation is incomplete. Unprotecting flash pages is not supported._ -- Flash Driver: lpc2000 This is the driver to support internal flash of all members of the LPC11(x)00 and LPC1300 microcontroller families and most members of the LPC800, LPC1500, LPC1700, LPC1800, LPC2000, LPC4000 and LPC54100 microcontroller families from NXP. Note: There are LPC2000 devices which are not supported by the LPC2000 driver: The LPC2888 is supported by the LPC288X driver. The LPC29xx family is supported by the LPC2900 driver. The LPC2000 driver defines two mandatory and one optional parameters, which must appear in the following order: * VARIANT ... required, may be 'lpc2000_v1' (older LPC21xx and LPC22xx) 'lpc2000_v2' (LPC213x, LPC214x, LPC210[123], LPC23xx and LPC24xx) 'lpc1700' (LPC175x and LPC176x and LPC177x/8x) 'lpc4300' - available also as 'lpc1800' alias (LPC18x[2357] and LPC43x[2357]) 'lpc800' (LPC8xx) 'lpc1100' (LPC11(x)xx and LPC13xx) 'lpc1500' (LPC15xx) 'lpc54100' (LPC541xx) 'lpc4000' (LPC40xx) or 'auto' - automatically detects flash variant and size for LPC11(x)00, LPC8xx, LPC13xx, LPC17xx and LPC40xx * CLOCK_KHZ ... the frequency, in kiloHertz, at which the core is running * 'calc_checksum' ... optional (but you probably want to provide this!), telling the driver to calculate a valid checksum for the exception vector table. Note: If you don't provide 'calc_checksum' when you're writing the vector table, the boot ROM will almost certainly ignore your flash image. However, if you do provide it, with most tool chains 'verify_image' will fail. LPC flashes don't require the chip and bus width to be specified. flash bank $_FLASHNAME lpc2000 0x0 0x7d000 0 0 $_TARGETNAME \ lpc2000_v2 14765 calc_checksum -- Command: lpc2000 part_id bank Displays the four byte part identifier associated with the specified flash BANK. -- Flash Driver: lpc288x The LPC2888 microcontroller from NXP needs slightly different flash support from its lpc2000 siblings. The LPC288X driver defines one mandatory parameter, the programming clock rate in Hz. LPC flashes don't require the chip and bus width to be specified. flash bank $_FLASHNAME lpc288x 0 0 0 0 $_TARGETNAME 12000000 -- Flash Driver: lpc2900 This driver supports the LPC29xx ARM968E based microcontroller family from NXP. The predefined parameters BASE, SIZE, CHIP_WIDTH and BUS_WIDTH of the 'flash bank' command are ignored. Flash size and sector layout are auto-configured by the driver. The driver has one additional mandatory parameter: The CPU clock rate (in kHz) at the time the flash operations will take place. Most of the time this will not be the crystal frequency, but a higher PLL frequency. The 'reset-init' event handler in the board script is usually the place where you start the PLL. The driver rejects flashless devices (currently the LPC2930). The EEPROM in LPC2900 devices is not mapped directly into the address space. It must be handled much more like NAND flash memory, and will therefore be handled by a separate 'lpc2900_eeprom' driver (not yet available). Sector protection in terms of the LPC2900 is handled transparently. Every time a sector needs to be erased or programmed, it is automatically unprotected. What is shown as protection status in the 'flash info' command, is actually the LPC2900 _sector security_. This is a mechanism to prevent a sector from ever being erased or programmed again. As this is an irreversible mechanism, it is handled by a special command ('lpc2900 secure_sector'), and not by the standard 'flash protect' command. Example for a 125 MHz clock frequency: flash bank $_FLASHNAME lpc2900 0 0 0 0 $_TARGETNAME 125000 Some 'lpc2900'-specific commands are defined. In the following command list, the BANK parameter is the bank number as obtained by the 'flash banks' command. -- Command: lpc2900 signature bank Calculates a 128-bit hash value, the _signature_, from the whole flash content. This is a hardware feature of the flash block, hence the calculation is very fast. You may use this to verify the content of a programmed device against a known signature. Example: lpc2900 signature 0 signature: 0x5f40cdc8:0xc64e592e:0x10490f89:0x32a0f317 -- Command: lpc2900 read_custom bank filename Reads the 912 bytes of customer information from the flash index sector, and saves it to a file in binary format. Example: lpc2900 read_custom 0 /path_to/customer_info.bin The index sector of the flash is a _write-only_ sector. It cannot be erased! In order to guard against unintentional write access, all following commands need to be preceeded by a successful call to the 'password' command: -- Command: lpc2900 password bank password You need to use this command right before each of the following commands: 'lpc2900 write_custom', 'lpc2900 secure_sector', 'lpc2900 secure_jtag'. The password string is fixed to "I_know_what_I_am_doing". Example: lpc2900 password 0 I_know_what_I_am_doing Potentially dangerous operation allowed in next command! -- Command: lpc2900 write_custom bank filename type Writes the content of the file into the customer info space of the flash index sector. The filetype can be specified with the TYPE field. Possible values for TYPE are: BIN (binary), IHEX (Intel hex format), ELF (ELF binary) or S19 (Motorola S-records). The file must contain a single section, and the contained data length must be exactly 912 bytes. Attention: This cannot be reverted! Be careful! Example: lpc2900 write_custom 0 /path_to/customer_info.bin bin -- Command: lpc2900 secure_sector bank first last Secures the sector range from FIRST to LAST (including) against further program and erase operations. The sector security will be effective after the next power cycle. Attention: This cannot be reverted! Be careful! Secured sectors appear as _protected_ in the 'flash info' command. Example: lpc2900 secure_sector 0 1 1 flash info 0 #0 : lpc2900 at 0x20000000, size 0x000c0000, (...) # 0: 0x00000000 (0x2000 8kB) not protected # 1: 0x00002000 (0x2000 8kB) protected # 2: 0x00004000 (0x2000 8kB) not protected -- Command: lpc2900 secure_jtag bank Irreversibly disable the JTAG port. The new JTAG security setting will be effective after the next power cycle. Attention: This cannot be reverted! Be careful! Examples: lpc2900 secure_jtag 0 -- Flash Driver: ocl This driver is an implementation of the "on chip flash loader" protocol proposed by Pavel Chromy. It is a minimalistic command-response protocol intended to be used over a DCC when communicating with an internal or external flash loader running from RAM. An example implementation for AT91SAM7x is available in 'contrib/loaders/flash/at91sam7x/'. flash bank $_FLASHNAME ocl 0 0 0 0 $_TARGETNAME -- Flash Driver: pic32mx The PIC32MX microcontrollers are based on the MIPS 4K cores, and integrate flash memory. flash bank $_FLASHNAME pix32mx 0x1fc00000 0 0 0 $_TARGETNAME flash bank $_FLASHNAME pix32mx 0x1d000000 0 0 0 $_TARGETNAME Some pic32mx-specific commands are defined: -- Command: pic32mx pgm_word address value bank Programs the specified 32-bit VALUE at the given ADDRESS in the specified chip BANK. -- Command: pic32mx unlock bank Unlock and erase specified chip BANK. This will remove any Code Protection. -- Flash Driver: psoc4 All members of the PSoC 41xx/42xx microcontroller family from Cypress include internal flash and use ARM Cortex M0 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note: Erased internal flash reads as 00. System ROM of PSoC 4 does not implement erase of a flash sector. flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME psoc4-specific commands -- Command: psoc4 flash_autoerase num (on|off) Enables or disables autoerase mode for a flash bank. If flash_autoerase is off, use mass_erase before flash programming. Flash erase command fails if region to erase is not whole flash memory. If flash_autoerase is on, a sector is both erased and programmed in one system ROM call. Flash erase command is ignored. This mode is suitable for gdb load. The NUM parameter is a value shown by 'flash banks'. -- Command: psoc4 mass_erase num Erases the contents of the flash memory, protection and security lock. The NUM parameter is a value shown by 'flash banks'. -- Flash Driver: stellaris All members of the Stellaris LM3Sxxx, LM4x and Tiva C microcontroller families from Texas Instruments include internal flash. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. (1) flash bank $_FLASHNAME stellaris 0 0 0 0 $_TARGETNAME -- Command: stellaris recover Performs the _Recovering a "Locked" Device_ procedure to restore the flash and its associated nonvolatile registers to their factory default values (erased). This is the only way to remove flash protection or re-enable debugging if that capability has been disabled. Note that the final "power cycle the chip" step in this procedure must be performed by hand, since OpenOCD can't do it. Warning: if more than one Stellaris chip is connected, the procedure is applied to all of them. -- Flash Driver: stm32f1x All members of the STM32F0, STM32F1 and STM32F3 microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M0/M3/M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. flash bank $_FLASHNAME stm32f1x 0 0x20000 0 0 $_TARGETNAME If you have a target with dual flash banks then define the second bank as per the following example. flash bank $_FLASHNAME stm32f1x 0x08080000 0 0 0 $_TARGETNAME Some stm32f1x-specific commands (2) are defined: -- Command: stm32f1x lock num Locks the entire stm32 device. The NUM parameter is a value shown by 'flash banks'. -- Command: stm32f1x unlock num Unlocks the entire stm32 device. The NUM parameter is a value shown by 'flash banks'. -- Command: stm32f1x options_read num Read and display the stm32 option bytes written by the 'stm32f1x options_write' command. The NUM parameter is a value shown by 'flash banks'. -- Command: stm32f1x options_write num ('SWWDG'|'HWWDG') ('RSTSTNDBY'|'NORSTSTNDBY') ('RSTSTOP'|'NORSTSTOP') Writes the stm32 option byte with the specified values. The NUM parameter is a value shown by 'flash banks'. -- Flash Driver: stm32f2x All members of the STM32F2 and STM32F4 microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M3/M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. flash bank $_FLASHNAME stm32f2x 0 0x20000 0 0 $_TARGETNAME Some stm32f2x-specific commands are defined: -- Command: stm32f2x lock num Locks the entire stm32 device. The NUM parameter is a value shown by 'flash banks'. -- Command: stm32f2x unlock num Unlocks the entire stm32 device. The NUM parameter is a value shown by 'flash banks'. -- Flash Driver: stm32lx All members of the STM32L microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M3 and Cortex-M0+ cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. If you use 0 as the bank base address, it tells the driver to autodetect the bank location assuming you're configuring the second bank. flash bank $_FLASHNAME stm32lx 0x08000000 0x20000 0 0 $_TARGETNAME Some stm32lx-specific commands are defined: -- Command: stm32lx mass_erase num Mass erases the entire stm32lx device (all flash banks and EEPROM data). This is the only way to unlock a protected flash (unless RDP Level is 2 which can't be unlocked at all). The NUM parameter is a value shown by 'flash banks'. -- Flash Driver: str7x All members of the STR7 microcontroller family from ST Microelectronics include internal flash and use ARM7TDMI cores. The STR7X driver defines one mandatory parameter, VARIANT, which is either 'STR71x', 'STR73x' or 'STR75x'. flash bank $_FLASHNAME str7x \ 0x40000000 0x00040000 0 0 $_TARGETNAME STR71x -- Command: str7x disable_jtag bank Activate the Debug/Readout protection mechanism for the specified flash bank. -- Flash Driver: str9x Most members of the STR9 microcontroller family from ST Microelectronics include internal flash and use ARM966E cores. The str9 needs the flash controller to be configured using the 'str9x flash_config' command prior to Flash programming. flash bank $_FLASHNAME str9x 0x40000000 0x00040000 0 0 $_TARGETNAME str9x flash_config 0 4 2 0 0x80000 -- Command: str9x flash_config num bbsr nbbsr bbadr nbbadr Configures the str9 flash controller. The NUM parameter is a value shown by 'flash banks'. * BBSR - Boot Bank Size register * NBBSR - Non Boot Bank Size register * BBADR - Boot Bank Start Address register * NBBADR - Boot Bank Start Address register -- Flash Driver: str9xpec Only use this driver for locking/unlocking the device or configuring the option bytes. Use the standard str9 driver for programming. Before using the flash commands the turbo mode must be enabled using the 'str9xpec enable_turbo' command. Here is some background info to help you better understand how this driver works. OpenOCD has two flash drivers for the str9: 1. Standard driver 'str9x' programmed via the str9 core. Normally used for flash programming as it is faster than the 'str9xpec' driver. 2. Direct programming 'str9xpec' using the flash controller. This is an ISC compilant (IEEE 1532) tap connected in series with the str9 core. The str9 core does not need to be running to program using this flash driver. Typical use for this driver is locking/unlocking the target and programming the option bytes. Before we run any commands using the 'str9xpec' driver we must first disable the str9 core. This example assumes the 'str9xpec' driver has been configured for flash bank 0. # assert srst, we do not want core running # while accessing str9xpec flash driver jtag_reset 0 1 # turn off target polling poll off # disable str9 core str9xpec enable_turbo 0 # read option bytes str9xpec options_read 0 # re-enable str9 core str9xpec disable_turbo 0 poll on reset halt The above example will read the str9 option bytes. When performing a unlock remember that you will not be able to halt the str9 - it has been locked. Halting the core is not required for the 'str9xpec' driver as mentioned above, just issue the commands above manually or from a telnet prompt. Several str9xpec-specific commands are defined: -- Command: str9xpec disable_turbo num Restore the str9 into JTAG chain. -- Command: str9xpec enable_turbo num Enable turbo mode, will simply remove the str9 from the chain and talk directly to the embedded flash controller. -- Command: str9xpec lock num Lock str9 device. The str9 will only respond to an unlock command that will erase the device. -- Command: str9xpec part_id num Prints the part identifier for bank NUM. -- Command: str9xpec options_cmap num ('bank0'|'bank1') Configure str9 boot bank. -- Command: str9xpec options_lvdsel num ('vdd'|'vdd_vddq') Configure str9 lvd source. -- Command: str9xpec options_lvdthd num ('2.4v'|'2.7v') Configure str9 lvd threshold. -- Command: str9xpec options_lvdwarn bank ('vdd'|'vdd_vddq') Configure str9 lvd reset warning source. -- Command: str9xpec options_read num Read str9 option bytes. -- Command: str9xpec options_write num Write str9 option bytes. -- Command: str9xpec unlock num unlock str9 device. -- Flash Driver: tms470 Most members of the TMS470 microcontroller family from Texas Instruments include internal flash and use ARM7TDMI cores. This driver doesn't require the chip and bus width to be specified. Some tms470-specific commands are defined: -- Command: tms470 flash_keyset key0 key1 key2 key3 Saves programming keys in a register, to enable flash erase and write commands. -- Command: tms470 osc_mhz clock_mhz Reports the clock speed, which is used to calculate timings. -- Command: tms470 plldis (0|1) Disables (1) or enables (0) use of the PLL to speed up the flash clock. -- Flash Driver: fm3 All members of the FM3 microcontroller family from Fujitsu include internal flash and use ARM Cortex M3 cores. The FM3 driver uses the TARGET parameter to select the correct bank config, it can currently be one of the following: 'mb9bfxx1.cpu', 'mb9bfxx2.cpu', 'mb9bfxx3.cpu', 'mb9bfxx4.cpu', 'mb9bfxx5.cpu' or 'mb9bfxx6.cpu'. flash bank $_FLASHNAME fm3 0 0 0 0 $_TARGETNAME -- Flash Driver: sim3x All members of the SiM3 microcontroller family from Silicon Laboratories include internal flash and use ARM Cortex M3 cores. It supports both JTAG and SWD interface. The SIM3X driver tries to probe the device to auto detect the MCU. If this failes, it will use the SIZE parameter as the size of flash bank. flash bank $_FLASHNAME sim3x 0 $_CPUROMSIZE 0 0 $_TARGETNAME There are 2 commands defined in the SIM3X driver: -- Command: sim3x mass_erase Erases the complete flash. This is used to unlock the flash. And this command is only possible when using the SWD interface. -- Command: sim3x lock Lock the flash. To unlock use the 'sim3x mass_erase' command. -- Flash Driver: nrf51 All members of the nRF51 microcontroller families from Nordic Semiconductor include internal flash and use ARM Cortex-M0 core. flash bank $_FLASHNAME nrf51 0 0x00000000 0 0 $_TARGETNAME Some nrf51-specific commands are defined: -- Command: nrf51 mass_erase Erases the contents of the code memory and user information configuration registers as well. It must be noted that this command works only for chips that do not have factory pre-programmed region 0 code. -- Flash Driver: mdr This drivers handles the integrated NOR flash on Milandr Cortex-M based controllers. A known limitation is that the Info memory can't be read or verified as it's not memory mapped. flash bank mdr \ 0 0 TYPE PAGE_COUNT SEC_COUNT * TYPE - 0 for main memory, 1 for info memory * PAGE_COUNT - total number of pages * SEC_COUNT - number of sector per page count Example usage: if { [info exists IMEMORY] && [string equal $IMEMORY true] } { flash bank ${_CHIPNAME}_info.flash mdr 0x00000000 0x01000 \ 0 0 $_TARGETNAME 1 1 4 } else { flash bank $_CHIPNAME.flash mdr 0x00000000 0x20000 \ 0 0 $_TARGETNAME 0 32 4 } 12.5 NAND Flash Commands ======================== Compared to NOR or SPI flash, NAND devices are inexpensive and high density. Today's NAND chips, and multi-chip modules, commonly hold multiple GigaBytes of data. NAND chips consist of a number of "erase blocks" of a given size (such as 128 KBytes), each of which is divided into a number of pages (of perhaps 512 or 2048 bytes each). Each page of a NAND flash has an "out of band" (OOB) area to hold Error Correcting Code (ECC) and other metadata, usually 16 bytes of OOB for every 512 bytes of page data. One key characteristic of NAND flash is that its error rate is higher than that of NOR flash. In normal operation, that ECC is used to correct and detect errors. However, NAND blocks can also wear out and become unusable; those blocks are then marked "bad". NAND chips are even shipped from the manufacturer with a few bad blocks. The highest density chips use a technology (MLC) that wears out more quickly, so ECC support is increasingly important as a way to detect blocks that have begun to fail, and help to preserve data integrity with techniques such as wear leveling. Software is used to manage the ECC. Some controllers don't support ECC directly; in those cases, software ECC is used. Other controllers speed up the ECC calculations with hardware. Single-bit error correction hardware is routine. Controllers geared for newer MLC chips may correct 4 or more errors for every 512 bytes of data. You will need to make sure that any data you write using OpenOCD includes the apppropriate kind of ECC. For example, that may mean passing the 'oob_softecc' flag when writing NAND data, or ensuring that the correct hardware ECC mode is used. The basic steps for using NAND devices include: 1. Declare via the command 'nand device' Do this in a board-specific configuration file, passing parameters as needed by the controller. 2. Configure each device using 'nand probe'. Do this only after the associated target is set up, such as in its reset-init script or in procures defined to access that device. 3. Operate on the flash via 'nand subcommand' Often commands to manipulate the flash are typed by a human, or run via a script in some automated way. Common task include writing a boot loader, operating system, or other data needed to initialize or de-brick a board. NOTE: At the time this text was written, the largest NAND flash fully supported by OpenOCD is 2 GiBytes (16 GiBits). This is because the variables used to hold offsets and lengths are only 32 bits wide. (Larger chips may work in some cases, unless an offset or length is larger than 0xffffffff, the largest 32-bit unsigned integer.) Some larger devices will work, since they are actually multi-chip modules with two smaller chips and individual chipselect lines. 12.5.1 NAND Configuration Commands ---------------------------------- NAND chips must be declared in configuration scripts, plus some additional configuration that's done after OpenOCD has initialized. -- Config Command: nand device name driver target [configparams...] Declares a NAND device, which can be read and written to after it has been configured through 'nand probe'. In OpenOCD, devices are single chips; this is unlike some operating systems, which may manage multiple chips as if they were a single (larger) device. In some cases, configuring a device will activate extra commands; see the controller-specific documentation. NOTE: This command is not available after OpenOCD initialization has completed. Use it in board specific configuration files, not interactively. * NAME ... may be used to reference the NAND bank in most other NAND commands. A number is also available. * DRIVER ... identifies the NAND controller driver associated with the NAND device being declared. *Note NAND Driver List: nanddriverlist. * TARGET ... names the target used when issuing commands to the NAND controller. * CONFIGPARAMS ... controllers may support, or require, additional parameters. See the controller-specific documentation for more information. -- Command: nand list Prints a summary of each device declared using 'nand device', numbered from zero. Note that un-probed devices show no details. > nand list #0: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8, blocksize: 131072, blocks: 8192 #1: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8, blocksize: 131072, blocks: 8192 > -- Command: nand probe num Probes the specified device to determine key characteristics like its page and block sizes, and how many blocks it has. The NUM parameter is the value shown by 'nand list'. You must (successfully) probe a device before you can use it with most other NAND commands. 12.5.2 Erasing, Reading, Writing to NAND Flash ---------------------------------------------- -- Command: nand dump num filename offset length [oob_option] Reads binary data from the NAND device and writes it to the file, starting at the specified offset. The NUM parameter is the value shown by 'nand list'. Use a complete path name for FILENAME, so you don't depend on the directory used to start the OpenOCD server. The OFFSET and LENGTH must be exact multiples of the device's page size. They describe a data region; the OOB data associated with each such page may also be accessed. NOTE: At the time this text was written, no error correction was done on the data that's read, unless raw access was disabled and the underlying NAND controller driver had a 'read_page' method which handled that error correction. By default, only page data is saved to the specified file. Use an OOB_OPTION parameter to save OOB data: * no oob_* parameter Output file holds only page data; OOB is discarded. * 'oob_raw' Output file interleaves page data and OOB data; the file will be longer than "length" by the size of the spare areas associated with each data page. Note that this kind of "raw" access is different from what's implied by 'nand raw_access', which just controls whether a hardware-aware access method is used. * 'oob_only' Output file has only raw OOB data, and will be smaller than "length" since it will contain only the spare areas associated with each data page. -- Command: nand erase num [offset length] Erases blocks on the specified NAND device, starting at the specified OFFSET and continuing for LENGTH bytes. Both of those values must be exact multiples of the device's block size, and the region they specify must fit entirely in the chip. If those parameters are not specified, the whole NAND chip will be erased. The NUM parameter is the value shown by 'nand list'. NOTE: This command will try to erase bad blocks, when told to do so, which will probably invalidate the manufacturer's bad block marker. For the remainder of the current server session, 'nand info' will still report that the block "is" bad. -- Command: nand write num filename offset [option...] Writes binary data from the file into the specified NAND device, starting at the specified offset. Those pages should already have been erased; you can't change zero bits to one bits. The NUM parameter is the value shown by 'nand list'. Use a complete path name for FILENAME, so you don't depend on the directory used to start the OpenOCD server. The OFFSET must be an exact multiple of the device's page size. All data in the file will be written, assuming it doesn't run past the end of the device. Only full pages are written, and any extra space in the last page will be filled with 0xff bytes. (That includes OOB data, if that's being written.) NOTE: At the time this text was written, bad blocks are ignored. That is, this routine will not skip bad blocks, but will instead try to write them. This can cause problems. Provide at most one OPTION parameter. With some NAND drivers, the meanings of these parameters may change if 'nand raw_access' was used to disable hardware ECC. * no oob_* parameter File has only page data, which is written. If raw acccess is in use, the OOB area will not be written. Otherwise, if the underlying NAND controller driver has a 'write_page' routine, that routine may write the OOB with hardware-computed ECC data. * 'oob_only' File has only raw OOB data, which is written to the OOB area. Each page's data area stays untouched. This can be a dangerous option, since it can invalidate the ECC data. You may need to force raw access to use this mode. * 'oob_raw' File interleaves data and OOB data, both of which are written If raw access is enabled, the data is written first, then the un-altered OOB. Otherwise, if the underlying NAND controller driver has a 'write_page' routine, that routine may modify the OOB before it's written, to include hardware-computed ECC data. * 'oob_softecc' File has only page data, which is written. The OOB area is filled with 0xff, except for a standard 1-bit software ECC code stored in conventional locations. You might need to force raw access to use this mode, to prevent the underlying driver from applying hardware ECC. * 'oob_softecc_kw' File has only page data, which is written. The OOB area is filled with 0xff, except for a 4-bit software ECC specific to the boot ROM in Marvell Kirkwood SoCs. You might need to force raw access to use this mode, to prevent the underlying driver from applying hardware ECC. -- Command: nand verify num filename offset [option...] Verify the binary data in the file has been programmed to the specified NAND device, starting at the specified offset. The NUM parameter is the value shown by 'nand list'. Use a complete path name for FILENAME, so you don't depend on the directory used to start the OpenOCD server. The OFFSET must be an exact multiple of the device's page size. All data in the file will be read and compared to the contents of the flash, assuming it doesn't run past the end of the device. As with 'nand write', only full pages are verified, so any extra space in the last page will be filled with 0xff bytes. The same OPTIONS accepted by 'nand write', and the file will be processed similarly to produce the buffers that can be compared against the contents produced from 'nand dump'. NOTE: This will not work when the underlying NAND controller driver's 'write_page' routine must update the OOB with a hardward-computed ECC before the data is written. This limitation may be removed in a future release. 12.5.3 Other NAND commands -------------------------- -- Command: nand check_bad_blocks num [offset length] Checks for manufacturer bad block markers on the specified NAND device. If no parameters are provided, checks the whole device; otherwise, starts at the specified OFFSET and continues for LENGTH bytes. Both of those values must be exact multiples of the device's block size, and the region they specify must fit entirely in the chip. The NUM parameter is the value shown by 'nand list'. NOTE: Before using this command you should force raw access with 'nand raw_access enable' to ensure that the underlying driver will not try to apply hardware ECC. -- Command: nand info num The NUM parameter is the value shown by 'nand list'. This prints the one-line summary from "nand list", plus for devices which have been probed this also prints any known status for each block. -- Command: nand raw_access num ('enable'|'disable') Sets or clears an flag affecting how page I/O is done. The NUM parameter is the value shown by 'nand list'. This flag is cleared (disabled) by default, but changing that value won't affect all NAND devices. The key factor is whether the underlying driver provides 'read_page' or 'write_page' methods. If it doesn't provide those methods, the setting of this flag is irrelevant; all access is effectively "raw". When those methods exist, they are normally used when reading data ('nand dump' or reading bad block markers) or writing it ('nand write'). However, enabling raw access (setting the flag) prevents use of those methods, bypassing hardware ECC logic. This can be a dangerous option, since writing blocks with the wrong ECC data can cause them to be marked as bad. 12.5.4 NAND Driver List ----------------------- As noted above, the 'nand device' command allows driver-specific options and behaviors. Some controllers also activate controller-specific commands. -- NAND Driver: at91sam9 This driver handles the NAND controllers found on AT91SAM9 family chips from Atmel. It takes two extra parameters: address of the NAND chip; address of the ECC controller. nand device $NANDFLASH at91sam9 $CHIPNAME 0x40000000 0xfffffe800 AT91SAM9 chips support single-bit ECC hardware. The 'write_page' and 'read_page' methods are used to utilize the ECC hardware unless they are disabled by using the 'nand raw_access' command. There are four additional commands that are needed to fully configure the AT91SAM9 NAND controller. Two are optional; most boards use the same wiring for ALE/CLE: -- Command: at91sam9 cle num addr_line Configure the address line used for latching commands. The NUM parameter is the value shown by 'nand list'. -- Command: at91sam9 ale num addr_line Configure the address line used for latching addresses. The NUM parameter is the value shown by 'nand list'. For the next two commands, it is assumed that the pins have already been properly configured for input or output. -- Command: at91sam9 rdy_busy num pio_base_addr pin Configure the RDY/nBUSY input from the NAND device. The NUM parameter is the value shown by 'nand list'. PIO_BASE_ADDR is the base address of the PIO controller and PIN is the pin number. -- Command: at91sam9 ce num pio_base_addr pin Configure the chip enable input to the NAND device. The NUM parameter is the value shown by 'nand list'. PIO_BASE_ADDR is the base address of the PIO controller and PIN is the pin number. -- NAND Driver: davinci This driver handles the NAND controllers found on DaVinci family chips from Texas Instruments. It takes three extra parameters: address of the NAND chip; hardware ECC mode to use ('hwecc1', 'hwecc4', 'hwecc4_infix'); address of the AEMIF controller on this processor. nand device davinci dm355.arm 0x02000000 hwecc4 0x01e10000 All DaVinci processors support the single-bit ECC hardware, and newer ones also support the four-bit ECC hardware. The 'write_page' and 'read_page' methods are used to implement those ECC modes, unless they are disabled using the 'nand raw_access' command. -- NAND Driver: lpc3180 These controllers require an extra 'nand device' parameter: the clock rate used by the controller. -- Command: lpc3180 select num [mlc|slc] Configures use of the MLC or SLC controller mode. MLC implies use of hardware ECC. The NUM parameter is the value shown by 'nand list'. At this writing, this driver includes 'write_page' and 'read_page' methods. Using 'nand raw_access' to disable those methods will prevent use of hardware ECC in the MLC controller mode, but won't change SLC behavior. -- NAND Driver: mx3 This driver handles the NAND controller in i.MX31. The mxc driver should work for this chip aswell. -- NAND Driver: mxc This driver handles the NAND controller found in Freescale i.MX chips. It has support for v1 (i.MX27 and i.MX31) and v2 (i.MX35). The driver takes 3 extra arguments, chip ('mx27', 'mx31', 'mx35'), ecc ('noecc', 'hwecc') and optionally if bad block information should be swapped between main area and spare area ('biswap'), defaults to off. nand device mx35.nand mxc imx35.cpu mx35 hwecc biswap -- Command: mxc biswap bank_num [enable|disable] Turns on/off bad block information swaping from main area, without parameter query status. -- NAND Driver: orion These controllers require an extra 'nand device' parameter: the address of the controller. nand device orion 0xd8000000 These controllers don't define any specialized commands. At this writing, their drivers don't include 'write_page' or 'read_page' methods, so 'nand raw_access' won't change any behavior. -- NAND Driver: s3c2410 -- NAND Driver: s3c2412 -- NAND Driver: s3c2440 -- NAND Driver: s3c2443 -- NAND Driver: s3c6400 These S3C family controllers don't have any special 'nand device' options, and don't define any specialized commands. At this writing, their drivers don't include 'write_page' or 'read_page' methods, so 'nand raw_access' won't change any behavior. 12.6 mFlash =========== 12.6.1 mFlash Configuration --------------------------- -- Config Command: mflash bank soc base RST_pin target Configures a mflash for SOC host bank at address BASE. The pin number format depends on the host GPIO naming convention. Currently, the mflash driver supports s3c2440 and pxa270. Example for s3c2440 mflash where RST PIN is GPIO B1: mflash bank $_FLASHNAME s3c2440 0x10000000 1b 0 Example for pxa270 mflash where RST PIN is GPIO 43: mflash bank $_FLASHNAME pxa270 0x08000000 43 0 12.6.2 mFlash commands ---------------------- -- Command: mflash config pll frequency Configure mflash PLL. The FREQUENCY is the mflash input frequency, in Hz. Issuing this command will erase mflash's whole internal nand and write new pll. After this command, mflash needs power-on-reset for normal operation. If pll was newly configured, storage and boot(optional) info also need to be update. -- Command: mflash config boot Configure bootable option. If bootable option is set, mflash offer the first 8 sectors (4kB) for boot. -- Command: mflash config storage Configure storage information. For the normal storage operation, this information must be written. -- Command: mflash dump num filename offset size Dump SIZE bytes, starting at OFFSET bytes from the beginning of the bank NUM, to the file named FILENAME. -- Command: mflash probe Probe mflash. -- Command: mflash write num filename offset Write the binary file FILENAME to mflash bank NUM, starting at OFFSET bytes from the beginning of the bank. ---------- Footnotes ---------- (1) Currently there is a 'stellaris mass_erase' command. That seems pointless since the same effect can be had using the standard 'flash erase_address' command. (2) Currently there is a 'stm32f1x mass_erase' command. That seems pointless since the same effect can be had using the standard 'flash erase_address' command.  File: openocd.info, Node: Flash Programming, Next: PLD/FPGA Commands, Prev: Flash Commands, Up: Top 13 Flash Programming ******************** OpenOCD implements numerous ways to program the target flash, whether internal or external. Programming can be acheived by either using GDB *note Programming using GDB: programmingusinggdb, or using the cmds given in *note Flash Programming Commands: flashprogrammingcommands. To simplify using the flash cmds directly a jimtcl script is available that handles the programming and verify stage. OpenOCD will program/verify/reset the target and optionally shutdown. The script is executed as follows and by default the following actions will be peformed. 1. 'init' is executed. 2. 'reset init' is called to reset and halt the target, any 'reset init' scripts are executed. 3. 'flash write_image' is called to erase and write any flash using the filename given. 4. 'verify_image' is called if 'verify' parameter is given. 5. 'reset run' is called if 'reset' parameter is given. 6. OpenOCD is shutdown if 'exit' parameter is given. An example of usage is given below. *Note program::. # program and verify using elf/hex/s19. verify and reset # are optional parameters openocd -f board/stm32f3discovery.cfg \ -c "program filename.elf verify reset exit" # binary files need the flash address passing openocd -f board/stm32f3discovery.cfg \ -c "program filename.bin exit 0x08000000"  File: openocd.info, Node: PLD/FPGA Commands, Next: General Commands, Prev: Flash Programming, Up: Top 14 PLD/FPGA Commands ******************** Programmable Logic Devices (PLDs) and the more flexible Field Programmable Gate Arrays (FPGAs) are both types of programmable hardware. OpenOCD can support programming them. Although PLDs are generally restrictive (cells are less functional, and there are no special purpose cells for memory or computational tasks), they share the same OpenOCD infrastructure. Accordingly, both are called PLDs here. 14.1 PLD/FPGA Configuration and Commands ======================================== As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND), OpenOCD maintains a list of PLDs available for use in various commands. Also, each such PLD requires a driver. They are referenced by the number shown by the 'pld devices' command, and new PLDs are defined by 'pld device driver_name'. -- Config Command: pld device driver_name tap_name [driver_options] Defines a new PLD device, supported by driver DRIVER_NAME, using the TAP named TAP_NAME. The driver may make use of any DRIVER_OPTIONS to configure its behavior. -- Command: pld devices Lists the PLDs and their numbers. -- Command: pld load num filename Loads the file 'filename' into the PLD identified by NUM. The file format must be inferred by the driver. 14.2 PLD/FPGA Drivers, Options, and Commands ============================================ Drivers may support PLD-specific options to the 'pld device' definition command, and may also define commands usable only with that particular type of PLD. -- FPGA Driver: virtex2 Virtex-II is a family of FPGAs sold by Xilinx. It supports the IEEE 1532 standard for In-System Configuration (ISC). No driver-specific PLD definition options are used, and one driver-specific command is defined. -- Command: virtex2 read_stat num Reads and displays the Virtex-II status register (STAT) for FPGA NUM.  File: openocd.info, Node: General Commands, Next: Architecture and Core Commands, Prev: PLD/FPGA Commands, Up: Top 15 General Commands ******************* The commands documented in this chapter here are common commands that you, as a human, may want to type and see the output of. Configuration type commands are documented elsewhere. Intent: * Source Of Commands OpenOCD commands can occur in a configuration script (discussed elsewhere) or typed manually by a human or supplied programatically, or via one of several TCP/IP Ports. * From the human A human should interact with the telnet interface (default port: 4444) or via GDB (default port 3333). To issue commands from within a GDB session, use the 'monitor' command, e.g. use 'monitor poll' to issue the 'poll' command. All output is relayed through the GDB session. * Machine Interface The Tcl interface's intent is to be a machine interface. The default Tcl port is 5555. 15.1 Daemon Commands ==================== -- Command: exit Exits the current telnet session. -- Command: help [string] With no parameters, prints help text for all commands. Otherwise, prints each helptext containing STRING. Not every command provides helptext. Configuration commands, and commands valid at any time, are explicitly noted in parenthesis. In most cases, no such restriction is listed; this indicates commands which are only available after the configuration stage has completed. -- Command: sleep msec ['busy'] Wait for at least MSEC milliseconds before resuming. If 'busy' is passed, busy-wait instead of sleeping. (This option is strongly discouraged.) Useful in connection with script files ('script' command and 'target_name' configuration). -- Command: shutdown ['error'] Close the OpenOCD daemon, disconnecting all clients (GDB, telnet, other). If option 'error' is used, OpenOCD will return a non-zero exit code to the parent process. -- Command: debug_level [n] Display debug level. If N (from 0..3) is provided, then set it to that level. This affects the kind of messages sent to the server log. Level 0 is error messages only; level 1 adds warnings; level 2 adds informational messages; and level 3 adds debugging messages. The default is level 2, but that can be overridden on the command line along with the location of that log file (which is normally the server's standard output). *Note Running::. -- Command: echo [-n] message Logs a message at "user" priority. Output MESSAGE to stdout. Option "-n" suppresses trailing newline. echo "Downloading kernel -- please wait" -- Command: log_output [filename] Redirect logging to FILENAME; the initial log output channel is stderr. -- Command: add_script_search_dir [directory] Add DIRECTORY to the file/script search path. 15.2 Target State handling ========================== In this section "target" refers to a CPU configured as shown earlier (*note CPU Configuration::). These commands, like many, implicitly refer to a current target which is used to perform the various operations. The current target may be changed by using 'targets' command with the name of the target which should become current. -- Command: reg [(number|name) [(value|'force')]] Access a single register by NUMBER or by its NAME. The target must generally be halted before access to CPU core registers is allowed. Depending on the hardware, some other registers may be accessible while the target is running. _With no arguments_: list all available registers for the current target, showing number, name, size, value, and cache status. For valid entries, a value is shown; valid entries which are also dirty (and will be written back later) are flagged as such. _With number/name_: display that register's value. Use FORCE argument to read directly from the target, bypassing any internal cache. _With both number/name and value_: set register's value. Writes may be held in a writeback cache internal to OpenOCD, so that setting the value marks the register as dirty instead of immediately flushing that value. Resuming CPU execution (including by single stepping) or otherwise activating the relevant module will flush such values. Cores may have surprisingly many registers in their Debug and trace infrastructure: > reg ===== ARM registers (0) r0 (/32): 0x0000D3C2 (dirty) (1) r1 (/32): 0xFD61F31C (2) r2 (/32) ... (164) ETM_contextid_comparator_mask (/32) > -- Command: halt [ms] -- Command: wait_halt [ms] The 'halt' command first sends a halt request to the target, which 'wait_halt' doesn't. Otherwise these behave the same: wait up to MS milliseconds, or 5 seconds if there is no parameter, for the target to halt (and enter debug mode). Using 0 as the MS parameter prevents OpenOCD from waiting. Warning: On ARM cores, software using the _wait for interrupt_ operation often blocks the JTAG access needed by a 'halt' command. This is because that operation also puts the core into a low power mode by gating the core clock; but the core clock is needed to detect JTAG clock transitions. One partial workaround uses adaptive clocking: when the core is interrupted the operation completes, then JTAG clocks are accepted at least until the interrupt handler completes. However, this workaround is often unusable since the processor, board, and JTAG adapter must all support adaptive JTAG clocking. Also, it can't work until an interrupt is issued. A more complete workaround is to not use that operation while you work with a JTAG debugger. Tasking environments generaly have idle loops where the body is the _wait for interrupt_ operation. (On older cores, it is a coprocessor action; newer cores have a 'wfi' instruction.) Such loops can just remove that operation, at the cost of higher power consumption (because the CPU is needlessly clocked). -- Command: resume [address] Resume the target at its current code position, or the optional ADDRESS if it is provided. OpenOCD will wait 5 seconds for the target to resume. -- Command: step [address] Single-step the target at its current code position, or the optional ADDRESS if it is provided. -- Command: reset -- Command: reset run -- Command: reset halt -- Command: reset init Perform as hard a reset as possible, using SRST if possible. _All defined targets will be reset, and target events will fire during the reset sequence._ The optional parameter specifies what should happen after the reset. If there is no parameter, a 'reset run' is executed. The other options will not work on all systems. *Note Reset Configuration::. - run Let the target run - halt Immediately halt the target - init Immediately halt the target, and execute the reset-init script -- Command: soft_reset_halt Requesting target halt and executing a soft reset. This is often used when a target cannot be reset and halted. The target, after reset is released begins to execute code. OpenOCD attempts to stop the CPU and then sets the program counter back to the reset vector. Unfortunately the code that was executed may have left the hardware in an unknown state. 15.3 I/O Utilities ================== These commands are available when OpenOCD is built with '--enable-ioutil'. They are mainly useful on embedded targets, notably the ZY1000. Hosts with operating systems have complementary tools. _Note:_ there are several more such commands. -- Command: append_file filename [string]* Appends the STRING parameters to the text file 'filename'. Each string except the last one is followed by one space. The last string is followed by a newline. -- Command: cat filename Reads and displays the text file 'filename'. -- Command: cp src_filename dest_filename Copies contents from the file 'src_filename' into 'dest_filename'. -- Command: ip _No description provided._ -- Command: ls _No description provided._ -- Command: mac _No description provided._ -- Command: meminfo Display available RAM memory on OpenOCD host. Used in OpenOCD regression testing scripts. -- Command: peek _No description provided._ -- Command: poke _No description provided._ -- Command: rm filename Unlinks the file 'filename'. -- Command: trunc filename Removes all data in the file 'filename'. 15.4 Memory access commands =========================== These commands allow accesses of a specific size to the memory system. Often these are used to configure the current target in some special way. For example - one may need to write certain values to the SDRAM controller to enable SDRAM. 1. Use the 'targets' (plural) command to change the current target. 2. In system level scripts these commands are deprecated. Please use their TARGET object siblings to avoid making assumptions about what TAP is the current target, or about MMU configuration. -- Command: mdw [phys] addr [count] -- Command: mdh [phys] addr [count] -- Command: mdb [phys] addr [count] Display contents of address ADDR, as 32-bit words ('mdw'), 16-bit halfwords ('mdh'), or 8-bit bytes ('mdb'). When the current target has an MMU which is present and active, ADDR is interpreted as a virtual address. Otherwise, or if the optional PHYS flag is specified, ADDR is interpreted as a physical address. If COUNT is specified, displays that many units. (If you want to manipulate the data instead of displaying it, see the 'mem2array' primitives.) -- Command: mww [phys] addr word -- Command: mwh [phys] addr halfword -- Command: mwb [phys] addr byte Writes the specified WORD (32 bits), HALFWORD (16 bits), or BYTE (8-bit) value, at the specified address ADDR. When the current target has an MMU which is present and active, ADDR is interpreted as a virtual address. Otherwise, or if the optional PHYS flag is specified, ADDR is interpreted as a physical address. 15.5 Image loading commands =========================== -- Command: dump_image filename address size Dump SIZE bytes of target memory starting at ADDRESS to the binary file named FILENAME. -- Command: fast_load Loads an image stored in memory by 'fast_load_image' to the current target. Must be preceeded by fast_load_image. -- Command: fast_load_image filename address ['bin'|'ihex'|'elf'|'s19'] Normally you should be using 'load_image' or GDB load. However, for testing purposes or when I/O overhead is significant(OpenOCD running on an embedded host), storing the image in memory and uploading the image to the target can be a way to upload e.g. multiple debug sessions when the binary does not change. Arguments are the same as 'load_image', but the image is stored in OpenOCD host memory, i.e. does not affect target. This approach is also useful when profiling target programming performance as I/O and target programming can easily be profiled separately. -- Command: load_image filename address [['bin'|'ihex'|'elf'|'s19'] 'min_addr' 'max_length'] Load image from file FILENAME to target memory offset by ADDRESS from its load address. The file format may optionally be specified ('bin', 'ihex', 'elf', or 's19'). In addition the following arguments may be specifed: MIN_ADDR - ignore data below MIN_ADDR (this is w.r.t. to the target's load address + ADDRESS) MAX_LENGTH - maximum number of bytes to load. proc load_image_bin {fname foffset address length } { # Load data from fname filename at foffset offset to # target at address. Load at most length bytes. load_image $fname [expr $address - $foffset] bin \ $address $length } -- Command: test_image filename [address ['bin'|'ihex'|'elf']] Displays image section sizes and addresses as if FILENAME were loaded into target memory starting at ADDRESS (defaults to zero). The file format may optionally be specified ('bin', 'ihex', or 'elf') -- Command: verify_image filename address ['bin'|'ihex'|'elf'] Verify FILENAME against target memory starting at ADDRESS. The file format may optionally be specified ('bin', 'ihex', or 'elf') This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. 15.6 Breakpoint and Watchpoint commands ======================================= CPUs often make debug modules accessible through JTAG, with hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. -- Command: bp [address len ['hw']] With no parameters, lists all active breakpoints. Else sets a breakpoint on code execution starting at ADDRESS for LENGTH bytes. This is a software breakpoint, unless 'hw' is specified in which case it will be a hardware breakpoint. (*Note arm9 vector_catch: arm9vectorcatch, or *note xscale vector_catch: xscalevectorcatch, for similar mechanisms that do not consume hardware breakpoints.) -- Command: rbp address Remove the breakpoint at ADDRESS. -- Command: rwp address Remove data watchpoint on ADDRESS -- Command: wp [address len [('r'|'w'|'a') [value [mask]]]] With no parameters, lists all active watchpoints. Else sets a data watchpoint on data from ADDRESS for LENGTH bytes. The watch point is an "access" watchpoint unless the 'r' or 'w' parameter is provided, defining it as respectively a read or write watchpoint. If a VALUE is provided, that value is used when determining if the watchpoint should trigger. The value may be first be masked using MASK to mark "don't care" fields. 15.7 Misc Commands ================== -- Command: profile seconds filename [start end] Profiling samples the CPU's program counter as quickly as possible, which is useful for non-intrusive stochastic profiling. Saves up to 10000 samples in 'filename' using "gmon.out" format. Optional 'start' and 'end' parameters allow to limit the address range. -- Command: version Displays a string identifying the version of this OpenOCD server. -- Command: virt2phys virtual_address Requests the current target to map the specified VIRTUAL_ADDRESS to its corresponding physical address, and displays the result.  File: openocd.info, Node: Architecture and Core Commands, Next: JTAG Commands, Prev: General Commands, Up: Top 16 Architecture and Core Commands ********************************* Most CPUs have specialized JTAG operations to support debugging. OpenOCD packages most such operations in its standard command framework. Some of those operations don't fit well in that framework, so they are exposed here as architecture or implementation (core) specific commands. 16.1 ARM Hardware Tracing ========================= CPUs based on ARM cores may include standard tracing interfaces, based on an "Embedded Trace Module" (ETM) which sends voluminous address and data bus trace records to a "Trace Port". * Development-oriented boards will sometimes provide a high speed trace connector for collecting that data, when the particular CPU supports such an interface. (The standard connector is a 38-pin Mictor, with both JTAG and trace port support.) Those trace connectors are supported by higher end JTAG adapters and some logic analyzer modules; frequently those modules can buffer several megabytes of trace data. Configuring an ETM coupled to such an external trace port belongs in the board-specific configuration file. * If the CPU doesn't provide an external interface, it probably has an "Embedded Trace Buffer" (ETB) on the chip, which is a dedicated SRAM. 4KBytes is one common ETB size. Configuring an ETM coupled only to an ETB belongs in the CPU-specific (target) configuration file, since it works the same on all boards. ETM support in OpenOCD doesn't seem to be widely used yet. Issues: ETM support may be buggy, and at least some 'etm config' parameters should be detected by asking the ETM for them. ETM trigger events could also implement a kind of complex hardware breakpoint, much more powerful than the simple watchpoint hardware exported by EmbeddedICE modules. _Such breakpoints can be triggered even when using the dummy trace port driver_. It seems like a GDB hookup should be possible, as well as tracing only during specific states (perhaps _handling IRQ 23_ or _calls foo()_). There should be GUI tools to manipulate saved trace data and help analyse it in conjunction with the source code. It's unclear how much of a common interface is shared with the current XScale trace support, or should be shared with eventual Nexus-style trace module support. At this writing (November 2009) only ARM7, ARM9, and ARM11 support for ETM modules is available. The code should be able to work with some newer cores; but not all of them support this original style of JTAG access. 16.1.1 ETM Configuration ------------------------ ETM setup is coupled with the trace port driver configuration. -- Config Command: etm config target width mode clocking driver Declares the ETM associated with TARGET, and associates it with a given trace port DRIVER. *Note Trace Port Drivers: traceportdrivers. Several of the parameters must reflect the trace port capabilities, which are a function of silicon capabilties (exposed later using 'etm info') and of what hardware is connected to that port (such as an external pod, or ETB). The WIDTH must be either 4, 8, or 16, except with ETMv3.0 and newer modules which may also support 1, 2, 24, 32, 48, and 64 bit widths. (With those versions, 'etm info' also shows whether the selected port width and mode are supported.) The MODE must be 'normal', 'multiplexed', or 'demultiplexed'. The CLOCKING must be 'half' or 'full'. Warning: With ETMv3.0 and newer, the bits set with the MODE and CLOCKING parameters both control the mode. This modified mode does not map to the values supported by previous ETM modules, so this syntax is subject to change. Note: You can see the ETM registers using the 'reg' command. Not all possible registers are present in every ETM. Most of the registers are write-only, and are used to configure what CPU activities are traced. -- Command: etm info Displays information about the current target's ETM. This includes resource counts from the 'ETM_CONFIG' register, as well as silicon capabilities (except on rather old modules). from the 'ETM_SYS_CONFIG' register. -- Command: etm status Displays status of the current target's ETM and trace port driver: is the ETM idle, or is it collecting data? Did trace data overflow? Was it triggered? -- Command: etm tracemode [type context_id_bits cycle_accurate branch_output] Displays what data that ETM will collect. If arguments are provided, first configures that data. When the configuration changes, tracing is stopped and any buffered trace data is invalidated. * TYPE ... describing how data accesses are traced, when they pass any ViewData filtering that that was set up. The value is one of 'none' (save nothing), 'data' (save data), 'address' (save addresses), 'all' (save data and addresses) * CONTEXT_ID_BITS ... 0, 8, 16, or 32 * CYCLE_ACCURATE ... 'enable' or 'disable' cycle-accurate instruction tracing. Before ETMv3, enabling this causes much extra data to be recorded. * BRANCH_OUTPUT ... 'enable' or 'disable'. Disable this unless you need to try reconstructing the instruction trace stream without an image of the code. -- Command: etm trigger_debug ('enable'|'disable') Displays whether ETM triggering debug entry (like a breakpoint) is enabled or disabled, after optionally modifying that configuration. The default behaviour is 'disable'. Any change takes effect after the next 'etm start'. By using script commands to configure ETM registers, you can make the processor enter debug state automatically when certain conditions, more complex than supported by the breakpoint hardware, happen. 16.1.2 ETM Trace Operation -------------------------- After setting up the ETM, you can use it to collect data. That data can be exported to files for later analysis. It can also be parsed with OpenOCD, for basic sanity checking. To configure what is being traced, you will need to write various trace registers using 'reg ETM_*' commands. For the definitions of these registers, read ARM publication _IHI 0014, "Embedded Trace Macrocell, Architecture Specification"_. Be aware that most of the relevant registers are write-only, and that ETM resources are limited. There are only a handful of address comparators, data comparators, counters, and so on. Examples of scenarios you might arrange to trace include: * Code flow within a function, _excluding_ subroutines it calls. Use address range comparators to enable tracing for instruction access within that function's body. * Code flow within a function, _including_ subroutines it calls. Use the sequencer and address comparators to activate tracing on an "entered function" state, then deactivate it by exiting that state when the function's exit code is invoked. * Code flow starting at the fifth invocation of a function, combining one of the above models with a counter. * CPU data accesses to the registers for a particular device, using address range comparators and the ViewData logic. * Such data accesses only during IRQ handling, combining the above model with sequencer triggers which on entry and exit to the IRQ handler. * _... more_ At this writing, September 2009, there are no Tcl utility procedures to help set up any common tracing scenarios. -- Command: etm analyze Reads trace data into memory, if it wasn't already present. Decodes and prints the data that was collected. -- Command: etm dump filename Stores the captured trace data in 'filename'. -- Command: etm image filename [base_address] [type] Opens an image file. -- Command: etm load filename Loads captured trace data from 'filename'. -- Command: etm start Starts trace data collection. -- Command: etm stop Stops trace data collection. 16.1.3 Trace Port Drivers ------------------------- To use an ETM trace port it must be associated with a driver. -- Trace Port Driver: dummy Use the 'dummy' driver if you are configuring an ETM that's not connected to anything (on-chip ETB or off-chip trace connector). _This driver lets OpenOCD talk to the ETM, but it does not expose any trace data collection._ -- Config Command: etm_dummy config target Associates the ETM for TARGET with a dummy driver. -- Trace Port Driver: etb Use the 'etb' driver if you are configuring an ETM to use on-chip ETB memory. -- Config Command: etb config target etb_tap Associates the ETM for TARGET with the ETB at ETB_TAP. You can see the ETB registers using the 'reg' command. -- Command: etb trigger_percent [percent] This displays, or optionally changes, ETB behavior after the ETM's configured _trigger_ event fires. It controls how much more trace data is saved after the (single) trace trigger becomes active. * The default corresponds to _trace around_ usage, recording 50 percent data before the event and the rest afterwards. * The minimum value of PERCENT is 2 percent, recording almost exclusively data before the trigger. Such extreme _trace before_ usage can help figure out what caused that event to happen. * The maximum value of PERCENT is 100 percent, recording data almost exclusively after the event. This extreme _trace after_ usage might help sort out how the event caused trouble. -- Trace Port Driver: oocd_trace This driver isn't available unless OpenOCD was explicitly configured with the '--enable-oocd_trace' option. You probably don't want to configure it unless you've built the appropriate prototype hardware; it's _proof-of-concept_ software. Use the 'oocd_trace' driver if you are configuring an ETM that's connected to an off-chip trace connector. -- Config Command: oocd_trace config target tty Associates the ETM for TARGET with a trace driver which collects data through the serial port TTY. -- Command: oocd_trace resync Re-synchronizes with the capture clock. -- Command: oocd_trace status Reports whether the capture clock is locked or not. 16.2 Generic ARM ================ These commands should be available on all ARM processors. They are available in addition to other core-specific commands that may be available. -- Command: arm core_state ['arm'|'thumb'] Displays the core_state, optionally changing it to process either 'arm' or 'thumb' instructions. The target may later be resumed in the currently set core_state. (Processors may also support the Jazelle state, but that is not currently supported in OpenOCD.) -- Command: arm disassemble address [count ['thumb']] Disassembles COUNT instructions starting at ADDRESS. If COUNT is not specified, a single instruction is disassembled. If 'thumb' is specified, or the low bit of the address is set, Thumb2 (mixed 16/32-bit) instructions are used; else ARM (32-bit) instructions are used. (Processors may also support the Jazelle state, but those instructions are not currently understood by OpenOCD.) Note that all Thumb instructions are Thumb2 instructions, so older processors (without Thumb2 support) will still see correct disassembly of Thumb code. Also, ThumbEE opcodes are the same as Thumb2, with a handful of exceptions. ThumbEE disassembly currently has no explicit support. -- Command: arm mcr pX op1 CRn CRm op2 value Write VALUE to a coprocessor PX register passing parameters CRN, CRM, opcodes OPC1 and OPC2, and using the MCR instruction. (Parameter sequence matches the ARM instruction, but omits an ARM register.) -- Command: arm mrc pX coproc op1 CRn CRm op2 Read a coprocessor PX register passing parameters CRN, CRM, opcodes OPC1 and OPC2, and the MRC instruction. Returns the result so it can be manipulated by Jim scripts. (Parameter sequence matches the ARM instruction, but omits an ARM register.) -- Command: arm reg Display a table of all banked core registers, fetching the current value from every core mode if necessary. -- Command: arm semihosting ['enable'|'disable'] Display status of semihosting, after optionally changing that status. Semihosting allows for code executing on an ARM target to use the I/O facilities on the host computer i.e. the system where OpenOCD is running. The target application must be linked against a library implementing the ARM semihosting convention that forwards operation requests by using a special SVC instruction that is trapped at the Supervisor Call vector by OpenOCD. 16.3 ARMv4 and ARMv5 Architecture ================================= The ARMv4 and ARMv5 architectures are widely used in embedded systems, and introduced core parts of the instruction set in use today. That includes the Thumb instruction set, introduced in the ARMv4T variant. 16.3.1 ARM7 and ARM9 specific commands -------------------------------------- These commands are specific to ARM7 and ARM9 cores, like ARM7TDMI, ARM720T, ARM9TDMI, ARM920T or ARM926EJ-S. They are available in addition to the ARM commands, and any other core-specific commands that may be available. -- Command: arm7_9 dbgrq ['enable'|'disable'] Displays the value of the flag controlling use of the the EmbeddedIce DBGRQ signal to force entry into debug mode, instead of breakpoints. If a boolean parameter is provided, first assigns that flag. This should be safe for all but ARM7TDMI-S cores (like NXP LPC). This feature is enabled by default on most ARM9 cores, including ARM9TDMI, ARM920T, and ARM926EJ-S. -- Command: arm7_9 dcc_downloads ['enable'|'disable'] Displays the value of the flag controlling use of the debug communications channel (DCC) to write larger (>128 byte) amounts of memory. If a boolean parameter is provided, first assigns that flag. DCC downloads offer a huge speed increase, but might be unsafe, especially with targets running at very low speeds. This command was introduced with OpenOCD rev. 60, and requires a few bytes of working area. -- Command: arm7_9 fast_memory_access ['enable'|'disable'] Displays the value of the flag controlling use of memory writes and reads that don't check completion of the operation. If a boolean parameter is provided, first assigns that flag. This provides a huge speed increase, especially with USB JTAG cables (FT2232), but might be unsafe if used with targets running at very low speeds, like the 32kHz startup clock of an AT91RM9200. 16.3.2 ARM720T specific commands -------------------------------- These commands are available to ARM720T based CPUs, which are implementations of the ARMv4T architecture based on the ARM7TDMI-S integer core. They are available in addition to the ARM and ARM7/ARM9 commands. -- Command: arm720t cp15 opcode [value] _DEPRECATED - avoid using this. Use the 'arm mrc' or 'arm mcr' commands instead._ Display cp15 register returned by the ARM instruction OPCODE; else if a VALUE is provided, that value is written to that register. The OPCODE should be the value of either an MRC or MCR instruction. 16.3.3 ARM9 specific commands ----------------------------- ARM9-family cores are built around ARM9TDMI or ARM9E (including ARM9EJS) integer processors. Such cores include the ARM920T, ARM926EJ-S, and ARM966. -- Command: arm9 vector_catch ['all'|'none'|list] Vector Catch hardware provides a sort of dedicated breakpoint for hardware events such as reset, interrupt, and abort. You can use this to conserve normal breakpoint resources, so long as you're not concerned with code that branches directly to those hardware vectors. This always finishes by listing the current configuration. If parameters are provided, it first reconfigures the vector catch hardware to intercept 'all' of the hardware vectors, 'none' of them, or a list with one or more of the following: 'reset' 'undef' 'swi' 'pabt' 'dabt' 'irq' 'fiq'. 16.3.4 ARM920T specific commands -------------------------------- These commands are available to ARM920T based CPUs, which are implementations of the ARMv4T architecture built using the ARM9TDMI integer core. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. -- Command: arm920t cache_info Print information about the caches found. This allows to see whether your target is an ARM920T (2x16kByte cache) or ARM922T (2x8kByte cache). -- Command: arm920t cp15 regnum [value] Display cp15 register REGNUM; else if a VALUE is provided, that value is written to that register. This uses "physical access" and the register number is as shown in bits 38..33 of table 9-9 in the ARM920T TRM. (Not all registers can be written.) -- Command: arm920t cp15i opcode [value [address]] _DEPRECATED - avoid using this. Use the 'arm mrc' or 'arm mcr' commands instead._ Interpreted access using ARM instruction OPCODE, which should be the value of either an MRC or MCR instruction (as shown tables 9-11, 9-12, and 9-13 in the ARM920T TRM). If no VALUE is provided, the result is displayed. Else if that value is written using the specified ADDRESS, or using zero if no other address is provided. -- Command: arm920t read_cache filename Dump the content of ICache and DCache to a file named 'filename'. -- Command: arm920t read_mmu filename Dump the content of the ITLB and DTLB to a file named 'filename'. 16.3.5 ARM926ej-s specific commands ----------------------------------- These commands are available to ARM926ej-s based CPUs, which are implementations of the ARMv5TEJ architecture based on the ARM9EJ-S integer core. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. The Feroceon cores also support these commands, although they are not built from ARM926ej-s designs. -- Command: arm926ejs cache_info Print information about the caches found. 16.3.6 ARM966E specific commands -------------------------------- These commands are available to ARM966 based CPUs, which are implementations of the ARMv5TE architecture. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. -- Command: arm966e cp15 regnum [value] Display cp15 register REGNUM; else if a VALUE is provided, that value is written to that register. The six bit REGNUM values are bits 37..32 from table 7-2 of the ARM966E-S TRM. There is no current control over bits 31..30 from that table, as required for BIST support. 16.3.7 XScale specific commands ------------------------------- Some notes about the debug implementation on the XScale CPUs: The XScale CPU provides a special debug-only mini-instruction cache (mini-IC) in which exception vectors and target-resident debug handler code are placed by OpenOCD. In order to get access to the CPU, OpenOCD must point vector 0 (the reset vector) to the entry of the debug handler. However, this means that the complete first cacheline in the mini-IC is marked valid, which makes the CPU fetch all exception handlers from the mini-IC, ignoring the code in RAM. To address this situation, OpenOCD provides the 'xscale vector_table' command, which allows the user to explicity write individual entries to either the high or low vector table stored in the mini-IC. It is recommended to place a pc-relative indirect branch in the vector table, and put the branch destination somewhere in memory. Doing so makes sure the code in the vector table stays constant regardless of code layout in memory: _vectors: ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] .org 0x100 .long real_reset_vector .long real_ui_handler .long real_swi_handler .long real_pf_abort .long real_data_abort .long 0 /* unused */ .long real_irq_handler .long real_fiq_handler Alternatively, you may choose to keep some or all of the mini-IC vector table entries synced with those written to memory by your system software. The mini-IC can not be modified while the processor is executing, but for each vector table entry not previously defined using the 'xscale vector_table' command, OpenOCD will copy the value from memory to the mini-IC every time execution resumes from a halt. This is done for both high and low vector tables (although the table not in use may not be mapped to valid memory, and in this case that copy operation will silently fail). This means that you will need to briefly halt execution at some strategic point during system start-up; e.g., after the software has initialized the vector table, but before exceptions are enabled. A breakpoint can be used to accomplish this once the appropriate location in the start-up code has been identified. A watchpoint over the vector table region is helpful in finding the location if you're not sure. Note that the same situation exists any time the vector table is modified by the system software. The debug handler must be placed somewhere in the address space using the 'xscale debug_handler' command. The allowed locations for the debug handler are either (0x800 - 0x1fef800) or (0xfe000800 - 0xfffff800). The default value is 0xfe000800. XScale has resources to support two hardware breakpoints and two watchpoints. However, the following restrictions on watchpoint functionality apply: (1) the value and mask arguments to the 'wp' command are not supported, (2) the watchpoint length must be a power of two and not less than four, and can not be greater than the watchpoint address, and (3) a watchpoint with a length greater than four consumes all the watchpoint hardware resources. This means that at any one time, you can have enabled either two watchpoints with a length of four, or one watchpoint with a length greater than four. These commands are available to XScale based CPUs, which are implementations of the ARMv5TE architecture. -- Command: xscale analyze_trace Displays the contents of the trace buffer. -- Command: xscale cache_clean_address address Changes the address used when cleaning the data cache. -- Command: xscale cache_info Displays information about the CPU caches. -- Command: xscale cp15 regnum [value] Display cp15 register REGNUM; else if a VALUE is provided, that value is written to that register. -- Command: xscale debug_handler target address Changes the address used for the specified target's debug handler. -- Command: xscale dcache ['enable'|'disable'] Enables or disable the CPU's data cache. -- Command: xscale dump_trace filename Dumps the raw contents of the trace buffer to 'filename'. -- Command: xscale icache ['enable'|'disable'] Enables or disable the CPU's instruction cache. -- Command: xscale mmu ['enable'|'disable'] Enables or disable the CPU's memory management unit. -- Command: xscale trace_buffer ['enable'|'disable' ['fill' [n] | 'wrap']] Displays the trace buffer status, after optionally enabling or disabling the trace buffer and modifying how it is emptied. -- Command: xscale trace_image filename [offset [type]] Opens a trace image from 'filename', optionally rebasing its segment addresses by OFFSET. The image TYPE may be one of 'bin' (binary), 'ihex' (Intel hex), 'elf' (ELF file), 's19' (Motorola s19), 'mem', or 'builder'. -- Command: xscale vector_catch [mask] Display a bitmask showing the hardware vectors to catch. If the optional parameter is provided, first set the bitmask to that value. The mask bits correspond with bit 16..23 in the DCSR: 0x01 Trap Reset 0x02 Trap Undefined Instructions 0x04 Trap Software Interrupt 0x08 Trap Prefetch Abort 0x10 Trap Data Abort 0x20 reserved 0x40 Trap IRQ 0x80 Trap FIQ -- Command: xscale vector_table [('low'|'high') index value] Set an entry in the mini-IC vector table. There are two tables: one for low vectors (at 0x00000000), and one for high vectors (0xFFFF0000), each holding the 8 exception vectors. INDEX can be 1-7, because vector 0 points to the debug handler entry and can not be overwritten. VALUE holds the 32-bit opcode that is placed in the mini-IC. Without arguments, the current settings are displayed. 16.4 ARMv6 Architecture ======================= 16.4.1 ARM11 specific commands ------------------------------ -- Command: arm11 memwrite burst ['enable'|'disable'] Displays the value of the memwrite burst-enable flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. Burst writes are only used for memory writes larger than 1 word. They improve performance by assuming that the CPU has read each data word over JTAG and completed its write before the next word arrives, instead of polling for a status flag to verify that completion. This is usually safe, because JTAG runs much slower than the CPU. -- Command: arm11 memwrite error_fatal ['enable'|'disable'] Displays the value of the memwrite error_fatal flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. When set, certain memory write errors cause earlier transfer termination. -- Command: arm11 step_irq_enable ['enable'|'disable'] Displays the value of the flag controlling whether IRQs are enabled during single stepping; they are disabled by default. If a boolean parameter is provided, first assigns that. -- Command: arm11 vcr [value] Displays the value of the _Vector Catch Register (VCR)_, coprocessor 14 register 7. If VALUE is defined, first assigns that. Vector Catch hardware provides dedicated breakpoints for certain hardware events. The specific bit values are core-specific (as in fact is using coprocessor 14 register 7 itself) but all current ARM11 cores _except the ARM1176_ use the same six bits. 16.5 ARMv7 Architecture ======================= 16.5.1 ARMv7 Debug Access Port (DAP) specific commands ------------------------------------------------------ These commands are specific to ARM architecture v7 Debug Access Port (DAP), included on Cortex-M and Cortex-A systems. They are available in addition to other core-specific commands that may be available. -- Command: dap apid [num] Displays ID register from AP NUM, defaulting to the currently selected AP. -- Command: dap apsel [num] Select AP NUM, defaulting to 0. -- Command: dap baseaddr [num] Displays debug base address from MEM-AP NUM, defaulting to the currently selected AP. -- Command: dap info [num] Displays the ROM table for MEM-AP NUM, defaulting to the currently selected AP. -- Command: dap memaccess [value] Displays the number of extra tck cycles in the JTAG idle to use for MEM-AP memory bus access [0-255], giving additional time to respond to reads. If VALUE is defined, first assigns that. -- Command: dap apcsw [0 / 1] fix CSW_SPROT from register AP_REG_CSW on selected dap. Defaulting to 0. 16.5.2 ARMv7-M specific commands -------------------------------- -- Command: tpiu config ('disable' | (('external' | 'internal FILENAME') ('sync PORT_WIDTH' | (('manchester' | 'uart') FORMATTER_ENABLE)) TRACECLKIN_FREQ [TRACE_FREQ])) ARMv7-M architecture provides several modules to generate debugging information internally (ITM, DWT and ETM). Their output is directed through TPIU to be captured externally either on an SWO pin (this configuration is called SWV) or on a synchronous parallel trace port. This command configures the TPIU module of the target and, if internal capture mode is selected, starts to capture trace output by using the debugger adapter features. Some targets require additional actions to be performed in the trace-config handler for trace port to be activated. Command options: - 'disable' disable TPIU handling; - 'external' configure TPIU to let user capture trace output externally (with an additional UART or logic analyzer hardware); - 'internal FILENAME' configure TPIU and debug adapter to gather trace data and append it to FILENAME (which can be either a regular file or a named pipe); - 'sync PORT_WIDTH' use synchronous parallel trace output mode, and set port width to PORT_WIDTH; - 'manchester' use asynchronous SWO mode with Manchester coding; - 'uart' use asynchronous SWO mode with NRZ (same as regular UART 8N1) coding; - FORMATTER_ENABLE is 'on' or 'off' to enable or disable TPIU formatter which needs to be used when both ITM and ETM data is to be output via SWO; - TRACECLKIN_FREQ this should be specified to match target's current TRACECLKIN frequency (usually the same as HCLK); - TRACE_FREQ trace port frequency. Can be omitted in internal mode to let the adapter driver select the maximum supported rate automatically. Example usage: 1. STM32L152 board is programmed with an application that configures PLL to provide core clock with 24MHz frequency; to use ITM output it's enough to: #include ... ITM_STIM8(0) = c; ... (the most obvious way is to use the first stimulus port for printf, for that this ITM_STIM8 assignment can be used inside _write(); to make it blocking to avoid data loss, add 'while (!(ITM_STIM8(0) & ITM_STIM_FIFOREADY));'); 2. An FT2232H UART is connected to the SWO pin of the board; 3. Commands to configure UART for 12MHz baud rate: $ setserial /dev/ttyUSB1 spd_cust divisor 5 $ stty -F /dev/ttyUSB1 38400 (FT2232H's base frequency is 60MHz, spd_cust allows to alias 38400 baud with our custom divisor to get 12MHz) 4. 'itmdump -f /dev/ttyUSB1 -d1' 5. OpenOCD invocation line: openocd -f interface/stlink-v2-1.cfg \ -c "transport select hla_swd" \ -f target/stm32l1.cfg \ -c "tpiu config external uart off 24000000 12000000" -- Command: itm port PORT ('0'|'1'|'on'|'off') Enable or disable trace output for ITM stimulus PORT (counting from 0). Port 0 is enabled on target creation automatically. -- Command: itm ports ('0'|'1'|'on'|'off') Enable or disable trace output for all ITM stimulus ports. 16.5.3 Cortex-M specific commands --------------------------------- -- Command: cortex_m maskisr ('auto'|'on'|'off') Control masking (disabling) interrupts during target step/resume. The 'auto' option handles interrupts during stepping a way they get served but don't disturb the program flow. The step command first allows pending interrupt handlers to execute, then disables interrupts and steps over the next instruction where the core was halted. After the step interrupts are enabled again. If the interrupt handlers don't complete within 500ms, the step command leaves with the core running. Note that a free breakpoint is required for the 'auto' option. If no breakpoint is available at the time of the step, then the step is taken with interrupts enabled, i.e. the same way the 'off' option does. Default is 'auto'. -- Command: cortex_m vector_catch ['all'|'none'|list] Vector Catch hardware provides dedicated breakpoints for certain hardware events. Parameters request interception of 'all' of these hardware event vectors, 'none' of them, or one or more of the following: 'hard_err' for a HardFault exception; 'mm_err' for a MemManage exception; 'bus_err' for a BusFault exception; 'irq_err', 'state_err', 'chk_err', or 'nocp_err' for various UsageFault exceptions; or 'reset'. If NVIC setup code does not enable them, MemManage, BusFault, and UsageFault exceptions are mapped to HardFault. UsageFault checks for divide-by-zero and unaligned access must also be explicitly enabled. This finishes by listing the current vector catch configuration. -- Command: cortex_m reset_config ('srst'|'sysresetreq'|'vectreset') Control reset handling. The default 'srst' is to use srst if fitted, otherwise fallback to 'vectreset'. - 'srst' use hardware srst if fitted otherwise fallback to 'vectreset'. - 'sysresetreq' use NVIC SYSRESETREQ to reset system. - 'vectreset' use NVIC VECTRESET to reset system. Using 'vectreset' is a safe option for all current Cortex-M cores. This however has the disadvantage of only resetting the core, all peripherals are uneffected. A solution would be to use a 'reset-init' event handler to manually reset the peripherals. *Note Target Events: targetevents. 16.6 Intel Architecture ======================= Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32 (Pentium x86 ISA) compatible SoC. The core CPU in the X10xx is codenamed Lakemont. Lakemont version 1 (LMT1) is used in X10xx. The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is used for SoC level operations. Useful docs are here: https://communities.intel.com/community/makers/documentation * Intel Quark SoC X1000 OpenOCD/GDB/Eclipse App Note (web search for doc num 330015) * Intel Quark SoC X1000 Debug Operations User Guide (web search for doc num 329866) * Intel Quark SoC X1000 Datasheet (web search for doc num 329676) 16.6.1 x86 32-bit specific commands ----------------------------------- The three main address spaces for x86 are memory, I/O and configuration space. These commands allow a user to read and write to the 64Kbyte I/O address space. -- Command: x86_32 idw address Display the contents of a 32-bit I/O port from address range 0x0000 - 0xffff. -- Command: x86_32 idh address Display the contents of a 16-bit I/O port from address range 0x0000 - 0xffff. -- Command: x86_32 idb address Display the contents of a 8-bit I/O port from address range 0x0000 - 0xffff. -- Command: x86_32 iww address Write the contents of a 32-bit I/O port to address range 0x0000 - 0xffff. -- Command: x86_32 iwh address Write the contents of a 16-bit I/O port to address range 0x0000 - 0xffff. -- Command: x86_32 iwb address Write the contents of a 8-bit I/O port to address range 0x0000 - 0xffff. 16.7 OpenRISC Architecture ========================== The OpenRISC CPU is a soft core. It is used in a programmable SoC which can be configured with any of the TAP / Debug Unit available. 16.7.1 TAP and Debug Unit selection commands -------------------------------------------- -- Command: tap_select ('vjtag'|'mohor'|'xilinx_bscan') Select between the Altera Virtual JTAG , Xilinx Virtual JTAG and Mohor TAP. -- Command: du_select ('adv'|'mohor') [option] Select between the Advanced Debug Interface and the classic one. An option can be passed as a second argument to the debug unit. When using the Advanced Debug Interface, option = 1 means the RTL core is configured with ADBG_USE_HISPEED = 1. This configuration skips status checking between bytes while doing read or write bursts. 16.7.2 Registers commands ------------------------- -- Command: addreg [name] [address] [feature] [reg_group] Add a new register in the cpu register list. This register will be included in the generated target descriptor file. *[feature]* must be "org.gnu.gdb.or1k.group[0..10]". *[reg_group]* can be anything. The default register list defines "system", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf", "power", "pic" and "timer" groups. _example:_ addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system -- Command: readgroup ('group') Display all registers in _group_. _group_ can be "system", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf", "power", "pic", "timer" or any new group created with addreg command. 16.8 Software Debug Messages and Tracing ======================================== OpenOCD can process certain requests from target software, when the target uses appropriate libraries. The most powerful mechanism is semihosting, but there is also a lighter weight mechanism using only the DCC channel. Currently 'target_request debugmsgs' is supported only for 'arm7_9' and 'cortex_m' cores. These messages are received as part of target polling, so you need to have 'poll on' active to receive them. They are intrusive in that they will affect program execution times. If that is a problem, *note ARM Hardware Tracing: armhardwaretracing. See 'libdcc' in the contrib dir for more details. In addition to sending strings, characters, and arrays of various size integers from the target, 'libdcc' also exports a software trace point mechanism. The target being debugged may issue trace messages which include a 24-bit "trace point" number. Trace point support includes two distinct mechanisms, each supported by a command: * _History_ ... A circular buffer of trace points can be set up, and then displayed at any time. This tracks where code has been, which can be invaluable in finding out how some fault was triggered. The buffer may overflow, since it collects records continuously. It may be useful to use some of the 24 bits to represent a particular event, and other bits to hold data. * _Counting_ ... An array of counters can be set up, and then displayed at any time. This can help establish code coverage and identify hot spots. The array of counters is directly indexed by the trace point number, so trace points with higher numbers are not counted. Linux-ARM kernels have a "Kernel low-level debugging via EmbeddedICE DCC channel" option (CONFIG_DEBUG_ICEDCC, depends on CONFIG_DEBUG_LL) which uses this mechanism to deliver messages before a serial console can be activated. This is not the same format used by 'libdcc'. Other software, such as the U-Boot boot loader, sometimes does the same thing. -- Command: target_request debugmsgs ['enable'|'disable'|'charmsg'] Displays current handling of target DCC message requests. These messages may be sent to the debugger while the target is running. The optional 'enable' and 'charmsg' parameters both enable the messages, while 'disable' disables them. With 'charmsg' the DCC words each contain one character, as used by Linux with CONFIG_DEBUG_ICEDCC; otherwise the libdcc format is used. -- Command: trace history ['clear'|count] With no parameter, displays all the trace points that have triggered in the order they triggered. With the parameter 'clear', erases all current trace history records. With a COUNT parameter, allocates space for that many history records. -- Command: trace point ['clear'|identifier] With no parameter, displays all trace point identifiers and how many times they have been triggered. With the parameter 'clear', erases all current trace point counters. With a numeric IDENTIFIER parameter, creates a new a trace point counter and associates it with that identifier. _Important:_ The identifier and the trace point number are not related except by this command. These trace point numbers always start at zero (from server startup, or after 'trace point clear') and count up from there. openocd-0.9.0/doc/openocd.info-20000644000175000017500000042117212526202223013303 00000000000000This is openocd.info, produced by makeinfo version 5.2 from openocd.texi. This User's Guide documents release 0.9.0, dated 18 May 2015, of the Open On-Chip Debugger (OpenOCD). * Copyright (C) 2008 The OpenOCD Project * Copyright (C) 2007-2008 Spencer Oliver * Copyright (C) 2008-2010 Oyvind Harboe * Copyright (C) 2008 Duane Ellis * Copyright (C) 2009-2010 David Brownell Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". INFO-DIR-SECTION Development START-INFO-DIR-ENTRY * OpenOCD: (openocd). OpenOCD User's Guide END-INFO-DIR-ENTRY  File: openocd.info, Node: JTAG Commands, Next: Boundary Scan Commands, Prev: Architecture and Core Commands, Up: Top 17 JTAG Commands **************** Most general purpose JTAG commands have been presented earlier. (*Note JTAG Speed: jtagspeed, *note Reset Configuration::, and *note TAP Declaration::.) Lower level JTAG commands, as presented here, may be needed to work with targets which require special attention during operations such as reset or initialization. To use these commands you will need to understand some of the basics of JTAG, including: * A JTAG scan chain consists of a sequence of individual TAP devices such as a CPUs. * Control operations involve moving each TAP through the same standard state machine (in parallel) using their shared TMS and clock signals. * Data transfer involves shifting data through the chain of instruction or data registers of each TAP, writing new register values while the reading previous ones. * Data register sizes are a function of the instruction active in a given TAP, while instruction register sizes are fixed for each TAP. All TAPs support a BYPASS instruction with a single bit data register. * The way OpenOCD differentiates between TAP devices is by shifting different instructions into (and out of) their instruction registers. 17.1 Low Level JTAG Commands ============================ These commands are used by developers who need to access JTAG instruction or data registers, possibly controlling the order of TAP state transitions. If you're not debugging OpenOCD internals, or bringing up a new JTAG adapter or a new type of TAP device (like a CPU or JTAG router), you probably won't need to use these commands. In a debug session that doesn't use JTAG for its transport protocol, these commands are not available. -- Command: drscan tap [numbits value]+ ['-endstate' tap_state] Loads the data register of TAP with a series of bit fields that specify the entire register. Each field is NUMBITS bits long with a numeric VALUE (hexadecimal encouraged). The return value holds the original value of each of those fields. For example, a 38 bit number might be specified as one field of 32 bits then one of 6 bits. _For portability, never pass fields which are more than 32 bits long. Many OpenOCD implementations do not support 64-bit (or larger) integer values._ All TAPs other than TAP must be in BYPASS mode. The single bit in their data registers does not matter. When TAP_STATE is specified, the JTAG state machine is left in that state. For example DRPAUSE might be specified, so that more instructions can be issued before re-entering the RUN/IDLE state. If the end state is not specified, the RUN/IDLE state is entered. Warning: OpenOCD does not record information about data register lengths, so _it is important that you get the bit field lengths right_. Remember that different JTAG instructions refer to different data registers, which may have different lengths. Moreover, those lengths may not be fixed; the SCAN_N instruction can change the length of the register accessed by the INTEST instruction (by connecting a different scan chain). -- Command: flush_count Returns the number of times the JTAG queue has been flushed. This may be used for performance tuning. For example, flushing a queue over USB involves a minimum latency, often several milliseconds, which does not change with the amount of data which is written. You may be able to identify performance problems by finding tasks which waste bandwidth by flushing small transfers too often, instead of batching them into larger operations. -- Command: irscan [tap instruction]+ ['-endstate' tap_state] For each TAP listed, loads the instruction register with its associated numeric INSTRUCTION. (The number of bits in that instruction may be displayed using the 'scan_chain' command.) For other TAPs, a BYPASS instruction is loaded. When TAP_STATE is specified, the JTAG state machine is left in that state. For example IRPAUSE might be specified, so the data register can be loaded before re-entering the RUN/IDLE state. If the end state is not specified, the RUN/IDLE state is entered. Note: OpenOCD currently supports only a single field for instruction register values, unlike data register values. For TAPs where the instruction register length is more than 32 bits, portable scripts currently must issue only BYPASS instructions. -- Command: jtag_reset trst srst Set values of reset signals. The TRST and SRST parameter values may be '0', indicating that reset is inactive (pulled or driven high), or '1', indicating it is active (pulled or driven low). The 'reset_config' command should already have been used to configure how the board and JTAG adapter treat these two signals, and to say if either signal is even present. *Note Reset Configuration::. Note that TRST is specially handled. It actually signifies JTAG's RESET state. So if the board doesn't support the optional TRST signal, or it doesn't support it along with the specified SRST value, JTAG reset is triggered with TMS and TCK signals instead of the TRST signal. And no matter how that JTAG reset is triggered, once the scan chain enters RESET with TRST inactive, TAP 'post-reset' events are delivered to all TAPs with handlers for that event. -- Command: pathmove start_state [next_state ...] Start by moving to START_STATE, which must be one of the _stable_ states. Unless it is the only state given, this will often be the current state, so that no TCK transitions are needed. Then, in a series of single state transitions (conforming to the JTAG state machine) shift to each NEXT_STATE in sequence, one per TCK cycle. The final state must also be stable. -- Command: runtest NUM_CYCLES Move to the RUN/IDLE state, and execute at least NUM_CYCLES of the JTAG clock (TCK). Instructions often need some time to execute before they take effect. -- Command: verify_ircapture ('enable'|'disable') Verify values captured during IRCAPTURE and returned during IR scans. Default is enabled, but this can be overridden by 'verify_jtag'. This flag is ignored when validating JTAG chain configuration. -- Command: verify_jtag ('enable'|'disable') Enables verification of DR and IR scans, to help detect programming errors. For IR scans, 'verify_ircapture' must also be enabled. Default is enabled. 17.2 TAP state names ==================== The TAP_STATE names used by OpenOCD in the 'drscan', 'irscan', and 'pathmove' commands are the same as those used in SVF boundary scan documents, except that SVF uses IDLE instead of RUN/IDLE. * RESET ... _stable_ (with TMS high); acts as if TRST were pulsed * RUN/IDLE ... _stable_; don't assume this always means IDLE * DRSELECT * DRCAPTURE * DRSHIFT ... _stable_; TDI/TDO shifting through the data register * DREXIT1 * DRPAUSE ... _stable_; data register ready for update or more shifting * DREXIT2 * DRUPDATE * IRSELECT * IRCAPTURE * IRSHIFT ... _stable_; TDI/TDO shifting through the instruction register * IREXIT1 * IRPAUSE ... _stable_; instruction register ready for update or more shifting * IREXIT2 * IRUPDATE Note that only six of those states are fully "stable" in the face of TMS fixed (low except for RESET) and a free-running JTAG clock. For all the others, the next TCK transition changes to a new state. * From DRSHIFT and IRSHIFT, clock transitions will produce side effects by changing register contents. The values to be latched in upcoming DRUPDATE or IRUPDATE states may not be as expected. * RUN/IDLE, DRPAUSE, and IRPAUSE are reasonable choices after 'drscan' or 'irscan' commands, since they are free of JTAG side effects. * RUN/IDLE may have side effects that appear at non-JTAG levels, such as advancing the ARM9E-S instruction pipeline. Consult the documentation for the TAP(s) you are working with.  File: openocd.info, Node: Boundary Scan Commands, Next: Utility Commands, Prev: JTAG Commands, Up: Top 18 Boundary Scan Commands ************************* One of the original purposes of JTAG was to support boundary scan based hardware testing. Although its primary focus is to support On-Chip Debugging, OpenOCD also includes some boundary scan commands. 18.1 SVF: Serial Vector Format ============================== The Serial Vector Format, better known as "SVF", is a way to represent JTAG test patterns in text files. In a debug session using JTAG for its transport protocol, OpenOCD supports running such test files. -- Command: svf filename ['quiet'] This issues a JTAG reset (Test-Logic-Reset) and then runs the SVF script from 'filename'. Unless the 'quiet' option is specified, each command is logged before it is executed. 18.2 XSVF: Xilinx Serial Vector Format ====================================== The Xilinx Serial Vector Format, better known as "XSVF", is a binary representation of SVF which is optimized for use with Xilinx devices. In a debug session using JTAG for its transport protocol, OpenOCD supports running such test files. Important: Not all XSVF commands are supported. -- Command: xsvf (tapname|'plain') filename ['virt2'] ['quiet'] This issues a JTAG reset (Test-Logic-Reset) and then runs the XSVF script from 'filename'. When a TAPNAME is specified, the commands are directed at that TAP. When 'virt2' is specified, the XRUNTEST command counts are interpreted as TCK cycles instead of microseconds. Unless the 'quiet' option is specified, messages are logged for comments and some retries. The OpenOCD sources also include two utility scripts for working with XSVF; they are not currently installed after building the software. You may find them useful: * _svf2xsvf_ ... converts SVF files into the extended XSVF syntax understood by the 'xsvf' command; see notes below. * _xsvfdump_ ... converts XSVF files into a text output format; understands the OpenOCD extensions. The input format accepts a handful of non-standard extensions. These include three opcodes corresponding to SVF extensions from Lattice Semiconductor (LCOUNT, LDELAY, LDSR), and two opcodes supporting a more accurate translation of SVF (XTRST, XWAITSTATE). If _xsvfdump_ shows a file is using those opcodes, it probably will not be usable with other XSVF tools.  File: openocd.info, Node: Utility Commands, Next: TFTP, Prev: Boundary Scan Commands, Up: Top 19 Utility Commands ******************* 19.1 RAM testing ================ There is often a need to stress-test random access memory (RAM) for errors. OpenOCD comes with a Tcl implementation of well-known memory testing procedures allowing the detection of all sorts of issues with electrical wiring, defective chips, PCB layout and other common hardware problems. To use them, you usually need to initialise your RAM controller first; consult your SoC's documentation to get the recommended list of register operations and translate them to the corresponding 'mww'/'mwb' commands. Load the memory testing functions with source [find tools/memtest.tcl] to get access to the following facilities: -- Command: memTestDataBus address Test the data bus wiring in a memory region by performing a walking 1's test at a fixed address within that region. -- Command: memTestAddressBus baseaddress size Perform a walking 1's test on the relevant bits of the address and check for aliasing. This test will find single-bit address failures such as stuck-high, stuck-low, and shorted pins. -- Command: memTestDevice baseaddress size Test the integrity of a physical memory device by performing an increment/decrement test over the entire region. In the process every storage bit in the device is tested as zero and as one. -- Command: runAllMemTests baseaddress size Run all of the above tests over a specified memory region. 19.2 Firmware recovery helpers ============================== OpenOCD includes an easy-to-use script to facilitate mass-market devices recovery with JTAG. For quickstart instructions run: openocd -f tools/firmware-recovery.tcl -c firmware_help  File: openocd.info, Node: TFTP, Next: GDB and OpenOCD, Prev: Utility Commands, Up: Top 20 TFTP ******* If OpenOCD runs on an embedded host (as ZY1000 does), then TFTP can be used to access files on PCs (either the developer's PC or some other PC). The way this works on the ZY1000 is to prefix a filename by "/tftp/ip/" and append the TFTP path on the TFTP server (tftpd). For example, load_image /tftp/10.0.0.96/c:\temp\abc.elf will load c:\temp\abc.elf from the developer pc (10.0.0.96) into memory as if the file was hosted on the embedded host. In order to achieve decent performance, you must choose a TFTP server that supports a packet size bigger than the default packet size (512 bytes). There are numerous TFTP servers out there (free and commercial) and you will have to do a bit of googling to find something that fits your requirements.  File: openocd.info, Node: GDB and OpenOCD, Next: Tcl Scripting API, Prev: TFTP, Up: Top 21 GDB and OpenOCD ****************** OpenOCD complies with the remote gdbserver protocol and, as such, can be used to debug remote targets. Setting up GDB to work with OpenOCD can involve several components: * The OpenOCD server support for GDB may need to be configured. *Note GDB Configuration: gdbconfiguration. * GDB's support for OpenOCD may need configuration, as shown in this chapter. * If you have a GUI environment like Eclipse, that also will probably need to be configured. Of course, the version of GDB you use will need to be one which has been built to know about the target CPU you're using. It's probably part of the tool chain you're using. For example, if you are doing cross-development for ARM on an x86 PC, instead of using the native x86 'gdb' command you might use 'arm-none-eabi-gdb' if that's the tool chain used to compile your code. 21.1 Connecting to GDB ====================== Use GDB 6.7 or newer with OpenOCD if you run into trouble. For instance GDB 6.3 has a known bug that produces bogus memory access errors, which has since been fixed; see OpenOCD can communicate with GDB in two ways: 1. A socket (TCP/IP) connection is typically started as follows: target remote localhost:3333 This would cause GDB to connect to the gdbserver on the local pc using port 3333. It is also possible to use the GDB extended remote protocol as follows: target extended-remote localhost:3333 2. A pipe connection is typically started as follows: target remote | openocd -c "gdb_port pipe; log_output openocd.log" This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout). Using this method has the advantage of GDB starting/stopping OpenOCD for the debug session. log_output sends the log output to a file to ensure that the pipe is not saturated when using higher debug level outputs. To list the available OpenOCD commands type 'monitor help' on the GDB command line. 21.2 Sample GDB session startup =============================== With the remote protocol, GDB sessions start a little differently than they do when you're debugging locally. Here's an example showing how to start a debug session with a small ARM program. In this case the program was linked to be loaded into SRAM on a Cortex-M3. Most programs would be written into flash (address 0) and run from there. $ arm-none-eabi-gdb example.elf (gdb) target remote localhost:3333 Remote debugging using localhost:3333 ... (gdb) monitor reset halt ... (gdb) load Loading section .vectors, size 0x100 lma 0x20000000 Loading section .text, size 0x5a0 lma 0x20000100 Loading section .data, size 0x18 lma 0x200006a0 Start address 0x2000061c, load size 1720 Transfer rate: 22 KB/sec, 573 bytes/write. (gdb) continue Continuing. ... You could then interrupt the GDB session to make the program break, type 'where' to show the stack, 'list' to show the code around the program counter, 'step' through code, set breakpoints or watchpoints, and so on. 21.3 Configuring GDB for OpenOCD ================================ OpenOCD supports the gdb 'qSupported' packet, this enables information to be sent by the GDB remote server (i.e. OpenOCD) to GDB. Typical information includes packet size and the device's memory map. You do not need to configure the packet size by hand, and the relevant parts of the memory map should be automatically set up when you declare (NOR) flash banks. However, there are other things which GDB can't currently query. You may need to set those up by hand. As OpenOCD starts up, you will often see a line reporting something like: Info : lm3s.cpu: hardware has 6 breakpoints, 4 watchpoints You can pass that information to GDB with these commands: set remote hardware-breakpoint-limit 6 set remote hardware-watchpoint-limit 4 With that particular hardware (Cortex-M3) the hardware breakpoints only work for code running from flash memory. Most other ARM systems do not have such restrictions. Another example of useful GDB configuration came from a user who found that single stepping his Cortex-M3 didn't work well with IRQs and an RTOS until he told GDB to disable the IRQs while stepping: define hook-step mon cortex_m maskisr on end define hookpost-step mon cortex_m maskisr off end Rather than typing such commands interactively, you may prefer to save them in a file and have GDB execute them as it starts, perhaps using a '.gdbinit' in your project directory or starting GDB using 'gdb -x filename'. 21.4 Programming using GDB ========================== By default the target memory map is sent to GDB. This can be disabled by the following OpenOCD configuration option: gdb_memory_map disable For this to function correctly a valid flash configuration must also be set in OpenOCD. For faster performance you should also configure a valid working area. Informing GDB of the memory map of the target will enable GDB to protect any flash areas of the target and use hardware breakpoints by default. This means that the OpenOCD option 'gdb_breakpoint_override' is not required when using a memory map. *Note gdb_breakpoint_override: gdbbreakpointoverride. To view the configured memory map in GDB, use the GDB command 'info mem'. All other unassigned addresses within GDB are treated as RAM. GDB 6.8 and higher set any memory area not in the memory map as inaccessible. This can be changed to the old behaviour by using the following GDB command set mem inaccessible-by-default off If 'gdb_flash_program enable' is also used, GDB will be able to program any flash memory using the vFlash interface. GDB will look at the target memory map when a load command is given, if any areas to be programmed lie within the target flash area the vFlash packets will be used. If the target needs configuring before GDB programming, an event script can be executed: $_TARGETNAME configure -event EVENTNAME BODY To verify any flash programming the GDB command 'compare-sections' can be used. 21.5 Using OpenOCD SMP with GDB =============================== For SMP support following GDB serial protocol packet have been defined : * j - smp status request * J - smp set request OpenOCD implements : * 'jc' packet for reading core id displayed by GDB connection. Reply is 'XXXXXXXX' (8 hex digits giving core id) or 'E01' for target not smp. * 'JcXXXXXXXX' (8 hex digits) packet for setting core id displayed at next GDB continue (core id -1 is reserved for returning to normal resume mode). Reply 'E01' for target not smp or 'OK' on success. Handling of this packet within GDB can be done : * by the creation of an internal variable (i.e '_core') by mean of function allocate_computed_value allowing following GDB command. set $_core 1 #Jc01 packet is sent print $_core #jc packet is sent and result is affected in $ * by the usage of GDB maintenance command as described in following example (2 cpus in SMP with core id 0 and 1 *note Define CPU targets working in SMP: definecputargetsworkinginsmp.). # toggle0 : force display of coreid 0 define toggle0 maint packet Jc0 continue main packet Jc-1 end # toggle1 : force display of coreid 1 define toggle1 maint packet Jc1 continue main packet Jc-1 end 21.6 RTOS Support ================= OpenOCD includes RTOS support, this will however need enabling as it defaults to disabled. It can be enabled by passing '-rtos' arg to the target *Note RTOS Type: rtostype. An example setup is below: $_TARGETNAME configure -rtos auto This will attempt to auto detect the RTOS within your application. Currently supported rtos's include: * 'eCos' * 'ThreadX' * 'FreeRTOS' * 'linux' * 'ChibiOS' * 'embKernel' * 'mqx' Note: Before an RTOS can be detected, it must export certain symbols; otherwise, it cannot be used by OpenOCD. Below is a list of the required symbols for each supported RTOS. 'eCos symbols' Cyg_Thread::thread_list, Cyg_Scheduler_Base::current_thread. 'ThreadX symbols' _tx_thread_current_ptr, _tx_thread_created_ptr, _tx_thread_created_count. 'FreeRTOS symbols' pxCurrentTCB, pxReadyTasksLists, xDelayedTaskList1, xDelayedTaskList2, pxDelayedTaskList, pxOverflowDelayedTaskList, xPendingReadyList, uxCurrentNumberOfTasks, uxTopUsedPriority. 'linux symbols' init_task. 'ChibiOS symbols' rlist, ch_debug, chSysInit. 'embKernel symbols' Rtos::sCurrentTask, Rtos::sListReady, Rtos::sListSleep, Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount. 'mqx symbols' _mqx_kernel_data, MQX_init_struct. For most RTOS supported the above symbols will be exported by default. However for some, eg. FreeRTOS, extra steps must be taken. These RTOSes may require additional OpenOCD-specific file to be linked along with the project: 'FreeRTOS' contrib/rtos-helpers/FreeRTOS-openocd.c  File: openocd.info, Node: Tcl Scripting API, Next: FAQ, Prev: GDB and OpenOCD, Up: Top 22 Tcl Scripting API ******************** 22.1 API rules ============== Tcl commands are stateless; e.g. the 'telnet' command has a concept of currently active target, the Tcl API proc's take this sort of state information as an argument to each proc. There are three main types of return values: single value, name value pair list and lists. Name value pair. The proc 'foo' below returns a name/value pair list. > set foo(me) Duane > set foo(you) Oyvind > set foo(mouse) Micky > set foo(duck) Donald If one does this: > set foo The result is: me Duane you Oyvind mouse Micky duck Donald Thus, to get the names of the associative array is easy: foreach { name value } [set foo] { puts "Name: $name, Value: $value" } Lists returned should be relatively small. Otherwise, a range should be passed in to the proc in question. 22.2 Internal low-level Commands ================================ By "low-level," we mean commands that a human would typically not invoke directly. Some low-level commands need to be prefixed with "ocd_"; e.g. 'ocd_flash_banks' is the low-level API upon which 'flash banks' is implemented. * mem2array Read memory and return as a Tcl array for script processing * array2mem Convert a Tcl array to memory locations and write the values * ocd_flash_banks ['driver options' ...] Return information about the flash banks * capture Run and return full log output that was produced during its execution. Example: > capture "reset init" OpenOCD commands can consist of two words, e.g. "flash banks". The 'startup.tcl' "unknown" proc will translate this into a Tcl proc called "flash_banks". 22.3 OpenOCD specific Global Variables ====================================== Real Tcl has ::tcl_platform(), and platform::identify, and many other variables. JimTCL, as implemented in OpenOCD creates $ocd_HOSTOS which holds one of the following values: * cygwin Running under Cygwin * darwin Darwin (Mac-OS) is the underlying operating sytem. * freebsd Running under FreeBSD * openbsd Running under OpenBSD * netbsd Running under NetBSD * linux Linux is the underlying operating sytem * mingw32 Running under MingW32 * winxx Built using Microsoft Visual Studio * ecos Running under eCos * other Unknown, none of the above. Note: 'winxx' was choosen because today (March-2009) no distinction is made between Win32 and Win64. Note: We should add support for a variable like Tcl variable 'tcl_platform(platform)', it should be called 'jim_platform' (because it is jim, not real tcl). 22.4 Tcl RPC server =================== OpenOCD provides a simple RPC server that allows to run arbitrary Tcl commands and receive the results. To access it, your application needs to connect to a configured TCP port (see 'tcl_port'). Then it can pass any string to the interpreter terminating it with '0x1a' and wait for the return value (it will be terminated with '0x1a' as well). This can be repeated as many times as desired without reopening the connection. Remember that most of the OpenOCD commands need to be prefixed with 'ocd_' to get the results back. Sometimes you might also need the 'capture' command. See 'contrib/rpc_examples/' for specific client implementations. 22.5 Tcl RPC server notifications ================================= Notifications are sent asynchronously to other commands being executed over the RPC server, so the port must be polled continuously. Target event, state and reset notifications are emitted as Tcl associative arrays in the following format. type target_event event [event-name] type target_state state [state-name] type target_reset mode [reset-mode] -- Command: tcl_notifications [on/off] Toggle output of target notifications to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off.  File: openocd.info, Node: FAQ, Next: Tcl Crash Course, Prev: Tcl Scripting API, Up: Top 23 FAQ ****** 1. RTCK, also known as: Adaptive Clocking - What is it? In digital circuit design it is often refered to as "clock synchronisation" the JTAG interface uses one clock (TCK or TCLK) operating at some speed, your CPU target is operating at another. The two clocks are not synchronised, they are "asynchronous" In order for the two to work together they must be synchronised well enough to work; JTAG can't go ten times faster than the CPU, for example. There are 2 basic options: 1. Use a special "adaptive clocking" circuit to change the JTAG clock rate to match what the CPU currently supports. 2. The JTAG clock must be fixed at some speed that's enough slower than the CPU clock that all TMS and TDI transitions can be detected. Does this really matter? For some chips and some situations, this is a non-issue, like a 500MHz ARM926 with a 5 MHz JTAG link; the CPU has no difficulty keeping up with JTAG. Startup sequences are often problematic though, as are other situations where the CPU clock rate changes (perhaps to save power). For example, Atmel AT91SAM chips start operation from reset with a 32kHz system clock. Boot firmware may activate the main oscillator and PLL before switching to a faster clock (perhaps that 500 MHz ARM926 scenario). If you're using JTAG to debug that startup sequence, you must slow the JTAG clock to sometimes 1 to 4kHz. After startup completes, JTAG can use a faster clock. Consider also debugging a 500MHz ARM926 hand held battery powered device that enters a low power "deep sleep" mode, at 32kHz CPU clock, between keystrokes unless it has work to do. When would that 5 MHz JTAG clock be usable? Solution #1 - A special circuit In order to make use of this, your CPU, board, and JTAG adapter must all support the RTCK feature. Not all of them support this; keep reading! The RTCK ("Return TCK") signal in some ARM chips is used to help with this problem. ARM has a good description of the problem described at this link: [checked 28/nov/2008]. Link title: "How does the JTAG synchronisation logic work? / how does adaptive clocking work?". The nice thing about adaptive clocking is that "battery powered hand held device example" - the adaptiveness works perfectly all the time. One can set a break point or halt the system in the deep power down code, slow step out until the system speeds up. Note that adaptive clocking may also need to work at the board level, when a board-level scan chain has multiple chips. Parallel clock voting schemes are good way to implement this, both within and between chips, and can easily be implemented with a CPLD. It's not difficult to have logic fan a module's input TCK signal out to each TAP in the scan chain, and then wait until each TAP's RTCK comes back with the right polarity before changing the output RTCK signal. Texas Instruments makes some clock voting logic available for free (with no support) in VHDL form; see Solution #2 - Always works - but may be slower Often this is a perfectly acceptable solution. In most simple terms: Often the JTAG clock must be 1/10 to 1/12 of the target clock speed. But what that "magic division" is varies depending on the chips on your board. ARM rule of thumb Most ARM based systems require an 6:1 division; ARM11 cores use an 8:1 division. Xilinx rule of thumb is 1/12 the clock speed. Note: most full speed FT2232 based JTAG adapters are limited to a maximum of 6MHz. The ones using USB high speed chips (FT2232H) often support faster clock rates (and adaptive clocking). You can still debug the 'low power' situations - you just need to either use a fixed and very slow JTAG clock rate ... or else manually adjust the clock speed at every step. (Adjusting is painful and tedious, and is not always practical.) It is however easy to "code your way around it" - i.e.: Cheat a little, have a special debug mode in your application that does a "high power sleep". If you are careful - 98% of your problems can be debugged this way. Note that on ARM you may need to avoid using the _wait for interrupt_ operation in your idle loops even if you don't otherwise change the CPU clock rate. That operation gates the CPU clock, and thus the JTAG clock; which prevents JTAG access. One consequence is not being able to 'halt' cores which are executing that _wait for interrupt_ operation. To set the JTAG frequency use the command: # Example: 1.234MHz adapter_khz 1234 2. Win32 Pathnames Why don't backslashes work in Windows paths? OpenOCD uses Tcl and a backslash is an escape char. Use { and } around Windows filenames. > echo \a > echo {\a} \a > echo "\a" > 3. Missing: cygwin1.dll OpenOCD complains about a missing cygwin1.dll. Make sure you have Cygwin installed, or at least a version of OpenOCD that claims to come with all the necessary DLLs. When using Cygwin, try launching OpenOCD from the Cygwin shell. 4. Breakpoint Issue I'm trying to set a breakpoint using GDB (or a frontend like Insight or Eclipse), but OpenOCD complains that "Info: arm7_9_common.c:213 arm7_9_add_breakpoint(): sw breakpoint requested, but software breakpoints not enabled". GDB issues software breakpoints when a normal breakpoint is requested, or to implement source-line single-stepping. On ARMv4T systems, like ARM7TDMI, ARM720T or ARM920T, software breakpoints consume one of the two available hardware breakpoints. 5. LPC2000 Flash When erasing or writing LPC2000 on-chip flash, the operation fails at random. Make sure the core frequency specified in the 'flash lpc2000' line matches the clock at the time you're programming the flash. If you've specified the crystal's frequency, make sure the PLL is disabled. If you've specified the full core speed (e.g. 60MHz), make sure the PLL is enabled. 6. Amontec Chameleon When debugging using an Amontec Chameleon in its JTAG Accelerator configuration, I keep getting "Error: amt_jtagaccel.c:184 amt_wait_scan_busy(): amt_jtagaccel timed out while waiting for end of scan, rtck was disabled". Make sure your PC's parallel port operates in EPP mode. You might have to try several settings in your PC BIOS (ECP, EPP, and different versions of those). 7. Data Aborts When debugging with OpenOCD and GDB (plain GDB, Insight, or Eclipse), I get lots of "Error: arm7_9_common.c:1771 arm7_9_read_memory(): memory read caused data abort". The errors are non-fatal, and are the result of GDB trying to trace stack frames beyond the last valid frame. It might be possible to prevent this by setting up a proper "initial" stack frame, if you happen to know what exactly has to be done, feel free to add this here. Simple: In your startup code - push 8 registers of zeros onto the stack before calling main(). What GDB is doing is "climbing" the run time stack by reading various values on the stack using the standard call frame for the target. GDB keeps going - until one of 2 things happen #1 an invalid frame is found, or #2 some huge number of stackframes have been processed. By pushing zeros on the stack, GDB gracefully stops. Debugging Interrupt Service Routines - In your ISR before you call your C code, do the same - artifically push some zeros onto the stack, remember to pop them off when the ISR is done. Also note: If you have a multi-threaded operating system, they often do not in the intrest of saving memory waste these few bytes. Painful... 8. JTAG Reset Config I get the following message in the OpenOCD console (or log file): "Warning: arm7_9_common.c:679 arm7_9_assert_reset(): srst resets test logic, too". This warning doesn't indicate any serious problem, as long as you don't want to debug your core right out of reset. Your .cfg file specified 'jtag_reset trst_and_srst srst_pulls_trst' to tell OpenOCD that either your board, your debugger or your target uC (e.g. LPC2000) can't assert the two reset signals independently. With this setup, it's not possible to halt the core right out of reset, everything else should work fine. 9. USB Power When using OpenOCD in conjunction with Amontec JTAGkey and the Yagarto toolchain (Eclipse, arm-elf-gcc, arm-elf-gdb), the debugging seems to be unstable. When single-stepping over large blocks of code, GDB and OpenOCD quit with an error message. Is there a stability issue with OpenOCD? No, this is not a stability issue concerning OpenOCD. Most users have solved this issue by simply using a self-powered USB hub, which they connect their Amontec JTAGkey to. Apparently, some computers do not provide a USB power supply stable enough for the Amontec JTAGkey to be operated. Laptops running on battery have this problem too... 10. USB Power When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following error messages: "Error: ft2232.c:201 ft2232_read(): FT_Read returned: 4" and "Error: ft2232.c:365 ft2232_send_and_recv(): couldn't read from FT2232". What does that mean and what might be the reason for this? First of all, the reason might be the USB power supply. Try using a self-powered hub instead of a direct connection to your computer. Secondly, the error code 4 corresponds to an FT_IO_ERROR, which means that the driver for the FTDI USB chip ran into some sort of error - this points us to a USB problem. 11. GDB Disconnects When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following error message: "Error: gdb_server.c:101 gdb_get_char(): read: 10054". What does that mean and what might be the reason for this? Error code 10054 corresponds to WSAECONNRESET, which means that the debugger (GDB) has closed the connection to OpenOCD. This might be a GDB issue. 12. LPC2000 Flash In the configuration file in the section where flash device configurations are described, there is a parameter for specifying the clock frequency for LPC2000 internal flash devices (e.g. 'flash bank $_FLASHNAME lpc2000 0x0 0x40000 0 0 $_TARGETNAME lpc2000_v1 14746 calc_checksum'), which must be specified in kilohertz. However, I do have a quartz crystal of a frequency that contains fractions of kilohertz (e.g. 14,745,600 Hz, i.e. 14,745.600 kHz). Is it possible to specify real numbers for the clock frequency? No. The clock frequency specified here must be given as an integral number. However, this clock frequency is used by the In-Application-Programming (IAP) routines of the LPC2000 family only, which seems to be very tolerant concerning the given clock frequency, so a slight difference between the specified clock frequency and the actual clock frequency will not cause any trouble. 13. Command Order Do I have to keep a specific order for the commands in the configuration file? Well, yes and no. Commands can be given in arbitrary order, yet the devices listed for the JTAG scan chain must be given in the right order (jtag newdevice), with the device closest to the TDO-Pin being listed first. In general, whenever objects of the same type exist which require an index number, then these objects must be given in the right order (jtag newtap, targets and flash banks - a target references a jtag newtap and a flash bank references a target). You can use the "scan_chain" command to verify and display the tap order. Also, some commands can't execute until after 'init' has been processed. Such commands include 'nand probe' and everything else that needs to write to controller registers, perhaps for setting up DRAM and loading it with code. 14. JTAG TAP Order Do I have to declare the TAPS in some particular order? Yes; whenever you have more than one, you must declare them in the same order used by the hardware. Many newer devices have multiple JTAG TAPs. For example: ST Microsystems STM32 chips have two TAPs, a "boundary scan TAP" and "Cortex-M3" TAP. Example: The STM32 reference manual, Document ID: RM0008, Section 26.5, Figure 259, page 651/681, the "TDI" pin is connected to the boundary scan TAP, which then connects to the Cortex-M3 TAP, which then connects to the TDO pin. Thus, the proper order for the STM32 chip is: (1) The Cortex-M3, then (2) The boundary scan TAP. If your board includes an additional JTAG chip in the scan chain (for example a Xilinx CPLD or FPGA) you could place it before or after the STM32 chip in the chain. For example: * OpenOCD_TDI(output) -> STM32 TDI Pin (BS Input) * STM32 BS TDO (output) -> STM32 Cortex-M3 TDI (input) * STM32 Cortex-M3 TDO (output) -> SM32 TDO Pin * STM32 TDO Pin (output) -> Xilinx TDI Pin (input) * Xilinx TDO Pin -> OpenOCD TDO (input) The "jtag device" commands would thus be in the order shown below. Note: * jtag newtap Xilinx tap -irlen ... * jtag newtap stm32 cpu -irlen ... * jtag newtap stm32 bs -irlen ... * # Create the debug target and say where it is * target create stm32.cpu -chain-position stm32.cpu ... 15. SYSCOMP Sometimes my debugging session terminates with an error. When I look into the log file, I can see these error messages: Error: arm7_9_common.c:561 arm7_9_execute_sys_speed(): timeout waiting for SYSCOMP TODO.  File: openocd.info, Node: Tcl Crash Course, Next: License, Prev: FAQ, Up: Top 24 Tcl Crash Course ******************* Not everyone knows Tcl - this is not intended to be a replacement for learning Tcl, the intent of this chapter is to give you some idea of how the Tcl scripts work. This chapter is written with two audiences in mind. (1) OpenOCD users who need to understand a bit more of how Jim-Tcl works so they can do something useful, and (2) those that want to add a new command to OpenOCD. 24.1 Tcl Rule #1 ================ There is a famous joke, it goes like this: 1. Rule #1: The wife is always correct 2. Rule #2: If you think otherwise, See Rule #1 The Tcl equal is this: 1. Rule #1: Everything is a string 2. Rule #2: If you think otherwise, See Rule #1 As in the famous joke, the consequences of Rule #1 are profound. Once you understand Rule #1, you will understand Tcl. 24.2 Tcl Rule #1b ================= There is a second pair of rules. 1. Rule #1: Control flow does not exist. Only commands For example: the classic FOR loop or IF statement is not a control flow item, they are commands, there is no such thing as control flow in Tcl. 2. Rule #2: If you think otherwise, See Rule #1 Actually what happens is this: There are commands that by convention, act like control flow key words in other languages. One of those commands is the word "for", another command is "if". 24.3 Per Rule #1 - All Results are strings ========================================== Every Tcl command results in a string. The word "result" is used deliberatly. No result is just an empty string. Remember: Rule #1 - Everything is a string 24.4 Tcl Quoting Operators ========================== In life of a Tcl script, there are two important periods of time, the difference is subtle. 1. Parse Time 2. Evaluation Time The two key items here are how "quoted things" work in Tcl. Tcl has three primary quoting constructs, the [square-brackets] the {curly-braces} and "double-quotes" By now you should know $VARIABLES always start with a $DOLLAR sign. BTW: To set a variable, you actually use the command "set", as in "set VARNAME VALUE" much like the ancient BASIC langauge "let x = 1" statement, but without the equal sign. * [square-brackets] [square-brackets] are command substitutions. It operates much like Unix Shell 'back-ticks'. The result of a [square-bracket] operation is exactly 1 string. Remember Rule #1 - Everything is a string. These two statements are roughly identical: # bash example X=`date` echo "The Date is: $X" # Tcl example set X [date] puts "The Date is: $X" * "double-quoted-things" "double-quoted-things" are just simply quoted text. $VARIABLES and [square-brackets] are expanded in place - the result however is exactly 1 string. Remember Rule #1 - Everything is a string set x "Dinner" puts "It is now \"[date]\", $x is in 1 hour" * {Curly-Braces} {Curly-Braces} are magic: $VARIABLES and [square-brackets] are parsed, but are NOT expanded or executed. {Curly-Braces} are like 'single-quote' operators in BASH shell scripts, with the added feature: {curly-braces} can be nested, single quotes can not. {{{this is nested 3 times}}} NOTE: [date] is a bad example; at this writing, Jim/OpenOCD does not have a date command. 24.5 Consequences of Rule 1/2/3/4 ================================= The consequences of Rule 1 are profound. 24.5.1 Tokenisation & Execution. -------------------------------- Of course, whitespace, blank lines and #comment lines are handled in the normal way. As a script is parsed, each (multi) line in the script file is tokenised and according to the quoting rules. After tokenisation, that line is immedatly executed. Multi line statements end with one or more "still-open" {curly-braces} which - eventually - closes a few lines later. 24.5.2 Command Execution ------------------------ Remember earlier: There are no "control flow" statements in Tcl. Instead there are COMMANDS that simply act like control flow operators. Commands are executed like this: 1. Parse the next line into (argc) and (argv[]). 2. Look up (argv[0]) in a table and call its function. 3. Repeat until End Of File. It sort of works like this: for(;;){ ReadAndParse( &argc, &argv ); cmdPtr = LookupCommand( argv[0] ); (*cmdPtr->Execute)( argc, argv ); } When the command "proc" is parsed (which creates a procedure function) it gets 3 parameters on the command line. 1 the name of the proc (function), 2 the list of parameters, and 3 the body of the function. Not the choice of words: LIST and BODY. The PROC command stores these items in a table somewhere so it can be found by "LookupCommand()" 24.5.3 The FOR command ---------------------- The most interesting command to look at is the FOR command. In Tcl, the FOR command is normally implemented in C. Remember, FOR is a command just like any other command. When the ascii text containing the FOR command is parsed, the parser produces 5 parameter strings, (If in doubt: Refer to Rule #1) they are: 0. The ascii text 'for' 1. The start text 2. The test expression 3. The next text 4. The body text Sort of reminds you of "main( int argc, char **argv )" does it not? Remember Rule #1 - Everything is a string. The key point is this: Often many of those parameters are in {curly-braces} - thus the variables inside are not expanded or replaced until later. Remember that every Tcl command looks like the classic "main( argc, argv )" function in C. In JimTCL - they actually look like this: int MyCommand( Jim_Interp *interp, int *argc, Jim_Obj * const *argvs ); Real Tcl is nearly identical. Although the newer versions have introduced a byte-code parser and intepreter, but at the core, it still operates in the same basic way. 24.5.4 FOR command implementation --------------------------------- To understand Tcl it is perhaps most helpful to see the FOR command. Remember, it is a COMMAND not a control flow structure. In Tcl there are two underlying C helper functions. Remember Rule #1 - You are a string. The first helper parses and executes commands found in an ascii string. Commands can be seperated by semicolons, or newlines. While parsing, variables are expanded via the quoting rules. The second helper evaluates an ascii string as a numerical expression and returns a value. Here is an example of how the FOR command could be implemented. The pseudo code below does not show error handling. void Execute_AsciiString( void *interp, const char *string ); int Evaluate_AsciiExpression( void *interp, const char *string ); int MyForCommand( void *interp, int argc, char **argv ) { if( argc != 5 ){ SetResult( interp, "WRONG number of parameters"); return ERROR; } // argv[0] = the ascii string just like C // Execute the start statement. Execute_AsciiString( interp, argv[1] ); // Top of loop test for(;;){ i = Evaluate_AsciiExpression(interp, argv[2]); if( i == 0 ) break; // Execute the body Execute_AsciiString( interp, argv[3] ); // Execute the LOOP part Execute_AsciiString( interp, argv[4] ); } // Return no error SetResult( interp, "" ); return SUCCESS; } Every other command IF, WHILE, FORMAT, PUTS, EXPR, everything works in the same basic way. 24.6 OpenOCD Tcl Usage ====================== 24.6.1 source and find commands ------------------------------- Where: In many configuration files Example: source [find FILENAME] Remember the parsing rules 1. The 'find' command is in square brackets, and is executed with the parameter FILENAME. It should find and return the full path to a file with that name; it uses an internal search path. The RESULT is a string, which is substituted into the command line in place of the bracketed 'find' command. (Don't try to use a FILENAME which includes the "#" character. That character begins Tcl comments.) 2. The 'source' command is executed with the resulting filename; it reads a file and executes as a script. 24.6.2 format command --------------------- Where: Generally occurs in numerous places. Tcl has no command like printf(), instead it has format, which is really more like sprintf(). Example set x 6 set y 7 puts [format "The answer: %d" [expr $x * $y]] 1. The SET command creates 2 variables, X and Y. 2. The double [nested] EXPR command performs math The EXPR command produces numerical result as a string. Refer to Rule #1 3. The format command is executed, producing a single string Refer to Rule #1. 4. The PUTS command outputs the text. 24.6.3 Body or Inlined Text --------------------------- Where: Various TARGET scripts. #1 Good proc someproc {} { ... multiple lines of stuff ... } $_TARGETNAME configure -event FOO someproc #2 Good - no variables $_TARGETNAME confgure -event foo "this ; that;" #3 Good Curly Braces $_TARGETNAME configure -event FOO { puts "Time: [date]" } #4 DANGER DANGER DANGER $_TARGETNAME configure -event foo "puts \"Time: [date]\"" 1. The $_TARGETNAME is an OpenOCD variable convention. $_TARGETNAME represents the last target created, the value changes each time a new target is created. Remember the parsing rules. When the ascii text is parsed, the $_TARGETNAME becomes a simple string, the name of the target which happens to be a TARGET (object) command. 2. The 2nd parameter to the '-event' parameter is a TCBODY There are 4 examples: 1. The TCLBODY is a simple string that happens to be a proc name 2. The TCLBODY is several simple commands seperated by semicolons 3. The TCLBODY is a multi-line {curly-brace} quoted string 4. The TCLBODY is a string with variables that get expanded. In the end, when the target event FOO occurs the TCLBODY is evaluated. Method #1 and #2 are functionally identical. For Method #3 and #4 it is more interesting. What is the TCLBODY? Remember the parsing rules. In case #3, {curly-braces} mean the $VARS and [square-brackets] are expanded later, when the EVENT occurs, and the text is evaluated. In case #4, they are replaced before the "Target Object Command" is executed. This occurs at the same time $_TARGETNAME is replaced. In case #4 the date will never change. {BTW: [date] is a bad example; at this writing, Jim/OpenOCD does not have a date command} 24.6.4 Global Variables ----------------------- Where: You might discover this when writing your own procs In simple terms: Inside a PROC, if you need to access a global variable you must say so. See also "upvar". Example: proc myproc { } { set y 0 #Local variable Y global x #Global variable X puts [format "X=%d, Y=%d" $x $y] } 24.7 Other Tcl Hacks ==================== Dynamic variable creation # Dynamically create a bunch of variables. for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { # Create var name set vn [format "BIT%d" $x] # Make it a global global $vn # Set it. set $vn [expr (1 << $x)] } Dynamic proc/command creation # One "X" function - 5 uart functions. foreach who {A B C D E} proc [format "show_uart%c" $who] { } "show_UARTx $who" }  File: openocd.info, Node: License, Next: OpenOCD Concept Index, Prev: Tcl Crash Course, Up: Top Appendix A The GNU Free Documentation License. ********************************************** Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See . Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents ==================================================== To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (C) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.  File: openocd.info, Node: OpenOCD Concept Index, Next: Command and Driver Index, Prev: License, Up: Top OpenOCD Concept Index ********************* [index] * Menu: * about: About. (line 6) * adaptive clocking: Debug Adapter Configuration. (line 741) * adaptive clocking <1>: FAQ. (line 6) * Architecture Specific Commands: Architecture and Core Commands. (line 6) * ARM: Architecture and Core Commands. (line 244) * ARM semihosting: OpenOCD Project Setup. (line 314) * ARM semihosting <1>: Architecture and Core Commands. (line 285) * ARM11: Architecture and Core Commands. (line 585) * ARM7: Architecture and Core Commands. (line 305) * ARM720T: Architecture and Core Commands. (line 343) * ARM9: Architecture and Core Commands. (line 305) * ARM9 <1>: Architecture and Core Commands. (line 359) * ARM920T: Architecture and Core Commands. (line 379) * ARM926ej-s: Architecture and Core Commands. (line 414) * ARM966E: Architecture and Core Commands. (line 428) * ARMv4: Architecture and Core Commands. (line 298) * ARMv5: Architecture and Core Commands. (line 298) * ARMv6: Architecture and Core Commands. (line 581) * ARMv7: Architecture and Core Commands. (line 618) * at91sam3: Flash Commands. (line 367) * at91sam4: Flash Commands. (line 422) * at91sam4l: Flash Commands. (line 427) * at91samd: Flash Commands. (line 323) * autoprobe: TAP Declaration. (line 309) * board config file: Config File Guidelines. (line 60) * breakpoint: General Commands. (line 313) * CFI: Flash Commands. (line 234) * command line options: Running. (line 6) * commands: General Commands. (line 6) * Common Flash Interface: Flash Commands. (line 234) * config command: Daemon Configuration. (line 13) * config file, board: Config File Guidelines. (line 60) * config file, interface: Debug Adapter Configuration. (line 6) * config file, overview: OpenOCD Project Setup. (line 139) * config file, target: Config File Guidelines. (line 287) * config file, user: OpenOCD Project Setup. (line 139) * configuration stage: Daemon Configuration. (line 13) * Connecting to GDB: GDB and OpenOCD. (line 27) * Core Specific Commands: Architecture and Core Commands. (line 6) * Cortex-M: Architecture and Core Commands. (line 727) * CPU type: CPU Configuration. (line 60) * DAP: Architecture and Core Commands. (line 622) * DCC: Architecture and Core Commands. (line 321) * DCC <1>: Architecture and Core Commands. (line 868) * Debug Access Port: Architecture and Core Commands. (line 622) * developers: Developers. (line 6) * directory search: Running. (line 6) * disassemble: Architecture and Core Commands. (line 255) * dongles: Debug Adapter Hardware. (line 6) * dotted name: TAP Declaration. (line 98) * ETB: Architecture and Core Commands. (line 14) * ETM: Architecture and Core Commands. (line 14) * ETM <1>: Architecture and Core Commands. (line 653) * event, reset-init: Config File Guidelines. (line 176) * events: Reset Configuration. (line 226) * events <1>: TAP Declaration. (line 208) * events <2>: CPU Configuration. (line 339) * faq: FAQ. (line 6) * Firmware recovery: Utility Commands. (line 45) * flash configuration: Flash Commands. (line 36) * flash erasing: Flash Commands. (line 87) * flash programming: Flash Commands. (line 87) * flash protection: Flash Commands. (line 179) * flash reading: Flash Commands. (line 87) * flash writing: Flash Commands. (line 87) * FPGA: PLD/FPGA Commands. (line 6) * FTDI: Debug Adapter Hardware. (line 6) * GDB: Daemon Configuration. (line 131) * GDB <1>: GDB and OpenOCD. (line 6) * GDB configuration: Daemon Configuration. (line 131) * GDB server: Daemon Configuration. (line 91) * GDB target: CPU Configuration. (line 6) * halt: General Commands. (line 78) * image dumping: General Commands. (line 264) * image loading: General Commands. (line 264) * initialization: Daemon Configuration. (line 6) * init_board procedure: Config File Guidelines. (line 241) * init_targets procedure: Config File Guidelines. (line 510) * init_target_events procedure: Config File Guidelines. (line 555) * interface config file: Debug Adapter Configuration. (line 6) * ITM: Architecture and Core Commands. (line 653) * Jim-Tcl: About Jim-Tcl. (line 6) * jrc: TAP Declaration. (line 246) * JTAG: About. (line 15) * JTAG <1>: Debug Adapter Configuration. (line 651) * JTAG autoprobe: TAP Declaration. (line 309) * JTAG Commands: JTAG Commands. (line 6) * JTAG Route Controller: TAP Declaration. (line 246) * libdcc: Architecture and Core Commands. (line 868) * Linux-ARM DCC support: Architecture and Core Commands. (line 868) * logfile: Running. (line 6) * lpcspifi: Flash Commands. (line 265) * memory access: General Commands. (line 231) * message level: General Commands. (line 55) * mFlash commands: Flash Commands. (line 1376) * mFlash Configuration: Flash Commands. (line 1360) * NAND: Flash Commands. (line 996) * NAND configuration: Flash Commands. (line 1051) * NAND erasing: Flash Commands. (line 1131) * NAND other commands: Flash Commands. (line 1222) * NAND programming: Flash Commands. (line 1131) * NAND programming <1>: Flash Commands. (line 1144) * NAND programming <2>: Flash Commands. (line 1197) * NAND reading: Flash Commands. (line 1098) * NAND verification: Flash Commands. (line 1197) * NAND writing: Flash Commands. (line 1144) * NXP SPI Flash Interface: Flash Commands. (line 265) * object command: CPU Configuration. (line 233) * PLD: PLD/FPGA Commands. (line 6) * port: Daemon Configuration. (line 81) * printer port: Debug Adapter Hardware. (line 6) * profiling: General Commands. (line 345) * Programming using GDB: GDB and OpenOCD. (line 126) * RAM testing: Utility Commands. (line 9) * reset: General Commands. (line 78) * Reset Configuration: Reset Configuration. (line 6) * reset-init handler: Config File Guidelines. (line 176) * RPC: Tcl Scripting API. (line 100) * RPC Notifications: Tcl Scripting API. (line 118) * RTCK: Debug Adapter Hardware. (line 6) * RTCK <1>: Debug Adapter Configuration. (line 741) * RTCK <2>: FAQ. (line 6) * RTOS Support: GDB and OpenOCD. (line 204) * scan chain: TAP Declaration. (line 28) * security: Daemon Configuration. (line 81) * Serial Peripheral Interface: Debug Adapter Configuration. (line 684) * Serial Vector Format: Boundary Scan Commands. (line 13) * Serial Wire Debug: Debug Adapter Configuration. (line 664) * server: Daemon Configuration. (line 81) * SMI: Flash Commands. (line 282) * SMP: Config File Guidelines. (line 414) * SMP <1>: GDB and OpenOCD. (line 164) * SPI: Debug Adapter Configuration. (line 684) * SPIFI: Flash Commands. (line 265) * STMicroelectronics Serial Memory Interface: Flash Commands. (line 282) * stmsmi: Flash Commands. (line 282) * str9xpec: Flash Commands. (line 835) * SVF: Boundary Scan Commands. (line 13) * SWD: Debug Adapter Configuration. (line 664) * SWO: Architecture and Core Commands. (line 653) * SWV: Architecture and Core Commands. (line 653) * TAP: About. (line 15) * TAP configuration: TAP Declaration. (line 6) * TAP declaration: TAP Declaration. (line 6) * TAP events: TAP Declaration. (line 208) * TAP naming convention: TAP Declaration. (line 121) * TAP state names: JTAG Commands. (line 142) * target config file: Config File Guidelines. (line 287) * target events: CPU Configuration. (line 339) * target initialization: General Commands. (line 78) * target type: CPU Configuration. (line 60) * target, current: CPU Configuration. (line 18) * target, list: CPU Configuration. (line 18) * tcl: About Jim-Tcl. (line 6) * Tcl: Tcl Crash Course. (line 6) * Tcl Scripting API: Tcl Scripting API. (line 6) * Tcl scripts: Tcl Scripting API. (line 5) * TCP port: Daemon Configuration. (line 81) * TFTP: TFTP. (line 6) * TPIU: Architecture and Core Commands. (line 653) * tracing: Architecture and Core Commands. (line 14) * tracing <1>: Architecture and Core Commands. (line 653) * tracing <2>: Architecture and Core Commands. (line 868) * translation: Config File Guidelines. (line 600) * Transport: Debug Adapter Configuration. (line 625) * USB Adapter: Debug Adapter Hardware. (line 6) * user config file: OpenOCD Project Setup. (line 139) * Utility Commands: Utility Commands. (line 5) * variable names: Config File Guidelines. (line 144) * vector_catch: OpenOCD Project Setup. (line 213) * vector_catch <1>: Architecture and Core Commands. (line 364) * vector_catch <2>: Architecture and Core Commands. (line 554) * vector_catch <3>: Architecture and Core Commands. (line 607) * vector_catch <4>: Architecture and Core Commands. (line 746) * vector_table: Architecture and Core Commands. (line 569) * watchpoint: General Commands. (line 313) * wiggler: Debug Adapter Hardware. (line 6) * Xilinx Serial Vector Format: Boundary Scan Commands. (line 25) * XScale: Architecture and Core Commands. (line 442) * XSVF: Boundary Scan Commands. (line 25) * zy1000: Debug Adapter Hardware. (line 6)  File: openocd.info, Node: Command and Driver Index, Prev: OpenOCD Concept Index, Up: Top Command and Driver Index ************************ [index] * Menu: * $target_name arp_examine: CPU Configuration. (line 258) * $target_name arp_halt: CPU Configuration. (line 259) * $target_name arp_poll: CPU Configuration. (line 260) * $target_name arp_reset: CPU Configuration. (line 261) * $target_name arp_waitstate: CPU Configuration. (line 262) * $target_name array2mem: CPU Configuration. (line 267) * $target_name cget: CPU Configuration. (line 285) * $target_name configure: CPU Configuration. (line 184) * $target_name curstate: CPU Configuration. (line 308) * $target_name eventlist: CPU Configuration. (line 313) * $target_name invoke-event: CPU Configuration. (line 317) * $target_name mdb: CPU Configuration. (line 324) * $target_name mdh: CPU Configuration. (line 323) * $target_name mdw: CPU Configuration. (line 322) * $target_name mem2array: CPU Configuration. (line 268) * $target_name mwb: CPU Configuration. (line 332) * $target_name mwh: CPU Configuration. (line 331) * $target_name mww: CPU Configuration. (line 330) * adapter_khz: Debug Adapter Configuration. (line 724) * adapter_name: Debug Adapter Configuration. (line 54) * adapter_nsrst_assert_width: Reset Configuration. (line 121) * adapter_nsrst_delay: Reset Configuration. (line 126) * addreg: Architecture and Core Commands. (line 845) * add_script_search_dir: General Commands. (line 72) * aduc702x: Flash Commands. (line 313) * amt_jtagaccel: Debug Adapter Configuration. (line 63) * append_file: General Commands. (line 192) * arm core_state: Architecture and Core Commands. (line 248) * arm disassemble: Architecture and Core Commands. (line 254) * arm mcr: Architecture and Core Commands. (line 268) * arm mrc: Architecture and Core Commands. (line 274) * arm reg: Architecture and Core Commands. (line 280) * arm semihosting: Architecture and Core Commands. (line 284) * arm-jtag-ew: Debug Adapter Configuration. (line 76) * arm11 memwrite burst: Architecture and Core Commands. (line 585) * arm11 memwrite error_fatal: Architecture and Core Commands. (line 595) * arm11 step_irq_enable: Architecture and Core Commands. (line 601) * arm11 vcr: Architecture and Core Commands. (line 606) * arm720t cp15: Architecture and Core Commands. (line 348) * arm7_9 dbgrq: Architecture and Core Commands. (line 310) * arm7_9 dcc_downloads: Architecture and Core Commands. (line 320) * arm7_9 fast_memory_access: Architecture and Core Commands. (line 331) * arm9 vector_catch: Architecture and Core Commands. (line 363) * arm920t cache_info: Architecture and Core Commands. (line 384) * arm920t cp15: Architecture and Core Commands. (line 389) * arm920t cp15i: Architecture and Core Commands. (line 395) * arm920t read_cache: Architecture and Core Commands. (line 405) * arm920t read_mmu: Architecture and Core Commands. (line 408) * arm926ejs cache_info: Architecture and Core Commands. (line 422) * arm966e cp15: Architecture and Core Commands. (line 432) * armjtagew_info: Debug Adapter Configuration. (line 80) * at91rm9200: Debug Adapter Configuration. (line 83) * at91sam3: Flash Commands. (line 366) * at91sam3 gpnvm: Flash Commands. (line 398) * at91sam3 gpnvm clear: Flash Commands. (line 399) * at91sam3 gpnvm set: Flash Commands. (line 400) * at91sam3 gpnvm show: Flash Commands. (line 401) * at91sam3 info: Flash Commands. (line 407) * at91sam3 slowclk: Flash Commands. (line 417) * at91sam4: Flash Commands. (line 421) * at91sam4l: Flash Commands. (line 426) * at91sam4l smap_reset_deassert: Flash Commands. (line 432) * at91sam7: Flash Commands. (line 437) * at91sam7 gpnvm: Flash Commands. (line 470) * at91sam9: Flash Commands. (line 1263) * at91sam9 ale: Flash Commands. (line 1277) * at91sam9 ce: Flash Commands. (line 1288) * at91sam9 cle: Flash Commands. (line 1274) * at91sam9 rdy_busy: Flash Commands. (line 1283) * at91samd: Flash Commands. (line 322) * at91samd bootloader: Flash Commands. (line 354) * at91samd chip-erase: Flash Commands. (line 324) * at91samd eeprom: Flash Commands. (line 340) * at91samd set-security: Flash Commands. (line 329) * avr: Flash Commands. (line 478) * bcm2835gpio: Debug Adapter Configuration. (line 608) * bp: General Commands. (line 317) * cat: General Commands. (line 197) * cfi: Flash Commands. (line 233) * cmsis-dap: Debug Adapter Configuration. (line 87) * cmsis-dap info: Debug Adapter Configuration. (line 101) * cmsis_dap_serial: Debug Adapter Configuration. (line 97) * cmsis_dap_vid_pid: Debug Adapter Configuration. (line 90) * cortex_m maskisr: Architecture and Core Commands. (line 727) * cortex_m reset_config: Architecture and Core Commands. (line 761) * cortex_m vector_catch: Architecture and Core Commands. (line 745) * cp: General Commands. (line 200) * dap apcsw: Architecture and Core Commands. (line 646) * dap apid: Architecture and Core Commands. (line 626) * dap apsel: Architecture and Core Commands. (line 630) * dap baseaddr: Architecture and Core Commands. (line 633) * dap info: Architecture and Core Commands. (line 637) * dap memaccess: Architecture and Core Commands. (line 641) * davinci: Flash Commands. (line 1294) * debug_level: General Commands. (line 54) * drscan: JTAG Commands. (line 42) * dummy: Debug Adapter Configuration. (line 105) * dummy <1>: Architecture and Core Commands. (line 190) * dump_image: General Commands. (line 264) * du_select: Architecture and Core Commands. (line 832) * echo: General Commands. (line 63) * efm32: Flash Commands. (line 482) * ep93xx: Debug Adapter Configuration. (line 108) * etb: Architecture and Core Commands. (line 198) * etb config: Architecture and Core Commands. (line 201) * etb trigger_percent: Architecture and Core Commands. (line 204) * etm analyze: Architecture and Core Commands. (line 166) * etm config: Architecture and Core Commands. (line 63) * etm dump: Architecture and Core Commands. (line 170) * etm image: Architecture and Core Commands. (line 173) * etm info: Architecture and Core Commands. (line 89) * etm load: Architecture and Core Commands. (line 176) * etm start: Architecture and Core Commands. (line 179) * etm status: Architecture and Core Commands. (line 95) * etm stop: Architecture and Core Commands. (line 182) * etm tracemode: Architecture and Core Commands. (line 100) * etm trigger_debug: Architecture and Core Commands. (line 119) * etm_dummy config: Architecture and Core Commands. (line 195) * exit: General Commands. (line 30) * fast_load: General Commands. (line 268) * fast_load_image: General Commands. (line 272) * flash bank: Flash Commands. (line 36) * flash banks: Flash Commands. (line 67) * flash erase_address: Flash Commands. (line 120) * flash erase_check: Flash Commands. (line 179) * flash erase_sector: Flash Commands. (line 114) * flash fillb: Flash Commands. (line 133) * flash fillh: Flash Commands. (line 132) * flash fillw: Flash Commands. (line 131) * flash info: Flash Commands. (line 183) * flash list: Flash Commands. (line 72) * flash padded_value: Flash Commands. (line 195) * flash probe: Flash Commands. (line 77) * flash protect: Flash Commands. (line 188) * flash write_bank: Flash Commands. (line 143) * flash write_image: Flash Commands. (line 148) * flush_count: JTAG Commands. (line 70) * fm3: Flash Commands. (line 930) * ft2232: Debug Adapter Configuration. (line 112) * ft2232_channel: Debug Adapter Configuration. (line 189) * ft2232_device_desc: Debug Adapter Configuration. (line 122) * ft2232_latency: Debug Adapter Configuration. (line 178) * ft2232_layout: Debug Adapter Configuration. (line 136) * ft2232_serial: Debug Adapter Configuration. (line 128) * ft2232_vid_pid: Debug Adapter Configuration. (line 172) * ftdi: Debug Adapter Configuration. (line 201) * ftdi_channel: Debug Adapter Configuration. (line 259) * ftdi_device_desc: Debug Adapter Configuration. (line 246) * ftdi_layout_init: Debug Adapter Configuration. (line 264) * ftdi_layout_signal: Debug Adapter Configuration. (line 274) * ftdi_serial: Debug Adapter Configuration. (line 251) * ftdi_set_signal: Debug Adapter Configuration. (line 308) * ftdi_vid_pid: Debug Adapter Configuration. (line 240) * gdb_breakpoint_override: Daemon Configuration. (line 136) * gdb_flash_program: Daemon Configuration. (line 143) * gdb_memory_map: Daemon Configuration. (line 147) * gdb_port: Daemon Configuration. (line 90) * gdb_report_data_abort: Daemon Configuration. (line 155) * gdb_save_tdesc: Daemon Configuration. (line 165) * gdb_target_description: Daemon Configuration. (line 160) * gw16012: Debug Adapter Configuration. (line 388) * halt: General Commands. (line 118) * help: General Commands. (line 33) * hla: Debug Adapter Configuration. (line 566) * hla_command: Debug Adapter Configuration. (line 589) * hla_device_desc: Debug Adapter Configuration. (line 577) * hla_layout: Debug Adapter Configuration. (line 583) * hla_serial: Debug Adapter Configuration. (line 580) * hla_vid_pid: Debug Adapter Configuration. (line 586) * init: Daemon Configuration. (line 47) * init_reset: Reset Configuration. (line 257) * interface: Debug Adapter Configuration. (line 42) * interface transports: Debug Adapter Configuration. (line 48) * interface_list: Debug Adapter Configuration. (line 45) * ip: General Commands. (line 203) * irscan: JTAG Commands. (line 81) * itm port: Architecture and Core Commands. (line 717) * itm ports: Architecture and Core Commands. (line 721) * jlink: Debug Adapter Configuration. (line 398) * jlink caps: Debug Adapter Configuration. (line 415) * jlink config: Debug Adapter Configuration. (line 423) * jlink config ip: Debug Adapter Configuration. (line 431) * jlink config kickstart: Debug Adapter Configuration. (line 425) * jlink config mac_address: Debug Adapter Configuration. (line 428) * jlink config reset: Debug Adapter Configuration. (line 438) * jlink config save: Debug Adapter Configuration. (line 440) * jlink config usb_address: Debug Adapter Configuration. (line 435) * jlink hw_jtag: Debug Adapter Configuration. (line 420) * jlink info: Debug Adapter Configuration. (line 417) * jlink pid: Debug Adapter Configuration. (line 443) * jlink serial: Debug Adapter Configuration. (line 446) * jtag arp_init: Reset Configuration. (line 275) * jtag arp_init-reset: Reset Configuration. (line 285) * jtag cget: TAP Declaration. (line 194) * jtag configure: TAP Declaration. (line 195) * jtag names: TAP Declaration. (line 81) * jtag newtap: TAP Declaration. (line 113) * jtag tapdisable: TAP Declaration. (line 289) * jtag tapenable: TAP Declaration. (line 294) * jtag tapisenabled: TAP Declaration. (line 299) * jtag_init: Daemon Configuration. (line 65) * jtag_ntrst_assert_width: Reset Configuration. (line 133) * jtag_ntrst_delay: Reset Configuration. (line 138) * jtag_rclk: Debug Adapter Configuration. (line 740) * jtag_reset: JTAG Commands. (line 98) * load_image: General Commands. (line 283) * log_output: General Commands. (line 68) * lpc2000: Flash Commands. (line 491) * lpc2000 part_id: Flash Commands. (line 529) * lpc288x: Flash Commands. (line 533) * lpc2900: Flash Commands. (line 541) * lpc2900 password: Flash Commands. (line 597) * lpc2900 read_custom: Flash Commands. (line 586) * lpc2900 secure_jtag: Flash Commands. (line 632) * lpc2900 secure_sector: Flash Commands. (line 618) * lpc2900 signature: Flash Commands. (line 577) * lpc2900 write_custom: Flash Commands. (line 607) * lpc3180: Flash Commands. (line 1307) * lpc3180 select: Flash Commands. (line 1310) * lpcspifi: Flash Commands. (line 264) * ls: General Commands. (line 206) * mac: General Commands. (line 209) * mdb: General Commands. (line 243) * mdh: General Commands. (line 242) * mdr: Flash Commands. (line 972) * mdw: General Commands. (line 241) * meminfo: General Commands. (line 212) * memTestAddressBus: Utility Commands. (line 29) * memTestDataBus: Utility Commands. (line 25) * memTestDevice: Utility Commands. (line 34) * mflash bank: Flash Commands. (line 1360) * mflash config boot: Flash Commands. (line 1383) * mflash config pll: Flash Commands. (line 1376) * mflash config storage: Flash Commands. (line 1387) * mflash dump: Flash Commands. (line 1391) * mflash probe: Flash Commands. (line 1395) * mflash write: Flash Commands. (line 1398) * mrvlqspi: Flash Commands. (line 301) * mwb: General Commands. (line 254) * mwh: General Commands. (line 253) * mww: General Commands. (line 252) * mx3: Flash Commands. (line 1320) * mxc: Flash Commands. (line 1324) * mxc biswap: Flash Commands. (line 1332) * nand check_bad_blocks: Flash Commands. (line 1222) * nand device: Flash Commands. (line 1054) * nand dump: Flash Commands. (line 1097) * nand erase: Flash Commands. (line 1130) * nand info: Flash Commands. (line 1234) * nand list: Flash Commands. (line 1077) * nand probe: Flash Commands. (line 1087) * nand raw_access: Flash Commands. (line 1239) * nand verify: Flash Commands. (line 1196) * nand write: Flash Commands. (line 1143) * nrf51: Flash Commands. (line 958) * nrf51 mass_erase: Flash Commands. (line 966) * ocl: Flash Commands. (line 639) * oocd_trace: Architecture and Core Commands. (line 222) * oocd_trace config: Architecture and Core Commands. (line 231) * oocd_trace resync: Architecture and Core Commands. (line 235) * oocd_trace status: Architecture and Core Commands. (line 238) * opendous: Debug Adapter Configuration. (line 593) * orion: Flash Commands. (line 1336) * parport: Debug Adapter Configuration. (line 458) * parport_cable: Debug Adapter Configuration. (line 464) * parport_port: Debug Adapter Configuration. (line 68) * parport_port <1>: Debug Adapter Configuration. (line 392) * parport_port <2>: Debug Adapter Configuration. (line 493) * parport_toggling_time: Debug Adapter Configuration. (line 503) * parport_write_on_exit: Debug Adapter Configuration. (line 537) * pathmove: JTAG Commands. (line 115) * peek: General Commands. (line 216) * pic32mx: Flash Commands. (line 650) * pic32mx pgm_word: Flash Commands. (line 658) * pic32mx unlock: Flash Commands. (line 661) * pld device: PLD/FPGA Commands. (line 23) * pld devices: PLD/FPGA Commands. (line 28) * pld load: PLD/FPGA Commands. (line 31) * poke: General Commands. (line 219) * poll: Daemon Configuration. (line 205) * power: Debug Adapter Configuration. (line 605) * presto: Debug Adapter Configuration. (line 549) * presto_serial: Debug Adapter Configuration. (line 551) * profile: General Commands. (line 345) * program: Flash Commands. (line 201) * psoc4: Flash Commands. (line 665) * psoc4 flash_autoerase: Flash Commands. (line 677) * psoc4 mass_erase: Flash Commands. (line 690) * rbp: General Commands. (line 327) * readgroup: Architecture and Core Commands. (line 858) * reg: General Commands. (line 84) * remote_bitbang: Debug Adapter Configuration. (line 317) * remote_bitbang_host: Debug Adapter Configuration. (line 329) * remote_bitbang_port: Debug Adapter Configuration. (line 325) * reset: General Commands. (line 157) * reset halt: General Commands. (line 159) * reset init: General Commands. (line 160) * reset run: General Commands. (line 158) * reset_config: Reset Configuration. (line 143) * resume: General Commands. (line 148) * rlink: Debug Adapter Configuration. (line 554) * rm: General Commands. (line 222) * rtck: Debug Adapter Configuration. (line 72) * runAllMemTests: Utility Commands. (line 39) * runtest: JTAG Commands. (line 123) * rwp: General Commands. (line 330) * s3c2410: Flash Commands. (line 1344) * s3c2412: Flash Commands. (line 1345) * s3c2440: Flash Commands. (line 1346) * s3c2443: Flash Commands. (line 1347) * s3c6400: Flash Commands. (line 1348) * scan_chain: TAP Declaration. (line 89) * shutdown: General Commands. (line 49) * sim3x: Flash Commands. (line 939) * sim3x lock: Flash Commands. (line 955) * sim3x mass_erase: Flash Commands. (line 950) * sleep: General Commands. (line 43) * soft_reset_halt: General Commands. (line 175) * stellaris: Flash Commands. (line 696) * stellaris recover: Flash Commands. (line 705) * step: General Commands. (line 153) * stm32f1x: Flash Commands. (line 718) * stm32f1x lock: Flash Commands. (line 739) * stm32f1x options_read: Flash Commands. (line 747) * stm32f1x options_write: Flash Commands. (line 752) * stm32f1x unlock: Flash Commands. (line 743) * stm32f2x: Flash Commands. (line 757) * stm32f2x lock: Flash Commands. (line 772) * stm32f2x unlock: Flash Commands. (line 776) * stm32lx: Flash Commands. (line 780) * stm32lx mass_erase: Flash Commands. (line 797) * stmsmi: Flash Commands. (line 281) * str7x: Flash Commands. (line 803) * str7x disable_jtag: Flash Commands. (line 812) * str9x: Flash Commands. (line 816) * str9x flash_config: Flash Commands. (line 825) * str9xpec: Flash Commands. (line 834) * str9xpec disable_turbo: Flash Commands. (line 877) * str9xpec enable_turbo: Flash Commands. (line 880) * str9xpec lock: Flash Commands. (line 884) * str9xpec options_cmap: Flash Commands. (line 891) * str9xpec options_lvdsel: Flash Commands. (line 894) * str9xpec options_lvdthd: Flash Commands. (line 897) * str9xpec options_lvdwarn: Flash Commands. (line 900) * str9xpec options_read: Flash Commands. (line 903) * str9xpec options_write: Flash Commands. (line 906) * str9xpec part_id: Flash Commands. (line 888) * str9xpec unlock: Flash Commands. (line 909) * svf: Boundary Scan Commands. (line 17) * swd newdap: Debug Adapter Configuration. (line 674) * swd wcr trn prescale: Debug Adapter Configuration. (line 677) * tap_select: Architecture and Core Commands. (line 829) * target create: CPU Configuration. (line 162) * target current: CPU Configuration. (line 37) * target names: CPU Configuration. (line 40) * target types: CPU Configuration. (line 71) * targets: CPU Configuration. (line 46) * target_request debugmsgs: Architecture and Core Commands. (line 907) * tcl_notifications: Tcl Scripting API. (line 128) * tcl_port: Daemon Configuration. (line 114) * telnet_port: Daemon Configuration. (line 121) * test_image: General Commands. (line 298) * tms470: Flash Commands. (line 912) * tms470 flash_keyset: Flash Commands. (line 919) * tms470 osc_mhz: Flash Commands. (line 923) * tms470 plldis: Flash Commands. (line 926) * tpiu config: Architecture and Core Commands. (line 653) * trace history: Architecture and Core Commands. (line 917) * trace point: Architecture and Core Commands. (line 923) * transport list: Debug Adapter Configuration. (line 628) * transport select: Debug Adapter Configuration. (line 632) * trunc: General Commands. (line 225) * ulink: Debug Adapter Configuration. (line 596) * usbprog: Debug Adapter Configuration. (line 557) * usb_blaster: Debug Adapter Configuration. (line 348) * usb_blaster_device_desc: Debug Adapter Configuration. (line 354) * usb_blaster_firmware: Debug Adapter Configuration. (line 384) * usb_blaster_lowlevel_driver: Debug Adapter Configuration. (line 378) * usb_blaster_pin: Debug Adapter Configuration. (line 368) * usb_blaster_vid_pid: Debug Adapter Configuration. (line 360) * verify_image: General Commands. (line 304) * verify_ircapture: JTAG Commands. (line 128) * verify_jtag: JTAG Commands. (line 134) * version: General Commands. (line 351) * virt2phys: General Commands. (line 354) * virtex2: PLD/FPGA Commands. (line 42) * virtex2 read_stat: PLD/FPGA Commands. (line 48) * virtual: Flash Commands. (line 213) * vsllink: Debug Adapter Configuration. (line 560) * wait_halt: General Commands. (line 119) * wp: General Commands. (line 333) * x86_32 idb: Architecture and Core Commands. (line 804) * x86_32 idh: Architecture and Core Commands. (line 800) * x86_32 idw: Architecture and Core Commands. (line 796) * x86_32 iwb: Architecture and Core Commands. (line 816) * x86_32 iwh: Architecture and Core Commands. (line 812) * x86_32 iww: Architecture and Core Commands. (line 808) * xscale analyze_trace: Architecture and Core Commands. (line 514) * xscale cache_clean_address: Architecture and Core Commands. (line 517) * xscale cache_info: Architecture and Core Commands. (line 520) * xscale cp15: Architecture and Core Commands. (line 523) * xscale dcache: Architecture and Core Commands. (line 530) * xscale debug_handler: Architecture and Core Commands. (line 527) * xscale dump_trace: Architecture and Core Commands. (line 533) * xscale icache: Architecture and Core Commands. (line 536) * xscale mmu: Architecture and Core Commands. (line 539) * xscale trace_buffer: Architecture and Core Commands. (line 542) * xscale trace_image: Architecture and Core Commands. (line 547) * xscale vector_catch: Architecture and Core Commands. (line 553) * xscale vector_table: Architecture and Core Commands. (line 568) * xsvf: Boundary Scan Commands. (line 32) * ZY1000: Debug Adapter Configuration. (line 599) openocd-0.9.0/doc/openocd.info0000644000175000017500000000672612526202223013150 00000000000000This is openocd.info, produced by makeinfo version 5.2 from openocd.texi. This User's Guide documents release 0.9.0, dated 18 May 2015, of the Open On-Chip Debugger (OpenOCD). * Copyright (C) 2008 The OpenOCD Project * Copyright (C) 2007-2008 Spencer Oliver * Copyright (C) 2008-2010 Oyvind Harboe * Copyright (C) 2008 Duane Ellis * Copyright (C) 2009-2010 David Brownell Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". INFO-DIR-SECTION Development START-INFO-DIR-ENTRY * OpenOCD: (openocd). OpenOCD User's Guide END-INFO-DIR-ENTRY  Indirect: openocd.info-1: 991 openocd.info-2: 301182  Tag Table: (Indirect) Node: Top991 Node: About3495 Node: Developers7812 Node: Debug Adapter Hardware11150 Node: About Jim-Tcl22713 Node: Running24858 Node: OpenOCD Project Setup29955 Ref: OpenOCD Project Setup-Footnote-149898 Ref: OpenOCD Project Setup-Footnote-250238 Ref: OpenOCD Project Setup-Footnote-350506 Node: Config File Guidelines50834 Ref: theinitboardprocedure61708 Ref: definecputargetsworkinginsmp68497 Ref: theinittargetsprocedure72931 Ref: theinittargeteventsprocedure74749 Ref: translatingconfigurationfiles76602 Ref: Config File Guidelines-Footnote-177829 Node: Daemon Configuration77904 Ref: configurationstage78226 Ref: enteringtherunstage79078 Ref: tcpipports81527 Ref: gdbconfiguration83773 Ref: gdbbreakpointoverride84088 Ref: gdbflashprogram84463 Ref: eventpolling85691 Node: Debug Adapter Configuration88127 Ref: hla_interface114603 Ref: jtagspeed119560 Node: Reset Configuration122518 Ref: srstandtrstissues125446 Node: TAP Declaration137491 Ref: enablinganddisablingtaps148669 Ref: autoprobing151316 Ref: TAP Declaration-Footnote-1154007 Node: CPU Configuration154207 Ref: targettypes157101 Ref: targetconfiguration159483 Ref: rtostype164859 Ref: targetcurstate168276 Ref: targetevents169517 Node: Flash Commands174508 Ref: norconfiguration176040 Ref: flashprogrammingcommands178699 Ref: flashprotect184329 Ref: program184946 Ref: flashdriverlist185204 Ref: at91samd190178 Ref: at91sam3192240 Ref: nandconfiguration223081 Ref: nanddriverlist233468 Ref: Flash Commands-Footnote-1239868 Ref: Flash Commands-Footnote-2240034 Node: Flash Programming240199 Node: PLD/FPGA Commands241695 Node: General Commands243756 Ref: debuglevel245810 Ref: targetstatehandling246736 Ref: resetcommand250492 Ref: memoryaccess252762 Ref: imageaccess254389 Node: Architecture and Core Commands258887 Ref: armhardwaretracing259357 Ref: traceportdrivers267275 Ref: arm9vectorcatch275171 Ref: xscalevectorcatch283574 Ref: softwaredebugmessagesandtracing296724 Node: JTAG Commands301182 Node: Boundary Scan Commands309632 Node: Utility Commands312094 Node: TFTP313928 Node: GDB and OpenOCD314797 Ref: programmingusinggdb319692 Ref: usingopenocdsmpwithgdb321137 Ref: gdbrtossupport322605 Node: Tcl Scripting API324224 Node: FAQ328421 Ref: faqrtck328531 Ref: faqtaporder341069 Node: Tcl Crash Course342832 Node: License354830 Node: OpenOCD Concept Index377241 Node: Command and Driver Index396883  End Tag Table openocd-0.9.0/doc/openocd.texi0000644000175000017500000126443512526201107013172 00000000000000\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename openocd.info @settitle OpenOCD User's Guide @dircategory Development @direntry * OpenOCD: (openocd). OpenOCD User's Guide @end direntry @paragraphindent 0 @c %**end of header @include version.texi @copying This User's Guide documents release @value{VERSION}, dated @value{UPDATED}, of the Open On-Chip Debugger (OpenOCD). @itemize @bullet @item Copyright @copyright{} 2008 The OpenOCD Project @item Copyright @copyright{} 2007-2008 Spencer Oliver @email{spen@@spen-soft.co.uk} @item Copyright @copyright{} 2008-2010 Oyvind Harboe @email{oyvind.harboe@@zylin.com} @item Copyright @copyright{} 2008 Duane Ellis @email{openocd@@duaneellis.com} @item Copyright @copyright{} 2009-2010 David Brownell @end itemize @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end quotation @end copying @titlepage @titlefont{@emph{Open On-Chip Debugger:}} @sp 1 @title OpenOCD User's Guide @subtitle for release @value{VERSION} @subtitle @value{UPDATED} @page @vskip 0pt plus 1filll @insertcopying @end titlepage @summarycontents @contents @ifnottex @node Top @top OpenOCD User's Guide @insertcopying @end ifnottex @menu * About:: About OpenOCD * Developers:: OpenOCD Developer Resources * Debug Adapter Hardware:: Debug Adapter Hardware * About Jim-Tcl:: About Jim-Tcl * Running:: Running OpenOCD * OpenOCD Project Setup:: OpenOCD Project Setup * Config File Guidelines:: Config File Guidelines * Daemon Configuration:: Daemon Configuration * Debug Adapter Configuration:: Debug Adapter Configuration * Reset Configuration:: Reset Configuration * TAP Declaration:: TAP Declaration * CPU Configuration:: CPU Configuration * Flash Commands:: Flash Commands * Flash Programming:: Flash Programming * PLD/FPGA Commands:: PLD/FPGA Commands * General Commands:: General Commands * Architecture and Core Commands:: Architecture and Core Commands * JTAG Commands:: JTAG Commands * Boundary Scan Commands:: Boundary Scan Commands * Utility Commands:: Utility Commands * TFTP:: TFTP * GDB and OpenOCD:: Using GDB and OpenOCD * Tcl Scripting API:: Tcl Scripting API * FAQ:: Frequently Asked Questions * Tcl Crash Course:: Tcl Crash Course * License:: GNU Free Documentation License @comment DO NOT use the plain word ``Index'', reason: CYGWIN filename @comment case issue with ``Index.html'' and ``index.html'' @comment Occurs when creating ``--html --no-split'' output @comment This fix is based on: http://sourceware.org/ml/binutils/2006-05/msg00215.html * OpenOCD Concept Index:: Concept Index * Command and Driver Index:: Command and Driver Index @end menu @node About @unnumbered About @cindex about OpenOCD was created by Dominic Rath as part of a 2005 diploma thesis written at the University of Applied Sciences Augsburg (@uref{http://www.hs-augsburg.de}). Since that time, the project has grown into an active open-source project, supported by a diverse community of software and hardware developers from around the world. @section What is OpenOCD? @cindex TAP @cindex JTAG The Open On-Chip Debugger (OpenOCD) aims to provide debugging, in-system programming and boundary-scan testing for embedded target devices. It does so with the assistance of a @dfn{debug adapter}, which is a small hardware module which helps provide the right kind of electrical signaling to the target being debugged. These are required since the debug host (on which OpenOCD runs) won't usually have native support for such signaling, or the connector needed to hook up to the target. Such debug adapters support one or more @dfn{transport} protocols, each of which involves different electrical signaling (and uses different messaging protocols on top of that signaling). There are many types of debug adapter, and little uniformity in what they are called. (There are also product naming differences.) These adapters are sometimes packaged as discrete dongles, which may generically be called @dfn{hardware interface dongles}. Some development boards also integrate them directly, which may let the development board connect directly to the debug host over USB (and sometimes also to power it over USB). For example, a @dfn{JTAG Adapter} supports JTAG signaling, and is used to communicate with JTAG (IEEE 1149.1) compliant TAPs on your target board. A @dfn{TAP} is a ``Test Access Port'', a module which processes special instructions and data. TAPs are daisy-chained within and between chips and boards. JTAG supports debugging and boundary scan operations. There are also @dfn{SWD Adapters} that support Serial Wire Debug (SWD) signaling to communicate with some newer ARM cores, as well as debug adapters which support both JTAG and SWD transports. SWD supports only debugging, whereas JTAG also supports boundary scan operations. For some chips, there are also @dfn{Programming Adapters} supporting special transports used only to write code to flash memory, without support for on-chip debugging or boundary scan. (At this writing, OpenOCD does not support such non-debug adapters.) @b{Dongles:} OpenOCD currently supports many types of hardware dongles: USB-based, parallel port-based, and other standalone boxes that run OpenOCD internally. @xref{Debug Adapter Hardware}. @b{GDB Debug:} It allows ARM7 (ARM7TDMI and ARM720t), ARM9 (ARM920T, ARM922T, ARM926EJ--S, ARM966E--S), XScale (PXA25x, IXP42x), Cortex-M3 (Stellaris LM3, ST STM32 and Energy Micro EFM32) and Intel Quark (x10xx) based cores to be debugged via the GDB protocol. @b{Flash Programming:} Flash writing is supported for external CFI-compatible NOR flashes (Intel and AMD/Spansion command set) and several internal flashes (LPC1700, LPC1800, LPC2000, LPC4300, AT91SAM7, AT91SAM3U, STR7x, STR9x, LM3, STM32x and EFM32). Preliminary support for various NAND flash controllers (LPC3180, Orion, S3C24xx, more) is included. @section OpenOCD Web Site The OpenOCD web site provides the latest public news from the community: @uref{http://openocd.org/} @section Latest User's Guide: The user's guide you are now reading may not be the latest one available. A version for more recent code may be available. Its HTML form is published regularly at: @uref{http://openocd.org/doc/html/index.html} PDF form is likewise published at: @uref{http://openocd.org/doc/pdf/openocd.pdf} @section OpenOCD User's Forum There is an OpenOCD forum (phpBB) hosted by SparkFun, which might be helpful to you. Note that if you want anything to come to the attention of developers, you should post it to the OpenOCD Developer Mailing List instead of this forum. @uref{http://forum.sparkfun.com/viewforum.php?f=18} @section OpenOCD User's Mailing List The OpenOCD User Mailing List provides the primary means of communication between users: @uref{https://lists.sourceforge.net/mailman/listinfo/openocd-user} @section OpenOCD IRC Support can also be found on irc: @uref{irc://irc.freenode.net/openocd} @node Developers @chapter OpenOCD Developer Resources @cindex developers If you are interested in improving the state of OpenOCD's debugging and testing support, new contributions will be welcome. Motivated developers can produce new target, flash or interface drivers, improve the documentation, as well as more conventional bug fixes and enhancements. The resources in this chapter are available for developers wishing to explore or expand the OpenOCD source code. @section OpenOCD Git Repository During the 0.3.x release cycle, OpenOCD switched from Subversion to a Git repository hosted at SourceForge. The repository URL is: @uref{git://git.code.sf.net/p/openocd/code} or via http @uref{http://git.code.sf.net/p/openocd/code} You may prefer to use a mirror and the HTTP protocol: @uref{http://repo.or.cz/r/openocd.git} With standard Git tools, use @command{git clone} to initialize a local repository, and @command{git pull} to update it. There are also gitweb pages letting you browse the repository with a web browser, or download arbitrary snapshots without needing a Git client: @uref{http://repo.or.cz/w/openocd.git} The @file{README} file contains the instructions for building the project from the repository or a snapshot. Developers that want to contribute patches to the OpenOCD system are @b{strongly} encouraged to work against mainline. Patches created against older versions may require additional work from their submitter in order to be updated for newer releases. @section Doxygen Developer Manual During the 0.2.x release cycle, the OpenOCD project began providing a Doxygen reference manual. This document contains more technical information about the software internals, development processes, and similar documentation: @uref{http://openocd.org/doc/doxygen/html/index.html} This document is a work-in-progress, but contributions would be welcome to fill in the gaps. All of the source files are provided in-tree, listed in the Doxyfile configuration at the top of the source tree. @section Gerrit Review System All changes in the OpenOCD Git repository go through the web-based Gerrit Code Review System: @uref{http://openocd.zylin.com/} After a one-time registration and repository setup, anyone can push commits from their local Git repository directly into Gerrit. All users and developers are encouraged to review, test, discuss and vote for changes in Gerrit. The feedback provides the basis for a maintainer to eventually submit the change to the main Git repository. The @file{HACKING} file, also available as the Patch Guide in the Doxygen Developer Manual, contains basic information about how to connect a repository to Gerrit, prepare and push patches. Patch authors are expected to maintain their changes while they're in Gerrit, respond to feedback and if necessary rework and push improved versions of the change. @section OpenOCD Developer Mailing List The OpenOCD Developer Mailing List provides the primary means of communication between developers: @uref{https://lists.sourceforge.net/mailman/listinfo/openocd-devel} @section OpenOCD Bug Tracker The OpenOCD Bug Tracker is hosted on SourceForge: @uref{http://bugs.openocd.org/} @node Debug Adapter Hardware @chapter Debug Adapter Hardware @cindex dongles @cindex FTDI @cindex wiggler @cindex zy1000 @cindex printer port @cindex USB Adapter @cindex RTCK Defined: @b{dongle}: A small device that plugs into a computer and serves as an adapter .... [snip] In the OpenOCD case, this generally refers to @b{a small adapter} that attaches to your computer via USB or the parallel port. One exception is the Ultimate Solutions ZY1000, packaged as a small box you attach via an ethernet cable. The ZY1000 has the advantage that it does not require any drivers to be installed on the developer PC. It also has a built in web interface. It supports RTCK/RCLK or adaptive clocking and has a built-in relay to power cycle targets remotely. @section Choosing a Dongle There are several things you should keep in mind when choosing a dongle. @enumerate @item @b{Transport} Does it support the kind of communication that you need? OpenOCD focusses mostly on JTAG. Your version may also support other ways to communicate with target devices. @item @b{Voltage} What voltage is your target - 1.8, 2.8, 3.3, or 5V? Does your dongle support it? You might need a level converter. @item @b{Pinout} What pinout does your target board use? Does your dongle support it? You may be able to use jumper wires, or an "octopus" connector, to convert pinouts. @item @b{Connection} Does your computer have the USB, parallel, or Ethernet port needed? @item @b{RTCK} Do you expect to use it with ARM chips and boards with RTCK support (also known as ``adaptive clocking'')? @end enumerate @section Stand-alone JTAG Probe The ZY1000 from Ultimate Solutions is technically not a dongle but a stand-alone JTAG probe that, unlike most dongles, doesn't require any drivers running on the developer's host computer. Once installed on a network using DHCP or a static IP assignment, users can access the ZY1000 probe locally or remotely from any host with access to the IP address assigned to the probe. The ZY1000 provides an intuitive web interface with direct access to the OpenOCD debugger. Users may also run a GDBSERVER directly on the ZY1000 to take full advantage of GCC & GDB to debug any distribution of embedded Linux or NetBSD running on the target. The ZY1000 supports RTCK & RCLK or adaptive clocking and has a built-in relay to power cycle the target remotely. For more information, visit: @b{ZY1000} See: @url{http://www.ultsol.com/index.php/component/content/article/8/210-zylin-zy1000-main} @section USB FT2232 Based There are many USB JTAG dongles on the market, many of them based on a chip from ``Future Technology Devices International'' (FTDI) known as the FTDI FT2232; this is a USB full speed (12 Mbps) chip. See: @url{http://www.ftdichip.com} for more information. In summer 2009, USB high speed (480 Mbps) versions of these FTDI chips started to become available in JTAG adapters. Around 2012, a new variant appeared - FT232H - this is a single-channel version of FT2232H. (Adapters using those high speed FT2232H or FT232H chips may support adaptive clocking.) The FT2232 chips are flexible enough to support some other transport options, such as SWD or the SPI variants used to program some chips. They have two communications channels, and one can be used for a UART adapter at the same time the other one is used to provide a debug adapter. Also, some development boards integrate an FT2232 chip to serve as a built-in low-cost debug adapter and USB-to-serial solution. @itemize @bullet @item @b{usbjtag} @* Link @url{http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html} @item @b{jtagkey} @* See: @url{http://www.amontec.com/jtagkey.shtml} @item @b{jtagkey2} @* See: @url{http://www.amontec.com/jtagkey2.shtml} @item @b{oocdlink} @* See: @url{http://www.oocdlink.com} By Joern Kaipf @item @b{signalyzer} @* See: @url{http://www.signalyzer.com} @item @b{Stellaris Eval Boards} @* See: @url{http://www.ti.com} - The Stellaris eval boards bundle FT2232-based JTAG and SWD support, which can be used to debug the Stellaris chips. Using separate JTAG adapters is optional. These boards can also be used in a "pass through" mode as JTAG adapters to other target boards, disabling the Stellaris chip. @item @b{TI/Luminary ICDI} @* See: @url{http://www.ti.com} - TI/Luminary In-Circuit Debug Interface (ICDI) Boards are included in Stellaris LM3S9B9x Evaluation Kits. Like the non-detachable FT2232 support on the other Stellaris eval boards, they can be used to debug other target boards. @item @b{olimex-jtag} @* See: @url{http://www.olimex.com} @item @b{Flyswatter/Flyswatter2} @* See: @url{http://www.tincantools.com} @item @b{turtelizer2} @* See: @uref{http://www.ethernut.de/en/hardware/turtelizer/index.html, Turtelizer 2}, or @url{http://www.ethernut.de} @item @b{comstick} @* Link: @url{http://www.hitex.com/index.php?id=383} @item @b{stm32stick} @* Link @url{http://www.hitex.com/stm32-stick} @item @b{axm0432_jtag} @* Axiom AXM-0432 Link @url{http://www.axman.com} - NOTE: This JTAG does not appear to be available anymore as of April 2012. @item @b{cortino} @* Link @url{http://www.hitex.com/index.php?id=cortino} @item @b{dlp-usb1232h} @* Link @url{http://www.dlpdesign.com/usb/usb1232h.shtml} @item @b{digilent-hs1} @* Link @url{http://www.digilentinc.com/Products/Detail.cfm?Prod=JTAG-HS1} @item @b{opendous} @* Link @url{http://code.google.com/p/opendous/wiki/JTAG} FT2232H-based (OpenHardware). @item @b{JTAG-lock-pick Tiny 2} @* Link @url{http://www.distortec.com/jtag-lock-pick-tiny-2} FT232H-based @item @b{GW16042} @* Link: @url{http://shop.gateworks.com/index.php?route=product/product&path=70_80&product_id=64} FT2232H-based @end itemize @section USB-JTAG / Altera USB-Blaster compatibles These devices also show up as FTDI devices, but are not protocol-compatible with the FT2232 devices. They are, however, protocol-compatible among themselves. USB-JTAG devices typically consist of a FT245 followed by a CPLD that understands a particular protocol, or emulates this protocol using some other hardware. They may appear under different USB VID/PID depending on the particular product. The driver can be configured to search for any VID/PID pair (see the section on driver commands). @itemize @item @b{USB-JTAG} Kolja Waschk's USB Blaster-compatible adapter @* Link: @url{http://ixo-jtag.sourceforge.net/} @item @b{Altera USB-Blaster} @* Link: @url{http://www.altera.com/literature/ug/ug_usb_blstr.pdf} @end itemize @section USB JLINK based There are several OEM versions of the Segger @b{JLINK} adapter. It is an example of a micro controller based JTAG adapter, it uses an AT91SAM764 internally. @itemize @bullet @item @b{ATMEL SAMICE} Only works with ATMEL chips! @* Link: @url{http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3892} @item @b{SEGGER JLINK} @* Link: @url{http://www.segger.com/jlink.html} @item @b{IAR J-Link} @* Link: @url{http://www.iar.com/en/products/hardware-debug-probes/iar-j-link/} @end itemize @section USB RLINK based Raisonance has an adapter called @b{RLink}. It exists in a stripped-down form on the STM32 Primer, permanently attached to the JTAG lines. It also exists on the STM32 Primer2, but that is wired for SWD and not JTAG, thus not supported. @itemize @bullet @item @b{Raisonance RLink} @* Link: @url{http://www.mcu-raisonance.com/~rlink-debugger-programmer__@/microcontrollers__tool~tool__T018:4cn9ziz4bnx6.html} @item @b{STM32 Primer} @* Link: @url{http://www.stm32circle.com/resources/stm32primer.php} @item @b{STM32 Primer2} @* Link: @url{http://www.stm32circle.com/resources/stm32primer2.php} @end itemize @section USB ST-LINK based ST Micro has an adapter called @b{ST-LINK}. They only work with ST Micro chips, notably STM32 and STM8. @itemize @bullet @item @b{ST-LINK} @* This is available standalone and as part of some kits, eg. STM32VLDISCOVERY. @* Link: @url{http://www.st.com/internet/evalboard/product/219866.jsp} @item @b{ST-LINK/V2} @* This is available standalone and as part of some kits, eg. STM32F4DISCOVERY. @* Link: @url{http://www.st.com/internet/evalboard/product/251168.jsp} @end itemize For info the original ST-LINK enumerates using the mass storage usb class; however, its implementation is completely broken. The result is this causes issues under Linux. The simplest solution is to get Linux to ignore the ST-LINK using one of the following methods: @itemize @bullet @item modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i @item add "options usb-storage quirks=483:3744:i" to /etc/modprobe.conf @end itemize @section USB TI/Stellaris ICDI based Texas Instruments has an adapter called @b{ICDI}. It is not to be confused with the FTDI based adapters that were originally fitted to their evaluation boards. This is the adapter fitted to the Stellaris LaunchPad. @section USB CMSIS-DAP based ARM has released a interface standard called CMSIS-DAP that simplifies connecting debuggers to ARM Cortex based targets @url{http://www.keil.com/support/man/docs/dapdebug/dapdebug_introduction.htm}. @section USB Other @itemize @bullet @item @b{USBprog} @* Link: @url{http://shop.embedded-projects.net/} - which uses an Atmel MEGA32 and a UBN9604 @item @b{USB - Presto} @* Link: @url{http://tools.asix.net/prg_presto.htm} @item @b{Versaloon-Link} @* Link: @url{http://www.versaloon.com} @item @b{ARM-JTAG-EW} @* Link: @url{http://www.olimex.com/dev/arm-jtag-ew.html} @item @b{Buspirate} @* Link: @url{http://dangerousprototypes.com/bus-pirate-manual/} @item @b{opendous} @* Link: @url{http://code.google.com/p/opendous-jtag/} - which uses an AT90USB162 @item @b{estick} @* Link: @url{http://code.google.com/p/estick-jtag/} @item @b{Keil ULINK v1} @* Link: @url{http://www.keil.com/ulink1/} @end itemize @section IBM PC Parallel Printer Port Based The two well-known ``JTAG Parallel Ports'' cables are the Xilinx DLC5 and the Macraigor Wiggler. There are many clones and variations of these on the market. Note that parallel ports are becoming much less common, so if you have the choice you should probably avoid these adapters in favor of USB-based ones. @itemize @bullet @item @b{Wiggler} - There are many clones of this. @* Link: @url{http://www.macraigor.com/wiggler.htm} @item @b{DLC5} - From XILINX - There are many clones of this @* Link: Search the web for: ``XILINX DLC5'' - it is no longer produced, PDF schematics are easily found and it is easy to make. @item @b{Amontec - JTAG Accelerator} @* Link: @url{http://www.amontec.com/jtag_accelerator.shtml} @item @b{Wiggler2} @* Link: @url{http://www.ccac.rwth-aachen.de/~michaels/index.php/hardware/armjtag} @item @b{Wiggler_ntrst_inverted} @* Yet another variation - See the source code, src/jtag/parport.c @item @b{old_amt_wiggler} @* Unknown - probably not on the market today @item @b{arm-jtag} @* Link: Most likely @url{http://www.olimex.com/dev/arm-jtag.html} [another wiggler clone] @item @b{chameleon} @* Link: @url{http://www.amontec.com/chameleon.shtml} @item @b{Triton} @* Unknown. @item @b{Lattice} @* ispDownload from Lattice Semiconductor @url{http://www.latticesemi.com/lit/docs/@/devtools/dlcable.pdf} @item @b{flashlink} @* From ST Microsystems; @* Link: @url{http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATA_BRIEF/DM00039500.pdf} @end itemize @section Other... @itemize @bullet @item @b{ep93xx} @* An EP93xx based Linux machine using the GPIO pins directly. @item @b{at91rm9200} @* Like the EP93xx - but an ATMEL AT91RM9200 based solution using the GPIO pins on the chip. @item @b{bcm2835gpio} @* A BCM2835-based board (e.g. Raspberry Pi) using the GPIO pins of the expansion header. @item @b{jtag_vpi} @* A JTAG driver acting as a client for the JTAG VPI server interface. @* Link: @url{http://github.com/fjullien/jtag_vpi} @end itemize @node About Jim-Tcl @chapter About Jim-Tcl @cindex Jim-Tcl @cindex tcl OpenOCD uses a small ``Tcl Interpreter'' known as Jim-Tcl. This programming language provides a simple and extensible command interpreter. All commands presented in this Guide are extensions to Jim-Tcl. You can use them as simple commands, without needing to learn much of anything about Tcl. Alternatively, you can write Tcl programs with them. You can learn more about Jim at its website, @url{http://jim.tcl.tk}. There is an active and responsive community, get on the mailing list if you have any questions. Jim-Tcl maintainers also lurk on the OpenOCD mailing list. @itemize @bullet @item @b{Jim vs. Tcl} @* Jim-Tcl is a stripped down version of the well known Tcl language, which can be found here: @url{http://www.tcl.tk}. Jim-Tcl has far fewer features. Jim-Tcl is several dozens of .C files and .H files and implements the basic Tcl command set. In contrast: Tcl 8.6 is a 4.2 MB .zip file containing 1540 files. @item @b{Missing Features} @* Our practice has been: Add/clone the real Tcl feature if/when needed. We welcome Jim-Tcl improvements, not bloat. Also there are a large number of optional Jim-Tcl features that are not enabled in OpenOCD. @item @b{Scripts} @* OpenOCD configuration scripts are Jim-Tcl Scripts. OpenOCD's command interpreter today is a mixture of (newer) Jim-Tcl commands, and the (older) original command interpreter. @item @b{Commands} @* At the OpenOCD telnet command line (or via the GDB monitor command) one can type a Tcl for() loop, set variables, etc. Some of the commands documented in this guide are implemented as Tcl scripts, from a @file{startup.tcl} file internal to the server. @item @b{Historical Note} @* Jim-Tcl was introduced to OpenOCD in spring 2008. Fall 2010, before OpenOCD 0.5 release, OpenOCD switched to using Jim-Tcl as a Git submodule, which greatly simplified upgrading Jim-Tcl to benefit from new features and bugfixes in Jim-Tcl. @item @b{Need a crash course in Tcl?} @*@xref{Tcl Crash Course}. @end itemize @node Running @chapter Running @cindex command line options @cindex logfile @cindex directory search Properly installing OpenOCD sets up your operating system to grant it access to the debug adapters. On Linux, this usually involves installing a file in @file{/etc/udev/rules.d,} so OpenOCD has permissions. An example rules file that works for many common adapters is shipped with OpenOCD in the @file{contrib} directory. MS-Windows needs complex and confusing driver configuration for every peripheral. Such issues are unique to each operating system, and are not detailed in this User's Guide. Then later you will invoke the OpenOCD server, with various options to tell it how each debug session should work. The @option{--help} option shows: @verbatim bash$ openocd --help --help | -h display this help --version | -v display OpenOCD version --file | -f use configuration file --search | -s dir to search for config files and scripts --debug | -d set debug level <0-3> --log_output | -l redirect log output to file --command | -c run @end verbatim If you don't give any @option{-f} or @option{-c} options, OpenOCD tries to read the configuration file @file{openocd.cfg}. To specify one or more different configuration files, use @option{-f} options. For example: @example openocd -f config1.cfg -f config2.cfg -f config3.cfg @end example Configuration files and scripts are searched for in @enumerate @item the current directory, @item any search dir specified on the command line using the @option{-s} option, @item any search dir specified using the @command{add_script_search_dir} command, @item @file{$HOME/.openocd} (not on Windows), @item the site wide script library @file{$pkgdatadir/site} and @item the OpenOCD-supplied script library @file{$pkgdatadir/scripts}. @end enumerate The first found file with a matching file name will be used. @quotation Note Don't try to use configuration script names or paths which include the "#" character. That character begins Tcl comments. @end quotation @section Simple setup, no customization In the best case, you can use two scripts from one of the script libraries, hook up your JTAG adapter, and start the server ... and your JTAG setup will just work "out of the box". Always try to start by reusing those scripts, but assume you'll need more customization even if this works. @xref{OpenOCD Project Setup}. If you find a script for your JTAG adapter, and for your board or target, you may be able to hook up your JTAG adapter then start the server with some variation of one of the following: @example openocd -f interface/ADAPTER.cfg -f board/MYBOARD.cfg openocd -f interface/ftdi/ADAPTER.cfg -f board/MYBOARD.cfg @end example You might also need to configure which reset signals are present, using @option{-c 'reset_config trst_and_srst'} or something similar. If all goes well you'll see output something like @example Open On-Chip Debugger 0.4.0 (2010-01-14-15:06) For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : JTAG tap: lm3s.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) @end example Seeing that "tap/device found" message, and no warnings, means the JTAG communication is working. That's a key milestone, but you'll probably need more project-specific setup. @section What OpenOCD does as it starts OpenOCD starts by processing the configuration commands provided on the command line or, if there were no @option{-c command} or @option{-f file.cfg} options given, in @file{openocd.cfg}. @xref{configurationstage,,Configuration Stage}. At the end of the configuration stage it verifies the JTAG scan chain defined using those commands; your configuration should ensure that this always succeeds. Normally, OpenOCD then starts running as a daemon. Alternatively, commands may be used to terminate the configuration stage early, perform work (such as updating some flash memory), and then shut down without acting as a daemon. Once OpenOCD starts running as a daemon, it waits for connections from clients (Telnet, GDB, Other) and processes the commands issued through those channels. If you are having problems, you can enable internal debug messages via the @option{-d} option. Also it is possible to interleave Jim-Tcl commands w/config scripts using the @option{-c} command line switch. To enable debug output (when reporting problems or working on OpenOCD itself), use the @option{-d} command line switch. This sets the @option{debug_level} to "3", outputting the most information, including debug messages. The default setting is "2", outputting only informational messages, warnings and errors. You can also change this setting from within a telnet or gdb session using @command{debug_level} (@pxref{debuglevel,,debug_level}). You can redirect all output from the daemon to a file using the @option{-l } switch. Note! OpenOCD will launch the GDB & telnet server even if it can not establish a connection with the target. In general, it is possible for the JTAG controller to be unresponsive until the target is set up correctly via e.g. GDB monitor commands in a GDB init script. @node OpenOCD Project Setup @chapter OpenOCD Project Setup To use OpenOCD with your development projects, you need to do more than just connect the JTAG adapter hardware (dongle) to your development board and start the OpenOCD server. You also need to configure your OpenOCD server so that it knows about your adapter and board, and helps your work. You may also want to connect OpenOCD to GDB, possibly using Eclipse or some other GUI. @section Hooking up the JTAG Adapter Today's most common case is a dongle with a JTAG cable on one side (such as a ribbon cable with a 10-pin or 20-pin IDC connector) and a USB cable on the other. Instead of USB, some cables use Ethernet; older ones may use a PC parallel port, or even a serial port. @enumerate @item @emph{Start with power to your target board turned off}, and nothing connected to your JTAG adapter. If you're particularly paranoid, unplug power to the board. It's important to have the ground signal properly set up, unless you are using a JTAG adapter which provides galvanic isolation between the target board and the debugging host. @item @emph{Be sure it's the right kind of JTAG connector.} If your dongle has a 20-pin ARM connector, you need some kind of adapter (or octopus, see below) to hook it up to boards using 14-pin or 10-pin connectors ... or to 20-pin connectors which don't use ARM's pinout. In the same vein, make sure the voltage levels are compatible. Not all JTAG adapters have the level shifters needed to work with 1.2 Volt boards. @item @emph{Be certain the cable is properly oriented} or you might damage your board. In most cases there are only two possible ways to connect the cable. Connect the JTAG cable from your adapter to the board. Be sure it's firmly connected. In the best case, the connector is keyed to physically prevent you from inserting it wrong. This is most often done using a slot on the board's male connector housing, which must match a key on the JTAG cable's female connector. If there's no housing, then you must look carefully and make sure pin 1 on the cable hooks up to pin 1 on the board. Ribbon cables are frequently all grey except for a wire on one edge, which is red. The red wire is pin 1. Sometimes dongles provide cables where one end is an ``octopus'' of color coded single-wire connectors, instead of a connector block. These are great when converting from one JTAG pinout to another, but are tedious to set up. Use these with connector pinout diagrams to help you match up the adapter signals to the right board pins. @item @emph{Connect the adapter's other end} once the JTAG cable is connected. A USB, parallel, or serial port connector will go to the host which you are using to run OpenOCD. For Ethernet, consult the documentation and your network administrator. For USB-based JTAG adapters you have an easy sanity check at this point: does the host operating system see the JTAG adapter? If you're running Linux, try the @command{lsusb} command. If that host is an MS-Windows host, you'll need to install a driver before OpenOCD works. @item @emph{Connect the adapter's power supply, if needed.} This step is primarily for non-USB adapters, but sometimes USB adapters need extra power. @item @emph{Power up the target board.} Unless you just let the magic smoke escape, you're now ready to set up the OpenOCD server so you can use JTAG to work with that board. @end enumerate Talk with the OpenOCD server using telnet (@code{telnet localhost 4444} on many systems) or GDB. @xref{GDB and OpenOCD}. @section Project Directory There are many ways you can configure OpenOCD and start it up. A simple way to organize them all involves keeping a single directory for your work with a given board. When you start OpenOCD from that directory, it searches there first for configuration files, scripts, files accessed through semihosting, and for code you upload to the target board. It is also the natural place to write files, such as log files and data you download from the board. @section Configuration Basics There are two basic ways of configuring OpenOCD, and a variety of ways you can mix them. Think of the difference as just being how you start the server: @itemize @item Many @option{-f file} or @option{-c command} options on the command line @item No options, but a @dfn{user config file} in the current directory named @file{openocd.cfg} @end itemize Here is an example @file{openocd.cfg} file for a setup using a Signalyzer FT2232-based JTAG adapter to talk to a board with an Atmel AT91SAM7X256 microcontroller: @example source [find interface/signalyzer.cfg] # GDB can also flash my flash! gdb_memory_map enable gdb_flash_program enable source [find target/sam7x256.cfg] @end example Here is the command line equivalent of that configuration: @example openocd -f interface/signalyzer.cfg \ -c "gdb_memory_map enable" \ -c "gdb_flash_program enable" \ -f target/sam7x256.cfg @end example You could wrap such long command lines in shell scripts, each supporting a different development task. One might re-flash the board with a specific firmware version. Another might set up a particular debugging or run-time environment. @quotation Important At this writing (October 2009) the command line method has problems with how it treats variables. For example, after @option{-c "set VAR value"}, or doing the same in a script, the variable @var{VAR} will have no value that can be tested in a later script. @end quotation Here we will focus on the simpler solution: one user config file, including basic configuration plus any TCL procedures to simplify your work. @section User Config Files @cindex config file, user @cindex user config file @cindex config file, overview A user configuration file ties together all the parts of a project in one place. One of the following will match your situation best: @itemize @item Ideally almost everything comes from configuration files provided by someone else. For example, OpenOCD distributes a @file{scripts} directory (probably in @file{/usr/share/openocd/scripts} on Linux). Board and tool vendors can provide these too, as can individual user sites; the @option{-s} command line option lets you say where to find these files. (@xref{Running}.) The AT91SAM7X256 example above works this way. Three main types of non-user configuration file each have their own subdirectory in the @file{scripts} directory: @enumerate @item @b{interface} -- one for each different debug adapter; @item @b{board} -- one for each different board @item @b{target} -- the chips which integrate CPUs and other JTAG TAPs @end enumerate Best case: include just two files, and they handle everything else. The first is an interface config file. The second is board-specific, and it sets up the JTAG TAPs and their GDB targets (by deferring to some @file{target.cfg} file), declares all flash memory, and leaves you nothing to do except meet your deadline: @example source [find interface/olimex-jtag-tiny.cfg] source [find board/csb337.cfg] @end example Boards with a single microcontroller often won't need more than the target config file, as in the AT91SAM7X256 example. That's because there is no external memory (flash, DDR RAM), and the board differences are encapsulated by application code. @item Maybe you don't know yet what your board looks like to JTAG. Once you know the @file{interface.cfg} file to use, you may need help from OpenOCD to discover what's on the board. Once you find the JTAG TAPs, you can just search for appropriate target and board configuration files ... or write your own, from the bottom up. @xref{autoprobing,,Autoprobing}. @item You can often reuse some standard config files but need to write a few new ones, probably a @file{board.cfg} file. You will be using commands described later in this User's Guide, and working with the guidelines in the next chapter. For example, there may be configuration files for your JTAG adapter and target chip, but you need a new board-specific config file giving access to your particular flash chips. Or you might need to write another target chip configuration file for a new chip built around the Cortex M3 core. @quotation Note When you write new configuration files, please submit them for inclusion in the next OpenOCD release. For example, a @file{board/newboard.cfg} file will help the next users of that board, and a @file{target/newcpu.cfg} will help support users of any board using that chip. @end quotation @item You may may need to write some C code. It may be as simple as supporting a new FT2232 or parport based adapter; a bit more involved, like a NAND or NOR flash controller driver; or a big piece of work like supporting a new chip architecture. @end itemize Reuse the existing config files when you can. Look first in the @file{scripts/boards} area, then @file{scripts/targets}. You may find a board configuration that's a good example to follow. When you write config files, separate the reusable parts (things every user of that interface, chip, or board needs) from ones specific to your environment and debugging approach. @itemize @item For example, a @code{gdb-attach} event handler that invokes the @command{reset init} command will interfere with debugging early boot code, which performs some of the same actions that the @code{reset-init} event handler does. @item Likewise, the @command{arm9 vector_catch} command (or @cindex vector_catch its siblings @command{xscale vector_catch} and @command{cortex_m vector_catch}) can be a timesaver during some debug sessions, but don't make everyone use that either. Keep those kinds of debugging aids in your user config file, along with messaging and tracing setup. (@xref{softwaredebugmessagesandtracing,,Software Debug Messages and Tracing}.) @item You might need to override some defaults. For example, you might need to move, shrink, or back up the target's work area if your application needs much SRAM. @item TCP/IP port configuration is another example of something which is environment-specific, and should only appear in a user config file. @xref{tcpipports,,TCP/IP Ports}. @end itemize @section Project-Specific Utilities A few project-specific utility routines may well speed up your work. Write them, and keep them in your project's user config file. For example, if you are making a boot loader work on a board, it's nice to be able to debug the ``after it's loaded to RAM'' parts separately from the finicky early code which sets up the DDR RAM controller and clocks. A script like this one, or a more GDB-aware sibling, may help: @example proc ramboot @{ @} @{ # Reset, running the target's "reset-init" scripts # to initialize clocks and the DDR RAM controller. # Leave the CPU halted. reset init # Load CONFIG_SKIP_LOWLEVEL_INIT version into DDR RAM. load_image u-boot.bin 0x20000000 # Start running. resume 0x20000000 @} @end example Then once that code is working you will need to make it boot from NOR flash; a different utility would help. Alternatively, some developers write to flash using GDB. (You might use a similar script if you're working with a flash based microcontroller application instead of a boot loader.) @example proc newboot @{ @} @{ # Reset, leaving the CPU halted. The "reset-init" event # proc gives faster access to the CPU and to NOR flash; # "reset halt" would be slower. reset init # Write standard version of U-Boot into the first two # sectors of NOR flash ... the standard version should # do the same lowlevel init as "reset-init". flash protect 0 0 1 off flash erase_sector 0 0 1 flash write_bank 0 u-boot.bin 0x0 flash protect 0 0 1 on # Reboot from scratch using that new boot loader. reset run @} @end example You may need more complicated utility procedures when booting from NAND. That often involves an extra bootloader stage, running from on-chip SRAM to perform DDR RAM setup so it can load the main bootloader code (which won't fit into that SRAM). Other helper scripts might be used to write production system images, involving considerably more than just a three stage bootloader. @section Target Software Changes Sometimes you may want to make some small changes to the software you're developing, to help make JTAG debugging work better. For example, in C or assembly language code you might use @code{#ifdef JTAG_DEBUG} (or its converse) around code handling issues like: @itemize @bullet @item @b{Watchdog Timers}... Watchog timers are typically used to automatically reset systems if some application task doesn't periodically reset the timer. (The assumption is that the system has locked up if the task can't run.) When a JTAG debugger halts the system, that task won't be able to run and reset the timer ... potentially causing resets in the middle of your debug sessions. It's rarely a good idea to disable such watchdogs, since their usage needs to be debugged just like all other parts of your firmware. That might however be your only option. Look instead for chip-specific ways to stop the watchdog from counting while the system is in a debug halt state. It may be simplest to set that non-counting mode in your debugger startup scripts. You may however need a different approach when, for example, a motor could be physically damaged by firmware remaining inactive in a debug halt state. That might involve a type of firmware mode where that "non-counting" mode is disabled at the beginning then re-enabled at the end; a watchdog reset might fire and complicate the debug session, but hardware (or people) would be protected.@footnote{Note that many systems support a "monitor mode" debug that is a somewhat cleaner way to address such issues. You can think of it as only halting part of the system, maybe just one task, instead of the whole thing. At this writing, January 2010, OpenOCD based debugging does not support monitor mode debug, only "halt mode" debug.} @item @b{ARM Semihosting}... @cindex ARM semihosting When linked with a special runtime library provided with many toolchains@footnote{See chapter 8 "Semihosting" in @uref{http://infocenter.arm.com/help/topic/com.arm.doc.dui0203i/DUI0203I_rvct_developer_guide.pdf, ARM DUI 0203I}, the "RealView Compilation Tools Developer Guide". The CodeSourcery EABI toolchain also includes a semihosting library.}, your target code can use I/O facilities on the debug host. That library provides a small set of system calls which are handled by OpenOCD. It can let the debugger provide your system console and a file system, helping with early debugging or providing a more capable environment for sometimes-complex tasks like installing system firmware onto NAND or SPI flash. @item @b{ARM Wait-For-Interrupt}... Many ARM chips synchronize the JTAG clock using the core clock. Low power states which stop that core clock thus prevent JTAG access. Idle loops in tasking environments often enter those low power states via the @code{WFI} instruction (or its coprocessor equivalent, before ARMv7). You may want to @emph{disable that instruction} in source code, or otherwise prevent using that state, to ensure you can get JTAG access at any time.@footnote{As a more polite alternative, some processors have special debug-oriented registers which can be used to change various features including how the low power states are clocked while debugging. The STM32 DBGMCU_CR register is an example; at the cost of extra power consumption, JTAG can be used during low power states.} For example, the OpenOCD @command{halt} command may not work for an idle processor otherwise. @item @b{Delay after reset}... Not all chips have good support for debugger access right after reset; many LPC2xxx chips have issues here. Similarly, applications that reconfigure pins used for JTAG access as they start will also block debugger access. To work with boards like this, @emph{enable a short delay loop} the first thing after reset, before "real" startup activities. For example, one second's delay is usually more than enough time for a JTAG debugger to attach, so that early code execution can be debugged or firmware can be replaced. @item @b{Debug Communications Channel (DCC)}... Some processors include mechanisms to send messages over JTAG. Many ARM cores support these, as do some cores from other vendors. (OpenOCD may be able to use this DCC internally, speeding up some operations like writing to memory.) Your application may want to deliver various debugging messages over JTAG, by @emph{linking with a small library of code} provided with OpenOCD and using the utilities there to send various kinds of message. @xref{softwaredebugmessagesandtracing,,Software Debug Messages and Tracing}. @end itemize @section Target Hardware Setup Chip vendors often provide software development boards which are highly configurable, so that they can support all options that product boards may require. @emph{Make sure that any jumpers or switches match the system configuration you are working with.} Common issues include: @itemize @bullet @item @b{JTAG setup} ... Boards may support more than one JTAG configuration. Examples include jumpers controlling pullups versus pulldowns on the nTRST and/or nSRST signals, and choice of connectors (e.g. which of two headers on the base board, or one from a daughtercard). For some Texas Instruments boards, you may need to jumper the EMU0 and EMU1 signals (which OpenOCD won't currently control). @item @b{Boot Modes} ... Complex chips often support multiple boot modes, controlled by external jumpers. Make sure this is set up correctly. For example many i.MX boards from NXP need to be jumpered to "ATX mode" to start booting using the on-chip ROM, when using second stage bootloader code stored in a NAND flash chip. Such explicit configuration is common, and not limited to booting from NAND. You might also need to set jumpers to start booting using code loaded from an MMC/SD card; external SPI flash; Ethernet, UART, or USB links; NOR flash; OneNAND flash; some external host; or various other sources. @item @b{Memory Addressing} ... Boards which support multiple boot modes may also have jumpers to configure memory addressing. One board, for example, jumpers external chipselect 0 (used for booting) to address either a large SRAM (which must be pre-loaded via JTAG), NOR flash, or NAND flash. When it's jumpered to address NAND flash, that board must also be told to start booting from on-chip ROM. Your @file{board.cfg} file may also need to be told this jumper configuration, so that it can know whether to declare NOR flash using @command{flash bank} or instead declare NAND flash with @command{nand device}; and likewise which probe to perform in its @code{reset-init} handler. A closely related issue is bus width. Jumpers might need to distinguish between 8 bit or 16 bit bus access for the flash used to start booting. @item @b{Peripheral Access} ... Development boards generally provide access to every peripheral on the chip, sometimes in multiple modes (such as by providing multiple audio codec chips). This interacts with software configuration of pin multiplexing, where for example a given pin may be routed either to the MMC/SD controller or the GPIO controller. It also often interacts with configuration jumpers. One jumper may be used to route signals to an MMC/SD card slot or an expansion bus (which might in turn affect booting); others might control which audio or video codecs are used. @end itemize Plus you should of course have @code{reset-init} event handlers which set up the hardware to match that jumper configuration. That includes in particular any oscillator or PLL used to clock the CPU, and any memory controllers needed to access external memory and peripherals. Without such handlers, you won't be able to access those resources without working target firmware which can do that setup ... this can be awkward when you're trying to debug that target firmware. Even if there's a ROM bootloader which handles a few issues, it rarely provides full access to all board-specific capabilities. @node Config File Guidelines @chapter Config File Guidelines This chapter is aimed at any user who needs to write a config file, including developers and integrators of OpenOCD and any user who needs to get a new board working smoothly. It provides guidelines for creating those files. You should find the following directories under @t{$(INSTALLDIR)/scripts}, with config files maintained upstream. Use them as-is where you can; or as models for new files. @itemize @bullet @item @file{interface} ... These are for debug adapters. Files that specify configuration to use specific JTAG, SWD and other adapters go here. @item @file{board} ... Think Circuit Board, PWA, PCB, they go by many names. Board files contain initialization items that are specific to a board. They reuse target configuration files, since the same microprocessor chips are used on many boards, but support for external parts varies widely. For example, the SDRAM initialization sequence for the board, or the type of external flash and what address it uses. Any initialization sequence to enable that external flash or SDRAM should be found in the board file. Boards may also contain multiple targets: two CPUs; or a CPU and an FPGA. @item @file{target} ... Think chip. The ``target'' directory represents the JTAG TAPs on a chip which OpenOCD should control, not a board. Two common types of targets are ARM chips and FPGA or CPLD chips. When a chip has multiple TAPs (maybe it has both ARM and DSP cores), the target config file defines all of them. @item @emph{more} ... browse for other library files which may be useful. For example, there are various generic and CPU-specific utilities. @end itemize The @file{openocd.cfg} user config file may override features in any of the above files by setting variables before sourcing the target file, or by adding commands specific to their situation. @section Interface Config Files The user config file should be able to source one of these files with a command like this: @example source [find interface/FOOBAR.cfg] @end example A preconfigured interface file should exist for every debug adapter in use today with OpenOCD. That said, perhaps some of these config files have only been used by the developer who created it. A separate chapter gives information about how to set these up. @xref{Debug Adapter Configuration}. Read the OpenOCD source code (and Developer's Guide) if you have a new kind of hardware interface and need to provide a driver for it. @section Board Config Files @cindex config file, board @cindex board config file The user config file should be able to source one of these files with a command like this: @example source [find board/FOOBAR.cfg] @end example The point of a board config file is to package everything about a given board that user config files need to know. In summary the board files should contain (if present) @enumerate @item One or more @command{source [find target/...cfg]} statements @item NOR flash configuration (@pxref{norconfiguration,,NOR Configuration}) @item NAND flash configuration (@pxref{nandconfiguration,,NAND Configuration}) @item Target @code{reset} handlers for SDRAM and I/O configuration @item JTAG adapter reset configuration (@pxref{Reset Configuration}) @item All things that are not ``inside a chip'' @end enumerate Generic things inside target chips belong in target config files, not board config files. So for example a @code{reset-init} event handler should know board-specific oscillator and PLL parameters, which it passes to target-specific utility code. The most complex task of a board config file is creating such a @code{reset-init} event handler. Define those handlers last, after you verify the rest of the board configuration works. @subsection Communication Between Config files In addition to target-specific utility code, another way that board and target config files communicate is by following a convention on how to use certain variables. The full Tcl/Tk language supports ``namespaces'', but Jim-Tcl does not. Thus the rule we follow in OpenOCD is this: Variables that begin with a leading underscore are temporary in nature, and can be modified and used at will within a target configuration file. Complex board config files can do the things like this, for a board with three chips: @example # Chip #1: PXA270 for network side, big endian set CHIPNAME network set ENDIAN big source [find target/pxa270.cfg] # on return: _TARGETNAME = network.cpu # other commands can refer to the "network.cpu" target. $_TARGETNAME configure .... events for this CPU.. # Chip #2: PXA270 for video side, little endian set CHIPNAME video set ENDIAN little source [find target/pxa270.cfg] # on return: _TARGETNAME = video.cpu # other commands can refer to the "video.cpu" target. $_TARGETNAME configure .... events for this CPU.. # Chip #3: Xilinx FPGA for glue logic set CHIPNAME xilinx unset ENDIAN source [find target/spartan3.cfg] @end example That example is oversimplified because it doesn't show any flash memory, or the @code{reset-init} event handlers to initialize external DRAM or (assuming it needs it) load a configuration into the FPGA. Such features are usually needed for low-level work with many boards, where ``low level'' implies that the board initialization software may not be working. (That's a common reason to need JTAG tools. Another is to enable working with microcontroller-based systems, which often have no debugging support except a JTAG connector.) Target config files may also export utility functions to board and user config files. Such functions should use name prefixes, to help avoid naming collisions. Board files could also accept input variables from user config files. For example, there might be a @code{J4_JUMPER} setting used to identify what kind of flash memory a development board is using, or how to set up other clocks and peripherals. @subsection Variable Naming Convention @cindex variable names Most boards have only one instance of a chip. However, it should be easy to create a board with more than one such chip (as shown above). Accordingly, we encourage these conventions for naming variables associated with different @file{target.cfg} files, to promote consistency and so that board files can override target defaults. Inputs to target config files include: @itemize @bullet @item @code{CHIPNAME} ... This gives a name to the overall chip, and is used as part of tap identifier dotted names. While the default is normally provided by the chip manufacturer, board files may need to distinguish between instances of a chip. @item @code{ENDIAN} ... By default @option{little} - although chips may hard-wire @option{big}. Chips that can't change endianness don't need to use this variable. @item @code{CPUTAPID} ... When OpenOCD examines the JTAG chain, it can be told verify the chips against the JTAG IDCODE register. The target file will hold one or more defaults, but sometimes the chip in a board will use a different ID (perhaps a newer revision). @end itemize Outputs from target config files include: @itemize @bullet @item @code{_TARGETNAME} ... By convention, this variable is created by the target configuration script. The board configuration file may make use of this variable to configure things like a ``reset init'' script, or other things specific to that board and that target. If the chip has 2 targets, the names are @code{_TARGETNAME0}, @code{_TARGETNAME1}, ... etc. @end itemize @subsection The reset-init Event Handler @cindex event, reset-init @cindex reset-init handler Board config files run in the OpenOCD configuration stage; they can't use TAPs or targets, since they haven't been fully set up yet. This means you can't write memory or access chip registers; you can't even verify that a flash chip is present. That's done later in event handlers, of which the target @code{reset-init} handler is one of the most important. Except on microcontrollers, the basic job of @code{reset-init} event handlers is setting up flash and DRAM, as normally handled by boot loaders. Microcontrollers rarely use boot loaders; they run right out of their on-chip flash and SRAM memory. But they may want to use one of these handlers too, if just for developer convenience. @quotation Note Because this is so very board-specific, and chip-specific, no examples are included here. Instead, look at the board config files distributed with OpenOCD. If you have a boot loader, its source code will help; so will configuration files for other JTAG tools (@pxref{translatingconfigurationfiles,,Translating Configuration Files}). @end quotation Some of this code could probably be shared between different boards. For example, setting up a DRAM controller often doesn't differ by much except the bus width (16 bits or 32?) and memory timings, so a reusable TCL procedure loaded by the @file{target.cfg} file might take those as parameters. Similarly with oscillator, PLL, and clock setup; and disabling the watchdog. Structure the code cleanly, and provide comments to help the next developer doing such work. (@emph{You might be that next person} trying to reuse init code!) The last thing normally done in a @code{reset-init} handler is probing whatever flash memory was configured. For most chips that needs to be done while the associated target is halted, either because JTAG memory access uses the CPU or to prevent conflicting CPU access. @subsection JTAG Clock Rate Before your @code{reset-init} handler has set up the PLLs and clocking, you may need to run with a low JTAG clock rate. @xref{jtagspeed,,JTAG Speed}. Then you'd increase that rate after your handler has made it possible to use the faster JTAG clock. When the initial low speed is board-specific, for example because it depends on a board-specific oscillator speed, then you should probably set it up in the board config file; if it's target-specific, it belongs in the target config file. For most ARM-based processors the fastest JTAG clock@footnote{A FAQ @uref{http://www.arm.com/support/faqdev/4170.html} gives details.} is one sixth of the CPU clock; or one eighth for ARM11 cores. Consult chip documentation to determine the peak JTAG clock rate, which might be less than that. @quotation Warning On most ARMs, JTAG clock detection is coupled to the core clock, so software using a @option{wait for interrupt} operation blocks JTAG access. Adaptive clocking provides a partial workaround, but a more complete solution just avoids using that instruction with JTAG debuggers. @end quotation If both the chip and the board support adaptive clocking, use the @command{jtag_rclk} command, in case your board is used with JTAG adapter which also supports it. Otherwise use @command{adapter_khz}. Set the slow rate at the beginning of the reset sequence, and the faster rate as soon as the clocks are at full speed. @anchor{theinitboardprocedure} @subsection The init_board procedure @cindex init_board procedure The concept of @code{init_board} procedure is very similar to @code{init_targets} (@xref{theinittargetsprocedure,,The init_targets procedure}.) - it's a replacement of ``linear'' configuration scripts. This procedure is meant to be executed when OpenOCD enters run stage (@xref{enteringtherunstage,,Entering the Run Stage},) after @code{init_targets}. The idea to have separate @code{init_targets} and @code{init_board} procedures is to allow the first one to configure everything target specific (internal flash, internal RAM, etc.) and the second one to configure everything board specific (reset signals, chip frequency, reset-init event handler, external memory, etc.). Additionally ``linear'' board config file will most likely fail when target config file uses @code{init_targets} scheme (``linear'' script is executed before @code{init} and @code{init_targets} - after), so separating these two configuration stages is very convenient, as the easiest way to overcome this problem is to convert board config file to use @code{init_board} procedure. Board config scripts don't need to override @code{init_targets} defined in target config files when they only need to add some specifics. Just as @code{init_targets}, the @code{init_board} procedure can be overridden by ``next level'' script (which sources the original), allowing greater code reuse. @example ### board_file.cfg ### # source target file that does most of the config in init_targets source [find target/target.cfg] proc enable_fast_clock @{@} @{ # enables fast on-board clock source # configures the chip to use it @} # initialize only board specifics - reset, clock, adapter frequency proc init_board @{@} @{ reset_config trst_and_srst trst_pulls_srst $_TARGETNAME configure -event reset-init @{ adapter_khz 1 enable_fast_clock adapter_khz 10000 @} @} @end example @section Target Config Files @cindex config file, target @cindex target config file Board config files communicate with target config files using naming conventions as described above, and may source one or more target config files like this: @example source [find target/FOOBAR.cfg] @end example The point of a target config file is to package everything about a given chip that board config files need to know. In summary the target files should contain @enumerate @item Set defaults @item Add TAPs to the scan chain @item Add CPU targets (includes GDB support) @item CPU/Chip/CPU-Core specific features @item On-Chip flash @end enumerate As a rule of thumb, a target file sets up only one chip. For a microcontroller, that will often include a single TAP, which is a CPU needing a GDB target, and its on-chip flash. More complex chips may include multiple TAPs, and the target config file may need to define them all before OpenOCD can talk to the chip. For example, some phone chips have JTAG scan chains that include an ARM core for operating system use, a DSP, another ARM core embedded in an image processing engine, and other processing engines. @subsection Default Value Boiler Plate Code All target configuration files should start with code like this, letting board config files express environment-specific differences in how things should be set up. @example # Boards may override chip names, perhaps based on role, # but the default should match what the vendor uses if @{ [info exists CHIPNAME] @} @{ set _CHIPNAME $CHIPNAME @} else @{ set _CHIPNAME sam7x256 @} # ONLY use ENDIAN with targets that can change it. if @{ [info exists ENDIAN] @} @{ set _ENDIAN $ENDIAN @} else @{ set _ENDIAN little @} # TAP identifiers may change as chips mature, for example with # new revision fields (the "3" here). Pick a good default; you # can pass several such identifiers to the "jtag newtap" command. if @{ [info exists CPUTAPID ] @} @{ set _CPUTAPID $CPUTAPID @} else @{ set _CPUTAPID 0x3f0f0f0f @} @end example @c but 0x3f0f0f0f is for an str73x part ... @emph{Remember:} Board config files may include multiple target config files, or the same target file multiple times (changing at least @code{CHIPNAME}). Likewise, the target configuration file should define @code{_TARGETNAME} (or @code{_TARGETNAME0} etc) and use it later on when defining debug targets: @example set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME @end example @subsection Adding TAPs to the Scan Chain After the ``defaults'' are set up, add the TAPs on each chip to the JTAG scan chain. @xref{TAP Declaration}, and the naming convention for taps. In the simplest case the chip has only one TAP, probably for a CPU or FPGA. The config file for the Atmel AT91SAM7X256 looks (in part) like this: @example jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID @end example A board with two such at91sam7 chips would be able to source such a config file twice, with different values for @code{CHIPNAME}, so it adds a different TAP each time. If there are nonzero @option{-expected-id} values, OpenOCD attempts to verify the actual tap id against those values. It will issue error messages if there is mismatch, which can help to pinpoint problems in OpenOCD configurations. @example JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (Manufacturer: 0x787, Part: 0xf0f0, Version: 0x3) ERROR: Tap: sam7x256.cpu - Expected id: 0x12345678, Got: 0x3f0f0f0f ERROR: expected: mfg: 0x33c, part: 0x2345, ver: 0x1 ERROR: got: mfg: 0x787, part: 0xf0f0, ver: 0x3 @end example There are more complex examples too, with chips that have multiple TAPs. Ones worth looking at include: @itemize @item @file{target/omap3530.cfg} -- with disabled ARM and DSP, plus a JRC to enable them @item @file{target/str912.cfg} -- with flash, CPU, and boundary scan @item @file{target/ti_dm355.cfg} -- with ETM, ARM, and JRC (this JRC is not currently used) @end itemize @subsection Add CPU targets After adding a TAP for a CPU, you should set it up so that GDB and other commands can use it. @xref{CPU Configuration}. For the at91sam7 example above, the command can look like this; note that @code{$_ENDIAN} is not needed, since OpenOCD defaults to little endian, and this chip doesn't support changing that. @example set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME @end example Work areas are small RAM areas associated with CPU targets. They are used by OpenOCD to speed up downloads, and to download small snippets of code to program flash chips. If the chip includes a form of ``on-chip-ram'' - and many do - define a work area if you can. Again using the at91sam7 as an example, this can look like: @example $_TARGETNAME configure -work-area-phys 0x00200000 \ -work-area-size 0x4000 -work-area-backup 0 @end example @anchor{definecputargetsworkinginsmp} @subsection Define CPU targets working in SMP @cindex SMP After setting targets, you can define a list of targets working in SMP. @example set _TARGETNAME_1 $_CHIPNAME.cpu1 set _TARGETNAME_2 $_CHIPNAME.cpu2 target create $_TARGETNAME_1 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase $_DAP_DBG1 target create $_TARGETNAME_2 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 1 -dbgbase $_DAP_DBG2 #define 2 targets working in smp. target smp $_CHIPNAME.cpu2 $_CHIPNAME.cpu1 @end example In the above example on cortex_a, 2 cpus are working in SMP. In SMP only one GDB instance is created and : @itemize @bullet @item a set of hardware breakpoint sets the same breakpoint on all targets in the list. @item halt command triggers the halt of all targets in the list. @item resume command triggers the write context and the restart of all targets in the list. @item following a breakpoint: the target stopped by the breakpoint is displayed to the GDB session. @item dedicated GDB serial protocol packets are implemented for switching/retrieving the target displayed by the GDB session @pxref{usingopenocdsmpwithgdb,,Using OpenOCD SMP with GDB}. @end itemize The SMP behaviour can be disabled/enabled dynamically. On cortex_a following command have been implemented. @itemize @bullet @item cortex_a smp_on : enable SMP mode, behaviour is as described above. @item cortex_a smp_off : disable SMP mode, the current target is the one displayed in the GDB session, only this target is now controlled by GDB session. This behaviour is useful during system boot up. @item cortex_a smp_gdb : display/fix the core id displayed in GDB session see following example. @end itemize @example >cortex_a smp_gdb gdb coreid 0 -> -1 #0 : coreid 0 is displayed to GDB , #-> -1 : next resume triggers a real resume > cortex_a smp_gdb 1 gdb coreid 0 -> 1 #0 :coreid 0 is displayed to GDB , #->1 : next resume displays coreid 1 to GDB > resume > cortex_a smp_gdb gdb coreid 1 -> 1 #1 :coreid 1 is displayed to GDB , #->1 : next resume displays coreid 1 to GDB > cortex_a smp_gdb -1 gdb coreid 1 -> -1 #1 :coreid 1 is displayed to GDB, #->-1 : next resume triggers a real resume @end example @subsection Chip Reset Setup As a rule, you should put the @command{reset_config} command into the board file. Most things you think you know about a chip can be tweaked by the board. Some chips have specific ways the TRST and SRST signals are managed. In the unusual case that these are @emph{chip specific} and can never be changed by board wiring, they could go here. For example, some chips can't support JTAG debugging without both signals. Provide a @code{reset-assert} event handler if you can. Such a handler uses JTAG operations to reset the target, letting this target config be used in systems which don't provide the optional SRST signal, or on systems where you don't want to reset all targets at once. Such a handler might write to chip registers to force a reset, use a JRC to do that (preferable -- the target may be wedged!), or force a watchdog timer to trigger. (For Cortex-M targets, this is not necessary. The target driver knows how to use trigger an NVIC reset when SRST is not available.) Some chips need special attention during reset handling if they're going to be used with JTAG. An example might be needing to send some commands right after the target's TAP has been reset, providing a @code{reset-deassert-post} event handler that writes a chip register to report that JTAG debugging is being done. Another would be reconfiguring the watchdog so that it stops counting while the core is halted in the debugger. JTAG clocking constraints often change during reset, and in some cases target config files (rather than board config files) are the right places to handle some of those issues. For example, immediately after reset most chips run using a slower clock than they will use later. That means that after reset (and potentially, as OpenOCD first starts up) they must use a slower JTAG clock rate than they will use later. @xref{jtagspeed,,JTAG Speed}. @quotation Important When you are debugging code that runs right after chip reset, getting these issues right is critical. In particular, if you see intermittent failures when OpenOCD verifies the scan chain after reset, look at how you are setting up JTAG clocking. @end quotation @anchor{theinittargetsprocedure} @subsection The init_targets procedure @cindex init_targets procedure Target config files can either be ``linear'' (script executed line-by-line when parsed in configuration stage, @xref{configurationstage,,Configuration Stage},) or they can contain a special procedure called @code{init_targets}, which will be executed when entering run stage (after parsing all config files or after @code{init} command, @xref{enteringtherunstage,,Entering the Run Stage}.) Such procedure can be overriden by ``next level'' script (which sources the original). This concept faciliates code reuse when basic target config files provide generic configuration procedures and @code{init_targets} procedure, which can then be sourced and enchanced or changed in a ``more specific'' target config file. This is not possible with ``linear'' config scripts, because sourcing them executes every initialization commands they provide. @example ### generic_file.cfg ### proc setup_my_chip @{chip_name flash_size ram_size@} @{ # basic initialization procedure ... @} proc init_targets @{@} @{ # initializes generic chip with 4kB of flash and 1kB of RAM setup_my_chip MY_GENERIC_CHIP 4096 1024 @} ### specific_file.cfg ### source [find target/generic_file.cfg] proc init_targets @{@} @{ # initializes specific chip with 128kB of flash and 64kB of RAM setup_my_chip MY_CHIP_WITH_128K_FLASH_64KB_RAM 131072 65536 @} @end example The easiest way to convert ``linear'' config files to @code{init_targets} version is to enclose every line of ``code'' (i.e. not @code{source} commands, procedures, etc.) in this procedure. For an example of this scheme see LPC2000 target config files. The @code{init_boards} procedure is a similar concept concerning board config files (@xref{theinitboardprocedure,,The init_board procedure}.) @anchor{theinittargeteventsprocedure} @subsection The init_target_events procedure @cindex init_target_events procedure A special procedure called @code{init_target_events} is run just after @code{init_targets} (@xref{theinittargetsprocedure,,The init_targets procedure}.) and before @code{init_board} (@xref{theinitboardprocedure,,The init_board procedure}.) It is used to set up default target events for the targets that do not have those events already assigned. @subsection ARM Core Specific Hacks If the chip has a DCC, enable it. If the chip is an ARM9 with some special high speed download features - enable it. If present, the MMU, the MPU and the CACHE should be disabled. Some ARM cores are equipped with trace support, which permits examination of the instruction and data bus activity. Trace activity is controlled through an ``Embedded Trace Module'' (ETM) on one of the core's scan chains. The ETM emits voluminous data through a ``trace port''. (@xref{armhardwaretracing,,ARM Hardware Tracing}.) If you are using an external trace port, configure it in your board config file. If you are using an on-chip ``Embedded Trace Buffer'' (ETB), configure it in your target config file. @example etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb @end example @subsection Internal Flash Configuration This applies @b{ONLY TO MICROCONTROLLERS} that have flash built in. @b{Never ever} in the ``target configuration file'' define any type of flash that is external to the chip. (For example a BOOT flash on Chip Select 0.) Such flash information goes in a board file - not the TARGET (chip) file. Examples: @itemize @bullet @item at91sam7x256 - has 256K flash YES enable it. @item str912 - has flash internal YES enable it. @item imx27 - uses boot flash on CS0 - it goes in the board file. @item pxa270 - again - CS0 flash - it goes in the board file. @end itemize @anchor{translatingconfigurationfiles} @section Translating Configuration Files @cindex translation If you have a configuration file for another hardware debugger or toolset (Abatron, BDI2000, BDI3000, CCS, Lauterbach, Segger, Macraigor, etc.), translating it into OpenOCD syntax is often quite straightforward. The most tricky part of creating a configuration script is oftentimes the reset init sequence where e.g. PLLs, DRAM and the like is set up. One trick that you can use when translating is to write small Tcl procedures to translate the syntax into OpenOCD syntax. This can avoid manual translation errors and make it easier to convert other scripts later on. Example of transforming quirky arguments to a simple search and replace job: @example # Lauterbach syntax(?) # # Data.Set c15:0x042f %long 0x40000015 # # OpenOCD syntax when using procedure below. # # setc15 0x01 0x00050078 proc setc15 @{regs value@} @{ global TARGETNAME echo [format "set p15 0x%04x, 0x%08x" $regs $value] arm mcr 15 [expr ($regs>>12)&0x7] \ [expr ($regs>>0)&0xf] [expr ($regs>>4)&0xf] \ [expr ($regs>>8)&0x7] $value @} @end example @node Daemon Configuration @chapter Daemon Configuration @cindex initialization The commands here are commonly found in the openocd.cfg file and are used to specify what TCP/IP ports are used, and how GDB should be supported. @anchor{configurationstage} @section Configuration Stage @cindex configuration stage @cindex config command When the OpenOCD server process starts up, it enters a @emph{configuration stage} which is the only time that certain commands, @emph{configuration commands}, may be issued. Normally, configuration commands are only available inside startup scripts. In this manual, the definition of a configuration command is presented as a @emph{Config Command}, not as a @emph{Command} which may be issued interactively. The runtime @command{help} command also highlights configuration commands, and those which may be issued at any time. Those configuration commands include declaration of TAPs, flash banks, the interface used for JTAG communication, and other basic setup. The server must leave the configuration stage before it may access or activate TAPs. After it leaves this stage, configuration commands may no longer be issued. @anchor{enteringtherunstage} @section Entering the Run Stage The first thing OpenOCD does after leaving the configuration stage is to verify that it can talk to the scan chain (list of TAPs) which has been configured. It will warn if it doesn't find TAPs it expects to find, or finds TAPs that aren't supposed to be there. You should see no errors at this point. If you see errors, resolve them by correcting the commands you used to configure the server. Common errors include using an initial JTAG speed that's too fast, and not providing the right IDCODE values for the TAPs on the scan chain. Once OpenOCD has entered the run stage, a number of commands become available. A number of these relate to the debug targets you may have declared. For example, the @command{mww} command will not be available until a target has been successfuly instantiated. If you want to use those commands, you may need to force entry to the run stage. @deffn {Config Command} init This command terminates the configuration stage and enters the run stage. This helps when you need to have the startup scripts manage tasks such as resetting the target, programming flash, etc. To reset the CPU upon startup, add "init" and "reset" at the end of the config script or at the end of the OpenOCD command line using the @option{-c} command line switch. If this command does not appear in any startup/configuration file OpenOCD executes the command for you after processing all configuration files and/or command line options. @b{NOTE:} This command normally occurs at or near the end of your openocd.cfg file to force OpenOCD to ``initialize'' and make the targets ready. For example: If your openocd.cfg file needs to read/write memory on your target, @command{init} must occur before the memory read/write commands. This includes @command{nand probe}. @end deffn @deffn {Overridable Procedure} jtag_init This is invoked at server startup to verify that it can talk to the scan chain (list of TAPs) which has been configured. The default implementation first tries @command{jtag arp_init}, which uses only a lightweight JTAG reset before examining the scan chain. If that fails, it tries again, using a harder reset from the overridable procedure @command{init_reset}. Implementations must have verified the JTAG scan chain before they return. This is done by calling @command{jtag arp_init} (or @command{jtag arp_init-reset}). @end deffn @anchor{tcpipports} @section TCP/IP Ports @cindex TCP port @cindex server @cindex port @cindex security The OpenOCD server accepts remote commands in several syntaxes. Each syntax uses a different TCP/IP port, which you may specify only during configuration (before those ports are opened). For reasons including security, you may wish to prevent remote access using one or more of these ports. In such cases, just specify the relevant port number as zero. If you disable all access through TCP/IP, you will need to use the command line @option{-pipe} option. @deffn {Command} gdb_port [number] @cindex GDB server Normally gdb listens to a TCP/IP port, but GDB can also communicate via pipes(stdin/out or named pipes). The name "gdb_port" stuck because it covers probably more than 90% of the normal use cases. No arguments reports GDB port. "pipe" means listen to stdin output to stdout, an integer is base port number, "disable" disables the gdb server. When using "pipe", also use log_output to redirect the log output to a file so as not to flood the stdin/out pipes. The -p/--pipe option is deprecated and a warning is printed as it is equivalent to passing in -c "gdb_port pipe; log_output openocd.log". Any other string is interpreted as named pipe to listen to. Output pipe is the same name as input pipe, but with 'o' appended, e.g. /var/gdb, /var/gdbo. The GDB port for the first target will be the base port, the second target will listen on gdb_port + 1, and so on. When not specified during the configuration stage, the port @var{number} defaults to 3333. @end deffn @deffn {Command} tcl_port [number] Specify or query the port used for a simplified RPC connection that can be used by clients to issue TCL commands and get the output from the Tcl engine. Intended as a machine interface. When not specified during the configuration stage, the port @var{number} defaults to 6666. @end deffn @deffn {Command} telnet_port [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. When not specified during the configuration stage, the port @var{number} defaults to 4444. When specified as zero, this port is not activated. @end deffn @anchor{gdbconfiguration} @section GDB Configuration @cindex GDB @cindex GDB configuration You can reconfigure some GDB behaviors if needed. The ones listed here are static and global. @xref{targetconfiguration,,Target Configuration}, about configuring individual targets. @xref{targetevents,,Target Events}, about configuring target-specific event handling. @anchor{gdbbreakpointoverride} @deffn {Command} gdb_breakpoint_override [@option{hard}|@option{soft}|@option{disable}] Force breakpoint type for gdb @command{break} commands. This option supports GDB GUIs which don't distinguish hard versus soft breakpoints, if the default OpenOCD and GDB behaviour is not sufficient. GDB normally uses hardware breakpoints if the memory map has been set up for flash regions. @end deffn @anchor{gdbflashprogram} @deffn {Config Command} gdb_flash_program (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to program the flash memory when a vFlash packet is received. The default behaviour is @option{enable}. @end deffn @deffn {Config Command} gdb_memory_map (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the memory configuration to GDB when requested. GDB will then know when to set hardware breakpoints, and program flash using the GDB load command. @command{gdb_flash_program enable} must also be enabled for flash programming to work. Default behaviour is @option{enable}. @xref{gdbflashprogram,,gdb_flash_program}. @end deffn @deffn {Config Command} gdb_report_data_abort (@option{enable}|@option{disable}) Specifies whether data aborts cause an error to be reported by GDB memory read packets. The default behaviour is @option{disable}; use @option{enable} see these errors reported. @end deffn @deffn {Config Command} gdb_target_description (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the target descriptions to gdb via qXfer:features:read packet. The default behaviour is @option{enable}. @end deffn @deffn {Command} gdb_save_tdesc Saves the target descripton file to the local file system. The file name is @i{target_name}.xml. @end deffn @anchor{eventpolling} @section Event Polling Hardware debuggers are parts of asynchronous systems, where significant events can happen at any time. The OpenOCD server needs to detect some of these events, so it can report them to through TCL command line or to GDB. Examples of such events include: @itemize @item One of the targets can stop running ... maybe it triggers a code breakpoint or data watchpoint, or halts itself. @item Messages may be sent over ``debug message'' channels ... many targets support such messages sent over JTAG, for receipt by the person debugging or tools. @item Loss of power ... some adapters can detect these events. @item Resets not issued through JTAG ... such reset sources can include button presses or other system hardware, sometimes including the target itself (perhaps through a watchdog). @item Debug instrumentation sometimes supports event triggering such as ``trace buffer full'' (so it can quickly be emptied) or other signals (to correlate with code behavior). @end itemize None of those events are signaled through standard JTAG signals. However, most conventions for JTAG connectors include voltage level and system reset (SRST) signal detection. Some connectors also include instrumentation signals, which can imply events when those signals are inputs. In general, OpenOCD needs to periodically check for those events, either by looking at the status of signals on the JTAG connector or by sending synchronous ``tell me your status'' JTAG requests to the various active targets. There is a command to manage and monitor that polling, which is normally done in the background. @deffn Command poll [@option{on}|@option{off}] Poll the current target for its current state. (Also, @pxref{targetcurstate,,target curstate}.) If that target is in debug mode, architecture specific information about the current state is printed. An optional parameter allows background polling to be enabled and disabled. You could use this from the TCL command shell, or from GDB using @command{monitor poll} command. Leave background polling enabled while you're using GDB. @example > poll background polling: on target state: halted target halted in ARM state due to debug-request, \ current mode: Supervisor cpsr: 0x800000d3 pc: 0x11081bfc MMU: disabled, D-Cache: disabled, I-Cache: enabled > @end example @end deffn @node Debug Adapter Configuration @chapter Debug Adapter Configuration @cindex config file, interface @cindex interface config file Correctly installing OpenOCD includes making your operating system give OpenOCD access to debug adapters. Once that has been done, Tcl commands are used to select which one is used, and to configure how it is used. @quotation Note Because OpenOCD started out with a focus purely on JTAG, you may find places where it wrongly presumes JTAG is the only transport protocol in use. Be aware that recent versions of OpenOCD are removing that limitation. JTAG remains more functional than most other transports. Other transports do not support boundary scan operations, or may be specific to a given chip vendor. Some might be usable only for programming flash memory, instead of also for debugging. @end quotation Debug Adapters/Interfaces/Dongles are normally configured through commands in an interface configuration file which is sourced by your @file{openocd.cfg} file, or through a command line @option{-f interface/....cfg} option. @example source [find interface/olimex-jtag-tiny.cfg] @end example These commands tell OpenOCD what type of JTAG adapter you have, and how to talk to it. A few cases are so simple that you only need to say what driver to use: @example # jlink interface interface jlink @end example Most adapters need a bit more configuration than that. @section Interface Configuration The interface command tells OpenOCD what type of debug adapter you are using. Depending on the type of adapter, you may need to use one or more additional commands to further identify or configure the adapter. @deffn {Config Command} {interface} name Use the interface driver @var{name} to connect to the target. @end deffn @deffn Command {interface_list} List the debug adapter drivers that have been built into the running copy of OpenOCD. @end deffn @deffn Command {interface transports} transport_name+ Specifies the transports supported by this debug adapter. The adapter driver builds-in similar knowledge; use this only when external configuration (such as jumpering) changes what the hardware can support. @end deffn @deffn Command {adapter_name} Returns the name of the debug adapter driver being used. @end deffn @section Interface Drivers Each of the interface drivers listed here must be explicitly enabled when OpenOCD is configured, in order to be made available at run time. @deffn {Interface Driver} {amt_jtagaccel} Amontec Chameleon in its JTAG Accelerator configuration, connected to a PC's EPP mode parallel port. This defines some driver-specific commands: @deffn {Config Command} {parport_port} number Specifies either the address of the I/O port (default: 0x378 for LPT1) or the number of the @file{/dev/parport} device. @end deffn @deffn {Config Command} rtck [@option{enable}|@option{disable}] Displays status of RTCK option. Optionally sets that option first. @end deffn @end deffn @deffn {Interface Driver} {arm-jtag-ew} Olimex ARM-JTAG-EW USB adapter This has one driver-specific command: @deffn Command {armjtagew_info} Logs some status @end deffn @end deffn @deffn {Interface Driver} {at91rm9200} Supports bitbanged JTAG from the local system, presuming that system is an Atmel AT91rm9200 and a specific set of GPIOs is used. @c command: at91rm9200_device NAME @c chooses among list of bit configs ... only one option @end deffn @deffn {Interface Driver} {cmsis-dap} ARM CMSIS-DAP compliant based adapter. @deffn {Config Command} {cmsis_dap_vid_pid} [vid pid]+ The vendor ID and product ID of the CMSIS-DAP device. If not specified the driver will attempt to auto detect the CMSIS-DAP device. Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. @example cmsis_dap_vid_pid 0xc251 0xf001 0x0d28 0x0204 @end example @end deffn @deffn {Config Command} {cmsis_dap_serial} [serial] Specifies the @var{serial} of the CMSIS-DAP device to use. If not specified, serial numbers are not considered. @end deffn @deffn {Command} {cmsis-dap info} Display various device information, like hardware version, firmware version, current bus status. @end deffn @end deffn @deffn {Interface Driver} {dummy} A dummy software-only driver for debugging. @end deffn @deffn {Interface Driver} {ep93xx} Cirrus Logic EP93xx based single-board computer bit-banging (in development) @end deffn @deffn {Interface Driver} {ft2232} FTDI FT2232 (USB) based devices over one of the userspace libraries. Note that this driver has several flaws and the @command{ftdi} driver is recommended as its replacement. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: @deffn {Config Command} {ft2232_device_desc} description Provides the USB device description (the @emph{iProduct string}) of the FTDI FT2232 device. If not specified, the FTDI default value is used. This setting is only valid if compiled with FTD2XX support. @end deffn @deffn {Config Command} {ft2232_serial} serial-number Specifies the @var{serial-number} of the FTDI FT2232 device to use, in case the vendor provides unique IDs and more than one FT2232 device is connected to the host. If not specified, serial numbers are not considered. (Note that USB serial numbers can be arbitrary Unicode strings, and are not restricted to containing only decimal digits.) @end deffn @deffn {Config Command} {ft2232_layout} name Each vendor's FT2232 device can use different GPIO signals to control output-enables, reset signals, and LEDs. Currently valid layout @var{name} values include: @itemize @minus @item @b{axm0432_jtag} Axiom AXM-0432 @item @b{comstick} Hitex STR9 comstick @item @b{cortino} Hitex Cortino JTAG interface @item @b{evb_lm3s811} TI/Luminary Micro EVB_LM3S811 as a JTAG interface, either for the local Cortex-M3 (SRST only) or in a passthrough mode (neither SRST nor TRST) This layout can not support the SWO trace mechanism, and should be used only for older boards (before rev C). @item @b{luminary_icdi} This layout should be used with most TI/Luminary eval boards, including Rev C LM3S811 eval boards and the eponymous ICDI boards, to debug either the local Cortex-M3 or in passthrough mode to debug some other target. It can support the SWO trace mechanism. @item @b{flyswatter} Tin Can Tools Flyswatter @item @b{icebear} ICEbear JTAG adapter from Section 5 @item @b{jtagkey} Amontec JTAGkey and JTAGkey-Tiny (and compatibles) @item @b{jtagkey2} Amontec JTAGkey2 (and compatibles) @item @b{m5960} American Microsystems M5960 @item @b{olimex-jtag} Olimex ARM-USB-OCD and ARM-USB-Tiny @item @b{oocdlink} OOCDLink @c oocdlink ~= jtagkey_prototype_v1 @item @b{redbee-econotag} Integrated with a Redbee development board. @item @b{redbee-usb} Integrated with a Redbee USB-stick development board. @item @b{sheevaplug} Marvell Sheevaplug development kit @item @b{signalyzer} Xverve Signalyzer @item @b{stm32stick} Hitex STM32 Performance Stick @item @b{turtelizer2} egnite Software turtelizer2 @item @b{usbjtag} "USBJTAG-1" layout described in the OpenOCD diploma thesis @end itemize @end deffn @deffn {Config Command} {ft2232_vid_pid} [vid pid]+ The vendor ID and product ID of the FTDI FT2232 device. If not specified, the FTDI default values are used. Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. @example ft2232_vid_pid 0x0403 0xcff8 0x15ba 0x0003 @end example @end deffn @deffn {Config Command} {ft2232_latency} ms On some systems using FT2232 based JTAG interfaces the FT_Read function call in ft2232_read() fails to return the expected number of bytes. This can be caused by USB communication delays and has proved hard to reproduce and debug. Setting the FT2232 latency timer to a larger value increases delays for short USB packets but it also reduces the risk of timeouts before receiving the expected number of bytes. The OpenOCD default value is 2 and for some systems a value of 10 has proved useful. @end deffn @deffn {Config Command} {ft2232_channel} channel Used to select the channel of the ft2232 chip to use (between 1 and 4). The default value is 1. @end deffn For example, the interface config file for a Turtelizer JTAG Adapter looks something like this: @example interface ft2232 ft2232_device_desc "Turtelizer JTAG/RS232 Adapter" ft2232_layout turtelizer2 ft2232_vid_pid 0x0403 0xbdc8 @end example @end deffn @deffn {Interface Driver} {ftdi} This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. It is a complete rewrite to address a large number of problems with the ft2232 interface driver. The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, bypassing intermediate libraries like libftdi of D2XX. Performance-wise it is consistently faster than the ft2232 driver, sometimes several times faster. A major improvement of this driver is that support for new FTDI based adapters can be added competely through configuration files, without the need to patch and rebuild OpenOCD. The driver uses a signal abstraction to enable Tcl configuration files to define outputs for one or several FTDI GPIO. These outputs can then be controlled using the @command{ftdi_set_signal} command. Special signal names are reserved for nTRST, nSRST and LED (for blink) so that they, if defined, will be used for their customary purpose. Depending on the type of buffer attached to the FTDI GPIO, the outputs have to be controlled differently. In order to support tristateable signals such as nSRST, both a data GPIO and an output-enable GPIO can be specified for each signal. The following output buffer configurations are supported: @itemize @minus @item Push-pull with one FTDI output as (non-)inverted data line @item Open drain with one FTDI output as (non-)inverted output-enable @item Tristate with one FTDI output as (non-)inverted data line and another FTDI output as (non-)inverted output-enable @item Unbuffered, using the FTDI GPIO as a tristate output directly by switching data and direction as necessary @end itemize These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: @deffn {Config Command} {ftdi_vid_pid} [vid pid]+ The vendor ID and product ID of the adapter. If not specified, the FTDI default values are used. Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. @example ftdi_vid_pid 0x0403 0xcff8 0x15ba 0x0003 @end example @end deffn @deffn {Config Command} {ftdi_device_desc} description Provides the USB device description (the @emph{iProduct string}) of the adapter. If not specified, the device description is ignored during device selection. @end deffn @deffn {Config Command} {ftdi_serial} serial-number Specifies the @var{serial-number} of the adapter to use, in case the vendor provides unique IDs and more than one adapter is connected to the host. If not specified, serial numbers are not considered. (Note that USB serial numbers can be arbitrary Unicode strings, and are not restricted to containing only decimal digits.) @end deffn @deffn {Config Command} {ftdi_channel} channel Selects the channel of the FTDI device to use for MPSSE operations. Most adapters use the default, channel 0, but there are exceptions. @end deffn @deffn {Config Command} {ftdi_layout_init} data direction Specifies the initial values of the FTDI GPIO data and direction registers. Each value is a 16-bit number corresponding to the concatenation of the high and low FTDI GPIO registers. The values should be selected based on the schematics of the adapter, such that all signals are set to safe levels with minimal impact on the target system. Avoid floating inputs, conflicting outputs and initially asserted reset signals. @end deffn @deffn {Config Command} {ftdi_layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name] Creates a signal with the specified @var{name}, controlled by one or more FTDI GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO register bitmasks to tell the driver the connection and type of the output buffer driving the respective signal. @var{data_mask} is the bitmask for the pin(s) connected to the data input of the output buffer. @option{-ndata} is used with inverting data inputs and @option{-data} with non-inverting inputs. The @option{-oe} (or @option{-noe}) option tells where the output-enable (or not-output-enable) input to the output buffer is connected. Both @var{data_mask} and @var{oe_mask} need not be specified. For example, a simple open-collector transistor driver would be specified with @option{-oe} only. In that case the signal can only be set to drive low or to Hi-Z and the driver will complain if the signal is set to drive high. Which means that if it's a reset signal, @command{reset_config} must be specified as @option{srst_open_drain}, not @option{srst_push_pull}. A special case is provided when @option{-data} and @option{-oe} is set to the same bitmask. Then the FTDI pin is considered being connected straight to the target without any buffer. The FTDI pin is then switched between output and input as necessary to provide the full set of low, high and Hi-Z characteristics. In all other cases, the pins specified in a signal definition are always driven by the FTDI. If @option{-alias} or @option{-nalias} is used, the signal is created identical (or with data inverted) to an already specified signal @var{name}. @end deffn @deffn {Command} {ftdi_set_signal} name @option{0}|@option{1}|@option{z} Set a previously defined signal to the specified level. @itemize @minus @item @option{0}, drive low @item @option{1}, drive high @item @option{z}, set to high-impedance @end itemize @end deffn For example adapter definitions, see the configuration files shipped in the @file{interface/ftdi} directory. @end deffn @deffn {Interface Driver} {remote_bitbang} Drive JTAG from a remote process. This sets up a UNIX or TCP socket connection with a remote process and sends ASCII encoded bitbang requests to that process instead of directly driving JTAG. The remote_bitbang driver is useful for debugging software running on processors which are being simulated. @deffn {Config Command} {remote_bitbang_port} number Specifies the TCP port of the remote process to connect to or 0 to use UNIX sockets instead of TCP. @end deffn @deffn {Config Command} {remote_bitbang_host} hostname Specifies the hostname of the remote process to connect to using TCP, or the name of the UNIX socket to use if remote_bitbang_port is 0. @end deffn For example, to connect remotely via TCP to the host foobar you might have something like: @example interface remote_bitbang remote_bitbang_port 3335 remote_bitbang_host foobar @end example To connect to another process running locally via UNIX sockets with socket named mysocket: @example interface remote_bitbang remote_bitbang_port 0 remote_bitbang_host mysocket @end example @end deffn @deffn {Interface Driver} {usb_blaster} USB JTAG/USB-Blaster compatibles over one of the userspace libraries for FTDI chips. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: @deffn {Config Command} {usb_blaster_device_desc} description Provides the USB device description (the @emph{iProduct string}) of the FTDI FT245 device. If not specified, the FTDI default value is used. This setting is only valid if compiled with FTD2XX support. @end deffn @deffn {Config Command} {usb_blaster_vid_pid} vid pid The vendor ID and product ID of the FTDI FT245 device. If not specified, default values are used. Currently, only one @var{vid}, @var{pid} pair may be given, e.g. for Altera USB-Blaster (default): @example usb_blaster_vid_pid 0x09FB 0x6001 @end example The following VID/PID is for Kolja Waschk's USB JTAG: @example usb_blaster_vid_pid 0x16C0 0x06AD @end example @end deffn @deffn {Command} {usb_blaster_pin} (@option{pin6}|@option{pin8}) (@option{0}|@option{1}|@option{s}|@option{t}) Sets the state or function of the unused GPIO pins on USB-Blasters (pins 6 and 8 on the female JTAG header). These pins can be used as SRST and/or TRST provided the appropriate connections are made on the target board. For example, to use pin 6 as SRST: @example usb_blaster_pin pin6 s reset_config srst_only @end example @end deffn @deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ftd2xx}|@option{ublast2}) Chooses the low level access method for the adapter. If not specified, @option{ftdi} is selected unless it wasn't enabled during the configure stage. USB-Blaster II needs @option{ublast2}. @end deffn @deffn {Command} {usb_blaster_firmware} @var{path} This command specifies @var{path} to access USB-Blaster II firmware image. To be used with USB-Blaster II only. @end deffn @end deffn @deffn {Interface Driver} {gw16012} Gateworks GW16012 JTAG programmer. This has one driver-specific command: @deffn {Config Command} {parport_port} [port_number] Display either the address of the I/O port (default: 0x378 for LPT1) or the number of the @file{/dev/parport} device. If a parameter is provided, first switch to use that port. This is a write-once setting. @end deffn @end deffn @deffn {Interface Driver} {jlink} Segger J-Link family of USB adapters. It currently supports JTAG and SWD transports. @quotation Compatibility Note Segger released many firmware versions for the many harware versions they produced. OpenOCD was extensively tested and intended to run on all of them, but some combinations were reported as incompatible. As a general recommendation, it is advisable to use the latest firmware version available for each hardware version. However the current V8 is a moving target, and Segger firmware versions released after the OpenOCD was released may not be compatible. In such cases it is recommended to revert to the last known functional version. For 0.5.0, this is from "Feb 8 2012 14:30:39", packed with 4.42c. For 0.6.0, the last known version is from "May 3 2012 18:36:22", packed with 4.46f. @end quotation @deffn {Command} {jlink caps} Display the device firmware capabilities. @end deffn @deffn {Command} {jlink info} Display various device information, like hardware version, firmware version, current bus status. @end deffn @deffn {Command} {jlink hw_jtag} [@option{2}|@option{3}] Set the JTAG protocol version to be used. Without argument, show the actual JTAG protocol version. @end deffn @deffn {Command} {jlink config} Display the J-Link configuration. @end deffn @deffn {Command} {jlink config kickstart} [val] Set the Kickstart power on JTAG-pin 19. Without argument, show the Kickstart configuration. @end deffn @deffn {Command} {jlink config mac_address} [@option{ff:ff:ff:ff:ff:ff}] Set the MAC address of the J-Link Pro. Without argument, show the MAC address. @end deffn @deffn {Command} {jlink config ip} [@option{A.B.C.D}(@option{/E}|@option{F.G.H.I})] Set the IP configuration of the J-Link Pro, where A.B.C.D is the IP address, E the bit of the subnet mask and F.G.H.I the subnet mask. Without arguments, show the IP configuration. @end deffn @deffn {Command} {jlink config usb_address} [@option{0x00} to @option{0x03} or @option{0xff}] Set the USB address; this will also change the product id. Without argument, show the USB address. @end deffn @deffn {Command} {jlink config reset} Reset the current configuration. @end deffn @deffn {Command} {jlink config save} Save the current configuration to the internal persistent storage. @end deffn @deffn {Config} {jlink pid} val Set the USB PID of the interface. As a configuration command, it can be used only before 'init'. @end deffn @deffn {Config} {jlink serial} serial-number Set the @var{serial-number} of the interface, in case more than one adapter is connected to the host. If not specified, serial numbers are not considered. Note that there may be leading zeros in the @var{serial-number} string that will not show in the Segger software, but must be specified here. Debug level 3 output contains serial numbers if there is a mismatch. As a configuration command, it can be used only before 'init'. @end deffn @end deffn @deffn {Interface Driver} {parport} Supports PC parallel port bit-banging cables: Wigglers, PLD download cable, and more. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: @deffn {Config Command} {parport_cable} name Set the layout of the parallel port cable used to connect to the target. This is a write-once setting. Currently valid cable @var{name} values include: @itemize @minus @item @b{altium} Altium Universal JTAG cable. @item @b{arm-jtag} Same as original wiggler except SRST and TRST connections reversed and TRST is also inverted. @item @b{chameleon} The Amontec Chameleon's CPLD when operated in configuration mode. This is only used to program the Chameleon itself, not a connected target. @item @b{dlc5} The Xilinx Parallel cable III. @item @b{flashlink} The ST Parallel cable. @item @b{lattice} Lattice ispDOWNLOAD Cable @item @b{old_amt_wiggler} The Wiggler configuration that comes with some versions of Amontec's Chameleon Programmer. The new version available from the website uses the original Wiggler layout ('@var{wiggler}') @item @b{triton} The parallel port adapter found on the ``Karo Triton 1 Development Board''. This is also the layout used by the HollyGates design (see @uref{http://www.lartmaker.nl/projects/jtag/}). @item @b{wiggler} The original Wiggler layout, also supported by several clones, such as the Olimex ARM-JTAG @item @b{wiggler2} Same as original wiggler except an led is fitted on D5. @item @b{wiggler_ntrst_inverted} Same as original wiggler except TRST is inverted. @end itemize @end deffn @deffn {Config Command} {parport_port} [port_number] Display either the address of the I/O port (default: 0x378 for LPT1) or the number of the @file{/dev/parport} device. If a parameter is provided, first switch to use that port. This is a write-once setting. When using PPDEV to access the parallel port, use the number of the parallel port: @option{parport_port 0} (the default). If @option{parport_port 0x378} is specified you may encounter a problem. @end deffn @deffn Command {parport_toggling_time} [nanoseconds] Displays how many nanoseconds the hardware needs to toggle TCK; the parport driver uses this value to obey the @command{adapter_khz} configuration. When the optional @var{nanoseconds} parameter is given, that setting is changed before displaying the current value. The default setting should work reasonably well on commodity PC hardware. However, you may want to calibrate for your specific hardware. @quotation Tip To measure the toggling time with a logic analyzer or a digital storage oscilloscope, follow the procedure below: @example > parport_toggling_time 1000 > adapter_khz 500 @end example This sets the maximum JTAG clock speed of the hardware, but the actual speed probably deviates from the requested 500 kHz. Now, measure the time between the two closest spaced TCK transitions. You can use @command{runtest 1000} or something similar to generate a large set of samples. Update the setting to match your measurement: @example > parport_toggling_time @end example Now the clock speed will be a better match for @command{adapter_khz rate} commands given in OpenOCD scripts and event handlers. You can do something similar with many digital multimeters, but note that you'll probably need to run the clock continuously for several seconds before it decides what clock rate to show. Adjust the toggling time up or down until the measured clock rate is a good match for the adapter_khz rate you specified; be conservative. @end quotation @end deffn @deffn {Config Command} {parport_write_on_exit} (@option{on}|@option{off}) This will configure the parallel driver to write a known cable-specific value to the parallel interface on exiting OpenOCD. @end deffn For example, the interface configuration file for a classic ``Wiggler'' cable on LPT2 might look something like this: @example interface parport parport_port 0x278 parport_cable wiggler @end example @end deffn @deffn {Interface Driver} {presto} ASIX PRESTO USB JTAG programmer. @deffn {Config Command} {presto_serial} serial_string Configures the USB serial number of the Presto device to use. @end deffn @end deffn @deffn {Interface Driver} {rlink} Raisonance RLink USB adapter @end deffn @deffn {Interface Driver} {usbprog} usbprog is a freely programmable USB adapter. @end deffn @deffn {Interface Driver} {vsllink} vsllink is part of Versaloon which is a versatile USB programmer. @quotation Note This defines quite a few driver-specific commands, which are not currently documented here. @end quotation @end deffn @anchor{hla_interface} @deffn {Interface Driver} {hla} This is a driver that supports multiple High Level Adapters. This type of adapter does not expose some of the lower level api's that OpenOCD would normally use to access the target. Currently supported adapters include the ST STLINK and TI ICDI. STLINK firmware version >= V2.J21.S4 recommended due to issues with earlier versions of firmware where serial number is reset after first use. Suggest using ST firmware update utility to upgrade STLINK firmware even if current version reported is V2.J21.S4. @deffn {Config Command} {hla_device_desc} description Currently Not Supported. @end deffn @deffn {Config Command} {hla_serial} serial Specifies the serial number of the adapter. @end deffn @deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi}) Specifies the adapter layout to use. @end deffn @deffn {Config Command} {hla_vid_pid} vid pid The vendor ID and product ID of the device. @end deffn @deffn {Command} {hla_command} command Execute a custom adapter-specific command. The @var{command} string is passed as is to the underlying adapter layout handler. @end deffn @end deffn @deffn {Interface Driver} {opendous} opendous-jtag is a freely programmable USB adapter. @end deffn @deffn {Interface Driver} {ulink} This is the Keil ULINK v1 JTAG debugger. @end deffn @deffn {Interface Driver} {ZY1000} This is the Zylin ZY1000 JTAG debugger. @end deffn @quotation Note This defines some driver-specific commands, which are not currently documented here. @end quotation @deffn Command power [@option{on}|@option{off}] Turn power switch to target on/off. No arguments: print status. @end deffn @deffn {Interface Driver} {bcm2835gpio} This SoC is present in Raspberry Pi which is a cheap single-board computer exposing some GPIOs on its expansion header. The driver accesses memory-mapped GPIO peripheral registers directly for maximum performance, but the only possible race condition is for the pins' modes/muxing (which is highly unlikely), so it should be able to coexist nicely with both sysfs bitbanging and various peripherals' kernel drivers. The driver restores the previous configuration on exit. See @file{interface/raspberrypi-native.cfg} for a sample config and pinout. @end deffn @section Transport Configuration @cindex Transport As noted earlier, depending on the version of OpenOCD you use, and the debug adapter you are using, several transports may be available to communicate with debug targets (or perhaps to program flash memory). @deffn Command {transport list} displays the names of the transports supported by this version of OpenOCD. @end deffn @deffn Command {transport select} @option{transport_name} Select which of the supported transports to use in this OpenOCD session. When invoked with @option{transport_name}, attempts to select the named transport. The transport must be supported by the debug adapter hardware and by the version of OpenOCD you are using (including the adapter's driver). If no transport has been selected and no @option{transport_name} is provided, @command{transport select} auto-selects the first transport supported by the debug adapter. @command{transport select} always returns the name of the session's selected transport, if any. @end deffn @subsection JTAG Transport @cindex JTAG JTAG is the original transport supported by OpenOCD, and most of the OpenOCD commands support it. JTAG transports expose a chain of one or more Test Access Points (TAPs), each of which must be explicitly declared. JTAG supports both debugging and boundary scan testing. Flash programming support is built on top of debug support. JTAG transport is selected with the command @command{transport select jtag}. Unless your adapter uses @ref{hla_interface,the hla interface driver}, in which case the command is @command{transport select hla_jtag}. @subsection SWD Transport @cindex SWD @cindex Serial Wire Debug SWD (Serial Wire Debug) is an ARM-specific transport which exposes one Debug Access Point (DAP, which must be explicitly declared. (SWD uses fewer signal wires than JTAG.) SWD is debug-oriented, and does not support boundary scan testing. Flash programming support is built on top of debug support. (Some processors support both JTAG and SWD.) SWD transport is selected with the command @command{transport select swd}. Unless your adapter uses @ref{hla_interface,the hla interface driver}, in which case the command is @command{transport select hla_swd}. @deffn Command {swd newdap} ... Declares a single DAP which uses SWD transport. Parameters are currently the same as "jtag newtap" but this is expected to change. @end deffn @deffn Command {swd wcr trn prescale} Updates TRN (turnaraound delay) and prescaling.fields of the Wire Control Register (WCR). No parameters: displays current settings. @end deffn @subsection SPI Transport @cindex SPI @cindex Serial Peripheral Interface The Serial Peripheral Interface (SPI) is a general purpose transport which uses four wire signaling. Some processors use it as part of a solution for flash programming. @anchor{jtagspeed} @section JTAG Speed JTAG clock setup is part of system setup. It @emph{does not belong with interface setup} since any interface only knows a few of the constraints for the JTAG clock speed. Sometimes the JTAG speed is changed during the target initialization process: (1) slow at reset, (2) program the CPU clocks, (3) run fast. Both the "slow" and "fast" clock rates are functions of the oscillators used, the chip, the board design, and sometimes power management software that may be active. The speed used during reset, and the scan chain verification which follows reset, can be adjusted using a @code{reset-start} target event handler. It can then be reconfigured to a faster speed by a @code{reset-init} target event handler after it reprograms those CPU clocks, or manually (if something else, such as a boot loader, sets up those clocks). @xref{targetevents,,Target Events}. When the initial low JTAG speed is a chip characteristic, perhaps because of a required oscillator speed, provide such a handler in the target config file. When that speed is a function of a board-specific characteristic such as which speed oscillator is used, it belongs in the board config file instead. In both cases it's safest to also set the initial JTAG clock rate to that same slow speed, so that OpenOCD never starts up using a clock speed that's faster than the scan chain can support. @example jtag_rclk 3000 $_TARGET.cpu configure -event reset-start @{ jtag_rclk 3000 @} @end example If your system supports adaptive clocking (RTCK), configuring JTAG to use that is probably the most robust approach. However, it introduces delays to synchronize clocks; so it may not be the fastest solution. @b{NOTE:} Script writers should consider using @command{jtag_rclk} instead of @command{adapter_khz}, but only for (ARM) cores and boards which support adaptive clocking. @deffn {Command} adapter_khz max_speed_kHz A non-zero speed is in KHZ. Hence: 3000 is 3mhz. JTAG interfaces usually support a limited number of speeds. The speed actually used won't be faster than the speed specified. Chip data sheets generally include a top JTAG clock rate. The actual rate is often a function of a CPU core clock, and is normally less than that peak rate. For example, most ARM cores accept at most one sixth of the CPU clock. Speed 0 (khz) selects RTCK method. @xref{faqrtck,,FAQ RTCK}. If your system uses RTCK, you won't need to change the JTAG clocking after setup. Not all interfaces, boards, or targets support ``rtck''. If the interface device can not support it, an error is returned when you try to use RTCK. @end deffn @defun jtag_rclk fallback_speed_kHz @cindex adaptive clocking @cindex RTCK This Tcl proc (defined in @file{startup.tcl}) attempts to enable RTCK/RCLK. If that fails (maybe the interface, board, or target doesn't support it), falls back to the specified frequency. @example # Fall back to 3mhz if RTCK is not supported jtag_rclk 3000 @end example @end defun @node Reset Configuration @chapter Reset Configuration @cindex Reset Configuration Every system configuration may require a different reset configuration. This can also be quite confusing. Resets also interact with @var{reset-init} event handlers, which do things like setting up clocks and DRAM, and JTAG clock rates. (@xref{jtagspeed,,JTAG Speed}.) They can also interact with JTAG routers. Please see the various board files for examples. @quotation Note To maintainers and integrators: Reset configuration touches several things at once. Normally the board configuration file should define it and assume that the JTAG adapter supports everything that's wired up to the board's JTAG connector. However, the target configuration file could also make note of something the silicon vendor has done inside the chip, which will be true for most (or all) boards using that chip. And when the JTAG adapter doesn't support everything, the user configuration file will need to override parts of the reset configuration provided by other files. @end quotation @section Types of Reset There are many kinds of reset possible through JTAG, but they may not all work with a given board and adapter. That's part of why reset configuration can be error prone. @itemize @bullet @item @emph{System Reset} ... the @emph{SRST} hardware signal resets all chips connected to the JTAG adapter, such as processors, power management chips, and I/O controllers. Normally resets triggered with this signal behave exactly like pressing a RESET button. @item @emph{JTAG TAP Reset} ... the @emph{TRST} hardware signal resets just the TAP controllers connected to the JTAG adapter. Such resets should not be visible to the rest of the system; resetting a device's TAP controller just puts that controller into a known state. @item @emph{Emulation Reset} ... many devices can be reset through JTAG commands. These resets are often distinguishable from system resets, either explicitly (a "reset reason" register says so) or implicitly (not all parts of the chip get reset). @item @emph{Other Resets} ... system-on-chip devices often support several other types of reset. You may need to arrange that a watchdog timer stops while debugging, preventing a watchdog reset. There may be individual module resets. @end itemize In the best case, OpenOCD can hold SRST, then reset the TAPs via TRST and send commands through JTAG to halt the CPU at the reset vector before the 1st instruction is executed. Then when it finally releases the SRST signal, the system is halted under debugger control before any code has executed. This is the behavior required to support the @command{reset halt} and @command{reset init} commands; after @command{reset init} a board-specific script might do things like setting up DRAM. (@xref{resetcommand,,Reset Command}.) @anchor{srstandtrstissues} @section SRST and TRST Issues Because SRST and TRST are hardware signals, they can have a variety of system-specific constraints. Some of the most common issues are: @itemize @bullet @item @emph{Signal not available} ... Some boards don't wire SRST or TRST to the JTAG connector. Some JTAG adapters don't support such signals even if they are wired up. Use the @command{reset_config} @var{signals} options to say when either of those signals is not connected. When SRST is not available, your code might not be able to rely on controllers having been fully reset during code startup. Missing TRST is not a problem, since JTAG-level resets can be triggered using with TMS signaling. @item @emph{Signals shorted} ... Sometimes a chip, board, or adapter will connect SRST to TRST, instead of keeping them separate. Use the @command{reset_config} @var{combination} options to say when those signals aren't properly independent. @item @emph{Timing} ... Reset circuitry like a resistor/capacitor delay circuit, reset supervisor, or on-chip features can extend the effect of a JTAG adapter's reset for some time after the adapter stops issuing the reset. For example, there may be chip or board requirements that all reset pulses last for at least a certain amount of time; and reset buttons commonly have hardware debouncing. Use the @command{adapter_nsrst_delay} and @command{jtag_ntrst_delay} commands to say when extra delays are needed. @item @emph{Drive type} ... Reset lines often have a pullup resistor, letting the JTAG interface treat them as open-drain signals. But that's not a requirement, so the adapter may need to use push/pull output drivers. Also, with weak pullups it may be advisable to drive signals to both levels (push/pull) to minimize rise times. Use the @command{reset_config} @var{trst_type} and @var{srst_type} parameters to say how to drive reset signals. @item @emph{Special initialization} ... Targets sometimes need special JTAG initialization sequences to handle chip-specific issues (not limited to errata). For example, certain JTAG commands might need to be issued while the system as a whole is in a reset state (SRST active) but the JTAG scan chain is usable (TRST inactive). Many systems treat combined assertion of SRST and TRST as a trigger for a harder reset than SRST alone. Such custom reset handling is discussed later in this chapter. @end itemize There can also be other issues. Some devices don't fully conform to the JTAG specifications. Trivial system-specific differences are common, such as SRST and TRST using slightly different names. There are also vendors who distribute key JTAG documentation for their chips only to developers who have signed a Non-Disclosure Agreement (NDA). Sometimes there are chip-specific extensions like a requirement to use the normally-optional TRST signal (precluding use of JTAG adapters which don't pass TRST through), or needing extra steps to complete a TAP reset. In short, SRST and especially TRST handling may be very finicky, needing to cope with both architecture and board specific constraints. @section Commands for Handling Resets @deffn {Command} adapter_nsrst_assert_width milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nSRST (active-low system reset) before allowing it to be deasserted. @end deffn @deffn {Command} adapter_nsrst_delay milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nSRST (active-low system reset) before starting new JTAG operations. When a board has a reset button connected to SRST line it will probably have hardware debouncing, implying you should use this. @end deffn @deffn {Command} jtag_ntrst_assert_width milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nTRST (active-low JTAG TAP reset) before allowing it to be deasserted. @end deffn @deffn {Command} jtag_ntrst_delay milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nTRST (active-low JTAG TAP reset) before starting new JTAG operations. @end deffn @deffn {Command} reset_config mode_flag ... This command displays or modifies the reset configuration of your combination of JTAG board and target in target configuration scripts. Information earlier in this section describes the kind of problems the command is intended to address (@pxref{srstandtrstissues,,SRST and TRST Issues}). As a rule this command belongs only in board config files, describing issues like @emph{board doesn't connect TRST}; or in user config files, addressing limitations derived from a particular combination of interface and board. (An unlikely example would be using a TRST-only adapter with a board that only wires up SRST.) The @var{mode_flag} options can be specified in any order, but only one of each type -- @var{signals}, @var{combination}, @var{gates}, @var{trst_type}, @var{srst_type} and @var{connect_type} -- may be specified at a time. If you don't provide a new value for a given type, its previous value (perhaps the default) is unchanged. For example, this means that you don't need to say anything at all about TRST just to declare that if the JTAG adapter should want to drive SRST, it must explicitly be driven high (@option{srst_push_pull}). @itemize @item @var{signals} can specify which of the reset signals are connected. For example, If the JTAG interface provides SRST, but the board doesn't connect that signal properly, then OpenOCD can't use it. Possible values are @option{none} (the default), @option{trst_only}, @option{srst_only} and @option{trst_and_srst}. @quotation Tip If your board provides SRST and/or TRST through the JTAG connector, you must declare that so those signals can be used. @end quotation @item The @var{combination} is an optional value specifying broken reset signal implementations. The default behaviour if no option given is @option{separate}, indicating everything behaves normally. @option{srst_pulls_trst} states that the test logic is reset together with the reset of the system (e.g. NXP LPC2000, "broken" board layout), @option{trst_pulls_srst} says that the system is reset together with the test logic (only hypothetical, I haven't seen hardware with such a bug, and can be worked around). @option{combined} implies both @option{srst_pulls_trst} and @option{trst_pulls_srst}. @item The @var{gates} tokens control flags that describe some cases where JTAG may be unvailable during reset. @option{srst_gates_jtag} (default) indicates that asserting SRST gates the JTAG clock. This means that no communication can happen on JTAG while SRST is asserted. Its converse is @option{srst_nogate}, indicating that JTAG commands can safely be issued while SRST is active. @item The @var{connect_type} tokens control flags that describe some cases where SRST is asserted while connecting to the target. @option{srst_nogate} is required to use this option. @option{connect_deassert_srst} (default) indicates that SRST will not be asserted while connecting to the target. Its converse is @option{connect_assert_srst}, indicating that SRST will be asserted before any target connection. Only some targets support this feature, STM32 and STR9 are examples. This feature is useful if you are unable to connect to your target due to incorrect options byte config or illegal program execution. @end itemize The optional @var{trst_type} and @var{srst_type} parameters allow the driver mode of each reset line to be specified. These values only affect JTAG interfaces with support for different driver modes, like the Amontec JTAGkey and JTAG Accelerator. Also, they are necessarily ignored if the relevant signal (TRST or SRST) is not connected. @itemize @item Possible @var{trst_type} driver modes for the test reset signal (TRST) are the default @option{trst_push_pull}, and @option{trst_open_drain}. Most boards connect this signal to a pulldown, so the JTAG TAPs never leave reset unless they are hooked up to a JTAG adapter. @item Possible @var{srst_type} driver modes for the system reset signal (SRST) are the default @option{srst_open_drain}, and @option{srst_push_pull}. Most boards connect this signal to a pullup, and allow the signal to be pulled low by various events including system powerup and pressing a reset button. @end itemize @end deffn @section Custom Reset Handling @cindex events OpenOCD has several ways to help support the various reset mechanisms provided by chip and board vendors. The commands shown in the previous section give standard parameters. There are also @emph{event handlers} associated with TAPs or Targets. Those handlers are Tcl procedures you can provide, which are invoked at particular points in the reset sequence. @emph{When SRST is not an option} you must set up a @code{reset-assert} event handler for your target. For example, some JTAG adapters don't include the SRST signal; and some boards have multiple targets, and you won't always want to reset everything at once. After configuring those mechanisms, you might still find your board doesn't start up or reset correctly. For example, maybe it needs a slightly different sequence of SRST and/or TRST manipulations, because of quirks that the @command{reset_config} mechanism doesn't address; or asserting both might trigger a stronger reset, which needs special attention. Experiment with lower level operations, such as @command{jtag_reset} and the @command{jtag arp_*} operations shown here, to find a sequence of operations that works. @xref{JTAG Commands}. When you find a working sequence, it can be used to override @command{jtag_init}, which fires during OpenOCD startup (@pxref{configurationstage,,Configuration Stage}); or @command{init_reset}, which fires during reset processing. You might also want to provide some project-specific reset schemes. For example, on a multi-target board the standard @command{reset} command would reset all targets, but you may need the ability to reset only one target at time and thus want to avoid using the board-wide SRST signal. @deffn {Overridable Procedure} init_reset mode This is invoked near the beginning of the @command{reset} command, usually to provide as much of a cold (power-up) reset as practical. By default it is also invoked from @command{jtag_init} if the scan chain does not respond to pure JTAG operations. The @var{mode} parameter is the parameter given to the low level reset command (@option{halt}, @option{init}, or @option{run}), @option{setup}, or potentially some other value. The default implementation just invokes @command{jtag arp_init-reset}. Replacements will normally build on low level JTAG operations such as @command{jtag_reset}. Operations here must not address individual TAPs (or their associated targets) until the JTAG scan chain has first been verified to work. Implementations must have verified the JTAG scan chain before they return. This is done by calling @command{jtag arp_init} (or @command{jtag arp_init-reset}). @end deffn @deffn Command {jtag arp_init} This validates the scan chain using just the four standard JTAG signals (TMS, TCK, TDI, TDO). It starts by issuing a JTAG-only reset. Then it performs checks to verify that the scan chain configuration matches the TAPs it can observe. Those checks include checking IDCODE values for each active TAP, and verifying the length of their instruction registers using TAP @code{-ircapture} and @code{-irmask} values. If these tests all pass, TAP @code{setup} events are issued to all TAPs with handlers for that event. @end deffn @deffn Command {jtag arp_init-reset} This uses TRST and SRST to try resetting everything on the JTAG scan chain (and anything else connected to SRST). It then invokes the logic of @command{jtag arp_init}. @end deffn @node TAP Declaration @chapter TAP Declaration @cindex TAP declaration @cindex TAP configuration @emph{Test Access Ports} (TAPs) are the core of JTAG. TAPs serve many roles, including: @itemize @bullet @item @b{Debug Target} A CPU TAP can be used as a GDB debug target. @item @b{Flash Programming} Some chips program the flash directly via JTAG. Others do it indirectly, making a CPU do it. @item @b{Program Download} Using the same CPU support GDB uses, you can initialize a DRAM controller, download code to DRAM, and then start running that code. @item @b{Boundary Scan} Most chips support boundary scan, which helps test for board assembly problems like solder bridges and missing connections. @end itemize OpenOCD must know about the active TAPs on your board(s). Setting up the TAPs is the core task of your configuration files. Once those TAPs are set up, you can pass their names to code which sets up CPUs and exports them as GDB targets, probes flash memory, performs low-level JTAG operations, and more. @section Scan Chains @cindex scan chain TAPs are part of a hardware @dfn{scan chain}, which is a daisy chain of TAPs. They also need to be added to OpenOCD's software mirror of that hardware list, giving each member a name and associating other data with it. Simple scan chains, with a single TAP, are common in systems with a single microcontroller or microprocessor. More complex chips may have several TAPs internally. Very complex scan chains might have a dozen or more TAPs: several in one chip, more in the next, and connecting to other boards with their own chips and TAPs. You can display the list with the @command{scan_chain} command. (Don't confuse this with the list displayed by the @command{targets} command, presented in the next chapter. That only displays TAPs for CPUs which are configured as debugging targets.) Here's what the scan chain might look like for a chip more than one TAP: @verbatim TapName Enabled IdCode Expected IrLen IrCap IrMask -- ------------------ ------- ---------- ---------- ----- ----- ------ 0 omap5912.dsp Y 0x03df1d81 0x03df1d81 38 0x01 0x03 1 omap5912.arm Y 0x0692602f 0x0692602f 4 0x01 0x0f 2 omap5912.unknown Y 0x00000000 0x00000000 8 0x01 0x03 @end verbatim OpenOCD can detect some of that information, but not all of it. @xref{autoprobing,,Autoprobing}. Unfortunately, those TAPs can't always be autoconfigured, because not all devices provide good support for that. JTAG doesn't require supporting IDCODE instructions, and chips with JTAG routers may not link TAPs into the chain until they are told to do so. The configuration mechanism currently supported by OpenOCD requires explicit configuration of all TAP devices using @command{jtag newtap} commands, as detailed later in this chapter. A command like this would declare one tap and name it @code{chip1.cpu}: @example jtag newtap chip1 cpu -irlen 4 -expected-id 0x3ba00477 @end example Each target configuration file lists the TAPs provided by a given chip. Board configuration files combine all the targets on a board, and so forth. Note that @emph{the order in which TAPs are declared is very important.} That declaration order must match the order in the JTAG scan chain, both inside a single chip and between them. @xref{faqtaporder,,FAQ TAP Order}. For example, the ST Microsystems STR912 chip has three separate TAPs@footnote{See the ST document titled: @emph{STR91xFAxxx, Section 3.15 Jtag Interface, Page: 28/102, Figure 3: JTAG chaining inside the STR91xFA}. @url{http://eu.st.com/stonline/products/literature/ds/13495.pdf}}. To configure those taps, @file{target/str912.cfg} includes commands something like this: @example jtag newtap str912 flash ... params ... jtag newtap str912 cpu ... params ... jtag newtap str912 bs ... params ... @end example Actual config files typically use a variable such as @code{$_CHIPNAME} instead of literals like @option{str912}, to support more than one chip of each type. @xref{Config File Guidelines}. @deffn Command {jtag names} Returns the names of all current TAPs in the scan chain. Use @command{jtag cget} or @command{jtag tapisenabled} to examine attributes and state of each TAP. @example foreach t [jtag names] @{ puts [format "TAP: %s\n" $t] @} @end example @end deffn @deffn Command {scan_chain} Displays the TAPs in the scan chain configuration, and their status. The set of TAPs listed by this command is fixed by exiting the OpenOCD configuration stage, but systems with a JTAG router can enable or disable TAPs dynamically. @end deffn @c FIXME! "jtag cget" should be able to return all TAP @c attributes, like "$target_name cget" does for targets. @c Probably want "jtag eventlist", and a "tap-reset" event @c (on entry to RESET state). @section TAP Names @cindex dotted name When TAP objects are declared with @command{jtag newtap}, a @dfn{dotted.name} is created for the TAP, combining the name of a module (usually a chip) and a label for the TAP. For example: @code{xilinx.tap}, @code{str912.flash}, @code{omap3530.jrc}, @code{dm6446.dsp}, or @code{stm32.cpu}. Many other commands use that dotted.name to manipulate or refer to the TAP. For example, CPU configuration uses the name, as does declaration of NAND or NOR flash banks. The components of a dotted name should follow ``C'' symbol name rules: start with an alphabetic character, then numbers and underscores are OK; while others (including dots!) are not. @section TAP Declaration Commands @c shouldn't this be(come) a {Config Command}? @deffn Command {jtag newtap} chipname tapname configparams... Declares a new TAP with the dotted name @var{chipname}.@var{tapname}, and configured according to the various @var{configparams}. The @var{chipname} is a symbolic name for the chip. Conventionally target config files use @code{$_CHIPNAME}, defaulting to the model name given by the chip vendor but overridable. @cindex TAP naming convention The @var{tapname} reflects the role of that TAP, and should follow this convention: @itemize @bullet @item @code{bs} -- For boundary scan if this is a separate TAP; @item @code{cpu} -- The main CPU of the chip, alternatively @code{arm} and @code{dsp} on chips with both ARM and DSP CPUs, @code{arm1} and @code{arm2} on chips with two ARMs, and so forth; @item @code{etb} -- For an embedded trace buffer (example: an ARM ETB11); @item @code{flash} -- If the chip has a flash TAP, like the str912; @item @code{jrc} -- For JTAG route controller (example: the ICEPick modules on many Texas Instruments chips, like the OMAP3530 on Beagleboards); @item @code{tap} -- Should be used only for FPGA- or CPLD-like devices with a single TAP; @item @code{unknownN} -- If you have no idea what the TAP is for (N is a number); @item @emph{when in doubt} -- Use the chip maker's name in their data sheet. For example, the Freescale i.MX31 has a SDMA (Smart DMA) with a JTAG TAP; that TAP should be named @code{sdma}. @end itemize Every TAP requires at least the following @var{configparams}: @itemize @bullet @item @code{-irlen} @var{NUMBER} @*The length in bits of the instruction register, such as 4 or 5 bits. @end itemize A TAP may also provide optional @var{configparams}: @itemize @bullet @item @code{-disable} (or @code{-enable}) @*Use the @code{-disable} parameter to flag a TAP which is not linked into the scan chain after a reset using either TRST or the JTAG state machine's @sc{reset} state. You may use @code{-enable} to highlight the default state (the TAP is linked in). @xref{enablinganddisablingtaps,,Enabling and Disabling TAPs}. @item @code{-expected-id} @var{NUMBER} @*A non-zero @var{number} represents a 32-bit IDCODE which you expect to find when the scan chain is examined. These codes are not required by all JTAG devices. @emph{Repeat the option} as many times as required if more than one ID code could appear (for example, multiple versions). Specify @var{number} as zero to suppress warnings about IDCODE values that were found but not included in the list. Provide this value if at all possible, since it lets OpenOCD tell when the scan chain it sees isn't right. These values are provided in vendors' chip documentation, usually a technical reference manual. Sometimes you may need to probe the JTAG hardware to find these values. @xref{autoprobing,,Autoprobing}. @item @code{-ignore-version} @*Specify this to ignore the JTAG version field in the @code{-expected-id} option. When vendors put out multiple versions of a chip, or use the same JTAG-level ID for several largely-compatible chips, it may be more practical to ignore the version field than to update config files to handle all of the various chip IDs. The version field is defined as bit 28-31 of the IDCODE. @item @code{-ircapture} @var{NUMBER} @*The bit pattern loaded by the TAP into the JTAG shift register on entry to the @sc{ircapture} state, such as 0x01. JTAG requires the two LSBs of this value to be 01. By default, @code{-ircapture} and @code{-irmask} are set up to verify that two-bit value. You may provide additional bits if you know them, or indicate that a TAP doesn't conform to the JTAG specification. @item @code{-irmask} @var{NUMBER} @*A mask used with @code{-ircapture} to verify that instruction scans work correctly. Such scans are not used by OpenOCD except to verify that there seems to be no problems with JTAG scan chain operations. @end itemize @end deffn @section Other TAP commands @deffn Command {jtag cget} dotted.name @option{-event} event_name @deffnx Command {jtag configure} dotted.name @option{-event} event_name handler At this writing this TAP attribute mechanism is used only for event handling. (It is not a direct analogue of the @code{cget}/@code{configure} mechanism for debugger targets.) See the next section for information about the available events. The @code{configure} subcommand assigns an event handler, a TCL string which is evaluated when the event is triggered. The @code{cget} subcommand returns that handler. @end deffn @section TAP Events @cindex events @cindex TAP events OpenOCD includes two event mechanisms. The one presented here applies to all JTAG TAPs. The other applies to debugger targets, which are associated with certain TAPs. The TAP events currently defined are: @itemize @bullet @item @b{post-reset} @* The TAP has just completed a JTAG reset. The tap may still be in the JTAG @sc{reset} state. Handlers for these events might perform initialization sequences such as issuing TCK cycles, TMS sequences to ensure exit from the ARM SWD mode, and more. Because the scan chain has not yet been verified, handlers for these events @emph{should not issue commands which scan the JTAG IR or DR registers} of any particular target. @b{NOTE:} As this is written (September 2009), nothing prevents such access. @item @b{setup} @* The scan chain has been reset and verified. This handler may enable TAPs as needed. @item @b{tap-disable} @* The TAP needs to be disabled. This handler should implement @command{jtag tapdisable} by issuing the relevant JTAG commands. @item @b{tap-enable} @* The TAP needs to be enabled. This handler should implement @command{jtag tapenable} by issuing the relevant JTAG commands. @end itemize If you need some action after each JTAG reset which isn't actually specific to any TAP (since you can't yet trust the scan chain's contents to be accurate), you might: @example jtag configure CHIP.jrc -event post-reset @{ echo "JTAG Reset done" ... non-scan jtag operations to be done after reset @} @end example @anchor{enablinganddisablingtaps} @section Enabling and Disabling TAPs @cindex JTAG Route Controller @cindex jrc In some systems, a @dfn{JTAG Route Controller} (JRC) is used to enable and/or disable specific JTAG TAPs. Many ARM-based chips from Texas Instruments include an ``ICEPick'' module, which is a JRC. Such chips include DaVinci and OMAP3 processors. A given TAP may not be visible until the JRC has been told to link it into the scan chain; and if the JRC has been told to unlink that TAP, it will no longer be visible. Such routers address problems that JTAG ``bypass mode'' ignores, such as: @itemize @item The scan chain can only go as fast as its slowest TAP. @item Having many TAPs slows instruction scans, since all TAPs receive new instructions. @item TAPs in the scan chain must be powered up, which wastes power and prevents debugging some power management mechanisms. @end itemize The IEEE 1149.1 JTAG standard has no concept of a ``disabled'' tap, as implied by the existence of JTAG routers. However, the upcoming IEEE 1149.7 framework (layered on top of JTAG) does include a kind of JTAG router functionality. @c (a) currently the event handlers don't seem to be able to @c fail in a way that could lead to no-change-of-state. In OpenOCD, tap enabling/disabling is invoked by the Tcl commands shown below, and is implemented using TAP event handlers. So for example, when defining a TAP for a CPU connected to a JTAG router, your @file{target.cfg} file should define TAP event handlers using code that looks something like this: @example jtag configure CHIP.cpu -event tap-enable @{ ... jtag operations using CHIP.jrc @} jtag configure CHIP.cpu -event tap-disable @{ ... jtag operations using CHIP.jrc @} @end example Then you might want that CPU's TAP enabled almost all the time: @example jtag configure $CHIP.jrc -event setup "jtag tapenable $CHIP.cpu" @end example Note how that particular setup event handler declaration uses quotes to evaluate @code{$CHIP} when the event is configured. Using brackets @{ @} would cause it to be evaluated later, at runtime, when it might have a different value. @deffn Command {jtag tapdisable} dotted.name If necessary, disables the tap by sending it a @option{tap-disable} event. Returns the string "1" if the tap specified by @var{dotted.name} is enabled, and "0" if it is disabled. @end deffn @deffn Command {jtag tapenable} dotted.name If necessary, enables the tap by sending it a @option{tap-enable} event. Returns the string "1" if the tap specified by @var{dotted.name} is enabled, and "0" if it is disabled. @end deffn @deffn Command {jtag tapisenabled} dotted.name Returns the string "1" if the tap specified by @var{dotted.name} is enabled, and "0" if it is disabled. @quotation Note Humans will find the @command{scan_chain} command more helpful for querying the state of the JTAG taps. @end quotation @end deffn @anchor{autoprobing} @section Autoprobing @cindex autoprobe @cindex JTAG autoprobe TAP configuration is the first thing that needs to be done after interface and reset configuration. Sometimes it's hard finding out what TAPs exist, or how they are identified. Vendor documentation is not always easy to find and use. To help you get past such problems, OpenOCD has a limited @emph{autoprobing} ability to look at the scan chain, doing a @dfn{blind interrogation} and then reporting the TAPs it finds. To use this mechanism, start the OpenOCD server with only data that configures your JTAG interface, and arranges to come up with a slow clock (many devices don't support fast JTAG clocks right when they come out of reset). For example, your @file{openocd.cfg} file might have: @example source [find interface/olimex-arm-usb-tiny-h.cfg] reset_config trst_and_srst jtag_rclk 8 @end example When you start the server without any TAPs configured, it will attempt to autoconfigure the TAPs. There are two parts to this: @enumerate @item @emph{TAP discovery} ... After a JTAG reset (sometimes a system reset may be needed too), each TAP's data registers will hold the contents of either the IDCODE or BYPASS register. If JTAG communication is working, OpenOCD will see each TAP, and report what @option{-expected-id} to use with it. @item @emph{IR Length discovery} ... Unfortunately JTAG does not provide a reliable way to find out the value of the @option{-irlen} parameter to use with a TAP that is discovered. If OpenOCD can discover the length of a TAP's instruction register, it will report it. Otherwise you may need to consult vendor documentation, such as chip data sheets or BSDL files. @end enumerate In many cases your board will have a simple scan chain with just a single device. Here's what OpenOCD reported with one board that's a bit more complex: @example clock speed 8 kHz There are no enabled taps. AUTO PROBING MIGHT NOT WORK!! AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x2b900f0f ..." AUTO auto1.tap - use "jtag newtap auto1 tap -expected-id 0x07926001 ..." AUTO auto2.tap - use "jtag newtap auto2 tap -expected-id 0x0b73b02f ..." AUTO auto0.tap - use "... -irlen 4" AUTO auto1.tap - use "... -irlen 4" AUTO auto2.tap - use "... -irlen 6" no gdb ports allocated as no target has been specified @end example Given that information, you should be able to either find some existing config files to use, or create your own. If you create your own, you would configure from the bottom up: first a @file{target.cfg} file with these TAPs, any targets associated with them, and any on-chip resources; then a @file{board.cfg} with off-chip resources, clocking, and so forth. @node CPU Configuration @chapter CPU Configuration @cindex GDB target This chapter discusses how to set up GDB debug targets for CPUs. You can also access these targets without GDB (@pxref{Architecture and Core Commands}, and @ref{targetstatehandling,,Target State handling}) and through various kinds of NAND and NOR flash commands. If you have multiple CPUs you can have multiple such targets. We'll start by looking at how to examine the targets you have, then look at how to add one more target and how to configure it. @section Target List @cindex target, current @cindex target, list All targets that have been set up are part of a list, where each member has a name. That name should normally be the same as the TAP name. You can display the list with the @command{targets} (plural!) command. This display often has only one CPU; here's what it might look like with more than one: @verbatim TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0* at91rm9200.cpu arm920t little at91rm9200.cpu running 1 MyTarget cortex_m little mychip.foo tap-disabled @end verbatim One member of that list is the @dfn{current target}, which is implicitly referenced by many commands. It's the one marked with a @code{*} near the target name. In particular, memory addresses often refer to the address space seen by that current target. Commands like @command{mdw} (memory display words) and @command{flash erase_address} (erase NOR flash blocks) are examples; and there are many more. Several commands let you examine the list of targets: @deffn Command {target current} Returns the name of the current target. @end deffn @deffn Command {target names} Lists the names of all current targets in the list. @example foreach t [target names] @{ puts [format "Target: %s\n" $t] @} @end example @end deffn @c yep, "target list" would have been better. @c plus maybe "target setdefault". @deffn Command targets [name] @emph{Note: the name of this command is plural. Other target command names are singular.} With no parameter, this command displays a table of all known targets in a user friendly form. With a parameter, this command sets the current target to the given target with the given @var{name}; this is only relevant on boards which have more than one target. @end deffn @section Target CPU Types @cindex target type @cindex CPU type Each target has a @dfn{CPU type}, as shown in the output of the @command{targets} command. You need to specify that type when calling @command{target create}. The CPU type indicates more than just the instruction set. It also indicates how that instruction set is implemented, what kind of debug support it integrates, whether it has an MMU (and if so, what kind), what core-specific commands may be available (@pxref{Architecture and Core Commands}), and more. It's easy to see what target types are supported, since there's a command to list them. @anchor{targettypes} @deffn Command {target types} Lists all supported target types. At this writing, the supported CPU types are: @itemize @bullet @item @code{arm11} -- this is a generation of ARMv6 cores @item @code{arm720t} -- this is an ARMv4 core with an MMU @item @code{arm7tdmi} -- this is an ARMv4 core @item @code{arm920t} -- this is an ARMv4 core with an MMU @item @code{arm926ejs} -- this is an ARMv5 core with an MMU @item @code{arm966e} -- this is an ARMv5 core @item @code{arm9tdmi} -- this is an ARMv4 core @item @code{avr} -- implements Atmel's 8-bit AVR instruction set. (Support for this is preliminary and incomplete.) @item @code{cortex_a} -- this is an ARMv7 core with an MMU @item @code{cortex_m} -- this is an ARMv7 core, supporting only the compact Thumb2 instruction set. @item @code{dragonite} -- resembles arm966e @item @code{dsp563xx} -- implements Freescale's 24-bit DSP. (Support for this is still incomplete.) @item @code{fa526} -- resembles arm920 (w/o Thumb) @item @code{feroceon} -- resembles arm926 @item @code{mips_m4k} -- a MIPS core @item @code{xscale} -- this is actually an architecture, not a CPU type. It is based on the ARMv5 architecture. @item @code{openrisc} -- this is an OpenRISC 1000 core. The current implementation supports three JTAG TAP cores: @itemize @minus @item @code{OpenCores TAP} (See: @url{http://opencores.org/project,jtag}) @item @code{Altera Virtual JTAG TAP} (See: @url{http://www.altera.com/literature/ug/ug_virtualjtag.pdf}) @item @code{Xilinx BSCAN_* virtual JTAG interface} (See: @url{http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_2/spartan6_hdl.pdf}) @end itemize And two debug interfaces cores: @itemize @minus @item @code{Advanced debug interface} (See: @url{http://opencores.org/project,adv_debug_sys}) @item @code{SoC Debug Interface} (See: @url{http://opencores.org/project,dbg_interface}) @end itemize @end itemize @end deffn To avoid being confused by the variety of ARM based cores, remember this key point: @emph{ARM is a technology licencing company}. (See: @url{http://www.arm.com}.) The CPU name used by OpenOCD will reflect the CPU design that was licenced, not a vendor brand which incorporates that design. Name prefixes like arm7, arm9, arm11, and cortex reflect design generations; while names like ARMv4, ARMv5, ARMv6, and ARMv7 reflect an architecture version implemented by a CPU design. @anchor{targetconfiguration} @section Target Configuration Before creating a ``target'', you must have added its TAP to the scan chain. When you've added that TAP, you will have a @code{dotted.name} which is used to set up the CPU support. The chip-specific configuration file will normally configure its CPU(s) right after it adds all of the chip's TAPs to the scan chain. Although you can set up a target in one step, it's often clearer if you use shorter commands and do it in two steps: create it, then configure optional parts. All operations on the target after it's created will use a new command, created as part of target creation. The two main things to configure after target creation are a work area, which usually has target-specific defaults even if the board setup code overrides them later; and event handlers (@pxref{targetevents,,Target Events}), which tend to be much more board-specific. The key steps you use might look something like this @example target create MyTarget cortex_m -chain-position mychip.cpu $MyTarget configure -work-area-phys 0x08000 -work-area-size 8096 $MyTarget configure -event reset-deassert-pre @{ jtag_rclk 5 @} $MyTarget configure -event reset-init @{ myboard_reinit @} @end example You should specify a working area if you can; typically it uses some on-chip SRAM. Such a working area can speed up many things, including bulk writes to target memory; flash operations like checking to see if memory needs to be erased; GDB memory checksumming; and more. @quotation Warning On more complex chips, the work area can become inaccessible when application code (such as an operating system) enables or disables the MMU. For example, the particular MMU context used to acess the virtual address will probably matter ... and that context might not have easy access to other addresses needed. At this writing, OpenOCD doesn't have much MMU intelligence. @end quotation It's often very useful to define a @code{reset-init} event handler. For systems that are normally used with a boot loader, common tasks include updating clocks and initializing memory controllers. That may be needed to let you write the boot loader into flash, in order to ``de-brick'' your board; or to load programs into external DDR memory without having run the boot loader. @deffn Command {target create} target_name type configparams... This command creates a GDB debug target that refers to a specific JTAG tap. It enters that target into a list, and creates a new command (@command{@var{target_name}}) which is used for various purposes including additional configuration. @itemize @bullet @item @var{target_name} ... is the name of the debug target. By convention this should be the same as the @emph{dotted.name} of the TAP associated with this target, which must be specified here using the @code{-chain-position @var{dotted.name}} configparam. This name is also used to create the target object command, referred to here as @command{$target_name}, and in other places the target needs to be identified. @item @var{type} ... specifies the target type. @xref{targettypes,,target types}. @item @var{configparams} ... all parameters accepted by @command{$target_name configure} are permitted. If the target is big-endian, set it here with @code{-endian big}. You @emph{must} set the @code{-chain-position @var{dotted.name}} here. @end itemize @end deffn @deffn Command {$target_name configure} configparams... The options accepted by this command may also be specified as parameters to @command{target create}. Their values can later be queried one at a time by using the @command{$target_name cget} command. @emph{Warning:} changing some of these after setup is dangerous. For example, moving a target from one TAP to another; and changing its endianness. @itemize @bullet @item @code{-chain-position} @var{dotted.name} -- names the TAP used to access this target. @item @code{-endian} (@option{big}|@option{little}) -- specifies whether the CPU uses big or little endian conventions @item @code{-event} @var{event_name} @var{event_body} -- @xref{targetevents,,Target Events}. Note that this updates a list of named event handlers. Calling this twice with two different event names assigns two different handlers, but calling it twice with the same event name assigns only one handler. @item @code{-work-area-backup} (@option{0}|@option{1}) -- says whether the work area gets backed up; by default, @emph{it is not backed up.} When possible, use a working_area that doesn't need to be backed up, since performing a backup slows down operations. For example, the beginning of an SRAM block is likely to be used by most build systems, but the end is often unused. @item @code{-work-area-size} @var{size} -- specify work are size, in bytes. The same size applies regardless of whether its physical or virtual address is being used. @item @code{-work-area-phys} @var{address} -- set the work area base @var{address} to be used when no MMU is active. @item @code{-work-area-virt} @var{address} -- set the work area base @var{address} to be used when an MMU is active. @emph{Do not specify a value for this except on targets with an MMU.} The value should normally correspond to a static mapping for the @code{-work-area-phys} address, set up by the current operating system. @anchor{rtostype} @item @code{-rtos} @var{rtos_type} -- enable rtos support for target, @var{rtos_type} can be one of @option{auto}|@option{eCos}|@option{ThreadX}| @option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx} @xref{gdbrtossupport,,RTOS Support}. @end itemize @end deffn @section Other $target_name Commands @cindex object command The Tcl/Tk language has the concept of object commands, and OpenOCD adopts that same model for targets. A good Tk example is a on screen button. Once a button is created a button has a name (a path in Tk terms) and that name is useable as a first class command. For example in Tk, one can create a button and later configure it like this: @example # Create button .foobar -background red -command @{ foo @} # Modify .foobar configure -foreground blue # Query set x [.foobar cget -background] # Report puts [format "The button is %s" $x] @end example In OpenOCD's terms, the ``target'' is an object just like a Tcl/Tk button, and its object commands are invoked the same way. @example str912.cpu mww 0x1234 0x42 omap3530.cpu mww 0x5555 123 @end example The commands supported by OpenOCD target objects are: @deffn Command {$target_name arp_examine} @deffnx Command {$target_name arp_halt} @deffnx Command {$target_name arp_poll} @deffnx Command {$target_name arp_reset} @deffnx Command {$target_name arp_waitstate} Internal OpenOCD scripts (most notably @file{startup.tcl}) use these to deal with specific reset cases. They are not otherwise documented here. @end deffn @deffn Command {$target_name array2mem} arrayname width address count @deffnx Command {$target_name mem2array} arrayname width address count These provide an efficient script-oriented interface to memory. The @code{array2mem} primitive writes bytes, halfwords, or words; while @code{mem2array} reads them. In both cases, the TCL side uses an array, and the target side uses raw memory. The efficiency comes from enabling the use of bulk JTAG data transfer operations. The script orientation comes from working with data values that are packaged for use by TCL scripts; @command{mdw} type primitives only print data they retrieve, and neither store nor return those values. @itemize @item @var{arrayname} ... is the name of an array variable @item @var{width} ... is 8/16/32 - indicating the memory access size @item @var{address} ... is the target memory address @item @var{count} ... is the number of elements to process @end itemize @end deffn @deffn Command {$target_name cget} queryparm Each configuration parameter accepted by @command{$target_name configure} can be individually queried, to return its current value. The @var{queryparm} is a parameter name accepted by that command, such as @code{-work-area-phys}. There are a few special cases: @itemize @bullet @item @code{-event} @var{event_name} -- returns the handler for the event named @var{event_name}. This is a special case because setting a handler requires two parameters. @item @code{-type} -- returns the target type. This is a special case because this is set using @command{target create} and can't be changed using @command{$target_name configure}. @end itemize For example, if you wanted to summarize information about all the targets you might use something like this: @example foreach name [target names] @{ set y [$name cget -endian] set z [$name cget -type] puts [format "Chip %d is %s, Endian: %s, type: %s" \ $x $name $y $z] @} @end example @end deffn @anchor{targetcurstate} @deffn Command {$target_name curstate} Displays the current target state: @code{debug-running}, @code{halted}, @code{reset}, @code{running}, or @code{unknown}. (Also, @pxref{eventpolling,,Event Polling}.) @end deffn @deffn Command {$target_name eventlist} Displays a table listing all event handlers currently associated with this target. @xref{targetevents,,Target Events}. @end deffn @deffn Command {$target_name invoke-event} event_name Invokes the handler for the event named @var{event_name}. (This is primarily intended for use by OpenOCD framework code, for example by the reset code in @file{startup.tcl}.) @end deffn @deffn Command {$target_name mdw} addr [count] @deffnx Command {$target_name mdh} addr [count] @deffnx Command {$target_name mdb} addr [count] Display contents of address @var{addr}, as 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), or 8-bit bytes (@command{mdb}). If @var{count} is specified, displays that many units. (If you want to manipulate the data instead of displaying it, see the @code{mem2array} primitives.) @end deffn @deffn Command {$target_name mww} addr word @deffnx Command {$target_name mwh} addr halfword @deffnx Command {$target_name mwb} addr byte Writes the specified @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) pattern, at the specified address @var{addr}. @end deffn @anchor{targetevents} @section Target Events @cindex target events @cindex events At various times, certain things can happen, or you want them to happen. For example: @itemize @bullet @item What should happen when GDB connects? Should your target reset? @item When GDB tries to flash the target, do you need to enable the flash via a special command? @item Is using SRST appropriate (and possible) on your system? Or instead of that, do you need to issue JTAG commands to trigger reset? SRST usually resets everything on the scan chain, which can be inappropriate. @item During reset, do you need to write to certain memory locations to set up system clocks or to reconfigure the SDRAM? How about configuring the watchdog timer, or other peripherals, to stop running while you hold the core stopped for debugging? @end itemize All of the above items can be addressed by target event handlers. These are set up by @command{$target_name configure -event} or @command{target create ... -event}. The programmer's model matches the @code{-command} option used in Tcl/Tk buttons and events. The two examples below act the same, but one creates and invokes a small procedure while the other inlines it. @example proc my_attach_proc @{ @} @{ echo "Reset..." reset halt @} mychip.cpu configure -event gdb-attach my_attach_proc mychip.cpu configure -event gdb-attach @{ echo "Reset..." # To make flash probe and gdb load to flash work # we need a reset init. reset init @} @end example The following target events are defined: @itemize @bullet @item @b{debug-halted} @* The target has halted for debug reasons (i.e.: breakpoint) @item @b{debug-resumed} @* The target has resumed (i.e.: gdb said run) @item @b{early-halted} @* Occurs early in the halt process @item @b{examine-start} @* Before target examine is called. @item @b{examine-end} @* After target examine is called with no errors. @item @b{gdb-attach} @* When GDB connects. This is before any communication with the target, so this can be used to set up the target so it is possible to probe flash. Probing flash is necessary during gdb connect if gdb load is to write the image to flash. Another use of the flash memory map is for GDB to automatically hardware/software breakpoints depending on whether the breakpoint is in RAM or read only memory. @item @b{gdb-detach} @* When GDB disconnects @item @b{gdb-end} @* When the target has halted and GDB is not doing anything (see early halt) @item @b{gdb-flash-erase-start} @* Before the GDB flash process tries to erase the flash (default is @code{reset init}) @item @b{gdb-flash-erase-end} @* After the GDB flash process has finished erasing the flash @item @b{gdb-flash-write-start} @* Before GDB writes to the flash @item @b{gdb-flash-write-end} @* After GDB writes to the flash (default is @code{reset halt}) @item @b{gdb-start} @* Before the target steps, gdb is trying to start/resume the target @item @b{halted} @* The target has halted @item @b{reset-assert-pre} @* Issued as part of @command{reset} processing after @command{reset_init} was triggered but before either SRST alone is re-asserted on the scan chain, or @code{reset-assert} is triggered. @item @b{reset-assert} @* Issued as part of @command{reset} processing after @command{reset-assert-pre} was triggered. When such a handler is present, cores which support this event will use it instead of asserting SRST. This support is essential for debugging with JTAG interfaces which don't include an SRST line (JTAG doesn't require SRST), and for selective reset on scan chains that have multiple targets. @item @b{reset-assert-post} @* Issued as part of @command{reset} processing after @code{reset-assert} has been triggered. or the target asserted SRST on the entire scan chain. @item @b{reset-deassert-pre} @* Issued as part of @command{reset} processing after @code{reset-assert-post} has been triggered. @item @b{reset-deassert-post} @* Issued as part of @command{reset} processing after @code{reset-deassert-pre} has been triggered and (if the target is using it) after SRST has been released on the scan chain. @item @b{reset-end} @* Issued as the final step in @command{reset} processing. @ignore @item @b{reset-halt-post} @* Currently not used @item @b{reset-halt-pre} @* Currently not used @end ignore @item @b{reset-init} @* Used by @b{reset init} command for board-specific initialization. This event fires after @emph{reset-deassert-post}. This is where you would configure PLLs and clocking, set up DRAM so you can download programs that don't fit in on-chip SRAM, set up pin multiplexing, and so on. (You may be able to switch to a fast JTAG clock rate here, after the target clocks are fully set up.) @item @b{reset-start} @* Issued as part of @command{reset} processing before @command{reset_init} is called. This is the most robust place to use @command{jtag_rclk} or @command{adapter_khz} to switch to a low JTAG clock rate, when reset disables PLLs needed to use a fast clock. @ignore @item @b{reset-wait-pos} @* Currently not used @item @b{reset-wait-pre} @* Currently not used @end ignore @item @b{resume-start} @* Before any target is resumed @item @b{resume-end} @* After all targets have resumed @item @b{resumed} @* Target has resumed @item @b{trace-config} @* After target hardware trace configuration was changed @end itemize @node Flash Commands @chapter Flash Commands OpenOCD has different commands for NOR and NAND flash; the ``flash'' command works with NOR flash, while the ``nand'' command works with NAND flash. This partially reflects different hardware technologies: NOR flash usually supports direct CPU instruction and data bus access, while data from a NAND flash must be copied to memory before it can be used. (SPI flash must also be copied to memory before use.) However, the documentation also uses ``flash'' as a generic term; for example, ``Put flash configuration in board-specific files''. Flash Steps: @enumerate @item Configure via the command @command{flash bank} @* Do this in a board-specific configuration file, passing parameters as needed by the driver. @item Operate on the flash via @command{flash subcommand} @* Often commands to manipulate the flash are typed by a human, or run via a script in some automated way. Common tasks include writing a boot loader, operating system, or other data. @item GDB Flashing @* Flashing via GDB requires the flash be configured via ``flash bank'', and the GDB flash features be enabled. @xref{gdbconfiguration,,GDB Configuration}. @end enumerate Many CPUs have the ablity to ``boot'' from the first flash bank. This means that misprogramming that bank can ``brick'' a system, so that it can't boot. JTAG tools, like OpenOCD, are often then used to ``de-brick'' the board by (re)installing working boot firmware. @anchor{norconfiguration} @section Flash Configuration Commands @cindex flash configuration @deffn {Config Command} {flash bank} name driver base size chip_width bus_width target [driver_options] Configures a flash bank which provides persistent storage for addresses from @math{base} to @math{base + size - 1}. These banks will often be visible to GDB through the target's memory map. In some cases, configuring a flash bank will activate extra commands; see the driver-specific documentation. @itemize @bullet @item @var{name} ... may be used to reference the flash bank in other flash commands. A number is also available. @item @var{driver} ... identifies the controller driver associated with the flash bank being declared. This is usually @code{cfi} for external flash, or else the name of a microcontroller with embedded flash memory. @xref{flashdriverlist,,Flash Driver List}. @item @var{base} ... Base address of the flash chip. @item @var{size} ... Size of the chip, in bytes. For some drivers, this value is detected from the hardware. @item @var{chip_width} ... Width of the flash chip, in bytes; ignored for most microcontroller drivers. @item @var{bus_width} ... Width of the data bus used to access the chip, in bytes; ignored for most microcontroller drivers. @item @var{target} ... Names the target used to issue commands to the flash controller. @comment Actually, it's currently a controller-specific parameter... @item @var{driver_options} ... drivers may support, or require, additional parameters. See the driver-specific documentation for more information. @end itemize @quotation Note This command is not available after OpenOCD initialization has completed. Use it in board specific configuration files, not interactively. @end quotation @end deffn @comment the REAL name for this command is "ocd_flash_banks" @comment less confusing would be: "flash list" (like "nand list") @deffn Command {flash banks} Prints a one-line summary of each device that was declared using @command{flash bank}, numbered from zero. Note that this is the @emph{plural} form; the @emph{singular} form is a very different command. @end deffn @deffn Command {flash list} Retrieves a list of associative arrays for each device that was declared using @command{flash bank}, numbered from zero. This returned list can be manipulated easily from within scripts. @end deffn @deffn Command {flash probe} num Identify the flash, or validate the parameters of the configured flash. Operation depends on the flash type. The @var{num} parameter is a value shown by @command{flash banks}. Most flash commands will implicitly @emph{autoprobe} the bank; flash drivers can distinguish between probing and autoprobing, but most don't bother. @end deffn @section Erasing, Reading, Writing to Flash @cindex flash erasing @cindex flash reading @cindex flash writing @cindex flash programming @anchor{flashprogrammingcommands} One feature distinguishing NOR flash from NAND or serial flash technologies is that for read access, it acts exactly like any other addressible memory. This means you can use normal memory read commands like @command{mdw} or @command{dump_image} with it, with no special @command{flash} subcommands. @xref{memoryaccess,,Memory access}, and @ref{imageaccess,,Image access}. Write access works differently. Flash memory normally needs to be erased before it's written. Erasing a sector turns all of its bits to ones, and writing can turn ones into zeroes. This is why there are special commands for interactive erasing and writing, and why GDB needs to know which parts of the address space hold NOR flash memory. @quotation Note Most of these erase and write commands leverage the fact that NOR flash chips consume target address space. They implicitly refer to the current JTAG target, and map from an address in that target's address space back to a flash bank. @comment In May 2009, those mappings may fail if any bank associated @comment with that target doesn't succesfuly autoprobe ... bug worth fixing? A few commands use abstract addressing based on bank and sector numbers, and don't depend on searching the current target and its address space. Avoid confusing the two command models. @end quotation Some flash chips implement software protection against accidental writes, since such buggy writes could in some cases ``brick'' a system. For such systems, erasing and writing may require sector protection to be disabled first. Examples include CFI flash such as ``Intel Advanced Bootblock flash'', and AT91SAM7 on-chip flash. @xref{flashprotect,,flash protect}. @deffn Command {flash erase_sector} num first last Erase sectors in bank @var{num}, starting at sector @var{first} up to and including @var{last}. Sector numbering starts at 0. Providing a @var{last} sector of @option{last} specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {flash erase_address} [@option{pad}] [@option{unlock}] address length Erase sectors starting at @var{address} for @var{length} bytes. Unless @option{pad} is specified, @math{address} must begin a flash sector, and @math{address + length - 1} must end a sector. Specifying @option{pad} erases extra data at the beginning and/or end of the specified region, as needed to erase only full sectors. The flash bank to use is inferred from the @var{address}, and the specified length must stay within that bank. As a special case, when @var{length} is zero and @var{address} is the start of the bank, the whole flash is erased. If @option{unlock} is specified, then the flash is unprotected before erase starts. @end deffn @deffn Command {flash fillw} address word length @deffnx Command {flash fillh} address halfword length @deffnx Command {flash fillb} address byte length Fills flash memory with the specified @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) pattern, starting at @var{address} and continuing for @var{length} units (word/halfword/byte). No erasure is done before writing; when needed, that must be done before issuing this command. Writes are done in blocks of up to 1024 bytes, and each write is verified by reading back the data and comparing it to what was written. The flash bank to use is inferred from the @var{address} of each block, and the specified length must stay within that bank. @end deffn @comment no current checks for errors if fill blocks touch multiple banks! @deffn Command {flash write_bank} num filename offset Write the binary @file{filename} to flash bank @var{num}, starting at @var{offset} bytes from the beginning of the bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {flash write_image} [erase] [unlock] filename [offset] [type] Write the image @file{filename} to the current target's flash bank(s). Only loadable sections from the image are written. A relocation @var{offset} may be specified, in which case it is added to the base address for each section in the image. The file [@var{type}] can be specified explicitly as @option{bin} (binary), @option{ihex} (Intel hex), @option{elf} (ELF file), @option{s19} (Motorola s19). @option{mem}, or @option{builder}. The relevant flash sectors will be erased prior to programming if the @option{erase} parameter is given. If @option{unlock} is provided, then the flash banks are unlocked before erase and program. The flash bank to use is inferred from the address of each image section. @quotation Warning Be careful using the @option{erase} flag when the flash is holding data you want to preserve. Portions of the flash outside those described in the image's sections might be erased with no notice. @itemize @item When a section of the image being written does not fill out all the sectors it uses, the unwritten parts of those sectors are necessarily also erased, because sectors can't be partially erased. @item Data stored in sector "holes" between image sections are also affected. For example, "@command{flash write_image erase ...}" of an image with one byte at the beginning of a flash bank and one byte at the end erases the entire bank -- not just the two sectors being written. @end itemize Also, when flash protection is important, you must re-apply it after it has been removed by the @option{unlock} flag. @end quotation @end deffn @section Other Flash commands @cindex flash protection @deffn Command {flash erase_check} num Check erase state of sectors in flash bank @var{num}, and display that status. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {flash info} num Print info about flash bank @var{num} The @var{num} parameter is a value shown by @command{flash banks}. This command will first query the hardware, it does not print cached and possibly stale information. @end deffn @anchor{flashprotect} @deffn Command {flash protect} num first last (@option{on}|@option{off}) Enable (@option{on}) or disable (@option{off}) protection of flash sectors in flash bank @var{num}, starting at sector @var{first} and continuing up to and including @var{last}. Providing a @var{last} sector of @option{last} specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {flash padded_value} num value Sets the default value used for padding any image sections, This should normally match the flash bank erased value. If not specified by this comamnd or the flash driver then it defaults to 0xff. @end deffn @anchor{program} @deffn Command {program} filename [verify] [reset] [exit] [offset] This is a helper script that simplifies using OpenOCD as a standalone programmer. The only required parameter is @option{filename}, the others are optional. @xref{Flash Programming}. @end deffn @anchor{flashdriverlist} @section Flash Driver List As noted above, the @command{flash bank} command requires a driver name, and allows driver-specific options and behaviors. Some drivers also activate driver-specific commands. @deffn {Flash Driver} virtual This is a special driver that maps a previously defined bank to another address. All bank settings will be copied from the master physical bank. The @var{virtual} driver defines one mandatory parameters, @itemize @item @var{master_bank} The bank that this virtual address refers to. @end itemize So in the following example addresses 0xbfc00000 and 0x9fc00000 refer to the flash bank defined at address 0x1fc00000. Any cmds executed on the virtual banks are actually performed on the physical banks. @example flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME flash bank vbank0 virtual 0xbfc00000 0 0 0 $_TARGETNAME $_FLASHNAME flash bank vbank1 virtual 0x9fc00000 0 0 0 $_TARGETNAME $_FLASHNAME @end example @end deffn @subsection External Flash @deffn {Flash Driver} cfi @cindex Common Flash Interface @cindex CFI The ``Common Flash Interface'' (CFI) is the main standard for external NOR flash chips, each of which connects to a specific external chip select on the CPU. Frequently the first such chip is used to boot the system. Your board's @code{reset-init} handler might need to configure additional chip selects using other commands (like: @command{mww} to configure a bus and its timings), or perhaps configure a GPIO pin that controls the ``write protect'' pin on the flash chip. The CFI driver can use a target-specific working area to significantly speed up operation. The CFI driver can accept the following optional parameters, in any order: @itemize @item @var{jedec_probe} ... is used to detect certain non-CFI flash ROMs, like AM29LV010 and similar types. @item @var{x16_as_x8} ... when a 16-bit flash is hooked up to an 8-bit bus. @end itemize To configure two adjacent banks of 16 MBytes each, both sixteen bits (two bytes) wide on a sixteen bit bus: @example flash bank $_FLASHNAME cfi 0x00000000 0x01000000 2 2 $_TARGETNAME flash bank $_FLASHNAME cfi 0x01000000 0x01000000 2 2 $_TARGETNAME @end example To configure one bank of 32 MBytes built from two sixteen bit (two byte) wide parts wired in parallel to create a thirty-two bit (four byte) bus with doubled throughput: @example flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME @end example @c "cfi part_id" disabled @end deffn @deffn {Flash Driver} lpcspifi @cindex NXP SPI Flash Interface @cindex SPIFI @cindex lpcspifi NXP's LPC43xx and LPC18xx families include a proprietary SPI Flash Interface (SPIFI) peripheral that can drive and provide memory mapped access to external SPI flash devices. The lpcspifi driver initializes this interface and provides program and erase functionality for these serial flash devices. Use of this driver @b{requires} a working area of at least 1kB to be configured on the target device; more than this will significantly reduce flash programming times. The setup command only requires the @var{base} parameter. All other parameters are ignored, and the flash size and layout are configured by the driver. @example flash bank $_FLASHNAME lpcspifi 0x14000000 0 0 0 $_TARGETNAME @end example @end deffn @deffn {Flash Driver} stmsmi @cindex STMicroelectronics Serial Memory Interface @cindex SMI @cindex stmsmi Some devices form STMicroelectronics (e.g. STR75x MCU family, SPEAr MPU family) include a proprietary ``Serial Memory Interface'' (SMI) controller able to drive external SPI flash devices. Depending on specific device and board configuration, up to 4 external flash devices can be connected. SMI makes the flash content directly accessible in the CPU address space; each external device is mapped in a memory bank. CPU can directly read data, execute code and boot from SMI banks. Normal OpenOCD commands like @command{mdw} can be used to display the flash content. The setup command only requires the @var{base} parameter in order to identify the memory bank. All other parameters are ignored. Additional information, like flash size, are detected automatically. @example flash bank $_FLASHNAME stmsmi 0xf8000000 0 0 0 $_TARGETNAME @end example @end deffn @deffn {Flash Driver} mrvlqspi This driver supports QSPI flash controller of Marvell's Wireless Microcontroller platform. The flash size is autodetected based on the table of known JEDEC IDs hardcoded in the OpenOCD sources. @example flash bank $_FLASHNAME mrvlqspi 0x0 0 0 0 $_TARGETNAME 0x46010000 @end example @end deffn @subsection Internal Flash (Microcontrollers) @deffn {Flash Driver} aduc702x The ADUC702x analog microcontrollers from Analog Devices include internal flash and use ARM7TDMI cores. The aduc702x flash driver works with models ADUC7019 through ADUC7028. The setup command only requires the @var{target} argument since all devices in this family have the same memory layout. @example flash bank $_FLASHNAME aduc702x 0 0 0 0 $_TARGETNAME @end example @end deffn @anchor{at91samd} @deffn {Flash Driver} at91samd @cindex at91samd @deffn Command {at91samd chip-erase} Issues a complete Flash erase via the Device Service Unit (DSU). This can be used to erase a chip back to its factory state and does not require the processor to be halted. @end deffn @deffn Command {at91samd set-security} Secures the Flash via the Set Security Bit (SSB) command. This prevents access to the Flash and can only be undone by using the chip-erase command which erases the Flash contents and turns off the security bit. Warning: at this time, openocd will not be able to communicate with a secured chip and it is therefore not possible to chip-erase it without using another tool. @example at91samd set-security enable @end example @end deffn @deffn Command {at91samd eeprom} Shows or sets the EEPROM emulation size configuration, stored in the User Row of the Flash. When setting, the EEPROM size must be specified in bytes and it must be one of the permitted sizes according to the datasheet. Settings are written immediately but only take effect on MCU reset. EEPROM emulation requires additional firmware support and the minumum EEPROM size may not be the same as the minimum that the hardware supports. Set the EEPROM size to 0 in order to disable this feature. @example at91samd eeprom at91samd eeprom 1024 @end example @end deffn @deffn Command {at91samd bootloader} Shows or sets the bootloader size configuration, stored in the User Row of the Flash. This is called the BOOTPROT region. When setting, the bootloader size must be specified in bytes and it must be one of the permitted sizes according to the datasheet. Settings are written immediately but only take effect on MCU reset. Setting the bootloader size to 0 disables bootloader protection. @example at91samd bootloader at91samd bootloader 16384 @end example @end deffn @end deffn @anchor{at91sam3} @deffn {Flash Driver} at91sam3 @cindex at91sam3 All members of the AT91SAM3 microcontroller family from Atmel include internal flash and use ARM's Cortex-M3 core. The driver currently (6/22/09) recognizes the AT91SAM3U[1/2/4][C/E] chips. Note that the driver was orginaly developed and tested using the AT91SAM3U4E, using a SAM3U-EK eval board. Support for other chips in the family was cribbed from the data sheet. @emph{Note to future readers/updaters: Please remove this worrysome comment after other chips are confirmed.} The AT91SAM3U4[E/C] (256K) chips have two flash banks; most other chips have one flash bank. In all cases the flash banks are at the following fixed locations: @example # Flash bank 0 - all chips flash bank $_FLASHNAME at91sam3 0x00080000 0 1 1 $_TARGETNAME # Flash bank 1 - only 256K chips flash bank $_FLASHNAME at91sam3 0x00100000 0 1 1 $_TARGETNAME @end example Internally, the AT91SAM3 flash memory is organized as follows. Unlike the AT91SAM7 chips, these are not used as parameters to the @command{flash bank} command: @itemize @item @emph{N-Banks:} 256K chips have 2 banks, others have 1 bank. @item @emph{Bank Size:} 128K/64K Per flash bank @item @emph{Sectors:} 16 or 8 per bank @item @emph{SectorSize:} 8K Per Sector @item @emph{PageSize:} 256 bytes per page. Note that OpenOCD operates on 'sector' sizes, not page sizes. @end itemize The AT91SAM3 driver adds some additional commands: @deffn Command {at91sam3 gpnvm} @deffnx Command {at91sam3 gpnvm clear} number @deffnx Command {at91sam3 gpnvm set} number @deffnx Command {at91sam3 gpnvm show} [@option{all}|number] With no parameters, @command{show} or @command{show all}, shows the status of all GPNVM bits. With @command{show} @var{number}, displays that bit. With @command{set} @var{number} or @command{clear} @var{number}, modifies that GPNVM bit. @end deffn @deffn Command {at91sam3 info} This command attempts to display information about the AT91SAM3 chip. @emph{First} it read the @code{CHIPID_CIDR} [address 0x400e0740, see Section 28.2.1, page 505 of the AT91SAM3U 29/may/2009 datasheet, document id: doc6430A] and decodes the values. @emph{Second} it reads the various clock configuration registers and attempts to display how it believes the chip is configured. By default, the SLOWCLK is assumed to be 32768 Hz, see the command @command{at91sam3 slowclk}. @end deffn @deffn Command {at91sam3 slowclk} [value] This command shows/sets the slow clock frequency used in the @command{at91sam3 info} command calculations above. @end deffn @end deffn @deffn {Flash Driver} at91sam4 @cindex at91sam4 All members of the AT91SAM4 microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same cmd names/syntax as @xref{at91sam3}. @end deffn @deffn {Flash Driver} at91sam4l @cindex at91sam4l All members of the AT91SAM4L microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same cmd names/syntax as @xref{at91sam3}. The AT91SAM4L driver adds some additional commands: @deffn Command {at91sam4l smap_reset_deassert} This command releases internal reset held by SMAP and prepares reset vector catch in case of reset halt. Command is used internally in event event reset-deassert-post. @end deffn @end deffn @deffn {Flash Driver} at91sam7 All members of the AT91SAM7 microcontroller family from Atmel include internal flash and use ARM7TDMI cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @example flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME @end example For chips which are not recognized by the controller driver, you must provide additional parameters in the following order: @itemize @item @var{chip_model} ... label used with @command{flash info} @item @var{banks} @item @var{sectors_per_bank} @item @var{pages_per_sector} @item @var{pages_size} @item @var{num_nvm_bits} @item @var{freq_khz} ... required if an external clock is provided, optional (but recommended) when the oscillator frequency is known @end itemize It is recommended that you provide zeroes for all of those values except the clock frequency, so that everything except that frequency will be autoconfigured. Knowing the frequency helps ensure correct timings for flash access. The flash controller handles erases automatically on a page (128/256 byte) basis, so explicit erase commands are not necessary for flash programming. However, there is an ``EraseAll`` command that can erase an entire flash plane (of up to 256KB), and it will be used automatically when you issue @command{flash erase_sector} or @command{flash erase_address} commands. @deffn Command {at91sam7 gpnvm} bitnum (@option{set}|@option{clear}) Set or clear a ``General Purpose Non-Volatile Memory'' (GPNVM) bit for the processor. Each processor has a number of such bits, used for controlling features such as brownout detection (so they are not truly general purpose). @quotation Note This assumes that the first flash bank (number 0) is associated with the appropriate at91sam7 target. @end quotation @end deffn @end deffn @deffn {Flash Driver} avr The AVR 8-bit microcontrollers from Atmel integrate flash memory. @emph{The current implementation is incomplete.} @comment - defines mass_erase ... pointless given flash_erase_address @end deffn @deffn {Flash Driver} efm32 All members of the EFM32 microcontroller family from Energy Micro include internal flash and use ARM Cortex M3 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @example flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME @end example @emph{The current implementation is incomplete. Unprotecting flash pages is not supported.} @end deffn @deffn {Flash Driver} lpc2000 This is the driver to support internal flash of all members of the LPC11(x)00 and LPC1300 microcontroller families and most members of the LPC800, LPC1500, LPC1700, LPC1800, LPC2000, LPC4000 and LPC54100 microcontroller families from NXP. @quotation Note There are LPC2000 devices which are not supported by the @var{lpc2000} driver: The LPC2888 is supported by the @var{lpc288x} driver. The LPC29xx family is supported by the @var{lpc2900} driver. @end quotation The @var{lpc2000} driver defines two mandatory and one optional parameters, which must appear in the following order: @itemize @item @var{variant} ... required, may be @option{lpc2000_v1} (older LPC21xx and LPC22xx) @option{lpc2000_v2} (LPC213x, LPC214x, LPC210[123], LPC23xx and LPC24xx) @option{lpc1700} (LPC175x and LPC176x and LPC177x/8x) @option{lpc4300} - available also as @option{lpc1800} alias (LPC18x[2357] and LPC43x[2357]) @option{lpc800} (LPC8xx) @option{lpc1100} (LPC11(x)xx and LPC13xx) @option{lpc1500} (LPC15xx) @option{lpc54100} (LPC541xx) @option{lpc4000} (LPC40xx) or @option{auto} - automatically detects flash variant and size for LPC11(x)00, LPC8xx, LPC13xx, LPC17xx and LPC40xx @item @var{clock_kHz} ... the frequency, in kiloHertz, at which the core is running @item @option{calc_checksum} ... optional (but you probably want to provide this!), telling the driver to calculate a valid checksum for the exception vector table. @quotation Note If you don't provide @option{calc_checksum} when you're writing the vector table, the boot ROM will almost certainly ignore your flash image. However, if you do provide it, with most tool chains @command{verify_image} will fail. @end quotation @end itemize LPC flashes don't require the chip and bus width to be specified. @example flash bank $_FLASHNAME lpc2000 0x0 0x7d000 0 0 $_TARGETNAME \ lpc2000_v2 14765 calc_checksum @end example @deffn {Command} {lpc2000 part_id} bank Displays the four byte part identifier associated with the specified flash @var{bank}. @end deffn @end deffn @deffn {Flash Driver} lpc288x The LPC2888 microcontroller from NXP needs slightly different flash support from its lpc2000 siblings. The @var{lpc288x} driver defines one mandatory parameter, the programming clock rate in Hz. LPC flashes don't require the chip and bus width to be specified. @example flash bank $_FLASHNAME lpc288x 0 0 0 0 $_TARGETNAME 12000000 @end example @end deffn @deffn {Flash Driver} lpc2900 This driver supports the LPC29xx ARM968E based microcontroller family from NXP. The predefined parameters @var{base}, @var{size}, @var{chip_width} and @var{bus_width} of the @code{flash bank} command are ignored. Flash size and sector layout are auto-configured by the driver. The driver has one additional mandatory parameter: The CPU clock rate (in kHz) at the time the flash operations will take place. Most of the time this will not be the crystal frequency, but a higher PLL frequency. The @code{reset-init} event handler in the board script is usually the place where you start the PLL. The driver rejects flashless devices (currently the LPC2930). The EEPROM in LPC2900 devices is not mapped directly into the address space. It must be handled much more like NAND flash memory, and will therefore be handled by a separate @code{lpc2900_eeprom} driver (not yet available). Sector protection in terms of the LPC2900 is handled transparently. Every time a sector needs to be erased or programmed, it is automatically unprotected. What is shown as protection status in the @code{flash info} command, is actually the LPC2900 @emph{sector security}. This is a mechanism to prevent a sector from ever being erased or programmed again. As this is an irreversible mechanism, it is handled by a special command (@code{lpc2900 secure_sector}), and not by the standard @code{flash protect} command. Example for a 125 MHz clock frequency: @example flash bank $_FLASHNAME lpc2900 0 0 0 0 $_TARGETNAME 125000 @end example Some @code{lpc2900}-specific commands are defined. In the following command list, the @var{bank} parameter is the bank number as obtained by the @code{flash banks} command. @deffn Command {lpc2900 signature} bank Calculates a 128-bit hash value, the @emph{signature}, from the whole flash content. This is a hardware feature of the flash block, hence the calculation is very fast. You may use this to verify the content of a programmed device against a known signature. Example: @example lpc2900 signature 0 signature: 0x5f40cdc8:0xc64e592e:0x10490f89:0x32a0f317 @end example @end deffn @deffn Command {lpc2900 read_custom} bank filename Reads the 912 bytes of customer information from the flash index sector, and saves it to a file in binary format. Example: @example lpc2900 read_custom 0 /path_to/customer_info.bin @end example @end deffn The index sector of the flash is a @emph{write-only} sector. It cannot be erased! In order to guard against unintentional write access, all following commands need to be preceeded by a successful call to the @code{password} command: @deffn Command {lpc2900 password} bank password You need to use this command right before each of the following commands: @code{lpc2900 write_custom}, @code{lpc2900 secure_sector}, @code{lpc2900 secure_jtag}. The password string is fixed to "I_know_what_I_am_doing". Example: @example lpc2900 password 0 I_know_what_I_am_doing Potentially dangerous operation allowed in next command! @end example @end deffn @deffn Command {lpc2900 write_custom} bank filename type Writes the content of the file into the customer info space of the flash index sector. The filetype can be specified with the @var{type} field. Possible values for @var{type} are: @var{bin} (binary), @var{ihex} (Intel hex format), @var{elf} (ELF binary) or @var{s19} (Motorola S-records). The file must contain a single section, and the contained data length must be exactly 912 bytes. @quotation Attention This cannot be reverted! Be careful! @end quotation Example: @example lpc2900 write_custom 0 /path_to/customer_info.bin bin @end example @end deffn @deffn Command {lpc2900 secure_sector} bank first last Secures the sector range from @var{first} to @var{last} (including) against further program and erase operations. The sector security will be effective after the next power cycle. @quotation Attention This cannot be reverted! Be careful! @end quotation Secured sectors appear as @emph{protected} in the @code{flash info} command. Example: @example lpc2900 secure_sector 0 1 1 flash info 0 #0 : lpc2900 at 0x20000000, size 0x000c0000, (...) # 0: 0x00000000 (0x2000 8kB) not protected # 1: 0x00002000 (0x2000 8kB) protected # 2: 0x00004000 (0x2000 8kB) not protected @end example @end deffn @deffn Command {lpc2900 secure_jtag} bank Irreversibly disable the JTAG port. The new JTAG security setting will be effective after the next power cycle. @quotation Attention This cannot be reverted! Be careful! @end quotation Examples: @example lpc2900 secure_jtag 0 @end example @end deffn @end deffn @deffn {Flash Driver} ocl This driver is an implementation of the ``on chip flash loader'' protocol proposed by Pavel Chromy. It is a minimalistic command-response protocol intended to be used over a DCC when communicating with an internal or external flash loader running from RAM. An example implementation for AT91SAM7x is available in @file{contrib/loaders/flash/at91sam7x/}. @example flash bank $_FLASHNAME ocl 0 0 0 0 $_TARGETNAME @end example @end deffn @deffn {Flash Driver} pic32mx The PIC32MX microcontrollers are based on the MIPS 4K cores, and integrate flash memory. @example flash bank $_FLASHNAME pix32mx 0x1fc00000 0 0 0 $_TARGETNAME flash bank $_FLASHNAME pix32mx 0x1d000000 0 0 0 $_TARGETNAME @end example @comment numerous *disabled* commands are defined: @comment - chip_erase ... pointless given flash_erase_address @comment - lock, unlock ... pointless given protect on/off (yes?) @comment - pgm_word ... shouldn't bank be deduced from address?? Some pic32mx-specific commands are defined: @deffn Command {pic32mx pgm_word} address value bank Programs the specified 32-bit @var{value} at the given @var{address} in the specified chip @var{bank}. @end deffn @deffn Command {pic32mx unlock} bank Unlock and erase specified chip @var{bank}. This will remove any Code Protection. @end deffn @end deffn @deffn {Flash Driver} psoc4 All members of the PSoC 41xx/42xx microcontroller family from Cypress include internal flash and use ARM Cortex M0 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note: Erased internal flash reads as 00. System ROM of PSoC 4 does not implement erase of a flash sector. @example flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME @end example psoc4-specific commands @deffn Command {psoc4 flash_autoerase} num (on|off) Enables or disables autoerase mode for a flash bank. If flash_autoerase is off, use mass_erase before flash programming. Flash erase command fails if region to erase is not whole flash memory. If flash_autoerase is on, a sector is both erased and programmed in one system ROM call. Flash erase command is ignored. This mode is suitable for gdb load. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {psoc4 mass_erase} num Erases the contents of the flash memory, protection and security lock. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn @deffn {Flash Driver} stellaris All members of the Stellaris LM3Sxxx, LM4x and Tiva C microcontroller families from Texas Instruments include internal flash. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @footnote{Currently there is a @command{stellaris mass_erase} command. That seems pointless since the same effect can be had using the standard @command{flash erase_address} command.} @example flash bank $_FLASHNAME stellaris 0 0 0 0 $_TARGETNAME @end example @deffn Command {stellaris recover} Performs the @emph{Recovering a "Locked" Device} procedure to restore the flash and its associated nonvolatile registers to their factory default values (erased). This is the only way to remove flash protection or re-enable debugging if that capability has been disabled. Note that the final "power cycle the chip" step in this procedure must be performed by hand, since OpenOCD can't do it. @quotation Warning if more than one Stellaris chip is connected, the procedure is applied to all of them. @end quotation @end deffn @end deffn @deffn {Flash Driver} stm32f1x All members of the STM32F0, STM32F1 and STM32F3 microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M0/M3/M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @example flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME @end example Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. @example flash bank $_FLASHNAME stm32f1x 0 0x20000 0 0 $_TARGETNAME @end example If you have a target with dual flash banks then define the second bank as per the following example. @example flash bank $_FLASHNAME stm32f1x 0x08080000 0 0 0 $_TARGETNAME @end example Some stm32f1x-specific commands @footnote{Currently there is a @command{stm32f1x mass_erase} command. That seems pointless since the same effect can be had using the standard @command{flash erase_address} command.} are defined: @deffn Command {stm32f1x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f1x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f1x options_read} num Read and display the stm32 option bytes written by the @command{stm32f1x options_write} command. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f1x options_write} num (@option{SWWDG}|@option{HWWDG}) (@option{RSTSTNDBY}|@option{NORSTSTNDBY}) (@option{RSTSTOP}|@option{NORSTSTOP}) Writes the stm32 option byte with the specified values. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn @deffn {Flash Driver} stm32f2x All members of the STM32F2 and STM32F4 microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M3/M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. @example flash bank $_FLASHNAME stm32f2x 0 0x20000 0 0 $_TARGETNAME @end example Some stm32f2x-specific commands are defined: @deffn Command {stm32f2x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f2x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn @deffn {Flash Driver} stm32lx All members of the STM32L microcontroller families from ST Microelectronics include internal flash and use ARM Cortex-M3 and Cortex-M0+ cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. If you use 0 as the bank base address, it tells the driver to autodetect the bank location assuming you're configuring the second bank. @example flash bank $_FLASHNAME stm32lx 0x08000000 0x20000 0 0 $_TARGETNAME @end example Some stm32lx-specific commands are defined: @deffn Command {stm32lx mass_erase} num Mass erases the entire stm32lx device (all flash banks and EEPROM data). This is the only way to unlock a protected flash (unless RDP Level is 2 which can't be unlocked at all). The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn @deffn {Flash Driver} str7x All members of the STR7 microcontroller family from ST Microelectronics include internal flash and use ARM7TDMI cores. The @var{str7x} driver defines one mandatory parameter, @var{variant}, which is either @code{STR71x}, @code{STR73x} or @code{STR75x}. @example flash bank $_FLASHNAME str7x \ 0x40000000 0x00040000 0 0 $_TARGETNAME STR71x @end example @deffn Command {str7x disable_jtag} bank Activate the Debug/Readout protection mechanism for the specified flash bank. @end deffn @end deffn @deffn {Flash Driver} str9x Most members of the STR9 microcontroller family from ST Microelectronics include internal flash and use ARM966E cores. The str9 needs the flash controller to be configured using the @command{str9x flash_config} command prior to Flash programming. @example flash bank $_FLASHNAME str9x 0x40000000 0x00040000 0 0 $_TARGETNAME str9x flash_config 0 4 2 0 0x80000 @end example @deffn Command {str9x flash_config} num bbsr nbbsr bbadr nbbadr Configures the str9 flash controller. The @var{num} parameter is a value shown by @command{flash banks}. @itemize @bullet @item @var{bbsr} - Boot Bank Size register @item @var{nbbsr} - Non Boot Bank Size register @item @var{bbadr} - Boot Bank Start Address register @item @var{nbbadr} - Boot Bank Start Address register @end itemize @end deffn @end deffn @deffn {Flash Driver} str9xpec @cindex str9xpec Only use this driver for locking/unlocking the device or configuring the option bytes. Use the standard str9 driver for programming. Before using the flash commands the turbo mode must be enabled using the @command{str9xpec enable_turbo} command. Here is some background info to help you better understand how this driver works. OpenOCD has two flash drivers for the str9: @enumerate @item Standard driver @option{str9x} programmed via the str9 core. Normally used for flash programming as it is faster than the @option{str9xpec} driver. @item Direct programming @option{str9xpec} using the flash controller. This is an ISC compilant (IEEE 1532) tap connected in series with the str9 core. The str9 core does not need to be running to program using this flash driver. Typical use for this driver is locking/unlocking the target and programming the option bytes. @end enumerate Before we run any commands using the @option{str9xpec} driver we must first disable the str9 core. This example assumes the @option{str9xpec} driver has been configured for flash bank 0. @example # assert srst, we do not want core running # while accessing str9xpec flash driver jtag_reset 0 1 # turn off target polling poll off # disable str9 core str9xpec enable_turbo 0 # read option bytes str9xpec options_read 0 # re-enable str9 core str9xpec disable_turbo 0 poll on reset halt @end example The above example will read the str9 option bytes. When performing a unlock remember that you will not be able to halt the str9 - it has been locked. Halting the core is not required for the @option{str9xpec} driver as mentioned above, just issue the commands above manually or from a telnet prompt. Several str9xpec-specific commands are defined: @deffn Command {str9xpec disable_turbo} num Restore the str9 into JTAG chain. @end deffn @deffn Command {str9xpec enable_turbo} num Enable turbo mode, will simply remove the str9 from the chain and talk directly to the embedded flash controller. @end deffn @deffn Command {str9xpec lock} num Lock str9 device. The str9 will only respond to an unlock command that will erase the device. @end deffn @deffn Command {str9xpec part_id} num Prints the part identifier for bank @var{num}. @end deffn @deffn Command {str9xpec options_cmap} num (@option{bank0}|@option{bank1}) Configure str9 boot bank. @end deffn @deffn Command {str9xpec options_lvdsel} num (@option{vdd}|@option{vdd_vddq}) Configure str9 lvd source. @end deffn @deffn Command {str9xpec options_lvdthd} num (@option{2.4v}|@option{2.7v}) Configure str9 lvd threshold. @end deffn @deffn Command {str9xpec options_lvdwarn} bank (@option{vdd}|@option{vdd_vddq}) Configure str9 lvd reset warning source. @end deffn @deffn Command {str9xpec options_read} num Read str9 option bytes. @end deffn @deffn Command {str9xpec options_write} num Write str9 option bytes. @end deffn @deffn Command {str9xpec unlock} num unlock str9 device. @end deffn @end deffn @deffn {Flash Driver} tms470 Most members of the TMS470 microcontroller family from Texas Instruments include internal flash and use ARM7TDMI cores. This driver doesn't require the chip and bus width to be specified. Some tms470-specific commands are defined: @deffn Command {tms470 flash_keyset} key0 key1 key2 key3 Saves programming keys in a register, to enable flash erase and write commands. @end deffn @deffn Command {tms470 osc_mhz} clock_mhz Reports the clock speed, which is used to calculate timings. @end deffn @deffn Command {tms470 plldis} (0|1) Disables (@var{1}) or enables (@var{0}) use of the PLL to speed up the flash clock. @end deffn @end deffn @deffn {Flash Driver} fm3 All members of the FM3 microcontroller family from Fujitsu include internal flash and use ARM Cortex M3 cores. The @var{fm3} driver uses the @var{target} parameter to select the correct bank config, it can currently be one of the following: @code{mb9bfxx1.cpu}, @code{mb9bfxx2.cpu}, @code{mb9bfxx3.cpu}, @code{mb9bfxx4.cpu}, @code{mb9bfxx5.cpu} or @code{mb9bfxx6.cpu}. @example flash bank $_FLASHNAME fm3 0 0 0 0 $_TARGETNAME @end example @end deffn @deffn {Flash Driver} sim3x All members of the SiM3 microcontroller family from Silicon Laboratories include internal flash and use ARM Cortex M3 cores. It supports both JTAG and SWD interface. The @var{sim3x} driver tries to probe the device to auto detect the MCU. If this failes, it will use the @var{size} parameter as the size of flash bank. @example flash bank $_FLASHNAME sim3x 0 $_CPUROMSIZE 0 0 $_TARGETNAME @end example There are 2 commands defined in the @var{sim3x} driver: @deffn Command {sim3x mass_erase} Erases the complete flash. This is used to unlock the flash. And this command is only possible when using the SWD interface. @end deffn @deffn Command {sim3x lock} Lock the flash. To unlock use the @command{sim3x mass_erase} command. @end deffn @end deffn @deffn {Flash Driver} nrf51 All members of the nRF51 microcontroller families from Nordic Semiconductor include internal flash and use ARM Cortex-M0 core. @example flash bank $_FLASHNAME nrf51 0 0x00000000 0 0 $_TARGETNAME @end example Some nrf51-specific commands are defined: @deffn Command {nrf51 mass_erase} Erases the contents of the code memory and user information configuration registers as well. It must be noted that this command works only for chips that do not have factory pre-programmed region 0 code. @end deffn @end deffn @deffn {Flash Driver} mdr This drivers handles the integrated NOR flash on Milandr Cortex-M based controllers. A known limitation is that the Info memory can't be read or verified as it's not memory mapped. @example flash bank mdr \ 0 0 @var{type} @var{page_count} @var{sec_count} @end example @itemize @bullet @item @var{type} - 0 for main memory, 1 for info memory @item @var{page_count} - total number of pages @item @var{sec_count} - number of sector per page count @end itemize Example usage: @example if @{ [info exists IMEMORY] && [string equal $IMEMORY true] @} @{ flash bank $@{_CHIPNAME@}_info.flash mdr 0x00000000 0x01000 \ 0 0 $_TARGETNAME 1 1 4 @} else @{ flash bank $_CHIPNAME.flash mdr 0x00000000 0x20000 \ 0 0 $_TARGETNAME 0 32 4 @} @end example @end deffn @section NAND Flash Commands @cindex NAND Compared to NOR or SPI flash, NAND devices are inexpensive and high density. Today's NAND chips, and multi-chip modules, commonly hold multiple GigaBytes of data. NAND chips consist of a number of ``erase blocks'' of a given size (such as 128 KBytes), each of which is divided into a number of pages (of perhaps 512 or 2048 bytes each). Each page of a NAND flash has an ``out of band'' (OOB) area to hold Error Correcting Code (ECC) and other metadata, usually 16 bytes of OOB for every 512 bytes of page data. One key characteristic of NAND flash is that its error rate is higher than that of NOR flash. In normal operation, that ECC is used to correct and detect errors. However, NAND blocks can also wear out and become unusable; those blocks are then marked "bad". NAND chips are even shipped from the manufacturer with a few bad blocks. The highest density chips use a technology (MLC) that wears out more quickly, so ECC support is increasingly important as a way to detect blocks that have begun to fail, and help to preserve data integrity with techniques such as wear leveling. Software is used to manage the ECC. Some controllers don't support ECC directly; in those cases, software ECC is used. Other controllers speed up the ECC calculations with hardware. Single-bit error correction hardware is routine. Controllers geared for newer MLC chips may correct 4 or more errors for every 512 bytes of data. You will need to make sure that any data you write using OpenOCD includes the apppropriate kind of ECC. For example, that may mean passing the @code{oob_softecc} flag when writing NAND data, or ensuring that the correct hardware ECC mode is used. The basic steps for using NAND devices include: @enumerate @item Declare via the command @command{nand device} @* Do this in a board-specific configuration file, passing parameters as needed by the controller. @item Configure each device using @command{nand probe}. @* Do this only after the associated target is set up, such as in its reset-init script or in procures defined to access that device. @item Operate on the flash via @command{nand subcommand} @* Often commands to manipulate the flash are typed by a human, or run via a script in some automated way. Common task include writing a boot loader, operating system, or other data needed to initialize or de-brick a board. @end enumerate @b{NOTE:} At the time this text was written, the largest NAND flash fully supported by OpenOCD is 2 GiBytes (16 GiBits). This is because the variables used to hold offsets and lengths are only 32 bits wide. (Larger chips may work in some cases, unless an offset or length is larger than 0xffffffff, the largest 32-bit unsigned integer.) Some larger devices will work, since they are actually multi-chip modules with two smaller chips and individual chipselect lines. @anchor{nandconfiguration} @subsection NAND Configuration Commands @cindex NAND configuration NAND chips must be declared in configuration scripts, plus some additional configuration that's done after OpenOCD has initialized. @deffn {Config Command} {nand device} name driver target [configparams...] Declares a NAND device, which can be read and written to after it has been configured through @command{nand probe}. In OpenOCD, devices are single chips; this is unlike some operating systems, which may manage multiple chips as if they were a single (larger) device. In some cases, configuring a device will activate extra commands; see the controller-specific documentation. @b{NOTE:} This command is not available after OpenOCD initialization has completed. Use it in board specific configuration files, not interactively. @itemize @bullet @item @var{name} ... may be used to reference the NAND bank in most other NAND commands. A number is also available. @item @var{driver} ... identifies the NAND controller driver associated with the NAND device being declared. @xref{nanddriverlist,,NAND Driver List}. @item @var{target} ... names the target used when issuing commands to the NAND controller. @comment Actually, it's currently a controller-specific parameter... @item @var{configparams} ... controllers may support, or require, additional parameters. See the controller-specific documentation for more information. @end itemize @end deffn @deffn Command {nand list} Prints a summary of each device declared using @command{nand device}, numbered from zero. Note that un-probed devices show no details. @example > nand list #0: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8, blocksize: 131072, blocks: 8192 #1: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8, blocksize: 131072, blocks: 8192 > @end example @end deffn @deffn Command {nand probe} num Probes the specified device to determine key characteristics like its page and block sizes, and how many blocks it has. The @var{num} parameter is the value shown by @command{nand list}. You must (successfully) probe a device before you can use it with most other NAND commands. @end deffn @subsection Erasing, Reading, Writing to NAND Flash @deffn Command {nand dump} num filename offset length [oob_option] @cindex NAND reading Reads binary data from the NAND device and writes it to the file, starting at the specified offset. The @var{num} parameter is the value shown by @command{nand list}. Use a complete path name for @var{filename}, so you don't depend on the directory used to start the OpenOCD server. The @var{offset} and @var{length} must be exact multiples of the device's page size. They describe a data region; the OOB data associated with each such page may also be accessed. @b{NOTE:} At the time this text was written, no error correction was done on the data that's read, unless raw access was disabled and the underlying NAND controller driver had a @code{read_page} method which handled that error correction. By default, only page data is saved to the specified file. Use an @var{oob_option} parameter to save OOB data: @itemize @bullet @item no oob_* parameter @*Output file holds only page data; OOB is discarded. @item @code{oob_raw} @*Output file interleaves page data and OOB data; the file will be longer than "length" by the size of the spare areas associated with each data page. Note that this kind of "raw" access is different from what's implied by @command{nand raw_access}, which just controls whether a hardware-aware access method is used. @item @code{oob_only} @*Output file has only raw OOB data, and will be smaller than "length" since it will contain only the spare areas associated with each data page. @end itemize @end deffn @deffn Command {nand erase} num [offset length] @cindex NAND erasing @cindex NAND programming Erases blocks on the specified NAND device, starting at the specified @var{offset} and continuing for @var{length} bytes. Both of those values must be exact multiples of the device's block size, and the region they specify must fit entirely in the chip. If those parameters are not specified, the whole NAND chip will be erased. The @var{num} parameter is the value shown by @command{nand list}. @b{NOTE:} This command will try to erase bad blocks, when told to do so, which will probably invalidate the manufacturer's bad block marker. For the remainder of the current server session, @command{nand info} will still report that the block ``is'' bad. @end deffn @deffn Command {nand write} num filename offset [option...] @cindex NAND writing @cindex NAND programming Writes binary data from the file into the specified NAND device, starting at the specified offset. Those pages should already have been erased; you can't change zero bits to one bits. The @var{num} parameter is the value shown by @command{nand list}. Use a complete path name for @var{filename}, so you don't depend on the directory used to start the OpenOCD server. The @var{offset} must be an exact multiple of the device's page size. All data in the file will be written, assuming it doesn't run past the end of the device. Only full pages are written, and any extra space in the last page will be filled with 0xff bytes. (That includes OOB data, if that's being written.) @b{NOTE:} At the time this text was written, bad blocks are ignored. That is, this routine will not skip bad blocks, but will instead try to write them. This can cause problems. Provide at most one @var{option} parameter. With some NAND drivers, the meanings of these parameters may change if @command{nand raw_access} was used to disable hardware ECC. @itemize @bullet @item no oob_* parameter @*File has only page data, which is written. If raw acccess is in use, the OOB area will not be written. Otherwise, if the underlying NAND controller driver has a @code{write_page} routine, that routine may write the OOB with hardware-computed ECC data. @item @code{oob_only} @*File has only raw OOB data, which is written to the OOB area. Each page's data area stays untouched. @i{This can be a dangerous option}, since it can invalidate the ECC data. You may need to force raw access to use this mode. @item @code{oob_raw} @*File interleaves data and OOB data, both of which are written If raw access is enabled, the data is written first, then the un-altered OOB. Otherwise, if the underlying NAND controller driver has a @code{write_page} routine, that routine may modify the OOB before it's written, to include hardware-computed ECC data. @item @code{oob_softecc} @*File has only page data, which is written. The OOB area is filled with 0xff, except for a standard 1-bit software ECC code stored in conventional locations. You might need to force raw access to use this mode, to prevent the underlying driver from applying hardware ECC. @item @code{oob_softecc_kw} @*File has only page data, which is written. The OOB area is filled with 0xff, except for a 4-bit software ECC specific to the boot ROM in Marvell Kirkwood SoCs. You might need to force raw access to use this mode, to prevent the underlying driver from applying hardware ECC. @end itemize @end deffn @deffn Command {nand verify} num filename offset [option...] @cindex NAND verification @cindex NAND programming Verify the binary data in the file has been programmed to the specified NAND device, starting at the specified offset. The @var{num} parameter is the value shown by @command{nand list}. Use a complete path name for @var{filename}, so you don't depend on the directory used to start the OpenOCD server. The @var{offset} must be an exact multiple of the device's page size. All data in the file will be read and compared to the contents of the flash, assuming it doesn't run past the end of the device. As with @command{nand write}, only full pages are verified, so any extra space in the last page will be filled with 0xff bytes. The same @var{options} accepted by @command{nand write}, and the file will be processed similarly to produce the buffers that can be compared against the contents produced from @command{nand dump}. @b{NOTE:} This will not work when the underlying NAND controller driver's @code{write_page} routine must update the OOB with a hardward-computed ECC before the data is written. This limitation may be removed in a future release. @end deffn @subsection Other NAND commands @cindex NAND other commands @deffn Command {nand check_bad_blocks} num [offset length] Checks for manufacturer bad block markers on the specified NAND device. If no parameters are provided, checks the whole device; otherwise, starts at the specified @var{offset} and continues for @var{length} bytes. Both of those values must be exact multiples of the device's block size, and the region they specify must fit entirely in the chip. The @var{num} parameter is the value shown by @command{nand list}. @b{NOTE:} Before using this command you should force raw access with @command{nand raw_access enable} to ensure that the underlying driver will not try to apply hardware ECC. @end deffn @deffn Command {nand info} num The @var{num} parameter is the value shown by @command{nand list}. This prints the one-line summary from "nand list", plus for devices which have been probed this also prints any known status for each block. @end deffn @deffn Command {nand raw_access} num (@option{enable}|@option{disable}) Sets or clears an flag affecting how page I/O is done. The @var{num} parameter is the value shown by @command{nand list}. This flag is cleared (disabled) by default, but changing that value won't affect all NAND devices. The key factor is whether the underlying driver provides @code{read_page} or @code{write_page} methods. If it doesn't provide those methods, the setting of this flag is irrelevant; all access is effectively ``raw''. When those methods exist, they are normally used when reading data (@command{nand dump} or reading bad block markers) or writing it (@command{nand write}). However, enabling raw access (setting the flag) prevents use of those methods, bypassing hardware ECC logic. @i{This can be a dangerous option}, since writing blocks with the wrong ECC data can cause them to be marked as bad. @end deffn @anchor{nanddriverlist} @subsection NAND Driver List As noted above, the @command{nand device} command allows driver-specific options and behaviors. Some controllers also activate controller-specific commands. @deffn {NAND Driver} at91sam9 This driver handles the NAND controllers found on AT91SAM9 family chips from Atmel. It takes two extra parameters: address of the NAND chip; address of the ECC controller. @example nand device $NANDFLASH at91sam9 $CHIPNAME 0x40000000 0xfffffe800 @end example AT91SAM9 chips support single-bit ECC hardware. The @code{write_page} and @code{read_page} methods are used to utilize the ECC hardware unless they are disabled by using the @command{nand raw_access} command. There are four additional commands that are needed to fully configure the AT91SAM9 NAND controller. Two are optional; most boards use the same wiring for ALE/CLE: @deffn Command {at91sam9 cle} num addr_line Configure the address line used for latching commands. The @var{num} parameter is the value shown by @command{nand list}. @end deffn @deffn Command {at91sam9 ale} num addr_line Configure the address line used for latching addresses. The @var{num} parameter is the value shown by @command{nand list}. @end deffn For the next two commands, it is assumed that the pins have already been properly configured for input or output. @deffn Command {at91sam9 rdy_busy} num pio_base_addr pin Configure the RDY/nBUSY input from the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @end deffn @deffn Command {at91sam9 ce} num pio_base_addr pin Configure the chip enable input to the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @end deffn @end deffn @deffn {NAND Driver} davinci This driver handles the NAND controllers found on DaVinci family chips from Texas Instruments. It takes three extra parameters: address of the NAND chip; hardware ECC mode to use (@option{hwecc1}, @option{hwecc4}, @option{hwecc4_infix}); address of the AEMIF controller on this processor. @example nand device davinci dm355.arm 0x02000000 hwecc4 0x01e10000 @end example All DaVinci processors support the single-bit ECC hardware, and newer ones also support the four-bit ECC hardware. The @code{write_page} and @code{read_page} methods are used to implement those ECC modes, unless they are disabled using the @command{nand raw_access} command. @end deffn @deffn {NAND Driver} lpc3180 These controllers require an extra @command{nand device} parameter: the clock rate used by the controller. @deffn Command {lpc3180 select} num [mlc|slc] Configures use of the MLC or SLC controller mode. MLC implies use of hardware ECC. The @var{num} parameter is the value shown by @command{nand list}. @end deffn At this writing, this driver includes @code{write_page} and @code{read_page} methods. Using @command{nand raw_access} to disable those methods will prevent use of hardware ECC in the MLC controller mode, but won't change SLC behavior. @end deffn @comment current lpc3180 code won't issue 5-byte address cycles @deffn {NAND Driver} mx3 This driver handles the NAND controller in i.MX31. The mxc driver should work for this chip aswell. @end deffn @deffn {NAND Driver} mxc This driver handles the NAND controller found in Freescale i.MX chips. It has support for v1 (i.MX27 and i.MX31) and v2 (i.MX35). The driver takes 3 extra arguments, chip (@option{mx27}, @option{mx31}, @option{mx35}), ecc (@option{noecc}, @option{hwecc}) and optionally if bad block information should be swapped between main area and spare area (@option{biswap}), defaults to off. @example nand device mx35.nand mxc imx35.cpu mx35 hwecc biswap @end example @deffn Command {mxc biswap} bank_num [enable|disable] Turns on/off bad block information swaping from main area, without parameter query status. @end deffn @end deffn @deffn {NAND Driver} orion These controllers require an extra @command{nand device} parameter: the address of the controller. @example nand device orion 0xd8000000 @end example These controllers don't define any specialized commands. At this writing, their drivers don't include @code{write_page} or @code{read_page} methods, so @command{nand raw_access} won't change any behavior. @end deffn @deffn {NAND Driver} s3c2410 @deffnx {NAND Driver} s3c2412 @deffnx {NAND Driver} s3c2440 @deffnx {NAND Driver} s3c2443 @deffnx {NAND Driver} s3c6400 These S3C family controllers don't have any special @command{nand device} options, and don't define any specialized commands. At this writing, their drivers don't include @code{write_page} or @code{read_page} methods, so @command{nand raw_access} won't change any behavior. @end deffn @section mFlash @subsection mFlash Configuration @cindex mFlash Configuration @deffn {Config Command} {mflash bank} soc base RST_pin target Configures a mflash for @var{soc} host bank at address @var{base}. The pin number format depends on the host GPIO naming convention. Currently, the mflash driver supports s3c2440 and pxa270. Example for s3c2440 mflash where @var{RST pin} is GPIO B1: @example mflash bank $_FLASHNAME s3c2440 0x10000000 1b 0 @end example Example for pxa270 mflash where @var{RST pin} is GPIO 43: @example mflash bank $_FLASHNAME pxa270 0x08000000 43 0 @end example @end deffn @subsection mFlash commands @cindex mFlash commands @deffn Command {mflash config pll} frequency Configure mflash PLL. The @var{frequency} is the mflash input frequency, in Hz. Issuing this command will erase mflash's whole internal nand and write new pll. After this command, mflash needs power-on-reset for normal operation. If pll was newly configured, storage and boot(optional) info also need to be update. @end deffn @deffn Command {mflash config boot} Configure bootable option. If bootable option is set, mflash offer the first 8 sectors (4kB) for boot. @end deffn @deffn Command {mflash config storage} Configure storage information. For the normal storage operation, this information must be written. @end deffn @deffn Command {mflash dump} num filename offset size Dump @var{size} bytes, starting at @var{offset} bytes from the beginning of the bank @var{num}, to the file named @var{filename}. @end deffn @deffn Command {mflash probe} Probe mflash. @end deffn @deffn Command {mflash write} num filename offset Write the binary file @var{filename} to mflash bank @var{num}, starting at @var{offset} bytes from the beginning of the bank. @end deffn @node Flash Programming @chapter Flash Programming OpenOCD implements numerous ways to program the target flash, whether internal or external. Programming can be acheived by either using GDB @ref{programmingusinggdb,,Programming using GDB}, or using the cmds given in @ref{flashprogrammingcommands,,Flash Programming Commands}. @*To simplify using the flash cmds directly a jimtcl script is available that handles the programming and verify stage. OpenOCD will program/verify/reset the target and optionally shutdown. The script is executed as follows and by default the following actions will be peformed. @enumerate @item 'init' is executed. @item 'reset init' is called to reset and halt the target, any 'reset init' scripts are executed. @item @code{flash write_image} is called to erase and write any flash using the filename given. @item @code{verify_image} is called if @option{verify} parameter is given. @item @code{reset run} is called if @option{reset} parameter is given. @item OpenOCD is shutdown if @option{exit} parameter is given. @end enumerate An example of usage is given below. @xref{program}. @example # program and verify using elf/hex/s19. verify and reset # are optional parameters openocd -f board/stm32f3discovery.cfg \ -c "program filename.elf verify reset exit" # binary files need the flash address passing openocd -f board/stm32f3discovery.cfg \ -c "program filename.bin exit 0x08000000" @end example @node PLD/FPGA Commands @chapter PLD/FPGA Commands @cindex PLD @cindex FPGA Programmable Logic Devices (PLDs) and the more flexible Field Programmable Gate Arrays (FPGAs) are both types of programmable hardware. OpenOCD can support programming them. Although PLDs are generally restrictive (cells are less functional, and there are no special purpose cells for memory or computational tasks), they share the same OpenOCD infrastructure. Accordingly, both are called PLDs here. @section PLD/FPGA Configuration and Commands As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND), OpenOCD maintains a list of PLDs available for use in various commands. Also, each such PLD requires a driver. They are referenced by the number shown by the @command{pld devices} command, and new PLDs are defined by @command{pld device driver_name}. @deffn {Config Command} {pld device} driver_name tap_name [driver_options] Defines a new PLD device, supported by driver @var{driver_name}, using the TAP named @var{tap_name}. The driver may make use of any @var{driver_options} to configure its behavior. @end deffn @deffn {Command} {pld devices} Lists the PLDs and their numbers. @end deffn @deffn {Command} {pld load} num filename Loads the file @file{filename} into the PLD identified by @var{num}. The file format must be inferred by the driver. @end deffn @section PLD/FPGA Drivers, Options, and Commands Drivers may support PLD-specific options to the @command{pld device} definition command, and may also define commands usable only with that particular type of PLD. @deffn {FPGA Driver} virtex2 Virtex-II is a family of FPGAs sold by Xilinx. It supports the IEEE 1532 standard for In-System Configuration (ISC). No driver-specific PLD definition options are used, and one driver-specific command is defined. @deffn {Command} {virtex2 read_stat} num Reads and displays the Virtex-II status register (STAT) for FPGA @var{num}. @end deffn @end deffn @node General Commands @chapter General Commands @cindex commands The commands documented in this chapter here are common commands that you, as a human, may want to type and see the output of. Configuration type commands are documented elsewhere. Intent: @itemize @bullet @item @b{Source Of Commands} @* OpenOCD commands can occur in a configuration script (discussed elsewhere) or typed manually by a human or supplied programatically, or via one of several TCP/IP Ports. @item @b{From the human} @* A human should interact with the telnet interface (default port: 4444) or via GDB (default port 3333). To issue commands from within a GDB session, use the @option{monitor} command, e.g. use @option{monitor poll} to issue the @option{poll} command. All output is relayed through the GDB session. @item @b{Machine Interface} The Tcl interface's intent is to be a machine interface. The default Tcl port is 5555. @end itemize @section Daemon Commands @deffn {Command} exit Exits the current telnet session. @end deffn @deffn {Command} help [string] With no parameters, prints help text for all commands. Otherwise, prints each helptext containing @var{string}. Not every command provides helptext. Configuration commands, and commands valid at any time, are explicitly noted in parenthesis. In most cases, no such restriction is listed; this indicates commands which are only available after the configuration stage has completed. @end deffn @deffn Command sleep msec [@option{busy}] Wait for at least @var{msec} milliseconds before resuming. If @option{busy} is passed, busy-wait instead of sleeping. (This option is strongly discouraged.) Useful in connection with script files (@command{script} command and @command{target_name} configuration). @end deffn @deffn Command shutdown [@option{error}] Close the OpenOCD daemon, disconnecting all clients (GDB, telnet, other). If option @option{error} is used, OpenOCD will return a non-zero exit code to the parent process. @end deffn @anchor{debuglevel} @deffn Command debug_level [n] @cindex message level Display debug level. If @var{n} (from 0..3) is provided, then set it to that level. This affects the kind of messages sent to the server log. Level 0 is error messages only; level 1 adds warnings; level 2 adds informational messages; and level 3 adds debugging messages. The default is level 2, but that can be overridden on the command line along with the location of that log file (which is normally the server's standard output). @xref{Running}. @end deffn @deffn Command echo [-n] message Logs a message at "user" priority. Output @var{message} to stdout. Option "-n" suppresses trailing newline. @example echo "Downloading kernel -- please wait" @end example @end deffn @deffn Command log_output [filename] Redirect logging to @var{filename}; the initial log output channel is stderr. @end deffn @deffn Command add_script_search_dir [directory] Add @var{directory} to the file/script search path. @end deffn @anchor{targetstatehandling} @section Target State handling @cindex reset @cindex halt @cindex target initialization In this section ``target'' refers to a CPU configured as shown earlier (@pxref{CPU Configuration}). These commands, like many, implicitly refer to a current target which is used to perform the various operations. The current target may be changed by using @command{targets} command with the name of the target which should become current. @deffn Command reg [(number|name) [(value|'force')]] Access a single register by @var{number} or by its @var{name}. The target must generally be halted before access to CPU core registers is allowed. Depending on the hardware, some other registers may be accessible while the target is running. @emph{With no arguments}: list all available registers for the current target, showing number, name, size, value, and cache status. For valid entries, a value is shown; valid entries which are also dirty (and will be written back later) are flagged as such. @emph{With number/name}: display that register's value. Use @var{force} argument to read directly from the target, bypassing any internal cache. @emph{With both number/name and value}: set register's value. Writes may be held in a writeback cache internal to OpenOCD, so that setting the value marks the register as dirty instead of immediately flushing that value. Resuming CPU execution (including by single stepping) or otherwise activating the relevant module will flush such values. Cores may have surprisingly many registers in their Debug and trace infrastructure: @example > reg ===== ARM registers (0) r0 (/32): 0x0000D3C2 (dirty) (1) r1 (/32): 0xFD61F31C (2) r2 (/32) ... (164) ETM_contextid_comparator_mask (/32) > @end example @end deffn @deffn Command halt [ms] @deffnx Command wait_halt [ms] The @command{halt} command first sends a halt request to the target, which @command{wait_halt} doesn't. Otherwise these behave the same: wait up to @var{ms} milliseconds, or 5 seconds if there is no parameter, for the target to halt (and enter debug mode). Using 0 as the @var{ms} parameter prevents OpenOCD from waiting. @quotation Warning On ARM cores, software using the @emph{wait for interrupt} operation often blocks the JTAG access needed by a @command{halt} command. This is because that operation also puts the core into a low power mode by gating the core clock; but the core clock is needed to detect JTAG clock transitions. One partial workaround uses adaptive clocking: when the core is interrupted the operation completes, then JTAG clocks are accepted at least until the interrupt handler completes. However, this workaround is often unusable since the processor, board, and JTAG adapter must all support adaptive JTAG clocking. Also, it can't work until an interrupt is issued. A more complete workaround is to not use that operation while you work with a JTAG debugger. Tasking environments generaly have idle loops where the body is the @emph{wait for interrupt} operation. (On older cores, it is a coprocessor action; newer cores have a @option{wfi} instruction.) Such loops can just remove that operation, at the cost of higher power consumption (because the CPU is needlessly clocked). @end quotation @end deffn @deffn Command resume [address] Resume the target at its current code position, or the optional @var{address} if it is provided. OpenOCD will wait 5 seconds for the target to resume. @end deffn @deffn Command step [address] Single-step the target at its current code position, or the optional @var{address} if it is provided. @end deffn @anchor{resetcommand} @deffn Command reset @deffnx Command {reset run} @deffnx Command {reset halt} @deffnx Command {reset init} Perform as hard a reset as possible, using SRST if possible. @emph{All defined targets will be reset, and target events will fire during the reset sequence.} The optional parameter specifies what should happen after the reset. If there is no parameter, a @command{reset run} is executed. The other options will not work on all systems. @xref{Reset Configuration}. @itemize @minus @item @b{run} Let the target run @item @b{halt} Immediately halt the target @item @b{init} Immediately halt the target, and execute the reset-init script @end itemize @end deffn @deffn Command soft_reset_halt Requesting target halt and executing a soft reset. This is often used when a target cannot be reset and halted. The target, after reset is released begins to execute code. OpenOCD attempts to stop the CPU and then sets the program counter back to the reset vector. Unfortunately the code that was executed may have left the hardware in an unknown state. @end deffn @section I/O Utilities These commands are available when OpenOCD is built with @option{--enable-ioutil}. They are mainly useful on embedded targets, notably the ZY1000. Hosts with operating systems have complementary tools. @emph{Note:} there are several more such commands. @deffn Command append_file filename [string]* Appends the @var{string} parameters to the text file @file{filename}. Each string except the last one is followed by one space. The last string is followed by a newline. @end deffn @deffn Command cat filename Reads and displays the text file @file{filename}. @end deffn @deffn Command cp src_filename dest_filename Copies contents from the file @file{src_filename} into @file{dest_filename}. @end deffn @deffn Command ip @emph{No description provided.} @end deffn @deffn Command ls @emph{No description provided.} @end deffn @deffn Command mac @emph{No description provided.} @end deffn @deffn Command meminfo Display available RAM memory on OpenOCD host. Used in OpenOCD regression testing scripts. @end deffn @deffn Command peek @emph{No description provided.} @end deffn @deffn Command poke @emph{No description provided.} @end deffn @deffn Command rm filename @c "rm" has both normal and Jim-level versions?? Unlinks the file @file{filename}. @end deffn @deffn Command trunc filename Removes all data in the file @file{filename}. @end deffn @anchor{memoryaccess} @section Memory access commands @cindex memory access These commands allow accesses of a specific size to the memory system. Often these are used to configure the current target in some special way. For example - one may need to write certain values to the SDRAM controller to enable SDRAM. @enumerate @item Use the @command{targets} (plural) command to change the current target. @item In system level scripts these commands are deprecated. Please use their TARGET object siblings to avoid making assumptions about what TAP is the current target, or about MMU configuration. @end enumerate @deffn Command mdw [phys] addr [count] @deffnx Command mdh [phys] addr [count] @deffnx Command mdb [phys] addr [count] Display contents of address @var{addr}, as 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), or 8-bit bytes (@command{mdb}). When the current target has an MMU which is present and active, @var{addr} is interpreted as a virtual address. Otherwise, or if the optional @var{phys} flag is specified, @var{addr} is interpreted as a physical address. If @var{count} is specified, displays that many units. (If you want to manipulate the data instead of displaying it, see the @code{mem2array} primitives.) @end deffn @deffn Command mww [phys] addr word @deffnx Command mwh [phys] addr halfword @deffnx Command mwb [phys] addr byte Writes the specified @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) value, at the specified address @var{addr}. When the current target has an MMU which is present and active, @var{addr} is interpreted as a virtual address. Otherwise, or if the optional @var{phys} flag is specified, @var{addr} is interpreted as a physical address. @end deffn @anchor{imageaccess} @section Image loading commands @cindex image loading @cindex image dumping @deffn Command {dump_image} filename address size Dump @var{size} bytes of target memory starting at @var{address} to the binary file named @var{filename}. @end deffn @deffn Command {fast_load} Loads an image stored in memory by @command{fast_load_image} to the current target. Must be preceeded by fast_load_image. @end deffn @deffn Command {fast_load_image} filename address [@option{bin}|@option{ihex}|@option{elf}|@option{s19}] Normally you should be using @command{load_image} or GDB load. However, for testing purposes or when I/O overhead is significant(OpenOCD running on an embedded host), storing the image in memory and uploading the image to the target can be a way to upload e.g. multiple debug sessions when the binary does not change. Arguments are the same as @command{load_image}, but the image is stored in OpenOCD host memory, i.e. does not affect target. This approach is also useful when profiling target programming performance as I/O and target programming can easily be profiled separately. @end deffn @deffn Command {load_image} filename address [[@option{bin}|@option{ihex}|@option{elf}|@option{s19}] @option{min_addr} @option{max_length}] Load image from file @var{filename} to target memory offset by @var{address} from its load address. The file format may optionally be specified (@option{bin}, @option{ihex}, @option{elf}, or @option{s19}). In addition the following arguments may be specifed: @var{min_addr} - ignore data below @var{min_addr} (this is w.r.t. to the target's load address + @var{address}) @var{max_length} - maximum number of bytes to load. @example proc load_image_bin @{fname foffset address length @} @{ # Load data from fname filename at foffset offset to # target at address. Load at most length bytes. load_image $fname [expr $address - $foffset] bin \ $address $length @} @end example @end deffn @deffn Command {test_image} filename [address [@option{bin}|@option{ihex}|@option{elf}]] Displays image section sizes and addresses as if @var{filename} were loaded into target memory starting at @var{address} (defaults to zero). The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) @end deffn @deffn Command {verify_image} filename address [@option{bin}|@option{ihex}|@option{elf}] Verify @var{filename} against target memory starting at @var{address}. The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. @end deffn @section Breakpoint and Watchpoint commands @cindex breakpoint @cindex watchpoint CPUs often make debug modules accessible through JTAG, with hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. @deffn Command {bp} [address len [@option{hw}]] With no parameters, lists all active breakpoints. Else sets a breakpoint on code execution starting at @var{address} for @var{length} bytes. This is a software breakpoint, unless @option{hw} is specified in which case it will be a hardware breakpoint. (@xref{arm9vectorcatch,,arm9 vector_catch}, or @pxref{xscalevectorcatch,,xscale vector_catch}, for similar mechanisms that do not consume hardware breakpoints.) @end deffn @deffn Command {rbp} address Remove the breakpoint at @var{address}. @end deffn @deffn Command {rwp} address Remove data watchpoint on @var{address} @end deffn @deffn Command {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]] With no parameters, lists all active watchpoints. Else sets a data watchpoint on data from @var{address} for @var{length} bytes. The watch point is an "access" watchpoint unless the @option{r} or @option{w} parameter is provided, defining it as respectively a read or write watchpoint. If a @var{value} is provided, that value is used when determining if the watchpoint should trigger. The value may be first be masked using @var{mask} to mark ``don't care'' fields. @end deffn @section Misc Commands @cindex profiling @deffn Command {profile} seconds filename [start end] Profiling samples the CPU's program counter as quickly as possible, which is useful for non-intrusive stochastic profiling. Saves up to 10000 samples in @file{filename} using ``gmon.out'' format. Optional @option{start} and @option{end} parameters allow to limit the address range. @end deffn @deffn Command {version} Displays a string identifying the version of this OpenOCD server. @end deffn @deffn Command {virt2phys} virtual_address Requests the current target to map the specified @var{virtual_address} to its corresponding physical address, and displays the result. @end deffn @node Architecture and Core Commands @chapter Architecture and Core Commands @cindex Architecture Specific Commands @cindex Core Specific Commands Most CPUs have specialized JTAG operations to support debugging. OpenOCD packages most such operations in its standard command framework. Some of those operations don't fit well in that framework, so they are exposed here as architecture or implementation (core) specific commands. @anchor{armhardwaretracing} @section ARM Hardware Tracing @cindex tracing @cindex ETM @cindex ETB CPUs based on ARM cores may include standard tracing interfaces, based on an ``Embedded Trace Module'' (ETM) which sends voluminous address and data bus trace records to a ``Trace Port''. @itemize @item Development-oriented boards will sometimes provide a high speed trace connector for collecting that data, when the particular CPU supports such an interface. (The standard connector is a 38-pin Mictor, with both JTAG and trace port support.) Those trace connectors are supported by higher end JTAG adapters and some logic analyzer modules; frequently those modules can buffer several megabytes of trace data. Configuring an ETM coupled to such an external trace port belongs in the board-specific configuration file. @item If the CPU doesn't provide an external interface, it probably has an ``Embedded Trace Buffer'' (ETB) on the chip, which is a dedicated SRAM. 4KBytes is one common ETB size. Configuring an ETM coupled only to an ETB belongs in the CPU-specific (target) configuration file, since it works the same on all boards. @end itemize ETM support in OpenOCD doesn't seem to be widely used yet. @quotation Issues ETM support may be buggy, and at least some @command{etm config} parameters should be detected by asking the ETM for them. ETM trigger events could also implement a kind of complex hardware breakpoint, much more powerful than the simple watchpoint hardware exported by EmbeddedICE modules. @emph{Such breakpoints can be triggered even when using the dummy trace port driver}. It seems like a GDB hookup should be possible, as well as tracing only during specific states (perhaps @emph{handling IRQ 23} or @emph{calls foo()}). There should be GUI tools to manipulate saved trace data and help analyse it in conjunction with the source code. It's unclear how much of a common interface is shared with the current XScale trace support, or should be shared with eventual Nexus-style trace module support. At this writing (November 2009) only ARM7, ARM9, and ARM11 support for ETM modules is available. The code should be able to work with some newer cores; but not all of them support this original style of JTAG access. @end quotation @subsection ETM Configuration ETM setup is coupled with the trace port driver configuration. @deffn {Config Command} {etm config} target width mode clocking driver Declares the ETM associated with @var{target}, and associates it with a given trace port @var{driver}. @xref{traceportdrivers,,Trace Port Drivers}. Several of the parameters must reflect the trace port capabilities, which are a function of silicon capabilties (exposed later using @command{etm info}) and of what hardware is connected to that port (such as an external pod, or ETB). The @var{width} must be either 4, 8, or 16, except with ETMv3.0 and newer modules which may also support 1, 2, 24, 32, 48, and 64 bit widths. (With those versions, @command{etm info} also shows whether the selected port width and mode are supported.) The @var{mode} must be @option{normal}, @option{multiplexed}, or @option{demultiplexed}. The @var{clocking} must be @option{half} or @option{full}. @quotation Warning With ETMv3.0 and newer, the bits set with the @var{mode} and @var{clocking} parameters both control the mode. This modified mode does not map to the values supported by previous ETM modules, so this syntax is subject to change. @end quotation @quotation Note You can see the ETM registers using the @command{reg} command. Not all possible registers are present in every ETM. Most of the registers are write-only, and are used to configure what CPU activities are traced. @end quotation @end deffn @deffn Command {etm info} Displays information about the current target's ETM. This includes resource counts from the @code{ETM_CONFIG} register, as well as silicon capabilities (except on rather old modules). from the @code{ETM_SYS_CONFIG} register. @end deffn @deffn Command {etm status} Displays status of the current target's ETM and trace port driver: is the ETM idle, or is it collecting data? Did trace data overflow? Was it triggered? @end deffn @deffn Command {etm tracemode} [type context_id_bits cycle_accurate branch_output] Displays what data that ETM will collect. If arguments are provided, first configures that data. When the configuration changes, tracing is stopped and any buffered trace data is invalidated. @itemize @item @var{type} ... describing how data accesses are traced, when they pass any ViewData filtering that that was set up. The value is one of @option{none} (save nothing), @option{data} (save data), @option{address} (save addresses), @option{all} (save data and addresses) @item @var{context_id_bits} ... 0, 8, 16, or 32 @item @var{cycle_accurate} ... @option{enable} or @option{disable} cycle-accurate instruction tracing. Before ETMv3, enabling this causes much extra data to be recorded. @item @var{branch_output} ... @option{enable} or @option{disable}. Disable this unless you need to try reconstructing the instruction trace stream without an image of the code. @end itemize @end deffn @deffn Command {etm trigger_debug} (@option{enable}|@option{disable}) Displays whether ETM triggering debug entry (like a breakpoint) is enabled or disabled, after optionally modifying that configuration. The default behaviour is @option{disable}. Any change takes effect after the next @command{etm start}. By using script commands to configure ETM registers, you can make the processor enter debug state automatically when certain conditions, more complex than supported by the breakpoint hardware, happen. @end deffn @subsection ETM Trace Operation After setting up the ETM, you can use it to collect data. That data can be exported to files for later analysis. It can also be parsed with OpenOCD, for basic sanity checking. To configure what is being traced, you will need to write various trace registers using @command{reg ETM_*} commands. For the definitions of these registers, read ARM publication @emph{IHI 0014, ``Embedded Trace Macrocell, Architecture Specification''}. Be aware that most of the relevant registers are write-only, and that ETM resources are limited. There are only a handful of address comparators, data comparators, counters, and so on. Examples of scenarios you might arrange to trace include: @itemize @item Code flow within a function, @emph{excluding} subroutines it calls. Use address range comparators to enable tracing for instruction access within that function's body. @item Code flow within a function, @emph{including} subroutines it calls. Use the sequencer and address comparators to activate tracing on an ``entered function'' state, then deactivate it by exiting that state when the function's exit code is invoked. @item Code flow starting at the fifth invocation of a function, combining one of the above models with a counter. @item CPU data accesses to the registers for a particular device, using address range comparators and the ViewData logic. @item Such data accesses only during IRQ handling, combining the above model with sequencer triggers which on entry and exit to the IRQ handler. @item @emph{... more} @end itemize At this writing, September 2009, there are no Tcl utility procedures to help set up any common tracing scenarios. @deffn Command {etm analyze} Reads trace data into memory, if it wasn't already present. Decodes and prints the data that was collected. @end deffn @deffn Command {etm dump} filename Stores the captured trace data in @file{filename}. @end deffn @deffn Command {etm image} filename [base_address] [type] Opens an image file. @end deffn @deffn Command {etm load} filename Loads captured trace data from @file{filename}. @end deffn @deffn Command {etm start} Starts trace data collection. @end deffn @deffn Command {etm stop} Stops trace data collection. @end deffn @anchor{traceportdrivers} @subsection Trace Port Drivers To use an ETM trace port it must be associated with a driver. @deffn {Trace Port Driver} dummy Use the @option{dummy} driver if you are configuring an ETM that's not connected to anything (on-chip ETB or off-chip trace connector). @emph{This driver lets OpenOCD talk to the ETM, but it does not expose any trace data collection.} @deffn {Config Command} {etm_dummy config} target Associates the ETM for @var{target} with a dummy driver. @end deffn @end deffn @deffn {Trace Port Driver} etb Use the @option{etb} driver if you are configuring an ETM to use on-chip ETB memory. @deffn {Config Command} {etb config} target etb_tap Associates the ETM for @var{target} with the ETB at @var{etb_tap}. You can see the ETB registers using the @command{reg} command. @end deffn @deffn Command {etb trigger_percent} [percent] This displays, or optionally changes, ETB behavior after the ETM's configured @emph{trigger} event fires. It controls how much more trace data is saved after the (single) trace trigger becomes active. @itemize @item The default corresponds to @emph{trace around} usage, recording 50 percent data before the event and the rest afterwards. @item The minimum value of @var{percent} is 2 percent, recording almost exclusively data before the trigger. Such extreme @emph{trace before} usage can help figure out what caused that event to happen. @item The maximum value of @var{percent} is 100 percent, recording data almost exclusively after the event. This extreme @emph{trace after} usage might help sort out how the event caused trouble. @end itemize @c REVISIT allow "break" too -- enter debug mode. @end deffn @end deffn @deffn {Trace Port Driver} oocd_trace This driver isn't available unless OpenOCD was explicitly configured with the @option{--enable-oocd_trace} option. You probably don't want to configure it unless you've built the appropriate prototype hardware; it's @emph{proof-of-concept} software. Use the @option{oocd_trace} driver if you are configuring an ETM that's connected to an off-chip trace connector. @deffn {Config Command} {oocd_trace config} target tty Associates the ETM for @var{target} with a trace driver which collects data through the serial port @var{tty}. @end deffn @deffn Command {oocd_trace resync} Re-synchronizes with the capture clock. @end deffn @deffn Command {oocd_trace status} Reports whether the capture clock is locked or not. @end deffn @end deffn @section Generic ARM @cindex ARM These commands should be available on all ARM processors. They are available in addition to other core-specific commands that may be available. @deffn Command {arm core_state} [@option{arm}|@option{thumb}] Displays the core_state, optionally changing it to process either @option{arm} or @option{thumb} instructions. The target may later be resumed in the currently set core_state. (Processors may also support the Jazelle state, but that is not currently supported in OpenOCD.) @end deffn @deffn Command {arm disassemble} address [count [@option{thumb}]] @cindex disassemble Disassembles @var{count} instructions starting at @var{address}. If @var{count} is not specified, a single instruction is disassembled. If @option{thumb} is specified, or the low bit of the address is set, Thumb2 (mixed 16/32-bit) instructions are used; else ARM (32-bit) instructions are used. (Processors may also support the Jazelle state, but those instructions are not currently understood by OpenOCD.) Note that all Thumb instructions are Thumb2 instructions, so older processors (without Thumb2 support) will still see correct disassembly of Thumb code. Also, ThumbEE opcodes are the same as Thumb2, with a handful of exceptions. ThumbEE disassembly currently has no explicit support. @end deffn @deffn Command {arm mcr} pX op1 CRn CRm op2 value Write @var{value} to a coprocessor @var{pX} register passing parameters @var{CRn}, @var{CRm}, opcodes @var{opc1} and @var{opc2}, and using the MCR instruction. (Parameter sequence matches the ARM instruction, but omits an ARM register.) @end deffn @deffn Command {arm mrc} pX coproc op1 CRn CRm op2 Read a coprocessor @var{pX} register passing parameters @var{CRn}, @var{CRm}, opcodes @var{opc1} and @var{opc2}, and the MRC instruction. Returns the result so it can be manipulated by Jim scripts. (Parameter sequence matches the ARM instruction, but omits an ARM register.) @end deffn @deffn Command {arm reg} Display a table of all banked core registers, fetching the current value from every core mode if necessary. @end deffn @deffn Command {arm semihosting} [@option{enable}|@option{disable}] @cindex ARM semihosting Display status of semihosting, after optionally changing that status. Semihosting allows for code executing on an ARM target to use the I/O facilities on the host computer i.e. the system where OpenOCD is running. The target application must be linked against a library implementing the ARM semihosting convention that forwards operation requests by using a special SVC instruction that is trapped at the Supervisor Call vector by OpenOCD. @end deffn @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 The ARMv4 and ARMv5 architectures are widely used in embedded systems, and introduced core parts of the instruction set in use today. That includes the Thumb instruction set, introduced in the ARMv4T variant. @subsection ARM7 and ARM9 specific commands @cindex ARM7 @cindex ARM9 These commands are specific to ARM7 and ARM9 cores, like ARM7TDMI, ARM720T, ARM9TDMI, ARM920T or ARM926EJ-S. They are available in addition to the ARM commands, and any other core-specific commands that may be available. @deffn Command {arm7_9 dbgrq} [@option{enable}|@option{disable}] Displays the value of the flag controlling use of the the EmbeddedIce DBGRQ signal to force entry into debug mode, instead of breakpoints. If a boolean parameter is provided, first assigns that flag. This should be safe for all but ARM7TDMI-S cores (like NXP LPC). This feature is enabled by default on most ARM9 cores, including ARM9TDMI, ARM920T, and ARM926EJ-S. @end deffn @deffn Command {arm7_9 dcc_downloads} [@option{enable}|@option{disable}] @cindex DCC Displays the value of the flag controlling use of the debug communications channel (DCC) to write larger (>128 byte) amounts of memory. If a boolean parameter is provided, first assigns that flag. DCC downloads offer a huge speed increase, but might be unsafe, especially with targets running at very low speeds. This command was introduced with OpenOCD rev. 60, and requires a few bytes of working area. @end deffn @deffn Command {arm7_9 fast_memory_access} [@option{enable}|@option{disable}] Displays the value of the flag controlling use of memory writes and reads that don't check completion of the operation. If a boolean parameter is provided, first assigns that flag. This provides a huge speed increase, especially with USB JTAG cables (FT2232), but might be unsafe if used with targets running at very low speeds, like the 32kHz startup clock of an AT91RM9200. @end deffn @subsection ARM720T specific commands @cindex ARM720T These commands are available to ARM720T based CPUs, which are implementations of the ARMv4T architecture based on the ARM7TDMI-S integer core. They are available in addition to the ARM and ARM7/ARM9 commands. @deffn Command {arm720t cp15} opcode [value] @emph{DEPRECATED -- avoid using this. Use the @command{arm mrc} or @command{arm mcr} commands instead.} Display cp15 register returned by the ARM instruction @var{opcode}; else if a @var{value} is provided, that value is written to that register. The @var{opcode} should be the value of either an MRC or MCR instruction. @end deffn @subsection ARM9 specific commands @cindex ARM9 ARM9-family cores are built around ARM9TDMI or ARM9E (including ARM9EJS) integer processors. Such cores include the ARM920T, ARM926EJ-S, and ARM966. @c 9-june-2009: tried this on arm920t, it didn't work. @c no-params always lists nothing caught, and that's how it acts. @c 23-oct-2009: doesn't work _consistently_ ... as if the ICE @c versions have different rules about when they commit writes. @anchor{arm9vectorcatch} @deffn Command {arm9 vector_catch} [@option{all}|@option{none}|list] @cindex vector_catch Vector Catch hardware provides a sort of dedicated breakpoint for hardware events such as reset, interrupt, and abort. You can use this to conserve normal breakpoint resources, so long as you're not concerned with code that branches directly to those hardware vectors. This always finishes by listing the current configuration. If parameters are provided, it first reconfigures the vector catch hardware to intercept @option{all} of the hardware vectors, @option{none} of them, or a list with one or more of the following: @option{reset} @option{undef} @option{swi} @option{pabt} @option{dabt} @option{irq} @option{fiq}. @end deffn @subsection ARM920T specific commands @cindex ARM920T These commands are available to ARM920T based CPUs, which are implementations of the ARMv4T architecture built using the ARM9TDMI integer core. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. @deffn Command {arm920t cache_info} Print information about the caches found. This allows to see whether your target is an ARM920T (2x16kByte cache) or ARM922T (2x8kByte cache). @end deffn @deffn Command {arm920t cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. This uses "physical access" and the register number is as shown in bits 38..33 of table 9-9 in the ARM920T TRM. (Not all registers can be written.) @end deffn @deffn Command {arm920t cp15i} opcode [value [address]] @emph{DEPRECATED -- avoid using this. Use the @command{arm mrc} or @command{arm mcr} commands instead.} Interpreted access using ARM instruction @var{opcode}, which should be the value of either an MRC or MCR instruction (as shown tables 9-11, 9-12, and 9-13 in the ARM920T TRM). If no @var{value} is provided, the result is displayed. Else if that value is written using the specified @var{address}, or using zero if no other address is provided. @end deffn @deffn Command {arm920t read_cache} filename Dump the content of ICache and DCache to a file named @file{filename}. @end deffn @deffn Command {arm920t read_mmu} filename Dump the content of the ITLB and DTLB to a file named @file{filename}. @end deffn @subsection ARM926ej-s specific commands @cindex ARM926ej-s These commands are available to ARM926ej-s based CPUs, which are implementations of the ARMv5TEJ architecture based on the ARM9EJ-S integer core. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. The Feroceon cores also support these commands, although they are not built from ARM926ej-s designs. @deffn Command {arm926ejs cache_info} Print information about the caches found. @end deffn @subsection ARM966E specific commands @cindex ARM966E These commands are available to ARM966 based CPUs, which are implementations of the ARMv5TE architecture. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. @deffn Command {arm966e cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. The six bit @var{regnum} values are bits 37..32 from table 7-2 of the ARM966E-S TRM. There is no current control over bits 31..30 from that table, as required for BIST support. @end deffn @subsection XScale specific commands @cindex XScale Some notes about the debug implementation on the XScale CPUs: The XScale CPU provides a special debug-only mini-instruction cache (mini-IC) in which exception vectors and target-resident debug handler code are placed by OpenOCD. In order to get access to the CPU, OpenOCD must point vector 0 (the reset vector) to the entry of the debug handler. However, this means that the complete first cacheline in the mini-IC is marked valid, which makes the CPU fetch all exception handlers from the mini-IC, ignoring the code in RAM. To address this situation, OpenOCD provides the @code{xscale vector_table} command, which allows the user to explicity write individual entries to either the high or low vector table stored in the mini-IC. It is recommended to place a pc-relative indirect branch in the vector table, and put the branch destination somewhere in memory. Doing so makes sure the code in the vector table stays constant regardless of code layout in memory: @example _vectors: ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] ldr pc,[pc,#0x100-8] .org 0x100 .long real_reset_vector .long real_ui_handler .long real_swi_handler .long real_pf_abort .long real_data_abort .long 0 /* unused */ .long real_irq_handler .long real_fiq_handler @end example Alternatively, you may choose to keep some or all of the mini-IC vector table entries synced with those written to memory by your system software. The mini-IC can not be modified while the processor is executing, but for each vector table entry not previously defined using the @code{xscale vector_table} command, OpenOCD will copy the value from memory to the mini-IC every time execution resumes from a halt. This is done for both high and low vector tables (although the table not in use may not be mapped to valid memory, and in this case that copy operation will silently fail). This means that you will need to briefly halt execution at some strategic point during system start-up; e.g., after the software has initialized the vector table, but before exceptions are enabled. A breakpoint can be used to accomplish this once the appropriate location in the start-up code has been identified. A watchpoint over the vector table region is helpful in finding the location if you're not sure. Note that the same situation exists any time the vector table is modified by the system software. The debug handler must be placed somewhere in the address space using the @code{xscale debug_handler} command. The allowed locations for the debug handler are either (0x800 - 0x1fef800) or (0xfe000800 - 0xfffff800). The default value is 0xfe000800. XScale has resources to support two hardware breakpoints and two watchpoints. However, the following restrictions on watchpoint functionality apply: (1) the value and mask arguments to the @code{wp} command are not supported, (2) the watchpoint length must be a power of two and not less than four, and can not be greater than the watchpoint address, and (3) a watchpoint with a length greater than four consumes all the watchpoint hardware resources. This means that at any one time, you can have enabled either two watchpoints with a length of four, or one watchpoint with a length greater than four. These commands are available to XScale based CPUs, which are implementations of the ARMv5TE architecture. @deffn Command {xscale analyze_trace} Displays the contents of the trace buffer. @end deffn @deffn Command {xscale cache_clean_address} address Changes the address used when cleaning the data cache. @end deffn @deffn Command {xscale cache_info} Displays information about the CPU caches. @end deffn @deffn Command {xscale cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. @end deffn @deffn Command {xscale debug_handler} target address Changes the address used for the specified target's debug handler. @end deffn @deffn Command {xscale dcache} [@option{enable}|@option{disable}] Enables or disable the CPU's data cache. @end deffn @deffn Command {xscale dump_trace} filename Dumps the raw contents of the trace buffer to @file{filename}. @end deffn @deffn Command {xscale icache} [@option{enable}|@option{disable}] Enables or disable the CPU's instruction cache. @end deffn @deffn Command {xscale mmu} [@option{enable}|@option{disable}] Enables or disable the CPU's memory management unit. @end deffn @deffn Command {xscale trace_buffer} [@option{enable}|@option{disable} [@option{fill} [n] | @option{wrap}]] Displays the trace buffer status, after optionally enabling or disabling the trace buffer and modifying how it is emptied. @end deffn @deffn Command {xscale trace_image} filename [offset [type]] Opens a trace image from @file{filename}, optionally rebasing its segment addresses by @var{offset}. The image @var{type} may be one of @option{bin} (binary), @option{ihex} (Intel hex), @option{elf} (ELF file), @option{s19} (Motorola s19), @option{mem}, or @option{builder}. @end deffn @anchor{xscalevectorcatch} @deffn Command {xscale vector_catch} [mask] @cindex vector_catch Display a bitmask showing the hardware vectors to catch. If the optional parameter is provided, first set the bitmask to that value. The mask bits correspond with bit 16..23 in the DCSR: @example 0x01 Trap Reset 0x02 Trap Undefined Instructions 0x04 Trap Software Interrupt 0x08 Trap Prefetch Abort 0x10 Trap Data Abort 0x20 reserved 0x40 Trap IRQ 0x80 Trap FIQ @end example @end deffn @deffn Command {xscale vector_table} [(@option{low}|@option{high}) index value] @cindex vector_table Set an entry in the mini-IC vector table. There are two tables: one for low vectors (at 0x00000000), and one for high vectors (0xFFFF0000), each holding the 8 exception vectors. @var{index} can be 1-7, because vector 0 points to the debug handler entry and can not be overwritten. @var{value} holds the 32-bit opcode that is placed in the mini-IC. Without arguments, the current settings are displayed. @end deffn @section ARMv6 Architecture @cindex ARMv6 @subsection ARM11 specific commands @cindex ARM11 @deffn Command {arm11 memwrite burst} [@option{enable}|@option{disable}] Displays the value of the memwrite burst-enable flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. Burst writes are only used for memory writes larger than 1 word. They improve performance by assuming that the CPU has read each data word over JTAG and completed its write before the next word arrives, instead of polling for a status flag to verify that completion. This is usually safe, because JTAG runs much slower than the CPU. @end deffn @deffn Command {arm11 memwrite error_fatal} [@option{enable}|@option{disable}] Displays the value of the memwrite error_fatal flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. When set, certain memory write errors cause earlier transfer termination. @end deffn @deffn Command {arm11 step_irq_enable} [@option{enable}|@option{disable}] Displays the value of the flag controlling whether IRQs are enabled during single stepping; they are disabled by default. If a boolean parameter is provided, first assigns that. @end deffn @deffn Command {arm11 vcr} [value] @cindex vector_catch Displays the value of the @emph{Vector Catch Register (VCR)}, coprocessor 14 register 7. If @var{value} is defined, first assigns that. Vector Catch hardware provides dedicated breakpoints for certain hardware events. The specific bit values are core-specific (as in fact is using coprocessor 14 register 7 itself) but all current ARM11 cores @emph{except the ARM1176} use the same six bits. @end deffn @section ARMv7 Architecture @cindex ARMv7 @subsection ARMv7 Debug Access Port (DAP) specific commands @cindex Debug Access Port @cindex DAP These commands are specific to ARM architecture v7 Debug Access Port (DAP), included on Cortex-M and Cortex-A systems. They are available in addition to other core-specific commands that may be available. @deffn Command {dap apid} [num] Displays ID register from AP @var{num}, defaulting to the currently selected AP. @end deffn @deffn Command {dap apsel} [num] Select AP @var{num}, defaulting to 0. @end deffn @deffn Command {dap baseaddr} [num] Displays debug base address from MEM-AP @var{num}, defaulting to the currently selected AP. @end deffn @deffn Command {dap info} [num] Displays the ROM table for MEM-AP @var{num}, defaulting to the currently selected AP. @end deffn @deffn Command {dap memaccess} [value] Displays the number of extra tck cycles in the JTAG idle to use for MEM-AP memory bus access [0-255], giving additional time to respond to reads. If @var{value} is defined, first assigns that. @end deffn @deffn Command {dap apcsw} [0 / 1] fix CSW_SPROT from register AP_REG_CSW on selected dap. Defaulting to 0. @end deffn @subsection ARMv7-M specific commands @cindex tracing @cindex SWO @cindex SWV @cindex TPIU @cindex ITM @cindex ETM @deffn Command {tpiu config} (@option{disable} | ((@option{external} | @option{internal @var{filename}}) @ (@option{sync @var{port_width}} | ((@option{manchester} | @option{uart}) @var{formatter_enable})) @ @var{TRACECLKIN_freq} [@var{trace_freq}])) ARMv7-M architecture provides several modules to generate debugging information internally (ITM, DWT and ETM). Their output is directed through TPIU to be captured externally either on an SWO pin (this configuration is called SWV) or on a synchronous parallel trace port. This command configures the TPIU module of the target and, if internal capture mode is selected, starts to capture trace output by using the debugger adapter features. Some targets require additional actions to be performed in the @b{trace-config} handler for trace port to be activated. Command options: @itemize @minus @item @option{disable} disable TPIU handling; @item @option{external} configure TPIU to let user capture trace output externally (with an additional UART or logic analyzer hardware); @item @option{internal @var{filename}} configure TPIU and debug adapter to gather trace data and append it to @var{filename} (which can be either a regular file or a named pipe); @item @option{sync @var{port_width}} use synchronous parallel trace output mode, and set port width to @var{port_width}; @item @option{manchester} use asynchronous SWO mode with Manchester coding; @item @option{uart} use asynchronous SWO mode with NRZ (same as regular UART 8N1) coding; @item @var{formatter_enable} is @option{on} or @option{off} to enable or disable TPIU formatter which needs to be used when both ITM and ETM data is to be output via SWO; @item @var{TRACECLKIN_freq} this should be specified to match target's current TRACECLKIN frequency (usually the same as HCLK); @item @var{trace_freq} trace port frequency. Can be omitted in internal mode to let the adapter driver select the maximum supported rate automatically. @end itemize Example usage: @enumerate @item STM32L152 board is programmed with an application that configures PLL to provide core clock with 24MHz frequency; to use ITM output it's enough to: @example #include ... ITM_STIM8(0) = c; ... @end example (the most obvious way is to use the first stimulus port for printf, for that this ITM_STIM8 assignment can be used inside _write(); to make it blocking to avoid data loss, add @code{while (!(ITM_STIM8(0) & ITM_STIM_FIFOREADY));}); @item An FT2232H UART is connected to the SWO pin of the board; @item Commands to configure UART for 12MHz baud rate: @example $ setserial /dev/ttyUSB1 spd_cust divisor 5 $ stty -F /dev/ttyUSB1 38400 @end example (FT2232H's base frequency is 60MHz, spd_cust allows to alias 38400 baud with our custom divisor to get 12MHz) @item @code{itmdump -f /dev/ttyUSB1 -d1} @item OpenOCD invocation line: @example openocd -f interface/stlink-v2-1.cfg \ -c "transport select hla_swd" \ -f target/stm32l1.cfg \ -c "tpiu config external uart off 24000000 12000000" @end example @end enumerate @end deffn @deffn Command {itm port} @var{port} (@option{0}|@option{1}|@option{on}|@option{off}) Enable or disable trace output for ITM stimulus @var{port} (counting from 0). Port 0 is enabled on target creation automatically. @end deffn @deffn Command {itm ports} (@option{0}|@option{1}|@option{on}|@option{off}) Enable or disable trace output for all ITM stimulus ports. @end deffn @subsection Cortex-M specific commands @cindex Cortex-M @deffn Command {cortex_m maskisr} (@option{auto}|@option{on}|@option{off}) Control masking (disabling) interrupts during target step/resume. The @option{auto} option handles interrupts during stepping a way they get served but don't disturb the program flow. The step command first allows pending interrupt handlers to execute, then disables interrupts and steps over the next instruction where the core was halted. After the step interrupts are enabled again. If the interrupt handlers don't complete within 500ms, the step command leaves with the core running. Note that a free breakpoint is required for the @option{auto} option. If no breakpoint is available at the time of the step, then the step is taken with interrupts enabled, i.e. the same way the @option{off} option does. Default is @option{auto}. @end deffn @deffn Command {cortex_m vector_catch} [@option{all}|@option{none}|list] @cindex vector_catch Vector Catch hardware provides dedicated breakpoints for certain hardware events. Parameters request interception of @option{all} of these hardware event vectors, @option{none} of them, or one or more of the following: @option{hard_err} for a HardFault exception; @option{mm_err} for a MemManage exception; @option{bus_err} for a BusFault exception; @option{irq_err}, @option{state_err}, @option{chk_err}, or @option{nocp_err} for various UsageFault exceptions; or @option{reset}. If NVIC setup code does not enable them, MemManage, BusFault, and UsageFault exceptions are mapped to HardFault. UsageFault checks for divide-by-zero and unaligned access must also be explicitly enabled. This finishes by listing the current vector catch configuration. @end deffn @deffn Command {cortex_m reset_config} (@option{srst}|@option{sysresetreq}|@option{vectreset}) Control reset handling. The default @option{srst} is to use srst if fitted, otherwise fallback to @option{vectreset}. @itemize @minus @item @option{srst} use hardware srst if fitted otherwise fallback to @option{vectreset}. @item @option{sysresetreq} use NVIC SYSRESETREQ to reset system. @item @option{vectreset} use NVIC VECTRESET to reset system. @end itemize Using @option{vectreset} is a safe option for all current Cortex-M cores. This however has the disadvantage of only resetting the core, all peripherals are uneffected. A solution would be to use a @code{reset-init} event handler to manually reset the peripherals. @xref{targetevents,,Target Events}. @end deffn @section Intel Architecture Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32 (Pentium x86 ISA) compatible SoC. The core CPU in the X10xx is codenamed Lakemont. Lakemont version 1 (LMT1) is used in X10xx. The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is used for SoC level operations. Useful docs are here: https://communities.intel.com/community/makers/documentation @itemize @item Intel Quark SoC X1000 OpenOCD/GDB/Eclipse App Note (web search for doc num 330015) @item Intel Quark SoC X1000 Debug Operations User Guide (web search for doc num 329866) @item Intel Quark SoC X1000 Datasheet (web search for doc num 329676) @end itemize @subsection x86 32-bit specific commands The three main address spaces for x86 are memory, I/O and configuration space. These commands allow a user to read and write to the 64Kbyte I/O address space. @deffn Command {x86_32 idw} address Display the contents of a 32-bit I/O port from address range 0x0000 - 0xffff. @end deffn @deffn Command {x86_32 idh} address Display the contents of a 16-bit I/O port from address range 0x0000 - 0xffff. @end deffn @deffn Command {x86_32 idb} address Display the contents of a 8-bit I/O port from address range 0x0000 - 0xffff. @end deffn @deffn Command {x86_32 iww} address Write the contents of a 32-bit I/O port to address range 0x0000 - 0xffff. @end deffn @deffn Command {x86_32 iwh} address Write the contents of a 16-bit I/O port to address range 0x0000 - 0xffff. @end deffn @deffn Command {x86_32 iwb} address Write the contents of a 8-bit I/O port to address range 0x0000 - 0xffff. @end deffn @section OpenRISC Architecture The OpenRISC CPU is a soft core. It is used in a programmable SoC which can be configured with any of the TAP / Debug Unit available. @subsection TAP and Debug Unit selection commands @deffn Command {tap_select} (@option{vjtag}|@option{mohor}|@option{xilinx_bscan}) Select between the Altera Virtual JTAG , Xilinx Virtual JTAG and Mohor TAP. @end deffn @deffn Command {du_select} (@option{adv}|@option{mohor}) [option] Select between the Advanced Debug Interface and the classic one. An option can be passed as a second argument to the debug unit. When using the Advanced Debug Interface, option = 1 means the RTL core is configured with ADBG_USE_HISPEED = 1. This configuration skips status checking between bytes while doing read or write bursts. @end deffn @subsection Registers commands @deffn Command {addreg} [name] [address] [feature] [reg_group] Add a new register in the cpu register list. This register will be included in the generated target descriptor file. @strong{[feature]} must be "org.gnu.gdb.or1k.group[0..10]". @strong{[reg_group]} can be anything. The default register list defines "system", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf", "power", "pic" and "timer" groups. @emph{example:} @example addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system @end example @end deffn @deffn Command {readgroup} (@option{group}) Display all registers in @emph{group}. @emph{group} can be "system", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf", "power", "pic", "timer" or any new group created with addreg command. @end deffn @anchor{softwaredebugmessagesandtracing} @section Software Debug Messages and Tracing @cindex Linux-ARM DCC support @cindex tracing @cindex libdcc @cindex DCC OpenOCD can process certain requests from target software, when the target uses appropriate libraries. The most powerful mechanism is semihosting, but there is also a lighter weight mechanism using only the DCC channel. Currently @command{target_request debugmsgs} is supported only for @option{arm7_9} and @option{cortex_m} cores. These messages are received as part of target polling, so you need to have @command{poll on} active to receive them. They are intrusive in that they will affect program execution times. If that is a problem, @pxref{armhardwaretracing,,ARM Hardware Tracing}. See @file{libdcc} in the contrib dir for more details. In addition to sending strings, characters, and arrays of various size integers from the target, @file{libdcc} also exports a software trace point mechanism. The target being debugged may issue trace messages which include a 24-bit @dfn{trace point} number. Trace point support includes two distinct mechanisms, each supported by a command: @itemize @item @emph{History} ... A circular buffer of trace points can be set up, and then displayed at any time. This tracks where code has been, which can be invaluable in finding out how some fault was triggered. The buffer may overflow, since it collects records continuously. It may be useful to use some of the 24 bits to represent a particular event, and other bits to hold data. @item @emph{Counting} ... An array of counters can be set up, and then displayed at any time. This can help establish code coverage and identify hot spots. The array of counters is directly indexed by the trace point number, so trace points with higher numbers are not counted. @end itemize Linux-ARM kernels have a ``Kernel low-level debugging via EmbeddedICE DCC channel'' option (CONFIG_DEBUG_ICEDCC, depends on CONFIG_DEBUG_LL) which uses this mechanism to deliver messages before a serial console can be activated. This is not the same format used by @file{libdcc}. Other software, such as the U-Boot boot loader, sometimes does the same thing. @deffn Command {target_request debugmsgs} [@option{enable}|@option{disable}|@option{charmsg}] Displays current handling of target DCC message requests. These messages may be sent to the debugger while the target is running. The optional @option{enable} and @option{charmsg} parameters both enable the messages, while @option{disable} disables them. With @option{charmsg} the DCC words each contain one character, as used by Linux with CONFIG_DEBUG_ICEDCC; otherwise the libdcc format is used. @end deffn @deffn Command {trace history} [@option{clear}|count] With no parameter, displays all the trace points that have triggered in the order they triggered. With the parameter @option{clear}, erases all current trace history records. With a @var{count} parameter, allocates space for that many history records. @end deffn @deffn Command {trace point} [@option{clear}|identifier] With no parameter, displays all trace point identifiers and how many times they have been triggered. With the parameter @option{clear}, erases all current trace point counters. With a numeric @var{identifier} parameter, creates a new a trace point counter and associates it with that identifier. @emph{Important:} The identifier and the trace point number are not related except by this command. These trace point numbers always start at zero (from server startup, or after @command{trace point clear}) and count up from there. @end deffn @node JTAG Commands @chapter JTAG Commands @cindex JTAG Commands Most general purpose JTAG commands have been presented earlier. (@xref{jtagspeed,,JTAG Speed}, @ref{Reset Configuration}, and @ref{TAP Declaration}.) Lower level JTAG commands, as presented here, may be needed to work with targets which require special attention during operations such as reset or initialization. To use these commands you will need to understand some of the basics of JTAG, including: @itemize @bullet @item A JTAG scan chain consists of a sequence of individual TAP devices such as a CPUs. @item Control operations involve moving each TAP through the same standard state machine (in parallel) using their shared TMS and clock signals. @item Data transfer involves shifting data through the chain of instruction or data registers of each TAP, writing new register values while the reading previous ones. @item Data register sizes are a function of the instruction active in a given TAP, while instruction register sizes are fixed for each TAP. All TAPs support a BYPASS instruction with a single bit data register. @item The way OpenOCD differentiates between TAP devices is by shifting different instructions into (and out of) their instruction registers. @end itemize @section Low Level JTAG Commands These commands are used by developers who need to access JTAG instruction or data registers, possibly controlling the order of TAP state transitions. If you're not debugging OpenOCD internals, or bringing up a new JTAG adapter or a new type of TAP device (like a CPU or JTAG router), you probably won't need to use these commands. In a debug session that doesn't use JTAG for its transport protocol, these commands are not available. @deffn Command {drscan} tap [numbits value]+ [@option{-endstate} tap_state] Loads the data register of @var{tap} with a series of bit fields that specify the entire register. Each field is @var{numbits} bits long with a numeric @var{value} (hexadecimal encouraged). The return value holds the original value of each of those fields. For example, a 38 bit number might be specified as one field of 32 bits then one of 6 bits. @emph{For portability, never pass fields which are more than 32 bits long. Many OpenOCD implementations do not support 64-bit (or larger) integer values.} All TAPs other than @var{tap} must be in BYPASS mode. The single bit in their data registers does not matter. When @var{tap_state} is specified, the JTAG state machine is left in that state. For example @sc{drpause} might be specified, so that more instructions can be issued before re-entering the @sc{run/idle} state. If the end state is not specified, the @sc{run/idle} state is entered. @quotation Warning OpenOCD does not record information about data register lengths, so @emph{it is important that you get the bit field lengths right}. Remember that different JTAG instructions refer to different data registers, which may have different lengths. Moreover, those lengths may not be fixed; the SCAN_N instruction can change the length of the register accessed by the INTEST instruction (by connecting a different scan chain). @end quotation @end deffn @deffn Command {flush_count} Returns the number of times the JTAG queue has been flushed. This may be used for performance tuning. For example, flushing a queue over USB involves a minimum latency, often several milliseconds, which does not change with the amount of data which is written. You may be able to identify performance problems by finding tasks which waste bandwidth by flushing small transfers too often, instead of batching them into larger operations. @end deffn @deffn Command {irscan} [tap instruction]+ [@option{-endstate} tap_state] For each @var{tap} listed, loads the instruction register with its associated numeric @var{instruction}. (The number of bits in that instruction may be displayed using the @command{scan_chain} command.) For other TAPs, a BYPASS instruction is loaded. When @var{tap_state} is specified, the JTAG state machine is left in that state. For example @sc{irpause} might be specified, so the data register can be loaded before re-entering the @sc{run/idle} state. If the end state is not specified, the @sc{run/idle} state is entered. @quotation Note OpenOCD currently supports only a single field for instruction register values, unlike data register values. For TAPs where the instruction register length is more than 32 bits, portable scripts currently must issue only BYPASS instructions. @end quotation @end deffn @deffn Command {jtag_reset} trst srst Set values of reset signals. The @var{trst} and @var{srst} parameter values may be @option{0}, indicating that reset is inactive (pulled or driven high), or @option{1}, indicating it is active (pulled or driven low). The @command{reset_config} command should already have been used to configure how the board and JTAG adapter treat these two signals, and to say if either signal is even present. @xref{Reset Configuration}. Note that TRST is specially handled. It actually signifies JTAG's @sc{reset} state. So if the board doesn't support the optional TRST signal, or it doesn't support it along with the specified SRST value, JTAG reset is triggered with TMS and TCK signals instead of the TRST signal. And no matter how that JTAG reset is triggered, once the scan chain enters @sc{reset} with TRST inactive, TAP @code{post-reset} events are delivered to all TAPs with handlers for that event. @end deffn @deffn Command {pathmove} start_state [next_state ...] Start by moving to @var{start_state}, which must be one of the @emph{stable} states. Unless it is the only state given, this will often be the current state, so that no TCK transitions are needed. Then, in a series of single state transitions (conforming to the JTAG state machine) shift to each @var{next_state} in sequence, one per TCK cycle. The final state must also be stable. @end deffn @deffn Command {runtest} @var{num_cycles} Move to the @sc{run/idle} state, and execute at least @var{num_cycles} of the JTAG clock (TCK). Instructions often need some time to execute before they take effect. @end deffn @c tms_sequence (short|long) @c ... temporary, debug-only, other than USBprog bug workaround... @deffn Command {verify_ircapture} (@option{enable}|@option{disable}) Verify values captured during @sc{ircapture} and returned during IR scans. Default is enabled, but this can be overridden by @command{verify_jtag}. This flag is ignored when validating JTAG chain configuration. @end deffn @deffn Command {verify_jtag} (@option{enable}|@option{disable}) Enables verification of DR and IR scans, to help detect programming errors. For IR scans, @command{verify_ircapture} must also be enabled. Default is enabled. @end deffn @section TAP state names @cindex TAP state names The @var{tap_state} names used by OpenOCD in the @command{drscan}, @command{irscan}, and @command{pathmove} commands are the same as those used in SVF boundary scan documents, except that SVF uses @sc{idle} instead of @sc{run/idle}. @itemize @bullet @item @b{RESET} ... @emph{stable} (with TMS high); acts as if TRST were pulsed @item @b{RUN/IDLE} ... @emph{stable}; don't assume this always means IDLE @item @b{DRSELECT} @item @b{DRCAPTURE} @item @b{DRSHIFT} ... @emph{stable}; TDI/TDO shifting through the data register @item @b{DREXIT1} @item @b{DRPAUSE} ... @emph{stable}; data register ready for update or more shifting @item @b{DREXIT2} @item @b{DRUPDATE} @item @b{IRSELECT} @item @b{IRCAPTURE} @item @b{IRSHIFT} ... @emph{stable}; TDI/TDO shifting through the instruction register @item @b{IREXIT1} @item @b{IRPAUSE} ... @emph{stable}; instruction register ready for update or more shifting @item @b{IREXIT2} @item @b{IRUPDATE} @end itemize Note that only six of those states are fully ``stable'' in the face of TMS fixed (low except for @sc{reset}) and a free-running JTAG clock. For all the others, the next TCK transition changes to a new state. @itemize @bullet @item From @sc{drshift} and @sc{irshift}, clock transitions will produce side effects by changing register contents. The values to be latched in upcoming @sc{drupdate} or @sc{irupdate} states may not be as expected. @item @sc{run/idle}, @sc{drpause}, and @sc{irpause} are reasonable choices after @command{drscan} or @command{irscan} commands, since they are free of JTAG side effects. @item @sc{run/idle} may have side effects that appear at non-JTAG levels, such as advancing the ARM9E-S instruction pipeline. Consult the documentation for the TAP(s) you are working with. @end itemize @node Boundary Scan Commands @chapter Boundary Scan Commands One of the original purposes of JTAG was to support boundary scan based hardware testing. Although its primary focus is to support On-Chip Debugging, OpenOCD also includes some boundary scan commands. @section SVF: Serial Vector Format @cindex Serial Vector Format @cindex SVF The Serial Vector Format, better known as @dfn{SVF}, is a way to represent JTAG test patterns in text files. In a debug session using JTAG for its transport protocol, OpenOCD supports running such test files. @deffn Command {svf} filename [@option{quiet}] This issues a JTAG reset (Test-Logic-Reset) and then runs the SVF script from @file{filename}. Unless the @option{quiet} option is specified, each command is logged before it is executed. @end deffn @section XSVF: Xilinx Serial Vector Format @cindex Xilinx Serial Vector Format @cindex XSVF The Xilinx Serial Vector Format, better known as @dfn{XSVF}, is a binary representation of SVF which is optimized for use with Xilinx devices. In a debug session using JTAG for its transport protocol, OpenOCD supports running such test files. @quotation Important Not all XSVF commands are supported. @end quotation @deffn Command {xsvf} (tapname|@option{plain}) filename [@option{virt2}] [@option{quiet}] This issues a JTAG reset (Test-Logic-Reset) and then runs the XSVF script from @file{filename}. When a @var{tapname} is specified, the commands are directed at that TAP. When @option{virt2} is specified, the @sc{xruntest} command counts are interpreted as TCK cycles instead of microseconds. Unless the @option{quiet} option is specified, messages are logged for comments and some retries. @end deffn The OpenOCD sources also include two utility scripts for working with XSVF; they are not currently installed after building the software. You may find them useful: @itemize @item @emph{svf2xsvf} ... converts SVF files into the extended XSVF syntax understood by the @command{xsvf} command; see notes below. @item @emph{xsvfdump} ... converts XSVF files into a text output format; understands the OpenOCD extensions. @end itemize The input format accepts a handful of non-standard extensions. These include three opcodes corresponding to SVF extensions from Lattice Semiconductor (LCOUNT, LDELAY, LDSR), and two opcodes supporting a more accurate translation of SVF (XTRST, XWAITSTATE). If @emph{xsvfdump} shows a file is using those opcodes, it probably will not be usable with other XSVF tools. @node Utility Commands @chapter Utility Commands @cindex Utility Commands @section RAM testing @cindex RAM testing There is often a need to stress-test random access memory (RAM) for errors. OpenOCD comes with a Tcl implementation of well-known memory testing procedures allowing the detection of all sorts of issues with electrical wiring, defective chips, PCB layout and other common hardware problems. To use them, you usually need to initialise your RAM controller first; consult your SoC's documentation to get the recommended list of register operations and translate them to the corresponding @command{mww}/@command{mwb} commands. Load the memory testing functions with @example source [find tools/memtest.tcl] @end example to get access to the following facilities: @deffn Command {memTestDataBus} address Test the data bus wiring in a memory region by performing a walking 1's test at a fixed address within that region. @end deffn @deffn Command {memTestAddressBus} baseaddress size Perform a walking 1's test on the relevant bits of the address and check for aliasing. This test will find single-bit address failures such as stuck-high, stuck-low, and shorted pins. @end deffn @deffn Command {memTestDevice} baseaddress size Test the integrity of a physical memory device by performing an increment/decrement test over the entire region. In the process every storage bit in the device is tested as zero and as one. @end deffn @deffn Command {runAllMemTests} baseaddress size Run all of the above tests over a specified memory region. @end deffn @section Firmware recovery helpers @cindex Firmware recovery OpenOCD includes an easy-to-use script to facilitate mass-market devices recovery with JTAG. For quickstart instructions run: @example openocd -f tools/firmware-recovery.tcl -c firmware_help @end example @node TFTP @chapter TFTP @cindex TFTP If OpenOCD runs on an embedded host (as ZY1000 does), then TFTP can be used to access files on PCs (either the developer's PC or some other PC). The way this works on the ZY1000 is to prefix a filename by "/tftp/ip/" and append the TFTP path on the TFTP server (tftpd). For example, @example load_image /tftp/10.0.0.96/c:\temp\abc.elf @end example will load c:\temp\abc.elf from the developer pc (10.0.0.96) into memory as if the file was hosted on the embedded host. In order to achieve decent performance, you must choose a TFTP server that supports a packet size bigger than the default packet size (512 bytes). There are numerous TFTP servers out there (free and commercial) and you will have to do a bit of googling to find something that fits your requirements. @node GDB and OpenOCD @chapter GDB and OpenOCD @cindex GDB OpenOCD complies with the remote gdbserver protocol and, as such, can be used to debug remote targets. Setting up GDB to work with OpenOCD can involve several components: @itemize @item The OpenOCD server support for GDB may need to be configured. @xref{gdbconfiguration,,GDB Configuration}. @item GDB's support for OpenOCD may need configuration, as shown in this chapter. @item If you have a GUI environment like Eclipse, that also will probably need to be configured. @end itemize Of course, the version of GDB you use will need to be one which has been built to know about the target CPU you're using. It's probably part of the tool chain you're using. For example, if you are doing cross-development for ARM on an x86 PC, instead of using the native x86 @command{gdb} command you might use @command{arm-none-eabi-gdb} if that's the tool chain used to compile your code. @section Connecting to GDB @cindex Connecting to GDB Use GDB 6.7 or newer with OpenOCD if you run into trouble. For instance GDB 6.3 has a known bug that produces bogus memory access errors, which has since been fixed; see @url{http://osdir.com/ml/gdb.bugs.discuss/2004-12/msg00018.html} OpenOCD can communicate with GDB in two ways: @enumerate @item A socket (TCP/IP) connection is typically started as follows: @example target remote localhost:3333 @end example This would cause GDB to connect to the gdbserver on the local pc using port 3333. It is also possible to use the GDB extended remote protocol as follows: @example target extended-remote localhost:3333 @end example @item A pipe connection is typically started as follows: @example target remote | openocd -c "gdb_port pipe; log_output openocd.log" @end example This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout). Using this method has the advantage of GDB starting/stopping OpenOCD for the debug session. log_output sends the log output to a file to ensure that the pipe is not saturated when using higher debug level outputs. @end enumerate To list the available OpenOCD commands type @command{monitor help} on the GDB command line. @section Sample GDB session startup With the remote protocol, GDB sessions start a little differently than they do when you're debugging locally. Here's an example showing how to start a debug session with a small ARM program. In this case the program was linked to be loaded into SRAM on a Cortex-M3. Most programs would be written into flash (address 0) and run from there. @example $ arm-none-eabi-gdb example.elf (gdb) target remote localhost:3333 Remote debugging using localhost:3333 ... (gdb) monitor reset halt ... (gdb) load Loading section .vectors, size 0x100 lma 0x20000000 Loading section .text, size 0x5a0 lma 0x20000100 Loading section .data, size 0x18 lma 0x200006a0 Start address 0x2000061c, load size 1720 Transfer rate: 22 KB/sec, 573 bytes/write. (gdb) continue Continuing. ... @end example You could then interrupt the GDB session to make the program break, type @command{where} to show the stack, @command{list} to show the code around the program counter, @command{step} through code, set breakpoints or watchpoints, and so on. @section Configuring GDB for OpenOCD OpenOCD supports the gdb @option{qSupported} packet, this enables information to be sent by the GDB remote server (i.e. OpenOCD) to GDB. Typical information includes packet size and the device's memory map. You do not need to configure the packet size by hand, and the relevant parts of the memory map should be automatically set up when you declare (NOR) flash banks. However, there are other things which GDB can't currently query. You may need to set those up by hand. As OpenOCD starts up, you will often see a line reporting something like: @example Info : lm3s.cpu: hardware has 6 breakpoints, 4 watchpoints @end example You can pass that information to GDB with these commands: @example set remote hardware-breakpoint-limit 6 set remote hardware-watchpoint-limit 4 @end example With that particular hardware (Cortex-M3) the hardware breakpoints only work for code running from flash memory. Most other ARM systems do not have such restrictions. Another example of useful GDB configuration came from a user who found that single stepping his Cortex-M3 didn't work well with IRQs and an RTOS until he told GDB to disable the IRQs while stepping: @example define hook-step mon cortex_m maskisr on end define hookpost-step mon cortex_m maskisr off end @end example Rather than typing such commands interactively, you may prefer to save them in a file and have GDB execute them as it starts, perhaps using a @file{.gdbinit} in your project directory or starting GDB using @command{gdb -x filename}. @section Programming using GDB @cindex Programming using GDB @anchor{programmingusinggdb} By default the target memory map is sent to GDB. This can be disabled by the following OpenOCD configuration option: @example gdb_memory_map disable @end example For this to function correctly a valid flash configuration must also be set in OpenOCD. For faster performance you should also configure a valid working area. Informing GDB of the memory map of the target will enable GDB to protect any flash areas of the target and use hardware breakpoints by default. This means that the OpenOCD option @command{gdb_breakpoint_override} is not required when using a memory map. @xref{gdbbreakpointoverride,,gdb_breakpoint_override}. To view the configured memory map in GDB, use the GDB command @option{info mem}. All other unassigned addresses within GDB are treated as RAM. GDB 6.8 and higher set any memory area not in the memory map as inaccessible. This can be changed to the old behaviour by using the following GDB command @example set mem inaccessible-by-default off @end example If @command{gdb_flash_program enable} is also used, GDB will be able to program any flash memory using the vFlash interface. GDB will look at the target memory map when a load command is given, if any areas to be programmed lie within the target flash area the vFlash packets will be used. If the target needs configuring before GDB programming, an event script can be executed: @example $_TARGETNAME configure -event EVENTNAME BODY @end example To verify any flash programming the GDB command @option{compare-sections} can be used. @anchor{usingopenocdsmpwithgdb} @section Using OpenOCD SMP with GDB @cindex SMP For SMP support following GDB serial protocol packet have been defined : @itemize @bullet @item j - smp status request @item J - smp set request @end itemize OpenOCD implements : @itemize @bullet @item @option{jc} packet for reading core id displayed by GDB connection. Reply is @option{XXXXXXXX} (8 hex digits giving core id) or @option{E01} for target not smp. @item @option{JcXXXXXXXX} (8 hex digits) packet for setting core id displayed at next GDB continue (core id -1 is reserved for returning to normal resume mode). Reply @option{E01} for target not smp or @option{OK} on success. @end itemize Handling of this packet within GDB can be done : @itemize @bullet @item by the creation of an internal variable (i.e @option{_core}) by mean of function allocate_computed_value allowing following GDB command. @example set $_core 1 #Jc01 packet is sent print $_core #jc packet is sent and result is affected in $ @end example @item by the usage of GDB maintenance command as described in following example (2 cpus in SMP with core id 0 and 1 @pxref{definecputargetsworkinginsmp,,Define CPU targets working in SMP}). @example # toggle0 : force display of coreid 0 define toggle0 maint packet Jc0 continue main packet Jc-1 end # toggle1 : force display of coreid 1 define toggle1 maint packet Jc1 continue main packet Jc-1 end @end example @end itemize @section RTOS Support @cindex RTOS Support @anchor{gdbrtossupport} OpenOCD includes RTOS support, this will however need enabling as it defaults to disabled. It can be enabled by passing @option{-rtos} arg to the target @xref{rtostype,,RTOS Type}. @* An example setup is below: @example $_TARGETNAME configure -rtos auto @end example This will attempt to auto detect the RTOS within your application. Currently supported rtos's include: @itemize @bullet @item @option{eCos} @item @option{ThreadX} @item @option{FreeRTOS} @item @option{linux} @item @option{ChibiOS} @item @option{embKernel} @item @option{mqx} @end itemize @quotation Note Before an RTOS can be detected, it must export certain symbols; otherwise, it cannot be used by OpenOCD. Below is a list of the required symbols for each supported RTOS. @end quotation @table @code @item eCos symbols Cyg_Thread::thread_list, Cyg_Scheduler_Base::current_thread. @item ThreadX symbols _tx_thread_current_ptr, _tx_thread_created_ptr, _tx_thread_created_count. @item FreeRTOS symbols @raggedright pxCurrentTCB, pxReadyTasksLists, xDelayedTaskList1, xDelayedTaskList2, pxDelayedTaskList, pxOverflowDelayedTaskList, xPendingReadyList, uxCurrentNumberOfTasks, uxTopUsedPriority. @end raggedright @item linux symbols init_task. @item ChibiOS symbols rlist, ch_debug, chSysInit. @item embKernel symbols Rtos::sCurrentTask, Rtos::sListReady, Rtos::sListSleep, Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount. @item mqx symbols _mqx_kernel_data, MQX_init_struct. @end table For most RTOS supported the above symbols will be exported by default. However for some, eg. FreeRTOS, extra steps must be taken. These RTOSes may require additional OpenOCD-specific file to be linked along with the project: @table @code @item FreeRTOS contrib/rtos-helpers/FreeRTOS-openocd.c @end table @node Tcl Scripting API @chapter Tcl Scripting API @cindex Tcl Scripting API @cindex Tcl scripts @section API rules Tcl commands are stateless; e.g. the @command{telnet} command has a concept of currently active target, the Tcl API proc's take this sort of state information as an argument to each proc. There are three main types of return values: single value, name value pair list and lists. Name value pair. The proc 'foo' below returns a name/value pair list. @example > set foo(me) Duane > set foo(you) Oyvind > set foo(mouse) Micky > set foo(duck) Donald @end example If one does this: @example > set foo @end example The result is: @example me Duane you Oyvind mouse Micky duck Donald @end example Thus, to get the names of the associative array is easy: @verbatim foreach { name value } [set foo] { puts "Name: $name, Value: $value" } @end verbatim Lists returned should be relatively small. Otherwise, a range should be passed in to the proc in question. @section Internal low-level Commands By "low-level," we mean commands that a human would typically not invoke directly. Some low-level commands need to be prefixed with "ocd_"; e.g. @command{ocd_flash_banks} is the low-level API upon which @command{flash banks} is implemented. @itemize @bullet @item @b{mem2array} <@var{varname}> <@var{width}> <@var{addr}> <@var{nelems}> Read memory and return as a Tcl array for script processing @item @b{array2mem} <@var{varname}> <@var{width}> <@var{addr}> <@var{nelems}> Convert a Tcl array to memory locations and write the values @item @b{ocd_flash_banks} <@var{driver}> <@var{base}> <@var{size}> <@var{chip_width}> <@var{bus_width}> <@var{target}> [@option{driver options} ...] Return information about the flash banks @item @b{capture} <@var{command}> Run <@var{command}> and return full log output that was produced during its execution. Example: @example > capture "reset init" @end example @end itemize OpenOCD commands can consist of two words, e.g. "flash banks". The @file{startup.tcl} "unknown" proc will translate this into a Tcl proc called "flash_banks". @section OpenOCD specific Global Variables Real Tcl has ::tcl_platform(), and platform::identify, and many other variables. JimTCL, as implemented in OpenOCD creates $ocd_HOSTOS which holds one of the following values: @itemize @bullet @item @b{cygwin} Running under Cygwin @item @b{darwin} Darwin (Mac-OS) is the underlying operating sytem. @item @b{freebsd} Running under FreeBSD @item @b{openbsd} Running under OpenBSD @item @b{netbsd} Running under NetBSD @item @b{linux} Linux is the underlying operating sytem @item @b{mingw32} Running under MingW32 @item @b{winxx} Built using Microsoft Visual Studio @item @b{ecos} Running under eCos @item @b{other} Unknown, none of the above. @end itemize Note: 'winxx' was choosen because today (March-2009) no distinction is made between Win32 and Win64. @quotation Note We should add support for a variable like Tcl variable @code{tcl_platform(platform)}, it should be called @code{jim_platform} (because it is jim, not real tcl). @end quotation @section Tcl RPC server @cindex RPC OpenOCD provides a simple RPC server that allows to run arbitrary Tcl commands and receive the results. To access it, your application needs to connect to a configured TCP port (see @command{tcl_port}). Then it can pass any string to the interpreter terminating it with @code{0x1a} and wait for the return value (it will be terminated with @code{0x1a} as well). This can be repeated as many times as desired without reopening the connection. Remember that most of the OpenOCD commands need to be prefixed with @code{ocd_} to get the results back. Sometimes you might also need the @command{capture} command. See @file{contrib/rpc_examples/} for specific client implementations. @section Tcl RPC server notifications @cindex RPC Notifications Notifications are sent asynchronously to other commands being executed over the RPC server, so the port must be polled continuously. Target event, state and reset notifications are emitted as Tcl associative arrays in the following format. @verbatim type target_event event [event-name] type target_state state [state-name] type target_reset mode [reset-mode] @end verbatim @deffn {Command} tcl_notifications [on/off] Toggle output of target notifications to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off. @end deffn @node FAQ @chapter FAQ @cindex faq @enumerate @anchor{faqrtck} @item @b{RTCK, also known as: Adaptive Clocking - What is it?} @cindex RTCK @cindex adaptive clocking @* In digital circuit design it is often refered to as ``clock synchronisation'' the JTAG interface uses one clock (TCK or TCLK) operating at some speed, your CPU target is operating at another. The two clocks are not synchronised, they are ``asynchronous'' In order for the two to work together they must be synchronised well enough to work; JTAG can't go ten times faster than the CPU, for example. There are 2 basic options: @enumerate @item Use a special "adaptive clocking" circuit to change the JTAG clock rate to match what the CPU currently supports. @item The JTAG clock must be fixed at some speed that's enough slower than the CPU clock that all TMS and TDI transitions can be detected. @end enumerate @b{Does this really matter?} For some chips and some situations, this is a non-issue, like a 500MHz ARM926 with a 5 MHz JTAG link; the CPU has no difficulty keeping up with JTAG. Startup sequences are often problematic though, as are other situations where the CPU clock rate changes (perhaps to save power). For example, Atmel AT91SAM chips start operation from reset with a 32kHz system clock. Boot firmware may activate the main oscillator and PLL before switching to a faster clock (perhaps that 500 MHz ARM926 scenario). If you're using JTAG to debug that startup sequence, you must slow the JTAG clock to sometimes 1 to 4kHz. After startup completes, JTAG can use a faster clock. Consider also debugging a 500MHz ARM926 hand held battery powered device that enters a low power ``deep sleep'' mode, at 32kHz CPU clock, between keystrokes unless it has work to do. When would that 5 MHz JTAG clock be usable? @b{Solution #1 - A special circuit} In order to make use of this, your CPU, board, and JTAG adapter must all support the RTCK feature. Not all of them support this; keep reading! The RTCK ("Return TCK") signal in some ARM chips is used to help with this problem. ARM has a good description of the problem described at this link: @url{http://www.arm.com/support/faqdev/4170.html} [checked 28/nov/2008]. Link title: ``How does the JTAG synchronisation logic work? / how does adaptive clocking work?''. The nice thing about adaptive clocking is that ``battery powered hand held device example'' - the adaptiveness works perfectly all the time. One can set a break point or halt the system in the deep power down code, slow step out until the system speeds up. Note that adaptive clocking may also need to work at the board level, when a board-level scan chain has multiple chips. Parallel clock voting schemes are good way to implement this, both within and between chips, and can easily be implemented with a CPLD. It's not difficult to have logic fan a module's input TCK signal out to each TAP in the scan chain, and then wait until each TAP's RTCK comes back with the right polarity before changing the output RTCK signal. Texas Instruments makes some clock voting logic available for free (with no support) in VHDL form; see @url{http://tiexpressdsp.com/index.php/Adaptive_Clocking} @b{Solution #2 - Always works - but may be slower} Often this is a perfectly acceptable solution. In most simple terms: Often the JTAG clock must be 1/10 to 1/12 of the target clock speed. But what that ``magic division'' is varies depending on the chips on your board. @b{ARM rule of thumb} Most ARM based systems require an 6:1 division; ARM11 cores use an 8:1 division. @b{Xilinx rule of thumb} is 1/12 the clock speed. Note: most full speed FT2232 based JTAG adapters are limited to a maximum of 6MHz. The ones using USB high speed chips (FT2232H) often support faster clock rates (and adaptive clocking). You can still debug the 'low power' situations - you just need to either use a fixed and very slow JTAG clock rate ... or else manually adjust the clock speed at every step. (Adjusting is painful and tedious, and is not always practical.) It is however easy to ``code your way around it'' - i.e.: Cheat a little, have a special debug mode in your application that does a ``high power sleep''. If you are careful - 98% of your problems can be debugged this way. Note that on ARM you may need to avoid using the @emph{wait for interrupt} operation in your idle loops even if you don't otherwise change the CPU clock rate. That operation gates the CPU clock, and thus the JTAG clock; which prevents JTAG access. One consequence is not being able to @command{halt} cores which are executing that @emph{wait for interrupt} operation. To set the JTAG frequency use the command: @example # Example: 1.234MHz adapter_khz 1234 @end example @item @b{Win32 Pathnames} Why don't backslashes work in Windows paths? OpenOCD uses Tcl and a backslash is an escape char. Use @{ and @} around Windows filenames. @example > echo \a > echo @{\a@} \a > echo "\a" > @end example @item @b{Missing: cygwin1.dll} OpenOCD complains about a missing cygwin1.dll. Make sure you have Cygwin installed, or at least a version of OpenOCD that claims to come with all the necessary DLLs. When using Cygwin, try launching OpenOCD from the Cygwin shell. @item @b{Breakpoint Issue} I'm trying to set a breakpoint using GDB (or a frontend like Insight or Eclipse), but OpenOCD complains that "Info: arm7_9_common.c:213 arm7_9_add_breakpoint(): sw breakpoint requested, but software breakpoints not enabled". GDB issues software breakpoints when a normal breakpoint is requested, or to implement source-line single-stepping. On ARMv4T systems, like ARM7TDMI, ARM720T or ARM920T, software breakpoints consume one of the two available hardware breakpoints. @item @b{LPC2000 Flash} When erasing or writing LPC2000 on-chip flash, the operation fails at random. Make sure the core frequency specified in the @option{flash lpc2000} line matches the clock at the time you're programming the flash. If you've specified the crystal's frequency, make sure the PLL is disabled. If you've specified the full core speed (e.g. 60MHz), make sure the PLL is enabled. @item @b{Amontec Chameleon} When debugging using an Amontec Chameleon in its JTAG Accelerator configuration, I keep getting "Error: amt_jtagaccel.c:184 amt_wait_scan_busy(): amt_jtagaccel timed out while waiting for end of scan, rtck was disabled". Make sure your PC's parallel port operates in EPP mode. You might have to try several settings in your PC BIOS (ECP, EPP, and different versions of those). @item @b{Data Aborts} When debugging with OpenOCD and GDB (plain GDB, Insight, or Eclipse), I get lots of "Error: arm7_9_common.c:1771 arm7_9_read_memory(): memory read caused data abort". The errors are non-fatal, and are the result of GDB trying to trace stack frames beyond the last valid frame. It might be possible to prevent this by setting up a proper "initial" stack frame, if you happen to know what exactly has to be done, feel free to add this here. @b{Simple:} In your startup code - push 8 registers of zeros onto the stack before calling main(). What GDB is doing is ``climbing'' the run time stack by reading various values on the stack using the standard call frame for the target. GDB keeps going - until one of 2 things happen @b{#1} an invalid frame is found, or @b{#2} some huge number of stackframes have been processed. By pushing zeros on the stack, GDB gracefully stops. @b{Debugging Interrupt Service Routines} - In your ISR before you call your C code, do the same - artifically push some zeros onto the stack, remember to pop them off when the ISR is done. @b{Also note:} If you have a multi-threaded operating system, they often do not @b{in the intrest of saving memory} waste these few bytes. Painful... @item @b{JTAG Reset Config} I get the following message in the OpenOCD console (or log file): "Warning: arm7_9_common.c:679 arm7_9_assert_reset(): srst resets test logic, too". This warning doesn't indicate any serious problem, as long as you don't want to debug your core right out of reset. Your .cfg file specified @option{jtag_reset trst_and_srst srst_pulls_trst} to tell OpenOCD that either your board, your debugger or your target uC (e.g. LPC2000) can't assert the two reset signals independently. With this setup, it's not possible to halt the core right out of reset, everything else should work fine. @item @b{USB Power} When using OpenOCD in conjunction with Amontec JTAGkey and the Yagarto toolchain (Eclipse, arm-elf-gcc, arm-elf-gdb), the debugging seems to be unstable. When single-stepping over large blocks of code, GDB and OpenOCD quit with an error message. Is there a stability issue with OpenOCD? No, this is not a stability issue concerning OpenOCD. Most users have solved this issue by simply using a self-powered USB hub, which they connect their Amontec JTAGkey to. Apparently, some computers do not provide a USB power supply stable enough for the Amontec JTAGkey to be operated. @b{Laptops running on battery have this problem too...} @item @b{USB Power} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following error messages: "Error: ft2232.c:201 ft2232_read(): FT_Read returned: 4" and "Error: ft2232.c:365 ft2232_send_and_recv(): couldn't read from FT2232". What does that mean and what might be the reason for this? First of all, the reason might be the USB power supply. Try using a self-powered hub instead of a direct connection to your computer. Secondly, the error code 4 corresponds to an FT_IO_ERROR, which means that the driver for the FTDI USB chip ran into some sort of error - this points us to a USB problem. @item @b{GDB Disconnects} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following error message: "Error: gdb_server.c:101 gdb_get_char(): read: 10054". What does that mean and what might be the reason for this? Error code 10054 corresponds to WSAECONNRESET, which means that the debugger (GDB) has closed the connection to OpenOCD. This might be a GDB issue. @item @b{LPC2000 Flash} In the configuration file in the section where flash device configurations are described, there is a parameter for specifying the clock frequency for LPC2000 internal flash devices (e.g. @option{flash bank $_FLASHNAME lpc2000 0x0 0x40000 0 0 $_TARGETNAME lpc2000_v1 14746 calc_checksum}), which must be specified in kilohertz. However, I do have a quartz crystal of a frequency that contains fractions of kilohertz (e.g. 14,745,600 Hz, i.e. 14,745.600 kHz). Is it possible to specify real numbers for the clock frequency? No. The clock frequency specified here must be given as an integral number. However, this clock frequency is used by the In-Application-Programming (IAP) routines of the LPC2000 family only, which seems to be very tolerant concerning the given clock frequency, so a slight difference between the specified clock frequency and the actual clock frequency will not cause any trouble. @item @b{Command Order} Do I have to keep a specific order for the commands in the configuration file? Well, yes and no. Commands can be given in arbitrary order, yet the devices listed for the JTAG scan chain must be given in the right order (jtag newdevice), with the device closest to the TDO-Pin being listed first. In general, whenever objects of the same type exist which require an index number, then these objects must be given in the right order (jtag newtap, targets and flash banks - a target references a jtag newtap and a flash bank references a target). You can use the ``scan_chain'' command to verify and display the tap order. Also, some commands can't execute until after @command{init} has been processed. Such commands include @command{nand probe} and everything else that needs to write to controller registers, perhaps for setting up DRAM and loading it with code. @anchor{faqtaporder} @item @b{JTAG TAP Order} Do I have to declare the TAPS in some particular order? Yes; whenever you have more than one, you must declare them in the same order used by the hardware. Many newer devices have multiple JTAG TAPs. For example: ST Microsystems STM32 chips have two TAPs, a ``boundary scan TAP'' and ``Cortex-M3'' TAP. Example: The STM32 reference manual, Document ID: RM0008, Section 26.5, Figure 259, page 651/681, the ``TDI'' pin is connected to the boundary scan TAP, which then connects to the Cortex-M3 TAP, which then connects to the TDO pin. Thus, the proper order for the STM32 chip is: (1) The Cortex-M3, then (2) The boundary scan TAP. If your board includes an additional JTAG chip in the scan chain (for example a Xilinx CPLD or FPGA) you could place it before or after the STM32 chip in the chain. For example: @itemize @bullet @item OpenOCD_TDI(output) -> STM32 TDI Pin (BS Input) @item STM32 BS TDO (output) -> STM32 Cortex-M3 TDI (input) @item STM32 Cortex-M3 TDO (output) -> SM32 TDO Pin @item STM32 TDO Pin (output) -> Xilinx TDI Pin (input) @item Xilinx TDO Pin -> OpenOCD TDO (input) @end itemize The ``jtag device'' commands would thus be in the order shown below. Note: @itemize @bullet @item jtag newtap Xilinx tap -irlen ... @item jtag newtap stm32 cpu -irlen ... @item jtag newtap stm32 bs -irlen ... @item # Create the debug target and say where it is @item target create stm32.cpu -chain-position stm32.cpu ... @end itemize @item @b{SYSCOMP} Sometimes my debugging session terminates with an error. When I look into the log file, I can see these error messages: Error: arm7_9_common.c:561 arm7_9_execute_sys_speed(): timeout waiting for SYSCOMP TODO. @end enumerate @node Tcl Crash Course @chapter Tcl Crash Course @cindex Tcl Not everyone knows Tcl - this is not intended to be a replacement for learning Tcl, the intent of this chapter is to give you some idea of how the Tcl scripts work. This chapter is written with two audiences in mind. (1) OpenOCD users who need to understand a bit more of how Jim-Tcl works so they can do something useful, and (2) those that want to add a new command to OpenOCD. @section Tcl Rule #1 There is a famous joke, it goes like this: @enumerate @item Rule #1: The wife is always correct @item Rule #2: If you think otherwise, See Rule #1 @end enumerate The Tcl equal is this: @enumerate @item Rule #1: Everything is a string @item Rule #2: If you think otherwise, See Rule #1 @end enumerate As in the famous joke, the consequences of Rule #1 are profound. Once you understand Rule #1, you will understand Tcl. @section Tcl Rule #1b There is a second pair of rules. @enumerate @item Rule #1: Control flow does not exist. Only commands @* For example: the classic FOR loop or IF statement is not a control flow item, they are commands, there is no such thing as control flow in Tcl. @item Rule #2: If you think otherwise, See Rule #1 @* Actually what happens is this: There are commands that by convention, act like control flow key words in other languages. One of those commands is the word ``for'', another command is ``if''. @end enumerate @section Per Rule #1 - All Results are strings Every Tcl command results in a string. The word ``result'' is used deliberatly. No result is just an empty string. Remember: @i{Rule #1 - Everything is a string} @section Tcl Quoting Operators In life of a Tcl script, there are two important periods of time, the difference is subtle. @enumerate @item Parse Time @item Evaluation Time @end enumerate The two key items here are how ``quoted things'' work in Tcl. Tcl has three primary quoting constructs, the [square-brackets] the @{curly-braces@} and ``double-quotes'' By now you should know $VARIABLES always start with a $DOLLAR sign. BTW: To set a variable, you actually use the command ``set'', as in ``set VARNAME VALUE'' much like the ancient BASIC langauge ``let x = 1'' statement, but without the equal sign. @itemize @bullet @item @b{[square-brackets]} @* @b{[square-brackets]} are command substitutions. It operates much like Unix Shell `back-ticks`. The result of a [square-bracket] operation is exactly 1 string. @i{Remember Rule #1 - Everything is a string}. These two statements are roughly identical: @example # bash example X=`date` echo "The Date is: $X" # Tcl example set X [date] puts "The Date is: $X" @end example @item @b{``double-quoted-things''} @* @b{``double-quoted-things''} are just simply quoted text. $VARIABLES and [square-brackets] are expanded in place - the result however is exactly 1 string. @i{Remember Rule #1 - Everything is a string} @example set x "Dinner" puts "It is now \"[date]\", $x is in 1 hour" @end example @item @b{@{Curly-Braces@}} @*@b{@{Curly-Braces@}} are magic: $VARIABLES and [square-brackets] are parsed, but are NOT expanded or executed. @{Curly-Braces@} are like 'single-quote' operators in BASH shell scripts, with the added feature: @{curly-braces@} can be nested, single quotes can not. @{@{@{this is nested 3 times@}@}@} NOTE: [date] is a bad example; at this writing, Jim/OpenOCD does not have a date command. @end itemize @section Consequences of Rule 1/2/3/4 The consequences of Rule 1 are profound. @subsection Tokenisation & Execution. Of course, whitespace, blank lines and #comment lines are handled in the normal way. As a script is parsed, each (multi) line in the script file is tokenised and according to the quoting rules. After tokenisation, that line is immedatly executed. Multi line statements end with one or more ``still-open'' @{curly-braces@} which - eventually - closes a few lines later. @subsection Command Execution Remember earlier: There are no ``control flow'' statements in Tcl. Instead there are COMMANDS that simply act like control flow operators. Commands are executed like this: @enumerate @item Parse the next line into (argc) and (argv[]). @item Look up (argv[0]) in a table and call its function. @item Repeat until End Of File. @end enumerate It sort of works like this: @example for(;;)@{ ReadAndParse( &argc, &argv ); cmdPtr = LookupCommand( argv[0] ); (*cmdPtr->Execute)( argc, argv ); @} @end example When the command ``proc'' is parsed (which creates a procedure function) it gets 3 parameters on the command line. @b{1} the name of the proc (function), @b{2} the list of parameters, and @b{3} the body of the function. Not the choice of words: LIST and BODY. The PROC command stores these items in a table somewhere so it can be found by ``LookupCommand()'' @subsection The FOR command The most interesting command to look at is the FOR command. In Tcl, the FOR command is normally implemented in C. Remember, FOR is a command just like any other command. When the ascii text containing the FOR command is parsed, the parser produces 5 parameter strings, @i{(If in doubt: Refer to Rule #1)} they are: @enumerate 0 @item The ascii text 'for' @item The start text @item The test expression @item The next text @item The body text @end enumerate Sort of reminds you of ``main( int argc, char **argv )'' does it not? Remember @i{Rule #1 - Everything is a string.} The key point is this: Often many of those parameters are in @{curly-braces@} - thus the variables inside are not expanded or replaced until later. Remember that every Tcl command looks like the classic ``main( argc, argv )'' function in C. In JimTCL - they actually look like this: @example int MyCommand( Jim_Interp *interp, int *argc, Jim_Obj * const *argvs ); @end example Real Tcl is nearly identical. Although the newer versions have introduced a byte-code parser and intepreter, but at the core, it still operates in the same basic way. @subsection FOR command implementation To understand Tcl it is perhaps most helpful to see the FOR command. Remember, it is a COMMAND not a control flow structure. In Tcl there are two underlying C helper functions. Remember Rule #1 - You are a string. The @b{first} helper parses and executes commands found in an ascii string. Commands can be seperated by semicolons, or newlines. While parsing, variables are expanded via the quoting rules. The @b{second} helper evaluates an ascii string as a numerical expression and returns a value. Here is an example of how the @b{FOR} command could be implemented. The pseudo code below does not show error handling. @example void Execute_AsciiString( void *interp, const char *string ); int Evaluate_AsciiExpression( void *interp, const char *string ); int MyForCommand( void *interp, int argc, char **argv ) @{ if( argc != 5 )@{ SetResult( interp, "WRONG number of parameters"); return ERROR; @} // argv[0] = the ascii string just like C // Execute the start statement. Execute_AsciiString( interp, argv[1] ); // Top of loop test for(;;)@{ i = Evaluate_AsciiExpression(interp, argv[2]); if( i == 0 ) break; // Execute the body Execute_AsciiString( interp, argv[3] ); // Execute the LOOP part Execute_AsciiString( interp, argv[4] ); @} // Return no error SetResult( interp, "" ); return SUCCESS; @} @end example Every other command IF, WHILE, FORMAT, PUTS, EXPR, everything works in the same basic way. @section OpenOCD Tcl Usage @subsection source and find commands @b{Where:} In many configuration files @* Example: @b{ source [find FILENAME] } @*Remember the parsing rules @enumerate @item The @command{find} command is in square brackets, and is executed with the parameter FILENAME. It should find and return the full path to a file with that name; it uses an internal search path. The RESULT is a string, which is substituted into the command line in place of the bracketed @command{find} command. (Don't try to use a FILENAME which includes the "#" character. That character begins Tcl comments.) @item The @command{source} command is executed with the resulting filename; it reads a file and executes as a script. @end enumerate @subsection format command @b{Where:} Generally occurs in numerous places. @* Tcl has no command like @b{printf()}, instead it has @b{format}, which is really more like @b{sprintf()}. @b{Example} @example set x 6 set y 7 puts [format "The answer: %d" [expr $x * $y]] @end example @enumerate @item The SET command creates 2 variables, X and Y. @item The double [nested] EXPR command performs math @* The EXPR command produces numerical result as a string. @* Refer to Rule #1 @item The format command is executed, producing a single string @* Refer to Rule #1. @item The PUTS command outputs the text. @end enumerate @subsection Body or Inlined Text @b{Where:} Various TARGET scripts. @example #1 Good proc someproc @{@} @{ ... multiple lines of stuff ... @} $_TARGETNAME configure -event FOO someproc #2 Good - no variables $_TARGETNAME confgure -event foo "this ; that;" #3 Good Curly Braces $_TARGETNAME configure -event FOO @{ puts "Time: [date]" @} #4 DANGER DANGER DANGER $_TARGETNAME configure -event foo "puts \"Time: [date]\"" @end example @enumerate @item The $_TARGETNAME is an OpenOCD variable convention. @*@b{$_TARGETNAME} represents the last target created, the value changes each time a new target is created. Remember the parsing rules. When the ascii text is parsed, the @b{$_TARGETNAME} becomes a simple string, the name of the target which happens to be a TARGET (object) command. @item The 2nd parameter to the @option{-event} parameter is a TCBODY @*There are 4 examples: @enumerate @item The TCLBODY is a simple string that happens to be a proc name @item The TCLBODY is several simple commands seperated by semicolons @item The TCLBODY is a multi-line @{curly-brace@} quoted string @item The TCLBODY is a string with variables that get expanded. @end enumerate In the end, when the target event FOO occurs the TCLBODY is evaluated. Method @b{#1} and @b{#2} are functionally identical. For Method @b{#3} and @b{#4} it is more interesting. What is the TCLBODY? Remember the parsing rules. In case #3, @{curly-braces@} mean the $VARS and [square-brackets] are expanded later, when the EVENT occurs, and the text is evaluated. In case #4, they are replaced before the ``Target Object Command'' is executed. This occurs at the same time $_TARGETNAME is replaced. In case #4 the date will never change. @{BTW: [date] is a bad example; at this writing, Jim/OpenOCD does not have a date command@} @end enumerate @subsection Global Variables @b{Where:} You might discover this when writing your own procs @* In simple terms: Inside a PROC, if you need to access a global variable you must say so. See also ``upvar''. Example: @example proc myproc @{ @} @{ set y 0 #Local variable Y global x #Global variable X puts [format "X=%d, Y=%d" $x $y] @} @end example @section Other Tcl Hacks @b{Dynamic variable creation} @example # Dynamically create a bunch of variables. for @{ set x 0 @} @{ $x < 32 @} @{ set x [expr $x + 1]@} @{ # Create var name set vn [format "BIT%d" $x] # Make it a global global $vn # Set it. set $vn [expr (1 << $x)] @} @end example @b{Dynamic proc/command creation} @example # One "X" function - 5 uart functions. foreach who @{A B C D E@} proc [format "show_uart%c" $who] @{ @} "show_UARTx $who" @} @end example @include fdl.texi @node OpenOCD Concept Index @comment DO NOT use the plain word ``Index'', reason: CYGWIN filename @comment case issue with ``Index.html'' and ``index.html'' @comment Occurs when creating ``--html --no-split'' output @comment This fix is based on: http://sourceware.org/ml/binutils/2006-05/msg00215.html @unnumbered OpenOCD Concept Index @printindex cp @node Command and Driver Index @unnumbered Command and Driver Index @printindex fn @bye openocd-0.9.0/doc/Makefile.am0000644000175000017500000000041712315575360012702 00000000000000info_TEXINFOS = openocd.texi openocd_TEXINFOS = fdl.texi man_MANS = openocd.1 EXTRA_DIST = openocd.1 \ manual \ INSTALL.txt MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in \ $(srcdir)/mdate-sh \ $(srcdir)/stamp-vti \ $(srcdir)/version.texi \ $(srcdir)/texinfo.tex openocd-0.9.0/doc/Makefile.in0000644000175000017500000006465612526201647012730 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(openocd_TEXINFOS) mdate-sh $(srcdir)/version.texi \ $(srcdir)/stamp-vti texinfo.tex ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = AM_V_DVIPS = $(am__v_DVIPS_@AM_V@) am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@) am__v_DVIPS_0 = @echo " DVIPS " $@; am__v_DVIPS_1 = AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@) am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@) am__v_MAKEINFO_0 = @echo " MAKEINFO" $@; am__v_MAKEINFO_1 = AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@) am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@) am__v_INFOHTML_0 = @echo " INFOHTML" $@; am__v_INFOHTML_1 = AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@) am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@) am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@; am__v_TEXI2DVI_1 = AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@) am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@) am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@; am__v_TEXI2PDF_1 = AM_V_texinfo = $(am__v_texinfo_@AM_V@) am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@) am__v_texinfo_0 = -q am__v_texinfo_1 = AM_V_texidevnull = $(am__v_texidevnull_@AM_V@) am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@) am__v_texidevnull_0 = > /dev/null am__v_texidevnull_1 = INFO_DEPS = $(srcdir)/openocd.info am__TEXINFO_TEX_DIR = $(srcdir) DVIS = openocd.dvi PDFS = openocd.pdf PSS = openocd.ps HTMLS = openocd.html TEXINFOS = openocd.texi TEXI2DVI = texi2dvi TEXI2PDF = $(TEXI2DVI) --pdf --batch MAKEINFOHTML = $(MAKEINFO) --html AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) DVIPS = dvips am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ info_TEXINFOS = openocd.texi openocd_TEXINFOS = fdl.texi man_MANS = openocd.1 EXTRA_DIST = openocd.1 \ manual \ INSTALL.txt MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in \ $(srcdir)/mdate-sh \ $(srcdir)/stamp-vti \ $(srcdir)/version.texi \ $(srcdir)/texinfo.tex all: all-am .SUFFIXES: .SUFFIXES: .dvi .html .info .pdf .ps .texi $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs .texi.info: $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \ am__cwd=`pwd` && $(am__cd) $(srcdir) && \ rm -rf $$backupdir && mkdir $$backupdir && \ if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ done; \ else :; fi && \ cd "$$am__cwd"; \ if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $@ $<; \ then \ rc=0; \ $(am__cd) $(srcdir); \ else \ rc=$$?; \ $(am__cd) $(srcdir) && \ $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ fi; \ rm -rf $$backupdir; exit $$rc .texi.dvi: $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \ $< .texi.pdf: $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \ $< .texi.html: $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp) $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $(@:.html=.htp) $<; \ then \ rm -rf $@; \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ else \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ exit 1; \ fi $(srcdir)/openocd.info: openocd.texi $(srcdir)/version.texi $(openocd_TEXINFOS) openocd.dvi: openocd.texi $(srcdir)/version.texi $(openocd_TEXINFOS) openocd.pdf: openocd.texi $(srcdir)/version.texi $(openocd_TEXINFOS) openocd.html: openocd.texi $(srcdir)/version.texi $(openocd_TEXINFOS) $(srcdir)/version.texi: $(srcdir)/stamp-vti $(srcdir)/stamp-vti: openocd.texi $(top_srcdir)/configure @(dir=.; test -f ./openocd.texi || dir=$(srcdir); \ set `$(SHELL) $(srcdir)/mdate-sh $$dir/openocd.texi`; \ echo "@set UPDATED $$1 $$2 $$3"; \ echo "@set UPDATED-MONTH $$2 $$3"; \ echo "@set EDITION $(VERSION)"; \ echo "@set VERSION $(VERSION)") > vti.tmp @cmp -s vti.tmp $(srcdir)/version.texi \ || (echo "Updating $(srcdir)/version.texi"; \ cp vti.tmp $(srcdir)/version.texi) -@rm -f vti.tmp @cp $(srcdir)/version.texi $@ mostlyclean-vti: -rm -f vti.tmp maintainer-clean-vti: -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi .dvi.ps: $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ $(DVIPS) $(AM_V_texinfo) -o $@ $< uninstall-dvi-am: @$(NORMAL_UNINSTALL) @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ rm -f "$(DESTDIR)$(dvidir)/$$f"; \ done uninstall-html-am: @$(NORMAL_UNINSTALL) @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ done uninstall-info-am: @$(PRE_UNINSTALL) @if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ done; \ else :; fi @$(NORMAL_UNINSTALL) @list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ else :; fi); \ done uninstall-pdf-am: @$(NORMAL_UNINSTALL) @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ done uninstall-ps-am: @$(NORMAL_UNINSTALL) @list='$(PSS)'; test -n "$(psdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ rm -f "$(DESTDIR)$(psdir)/$$f"; \ done dist-info: $(INFO_DEPS) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for base in $$list; do \ case $$base in \ $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$base; then d=.; else d=$(srcdir); fi; \ base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ if test -f $$file; then \ relfile=`expr "$$file" : "$$d/\(.*\)"`; \ test -f "$(distdir)/$$relfile" || \ cp -p $$file "$(distdir)/$$relfile"; \ else :; fi; \ done; \ done mostlyclean-aminfo: -rm -rf openocd.t2d openocd.t2p clean-aminfo: -test -z "openocd.dvi openocd.pdf openocd.ps openocd.html" \ || rm -rf openocd.dvi openocd.pdf openocd.ps openocd.html maintainer-clean-aminfo: @list='$(INFO_DEPS)'; for i in $$list; do \ i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ done install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-info check-am: all-am check: check-am all-am: Makefile $(INFO_DEPS) $(MANS) installdirs: for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-aminfo clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: $(DVIS) html: html-am html-am: $(HTMLS) info: info-am info-am: $(INFO_DEPS) install-data-am: install-info-am install-man install-dvi: install-dvi-am install-dvi-am: $(DVIS) @$(NORMAL_INSTALL) @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \ $(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ done install-exec-am: install-html: install-html-am install-html-am: $(HTMLS) @$(NORMAL_INSTALL) @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \ $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ $(am__strip_dir) \ d2=$$d$$p; \ if test -d "$$d2"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \ $(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ else \ list2="$$list2 $$d2"; \ fi; \ done; \ test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ done; } install-info: install-info-am install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \ $(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \ fi; \ for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ if test -f $$ifile; then \ echo "$$ifile"; \ else : ; fi; \ done; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done @$(POST_INSTALL) @if $(am__can_run_installinfo); then \ list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ done; \ else : ; fi install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: $(PDFS) @$(NORMAL_INSTALL) @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done install-ps: install-ps-am install-ps-am: $(PSS) @$(NORMAL_INSTALL) @list='$(PSS)'; test -n "$(psdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-vti mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-aminfo mostlyclean-generic \ mostlyclean-libtool mostlyclean-vti pdf: pdf-am pdf-am: $(PDFS) ps: ps-am ps-am: $(PSS) uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ uninstall-man uninstall-pdf-am uninstall-ps-am uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-aminfo clean-generic \ clean-libtool cscopelist-am ctags-am dist-info distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-aminfo maintainer-clean-generic \ maintainer-clean-vti mostlyclean mostlyclean-aminfo \ mostlyclean-generic mostlyclean-libtool mostlyclean-vti pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am \ uninstall-dvi-am uninstall-html-am uninstall-info-am \ uninstall-man uninstall-man1 uninstall-pdf-am uninstall-ps-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/doc/openocd.10000644000175000017500000000624512315575360012364 00000000000000.TH "OPENOCD" "1" "November 24, 2009" .SH "NAME" openocd \- A free and open on\-chip debugging, in\-system programming and boundary\-scan testing tool for ARM and MIPS systems .SH "SYNOPSIS" .B openocd \fR[\fB\-fsdlcphv\fR] [\fB\-\-file\fR ] [\fB\-\-search\fR ] [\fB\-\-debug\fR ] [\fB\-\-log_output\fR ] [\fB\-\-command\fR ] [\fB\-\-pipe\fR] [\fB\-\-help\fR] [\fB\-\-version\fR] .SH "DESCRIPTION" .B OpenOCD is an on\-chip debugging, in\-system programming and boundary\-scan testing tool for various ARM and MIPS systems. .PP The debugger uses an IEEE 1149\-1 compliant JTAG TAP bus master to access on\-chip debug functionality available on ARM based microcontrollers or system-on-chip solutions. For MIPS systems the EJTAG interface is supported. .PP User interaction is realized through a telnet command line interface, a gdb (the GNU debugger) remote protocol server, and a simplified RPC connection that can be used to interface with OpenOCD's Jim Tcl engine. .PP OpenOCD supports various different types of JTAG interfaces/programmers, please check the \fIopenocd\fR info page for the complete list. .SH "OPTIONS" .TP .B "\-f, \-\-file " This is a shortcut for a \fB\-c "[script \fI\fB]"\fR command, using a search path to load the configuration file .IR . In order to specify multiple config files, you can use multiple .B \-\-file arguments. If no such \fB\-c\fR options are included, the first config file .B openocd.cfg in the search path will be used. .TP .B "\-s, \-\-search " Add .I to the search path used for config files and scripts. The search path begins with the current directory, then includes these additional directories before other components such as the standard OpenOCD script libraries. .TP .B "\-d, \-\-debug " Set debug level. Possible values are: .br .RB " * " 0 " (errors)" .br .RB " * " 1 " (warnings)" .br .RB " * " 2 " (informational messages)" .br .RB " * " 3 " (debug messages)" .br The default level is .BR 2 . .TP .B "\-l, \-\-log_output " Redirect log output to the file .IR . Per default the log output is printed on .BR stderr . .TP .B "\-c, \-\-command " Add the command .I to a list of commands executed on server startup. Note that you will need to explicitly invoke .I init if the command requires access to a target or flash. .TP .B "\-p, \-\-pipe" Use pipes when talking to gdb. .TP .B "\-h, \-\-help" Show a help text and exit. .TP .B "\-v, \-\-version" Show version information and exit. .SH "BUGS" Please report any bugs on the mailing list at .BR openocd\-devel@lists.sourceforge.net . .SH "LICENCE" .B OpenOCD is covered by the GNU General Public License (GPL), version 2 or later. .SH "SEE ALSO" .BR jtag (1) .PP The full documentation for .B openocd is maintained as a Texinfo manual. If the .BR info (or .BR pinfo ) and .BR openocd programs are properly installed at your site, the command .B info openocd should give you access to the complete manual. .SH "AUTHORS" Please see the file AUTHORS. .PP This manual page was written by Uwe Hermann . It is licensed under the terms of the GNU GPL (version 2 or later). openocd-0.9.0/doc/manual/0000755000175000017500000000000012315575360012201 500000000000000openocd-0.9.0/doc/manual/jtag/0000755000175000017500000000000012315575360013126 500000000000000openocd-0.9.0/doc/manual/jtag/drivers/0000755000175000017500000000000012315575360014604 500000000000000openocd-0.9.0/doc/manual/jtag/drivers/remote_bitbang.txt0000644000175000017500000000264612315575360020256 00000000000000/** @remote_bitbangpage OpenOCD Developer's Guide The remote_bitbang JTAG driver is used to drive JTAG from a remote process. The remote_bitbang driver communicates via TCP or UNIX sockets with some remote process using an ASCII encoding of the bitbang interface. The remote process presumably then drives the JTAG however it pleases. The remote process should act as a server, listening for connections from the openocd remote_bitbang driver. The remote bitbang driver is useful for debugging software running on processors which are being simulated. The bitbang interface consists of the following functions. blink on Blink a light somewhere. The argument on is either 1 or 0. read Sample the value of tdo. write tck tms tdi Set the value of tck, tms, and tdi. reset trst srst Set the value of trst, srst. An additional function, quit, is added to the remote_bitbang interface to indicate there will be no more requests and the connection with the remote driver should be closed. These five functions are encoded in ascii by assigning a single character to each possible request. The assignments are: B - Blink on b - Blink off R - Read request Q - Quit request 0 - Write 0 0 0 1 - Write 0 0 1 2 - Write 0 1 0 3 - Write 0 1 1 4 - Write 1 0 0 5 - Write 1 0 1 6 - Write 1 1 0 7 - Write 1 1 1 r - Reset 0 0 s - Reset 0 1 t - Reset 1 0 u - Reset 1 1 The read response is encoded in ascii as either digit 0 or 1. */ openocd-0.9.0/doc/manual/style.txt0000644000175000017500000004105412315575360014026 00000000000000/** @page styleguide Style Guides The goals for each of these guides are: - to produce correct code that appears clean, consistent, and readable, - to allow developers to create patches that conform to a standard, and - to eliminate these issues as points of future contention. Some of these rules may be ignored in the spirit of these stated goals; however, such exceptions should be fairly rare. The following style guides describe a formatting, naming, and other conventions that should be followed when writing or changing the OpenOCD code: - @subpage styletcl - @subpage stylec - @subpage styleperl - @subpage styleautotools In addition, the following style guides provide information for providing documentation, either as part of the C code or stand-alone. - @subpage styledoxygen - @subpage styletexinfo - @subpage stylelatex Feedback would be welcome to improve the OpenOCD guidelines. */ /** @page styletcl TCL Style Guide OpenOCD needs to expand its Jim/TCL Style Guide. Many of the guidelines listed on the @ref stylec page should apply to OpenOCD's Jim/TCL code as well. */ /** @page stylec C Style Guide This page contains guidelines for writing new C source code for the OpenOCD project. @section styleformat Formatting Guide - remove any trailing white space at the end of lines. - use TAB characters for indentation; do NOT use spaces. - displayed TAB width is 4 characters. - use Unix line endings ('\\n'); do NOT use DOS endings ('\\r\\n') - limit adjacent empty lines to at most two (2). - remove any trailing empty lines at the end of source files - do not "comment out" code from the tree; instead, one should either: -# remove it entirely (git can retrieve the old version), or -# use an @c \#if/\#endif block. Finally, try to avoid lines of code that are longer than than 72-80 columns: - long lines frequently indicate other style problems: - insufficient use of static functions, macros, or temporary variables - poor flow-control structure; "inverted" logical tests - a few lines may be wider than this limit (typically format strings), but: - all C compilers will concatenate series of string constants. - all long string constants should be split across multiple lines. @section stylenames Naming Rules - most identifiers must use lower-case letters (and digits) only. - macros must use upper-case letters (and digits) only. - OpenOCD identifiers should NEVER use @c MixedCaps. - @c typedef names must end with the '_t' suffix. - This should be reserved for types that should be passed by value. - Do @b not mix the typedef keyword with @c struct. - use underline characters between consecutive words in identifiers (e.g. @c more_than_one_word). @section stylec99 C99 Rules - inline functions - @c // comments -- in new code, prefer these for single-line comments - trailing comma allowed in enum declarations - designated initializers ( .field = value ) - variables declarations should occur at the point of first use - new block scopes for selection and iteration statements - use malloc() to create dynamic arrays. Do @b not use @c alloca or variable length arrays on the stack. non-MMU hosts(uClinux) and pthreads require modest and predictable stack usage. @section styletypes Type Guidelines - use native types (@c int or @c unsigned) if the type is not important - if size matters, use the types from \ or \: - @c int8_t, @c int16_t, @c int32_t, or @c int64_t: signed types of specified size - @c uint8_t, @c uint16_t, @c uint32_t, or @c uint64_t: unsigned types of specified size - do @b NOT redefine @c uN types from "types.h" @section stylefunc Functions - static inline functions should be prefered over macros: @code /** do NOT define macro-like functions like this... */ #define CUBE(x) ((x) * (x) * (x)) /** instead, define the same expression using a C99 inline function */ static inline int cube(int x) { return x * x * x; } @endcode - Functions should be declared static unless required by other modules - define static functions before first usage to avoid forward declarations. - Functions should have no space between its name and its parameter list: @code int f(int x1, int x2) { ... int y = f(x1, x2 - x1); ... } @endcode - Separate assignment and logical test statements. In other words, you should write statements like the following: @code // separate statements should be preferred result = foo(); if (ERROR_OK != result) ... @endcode More directly, do @b not combine these kinds of statements: @code // Combined statements should be avoided if (ERROR_OK != (result = foo())) return result; @endcode */ /** @page styledoxygen Doxygen Style Guide The following sections provide guidelines for OpenOCD developers who wish to write Doxygen comments in the code or this manual. For an introduction to Doxygen documentation, see the @ref primerdoxygen. @section styledoxyblocks Doxygen Block Selection Several different types of Doxygen comments can be used; often, one style will be the most appropriate for a specific context. The following guidelines provide developers with heuristics for selecting an appropriate form and writing consistent documentation comments. -# use @c /// to for one-line documentation of instances. -# for documentation requiring multiple lines, use a "block" style: @verbatim /** * @brief First sentence is short description. Remaining text becomes * the full description block, where "empty" lines start new paragraphs. * * One can make text appear in @a italics, @b bold, @c monospace, or * in blocks such as the one in which this example appears in the Style * Guide. See the Doxygen Manual for the full list of commands. * * @param foo For a function, describe the parameters (e.g. @a foo). * @returns The value(s) returned, or possible error conditions. */ @endverbatim -# The block should start on the line following the opening @c /**. -# The end of the block, \f$*/\f$, should also be on its own line. -# Every line in the block should have a @c '*' in-line with its start: - A leading space is required to align the @c '*' with the @c /** line. - A single "empty" line should separate the function documentation from the block of parameter and return value descriptions. - Except to separate paragraphs of documentation, other extra "empty" lines should be removed from the block. -# Only single spaces should be used; do @b not add mid-line indentation. -# If the total line length will be less than 72-80 columns, then - The @c /**< form can be used on the same line. - This style should be used sparingly; the best use is for fields: @code int field; /**< field description */ @endcode @section styledoxyall Doxygen Style Guide The following guidelines apply to all Doxygen comment blocks: -# Use the @c '\@cmd' form for all doxygen commands (do @b not use @c '\\cmd'). -# Use symbol names such that Doxygen automatically creates links: -# @c function_name() can be used to reference functions (e.g. flash_set_dirty()). -# @c struct_name::member_name should be used to reference structure fields in the documentation (e.g. @c flash_driver::name). -# URLS get converted to markup automatically, without any extra effort. -# new pages can be linked into the heirarchy by using the @c \@subpage command somewhere the page(s) under which they should be linked: -# use @c \@ref in other contexts to create links to pages and sections. -# Use good Doxygen mark-up: -# '\@a' (italics) should be used to reference parameters (e.g. foo). -# '\@b' (bold) should be used to emphasizing single words. -# '\@c' (monospace) should be used with file names and code symbols, so they appear visually distinct from surrounding text. -# To mark-up multiple words, the HTML alternatives must be used. -# Two spaces should be used when nesting lists; do @b not use '\\t' in lists. -# Code examples provided in documentation must conform to the Style Guide. @section styledoxytext Doxygen Text Inputs In addition to the guidelines in the preceding sections, the following additional style guidelines should be considered when writing documentation as part of standalone text files: -# Text files must contain Doxygen at least one comment block: -# Documentation should begin in the first column (except for nested lists). -# Do NOT use the @c '*' convention that must be used in the source code. -# Each file should contain at least one @c \@page block. -# Each new page should be listed as a \@subpage in the \@page block of the page that should serve as its parent. -# Large pages should be structure in parts using meaningful \@section and \@subsection commands. -# Include a @c \@file block at the end of each Doxygen @c .txt file to document its contents: - Doxygen creates such pages for files automatically, but no content will appear on them for those that only contain manual pages. - The \@file block should provide useful meta-documentation to assist techincal writers; typically, a list of the pages that it contains. - For example, the @ref styleguide exists in @c doc/manual/style.txt, which contains a reference back to itself. -# The \@file and \@page commands should begin on the same line as the start of the Doxygen comment: @verbatim /** @page pagename Page Title Documentation for the page. */ /** @file This file contains the @ref pagename page. */ @endverbatim For an example, the Doxygen source for this Style Guide can be found in @c doc/manual/style.txt, alongside other parts of The Manual. */ /** @page styletexinfo Texinfo Style Guide The User's Guide is there to provide two basic kinds of information. It is a guide for how and why to use each feature or mechanism of OpenOCD. It is also the reference manual for all commands and options involved in using them, including interface, flash, target, and other drivers. At this time, it is the only user-targetted documentation; everything else is addressing OpenOCD developers. There are two key audiences for the User's Guide, both developer based. The primary audience is developers using OpenOCD as a tool in their work, or who may be starting to use it that way. A secondary audience includes developers who are supporting those users by packaging or customizing it for their hardware, installing it as part of some software distribution, or by evolving OpenOCD itself. There is some crossover between those audiences. We encourage contributions from users as the fundamental way to evolve and improve OpenOCD. In particular, creating a board or target specific configuration file is something that many users will end up doing at some point, and we like to see such files become part of the mainline release. General documentation rules to remember include: - Be concise and clear. It's work to remove those extra words and sentences, but such "noise" doesn't help readers. - Make it easy to skim and browse. "Tell what you're going to say, then say it". Help readers decide whether to dig in now, or leave it for later. - Make sure the chapters flow well. Presentations should not jump around, and should move easily from overview down to details. - Avoid using the passive voice. - Address the reader to clarify roles ("your config file", "the board you are debugging", etc.); "the user" (etc) is artificial. - Use good English grammar and spelling. Remember also that English will not be the first language for many readers. Avoid complex or idiomatic usage that could create needless barriers. - Use examples to highlight fundamental ideas and common idioms. - Don't overuse list constructs. This is not a slide presentation; prefer paragraphs. When presenting features and mechanisms of OpenOCD: - Explain key concepts before presenting commands using them. - Tie examples to common developer tasks. - When giving instructions, you can \@enumerate each step both to clearly delineate the steps, and to highlight that this is not explanatory text. - When you provide "how to use it" advice or tutorials, keep it in separate sections from the reference material. - Good indexing is something of a black art. Use \@cindex for important concepts, but don't overuse it. In particular, rely on the \@deffn indexing, and use \@cindex primarily with significant blocks of text such as \@subsection. The \@dfn of a key term may merit indexing. - Use \@xref (and \@anchor) with care. Hardcopy versions, from the PDF, must make sense without clickable links (which don't work all that well with Texinfo in any case). If you find you're using many links, read that as a symptom that the presentation may be disjointed and confusing. - Avoid font tricks like \@b, but use \@option, \@file, \@dfn, \@emph and related mechanisms where appropriate. For technical reference material: - It's OK to start sections with explanations and end them with detailed lists of the relevant commands. - Use the \@deffn style declarations to define all commands and drivers. These will automatically appear in the relevant index, and those declarations help promote consistent presentation and style. - It's a "Command" if it can be used interactively. - Else it's a "Config Command" if it must be used before the configuration stage completes. - For a "Driver", list its name. - Use EBNF style regular expressions to define parameters: brackets around zero-or-one choices, parentheses around exactly-one choices. - Use \@option, \@file, \@var and other mechanisms where appropriate. - Say what output it displays, and what value it returns to callers. - Explain clearly what the command does. Sometimes you will find that it can't be explained clearly. That usually means the command is poorly designed; replace it with something better, if you can. - Be complete: document all commands, except as part of a strategy to phase something in or out. - Be correct: review the documentation against the code, and vice versa. - Alphabetize the \@defn declarations for all commands in each section. - Keep the per-command documentation focussed on exactly what that command does, not motivation, advice, suggestions, or big examples. When commands deserve such expanded text, it belongs elsewhere. Solutions might be using a \@section explaining a cluster of related commands, or acting as a mini-tutorial. - Details for any given driver should be grouped together. The User's Guide is the first place most users will start reading, after they begin using OpenOCD. Make that investment of their time be as productive as possible. Needing to look at OpenOCD source code, to figure out how to use it is a bad sign, though it's OK to need to look at the User's guide to figure out what a config script is doing. */ /** @page stylelatex LaTeX Style Guide This page needs to provide style guidelines for using LaTeX, the typesetting language used by The References for OpenOCD Hardware. Likewise, the @ref primerlatex for using this guide needs to be completed. */ /** @page styleperl Perl Style Guide This page provides some style guidelines for using Perl, a scripting language used by several small tools in the tree: -# Ensure all Perl scripts use the proper suffix (@c .pl for scripts, and @c .pm for modules) -# Pass files as script parameters or piped as input: - Do NOT code paths to files in the tree, as this breaks out-of-tree builds. - If you must, then you must also use an automake rule to create the script. -# use @c '#!/usr/bin/perl' as the first line of Perl scripts. -# always use strict and use warnings -# invoke scripts indirectly in Makefiles or other scripts: @code perl script.pl @endcode Maintainers must also be sure to follow additional guidelines: -# Ensure that Perl scripts are committed as executables: Use "chmod +x script.pl" @a before using "git add script.pl" */ /** @page styleautotools Autotools Style Guide This page contains style guidelines for the OpenOCD autotools scripts. The following guidelines apply to the @c configure.ac file: - Better guidelines need to be developed, but until then... - Use good judgement. The following guidelines apply to @c Makefile.am files: -# When assigning variables with long lists of items: -# Separate the values on each line to make the files "patch friendly": @code VAR = \ value1 \ value2 \ ... value9 \ value10 @endcode */ /** @file This file contains the @ref styleguide pages. The @ref styleguide pages include the following Style Guides for their respective code and documentation languages: - @ref styletcl - @ref stylec - @ref styledoxygen - @ref styletexinfo - @ref stylelatex - @ref styleperl - @ref styleautotools */ openocd-0.9.0/doc/manual/helper.txt0000644000175000017500000001205312315575360014142 00000000000000/** @page helperdocs OpenOCD Helper APIs OpenOCD uses several low-level APIs as the foundation for high-level APIs: - @subpage helperporting - @subpage helperjim - @subpage helpercommand - @subpage helperlogging - @subpage helperbuffers This section needs to be expanded. */ /** @page helperporting OpenOCD Types/Portability APIs This section needs to be expanded to describe OpenOCD's type and portability API. */ /** @page helperjim OpenOCD Jim API The Jim API provides access to a small-footprint TCL implementation. Visit http://jim.tcl.tk/ for more information on Jim. This section needs to be expanded to describe OpenOCD's Jim API. */ /** @page helpercommand OpenOCD Command API OpenOCD's command API allows modules to register callbacks that are then available to the scripting services. It provides the mechanism for these commands to be dispatched to the module using a standard interface. It provides macros for defining functions that use and extend this interface. @section helpercmdhandler Command Handlers Command handlers are functions with a particular signature, which can be extended by modules for passing additional parameters to helpers or another layer of handlers. @subsection helpercmdhandlerdef Defining and Calling Command Handlers These functions should be defined using the @c COMMAND_HANDLER macro. These methods must be defined as static, as their principal entry point should be the run_command dispatch mechanism. Command helper functions that require access to the full set of parameters should be defined using the @c COMMAND_HELPER. These must be declared static by you, as sometimes you might want to share a helper among several files (e.g. @c s3c24xx_nand.h). Both types of routines must be called using the @c CALL_COMMAND_HANDLER macro. Calls using this macro to normal handlers require the name of the command handler (which can be a name or function pointer). Calls to helpers and derived handlers must pass those extra parameters specified by their definitions; however, lexical capture is used for the core parameters. This dirty trick is being used as a stop-gap measure while the API is migrated to one that passes a pointer to a structure containing the same ingredients. At that point, this macro will be removed and callers will be able to use direct invocations. Thus, the following macros can be used to define and call command handlers or helpers: - @c COMMAND_HANDLER - declare or define a command handler. - @c COMMAND_HELPER - declare or define a derived command handler or helper. - @c CALL_COMMAND_HANDLER - call a command handler/helper. @subsection helpercmdhandlermacros Command Handler Macros In addition, the following macros may be used in the context of command handlers and helpers: - @c CMD_CTX - the current @c command_context - @c CMD_NAME - invoked command name - @c CMD_ARGC - the number of command arguments - @c CMD_ARGV - array of command argument strings @section helpercmdregister Command Registration In order to use a command handler, it must be registered with the command subsystem. All commands are registered with command_registration structures, specifying the name of the command, its handler, its allowed mode(s) of execution, and strings that provide usage and help text. A single handler may be registered using multiple names, but any name may have only one handler associated with it. The @c register_commands() and @c register_commands() functions provide registration, while the @c unregister_command() and @c unregister_all_commands() functions will remove existing commands. These may be called at any time, allowing the command set to change in response to system actions. @subsection helpercmdjim Jim Command Registration The command_registration structure provides support for registering native Jim command handlers (@c jim_handler) too. For these handlers, the module can provide help and usage support; however, this mechanism allows Jim handlers to be called as sub-commands of other commands. These commands may be registered with a private data value (@c jim_handler_data) that will be available when called, as with low-level Jim command registration. A command may have a normal @c handler or a @c jim_handler, but not both. @subsection helpercmdregisterchains Command Chaining When using register_commands(), the array of commands may reference other arrays. When the @c chain field is filled in a command_registration record, the commands on in the chained list will added in one of two places. If the record defines a new command, then the chained commands are added under it; otherwise, the commands are added in the same context as the other commands in the array. @section helpercmdprimer Command Development Primer This @ref primercommand provides details about the @c hello module, showing how the pieces described on this page fit together. */ /** @page helperlogging OpenOCD Logging API This section needs to be expanded to describe OpenOCD's Logging API. */ /** @page helperbuffers OpenOCD Byte Buffer API This section needs to be expanded to describe OpenOCD's Byte Buffer API. */ openocd-0.9.0/doc/manual/jtag.txt0000644000175000017500000000366312315575360013617 00000000000000/** @page jtagdocs JTAG APIs For new developers unfamiliar with the technology, @ref primerjtag provides a brief introduction to the IEEE JTAG interface. The OpenOCD JTAG library API covers several functional areas. The jtag @b core communicates through the @b minidriver API with either its full @a driver implementation (src/jtag/jtag_driver.c) or a @a minidriver . Internally, the @b command API is used by the JTAG driver for managing asynchronous transactions. - @subpage jtagcore - @b public API routines - declared in @c src/jtag/jtag.h - used by other modules - @subpage jtagtcl - @b private TCL handling routines - defined in @c src/jtag/tcl.c - registers and handles Jim commands that configure and use the JTAG core - @subpage jtagcmd - @b private command queue API - declared in @c src/jtag/commands.h - provides routines used internally by the full JTAG drivers. - @subpage jtagiface - @b private interface driver API - declared in @c src/jtag/interface.h - used by the core, minidrivers, and the full interface device drivers. - allows implementing new interface device drivers. - includes the Cable/TAP API (commands starting with @c tap_) - @subpage jtagdriver - @b private minidriver API - declared in @c src/jtag/minidriver.h - used @a only by the core and minidriver implementations: - @c jtag_driver.c (in-tree OpenOCD drivers) - @c zy1000/build/include/jtag_minidriver.h (ZY1000 minidriver) - future implementations (on other embedded hosts) - interface device drivers do @b not need this API. */ /** @page jtagcore JTAG Core API This section needs to be expanded. */ /** @page jtagtcl JTAG TCL API This section needs to be expanded. */ /** @page jtagcmd JTAG Command API This section needs to be expanded. */ /** @page jtagiface JTAG Interface API This section needs to be expanded. */ /** @page jtagdriver JTAG Minidriver API This section needs to be expanded. */ openocd-0.9.0/doc/manual/release.txt0000644000175000017500000005301212315575360014303 00000000000000/** @page releases Release Processes This page provides an introduction to the OpenOCD Release Processes: - @ref releasewhy - Explain the motivations for producing releases on a regular basis. - @ref releasewho - Describes the responsibilities and authority required to produce official OpenOCD releases. - @ref releasewhen - Provides guidelines for scheduling activities for each release cycle. - @ref releasehow - Outlines all of the steps for the processes used to produce and release the package source archives. - @ref releasescriptcmds - Introduces the automated @c release.sh script. @section releasewhy Why Produce Releases? The OpenOCD maintainers produce releases periodically for many reasons. This section provides the key reasons for making releases on a regular basis and why a set of release processes should be used to produce them. At any time, source archives can be produced by running make dist in the OpenOCD project tree. With the 0.2.0 release, this command will package the tree into several popular archive formats: openocd-\.{tar.gz,tar.bz2,zip}. If produced properly, these files are suitable for release to the public. When properly versioned and released for users, these archives present several important advantages compared to using the source repository (including snapshots downloaded from that repository using gitweb): -# They allow others to package and distribute the code using consistent version labels. Users won't normally need to care whose package they use, just the version of OpenOCD. -# They contain a working configure script and makefiles, which were produced as part of creating the archive. -# Because they have been formally released by the project, users don't need to try a random work-in-process revision. Releasing involves spending some time specifically on quality improvments, including bugfixing source code and documentation. -# They provide developers with the flexibility needed to address larger issues, which sometimes involves temporary breakage. Hopefully, this shows several good reasons to produce regular releases, but the release processes were developed with some additional design goals in mind. Specifically, the releases processes should have the following properties: -# Produce successive sets of archives cleanly and consistently. -# Implementable as a script that automates the critical steps. -# Prevent human operators from producing broken packages, when possible. -# Allow scheduling and automation of building and publishing milestones. The current release processes are documented in the following sections. They attempt to meet these design goals, but improvements may still need to be made. @subsection version_labels Version Labels Users can display the OpenOCD version string in at least two ways. The command line openocd -v invocation displays it; as does the Tcl version command. Labels for released versions look like 0.3.0, or 0.3.0-rc1 for a preliminary release. Non-released (developer) versions look like 0.3.0-dev, or 0.3.0-rc1-dev. In all cases, additional tags may be appended to those base release version labels. The tools/release/version.sh script is used to manipulate version IDs found in the source tree. @subsubsection releaseversions Release Versions and Tags The OpenOCD version string is composed of three numeric components separated by two decimal points: @c x.y.z, where @c x is the @a major version number, @c y is the @a minor number, and @c z is the @a micro. For any bug-fix release, the micro version number will be non-zero (z > 0). For a minor release, the micro version number will be zero (z = 0). For a major releases, the minor version will @a also be zero (y = 0, z = 0). After these required numeric components, release version strings may contain tags such as as -rc1 or -rc2. These 'rc' tags indicate "release candidate" versions of the package. Like major/minor/micro numbers, these are updated as part of the release process. The release process includes version number manipulations to the tree being released, ensuring that all numbers are incremented (or rolled over) at the right time and in the proper locations of the repository. One of those manipulations creates a repository tag matching that release's version label. @subsubsection releaseversionsdist Packager Versions Distributors of patched versions of OpenOCD are encouraged to extend the version string with a unique version tag when producing external releases, as this helps to identify your particular distribution series. Knowing that a release has such patches can be essential to tracking down and fixing bugs. Packager version tags should always be suffixes to the version code from the OpenOCD project, signifying modifications to the original code base. Each packager release should have a unique version. For example, the following command will add a 'foo' tag to the configure.ac script of a local copy of the source tree, giving a version label like 0.3.0-foo: @code tools/release/version.sh tag add foo @endcode This command will modify the configure.ac script in your working copy only. After running the @c bootstrap sequence, the tree can be patched and used to produce your own derived versions. You might check that change into a private branch of your git tree, along with the other patches you are providing. You can also "bump" those tags (so "foo1" becomes "foo2" etc) each time a derived package is released, incrementing the tag's version to facilitate tracking the changes you have distributed. @code tools/release/version.sh bump tag foo @endcode Of course, any patches in your branches must be provided to your customers, and be in conformance with the GPL. In most cases you should also work to merge your improvements to the mainline tree. @subsubsection version_tags Development Versions and Tags Everything except formal releases should have the tag -dev in their version number. This helps developers identify reports created from non-release versions, and it can be detected and manipulated by the release script. Specifically, this tag will be removed and re-added during the release process; it should never be manipulated by developers in submitted patches. Versions built from developer trees may have additional tags. Trees built from git snapshots have snapshot tags. When built from a "live" git tree, tags specify specific git revisions: 0.3.0-rc1-dev-00015-gf37c9b8-dirty indicates a development tree based on git revison f37c9b8 (a truncated version of a SHA1 hash) with some non-git patches applied (the dirty tag). This information can be useful when tracking down bugs. (Note that at this writing, the tags do not directly correspond to git describe output. The hash ID can be used with git show, but the relevant repository tag isn't 0.3.0-rc1-dev; this might change in the future.) @section releasewho Release Manager OpenOCD archive releases will be produced by an individual filling the role of Release Manager, hereafter abbreviated as RM. This individual determines the schedule and executes the release processes for the community. @subsection releasewhohow RM Authority Each release requires one individual to fulfill the RM role; however, graceful transitions of this authority may take place at any time. The current RM may transfer their authority to another contributor in a post to the OpenOCD development mailing list. Such delegation of authority must be approved by the individual that will receive it and the community of maintainers. Initial arrangements with the new RM should be made off-list, as not every contributor wants these responsibilities. @subsection releasewhowhat RM Responsibilities In addition to the actual process of producing the releases, the RM is responsible for keeping the community informed of all progress through the release cycle(s) being managed. The RM is responsible for managing the changes to the package version, though the release tools should manage the tasks of adding or removing any required development branch tags and incrementing the version. These responsibilities matter most towards the end of the release cycle, when the RM creates the first RC and all contributors enter a quality-improvement mode. The RM works with other contributors to make sure everyone knows what kinds of fixes should merge, the status of major issues, and the release timetable. In particular, the RM has the final decision on whether a given bug should block the release. @section releasewhen Release Schedule The OpenOCD release process must be carried out on a periodic basis, so the project can realize the benefits presented in answer to the question, @ref releasewhy. Starting with the 0.2.0 release, the OpenOCD project expects to produce new releases every few months. Bug fix releases could be provided more frequently. These release schedule goals may be adjusted in the future, after the project maintainers and distributors receive feedback and experience. More importantly, the statements made in this section do not create an obligation by any member of the OpenOCD community to produce new releases on regular schedule, now or in the future. @subsection releasewhenexample Sample Schedule The RM must pro-actively communicate with the community from the beginning of the development cycle through the delivery of the new release. This section presents guidelines for scheduling key points where the community must be informed of changing conditions. If Tn is the time of release n, then the following schedule might describe some key T0-to-T1 release cycle milestones. - T0 ... End of T0 release cycle. T1 cycle starts, with merge window opening. Developers begin to merge queued work. - ... several weeks of merge window ... - RC1 ... Close mainline to new work. Produce RC1 release, begin testing phase; developers are in "bugfix mode", all other work is queued; send out planned endgame schedule. - RC2 ... Produce RC2 and send schedule update to mailing list, listing priorities for remaining fixes - ... more RC milestones, until ready ... - T1: End of T1 release cycle. T2 cycle starts, with merge window opening. Developers begin to merge queued work. Note that until it happens, any date for T1 is just a goal. Critical bugs prevent releases from happening. We are just beginning to use this window-plus-RCs process, so the lengths of the merge windows versus the RC phase is subject to change. Most projects have RC phases of a month or more. Some additional supplemental communication will be desirable. The above list omits the step-by-step instructions to daily release management. Individuals performing release management need to have the ability to interact proactively with the community as a whole, anticipating when such interaction will be required and giving ample notification. The next section explains why the OpenOCD project allows significant flexibility in the part of the development that precedes the release process. @subsection releasewhenflex Schedule Flexibility The Release Manager should attempt to follow the guidelines in this document, but the process of scheduling each release milestone should be community driven at the start. Features that don't complete before the merge window closes can be held (perhaps in some branch) until the next merge window opens, rather than delaying the release cycle. The Release Manager cannot schedule the work that will be done on the project, when it will be submitted, reviewed, and deemed suitable to be committed. That is, the RM cannot act as a priest in a cathedral; OpenOCD uses the bazaar development model. The release schedule must adapt continuously in response to changes in the rate of work. Fewer releases may be required if developers contribute less patches, and more releases may be desirable if the project continues to grow and experience high rates of community contribution. During each cycle, the RM should be tracking the situation and gathering feedback from the community. @section releasehow Release Process: Step-by-Step The release process is not final; it may need more iterations to work out bugs. While there are release scripts, key steps require community support; the Release Manager isn't the only participant. The following steps should be followed to produce each release: -# Produce final patches using a local clone of mainline. Nobody except the RM should be committing anything. Everyone with commit privileges needs to know and agree to this in advance! Even the RM only commits a handful of updates as part of the release process itself ... to files which are part of the version identification scheme or release process; and to create the version tag; and then to open the merge window for the next release cycle. -# Finalize @c the NEWS file to describe the changes in the release - This file is used to automatically post "blurbs" about the project. - This material should have been produced during the development cycle, by adding items for each @c NEWS-worthy contribution, when committed during the merge window. (One part of closing the merge window, by opening the RC phase of the release, is the commitment to hold all further such contributions until the next merge window opens.) - The RM should make sure nothing important was omitted, as part of the RC1 cycle. From then on, no more updates to NEWS content should be needed (except to seed the process for the next release, or maybe if a significant and longstanding bug is fixed late in the RC phase). -# Bump library version if our API changed (not yet required) -# Update and commit the final package version in @c configure.ac: (The tools/release/version.sh script might help ensure the versions are named properly.): -# Remove @c -dev tag. -# Update any @c -rc tag: - If producing the final release from an -rc series, remove it - If producing the first RC in a series, add rc1 - If producing the next RC in a series, bump the rc number -# Commit that version change, with a good descriptive comment. -# Create a git tag for the final commit, with a tag name matching the version string in configure.ac (including -rcN where relevant): @verbatim PACKAGE_VERSION="x.y.z" PACKAGE_TAG="v${PACKAGE_VERSION}" git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}" @endverbatim -# Do not push those changes to mainline yet; only builds using the source archives you will be creating should ever be labeled as official releases (with no "-dev" suffix). Since mainline is a development tree, these will be pushed later, as part of opening the merge window for the next release cycle (restoring the "-dev" suffix for that next release.) Those version and tag updates are the last ones to be included in the release being made. -# Produce the release files, using the local clone of the source tree which holds the release's tag and updated version in @c configure.ac ... this is used only to produce the release, and all files should already be properly checked out. -# Run tools/release.sh package to produce the source archives. This automatically bootstraps and configures the process. -# Run tools/release.sh stage to create an @c archives directory with the release data, including MD5 and SHA1 checksum files. -# Sanity check at least one of those archives, by extracting and configuring its contents, using them to build a copy of OpenOCD, and verifying that the result prints the correct release version in its startup banner. (For example, "configure --enable-ft2232_libftdi --enable-parport" then "make" and run "src/openocd -v" as a sanity check.) -# Run make docs to create the documentation which will be published. -# Upload packages and post announcements of their availability: -# Release packages into files section of project sites: - SF.net: -# Under "Project Admin", use the "File Manager" -# Create a new folder under "openocd" named "${PACKAGE_VERSION}" -# Upload the @c NEWS file and mark it as the release notes. -# Upload the three source archive files, using the Web interface, into that folder. Verify the upload worked OK by checking the MD5 and SHA1 checksums computed by SourceForge against the versions created as part of staging the release. -# Also upload doc/openocd.pdf (the User's Guide) so the version matching each release will be easily available. -# Select each file in the release, and use the property panel to set its type and select the right release notes. - .tar.bz2: Linux, Mac - .tar.gz: BSD, Solaris, Others - .zip: Windows - For openocd.pdf just associate it with the right release notes. -# Create an SF.net project news update. -# Depending on how paranoid you're feeling today, verify the images by downloading them from the websites and making sure there are no differences between the downloaded copies and your originals. -# Publish User's and Developer's Guides to the project web sites: -# Use SCP to update the SF.net web site with PDF and HTML for the User's Guide, and HTML for the developer's guide ... you can instantiate a shell.sourceforge.net instance and set up symlinks from your home directory, to simplify this process. -# Post announcement e-mail to the openocd-development list. -# optionally: -# Post an update on the OpenOCD blog. -# Announce updates on freshmeat.net and other trackers. -# Submit updates to news feeds (e.g. Digg, Reddit, etc.). -# Resume normal development on mainline, by opening the merge window for the next major or minor release cycle. (You might want to do this before all the release bits are fully published.) - Update the version label in the @c configure.ac file: - Restore @c -dev version tag. - For a new minor release cycle, increment the release's minor number - For a new major release cycle, increment the release's major number and zero its minor number - Archive @c NEWS file as "doc/news/NEWS-${PACKAGE_VERSION}". - Create a new @c NEWS file for the next release - Commit those changes. - Push all the updates to mainline. - Last updates for the release, including the release tag (you will need to "git push --tags"). - Updates opening the merge window - At this point, it's OK for commiters to start pushing changes which have been held off until the next release. (Any bugfixes to this release will be against a bug-fix release branch starting from the commit you tagged as this release, not mainline.) - Announce to the openocd-development list. Ideally, you will also be able to say who is managing the next release cycle. To start a bug-fix release branch: -# Create a new branch, starting from a major or minor release tag -# Restore @c -dev version tag. -# Bump micro version number in configure.ac -# Backport bugfix patches from mainline into that branch. (Always be sure mainline has the fix first, so it's hard to just lose a bugfix.) -# Commit and push those patches. -# When desired, release as above ... except note that the next release of a bugfix branch is never a new major or minor release @subsection releasescriptcmds Release Script Commands The @c release.sh script automates some of the steps involved in making releases, simplifying the Release Manager's work. The release script can be used for two tasks: - Creating releases and starting a new release cycle: @code git checkout master tools/release.sh --type=minor --final --start-rc release @endcode - Creating a development branch from a tagged release: @code git checkout 'v0.2.0' tools/release.sh --type=micro branch @endcode Both of these variations make automatic commits and tags in your repository, so you should be sure to run it on a cloned copy before proceding with a live release. @subsection releasescriptopts Release Script Options The @c release.sh script recognizes some command-line options that affect its behavior: - The @c --start-rc indicates that the new development release cycle should start with @c -rc0. Without this, the @c -rc tag will be omitted, leading to non-monotonic versioning of the in-tree version numbers. - The @c --final indicates that the release should drop the @c -rc tag, to going from @c x.y.z-rcN-dev to x.y.z. @subsection releasescriptenv Release Script Environment The @c release.sh script recognizes some environment variables which affect its behavior: - @c CONFIG_OPTS : Passed as options to the configure script. - @c MAKE_OPTS : Passed as options to the 'make' processes. @section releasetutorial Release Tutorials This section should contain a brief tutorial for using the Release Script to perform release tasks, but the new script needs to be used for 0.3.0. @section releasetodo Release Script Shortcomings Improved automated packaging and distribution of OpenOCD requires more patching of the configure script. The final release script should be able to manage most steps of the processes. The steps requiring user input could be guided by an "assistant" that walks the Release Manager through the process from beginning to end, performing basic sanity checks on their various inputs (e.g. the @c NEWS blurb). */ /** @file This file contains the @ref releases page. */ openocd-0.9.0/doc/manual/main.txt0000644000175000017500000000716212315575360013614 00000000000000/** @mainpage OpenOCD Developer's Guide Welcome to the OpenOCD Developer's Guide -- the developer's resource for learning about the internal architecture of the OpenOCD project. @par In addition, this document contains the tactical and strategic plans and processes that have been developed by and for the OpenOCD community. Developers that want to contribute to OpenOCD should read the following sections before starting work: - The List of @subpage thelist enumerates opportunities for improving or extending the OpenOCD platform. If your ideas are on The List, you might check the mailing list archives to find the status of your feature (or bug). - The @subpage styleguide provides rules that developers should follow when writing new code for OpenOCD. - The @subpage patchguide provides policies that developers should follow when submitting patches to the project. - The @subpage bugs page contains the content of the BUGS file, which provides instructions for submitting bug reports to the maintainers. - The @subpage releases page describes the project's release process. @ref primer provide introductory materials for new developers on various specific topics. Finally, the @ref oocd pages explain how the code has been organized into layers of APIs, providing an overview of how they fit together. These pages attempt to give developers a high-level perspective of the various code modules provided by OpenOCD. */ /** @page primer OpenOCD Technical Primers This pages lists Technical Primers available for OpenOCD Developers. They seek to provide information to pull novices up the learning curves associated with the fundamental technologies used by OpenOCD. - @subpage primerdocs - @subpage primerautotools - @subpage primertcl - @subpage primerjtag The above documents should bridge any "ancillary" gaps in contributor knowledge, without having to learn the complete languages or technology. They should provide enough information for experienced developers to learn how to make "correct" changes when creating patches. Beyond the fundamentals, the following primers provide introductory tutorials for OpenOCD's sub-systems. These complement the @ref oocd pages that provide more high-level perspective on related topics. - @subpage primercommand In all cases, these Primers should use idiomatic conventions that the community has agreed are the "right way of doing things". In this respect, these documents typically assume some familiarity with the information contained in one or more @ref styleguide, or they will directly refer to specific style guides as supplemental reading. Contributions or suggestions for new Technical Primers are welcome. */ /** @page oocd OpenOCD Architecture The OpenOCD library consists of several APIs that build together to provide the support functionality. The following list shows how these modules are stacked in the current implementation (from bottom to top): - @subpage helperdocs - @ref helperporting - @ref helperjim - @ref helpercommand - @ref helperlogging - @subpage jtagdocs - @ref jtagcore - @ref jtagtcl - @ref jtagcmd - @ref jtagiface - @ref jtagdriver - @subpage targetdocs - @ref targetarm - @ref targetnotarm - @ref targetmips - @ref targetregister - @ref targetimage - @ref targettrace - @subpage flashdocs - @ref flashcfi - @ref flashnand - @ref flashtarget - @subpage serverdocs - @ref servergdb - @ref servertelnet - @ref serverhttp - @subpage appdocs Obviously, there are some nuances to the stack that are not shown by this linear list of layers. The List of @ref thelist enumerates opportunities for improving or extending the OpenOCD platform. */ openocd-0.9.0/doc/manual/target.txt0000644000175000017500000000217212315575360014152 00000000000000/** @page targetdocs OpenOCD Target APIs OpenOCD provides its Target APIs to allow developers to provide trace and debugging support for specific device targets. These primarily consist of ARM cores, but other types have been supported. New targets should be developed by following or using these APIs. The Target Support module contains APIs that cover several functional areas: - @subpage targetarm - @subpage targetnotarm - @subpage targetmips - @subpage targetregister - @subpage targetimage - @subpage targettrace This section needs to be expanded. */ /** @page targetarm OpenOCD ARM Targets This section needs to describe OpenOCD's ARM target support. */ /** @page targetregister OpenOCD Target Register API This section needs to describe OpenOCD's Target Register API, as provided by 'src/target/register.h'. */ /** @page targetimage OpenOCD Target Image API This section needs to describe OpenOCD's Target Image API, as provided by 'src/target/image.h'. */ /** @page targettrace OpenOCD Target Trace API This section needs to describe OpenOCD's Target Trace API, as provided by 'src/target/trace.h'. */ openocd-0.9.0/doc/manual/flash.txt0000644000175000017500000000142112315575360013755 00000000000000/** @page flashdocs OpenOCD Flash APIs OpenOCD provides its Flash APIs for developers to support different types of flash devices, some of which are built-in to target devices while others may be connected via standard memory interface (e.g. CFI, FMI, etc.). The Flash module provides the following APIs: - @subpage flashcfi - @subpage flashnand - @subpage flashtarget This section needs to be expanded. */ /** @page flashcfi OpenOCD CFI Flash API This section needs to be expanded to describe OpenOCD's CFI Flash API. */ /** @page flashnand OpenOCD NAND Flash API This section needs to be expanded to describe OpenOCD's NAND Flash API. */ /** @page flashtarget OpenOCD Target Flash API This section needs to be expanded to describe OpenOCD's Target Flash API. */ openocd-0.9.0/doc/manual/images/0000755000175000017500000000000012315575360013446 500000000000000openocd-0.9.0/doc/manual/images/jtag-state-machine-large.png0000644000175000017500000002623012315575360020634 00000000000000‰PNG  IHDRÉpL. bPLTE?Àÿ**?**À*ÿUU?UUÀUÿ?Àÿªª?ªªÀªÿÕÕ?ÕÕÀÕÿÿÿ?ÿÿÀÿÿ**?**À*ÿ****?****À**ÿ*U*U?*U*UÀ*Uÿ**?**À*ÿ*ª*ª?*ª*ªÀ*ªÿ*Õ*Õ?*Õ*ÕÀ*Õÿ*ÿ*ÿ?*ÿ*ÿÀ*ÿÿUU?UUÀUÿU*U*?U*U*ÀU*ÿUUUU?UUUUÀUUÿUU?UUÀUÿUªUª?UªUªÀUªÿUÕUÕ?UÕUÕÀUÕÿUÿUÿ?UÿUÿÀUÿÿ?Àÿ**?**À*ÿUU?UUÀUÿ?Àÿªª?ªªÀªÿÕÕ?ÕÕÀÕÿÿÿ?ÿÿÀÿÿªª?ªªÀªÿª*ª*?ª*ª*Àª*ÿªUªU?ªUªUÀªUÿªª?ªªÀªÿªªªª?ªªªªÀªªÿªÕªÕ?ªÕªÕÀªÕÿªÿªÿ?ªÿªÿÀªÿÿÕÕ?ÕÕÀÕÿÕ*Õ*?Õ*Õ*ÀÕ*ÿÕUÕU?ÕUÕUÀÕUÿÕÕ?ÕÕÀÕÿÕªÕª?ÕªÕªÀÕªÿÕÕÕÕ?ÕÕÕÕÀÕÕÿÕÿÕÿ?ÕÿÕÿÀÕÿÿÿÿ?ÿÿÀÿÿÿ*ÿ*?ÿ*ÿ*Àÿ*ÿÿUÿU?ÿUÿUÀÿUÿÿÿ?ÿÿÀÿÿÿªÿª?ÿªÿªÀÿªÿÿÕÿÕ?ÿÕÿÕÀÿÕÿÿÿÿÿ?ÿÿÿÿÀÿÿÿÿÿ?ÿÿÀ***UUUªªªÕÕÕÿÿÿÛßÝó pHYs M MÒέNtEXtSoftwareGNU Ghostscript 5.50åû‹” IDATxœíÙ–ì¨Dïÿÿ1OÜÕ§ÒF̈ѫ»*Ë ’"ÙiãñüÏBÐ úßê HE ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC ºC,’ÍO£‹ fÕHöÌжª‘ –¡=U$9‰-X†vT‰ä²@ÚOy’Kë^° í¦Æ£p@ÚL9’k¨eh/µ’ ”¡½”!™Á)P†vRšd¥ ÚIí$eh'%Iæ1jÜ3¤jºN)’™Ð˜©ke  ÕAòìéP† êY'ÏF (Cyµ“¼€+  eÕLò ª@2”U‚ämWÉ Êë(’2”Õ’;öA2”Óh’Ø‚dh€†¯“UáÉPNJ$Çw®Ê¢U„QÁ4äK‡ä¿ë"~Gü^×μïü÷â}ý4úþý‘¼ÔÂX‚¨”Ž'û»¢èï—¿N6îcüÆöoiÔפ/ê -1ýA_‘É`¿Õ*}çï·ù±êîVÚoßßé'àÒ8(-M’Ÿ×Æ&I¶%’Ißg]J }F©üû¾ó´7ÆD}’ßHv¯Õ(t–’LÎÍ“é"Ú8ìûïì± ü©ÜpŸqGèO2óµï1ºèiöuG3’IAòõÒ!yЭՙCk¢ÐG´3Éùé¯,ô)‘̈#_¹öÏoAòw¤Er5Њ™*@þæl =1M ùCR#9‰ÏKW|Jz$çhOOLLœb€ãI‘äd°è ›Ê‰I†¤¾ Ã¥Jrú†°À%T“.ɉx*kH Õ¤M²wUû¿—›z Õ¤Nò_Tº&ÉÐ!¹3Ç€ÐíšAr¿@2TH†îH†îÐY$»óÁet¨çF¾¦ÃH¶ï}O†ž7´ÑßRœ®þ˜Î"ùßkÿŽ$ɆÜr }Cç’ü<\ u Ÿ1$Lj÷ŒÄWïzWiOÊ:É4—yŸ\’¿$Í»Ÿ~7ë{›ÿh«Gòï Z© FAò÷¤9»ðŸD8™deü= 9±ÙïK™#ÙíØ=_!Ì.¾«Ñ$‡3Ø–”’­G²× K#H.lö›R†ØÜ7ļëåÄ™ü)M 9D¹s A) !™œ™g°-)A2T×(’­OrWJ Õ¥H²ywîÜ6u_à $C5w¶‚RÚŸd<Áâh’ㇿ@P¬sHžž:J¬óðèrCòü´ÐQÉÐ:d\DÕ5„dí£ ªJdJ° ªJ™ä9A2T“.É©hñUS$õÅÒÑÅ‹u–[ýkáJ9&’~¦£‹ß¹¥í¶´CáZ¸ê;sÇ'ü€ë“|WºÎµÅ—Z¦mõ=Ÿaîw‰;T±'“xÅ”ø_1sïM_ÑÄã˜xAâêÿä$iH…qflõÝÕ¾çP%< ¹ÈT[ŒPœ1ñ ÞˆïP|¡ml«‹äÜò<é“\‹³æ^ç(eâöïÄô7÷±Î•x. ÷|†Üò<Í'yÍNŒäã!Ó²ÉcëLª“äŽç3lá–çIäz˜5»ãÑWøQ“}W¢×š±•Lk“¶šŸÏ°…[ž'm’9Q”>Ù7¢÷ãÉ/™ n’[ŸÏ°…[ž§ H6–Cuöãq2ømµZgÙèV½í@ÉΖ%™UgÙ³îfÓP3†*áI™dVå/:ohJõI.ô*&Ê“lݼ.ÞÒ3ÔF²õG½%`¹]öÝwÝЄ2c¨žö'9jeÅ <_äÁ¹µÈ{è'_N¥0û~àn}2Žä”­’¯Z:ÉïßVã°LOîÏÕ$?ÿöÍ»‡úŒ?ùr?¼Ùç÷/·Ú%å*÷1ÑýhZƒ1&(ôïw0¼~÷¿¡J¹PÞŠÕT€‚e8E2×j*©´|im’ÿ›Î?ŽwcoŸEÏ7’~óI;óþ)JÊUf†i¼ÄÆ+Ô„ëd7Ov7¾!ÅâÅÊϧy†ß5NƒÕDRqùÒ ’y1rëdûbûþoŸ Š[]ÛàÓy:Vö04H6t´þ[2do ä;ø¶²Žä »Wc°D¥x±2n-×°#9èH嬿JÊ—v˜IòÓÆs’\Nª¥ *­îû>ƒÙE0¾ÄNžäeŠ+a&{|b«nSAKZ@røyHHîx·°–2&5°ÞøÆ{|ÉîÆH®”§¬¬[Ë3Üc5·p¤æ‘LI6®cvÞU/­ú=v_öh{ë¿/Íï×ÛùýìÑÆû‘œNÌ0œÚããZÍ-)m’énÙ4·WL¾i_ⱟäDœ· ÷ëF—¸BßmžñÆ7èNÍ Š×WÆ­•nµšH:\Ê$VärQ&ñj¢f“¼*ñ¢¤G‘\™[ÔvÅß—y’yElHÞ)õü”Í$o÷ñˆŽÝìVüu©O"y~± Ù5íUüuɸí yÝ.Lò]áñô­Š¿-ý ·Í×'KÚiˆ{ö°·"äg¬Ô+¸6Ù£.’§ž€eT÷½_ñ£u½ÛÆûøúÊduÞ'¸™“tŽÓ¦{«{¿wƒ¾µ Y_ç8m ¹{ 2jû’õuŽSé3ˆ4¦B£¦R Y_ç8>NeR’ÏÑ9N¥ÏêT$¢sœŠŸŸ¬DòˆO$ëë§ Ï´W$Ÿ¡sœ6ü;# ù ñíÕ9N[þí§>wãNÍ'9qfËл`HÎó5è_Õ9›[¹œþïñ <¥¹€dkéMpö9,ÇTo¶ÝT¯“„ͽ\®ø7Rï:[MïíË‘l²·»í.²AþûY y­KÜ›é7Ä¿{kß[lýöÆ^B2µ¹—KÜ›)E2-c.%ùAÙ›Cƒä}ÃV2=Cüo–èFÒ[a]D²os#— ¹7S†do¯%y#—©§☃.w’LöxÂîM$;›?—ûÎ.Ü1—Q]®%Ùú${Ž9M²õI¶¤ÍvGá‚iòA—›H~WEô»1s}¼È\)²¹—Ë ÉcºÜDòå:Ç©€d½ƒ. ùã´Fòƒ. ùãTF²ÒA|ŒÎqZ%yÄA—£Ix Ôn:Ê)‡d«}Ð$Ÿ¡£œfžÜâvîFt9šd{Òðöé(§8[-OsÒøöé$§ ¹!Ï9ÃÛ)\H>D'9É yßNä$·$:fx{’ËÉ§è § ¹%Ñ9ãÛ«sœžG²ÉK;žžz ëéj§’¬UÅ¿`“>ûõ0OtºÆê§Ižú™ÓüÂU˜q×çû}ô²«E$s.«#œ~šäÉ2î×ßUÏprËTª‡ZêYŠœVî£ÉëªèÌH.k±Hžn5t ’µ; Ôñ¹¿3qKNºƒRÞizSr y‡8M9S${w³šÄz«?í<Iâ$ÏTDrá–¯½NÖ™r{}ÏŸùûè,HÞ!NSÎ ÉáßK²¾Sdjöçöwvù™+`ìig’ÝN‰±d@Éÿÿí‚»pdö8ÉÁRó¾+"Ù?*,LªÙAÃ7+"¹ZØt§ 9XJös?ýÞ£¢Ï‘aãýÐ+~0ÉÔ,¥×m\Œq{| Y9Îo;çoõ ÙŸ{~×ÞxG ÊkJ²oÖ† ÍZ·°:Ò«’'<#W{¼±$ëçj’GÆÉ£sêeÿ0ÉŒ@wÌ ’ÅÚ‚dF ƒ`’Œ]Z£hº]àôÃ$O?xß’o"ɚɣ; 5*›R‰Ê—Ù@rW¬i#ÜšIo.5åEN¿M²õTsyÇ9m­$¯Ð¼V»=Ç)HnÑ9ã{N~¼BçŒï9ùAò 3¾çäÉ+tÎøž“$¯Ð9ã{N~¼BçŒï9ùAò 3¾çäÉ+tÎøž“$¯Ð9ã{N~¼BçŒï9ùAò 3¾çäÉ+ôÔ¸rƸ{<½«¯…kTäÔV·q ’[dÈoòü8û‚Lý-n¼ØqµÛØ©ou§ ¹EÁÐY[!Ù°ÛSË´B±Ó2É뜂ä%H~žÌó>Æm®!™ZÝÇ)HnQd:[6Æ\Lò>N?C²*)’ÿÍÝ(z+«©ã;ØiduSO_ ÙískÝÌÆ Ùàiã;ÁiùK ’‡uŽŽõäNÕð’LövžÆÔmn€ï(§¾Õ%N“ºœäÄgª1Â9’­O²×hð±©iN}« œft7Éé¶ý#ìœÛñy÷åãí{ëöžÛižSßê|§9ÝLrþíýÔæQàeúŽÓ¼.&¹Ô°£‚Þç:³õ6ê)s?§ÝKr¹]?ÊíDɺÛ(|iÛ#H’uö¿–äZ³öv#ù;N‹º•äz«æ"vßj“^”›»Ëruöÿ.É(·v–æRhÑû¥mí-ÌÕÙÿR’û§—¥Ž;‘ü§ÝI²홞ӆWiêÐ…rk_iªÎþ&¹k|[»ŠSu¾/i•ê¸Óš®$YéðF¾ã>ã;ÞjkOq¦Îþ_&¹c|[;jgï$—´ É–œ±­1n¿ã´ªo“¼úãû§u}—äùÃÛ’óP’ÕÖ’gj É78­ $ÏÔwH–'É­áEE¼vtêMZï0ˆäç~=i¿¾¤=Ù,Hf¶ò4ô[òœœÐ_V<ñQIïqJÖþ®#’÷ÉÇ×äþ wT˾ã ’}‚dÎ#IöÖ[ö}¼ƒ˜d•ø`’ÉÈŠ|ê;­ $ç<ÛX·>"Xò()9ÉjÓ5’©Yû>‘Ë8—$œxÉ…÷„ŸÖ‰u²ðþc7¯Þ‹dßìk4X'‹çÉCw!äìûñ˜Hæd´¿µžæø²Ö·Œ&¾¿<ÉŒtORe§5]I²NCdzH2£+¾.rɾÙɂɅ¾Óšî$YgÅMg9’ß=>NUÞøò*«ßI…¥§QÉ’½GÎ:Ù$_6 $—›TH–î ±æÉ²5•F‹_+Éüygæ’ZÕçÉÏÈú˜weüŒ’ ±7%áT6‰dϬ;rLÍŠ|2‚äþf’=¹œz$ïé”ZeµÉ ÍD»Ôª’oOúöèÖ9•[ÉÙvɆn7ä’3Ü׫òõ Hµ¤ûÓóÇ·asÒ¾W`@òxM"9µZ¦G†¦ð0’Ou ’;Ó™ãän^ÉñÛhÉþNA² µ þôvfpÛ¥½‚¹TÑêžNA²¨ý»‰}ÿÿÍ9js(Û‹îH÷t§mVA2¯ù|ŽJ]Ã5“ü×ã § yµv&YW ¹(ÌŽ¾Ú-H. $³£¯v ’‹Éìè«Ý‚ä¢@2;új· ¹(ÌŽ¾Ú-H. $³£¯v ’‹Éìè«Ý‚䢓œ8ßäŸû¢-ÕÐ#É9«‡8Éõ3>ãgÜeœ&¦ñ4Ø>$Û¤ÕSœ‚dF«çR ë~‡ãkd÷½‹kh•pv‘°zŠSÌhõÌÂÑ5o› Ç·djõ§ ™Ñ*A2-#{4aºþŒ\⹟äe¯8§6°Úå$3Z=Ø¿;ö|Îh›¾ñµÌù ’}«ÃœVfä Y¹s†äà’]Û9¾$Ón$s ’‰f’Löv ®*ÉÅ9»ì8:£ylõçTqvá•gä¼’SmAr¦^ë“ì5ê?6Å™‘³ËŽ£3šÇVG:M~i‚äz#ã>fã܉f]5pfäܲÑë­VG:-ÏÈY%'Û‚äbð¸uòP1Hîp ’W+IraFn/#9š‘cv1»³’r$[Ÿä\IôÆ µ”%Ùffä yNg%yûR¬yj'Ÿ}¹ÛØimF.q ’WÊÛ’ŽÉy=]Âä•Éš’/›’åLÞ-H™!ù²I Y^ÀgHNÍ‚•$_6 $7T0oxA2[ ¹¡‚o‘<4Aòe“@rCŸ!¹ù$7;~òe“@rK Ó†wµ[\H.‡Ï¼^ ÁNAòb}‡äÆkAùá“/›’Í 5;Tu»S¬&ñG?#Ï’å”ÍÈ’ƒEñJÁ¸+yò½'a,MV Ù¹ ¬VœÎ¥à ¢ÖÎÐþ÷ûNC.®Ìöž=åæ+‘l§¾ÕšÓÉV[¾´ ùYü7˜’çïL13V¾mÁMG,’Ù%*©áK ’ŸÅ¿ÁŒï–Ìõ>dju7§ VAò³8ArñÆßÇ·x9H~P&VOp ’S‹P¹·8ï;¾\’¹·8¯p*· ’ŸÅi’ó7þÞFò^NArsgñ-Î’"ÔöýYqØ$G·8ëÌ.TÜ‚äÖÎâ[œI6n™ûz°Ïn©“l}’“=ÛI&6·ÃÁ "m’KßÏÚºƒ­‰OÞýÝX!Ùº<ñ4µÒ›Û(î@¾>Îê§^O¡O<ºsOC~Z²£E·ܤE*ëd±Zbfé†NÈh±=H_ijª{Q §ŸnGKLre#=ŸdÏì3ß¶ $צ# yxïšÖºù·ßÍ#Y0Oö¯©U6…äÀ¬5‘Ùw.%™'ׂäáE¸#†K2/©$¥^Ù ’C³e’¹I9NArb©\Å$°5’¹]"u&ÌHfO.ô«¬é’u‹O¬äIö^3’Ö®6ƒç$’tˆÎ"•Hæ¦Ï.z’3ïšgúø_’dážÐ¯Ï^$‡f+$3çQ¿n YØYŸä‡`c‡ÀµxÖØÜ!&_ƒ½H¦fÉacϬÀ'I ’…µI#Éê¬3HO ©X•$ÏÔwHæÏ¦µô]’W ð’÷u ’UBÎ_á=Á*7!HV 9{|•†$'õe’'0;›>Éìó:âgÉJ!ûÏ,È4€ä™,K2d½ò³ªMêwØmu’SM«}ždÅ&EŸ;Q8&§ Y9dW )’élÙÉciÃèò·uU#¹Ï)Hn©:þ)’ÿÍÝ(z+«©$vYíp ’e!Ý>·ÖÍl ’½žEò §å/-Hîíœ #êÉÊö’LövžÆÔÙÅ$§¾Õ>§ ™2±Xc„s$[Ÿd¯Ñà£p‰ðcœúVûœ‚dæÒÌGÚ?ÂÞȹãïù9Ç’<Ï©oµÏ)Hæ-ͧéýUwª¤ÑEÛ™½‚dÖÒâN`Gþ–ç:È2HßäÔw ’9KËIúQnPM |{´SœÕ ’k9ÚkX=¼áÛ;Éõ¥õÍEœFr7ÊÍÝ ôB}—äN”[;sâ‹Þî$ç5ždN†;H>Ú)H®-e%èÚè6÷å„—¼=Ö*H.k’»Æ·µ++¼àí³‚äÊRfü]ÇW@2·Ž«­=yáõB}™äŽñmí¨$'õi’-9c7ZÝ“oïèTѪDß&yð§1Õ’':}½ô²ÞH2x{êkÄõÉÃgMÂõÉ÷^µºLò¥Jf5-(ìÃ$O^¥Âä$oë$——>ÆÚ!•ÊN yAe y¦Ö¼¯S\^zúøÞ@òüÒ@òT±’‚ääŽJ܉î)e’Uâñôçê$7v–ŸÑ ùßó{ÉâsI~<ò|‚äæÎËHv#Ì9!pɼ ¹±³.Éïó1n­[fÝŸö}XÉ¡${fC^É $ÇÚŸägHŸÿžÿÿ¹•ñï÷Éódßlà”p‹yr¬ýIv èøþæÅ&CrgRn#±UN¼×ìKr`–ÌH ’›;F~ïàJ2™gØçÏßïতÜFÃH6”䨒7÷èM*jÅÒ$s2pHö·¹nFlŸ¿ž_íI¹Ä_Z&Éþì"4+ó ’›;ë“Ͻ…ö!Ùí-Øãc…dÄ#¾È÷–š¥$«Í£@r}ißø>ÓAÿN·Œ´¢»øõ!Þ’dÏ,ùe©Yë-­æÉ­£¥å•Ÿ!®Œd¨]é’;KH®ßnvÉ…ö¬ë@r»fœÙºÉÂ=$§;Ði‘BQB1ƒ‚dÖÒÄ2zÿoqUÖV[E:Û²•jÆ$yŒYÜÚ9³ZJ,"»i=e´hɧ:Éì¹V¨C¬÷V—–®sÊO’Ù!ƒmg° 4s€ù¹ÚöÐÂY‚ouêó.Ô¬Jt;ÉÖ?^ê~‘÷æ¨×!ãmêô÷{…S=«}€ä¿÷ý«;5v×wÔì$§ Y9¤R “¢Oµ ’‹É=ÑArR Y¯†IÑArR Y¯†IÑArR Y¯†IÑArR Y¯†IÑArR Y¯†IÑArR Y¯†IÑArR7’œ8ßäŸû¢-kÐ’€äœÕCœ‚äòÒ?hÿûýŒŸq—qú4žÛ‡d›´zŠS\_ê?A'M²áßóΪAKÂÙEÂê)NAr}és]îá肚·Í†ãÛF2µzŠS\_š"™Î–á?Ì-Ÿ?#—xî'ùAÙ+NÇ© ¬v9Éõ¥ï½wìùœÑ6}ãk™3ò$ûV‡9­ÌÈArgg&ÉÁ%»¶s|I¦ÝHæ$Í$™ìí„\U’‹3òlÙÕ茷VNg.QyF^/¿¹mE_ Ùú${úMqfäÙ²«Ño'¬ŽtšüÒ6:ÉÕ¥ïjˆNí莙׬«ÎŒ<[v5zýí”Õ‘NË3òzùÍm+º”äÁbð¸uòP1Hîp ’•CvÕÀ™‘Ë ÜŸähFŽÙ…Zç=H¶>ɹ.‚èò·u•%Ùffä ¹³ó2’™3òÔN>#zÃÛºŠÖfä§ Y9¤,?Ý’ŽÉÐõ¶¢†;ÉÊ!eùWJ’å|ä‘ôBdyŸ!95 VN  $7T°vxArR ¹¡‚o‘<4^(ÜPÁgHn>ÉÍŽ¯ $·”°txArR ¹¥„/‘<6¾^(ÜRÂÒáýU‰@²™!‡ýV÷s ’ÕBŠ?úF‰ò !y¢S=«}šäIƒ+M6‚äU—©µ¬êË$O]A>}’§~e­ D¬r6ÈìŒH–wé“Ò—V"ÉïÃO&Ù3ûçÈ7 ’Ó:€äwMëVMƽõï%ùìyr`ö]!ÛˆdÌ“}íOò;fÏ>ëà­u$ó’*\©Nrh–LötŸ†Ü¤V%Éé7ý!$$›° ™€t&ejÉÁ+™¥{|:IÕ’Óoº5¯Or<ênÓÜ›”©q$‡ëd“ ™›$7vVŸ'›gúø_0–Æ ¶òŸvŒú<Ù7ûLÁ´Ç§(œy×<ãHvé½};2Ñ3Ü!VÞ$S³ïaãÀ¬ÀgK•½É3µ)É#’;ƒäÁY·Ïù]’W ð’u*Hž(Œ'X]ðÝù0ÉÓ?n¥| 9©/“<ùó¦Ù繞£þ¡Äi°¦/íT«4[Î)˪DŸ&¹÷ÃkÏôÍ þéöçh.éC¸¹UžSžU‰¾M² Öã”ÌüËoßßáðšÔùáÍ­òœò¬Jôy’kù æsš±ÑŠ3y&bîDA%Hì”gU"¬Wƒ4H~|½5Ü$ÓÙ²1’k¼3Éz5Hƒ<X“ý÷Ì/#Ùwʰ*HÖ«A¤>¾w“\·*HÖ«AäÝéy÷v~›Ý[gt¿.œEdJ5Hƒñµ>É´ÒQ¸Frʳ*HÖ«AãÝåùmxͳŽJ´ÒNÎÖ(§<«d½nL¾Ô©H ¹§†Ä)²ÆTà’é„¶|~}ü ¹§7¿-ŸÀŠþÒH>E±ÓÊùuÜÙyÝì‚s*6úK+ùpÅNA2Ñ$OÅÚ«H._· ¹³ó^$‡§bU ÜŠä¡NEɽ5pNÅÚ»H.œ_· ¹³óv$‡|/É㜊’{kàœŠU-p’£óë˜]¨uÞƒd드뢗|¸²$[ä\—‰É50OŦvòû“Wì´v~]Ñ©H Y¯†“/u*Ì›N¤ IDATHÖ«áÆä ¹(|Lr\H>&9H. $“$u4ÉÁUœó5ßê´„=Éò/HN $Ë øÉÓòu $Ë ø É©óÛ $7T°vxg“Áó¿5î%Øw,C’ÛŠ—Ij•Gòïç66KHV«RO·ÜpÑb)AŠdã—d}ÿQñ"é9µy’Sfý5w­Êvƒmº†dfçöu2™dD$“éæÀâeêZ''Í |‚äáÝJŠE2™9Ò–y7Áæý9m)†S™ýYK›¥$O™G‰ôA’kq蟻ø. ýfp†x2Éõ¤¡YûºŒÍÚwÙ¤y”HŸ#™gÀXÌ^Sf›Æô“ô1’%q'Y–U»²ùNAòðDcC*¥ÉMÚ‚äZ òÑ«‡‰q¤AÛ,HÜyP¤].K¼Àé—Ižüy¯¹yþ—ûêtÿôi’KX!<ïbˆ¶!¹áÌo³4ËÞÛé«'Y7ÓjZ›Ô[ô.¦A²b¦]U$Ü!¼‘@r‡@òFÉÉ $w$o$Ü!¼‘@r‡@òFÉÉ $wh ɉÓP†Þåh"™ŸeÌÉ0—;(@Íe˜PœxŒñ/‘lí{›ÚoÝÝ•z$s³<{Q–Ëï ç2‘P”xñ‘ü¯óßç:dnü۾E^âY$s2þM’Ÿ[ÝŸÍ~:G/ÉÅ,Ì[”›ô€D Ðs™ŒÂO<Ê8Hö汆ÞW¯Jr˜e6ÉQÄæ’gÿ(Éÿ&kîUÜããf™B²_ÀØ=>nb¬Ó9ÍX8ÈcHö², YÉe˜L˜$ët~'nÇÃÛèªÎ.JYæì øåŸ4»ˆcv¡Ü™0f}Æâ*$g³˜1£H¯=—a2iâAÆ¿Eò³2ú}Ât_$l×’ÉmK9Y¢¬Zz·,´=—a6qâ1Æ¿EòàLóJS”æ:y¥@²b¦]U$Ü!¼‘@r‡@òFÉÉ $w$o$Ü!¼‘@r‡@òFÉÉ $w$o$Ü!¼‘@r‡Î"™™À.ƒ*HîÐI$'®¼)w8M ¹CÇì]´Ìép @r‡úH†tµr0uÉ%íS|©jÓ ¹(\Õ.¦ArM ¹¬]Lƒd†@rA»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠºÕWQ»˜ÉŠz}úgvÔ.VA²¢Ä¸A»XÉŠúÏ—Îmži« YQz7,¤]¬.!wúߤ%ÅZCòµÚmx?$¬,¼H Y_ y…@òäéÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉÐÉКIò¿§LEÏx4~ƒ÷ öà ¥ÏûáFÍTJ–5>iÈ;ú±÷†ûxý µLÒÔuòŸØóÿóñ‘Oñ‡‡ñ³Æ¢¥Žb¿R¥®{+ÊïQb“lAr‹þ!`_dË( nyÔ0T<þWF\©ë¾-É|mRF¿¦“L[ú\Ë‘iØŒßDd½ÊTúþ¬§Nµ¨“l²T» ›ä¥HNM3¢/FÏL›4!Þ6áoòË…ýMž×þ=, ®ÔŸùÄIŸ¿IŠ—Íý0Oï ý.Žþ°™˜o„÷O×,Q–_µßæï“HÅ7-ÀYÚŽdÓ`¦ñ@/¦&ùßëCQio8`>U©¿^wsêpòñv!5¼$ÍÐ,qú½!1ÃÆ4…q£²‚ÏŽ¾chM~|u?-&™ŒOj–A×BÆûÜãï(<¿½>Ѫˆ åÑbýéJÉú‘ü2aÀ'˜ ’Ðg=Ôkó¼ð¾ûþ«€p¯(ú¿I„ ^ì¨Õ$“CZÑ› £µ‚‰`Häã¿-ä¸Rš-0E²ÿe‹ú_VçÌÛªµ±AÃÉAI!Éq¤d|üŸ"X)c&&.aR™äÌ÷t·á e[Ž'™n"Lh˜%XÅ“cw’é<"®${ÊüLË8$ód ^ ¼à“L§Èñò(`HòKðó;Er O‘äèEjžœ\Ù¦æì‹ýéHdL™d›Úv{=']ݺ÷Sÿ»>ñ¾ýɰeP*MNäC‚| T^ƒ®·Z/ž×Ô‹ÁÓŸ>èï-$ãƒd÷Uÿ{峛ؕò>MÞÃR®¥‹ýuŠwôÊx½Œ"X/p¡R¯{äŽ|ÿÃOçÇy›¸C_¾ëwÌÌ’â¢ÔaYÞçíe³t¡WƒqÅl(\A”s´vÕßÕc’Óâäyã]—!?OHΈ3”ç 7CtB~’@2èȹH†nH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îH†îÐÿŽ§Ž–Ê—IEND®B`‚openocd-0.9.0/doc/manual/server.txt0000644000175000017500000003107712315575360014200 00000000000000/** @page serverdocs OpenOCD Server APIs OpenOCD provides support for implementing different types of servers. Presently, the following servers have APIs that can be used. - @subpage servergdb - @subpage servertelnet - @subpage serverhttp @section serverdocsoverview Overview What follows is a development history, and describes some of the intent of why certain features exist within OpenOCD along with the reasoning behind them. This roadmap section was written May 2009 - about 9 to 12 months after some of this work had started, it attempts to document some of the reasons why certain features exist within OpenOCD at that time. @section serverdocsbg Background In early 2008, Oyvind Harboe and Duane Ellis had talked about how to create a reasonable GUI for OpenOCD - something that is non-invasive, simple to use and maintain, and does not tie OpenOCD to many other packages. It would be wrong to "spider web" requirements into other external external packages. That makes it difficult for developers to write new code and creates a support nightmare. In many ways, people had talked about the need for some type of high-level interface to OpenOCD, because they only had two choices: - the ability to script: via an external program the actions of OpenOCD. - the ablity to write a complex internal commands: native 'commands' inside of OpenOCD was complicated. Fundamentally, the basic problem with both of those would be solved with a script language: -# Internal: simple, small, and self-contained. -# Cross Language: script friendly front-end -# Cross Host: GUI Host interface -# Cross Debugger: GUI-like interface What follows hopefully shows how the plans to solve these problems materialized and help to explain the grand roadmap plan. @subsection serverdocsjim Why JimTCL? The Internal Script Language At the time, the existing "command context schema" was proving itself insufficient. However, the problem was also considered from another direction: should OpenOCD be first class and the script second class? Which one rules? In the end, OpenOCD won, the conclusion was that simpler will be better. Let the script language be "good enough"; it would not need numerous features. Imagine debugging an embedded Perl module while debugging OpenOCD. Yuck. OpenOCD already has a complex enough build system, why make it worse? The goal was to add a simple language that would be moderately easy to work with and be self-contained. JimTCL is a single C and single H file, allowing OpenOCD to avoid the spider web of dependent packages. @section serverdocstcl TCL Server Port The TCL Server port was added in mid-2008. With embedded TCL, we can write scripts internally to help things, or we can write "C" code that interfaces well with TCL. From there, the developers wanted to create an external front-end that would be @a very usable and that that @a any language could utilize, allowing simple front-ends to be (a) cross-platform (b) languag agnostic, and (c) easy to develop and use. Simple ASCII protocols are easy. For example, HTTP, FTP (control), and SMTP are all text-based. All of these examples are widely and well-known, and they do not require high-speed or high-volume. They also support a high degree of interoperability with multiple systems. They are not human-centric protocols; more correctly, they are rigid, terse, simple ASCII protocols that are emensely parsable by a script. Thus, the TCL server -- a 'machine' type socket interface -- was added with the hope was it would output simple "name-value" pair type data. At the time, simple name/value pairs seemed reasonably easier to do at the time, though Maybe it should output JSON; See here: http://www.mail-archive.com/openocd-development%40lists.berlios.de/msg00248.html The hope was that one could write a script in what ever language you want and do things with it! @section serverdocsgui GUI Like Interfaces A lot has been said about various "widigit-foo-gui-library is so wonderful". Please refer back to the domino and spider web problem of dependencies. Sure, you may well know the WhatEver-GUI library, but most others will not (including the next contributer to OpenOCD). How do we solve that problem? For example, Cygwin can be painful, Cygwin GUI packages want X11 to be present, crossing the barrier between MinGW and Cygwin is painful, let alone getting the GUI front end to work on MacOS, and Linux, yuck yuck yuck. Painful. very very painful. What works easier and is less work is what is already present in every platform? The answer: A web browser. In other words, OpenOCD could serve out embedded web pages via "localhost" to your browser. Long before OpenOCD had a TCL command line, Zylin AS built their ZY1000 devince with a built-in HTTP server. Later, they were willing to both contribute and integrate most of that work into the main tree. @subsection serverdocsother Other Options Considered What if a web browser is not acceptable ie: You want to write your own front gadget in Eclipse, or KDevelop, or PerlTK, Ruby, or what ever the latest and greatest Script De Jour is. - Option 1: Can we transport this extra data through the GDB server protocol? In other words, can we extend the GDB server protocol? No, Eclipse wants to talk to GDB directly and control the GDB port. - Option 2: SWIG front end (libopenocd): Would that work? That's painful - unless you design your api to be very simplistic - every language has it's own set of wack-ness, parameter marshaling is painful. What about "callbacks" and structures, and other mess. Imagine debugging that system. When JimTCL was introduced Spencer Oliver had quite a few well-put concerns (Summer 2008) about the idea of "TCL" taking over OpenOCD. His concern is and was: how do you debug something written in 2 different languages? A "SWIG" front-end is unlikely to help that situation. @subsection serverdoccombined Combined: Socket & WebServer Benifits Seriously think about this question: What script language (or compiled language) today cannot talk directly to a socket? Every thing in the OpenOCD world can work a socket interface. Any host side tool can talk to Localhost or remote host, however one might want to make it work. A socket interface is very simple. One could write a Java application and serve it out via the embedded web server, could it - or something like it talk to the built in TCL server? Yes, absolutely! We are on to something here. @subsection serverdocplatforms Platform Permuntations Look at some permutations where OpenOCD can run; these "just work" if the Socket Approach is used. - Linux/Cygwin/MinGw/MacOSx/FreeBSD development Host Locally - OpenOCD with some dongle on that host - Linux/Cygwin/MingW/MacOS/FreeBSD development host - DONGLE: tcpip based ARM-Linux perhaps at91rm9200 or ep93xx.c, running openocd. - Windows cygwin/X desktop environment. - Linux development host (via remote X11) - Dongle: "eb93xx.c" based linux board @subsection serverdocfuture Development Scale Out During 2008, Duane Ellis created some TCL scripts to display peripheral register contents. For example, look at the sam7 TCL scripts, and the stm32 TCL scripts. The hope was others would create more. A good example of this is display/view the peripheral registers on your embedded target. Lots of commercial embedded debug tools have this, some can show the TIMER registers, the interrupt controller. What if the chip companies behind STM32, or PIC32, AT91SAM chips - wanted to write something that makes working with their chip better, easier, faster, etc. @a Question: How can we (the OpenOCD group) make that really fancy stuff across multiple different host platforms? Remember: OpenOCD runs on: -# Linux via USB, -# ARM Linux - bit-banging GPIO pins -# MacOSX -# FreeBSD -# Cygwin -# MinGW32 -# Ecos How can we get that to work? @subsection serverdocdebug What about Debugger Plugins? Really GDB is nice, it works, but it is not a good embedded debug tool. OpenOCD cannot work in a GUI when one cannot get to its command line. Some GDB front-end developers have pedantic designs that refuse any and all access to the GDB command line (e.g. http://www.kdbg.org/todo.php). The TELNET interface to OpenOCD works, but the intent of that interface is human interaction. It must remain available, developers depend upon it, sometimes that is the only scheme available. As a small group of developers, supporting all the platforms and targets in the debugger will be difficult, as there are enough problem with the plethora of Adapters, Chips, and different target boards. Yes, the TCL interface might be suitable, but it has not received much love or attention. Perhaps it will after you read and understand this. One reason might be, this adds one more host side requirement to make use of the feature. In other words, one could write a Python/TK front-end, but it is only useable if you have Python/TK installed. Maybe this can be done via Ecllipse, but not all developers use Ecplise. Many devlopers use Emacs (possibly with GUD mode) or vim and will not accept such an interface. The next developer reading this might be using Insight (GDB-TK) - and somebody else - DDD.. There is no common host-side GDB front-end method. @section serverdocschallenge Front-End Scaling Maybe we are wrong - ie: OpenOCD + some TK tool Remember: OpenOCD is often (maybe 99.9%) of the time used with GDB-REMOTE. There is always some front-end package - be it command-line GDB under DDD, Eclipse, KDevelop, Emacs, or some other package (e.g. IAR tools can talk to GDB servers). How can the OpenOCD developers make that fancy target display GUI visible under 5 to 10 different host-side GDB.. Sure - a man on a mission can make that work. The GUI might be libopenocd + Perl/TK, or maybe an Eclipse Plug-in. That is a development support nightmare for reasons described above. We have enough support problems as it is with targets, adapters, etc. @section serverdocshttpbg HTTP Server Background OpenOCD includes an HTTP server because most development environments are likely contain a web browser. The web browser can talk to OpenOCD's HTTP server and provide a high-level interfaces to the program. Altogether, it provides a universally accessible GUI for OpenOCD. @section serverdocshtml Simple HTML Pages There is (or could be) a simple "Jim TCL" function to read a memory location. If that can be tied into a TCL script that can modify the HTTP text, then we have a simple script-based web server with a JTAG engine under the hood. Imagine a web page - served from a small board with two buttons: "LED_ON" and "LED_OFF", each click - turns the LED on or OFF, a very simplistic idea. Little boards with web servers are great examples of this: Ethernut is a good example and Contiki (not a board, an embedded OS) is another example. One could create a simple: Click here to display memory or maybe click here to display the UART REGISTER BLOCK; click again and see each register explained in exquisit detail. For an STM32, one could create a simple HTML page, with simple substitution text that the simple web server use to substitute the HTML text JIMTCL_PEEK32( 0x12345678 ) with the value read from memory. We end up with an HTML page that could list the contents of every peripheral register on the target platform. That also is transportable, regardless of the OpenOCD host platform: Linux/X86, Linux/ARM, FreeBSD, Cygwin, MingW, or MacOSX. You could even port OpenOCD to an Android system and use it as a bit-banging JTAG Adapter serving web pages. @subsection serverdocshtmladv Advanced HTML Pages Java or JavaScript could be used to talk back to the TCL port. One could write a Java, AJAX, FLASH, or some other developer friendly toolbox and get a real cross-platform GUI interface. Sure, the interface is not native - but it is 100% cross-platform! OpenOCD current uses simple HTML pages; others might be an Adobe FLASH expert, or a Java Expert. These possibilities could allow the pages remain cross-platform but still provide a rich user-interface experience. Don't forget it can also be very simple, exactly what one developer can contribute, a set of very simple web pages. @subsection serverdocshtmlstatus HTTP/HTML Status As of May 2009, much of the HTML pages were contributed by Zylin AS, hence they continue to retain some resemblance to the ZY1000 interface. Patches would be welcome to move these parts of the system forward. */ /** @page servergdb OpenOCD GDB Server API This section needs to be expanded. */ /** @page servertelnet OpenOCD Telnet Server API This section needs to be expanded. */ /** @page serverhttp OpenOCD http Server API This section needs to be expanded. */ openocd-0.9.0/doc/manual/primer/0000755000175000017500000000000012315575360013477 500000000000000openocd-0.9.0/doc/manual/primer/commands.txt0000644000175000017500000001042112315575360015757 00000000000000/** @page primercommand Command Development Primer This page provides a primer for writing commands by introducing @c hello module. The full source code used in this example can be found in hello.c, and the @ref primercmdcode section shows how to use it. A summary of this information can be found in @ref helpercommand . @section primercmdhandler Command Handlers Defining new commands and their helpers is easy. The following code defines a simple command handler that delegates its argument parsing: @code COMMAND_HANDLER(handle_hello_command) { const char *sep, *name; int retval = CALL_COMMAND_HANDLER(handle_hello_args); if (ERROR_OK == retval) command_print(CMD_CTX, "Greetings%s%s!", sep, name); return retval; } @endcode Here, the @c COMMAND_HANDLER macro establishes the function signature, see in command.h by the @c __COMMAND_HANDLER macro. The COMMAND_HELPER macro function allows defining functions with an extended version of the base signature. These helper functions can be called (with the appropriate parameters), the @c CALL_COMMAND_HANDLER macro to pass any e as parameters to the following helper function: The subsequent blocks of code are a normal C function that can do anything, so only complex commands deserve should use comamnd helper functions. In this respect, this example uses one to demonstrate how -- not when -- they should be used. @code static COMMAND_HELPER(handle_hello_args, const char **sep, const char **name) { if (argc > 1) { LOG_ERROR("%s: too many arguments", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } if (1 == CMD_ARGC) { *sep = ", "; *name = CMD_ARGV[0]; } else *sep = *name = ""; return ERROR_OK; } @endcode Of course, you may also call other macros or functions, but that extends beyond the scope of this tutorial on writing commands. @section primercmdreg Command Registration Before this new function can be used, it must be registered somehow. For a new module, registering should be done in a new function for the purpose, which must be called from @c openocd.c: @code static const struct command_registration hello_command_handlers[] = { { .name = "hello", .mode = COMMAND_ANY, .handler = handle_hello_command, .help = "print a warm greeting", .usage = "[name]", }, { .chain = foo_command_handlers, } COMMAND_REGISTRATION_DONE }; int hello_register_commands(struct command_context_s *cmd_ctx) { return register_commands(cmd_ctx, NULL, handle_command_handlers); } @endcode Note that the "usage" text should use the same EBNF that's found in the User's Guide: literals in 'single quotes', sequences of optional parameters in [square brackets], and alternatives in (parentheses|with|vertical bars), and so forth. No angle brackets. That's it! The command should now be registered and available to scripts. @section primercmdchain Command Chaining This example also shows how to chain command handler registration, so your modules can "inherit" commands provided by other (sub)modules. Here, the hello module includes the foo commands in the same context that the 'hello' command will be registered. If the @c chain field had been put in the 'hello' command, then the @c foo module commands would be registered under it. Indeed, that technique is used to define the 'foo bar' and 'foo baz' commands, as well as for the example drivers that use these modules. The code for the 'foo' command handlers can be found in @c hello.c. @section primercmdcode Trying These Example Commands These commands have been inherited by the dummy interface, faux flash, and testee target drivers. The easiest way to test these is by using the dummy interface. Once OpenOCD has been built with this example code, the following command demonstrates the abilities that the @c hello module provides: @code openocd -c 'interface dummy' \ -c 'dummy hello' \ -c 'dummy hello World' \ -c 'dummy hello {John Doe}' \ -c 'dummy hello John Doe' # error: too many arguments @endcode If saved in @c hello.cfg, then running openocd -f hello.cfg should produce the following output before displaying the help text and exiting: @code Greetings! Greetings, World! Greetings, John Doe! Error: hello: too many arguments Runtime error, file "openocd.cfg", line 14: hello: too many arguments dummy hello [] prints a warm welcome @endcode */ openocd-0.9.0/doc/manual/primer/jtag.txt0000644000175000017500000001512212315575360015106 00000000000000/** @page primerjtag OpenOCD JTAG Primer JTAG is unnecessarily confusing, because JTAG is often confused with boundary scan, which is just one of its possible functions. JTAG is simply a communication interface designed to allow communication to functions contained on devices, for the designed purposes of initialisation, programming, testing, debugging, and anything else you want to use it for (as a chip designer). Think of JTAG as I2C for testing. It doesn't define what it can do, just a logical interface that allows a uniform channel for communication. See @par http://en.wikipedia.org/wiki/Joint_Test_Action_Group @image html jtag-state-machine-large.png The first page (among other things) shows a logical representation describing how multiple devices are wired up using JTAG. JTAG does not specify, data rates or interface levels (3.3V/1.8V, etc) each device can support different data rates/interface logic levels. How to wire them in a compatible way is an exercise for an engineer. Basically TMS controls which shift register is placed on the device, between TDI and TDO. The second diagram shows the state transitions on TMS which will select different shift registers. The first thing you need to do is reset the state machine, because when you connect to a chip you do not know what state the controller is in,you need to clock TMS as 1, at least 5 times. This will put you into "Test Logic Reset" State. Knowing this, you can, once reset, then track what each transition on TMS will do, and hence know what state the JTAG state machine is in. There are 2 "types" of shift registers. The Instruction shift register and the data shift register. The sizes of these are undefined, and can change from chip to chip. The Instruction register is used to select which Data register/data register function is used, and the data register is used to read data from that function or write data to it. Each of the states control what happens to either the data register or instruction register. For example, one of the data registers will be known as "bypass" this is (usually) a single bit which has no function and is used to bypass the chip. Assume we have 3 identical chips, wired up like the picture(wikipedia) and each has a 3 bits instruction register, and there are 2 known instructions (110 = bypass, 010 = "some other function") if we want to use "some other function", on the second chip in the line, and not change the other chips we would do the following transitions. From Test Logic Reset, TMS goes: 0 1 1 0 0 which puts every chip in the chain into the "Shift IR state" Then (while holding TMS as 0) TDI goes: 0 1 1 0 1 0 0 1 1 which puts the following values in the instruction shift register for each chip [110] [010] [110] The order is reversed, because we shift out the least significant bit first. Then we transition TMS: 1 1 1 0 0 which puts us in the "Shift DR state". Now when we clock data onto TDI (again while holding TMS to 0) , the data shifts through the data registers, and because of the instruction registers we selected ("some other function" has 8 bits in its data register), our total data register in the chain looks like this: 0 00000000 0 The first and last bit are in the "bypassed" chips, so values read from them are irrelevant and data written to them is ignored. But we need to write bits for those registers, because they are in the chain. If we wanted to write 0xF5 to the data register we would clock out of TDI (holding TMS to 0): 0 1 0 1 0 1 1 1 1 0 Again, we are clocking the least-significant bit first. Then we would clock TMS: 1 1 0 which updates the selected data register with the value 0xF5 and returns us to run test idle. If we needed to read the data register before over-writing it with F5, no sweat, that's already done, because the TDI/TDO are set up as a circular shift register, so if you write enough bits to fill the shift register, you will receive the "captured" contents of the data registers simultaneously on TDO. That's JTAG in a nutshell. On top of this, you need to get specs for target chips and work out what the various instruction registers/data registers do, so you can actually do something useful. That's where it gets interesting. But in and of itself, JTAG is actually very simple. @section primerjtag More Reading A separate primer contains information about @subpage primerjtagbs for developers that want to extend OpenOCD for such purposes. */ /** @page primerjtagbs JTAG Boundary Scan Primer The following page provides an introduction on JTAG that focuses on its boundary scan capabilities: @par http://www.engr.udayton.edu/faculty/jloomis/ece446/notes/jtag/jtag1.html OpenOCD does not presently have clear means of using JTAG for boundary scan testing purposes; however, some developers have explored the possibilities. The page contains information that may be useful to those wishing to implement boundary scan capabilities in OpenOCD. @section primerbsdl The BSDL Language For more information on the Boundary Scan Description Language (BSDL), the following page provides a good introduction: @par http://www.radio-electronics.com/info/t_and_m/boundaryscan/bsdl.php @section primerbsdlvendors Vendor BSDL Files NXP LPC: @par http://www.standardics.nxp.com/support/models/lpc2000/ Freescale PowerPC: @par http://www.freescale.com/webapp/sps/site/overview.jsp?code=DRPPCBSDLFLS Freescale i.MX1 (too old): @par http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=i.MX1&nodeId=0162468rH311432973ZrDR&fpsp=1&tab=Design_Tools_Tab Renesas R32C/117: @par http://sg.renesas.com/fmwk.jsp?cnt=r32c116_7_8_root.jsp&fp=/products/mpumcu/m16c_family/r32c100_series/r32c116_7_8_group/ - The device page does not come with BSDL file; you have to register to download them. @par http://www.corelis.com/support/BSDL.htm TI links theirs right off the generic page for each chip; this may be the case for other vendors as well. For example: - DaVinci DM355 -- http://www.ti.com/litv/zip/sprm262b - DaVinci DM6446 - 2.1 silicon -- http://www.ti.com/litv/zip/sprm325a - older silicon -- http://www.ti.com/litv/zip/sprm203 - OMAP 3530 - CBB package -- http://www.ti.com/litv/zip/sprm315b - 515 ball s-PGBA, POP, 0.4mm pitch - CUS package -- http://www.ti.com/litv/zip/sprm314a - 515 ball s-PGBA, POP, 0.5mm pitch - CBC package -- http://www.ti.com/litv/zip/sprm346 - 423 ball s-PGBA, 0.65mm pitch Many other files are available in the "Semiconductor Manufacturer's BSDL files" section of the following site: @par http://www.freelabs.com/~whitis/electronics/jtag/ */ /** @file This file contains the @ref primerjtag and @ref primerjtagbs page. */ openocd-0.9.0/doc/manual/primer/tcl.txt0000644000175000017500000002770412315575360014754 00000000000000/** @page primertcl OpenOCD TCL Primer The @subpage scripting page provides additional TCL Primer material. @verbatim **************************************** **************************************** This is a short introduction to 'un-scare' you about the language known as TCL. It is structured as a guided tour through the files written by me [Duane Ellis] - in early July 2008 for OpenOCD. Which uses the "JIM" embedded Tcl clone-ish language. Thing described here are *totally* TCL generic... not Jim specific. The goal of this document is to encourage you to add your own set of chips to the TCL package - and most importantly you should know where you should put them - so they end up in an organized way. --Duane Ellis. duane@duaneellis.com **************************************** **************************************** Adding "chip" support - Duane Ellis July 5 - 2008. The concept is this: In your "openocd.cfg" file add something like this: source [find tcl/chip/VENDOR/FAMILY/NAME.tcl] For example... source [find tcl/chip/atmel/at91/at91sam7x256.tcl] You'll notice that it makes use of: tcl/cpu/arm/.tcl. Yes, that is where you should put "core" specific things. Be careful and learn the difference: THE "CORE" - is not the entire chip! Definition: That "file" listed above is called a "CHIP FILE". It may be standalone, or may need to "source" other "helper" files. The reference [7/5/2008] is the at91sam7x256.tcl file. **************************************** **************************************** === TCL TOUR === Open: at91sam7x256.tcl === TCL TOUR === A walk through --- For those who are new to TCL. Examine the file: at91sam7x256.tcl It starts with: source [find path/filename.tcl] In TCL - this is very important. Rule #1 Everything is a string. Rule #2 If you think other wise See #1. Reminds you of: Rule #1: The wife is correct. Rule #2: If you think otherwise, See #1 Any text contained inside of [square-brackets] is just like `back-ticks` in BASH. Hence, the [find FILENAME] executes the command find with a single parameter the filename. ======================================== Next you see a series of: set NAME VALUE It is mostly "obvious" what is going on. Exception: The arrays. You would *THINK* Tcl supports arrays. In fact, multi-dim arrays. That is false. For the index for"FLASH(0,CHIPSELECT)" is actually the string "0,CHIPSELECT". This is problematic. In the normal world, you think of array indexes as integers. For example these are different: set foo(0x0c) 123 set foo(12) 444 Why? Because 0x0c {lowercase} is a string. Don't forget UPPER CASE. You must be careful - always... always... use simple decimal numbers. When in doubt use 'expr' the evaluator. These are all the same. set x 0x0c set foo([expr $x]) "twelve" set x 12 set foo([expr $x]) "twelve" set x "2 * 6" set foo([expr $x]) "twelve" ************************************************** *************************************************** === TCL TOUR === Open the file: "bitsbytes.tcl" There is some tricky things going on. =============== First, there is a "for" loop - at level 0 {level 0 means: out side of a proc/function} This means it is evaluated when the file is parsed. == SIDEBAR: About The FOR command == In TCL, "FOR" is a funny thing, it is not what you think it is. Syntactically - FOR is a just a command, it is not language construct like for(;;) in C... The "for" command takes 4 parameters. (1) The "initial command" to execute. (2) the test "expression" (3) the "next command" (4) the "body command" of the FOR loop. Notice I used the words "command" and "expression" above. The FOR command: 1) executes the "initial command" 2) evaluates the expression if 0 it stops. 3) executes the "body command" 4) executes the "next command" 5) Goto Step 2. As show, each of these items are in {curly-braces}. This means they are passed as they are - KEY-POINT: un evaluated to the FOR command. Think of it like escaping the backticks in Bash so that the "under-lying" command can evaluate the contents. In this case, the FOR COMMAND. == END: SIDEBAR: About The FOR command == You'll see two lines: LINE1: set vn [format "BIT%d" $x] Format is like "sprintf". Because of the [brackets], it becomes what you think. But here's how: First - the line is parsed - for {braces}. In this case, there are none. The, the parser looks for [brackets] and finds them. The, parser then evaluates the contents of the [brackets], and replaces them. It is alot this bash statement. EXPORT vn=`date` LINE 2 & 3 set $vn [expr (1024 * $x)] global $vn In line 1, we dynamically created a variable name. Here, we are assigning it a value. Lastly Line 3 we force the variable to be global, not "local" the the "for command body" =============== The PROCS proc create_mask { MSB LSB } { ... body .... } Like "for" - PROC is really just a command that takes 3 parameters. The (1) NAME of the function, a (2) LIST of parameters, and a (3) BODY Again, this is at "level 0" so it is a global function. (Yes, TCL supports local functions, you put them inside of a function} You'll see in some cases, I nest [brackets] alot and in others I'm lazy or wanted it to be more clear... it is a matter of choice. =============== ************************************************** *************************************************** === TCL TOUR === Open the file: "memory.tcl" =============== Here is where I setup some 'memory definitions' that various targets can use. For example - there is an "unknown" memory region. All memory regions must have 2 things: (1) N_ (2) NAME( array ) And the array must have some specific names: ( , THING ) Where: THING is one of: CHIPSELECT BASE LEN HUMAN TYPE RWX - the access ability. WIDTH - the accessible width. ie: Some regions of memory are not 'word' accessible. The function "address_info" - given an address should tell you about the address. [as of this writing: 7/5/2008 I have done only a little bit with this -Duane] === MAJOR FUNCTION: == proc memread32 { ADDR } proc memread16 { ADDR } proc memread8 { ADDR } All read memory - and return the contents. [ FIXME: 7/5/2008 - I need to create "memwrite" functions] ************************************************** *************************************************** === TCL TOUR === Open the file: "mmr_helpers.tcl" =============== This file is used to display and work with "memory mapped registers" For example - 'show_mmr32_reg' is given the NAME of the register to display. The assumption is - the NAME is a global variable holding the address of that MMR. The code does some tricks. The [set [set NAME]] is the TCL way of doing double variable interpolation - like makefiles... In a makefile or shell script you may have seen this: FOO_linux = "Penguins rule" FOO_winXP = "Broken Glass" FOO_mac = "I like cat names" # Pick one BUILD = linux #BUILD = winXP #BUILD = mac FOO = ${FOO_${BUILD}} The "double [set] square bracket" thing is the TCL way, nothing more. ---- The IF statement - and "CATCH" . Notice this IF COMMAND - (not statement) is like this: [7/5/2008 it is this way] if ![catch { command } msg ] { ...something... } else { error [format string...] } The "IF" command expects either 2 params, or 4 params. === Sidebar: About "commands" === Take a look at the internals of "jim.c" Look for the function: Jim_IfCoreCommand() And all those other "CoreCommands" You'll notice - they all have "argc" and "argv" Yea, the entire thing is done that way. IF is a command. SO is "FOR" and "WHILE" and "DO" and the others. That is why I keep using the phase it is a "command" === END: Sidebar: About "commands" === Parameter 1 to the IF command is expected to be an expression. As such, I do not need to wrap it in {braces}. In this case, the "expression" is the result of the "CATCH" command. CATCH - is an error catcher. You give CATCH 1 or 2 parameters. The first 1st parameter is the "code to execute" The 2nd (optional) is where to put the error message. CATCH returns 0 on success, 1 for failure. The "![catch command]" is self explaintory. The 3rd parameter to IF must be exactly "else" or "elseif" [I lied above, the IF command can take many parameters they just have to be joined by exactly the words "else" or "elseif". The 4th parameter contains: "error [format STRING....]" This lets me modify the previous lower level error by tacking more text onto the end of it. In this case, i want to add the MMR register name to make my error message look better. --------- Back to something inside show_mmr32_reg{}. You'll see something 'set fn show_${NAME}_helper' Here I am constructing a 'function name' Then - I look it up to see if it exists. {the function: "proc_exists" does this} And - if it does - I call the function. In "C" it is alot like using: 'sprintf()' to construct a function name string, then using "dlopen()" and "dlsym()" to look it up - and get a function pointer - and calling the function pointer. In this case - I execute a dynamic command. You can do some cool tricks with interpretors. ---------- Function: show_mmr32_bits() In this case, we use the special TCL command "upvar" which tcl's way of passing things by reference. In this case, we want to reach up into the callers lexical scope and find the array named "NAMES" The rest of the function is pretty straight forward. First - we figure out the longest name. Then print 4 rows of 8bits - with names. ************************************************** *************************************************** === TCL TOUR === Open the file: "chips/atmel/at91/usarts.tcl" =============== First - about the AT91SAM series - all of the usarts are basically identical... Second - there can be many of them. In this case - I do some more TCL tricks to dynamically create functions out of thin air. Some assumptions: The "CHIP" file has defined some variables in a proper form. ie: AT91C_BASE_US0 - for usart0, AT91C_BASE_US1 - for usart1 ... And so on ... Near the end of the file - look for a large "foreach" loop that looks like this: foreach WHO { US0 US1 US2 US3 US4 .... } { } In this case, I'm trying to figure out what USARTs exist. Step 1 - is to determine if the NAME has been defined. ie: Does AT91C_BASE_USx - where X is some number exist? The "info exists VARNAME" tells you if the variable exists. Then - inside the IF statement... There is another loop. This loop is the name of various "sub-registers" within the USART. Some more trick are played with the [set VAR] backtick evaluation stuff. And we create two variables We calculate and create the global variable name for every subregister in the USART. And - declare that variable as GLOBAL so the world can find it. Then - we dynamically create a function - based on the register name. Look carefully at how that is done. You'll notice the FUNCTION BODY is a string - not something in {braces}. Why? This is because we need TCL to evaluate the contents of that string "*NOW*" - when $vn exists not later, when the function "show_FOO" is invoked. Lastly - we build a "str" of commands - and create a single function - with the generated list of commands for the entire USART. With that little bit of code - I now have a bunch of functions like: show_US0, show_US1, show_US2, .... etc ... And show_US0_MR, show_US0_IMR ... etc... And - I have this for every USART... without having to create tons of boiler plate yucky code. **************************************** **************************************** END of the Tcl Intro and Walk Through **************************************** **************************************** FUTURE PLANS Some "GPIO" functions... @endverbatim */ openocd-0.9.0/doc/manual/primer/autotools.txt0000644000175000017500000001334512315575360016217 00000000000000/** @page primerautotools OpenOCD Autotools Primer This page provides an overview to OpenOCD's use of the GNU autotool suite: - @ref primerautoconf - @ref primerautomake - @ref primerlibtool Most developers do not need to concern themselves with these tools, as the @ref primerbootstrap script runs these tools in the required sequence. @section primerbootstrap Autotools Bootstrap The @c bootstrap script should be used by developers to run the autotools in the correct sequence. When run after a fresh checkout, this script generates the build files required to compile the project, producing the project configure script. After running @c configure, the @ref primermaintainermode settings will handle most situations that require running these tools again. In some cases, a fresh bootstrap may be still required. @subsection primerbootstrapcures Problems Solved By Bootstrap For example, the build system can fail in unexpected ways after running git pull. Here, the make maintainer-clean should be used to remove all of the files generated by the @c bootstrap script and subsequent build processes. In this particular case, one may also need to remove stray files by hand after running this command to ensure everything is rebuilt properly. This step should be necessary only if the @c maintainer-clean was run @b after altering the build system files with git. If it is run @b before any updates, the build system should never leave artifacts in the tree. Without such precautions, changes can be introduced that leave the tree timestamps in an inconsistent state, producing strange compile errors that are resolve after such diligence. @subsection primermaintainerclean Autotools Cleaning Normally, all files generated by the bootstrap script, configure process, and build system should be removed after running make maintainer-clean. Automatically generated files that remain after this should be listed in @c MAINTAINERCLEANFILES, @c DISTCLEANFILES, or @c CLEANFILES, depending on which stage of the build process they are produced. @section primerautoconf Autoconf Configuration Script The @c autoconf program generates the @c configure script from @c configure.in, using serious Perl voodoo. The resulting script is included in the project distribution packages and run by users to configure the build process for their system. @section primerautomake Automake Makefiles The @c automake program generates @c Makefile.in files (from @c Makefile.am files). These files are later processed by the configure script produced by @c autoconf. @subsection primerautomakenewfiles Creating Makefile.am Files This section shows how to add a @c Makefile.am in a new directory (or one that lacks one). -# The new directory must be listed in the @c SUBDIRS variable in the parent directory's Makefile.am: @code $ echo 'SUBDIRS += directory' >>../Makefile.am @endcode -# Create an bare-bones Makefile.am file in directory that needs it: @code $ echo "MAINTAINERCLEANFILES = Makefile.in" >Makefile.am @endcode -# The @c configure.in script must be updated, so it generates the required Makefile when the @a configure script is run by the user: @verbatim AC_OUTPUT([ ... path/to/new/Makefile ]) @endverbatim Note: these instructions are @b not meant to be used literally, rather they are shown for demonstration purposes. The default MAINTAINERCLEANFILES rule ensures that the automake-generated @c Makefile.in file will be removed when developers run make maintainer-clean. Additional rules may be added after this; however, the project should bootstrap and tear down cleanly after taking these minimal steps, with the new directory being visited during the @c make sequence. @subsection primerautomaketweaks Updating Makefile.am Files Adding, removing, and renaming files from the project tree usually requires updating the autotools inputs. This section will help describe how to do this as questions arise. @section primerlibtool Libtool and Libraries The @c libtool program provides the means of generating libraries in a portable and painless manner (relatively speaking). This section will contain an answer to "what does libtool give OpenOCD?" and "what do developers need to consider in new code?" @section primerautotoolsmation Autotools Automation This section outlines three ways the autotools provides automation to assist with testing and distribution: - @ref primerautocheck -- automatic unit and smoke tests - @ref primerautodistcheck -- automatic distribution and packaging tests @subsection primerautocheck make check The make check command will run the OpenOCD test suite, once it has been integrated as such. This section will contain information about how to extend the testing build system components to implement new checks. @subsection primerautodistcheck make distcheck The make distcheck command produces an archive of the project deliverables (using make dist) and verifies its integrity for distribution by attemptng to use the package in the same manner as a user. These checks includes the following steps: -# Unpack the project archive into its expected directory. -# Configure and build the project in a temporary out-of-tree directory. -# Run make check to ensure the distributed code passes all tests. -# Run make install into a temporary installation directory. -# Check that make uninstall removes all files that were installed. -# Check that make distclean removes all files created during all other steps (except the first). If all of these steps complete successfully, the @c make process will output a friendly message indicating the archive is ready to be distributed. */ /** @file This file contains the @ref primerautotools page. */ openocd-0.9.0/doc/manual/primer/docs.txt0000644000175000017500000001220612315575360015111 00000000000000/** @page primerdocs OpenOCD Documentation Primers This page provides an introduction to OpenOCD's documentation processes. OpenOCD presently produces several kinds of documentation: - The User's Guide: - Focuses on using the OpenOCD software. - Details the installation, usage, and customization. - Provides descriptions of public Jim/TCL script commands. - Written using GNU texinfo. - Created with 'make pdf' or 'make html'. - See @subpage primertexinfo and @ref styletexinfo. - The References: (as proposed) - Focuses on using specific hardware with OpenOCD. - Details the supported interfaces, chips, boards, and targets. - Provides overview, usage, reference, and FAQ for each device. - Written using LaTeX language with custom macros. - Created with 'make references'. - See @subpage primerlatex and @ref stylelatex. - The Manual: - Focuses on developing the OpenOCD software. - Details the architecutre, driver interfaces, and processes. - Provides "full" coverage of C source code (work-in-progress). - Written using Doxygen C language conventions (i.e. in comments). - Created with 'make doxygen'. - See @subpage primerdoxygen and @ref styledoxygen. The following sections provide more information for anyone that wants to contribute new or updated documentation to the OpenOCD project. */ /** @page primertexinfo Texinfo Primer The OpenOCD User's Guide presently exists entirely within the doc/openocd.texi document. That file contains documentation with mark-up suitable for being parsed by the GNU Texinfo utilities (http://www.gnu.org/software/texinfo/). When you add a new command, driver, or driver option, it needs to be documented in the User's Guide. Use the existing documentation for models, but feel free to make better use of Texinfo mechanisms. See the Texinfo web site for the Texinfo manual and more information. OpenOCD style guidelines for Texinfo documentation can be found on the @ref styletexinfo page. */ /** @page primerlatex LaTeX Primer The OpenOCD project provides a number of reference guides using the LaTeX typesetting language. - OpenOCD Quick Reference Sheets - OpenOCD Hardware Reference Guides These documents have not yet been produced, so this Primer serves as a placeholder to describe how they are created and can be extended. The same holds true for the @ref stylelatex page. */ /** @page primerdoxygen Doxygen Primer Doxygen-style comments are used to provide documentation in-line with the OpenOCD source code. These comments are used to document functions, variables, structs, enums, fields, and everything else that might need to be documented for developers. Additional files containing comments that supplement the code comments in order to provide complete developer documentation. Even if you already know Doxygen, please read this Primer to learn how OpenOCD developers already use Doxygen features in the project tree. For more information about OpenOCD's required style for using Doxygen, see the @ref styledoxygen page and look at existing documentation in the @c doc/manual tree. @section primerdoxytext Doxygen Input Files Doxygen has been configured parse all of the C source code files (*.c and *.h) in @c src/ in order to produce a complete reference of all OpenOCD project symbols. In addition to the source code files, other files will also be scanned for comment blocks; some are referenced explicitly by the @c INPUT variable in the Doxygen configuration file. By default, the Doxygen configuration enables a "full" set of features, including generation of dependency graphs (using the GraphViz package). These features may be disabled by editing the @c Doxyfile.in file at the top of the project tree; the configuration file includes comments that provide detailed documentation for each option. To support out-of-tree building of the documentation, the @c Doxyfile.in @c INPUT values will have all instances of the string @c "@srcdir@" replaced with the current value of the make variable $(srcdir). The Makefile uses a rule to convert @c Doxyfile.in into the @c Doxyfile used by make doxygen. @section primerdoxyoocd OpenOCD Input Files OpenOCD uses the @c INPUT mechanism to include additional documentation to provide The Manual for OpenOCD Developers. These extra files contain high-level information intended to supplement the relatively low-level documentation that gets extracted from the source code comments. OpenOCD's Doxygen configuration file will search for all @c .txt files that can be found under the @c doc/manual directory in the project tree. New files containing valid Doxygen markup that are placed in or under that directory will be detected and included in The Manual automatically. @section primerdoxyman Doxygen Reference Manual The full documentation for Doxygen can be referenced on-line at the project home page: http://www.doxygen.org/index.html. In HTML versions of this document, an image with a link to this site appears in the page footer. */ /** @file This file contains the Doxygen source code for the @ref primerdocs. The @ref primerdocs page also contains the following sections: - @ref primertexinfo - @ref primerlatex - @ref primerdoxygen */ openocd-0.9.0/doc/manual/scripting.txt0000644000175000017500000000604212315575360014666 00000000000000/** @page scripting Scripting Overview @section scriptingisnt What scripting will not do The scripting support is intended for developers of OpenOCD. It is not the intention that normal OpenOCD users will use tcl scripting extensively, write lots of clever scripts, or contribute back to OpenOCD. Target scripts can contain new procedures that end users may tinker to their needs without really understanding tcl. Since end users are not expected to mess with the scripting language, the choice of language is not terribly important to those same end users. Jim Tcl was chosen as it was easy to integrate, works great in an embedded environment and Øyvind Harboe had experience with it. @section scriptinguses Uses of scripting Default implementation of procedures in tcl/procedures.tcl. - Polymorphic commands for target scripts. - there will be added some commands in Tcl that the target scripts can replace. - produce \ \. Default implementation is to ignore serial number and write a raw binary file to beginning of first flash. Target script can dictate file format and structure of serialnumber. Tcl allows an argument to consist of e.g. a list so the structure of the serial number is not limited to a single string. - reset handling. Precise control of how srst, trst & tms is handled. - replace some parts of the current command line handler. This is only to simplify the implementation of OpenOCD and will have no externally visible consequences. Tcl has an advantage in that it's syntax is backwards compatible with the current OpenOCD syntax. - external scripting. Low level tcl functions will be defined that return machine readable output. These low level tcl functions constitute the tcl api. flash_banks is such a low level tcl proc. "flash banks" is an example of a command that has human readable output. The human readable output is expected to change inbetween versions of OpenOCD. The output from flash_banks may not be in the preferred form for the client. The client then has two choices a) parse the output from flash_banks or b) write a small piece of tcl to output the flash_banks output to a more suitable form. The latter may be simpler. @section scriptingexternal External scripting The embedded Jim Tcl interpreter in OpenOCD is very limited compared to any full scale PC hosted scripting language. The goal is to keep the internal Jim Tcl interpreter as small as possible and allow any advanced scripting, especially scripting that interacts with the host, run on the host and talk to OpenOCD via the TCP/IP scripting connection. Another problem with Jim Tcl is that there is no debugger for it. With a bit of trickery it should be possible to run Jim Tcl scripts under a Tcl interpreter on a PC. The advantage would be that the Jim Tcl scripts could be debugged using a standard PC Tcl debugger. The rough idea is to write an unknown proc that sends unknown commands to OpenOCD. Basically a PC version of startup.tcl. Patches most gratefully accepted! :-) */ openocd-0.9.0/doc/manual/target/0000755000175000017500000000000012315575360013467 500000000000000openocd-0.9.0/doc/manual/target/notarm.txt0000644000175000017500000000355312315575360015456 00000000000000/** @page targetnotarm OpenOCD Non-ARM Targets This page describes outstanding issues w.r.t. non-ARM targets. @section targetnotarmflash Flash drivers The flash drivers contain ARM32 code that is used to execute code on the target. This needs to be handled in some CPU independent manner. The ocl and ecos flash drivers compile the flash driver code to run on the target on the developer machine. The ocl and ecos flash drivers should be unified and instructions should be written on how to compile the target flash drivers. Perhaps using automake? eCos has CFI driver that could probably be compiled for all targets. The trick is to figure out a way to make the compiled flash drivers work on all target memory maps + sort out all the little details @section targetnotarm32v64 32 vs. 64 bit Currently OpenOCD only supports 32 bit targets. Adding 64 bit support would be nice but there hasn't been any call for it in the openocd development mailing list @section targetnotarmsupport Target Support target.h is relatively CPU agnostic and the intention is to move in the direction of less instruction set specific. Non-CPU targets are also supported, but there isn't a lot of activity on it in the mailing list currently. An example is FPGA programming support via JTAG, but also flash chips can be programmed directly using JTAG. @section targetnotarmphy non-JTAG physical layer JTAG is not the only physical protocol used to talk to CPUs. OpenOCD does not today have targets that use non-JTAG. The actual physical layer is a relatively modest part of the total OpenOCD system. @section targetnotarmppc PowerPC there exists open source implementations of powerpc target manipulation, but there hasn't been a lot of activity in the mailing list. @section targetnotarmmips MIPS Currently OpenOCD has a MIPS target defined. This is the first non-ARM example of a CPU target */ openocd-0.9.0/doc/manual/target/mips.txt0000644000175000017500000006304312315575360015126 00000000000000/** @page targetmips OpenOCD MIPS Targets @section ejatgmem EJTAG Memory Addresses An optional uncached and unmapped debug segment dseg (EJTAG area) appears in the address range 0xFFFF FFFF FF20 0000 to 0xFFFF FFFF FF3F FFFF. The dseg segment thereby appears in the kseg part of the compatibility segment, and access to kseg is possible with the dseg segment. The dseg segment is subdivided into dmseg (EJTAG memory) segment and the drseg (EJTAG registers) segment. The dmseg segment is used when the probe services the memory segment. The drseg segment is used when the memory-mapped debug registers are accessed. Table 5-2 shows the subdivision and attributes for the segments. dseg is divided in : - dmseg (0xFFFF FFFF FF20 0000 to 0xFFFF FFFF FF2F FFFF) - drseg (0xFFFF FFFF FF30 0000 to 0xFFFF FFFF FF3F FFFF) Because the dseg segment is serviced exclusively by the EJTAG features, there are no physical address per se. Instead the lower 21 bits of the virtual address select the appropriate reference in either EJTAG memory or registers. References are not mapped through the TLB, nor do the accesses appear on the external system memory interface. Both of this memory segments are Uncached. On debug exception (break) CPU jumps to the beginning of dmseg. This some kind of memory shared between CPU and EJTAG dongle. There CPU stops (correct terminology is : stalls, because it stops it's pipeline), and is waiting for some action of dongle. If the dongle gives it instruction, CPU executes it, augments it's PC to 0xFFFF FFFF FF20 0001 - but it again points to dmseg area, so it stops waiting for next instruction. This will all become clear later, after reading following prerequisite chapters. @section impflags Important flags @subsection pnnw PNnW Indicates read or write of a pending processor access: - 0 : Read processor access, for a fetch/load access - 1 : Write processor access, for a store access This value is defined only when a processor access is pending. Processor will do the action for us : it can for example read internal state (register values), and send us back the information via EJTAG memory (dmseg), or it can take some data from dmseg and write it into the registers or RAM. Every time when it sees address (i.e. when this address is the part of the opcode it is executing, wether it is instruction or data fetch) that falls into dmseg, processor stalls. That acutally meand that CPU stops it's pipeline and it is waitning for dongle to take some action. CPU is now either waiting for dongle to take some data from dmseg (if we requested for CPU do give us internal state, for example), or it will wait for some data from dongle (if it needs following instruction because it did previous, or if the operand address of the currently executed opcode falls somewhere (anywhere) in dmseg (0xff..ff20000 - 0xff..ff2fffff)). Bit PNnW describes character of CPU access to EJTAG memory (the memry where dongle puts/takes data) - CPU can either READ for it (PNnW == 0) or WRITE to it (PNnW == 1). By reading PNnW bit OpenOCD will know if it has to send (PNnW == 0) or to take (PNnW == 1) data (from dmseg, via dongle). @subsection pracc PrAcc Indicates a pending processor access and controls finishing of a pending processor access. When read: - 0 : No pending processor access - 1 : Pending processor access A write of 0 finishes a processor access if pending; otherwise operation of the processor is UNDEFINED if the bit is written to 0 when no processor access is pending. A write of 1 is ignored. A successful FASTDATA access will clear this bit. As noted above, on any access to dmseg, processor will stall. It waits for dongle to do some action - either to take or put some data. OpenOCD can figure out which action has to be taken by reading PrAcc bit. Once action from dongle has been done, i.e. after the data is taken/put, OpenOCD can signal to CPU to proceed with executing the instruction. This can be the next instruction (if previous was finished before pending), or the same instruction - if for example CPU was waiting on dongle to give it an operand, because it saw in the instruction opcode that operand address is somewhere in dmseg. That prowoked the CPU to stall (it tried operand fetch to dmseg and stopped), and PNnW bit is 0 (CPU does read from dmseg), and PrAcc is 1 (CPU is pending on dmseg access). @subsection spracc SPrAcc Shifting in a zero value requests completion of the Fastdata access. The PrAcc bit in the EJTAG Control register is overwritten with zero when the access succeeds. (The access succeeds if PrAcc is one and the operation address is in the legal dmseg segment Fastdata area.) When successful, a one is shifted out. Shifting out a zero indicates a Fastdata access failure. Shifting in a one does not complete the Fastdata access and the PrAcc bit is unchanged. Shifting out a one indicates that the access would have been successful if allowed to complete and a zero indicates the access would not have successfully completed. @section fdreg Fastdata Register (TAP Instruction FASTDATA) The width of the Fastdata register is 1 bit. During a Fastdata access, the Fastdata register is written and read, i.e., a bit is shifted in and a bit is shifted out. Also during a Fastdata access, the Fastdata register value shifted in specifies whether the Fastdata access should be completed or not. The value shifted out is a flag that indicates whether the Fastdata access was successful or not (if completion was requested). @section ejtagacc EJTAG Access Implementation OpenOCD reads/writes data to JTAG via mips_m4k_read_memory() and mips_m4k_write_memory() functions defined in src/target/mips_m4k.c. Internally, these functions call mips32_pracc_read_mem() and mips32_pracc_write_mem() defined in src/target/mips32_pracc.c Let's take for example function mips32_pracc_read_mem32() which describes CPU reads (fetches) from dmseg (EJTAG memory) : @code static const uint32_t code[] = { /* start: */ MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), MIPS32_SW(8,0,15), /* sw $8,($15) */ MIPS32_SW(9,0,15), /* sw $9,($15) */ MIPS32_SW(10,0,15), /* sw $10,($15) */ MIPS32_SW(11,0,15), /* sw $11,($15) */ MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */ MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */ MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */ MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)), /* loop: */ MIPS32_BEQ(0,10,8), /* beq 0, $10, end */ MIPS32_NOP, MIPS32_LW(8,0,9), /* lw $8,0($9), Load $8 with the word @mem[$9] */ MIPS32_SW(8,0,11), /* sw $8,0($11) */ MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ MIPS32_ADDI(9,9,4), /* $1 += 4 */ MIPS32_ADDI(11,11,4), /* $11 += 4 */ MIPS32_B(NEG16(8)), /* b loop */ MIPS32_NOP, /* end: */ MIPS32_LW(11,0,15), /* lw $11,($15) */ MIPS32_LW(10,0,15), /* lw $10,($15) */ MIPS32_LW(9,0,15), /* lw $9,($15) */ MIPS32_LW(8,0,15), /* lw $8,($15) */ MIPS32_B(NEG16(27)), /* b start */ MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ }; @endcode We have to pass this code to CPU via dongle via dmseg. After debug exception CPU will find itself stalling at the begining of the dmseg. It waits for the first instruction from dongle. This is MIPS32_MTC0(15,31,0), so CPU saves C0 and continues to addr 0xFF20 0001, which falls also to dmseg, so it stalls. Dongle proceeds giving to CPU one by one instruction in this manner. However, things are not so simple. If you take a look at the program, you will see that some instructions take operands. If it has to take operand from the address in dmseg, CPU will stall witing for the dongle to do the action of passing the operand and signal this by putting PrAcc to 0. If this operand is somewhere in RAM, CPU will not stall (it stalls only on dmseg), but it will just take it and proceed to nex instruction. But since PC for next instruction points to dmseg, it will stall, so that dongle can pass next instruction. Some instuctions are jumps (if these are jumps in dmseg addr, CPU will jump and then stall. If this is jump to some address in RAM, CPU will jump and just proceed - will not stall on addresses in RAM). To have information about CPU is currently (does it stalls wanting on operand or it jumped somewhere waiting for next instruction), OpenOCD has to call TAP ADDRESS instruction, which will ask CPU to give us his address within EJTAG memory : @code address = data = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &address); @endcode And then, upon the results, we can conclude where it is in our code so far, so we can give it what it wants next : @code if ((address >= MIPS32_PRACC_PARAM_IN) && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) { offset = (address - MIPS32_PRACC_PARAM_IN) / 4; data = ctx->local_iparam[offset]; } else if ((address >= MIPS32_PRACC_PARAM_OUT) && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) { offset = (address - MIPS32_PRACC_PARAM_OUT) / 4; data = ctx->local_oparam[offset]; } else if ((address >= MIPS32_PRACC_TEXT) && (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4)) { offset = (address - MIPS32_PRACC_TEXT) / 4; data = ctx->code[offset]; } else if (address == MIPS32_PRACC_STACK) { /* save to our debug stack */ data = ctx->stack[--ctx->stack_offset]; } else { /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back to start of debug vector */ data = 0; LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address); return ERROR_JTAG_DEVICE_ERROR; } @endcode i.e. if CPU is stalling on addresses in dmseg that are reserved for input parameters, we can conclude that it actually tried to take (read) parametar from there, and saw that address of param falls in dmseg, so it stopped. Obviously, now dongle have to give to it operand. Similarly, mips32_pracc_exec_write() describes CPU writes into EJTAG memory (dmseg). Obvioulsy, code is RO, and CPU can change only parameters : @code mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ctx->ejtag_info, &data); /* Clear access pending bit */ ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl); //jtag_add_clocks(5); jtag_execute_queue(); if ((address >= MIPS32_PRACC_PARAM_IN) && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) { offset = (address - MIPS32_PRACC_PARAM_IN) / 4; ctx->local_iparam[offset] = data; } else if ((address >= MIPS32_PRACC_PARAM_OUT) && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) { offset = (address - MIPS32_PRACC_PARAM_OUT) / 4; ctx->local_oparam[offset] = data; } else if (address == MIPS32_PRACC_STACK) { /* save data onto our stack */ ctx->stack[ctx->stack_offset++] = data; } else { LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address); return ERROR_JTAG_DEVICE_ERROR; } @endcode CPU loops here : @code while (1) { if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK) return retval; address = data = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &address); /* Check for read or write */ if (ejtag_ctrl & EJTAG_CTRL_PRNW) { if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK) return retval; } else { /* Check to see if its reading at the debug vector. The first pass through * the module is always read at the vector, so the first one we allow. When * the second read from the vector occurs we are done and just exit. */ if ((address == MIPS32_PRACC_TEXT) && (pass++)) { break; } if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK) return retval; } if (cycle == 0) break; } @endcode and using presented R (mips32_pracc_exec_read()) and W (mips32_pracc_exec_write()) functions it reads in the code (RO) and reads and writes operands (RW). @section fdimpl OpenOCD FASTDATA Implementation OpenOCD FASTDATA write function, mips32_pracc_fastdata_xfer() is called from bulk_write_memory callback, which writes a count items of 4 bytes to the memory of a target at the an address given. Because it operates only on whole words, this should be faster than target_write_memory(). In order to implement FASTDATA write, mips32_pracc_fastdata_xfer() uses the following handler : @code uint32_t handler_code[] = { /* caution when editing, table is modified below */ /* r15 points to the start of this code */ MIPS32_SW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15), MIPS32_SW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15), MIPS32_SW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15), MIPS32_SW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15), /* start of fastdata area in t0 */ MIPS32_LUI(8,UPPER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_LW(9,0,8), /* start addr in t1 */ MIPS32_LW(10,0,8), /* end addr to t2 */ /* loop: */ /* 8 */ MIPS32_LW(11,0,0), /* lw t3,[t8 | r9] */ /* 9 */ MIPS32_SW(11,0,0), /* sw t3,[r9 | r8] */ MIPS32_BNE(10,9,NEG16(3)), /* bne $t2,t1,loop */ MIPS32_ADDI(9,9,4), /* addi t1,t1,4 */ MIPS32_LW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15), MIPS32_LW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15), MIPS32_LW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15), MIPS32_LW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15), MIPS32_LUI(15,UPPER16(MIPS32_PRACC_TEXT)), MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_TEXT)), MIPS32_JR(15), /* jr start */ MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ }; @endcode In the begining and the end of the handler we have fuction prologue (save the regs that will be clobbered) and epilogue (restore regs), and in the very end, after all the xfer have been done, we do jump to the MIPS32_PRACC_TEXT address, i.e. Debug Exception Vector location. We will use this fact (that we came back to MIPS32_PRACC_TEXT) to verify later if all the handler is executed (because when in RAM, processor do not stall - it executes all instructions untill one of them do not demand access to dmseg (if one of it's opernads is there)). This handler is put into the RAM and executed from there, and not instruction by instruction, like in previous simple write (mips_m4k_write_memory()) and read (mips_m4k_read_memory()) functions. N.B. When it is executing this code in RAM, CPU will not stall on instructions, but execute all until it comes to the : @code MIPS32_LW(9,0,8) /* start addr in t1 */ @endcode and there it will stall - because it will see that one of the operands have to be fetched from dmseg (EJTAG memory, in this case FASTDATA memory segment). This handler is loaded in the RAM, ath the reserved location "work_area". This work_area is configured in OpenOCD configuration script and should be selected in that way that it is not clobbered (overwritten) by data we want to write-in using FASTDATA. What is executed instruction by instruction which is passed by dongle (via EJATG memory) is small jump code, which jumps at the handler in RAM. CPU stalls on dmseg when receiving these jmp_code instructions, but once it jumps in RAM, CPU do not stall anymore and executes bunch of handler instructions. Untill it comes to the first instruction which has an operand in FASTDATA area. There it stalls and waits on action from probe. It happens actually when CPU comes to this loop : @code MIPS32_LW(9,0,8), /* start addr in t1 */ MIPS32_LW(10,0,8), /* end addr to t2 */ /* loop: */ /* 8 */ MIPS32_LW(11,0,0), /* lw t3,[t8 | r9] */ /* 9 */ MIPS32_SW(11,0,0), /* sw t3,[r9 | r8] */ MIPS32_BNE(10,9,NEG16(3)), /* bne $t2,t1,loop */ @endcode and then it stalls because operand in r8 points to FASTDATA area. OpenOCD first verifies that CPU came to this place by : @code /* next fetch to dmseg should be in FASTDATA_AREA, check */ address = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &address); if (address != MIPS32_PRACC_FASTDATA_AREA) return ERROR_FAIL; @endcode and then passes to CPU start and end address of the loop region for handler in RAM. In the loop in handler, CPU sees that it has to take and operand from FSTDATA area (to write it to the dst in RAM after), and so it stalls, putting PrAcc to "1". OpenOCD fills the data via this loop : @code for (i = 0; i < count; i++) { /* Send the data out using fastdata (clears the access pending bit) */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); if ((retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++)) != ERROR_OK) return retval; } @endcode Each time when OpenOCD fills data to CPU (via dongle, via dmseg), CPU takes it and proceeds in executing the endler. However, since handler is in a assembly loop, CPU comes to next instruction which also fetches data from FASTDATA area. So it stalls. Then OpenOCD fills the data again, from it's (OpenOCD's) loop. And this game continues untill all the data has been filled. After the last data has beend given to CPU it sees that it reached the end address, so it proceeds with next instruction. However, rhis instruction do not point into dmseg, so CPU executes bunch of handler instructions (all prologue) and in the end jumps to MIPS32_PRACC_TEXT address. On it's side, OpenOCD checks in CPU has jumped back to MIPS32_PRACC_TEXT, which is the confirmation that it correclty executed all the rest of the handler in RAM, and that is not stuck somewhere in the RAM, or stalling on some acces in dmseg - that would be an error : @code address = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &address); if (address != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); @endcode @section fdejtagspec EJTAG spec on FASTDATA access The width of the Fastdata register is 1 bit. During a Fastdata access, the Fastdata register is written and read, i.e., a bit is shifted in and a bit is shifted out. During a Fastdata access, the Fastdata register value shifted in specifies whether the Fastdata access should be completed or not. The value shifted out is a flag that indicates whether the Fastdata access was successful or not (if completion was requested). The FASTDATA access is used for efficient block transfers between dmseg (on the probe) and target memory (on the processor). An "upload" is defined as a sequence of processor loads from target memory and stores to dmseg. A "download" is a sequence of processor loads from dmseg and stores to target memory. The "Fastdata area" specifies the legal range of dmseg addresses (0xFF20.0000 - 0xFF20.000F) that can be used for uploads and downloads. The Data + Fastdata registers (selected with the FASTDATA instruction) allow efficient completion of pending Fastdata area accesses. During Fastdata uploads and downloads, the processor will stall on accesses to the Fastdata area. The PrAcc (processor access pending bit) will be 1 indicating the probe is required to complete the access. Both upload and download accesses are attempted by shifting in a zero SPrAcc value (to request access completion) and shifting out SPrAcc to see if the attempt will be successful (i.e., there was an access pending and a legal Fastdata area address was used). Downloads will also shift in the data to be used to satisfy the load from dmseg’s Fastdata area, while uploads will shift out the data being stored to dmseg’s Fastdata area. As noted above, two conditions must be true for the Fastdata access to succeed. These are: - PrAcc must be 1, i.e., there must be a pending processor access. - The Fastdata operation must use a valid Fastdata area address in dmseg (0xFF20.0000 to 0xFF20.000F). Basically, because FASTDATA area in dmseg is 16 bytes, we transfer (0xFF20.0000 - 0xFF20.000F) FASTDATA scan TAP instruction selects the Data and the Fastdata registers at once. They come in order : TDI -> | Data register| -> | Fastdata register | -> TDO FASTDATA register is 1-bit width register. It takes in SPrAcc bit which should be shifted first, followed by 32 bit of data. Scan width of FASTDTA is 33 bits in total : 33 bits are shifted in and 33 bits are shifted out. First bit that is shifted out is SPrAcc that comes out of Fastdata register and should give us status on FATSDATA write we want to do. @section fdcheck OpenOCD misses FASTDATA check Download flow (probe -> target block transfer) : 1) Probe transfer target execution to a loop in target memory doing a fixed number of "loads" to fastdata area of dmseg (and stores to the target download destination.) 2) Probe loops attempting to satisfy the loads "expected" from the target. On FASTDATA access "successful" move on to next "load". On FASTDATA access "failure" repeat until "successful" or timeout. (A "failure" is an attempt to satisfy an access when none are pending.) Note: A failure may have a recoverable (and even expected) cause like slow target execution of the load loop. Other failures may be due to unexpected more troublesome causes like an exception while in debug mode or a target hang on a bad target memory access. Shifted out SPrAcc bit inform us that there was CPU access pendingand that it can be complete. Basically, we should do following procedure : - Download (dongle -> CPU) : You shift "download" DATA and FASTDATA[SPrAcc] = 0 (33 bit scan) into the target. If the value of FASTDATA[SPrAcc] shifted out is "1" then an access was pending when you started the scan and it is now complete. If SPrAcc is 0 then no access was pending to the fastdata area. (Repeat attempt to complete the access you expect for this data word. Timeout if you think the access is "long overdue" as something unexpected has happened.) - Upload (CPU -> dongle) : You shift "dummy" DATA and FASTDATA[SPrAcc] = 0 (33 bit scan) into the target. If the value of FASTDATA[SPrAcc] shifted out is "1" then an access was pending when you started the scan and it is now complete. The "upload" is the DATA shifted out of the target. If SPrAcc is 0 then no access was pending to the fastdata area. (Repeat attempt to complete the access you expect for this data word. Timeout if you think the access is "long overdue" as something unexpected has happened.) Basically, if checking first (before scan) if CPU is pending on FASTDATA access (PrAcc is "1"), like this @code wait(ready); do_scan(); @endcode which is inefficient, we should do it like this : @code BEGIN : do_scan(); if (!was_ready) goto BEGIN; @endcode by checking SPrAcc that we shifted out. If some FASTDATA write fails, OpenOCD will continue with it's loop (on the host side), but CPU will rest pending (on the target side) waiting for correct FASTDATA write. Since OpenOCD goes ahead, it will eventually finish it's loop, and proceede to check if CPU took all the data. But since CPU did not took all the data, it is still turns in handler's loop in RAM, stalling on Fastdata area so this check : @code address = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); retval = mips_ejtag_drscan_32(ejtag_info, &address); if (retval != ERROR_OK) return retval; if (address != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); @endcode fails, and that gives us enough information of the failure. In this case, we can lower the JTAG frquency and try again, bacuse most probable reason of this failure is that we tried FASTDATA upload before CPU arrived to rise PrAcc (i.e. before it was pending on access). However, the reasons for failure might be numerous : reset, exceptions which can occur in debug mode, bus hangs, etc. If lowering the JTAG freq does not work either, we can fall back to more robust solution with patch posted below. To summarize, FASTDATA communication goes as following : -# CPU jumps to Debug Exception Vector Location 0xFF200200 in dmseg and it stalls, pending and waiting for EJTAG to give it first debug instruction and signall it by putting PrAcc to "0" -# When PrAcc goes to "0" CPU execute one opcode sent by EJTAG via DATA reg. Then it pends on next access, waiting for PrAcc to be put to "0" again -# Following this game, OpenOCD first loads handler code in RAM, and then sends the jmp_code - instruction by instruction via DATA reg, which redirects CPU to handler previously set up in RAM -# Once in RAM CPU does not pend on any instruction, but it executes all handler instructions untill first "fetch" to Fastdata area - then it stops and pends. -# So - when it comes to any instruction (opcode) in this handler in RAM which reads (or writes) to Fastdata area (0xF..F20.0000 to 0xF..F20.000F), CPU stops (i.e. stalls access). I.e. it stops on this lw opcode and waits to FASTDATA TAP command from the probe. -# CPU continues only if OpenOCD shifted in SPrAcc "0" (and if the PrAcc was "1"). It shifts-out "1" to tell us that it was OK (processor was stalled, so it can complete the access), and that it continued execution of the handler in RAM. -# If PrAcc was not "1" CPU will not continue (go to next instruction), but will shift-out "0" and keep stalling on the same instruction of my handler in RAM. -# When Fastdata loop is finished, CPU executes all following hadler instructions in RAM (prologue). -# In the end of my handler in RAM, I jumps back to begining of Debug Exception Vector Location 0xFF200200 in dmseg. -# When it jumps back to 0xFF200200 in dmseg processor stops and pends, waiting for OpenOCD to send it instruction via DATA reg and signal it by putting PrAcc to "0". */ openocd-0.9.0/doc/manual/app.txt0000644000175000017500000000047312315575360013446 00000000000000/** @page appdocs OpenOCD Application APIs The top-level APIs in the OpenOCD library allow applications to integrate all of the low-level functionality using a set of simple function calls. These function calls do not exist in a re-usable form, but contributions to create and document them will be welcome. */ openocd-0.9.0/doc/fdl.texi0000644000175000017500000005107612315575360012315 00000000000000@c -*-texinfo-*- @node License @appendix The GNU Free Documentation License. @center Version 1.2, November 2002 @c This file is intended to be included within another document, @c hence no sectioning command or @node. @display Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @enumerate 0 @item PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document @dfn{free} in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of ``copyleft'', which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. @item APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The ``Document'', below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as ``you''. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A ``Modified Version'' of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A ``Secondary Section'' is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The ``Invariant Sections'' are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The ``Cover Texts'' are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A ``Transparent'' copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not ``Transparent'' is called ``Opaque''. Examples of suitable formats for Transparent copies include plain @sc{ascii} without markup, Texinfo input format, La@TeX{} input format, @acronym{SGML} or @acronym{XML} using a publicly available @acronym{DTD}, and standard-conforming simple @acronym{HTML}, PostScript or @acronym{PDF} designed for human modification. Examples of transparent image formats include @acronym{PNG}, @acronym{XCF} and @acronym{JPG}. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, @acronym{SGML} or @acronym{XML} for which the @acronym{DTD} and/or processing tools are not generally available, and the machine-generated @acronym{HTML}, PostScript or @acronym{PDF} produced by some word processors for output purposes only. The ``Title Page'' means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, ``Title Page'' means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section ``Entitled XYZ'' means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as ``Acknowledgements'', ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' of such a section when you modify the Document means that it remains a section ``Entitled XYZ'' according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. @item VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. @item COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. @item MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: @enumerate A @item Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. @item List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. @item State on the Title page the name of the publisher of the Modified Version, as the publisher. @item Preserve all the copyright notices of the Document. @item Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. @item Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. @item Include an unaltered copy of this License. @item Preserve the section Entitled ``History'', Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled ``History'' in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @item Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the ``History'' section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @item Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item Delete any section Entitled ``Endorsements''. Such a section may not be included in the Modified Version. @item Do not retitle any existing section to be Entitled ``Endorsements'' or to conflict in title with any Invariant Section. @item Preserve any Warranty Disclaimers. @end enumerate If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled ``Endorsements'', provided it contains nothing but endorsements of your Modified Version by various parties---for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. @item COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled ``History'' in the various original documents, forming one section Entitled ``History''; likewise combine any sections Entitled ``Acknowledgements'', and any sections Entitled ``Dedications''. You must delete all sections Entitled ``Endorsements.'' @item COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. @item AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. @item TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled ``Acknowledgements'', ``Dedications'', or ``History'', the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @item TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. @item FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See @uref{http://www.gnu.org/copyleft/}. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. @end enumerate @unnumberedsec ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: @smallexample @group Copyright (C) @var{year} @var{your name}. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end group @end smallexample If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the ``with@dots{}Texts.'' line with this: @smallexample @group with the Invariant Sections being @var{list their titles}, with the Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. @end group @end smallexample If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. @c Local Variables: @c ispell-local-pdict: "ispell-dict" @c End: openocd-0.9.0/doc/mdate-sh0000755000175000017500000001363712526201647012304 00000000000000#!/bin/sh # Get modification time of a file or directory and pretty-print it. scriptversion=2010-08-21.06; # UTC # Copyright (C) 1995-2013 Free Software Foundation, Inc. # written by Ulrich Drepper , June 1995 # # This program 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 2, or (at your option) # any later version. # # This program 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 . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST fi case $1 in '') echo "$0: No file. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: mdate-sh [--help] [--version] FILE Pretty-print the modification day of FILE, in the format: 1 January 1970 Report bugs to . EOF exit $? ;; -v | --v*) echo "mdate-sh $scriptversion" exit $? ;; esac error () { echo "$0: $1" >&2 exit 1 } # Prevent date giving response in another language. LANG=C export LANG LC_ALL=C export LC_ALL LC_TIME=C export LC_TIME # GNU ls changes its time format in response to the TIME_STYLE # variable. Since we cannot assume 'unset' works, revert this # variable to its documented default. if test "${TIME_STYLE+set}" = set; then TIME_STYLE=posix-long-iso export TIME_STYLE fi save_arg1=$1 # Find out how to get the extended ls output of a file or directory. if ls -L /dev/null 1>/dev/null 2>&1; then ls_command='ls -L -l -d' else ls_command='ls -l -d' fi # Avoid user/group names that might have spaces, when possible. if ls -n /dev/null 1>/dev/null 2>&1; then ls_command="$ls_command -n" fi # A 'ls -l' line looks as follows on OS/2. # drwxrwx--- 0 Aug 11 2001 foo # This differs from Unix, which adds ownership information. # drwxrwx--- 2 root root 4096 Aug 11 2001 foo # # To find the date, we split the line on spaces and iterate on words # until we find a month. This cannot work with files whose owner is a # user named "Jan", or "Feb", etc. However, it's unlikely that '/' # will be owned by a user whose name is a month. So we first look at # the extended ls output of the root directory to decide how many # words should be skipped to get the date. # On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. set x`$ls_command /` # Find which argument is the month. month= command= until test $month do test $# -gt 0 || error "failed parsing '$ls_command /' output" shift # Add another shift to the command. command="$command shift;" case $1 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac done test -n "$month" || error "failed parsing '$ls_command /' output" # Get the extended ls output of the file or directory. set dummy x`eval "$ls_command \"\\\$save_arg1\""` # Remove all preceding arguments eval $command # Because of the dummy argument above, month is in $2. # # On a POSIX system, we should have # # $# = 5 # $1 = file size # $2 = month # $3 = day # $4 = year or time # $5 = filename # # On Darwin 7.7.0 and 7.6.0, we have # # $# = 4 # $1 = day # $2 = month # $3 = year or time # $4 = filename # Get the month. case $2 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac case $3 in ???*) day=$1;; *) day=$3; shift;; esac # Here we have to deal with the problem that the ls output gives either # the time of day or the year. case $3 in *:*) set `date`; eval year=\$$# case $2 in Jan) nummonthtod=1;; Feb) nummonthtod=2;; Mar) nummonthtod=3;; Apr) nummonthtod=4;; May) nummonthtod=5;; Jun) nummonthtod=6;; Jul) nummonthtod=7;; Aug) nummonthtod=8;; Sep) nummonthtod=9;; Oct) nummonthtod=10;; Nov) nummonthtod=11;; Dec) nummonthtod=12;; esac # For the first six month of the year the time notation can also # be used for files modified in the last year. if (expr $nummonth \> $nummonthtod) > /dev/null; then year=`expr $year - 1` fi;; *) year=$3;; esac # The result. echo $day $month $year # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: openocd-0.9.0/doc/stamp-vti0000644000175000017500000000013312526201705012501 00000000000000@set UPDATED 18 May 2015 @set UPDATED-MONTH May 2015 @set EDITION 0.9.0 @set VERSION 0.9.0 openocd-0.9.0/doc/texinfo.tex0000644000175000017500000116703612526201647013056 00000000000000% texinfo.tex -- TeX macros to handle Texinfo files. % % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % \def\texinfoversion{2013-02-01.11} % % Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, % 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. % % This texinfo.tex 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 texinfo.tex 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 . % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without % restriction. This Exception is an additional permission under section 7 % of the GNU General Public License, version 3 ("GPLv3"). % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: % http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or % http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or % http://www.gnu.org/software/texinfo/ (the Texinfo home page) % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % % Send bug reports to bug-texinfo@gnu.org. Please include including a % complete document in each bug report with which we can reproduce the % problem. Patches are, of course, greatly appreciated. % % To process a Texinfo manual with TeX, it's most reliable to use the % texi2dvi shell script that comes with the distribution. For a simple % manual foo.texi, however, you can get away with this: % tex foo.texi % texindex foo.?? % tex foo.texi % tex foo.texi % dvips foo.dvi -o # or whatever; this makes foo.ps. % The extra TeX runs get the cross-reference information correct. % Sometimes one run after texindex suffices, and sometimes you need more % than two; texi2dvi does it as many times as necessary. % % It is possible to adapt texinfo.tex for other languages, to some % extent. You can get the existing language-specific files from the % full Texinfo distribution. % % The GNU Texinfo home page is http://www.gnu.org/software/texinfo. \message{Loading texinfo [version \texinfoversion]:} % If in a .fmt file, print the version number % and turn on active characters that we couldn't do earlier because % they might have appeared in the input file name. \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. % For @tex, we can use \tabalign. \let\+ = \relax % Save some plain tex macros whose names we will redefine. \let\ptexb=\b \let\ptexbullet=\bullet \let\ptexc=\c \let\ptexcomma=\, \let\ptexdot=\. \let\ptexdots=\dots \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! \let\ptexfootnote=\footnote \let\ptexgtr=> \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexnewwrite\newwrite \let\ptexnoindent=\noindent \let\ptexplus=+ \let\ptexraggedright=\raggedright \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t \let\ptextop=\top {\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J % Use TeX 3.0's \inputlineno to get the line number, for better error % messages, but if we're using an old version of TeX, don't do anything. % \ifx\inputlineno\thisisundefined \let\linenumber = \empty % Pre-3.0. \else \def\linenumber{l.\the\inputlineno:\space} \fi % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi \ifx\putworderror\undefined \gdef\putworderror{error}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi \ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi \ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi \ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi \ifx\putwordof\undefined \gdef\putwordof{of}\fi \ifx\putwordon\undefined \gdef\putwordon{on}\fi \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi \ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi \ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi % \ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi \ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi \ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi \ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi \ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi \ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi \ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi \ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi \ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi \ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi \ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi \ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi % \ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi \ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi \ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi % Since the category of space is not known, we have to be careful. \chardef\spacecat = 10 \def\spaceisspace{\catcode`\ =\spacecat} % sometimes characters are active, so we need control sequences. \chardef\ampChar = `\& \chardef\colonChar = `\: \chardef\commaChar = `\, \chardef\dashChar = `\- \chardef\dotChar = `\. \chardef\exclamChar= `\! \chardef\hashChar = `\# \chardef\lquoteChar= `\` \chardef\questChar = `\? \chardef\rquoteChar= `\' \chardef\semiChar = `\; \chardef\slashChar = `\/ \chardef\underChar = `\_ % Ignore a token. % \def\gobble#1{} % The following is used inside several \edef's. \def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. \hyphenation{ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script ap-pen-dix bit-map bit-maps data-base data-bases eshell fall-ing half-way long-est man-u-script man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces spell-ing spell-ings stand-alone strong-est time-stamp time-stamps which-ever white-space wide-spread wrap-around } % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight % For a final copy, take out the rectangles % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % \def\finalout{\overfullrule=0pt } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make % some effort to order the tracing commands to reduce output in the log % file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% \def\loggingall{% \tracingstats2 \tracingpages1 \tracinglostchars2 % 2 gives us more in etex \tracingparagraphs1 \tracingoutput1 \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen \ifx\eTeXversion\thisisundefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 \tracingnesting2 \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex \errorcontextlines16 }% % @errormsg{MSG}. Do the index-like expansions on MSG, but if things % aren't perfect, it's not the end of the world, being an error message, % after all. % \def\errormsg{\begingroup \indexnofonts \doerrormsg} \def\doerrormsg#1{\errmessage{#1}} % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % \def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount \removelastskip\penalty-50\smallskip\fi\fi} \def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi\fi} \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} % Do @cropmarks to get crop marks. % \newif\ifcropmarks \let\cropmarks = \cropmarkstrue % % Dimensions to add cropmarks at corners. % Added by P. A. MacKay, 12 Nov. 1986 % \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines \newdimen\cornerlong \cornerlong=1pc \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Output a mark which sets \thischapter, \thissection and \thiscolor. % We dump everything together because we only have one kind of mark. % This works because we only use \botmark / \topmark, not \firstmark. % % A mark contains a subexpression of the \ifcase ... \fi construct. % \get*marks macros below extract the needed part using \ifcase. % % Another complication is to let the user choose whether \thischapter % (\thissection) refers to the chapter (section) in effect at the top % of a page, or that at the bottom of a page. The solution is % described on page 260 of The TeXbook. It involves outputting two % marks for the sectioning macros, one before the section break, and % one after. I won't pretend I can describe this better than DEK... \def\domark{% \toks0=\expandafter{\lastchapterdefs}% \toks2=\expandafter{\lastsectiondefs}% \toks4=\expandafter{\prevchapterdefs}% \toks6=\expandafter{\prevsectiondefs}% \toks8=\expandafter{\lastcolordefs}% \mark{% \the\toks0 \the\toks2 \noexpand\or \the\toks4 \the\toks6 \noexpand\else \the\toks8 }% } % \topmark doesn't work for the very first chapter (after the title % page or the contents), so we use \firstmark there -- this gets us % the mark with the chapter defs, unless the user sneaks in, e.g., % @setcolor (or @url, or @link, etc.) between @contents and the very % first @chapter. \def\gettopheadingmarks{% \ifcase0\topmark\fi \ifx\thischapter\empty \ifcase0\firstmark\fi \fi } \def\getbottomheadingmarks{\ifcase1\botmark\fi} \def\getcolormarks{\ifcase2\topmark\fi} % Avoid "undefined control sequence" errors. \def\lastchapterdefs{} \def\lastsectiondefs{} \def\prevchapterdefs{} \def\prevsectiondefs{} \def\lastcolordefs{} % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} \newbox\headlinebox \newbox\footlinebox % \onepageout takes a vbox as an argument. Note that \pagecontents % does insertions, but you have to call it yourself. \def\onepageout#1{% \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if % the page break happens to be in the middle of an example. % We don't want .vr (or whatever) entries like this: % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} % "\acronym" won't work when it's read back in; % it needs to be % {\code {{\tt \backslashcurfont }acronym} \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize \vskip-\topandbottommargin \vtop to0pt{% \line{\ewtop\hfil\ewtop}% \nointerlineskip \line{% \vbox{\moveleft\cornerthick\nstop}% \hfill \vbox{\moveright\cornerthick\nstop}% }% \vss}% \vskip\topandbottommargin \line\bgroup \hfil % center the page within the outer (page) hsize. \ifodd\pageno\hskip\bindingoffset\fi \vbox\bgroup \fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. % (We lessened \vsize for it in \oddfootingyyy.) % The \baselineskip=24pt in plain's \makefootline has no effect. \vskip 24pt \unvbox\footlinebox \fi % \ifcropmarks \egroup % end of \vbox\bgroup \hfil\egroup % end of (centering) \line\bgroup \vskip\topandbottommargin plus1fill minus1fill \boxmaxdepth = \cornerthick \vbox to0pt{\vss \line{% \vbox{\moveleft\cornerthick\nsbot}% \hfill \vbox{\moveright\cornerthick\nsbot}% }% \nointerlineskip \line{\ewbot\hfil\ewbot}% }% \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox }% end of group with \indexdummies \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi \dimen@=\dp#1\relax \unvbox#1\relax \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } % Here are the rules for the cropmarks. Note that they are % offset so that the space between them is truly \outerhsize or \outervsize % (P. A. MacKay, 12 November, 1986) % \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} \def\nstop{\vbox {\hrule height\cornerthick depth\cornerlong width\cornerthick}} \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} \def\nsbot{\vbox {\hrule height\cornerlong depth\cornerthick width\cornerthick}} % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% \def\argtorun{#2}% \begingroup \obeylines \spaceisspace #1% \parseargline\empty% Insert the \empty token, see \finishparsearg below. } {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. \argremovecomment #1\comment\ArgTerm% }% } % First remove any @comment, then any @c comment. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} % Each occurrence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo % This space token undergoes the same procedure and is eventually removed % by \finishparsearg. % \def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} \def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: \let\temp\finishparsearg \else \let\temp\argcheckspaces \fi % Put the space token in: \temp#1 #3\ArgTerm } % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \argtorun. % (Similarly, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % \def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} % % Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % favourite TeX trick. --kasal, 16nov03 \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } \def\doparseargdef#1#2{% \def#2{\parsearg#1}% \def#1##1% } % Several utility definitions with active space: { \obeyspaces \gdef\obeyedspace{ } % Make each space character in the input produce a normal interword % space in the output. Don't allow a line break at this space, as this % is used only in environments like @example, where each line of input % should produce a line of output anyway. % \gdef\sepspaces{\obeyspaces\let =\tie} % If an index command is used in an @example environment, any spaces % therein should become regular spaces in the raw index file, not the % expansion of \tie (\leavevmode \penalty \@M \ ). \gdef\unsepspaces{\let =\space} } \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} % Define the framework for environments in texinfo.tex. It's used like this: % % \envdef\foo{...} % \def\Efoo{...} % % It's the responsibility of \envdef to insert \begingroup before the % actual body; @end closes the group after calling \Efoo. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they % are not treated as environments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) % At run-time, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty % ... but they get defined via ``\envdef\foo{...}'': \long\def\envdef#1#2{\def#1{\startenvironment#1#2}} \def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} % Check whether we're in the right environment: \def\checkenv#1{% \def\temp{#1}% \ifx\thisenv\temp \else \badenverr \fi } % Environment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, not \inenvironment\thisenv}% } \def\inenvironment#1{% \ifx#1\empty outside of any environment% \else in environment \expandafter\string#1% \fi } % @end foo executes the definition of \Efoo. % But first, it executes a specialized version of \checkenv % \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else % The general wording of \badenverr may not be ideal. \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup \fi } \newhelp\EMsimple{Press RETURN to continue.} % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and % since \penalty is valid in vertical mode, we'd end up putting the % penalty on the vertical list instead of in the new paragraph. {\catcode`@ = 11 % Avoid using \@M directly, because that causes trouble % if the definition is written into an index file. \global\let\tiepenalty = \@M \gdef\tie{\leavevmode\penalty\tiepenalty\ } } % @: forces normal size whitespace following. \def\:{\spacefactor=1000 } % @* forces a line break. \def\*{\unskip\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. \def\.{.\spacefactor=\endofsentencespacefactor\space} % @! is an end-of-sentence bang. \def\!{!\spacefactor=\endofsentencespacefactor\space} % @? is an end-of-sentence query. \def\?{?\spacefactor=\endofsentencespacefactor\space} % @frenchspacing on|off says whether to put extra space after punctuation. % \def\onword{on} \def\offword{off} % \parseargdef\frenchspacing{% \def\temp{#1}% \ifx\temp\onword \plainfrenchspacing \else\ifx\temp\offword \plainnonfrenchspacing \else \errhelp = \EMsimple \errmessage{Unknown @frenchspacing option `\temp', must be on|off}% \fi\fi } % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would % produce a whole line of output instead of starting the paragraph. \def\w#1{\leavevmode\hbox{#1}} % @group ... @end group forces ... to be all on one page, by enclosing % it in a TeX vbox. We use \vtop instead of \vbox to construct the box % to keep its height that of a normal line. According to the rules for % \topskip (p.114 of the TeXbook), the glue inserted is % max (\topskip - \ht (first item), 0). If that height is large, % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % % Another complication is that the group might be very large. This can % cause the glue on the previous page to be unduly stretched, because it % does not have much material. In this case, it's better to add an % explicit \vfill so that the extra space is at the bottom. The % threshold for doing this is if the group is more than \vfilllimit % percent of a page (\vfilllimit can be changed inside of @tex). % \newbox\groupbox \def\vfilllimit{0.7} % \envdef\group{% \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi \startsavinginserts % \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after % the `@group' to put extra space in the output. Since @group % should appear on a line by itself (according to the Texinfo % manual), we don't worry about eating any user text. \comment } % % The \vtop produces a box with normal height and large depth; thus, TeX puts % \baselineskip glue before it, and (when the next line of text is done) % \lineskip glue after it. Thus, space below is not quite equal to space % above. But it's pretty close. \def\Egroup{% % To get correct interline space between the last line of the group % and the first line afterwards, we have to propagate \prevdepth. \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). \dimen2 = \pageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 \ifdim \pagetotal < \vfilllimit\pageheight \page \fi \fi \box\groupbox \prevdepth = \dimen1 \checkinserts } % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % \newhelp\groupinvalidhelp{% group can only be used in environments such as @example,^^J% where each line of input produces a line of output.} % @need space-in-mils % forces a page break if there is not space-in-mils remaining. \newdimen\mil \mil=0.001in \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % % If the @need value is less than one line space, it's useless. \dimen0 = #1\mil \dimen2 = \ht\strutbox \advance\dimen2 by \dp\strutbox \ifdim\dimen0 > \dimen2 % % Do a \strut just to make the height of this box be normal, so the % normal leading is inserted relative to the preceding line. % And a page break here is fine. \vtop to #1\mil{\strut\vfil}% % % TeX does not even consider page breaks if a penalty added to the % main vertical list is 10000 or more. But in order to see if the % empty box we just added fits on the page, we must make it consider % page breaks. On the other hand, we don't want to actually break the % page after the empty box. So we use a penalty of 9999. % % There is an extremely small chance that TeX will actually break the % page at this \penalty, if there are no other feasible breakpoints in % sight. (If the user is using lots of big @group commands, which % almost-but-not-quite fill up a page, TeX will have a hard time doing % good page breaking, for example.) However, I could not construct an % example where a page broke at this \penalty; if it happens in a real % document, then we can reconsider our strategy. \penalty9999 % % Back up by the size of the box, whether we did a page break or not. \kern -#1\mil % % Do not allow a page break right after this kern. \nobreak \fi } % @br forces paragraph break (and is undocumented). \let\br = \par % @page forces the start of a new page. % \def\page{\par\vfill\supereject} % @exdent text.... % outputs text on separate line in roman font, starting at standard page margin % This records the amount of indent in the innermost environment. % That's how much \exdent should take out. \newskip\exdentamount % This defn is used inside fill environments such as @defun. \parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. \parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount \leftline{\hskip\leftskip{\rm#1}}}} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion % class. WHICH is `l' or `r'. Not documented, written for gawk manual. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} % \def\doinmargin#1#2{\strut\vadjust{% \nobreak \kern-\strutdepth \vtop to \strutdepth{% \baselineskip=\strutdepth \vss % if you have multiple lines of stuff to put here, you'll need to % make the vbox yourself of the appropriate size. \ifx#1l% \llap{\ignorespaces #2\hskip\inmarginspacing}% \else \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% \fi \null }% }} \def\inleftmargin{\doinmargin l} \def\inrightmargin{\doinmargin r} % % @inmargin{TEXT [, RIGHT-TEXT]} % (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; % else use TEXT for both). % \def\inmargin#1{\parseinmargin #1,,\finish} \def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \def\lefttext{#1}% have both texts \def\righttext{#2}% \else \def\lefttext{#1}% have only one text \def\righttext{#1}% \fi % \ifodd\pageno \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin \else \def\temp{\inleftmargin\lefttext}% \fi \temp } % @| inserts a changebar to the left of the current line. It should % surround any changed text. This approach does *not* work if the % change spans more than two lines of output. To handle that, we would % have adopt a much more difficult approach (putting marks into the main % vertical list for the beginning and end of each change). This command % is not documented, not supported, and doesn't work. % \def\|{% % \vadjust can only be used in horizontal mode. \leavevmode % % Append this vertical mode material after the current line in the output. \vadjust{% % We want to insert a rule with the height and depth of the current % leading; that is exactly what \strutbox is supposed to record. \vskip-\baselineskip % % \vadjust-items are inserted at the left edge of the type. So % the \llap here moves out into the left-hand margin. \llap{% % % For a thicker or thinner bar, change the `1pt'. \vrule height\baselineskip width1pt % % This is the space between the bar and the text. \hskip 12pt }% }% } % @include FILE -- \input text of FILE. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% \makevalueexpandable % we want to expand any @value in FILE. \turnoffactive % and allow special characters in the expansion \indexnofonts % Allow `@@' and other weird things in file names. \wlog{texinfo.tex: doing @include of #1^^J}% \edef\temp{\noexpand\input #1 }% % % This trickery is to read FILE outside of a group, in case it makes % definitions, etc. \expandafter }\temp \popthisfilestack } \def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other \catcode`_=\other \catcode`|=\other \catcode`<=\other \catcode`>=\other \catcode`+=\other \catcode`-=\other \catcode`\`=\other \catcode`\'=\other } \def\pushthisfilestack{% \expandafter\pushthisfilestackX\popthisfilestack\StackTerm } \def\pushthisfilestackX{% \expandafter\pushthisfilestackY\thisfile\StackTerm } \def\pushthisfilestackY #1\StackTerm #2\StackTerm {% \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% } \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} % \def\thisfile{} % @center line % outputs that line, centered. % \parseargdef\center{% \ifhmode \let\centersub\centerH \else \let\centersub\centerV \fi \centersub{\hfil \ignorespaces#1\unskip \hfil}% \let\centersub\relax % don't let the definition persist, just in case } \def\centerH#1{{% \hfil\break \advance\hsize by -\leftskip \advance\hsize by -\rightskip \line{#1}% \break }} % \newcount\centerpenalty \def\centerV#1{% % The idea here is the same as in \startdefun, \cartouche, etc.: if % @center is the first thing after a section heading, we need to wipe % out the negative parskip inserted by \sectionheading, but still % prevent a page break here. \centerpenalty = \lastpenalty \ifnum\centerpenalty>10000 \vskip\parskip \fi \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi \line{\kern\leftskip #1\kern\rightskip}% } % @sp n outputs n lines of vertical space % \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment % \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} % \let\c=\comment % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. % NCHARS can also be the word `asis' or `none'. % We cannot feasibly implement @paragraphindent asis, though. % \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % \parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \defaultparindent = 0pt \else \defaultparindent = #1em \fi \fi \parindent = \defaultparindent } % @exampleindent NCHARS % We'll use ems for NCHARS like @paragraphindent. % It seems @exampleindent asis isn't necessary, but % I preserve it to make it similar to @paragraphindent. \parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \lispnarrowing = 0pt \else \lispnarrowing = #1em \fi \fi } % @firstparagraphindent WORD % If WORD is `none', then suppress indentation of the first paragraph % after a section heading. If WORD is `insert', then do indent at such % paragraphs. % % The paragraph indentation is suppressed or not by calling % \suppressfirstparagraphindent, which the sectioning commands do. % We switch the definition of this back and forth according to WORD. % By default, we suppress indentation. % \def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} \def\insertword{insert} % \parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent \else\ifx\temp\insertword \let\suppressfirstparagraphindent = \relax \else \errhelp = \EMsimple \errmessage{Unknown @firstparagraphindent option `\temp'}% \fi\fi } % Here is how we actually suppress indentation. Redefine \everypar to % \kern backwards by \parindent, and then reset itself to empty. % % We also make \indent itself not actually do anything until the next % paragraph. % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% \restorefirstparagraphindent \indent }% \gdef\noindent{% \restorefirstparagraphindent \noindent }% \global\everypar = {% \kern -\parindent \restorefirstparagraphindent }% } \gdef\restorefirstparagraphindent{% \global \let \indent = \ptexindent \global \let \noindent = \ptexnoindent \global \everypar = {}% } % @refill is a no-op. \let\refill=\relax % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate (before @setfilename). % \newif\iflinks \linkstrue % by default we want the aux files. \let\novalidate = \linksfalse % @setfilename is done at the beginning of every texinfo file. % So open here the files we need to have open while reading the input. % This makes it possible to make a .fmt file for texinfo. \def\setfilename{% \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks \tryauxfile % Open the new aux file. TeX will close it automatically at exit. \immediate\openout\auxfile=\jobname.aux \fi % \openindices needs to do some work in any case. \openindices \let\setfilename=\comment % Ignore extra @setfilename cmds. % % If texinfo.cnf is present on the system, read it. % Useful for site-wide @afourpaper, etc. \openin 1 texinfo.cnf \ifeof 1 \else \input texinfo.cnf \fi \closein 1 % \comment % Ignore the actual filename. } % Called from \setfilename. % \def\openindices{% \newindex{cp}% \newcodeindex{fn}% \newcodeindex{vr}% \newcodeindex{tp}% \newcodeindex{ky}% \newcodeindex{pg}% } % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \message{pdf,} % adobe `portable' document format \newcount\tempnum \newcount\lnkcount \newtoks\filename \newcount\filenamelength \newcount\pgn \newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD \newbox\boxA \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as being undefined. \ifx\pdfoutput\thisisundefined \else \ifx\pdfoutput\relax \else \ifcase\pdfoutput \else \pdftrue \fi \fi \fi % PDF uses PostScript string constants for the names of xref targets, % for display in the outlines, and in other places. Thus, we have to % double any backslashes. Otherwise, a name like "\node" will be % interpreted as a newline (\n), followed by o, d, e. Not good. % % See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and % related messages. The final outcome is that it is up to the TeX user % to double the backslashes and otherwise make the string valid, so % that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to % do this reliably, so we use it. % #1 is a control sequence in which to do the replacements, % which we \xdef. \def\txiescapepdf#1{% \ifx\pdfescapestring\thisisundefined % No primitive available; should we give a warning or log? % Many times it won't matter. \else % The expandable \pdfescapestring primitive escapes parentheses, % backslashes, and other special chars. \xdef#1{\pdfescapestring{#1}}% \fi } \newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images with PDF output, and none of those formats could be found. (.eps cannot be supported due to the design of the PDF format; use regular TeX (DVI output) for that.)} \ifpdf % % Color manipulation macros based on pdfcolor.tex, % except using rgb instead of cmyk; the latter is said to render as a % very dark gray on-screen and a very dark halftone in print, instead % of actual black. \def\rgbDarkRed{0.50 0.09 0.12} \def\rgbBlack{0 0 0} % % k sets the color for filling (usual text, etc.); % K sets the color for stroking (thin rules, e.g., normal _'s). \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} % % Set color, and create a mark which defines \thiscolor accordingly, % so that \makeheadline knows which color to restore. \def\setcolor#1{% \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% \domark \pdfsetcolor{#1}% } % \def\maincolor{\rgbBlack} \pdfsetcolor{\maincolor} \edef\thiscolor{\maincolor} \def\lastcolordefs{} % \def\makefootline{% \baselineskip24pt \line{\pdfsetcolor{\maincolor}\the\footline}% } % \def\makeheadline{% \vbox to 0pt{% \vskip-22.5pt \line{% \vbox to8.5pt{}% % Extract \thiscolor definition from the marks. \getcolormarks % Typeset the headline with \maincolor, then restore the color. \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% }% \vss }% \nointerlineskip } % % \pdfcatalog{/PageMode /UseOutlines} % % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). \def\dopdfimage#1#2#3{% \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% % % pdftex (and the PDF format) support .pdf, .png, .jpg (among % others). Let's try in that order, PDF first since if % someone has a scalable image, presumably better to use that than a % bitmap. \let\pdfimgext=\empty \begingroup \openin 1 #1.pdf \ifeof 1 \openin 1 #1.PDF \ifeof 1 \openin 1 #1.png \ifeof 1 \openin 1 #1.jpg \ifeof 1 \openin 1 #1.jpeg \ifeof 1 \openin 1 #1.JPG \ifeof 1 \errhelp = \nopdfimagehelp \errmessage{Could not find image file #1 for pdf}% \else \gdef\pdfimgext{JPG}% \fi \else \gdef\pdfimgext{jpeg}% \fi \else \gdef\pdfimgext{jpg}% \fi \else \gdef\pdfimgext{png}% \fi \else \gdef\pdfimgext{PDF}% \fi \else \gdef\pdfimgext{pdf}% \fi \closein 1 \endgroup % % without \immediate, ancient pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi \ifdim \wd0 >0pt width \pdfimagewidth \fi \ifdim \wd2 >0pt height \pdfimageheight \fi \ifnum\pdftexversion<13 #1.\pdfimgext \else {#1.\pdfimgext}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} % \def\pdfmkdest#1{{% % We have to set dummies so commands such as @code, and characters % such as \, aren't expanded when present in a section title. \indexnofonts \turnoffactive \makevalueexpandable \def\pdfdestname{#1}% \txiescapepdf\pdfdestname \safewhatsit{\pdfdest name{\pdfdestname} xyz}% }} % % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % % by default, use a color that is dark enough to print on paper as % nearly black, but still distinguishable for online viewing. \def\urlcolor{\rgbDarkRed} \def\linkcolor{\rgbDarkRed} \def\endlink{\setcolor{\maincolor}\pdfendlink} % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% \else \csname#1\endcsname \fi} \def\advancenumber#1{\tempnum=\expnumber{#1}\relax \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % % #1 is the section text, which is what will be displayed in the % outline by the pdf viewer. #2 is the pdf expression for the number % of subentries (or empty, for subsubsections). #3 is the node text, % which might be empty if this toc entry had no corresponding node. % #4 is the page number % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worth the trouble, since most documents are normally structured. \edef\pdfoutlinedest{#3}% \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}% \else \txiescapepdf\pdfoutlinedest \fi % % Also escape PDF chars in the display string. \edef\pdfoutlinetext{#1}% \txiescapepdf\pdfoutlinetext % \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% } % \def\pdfmakeoutlines{% \begingroup % Read toc silently, to get counts of subentries for \pdfoutline. \def\partentry##1##2##3##4{}% ignore parts in the outlines \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% \def\thissecnum{0}% \def\thissubsecnum{0}% }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% \def\thissubsecnum{0}% }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% \def\thissubsecnum{##2}% }% \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% \def\thischapnum{0}% \def\thissecnum{0}% \def\thissubsecnum{0}% % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. \def\appentry{\numchapentry}% \def\appsecentry{\numsecentry}% \def\appsubsecentry{\numsubsecentry}% \def\appsubsubsecentry{\numsubsubsecentry}% \def\unnchapentry{\numchapentry}% \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of % subentries, which we calculated on our first read of the .toc above. % % We use the node names as the destinations. \def\numchapentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \def\numsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \def\numsubsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, % since the encoding is unknown. For example, the eogonek from % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % % TODO this right, we have to translate 8-bit characters to % their "best" equivalent, based on the @documentencoding. Too % much work for too little return. Just use the ASCII equivalents % we use for the index sort strings. % \indexnofonts \setupdatafile % We can have normal brace characters in the PDF outlines, unlike % Texinfo index files. So set that up. \def\{{\lbracecharliteral}% \def\}{\rbracecharliteral}% \catcode`\\=\active \otherbackslash \input \tocreadfilename \endgroup } {\catcode`[=1 \catcode`]=2 \catcode`{=\other \catcode`}=\other \gdef\lbracecharliteral[{]% \gdef\rbracecharliteral[}]% ] % \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces \addtokens{\filename}{\PP}% \advance\filenamelength by 1 \fi \nextsp} \def\getfilename#1{% \filenamelength=0 % If we don't expand the argument now, \skipspaces will get % snagged on things like "@value{foo}". \edef\temp{#1}% \expandafter\skipspaces\temp|\relax } \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi % make a live url in pdf output. \def\pdfurl#1{% \begingroup % it seems we really need yet another set of dummies; have not % tried to figure out what each command should do in the context % of @url. for now, just make @/ a no-op, that's the only one % people have actually reported a problem with. % \normalturnoffactive \def\@{@}% \let\/=\empty \makevalueexpandable % do we want to go so far as to use \indexnofonts instead of just % special-casing \var here? \def\var##1{##1}% % \leavevmode\setcolor{\urlcolor}% \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} \def\maketoks{% \expandafter\poptoks\the\toksA|ENDTOKS|\relax \ifx\first0\adn0 \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 \else \ifnum0=\countA\else\makelink\fi \ifx\first.\let\next=\done\else \let\next=\maketoks \addtokens{\toksB}{\the\toksD} \ifx\first,\addtokens{\toksB}{\space}\fi \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next} \def\makelink{\addtokens{\toksB}% {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \setcolor{\linkcolor}#1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else % non-pdf mode \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax \let\setcolor = \gobble \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput \message{fonts,} % Change the current font style to #1, remembering it in \curfontstyle. % For now, we do not accumulate font styles: @b{@i{foo}} prints foo in % italics, not bold italics. % \def\setfontstyle#1{% \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. \csname ten#1\endcsname % change the current font } % Select #1 fonts with the current style. % \def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} \def\tt{\fam=\ttfam \setfontstyle{tt}} % Unfortunately, we have to override this for titles and the like, since % in those cases "rm" is bold. Sigh. \def\rmisbold{\rm\def\curfontstyle{bf}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam \def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. % \def\lineskipfactor{.08333} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % % can get a sort of poor man's double spacing by redefining this. \def\baselinefactor{1} % \newdimen\textleading \def\setleading#1{% \dimen0 = #1\relax \normalbaselineskip = \baselinefactor\dimen0 \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% \vrule width0pt height\strutheightpercent\baselineskip depth \strutdepthpercent \baselineskip }% } % PDF CMaps. See also LaTeX's t1.cmap. % % do nothing with this by default. \expandafter\let\csname cmapOT1\endcsname\gobble \expandafter\let\csname cmapOT1IT\endcsname\gobble \expandafter\let\csname cmapOT1TT\endcsname\gobble % if we are producing pdf, and we have \pdffontattr, then define cmaps. % (\pdffontattr was introduced many years ago, but people still run % older pdftex's; it's easy to conditionalize, so we do.) \ifpdf \ifx\pdffontattr\thisisundefined \else \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1-0) %%Title: (TeX-OT1-0 TeX OT1 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1) /Supplement 0 >> def /CMapName /TeX-OT1-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <23> <26> <0023> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 40 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1IT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1IT-0) %%Title: (TeX-OT1IT-0 TeX OT1IT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1IT) /Supplement 0 >> def /CMapName /TeX-OT1IT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <25> <26> <0025> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 42 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <23> <0023> <24> <00A3> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1IT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1TT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1TT-0) %%Title: (TeX-OT1TT-0 TeX OT1TT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1TT) /Supplement 0 >> def /CMapName /TeX-OT1TT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 5 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <21> <26> <0021> <28> <5F> <0028> <61> <7E> <0061> endbfrange 32 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <2191> <0C> <2193> <0D> <0027> <0E> <00A1> <0F> <00BF> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <20> <2423> <27> <2019> <60> <2018> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1TT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% \fi\fi % Set the font macro #1 to the font named \fontprefix#2. % #3 is the font's design size, #4 is a scale factor, #5 is the CMap % encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). % Example: % #1 = \textrm % #2 = \rmshape % #3 = 10 % #4 = \mainmagstep % #5 = OT1 % \def\setfont#1#2#3#4#5{% \font#1=\fontprefix#2#3 scaled #4 \csname cmap#5\endcsname#1% } % This is what gets called when #5 of \setfont is empty. \let\cmap\gobble % % (end of cmaps) % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. \ifx\fontprefix\thisisundefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} \def\rmbshape{bx} % where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} \def\ttbshape{tt} \def\ttslshape{sltt} \def\itshape{ti} \def\itbshape{bxti} \def\slshape{sl} \def\slbshape{bxsl} \def\sfshape{ss} \def\sfbshape{ss} \def\scshape{csc} \def\scbshape{csc} % Definitions for a main text size of 11pt. (The default in Texinfo.) % \def\definetextfontsizexi{% % Text fonts (11.2pt, magstep1). \def\textnominalsize{11pt} \edef\mainmagstep{\magstephalf} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1095} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1}{OT1} \setfont\deftt\ttshape{10}{\magstep1}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\titleecsize{2074} % Chapter (and unnumbered) fonts (17.28pt). \def\chapnominalsize{17pt} \setfont\chaprm\rmbshape{12}{\magstep2}{OT1} \setfont\chapit\itbshape{10}{\magstep3}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep3}{OT1} \setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} \setfont\chapsf\sfbshape{17}{1000}{OT1} \let\chapbf=\chaprm \setfont\chapsc\scbshape{10}{\magstep3}{OT1} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 \def\chapecsize{1728} % Section fonts (14.4pt). \def\secnominalsize{14pt} \setfont\secrm\rmbshape{12}{\magstep1}{OT1} \setfont\secit\itbshape{10}{\magstep2}{OT1IT} \setfont\secsl\slbshape{10}{\magstep2}{OT1} \setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\secsf\sfbshape{12}{\magstep1}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep2}{OT1} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 \def\sececsize{1440} % Subsection fonts (13.15pt). \def\ssecnominalsize{13pt} \setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} \setfont\ssecit\itbshape{10}{1315}{OT1IT} \setfont\ssecsl\slbshape{10}{1315}{OT1} \setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} \setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1315}{OT1} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 \def\ssececsize{1200} % Reduced fonts for @acro in text (10pt). \def\reducednominalsize{10pt} \setfont\reducedrm\rmshape{10}{1000}{OT1} \setfont\reducedtt\ttshape{10}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{1000}{OT1} \setfont\reducedit\itshape{10}{1000}{OT1IT} \setfont\reducedsl\slshape{10}{1000}{OT1} \setfont\reducedsf\sfshape{10}{1000}{OT1} \setfont\reducedsc\scshape{10}{1000}{OT1} \setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 \def\reducedecsize{1000} \textleading = 13.2pt % line spacing for 11pt CM \textfonts % reset the current fonts \rm } % end of 11pt text font size definitions, \definetextfontsizexi % Definitions to make the main text be 10pt Computer Modern, with % section, chapter, etc., sizes following suit. This is for the GNU % Press printing of the Emacs 22 manual. Maybe other manuals in the % future. Used with @smallbook, which sets the leading to 12pt. % \def\definetextfontsizex{% % Text fonts (10pt). \def\textnominalsize{10pt} \edef\mainmagstep{1000} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1000} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstephalf}{OT1} \setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\titleecsize{2074} % Chapter fonts (14.4pt). \def\chapnominalsize{14pt} \setfont\chaprm\rmbshape{12}{\magstep1}{OT1} \setfont\chapit\itbshape{10}{\magstep2}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep2}{OT1} \setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\chapsf\sfbshape{12}{\magstep1}{OT1} \let\chapbf\chaprm \setfont\chapsc\scbshape{10}{\magstep2}{OT1} \font\chapi=cmmi12 scaled \magstep1 \font\chapsy=cmsy10 scaled \magstep2 \def\chapecsize{1440} % Section fonts (12pt). \def\secnominalsize{12pt} \setfont\secrm\rmbshape{12}{1000}{OT1} \setfont\secit\itbshape{10}{\magstep1}{OT1IT} \setfont\secsl\slbshape{10}{\magstep1}{OT1} \setfont\sectt\ttbshape{12}{1000}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} \setfont\secsf\sfbshape{12}{1000}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep1}{OT1} \font\seci=cmmi12 \font\secsy=cmsy10 scaled \magstep1 \def\sececsize{1200} % Subsection fonts (10pt). \def\ssecnominalsize{10pt} \setfont\ssecrm\rmbshape{10}{1000}{OT1} \setfont\ssecit\itbshape{10}{1000}{OT1IT} \setfont\ssecsl\slbshape{10}{1000}{OT1} \setfont\ssectt\ttbshape{10}{1000}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} \setfont\ssecsf\sfbshape{10}{1000}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1000}{OT1} \font\sseci=cmmi10 \font\ssecsy=cmsy10 \def\ssececsize{1000} % Reduced fonts for @acro in text (9pt). \def\reducednominalsize{9pt} \setfont\reducedrm\rmshape{9}{1000}{OT1} \setfont\reducedtt\ttshape{9}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{900}{OT1} \setfont\reducedit\itshape{9}{1000}{OT1IT} \setfont\reducedsl\slshape{9}{1000}{OT1} \setfont\reducedsf\sfshape{9}{1000}{OT1} \setfont\reducedsc\scshape{10}{900}{OT1} \setfont\reducedttsl\ttslshape{10}{900}{OT1TT} \font\reducedi=cmmi9 \font\reducedsy=cmsy9 \def\reducedecsize{0900} \divide\parskip by 2 % reduce space between paragraphs \textleading = 12pt % line spacing for 10pt CM \textfonts % reset the current fonts \rm } % end of 10pt text font size definitions, \definetextfontsizex % We provide the user-level command % @fonttextsize 10 % (or 11) to redefine the text font size. pt is assumed. % \def\xiword{11} \def\xword{10} \def\xwordpt{10pt} % \parseargdef\fonttextsize{% \def\textsizearg{#1}% %\wlog{doing @fonttextsize \textsizearg}% % % Set \globaldefs so that documents can use this inside @tex, since % makeinfo 4.8 does not support it, but we need it nonetheless. % \begingroup \globaldefs=1 \ifx\textsizearg\xword \definetextfontsizex \else \ifx\textsizearg\xiword \definetextfontsizexi \else \errhelp=\EMsimple \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} \fi\fi \endgroup } % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since % texinfo doesn't allow for producing subscripts and superscripts except % in the main text, we don't bother to reset \scriptfont and % \scriptscriptfont (which would also require loading a lot more fonts). % \def\resetmathfonts{% \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf \textfont\ttfam=\tentt \textfont\sffam=\tensf } % The font-changing commands redefine the meanings of \tenSTYLE, instead % of just \STYLE. We do this because \STYLE needs to also set the % current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire % \tenSTYLE to set the current font. % % Each font-changing command also sets the names \lsize (one size lower) % and \lllsize (three sizes lower). These relative commands are used in % the LaTeX logo and acronyms. % % This all needs generalizing, badly. % \def\textfonts{% \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl \def\curfontsize{text}% \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl \def\curfontsize{title}% \def\lsize{chap}\def\lllsize{subsec}% \resetmathfonts \setleading{27pt}} \def\titlefont#1{{\titlefonts\rmisbold #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl \def\curfontsize{chap}% \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl \def\curfontsize{sec}% \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl \def\curfontsize{ssec}% \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts \def\reducedfonts{% \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl \def\curfontsize{reduced}% \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl \def\curfontsize{small}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl \def\curfontsize{smaller}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000}{OT1} \setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000}{OT1} \setfont\shortconttt\ttshape{12}{1000}{OT1TT} % Define these just so they can be easily changed for other fonts. \def\angleleft{$\langle$} \def\angleright{$\rangle$} % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts % About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample % can fit this many characters: % 8.5x11=86 smallbook=72 a4=90 a5=69 % If we use \scriptfonts (8pt), then we can fit this many characters: % 8.5x11=90+ smallbook=80 a4=90+ a5=77 % For me, subjectively, the few extra characters that fit aren't worth % the additional smallness of 8pt. So I'm making the default 9pt. % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % \definetextfontsizexi \message{markup,} % Check if we are currently using a typewriter font. Since all the % Computer Modern typewriter fonts have zero interword stretch (and % shrink), and it is reasonable to expect all typewriter fonts to have % this property, we can check that font parameter. % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } % Markup style infrastructure. \defmarkupstylesetup\INITMACRO will % define and register \INITMACRO to be called on markup style changes. % \INITMACRO can check \currentmarkupstyle for the innermost % style and the set of \ifmarkupSTYLE switches for all styles % currently in effect. \newif\ifmarkupvar \newif\ifmarkupsamp \newif\ifmarkupkey %\newif\ifmarkupfile % @file == @samp. %\newif\ifmarkupoption % @option == @samp. \newif\ifmarkupcode \newif\ifmarkupkbd %\newif\ifmarkupenv % @env == @code. %\newif\ifmarkupcommand % @command == @code. \newif\ifmarkuptex % @tex (and part of @math, for now). \newif\ifmarkupexample \newif\ifmarkupverb \newif\ifmarkupverbatim \let\currentmarkupstyle\empty \def\setupmarkupstyle#1{% \csname markup#1true\endcsname \def\currentmarkupstyle{#1}% \markupstylesetup } \let\markupstylesetup\empty \def\defmarkupstylesetup#1{% \expandafter\def\expandafter\markupstylesetup \expandafter{\markupstylesetup #1}% \def#1% } % Markup style setup for left and right quotes. \defmarkupstylesetup\markupsetuplq{% \expandafter\let\expandafter \temp \csname markupsetuplq\currentmarkupstyle\endcsname \ifx\temp\relax \markupsetuplqdefault \else \temp \fi } \defmarkupstylesetup\markupsetuprq{% \expandafter\let\expandafter \temp \csname markupsetuprq\currentmarkupstyle\endcsname \ifx\temp\relax \markupsetuprqdefault \else \temp \fi } { \catcode`\'=\active \catcode`\`=\active \gdef\markupsetuplqdefault{\let`\lq} \gdef\markupsetuprqdefault{\let'\rq} \gdef\markupsetcodequoteleft{\let`\codequoteleft} \gdef\markupsetcodequoteright{\let'\codequoteright} } \let\markupsetuplqcode \markupsetcodequoteleft \let\markupsetuprqcode \markupsetcodequoteright % \let\markupsetuplqexample \markupsetcodequoteleft \let\markupsetuprqexample \markupsetcodequoteright % \let\markupsetuplqkbd \markupsetcodequoteleft \let\markupsetuprqkbd \markupsetcodequoteright % \let\markupsetuplqsamp \markupsetcodequoteleft \let\markupsetuprqsamp \markupsetcodequoteright % \let\markupsetuplqverb \markupsetcodequoteleft \let\markupsetuprqverb \markupsetcodequoteright % \let\markupsetuplqverbatim \markupsetcodequoteleft \let\markupsetuprqverbatim \markupsetcodequoteright % Allow an option to not use regular directed right quote/apostrophe % (char 0x27), but instead the undirected quote from cmtt (char 0x0d). % The undirected quote is ugly, so don't make it the default, but it % works for pasting with more pdf viewers (at least evince), the % lilypond developers report. xpdf does work with the regular 0x27. % \def\codequoteright{% \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax '% \else \char'15 \fi \else \char'15 \fi } % % and a similar option for the left quote char vs. a grave accent. % Modern fonts display ASCII 0x60 as a grave accent, so some people like % the code environments to do likewise. % \def\codequoteleft{% \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax % [Knuth] pp. 380,381,391 % \relax disables Spanish ligatures ?` and !` of \tt font. \relax`% \else \char'22 \fi \else \char'22 \fi } % Commands to set the quote options. % \parseargdef\codequoteundirected{% \def\temp{#1}% \ifx\temp\onword \expandafter\let\csname SETtxicodequoteundirected\endcsname = t% \else\ifx\temp\offword \expandafter\let\csname SETtxicodequoteundirected\endcsname = \relax \else \errhelp = \EMsimple \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}% \fi\fi } % \parseargdef\codequotebacktick{% \def\temp{#1}% \ifx\temp\onword \expandafter\let\csname SETtxicodequotebacktick\endcsname = t% \else\ifx\temp\offword \expandafter\let\csname SETtxicodequotebacktick\endcsname = \relax \else \errhelp = \EMsimple \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}% \fi\fi } % [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. \def\noligaturesquoteleft{\relax\lq} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 % Font commands. % #1 is the font command (\sl or \it), #2 is the text to slant. % If we are in a monospaced environment, however, 1) always use \ttsl, % and 2) do not add an italic correction. \def\dosmartslant#1#2{% \ifusingtt {{\ttsl #2}\let\next=\relax}% {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% \next } \def\smartslanted{\dosmartslant\sl} \def\smartitalic{\dosmartslant\it} % Output an italic correction unless \next (presumed to be the following % character) is such as not to need one. \def\smartitaliccorrection{% \ifx\next,% \else\ifx\next-% \else\ifx\next.% \else\ptexslash \fi\fi\fi \aftersmartic } % Unconditional use \ttsl, and no ic. @var is set to this for defuns. \def\ttslanted#1{{\ttsl #1}} % @cite is like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? \def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} \def\aftersmartic{} \def\var#1{% \let\saveaftersmartic = \aftersmartic \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% \smartslanted{#1}% } \let\i=\smartitalic \let\slanted=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic % Explicit font changes: @r, @sc, undocumented @ii. \def\r#1{{\rm #1}} % roman font \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font % @b, explicit bold. Also @strong. \def\b#1{{\bf #1}} \let\strong=\b % @sansserif, explicit sans. \def\sansserif#1{{\sf #1}} % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. % \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } % Set sfcode to normal for the chars that usually have another value. % Can't use plain's \frenchspacing because it uses the `\x notation, and % sometimes \x has an active definition that messes things up. % \catcode`@=11 \def\plainfrenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m \def\endofsentencespacefactor{1000}% for @. and friends } \def\plainnonfrenchspacing{% \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 \def\endofsentencespacefactor{3000}% for @. and friends } \catcode`@=\other \def\endofsentencespacefactor{3000}% default % @t, explicit typewriter. \def\t#1{% {\tt \rawbackslash \plainfrenchspacing #1}% \null } % @samp. \def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} % @indicateurl is \samp, that is, with quotes. \let\indicateurl=\samp % @code (and similar) prints in typewriter, but with spaces the same % size as normal in the surrounding text, without hyphenation, etc. % This is a subroutine for that. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. \spaceskip = \fontdimen2\font % % Switch to typewriter. \tt % % But `\ ' produces the large typewriter interword space. \def\ {{\spaceskip = 0pt{} }}% % % Turn off hyphenation. \nohyphenation % \rawbackslash \plainfrenchspacing #1% }% \null % reset spacefactor to 1000 } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { \catcode`\-=\active \catcode`\_=\active \catcode`\'=\active \catcode`\`=\active \global\let'=\rq \global\let`=\lq % default definitions % \global\def\code{\begingroup \setupmarkupstyle{code}% % The following should really be moved into \setupmarkupstyle handlers. \catcode\dashChar=\active \catcode\underChar=\active \ifallowcodebreaks \let-\codedash \let_\codeunder \else \let-\normaldash \let_\realunder \fi \codex } } \def\codex #1{\tclose{#1}\endgroup} \def\normaldash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) % will therefore expand the active definition of _, which is us % (inside @code that is), therefore an endless loop. \ifusingtt{\ifmmode \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. \else\normalunderscore \fi \discretionary{}{}{}}% {\_}% } % An additional complication: the above will allow breaks after, e.g., % each of the four underscores in __typeof__. This is bad. % @allowcodebreaks provides a document-level way to turn breaking at - % and _ on and off. % \newif\ifallowcodebreaks \allowcodebreakstrue \def\keywordtrue{true} \def\keywordfalse{false} \parseargdef\allowcodebreaks{% \def\txiarg{#1}% \ifx\txiarg\keywordtrue \allowcodebreakstrue \else\ifx\txiarg\keywordfalse \allowcodebreaksfalse \else \errhelp = \EMsimple \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}% \fi\fi } % For @command, @env, @file, @option quotes seem unnecessary, % so use \code rather than \samp. \let\command=\code \let\env=\code \let\file=\code \let\option=\code % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url % itself. First (mandatory) arg is the url. % (This \urefnobreak definition isn't used now, leaving it for a while % for comparison.) \def\urefnobreak#1{\dourefnobreak #1,,,\finish} \def\dourefnobreak#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url \fi \else \code{#1}% only url given, so show it \fi \fi \endlink \endgroup} % This \urefbreak definition is the active one. \def\urefbreak{\begingroup \urefcatcodes \dourefbreak} \let\uref=\urefbreak \def\dourefbreak#1{\urefbreakfinish #1,,,\finish} \def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url \fi \else \urefcode{#1}% only url given, so show it \fi \fi \endlink \endgroup} % Allow line breaks around only a few characters (only). \def\urefcatcodes{% \catcode\ampChar=\active \catcode\dotChar=\active \catcode\hashChar=\active \catcode\questChar=\active \catcode\slashChar=\active } { \urefcatcodes % \global\def\urefcode{\begingroup \setupmarkupstyle{code}% \urefcatcodes \let&\urefcodeamp \let.\urefcodedot \let#\urefcodehash \let?\urefcodequest \let/\urefcodeslash \codex } % % By default, they are just regular characters. \global\def&{\normalamp} \global\def.{\normaldot} \global\def#{\normalhash} \global\def?{\normalquest} \global\def/{\normalslash} } % we put a little stretch before and after the breakable chars, to help % line breaking of long url's. The unequal skips make look better in % cmtt at least, especially for dots. \def\urefprestretch{\urefprebreak \hskip0pt plus.13em } \def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em } % \def\urefcodeamp{\urefprestretch \&\urefpoststretch} \def\urefcodedot{\urefprestretch .\urefpoststretch} \def\urefcodehash{\urefprestretch \#\urefpoststretch} \def\urefcodequest{\urefprestretch ?\urefpoststretch} \def\urefcodeslash{\futurelet\next\urefcodeslashfinish} { \catcode`\/=\active \global\def\urefcodeslashfinish{% \urefprestretch \slashChar % Allow line break only after the final / in a sequence of % slashes, to avoid line break between the slashes in http://. \ifx\next/\else \urefpoststretch \fi } } % One more complication: by default we'll break after the special % characters, but some people like to break before the special chars, so % allow that. Also allow no breaking at all, for manual control. % \parseargdef\urefbreakstyle{% \def\txiarg{#1}% \ifx\txiarg\wordnone \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} \else\ifx\txiarg\wordbefore \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak} \else\ifx\txiarg\wordafter \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak} \else \errhelp = \EMsimple \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% \fi\fi\fi } \def\wordafter{after} \def\wordbefore{before} \def\wordnone{none} \urefbreakstyle after % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} \ifpdf \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces \pdfurl{mailto:#1}% \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi \endlink \endgroup} \else \let\email=\uref \fi % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). \parseargdef\kbdinputstyle{% \def\txiarg{#1}% \ifx\txiarg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% \else\ifx\txiarg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% \else\ifx\txiarg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% \else \errhelp = \EMsimple \errmessage{Unknown @kbdinputstyle setting `\txiarg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} % Default is `distinct'. \kbdinputstyle distinct % @kbd is like @code, except that if the argument is just one @key command, % then @kbd has no effect. \def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} \def\xkey{\key} \def\kbdsub#1#2#3\par{% \def\one{#1}\def\three{#3}\def\threex{??}% \ifx\one\xkey\ifx\threex\three \key{#2}% \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi } % definition of @key that produces a lozenge. Doesn't adjust to text size. %\setfont\keyrm\rmshape{8}{1000}{OT1} %\font\keysy=cmsy9 %\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% % \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% % \vbox{\hrule\kern-0.4pt % \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% % \kern-0.4pt\hrule}% % \kern-.06em\raise0.4pt\hbox{\angleright}}}} % definition of @key with no lozenge. If the current font is already % monospace, don't change it; that way, we respect @kbdinputstyle. But % if it isn't monospace, then use \tt. % \def\key#1{{\setupmarkupstyle{key}% \nohyphenation \ifmonospace\else\tt\fi #1}\null} % @clicksequence{File @click{} Open ...} \def\clicksequence#1{\begingroup #1\endgroup} % @clickstyle @arrow (by default) \parseargdef\clickstyle{\def\click{#1}} \def\click{\arrow} % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. % \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi \null % reset \spacefactor=1000 } % @abbr for "Comput. J." and the like. % No font change, but don't do end-of-sentence spacing. % \def\abbr#1{\doabbr #1,,\finish} \def\doabbr#1,#2,#3\finish{% {\plainfrenchspacing #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi \null % reset \spacefactor=1000 } % @asis just yields its argument. Used with @table, for example. % \def\asis#1{#1} % @math outputs its argument in math mode. % % One complication: _ usually means subscripts, but it could also mean % an actual _ character, as in @math{@var{some_variable} + 1}. So make % _ active, and distinguish by seeing if the current family is \slfam, % which is what @var uses. { \catcode`\_ = \active \gdef\mathunderscore{% \catcode`\_=\active \def_{\ifnum\fam=\slfam \_\else\sb\fi}% } } % Another complication: we want \\ (and @\) to output a math (or tt) \. % FYI, plain.tex uses \\ as a temporary control sequence (for no % particular reason), but this is not advertised and we don't care. % % The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% \tex \mathunderscore \let\\ = \mathbackslash \mathactive % make the texinfo accent commands work in math mode \let\"=\ddot \let\'=\acute \let\==\bar \let\^=\hat \let\`=\grave \let\u=\breve \let\v=\check \let\~=\tilde \let\dotaccent=\dot $\finishmath } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % Some active characters (such as <) are spaced differently in math. % We have to reset their definitions in case the @math was an argument % to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active \catcode`< = \active \catcode`> = \active \catcode`+ = \active \catcode`' = \active \gdef\mathactive{% \let^ = \ptexhat \let< = \ptexless \let> = \ptexgtr \let+ = \ptexplus \let' = \ptexquoteright } } % ctrl is no longer a Texinfo command, but leave this definition for fun. \def\ctrl #1{{\tt \rawbackslash \hat}#1} % @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. % Ignore unless FMTNAME == tex; then it is like @iftex and @tex, % except specified as a normal braced arg, so no newlines to worry about. % \def\outfmtnametex{tex} % \long\def\inlinefmt#1{\doinlinefmt #1,\finish} \long\def\doinlinefmt#1,#2,\finish{% \def\inlinefmtname{#1}% \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi } % For raw, must switch into @tex before parsing the argument, to avoid % setting catcodes prematurely. Doing it this way means that, for % example, @inlineraw{html, foo{bar} gets a parse error instead of being % ignored. But this isn't important because if people want a literal % *right* brace they would have to use a command anyway, so they may as % well use a command to get a left brace too. We could re-use the % delimiter character idea from \verb, but it seems like overkill. % \long\def\inlineraw{\tex \doinlineraw} \long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} \def\doinlinerawtwo#1,#2,\finish{% \def\inlinerawname{#1}% \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi \endgroup % close group opened by \tex. } \message{glyphs,} % and logos. % @@ prints an @, as does @atchar{}. \def\@{\char64 } \let\atchar=\@ % @{ @} @lbracechar{} @rbracechar{} all generate brace characters. % Unless we're in typewriter, use \ecfont because the CM text fonts do % not have braces, and we don't want to switch into math. \def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}} \def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}} \let\{=\mylbrace \let\lbracechar=\{ \let\}=\myrbrace \let\rbracechar=\} \begingroup % Definitions to produce \{ and \} commands for indices, % and @{ and @} for the aux/toc files. \catcode`\{ = \other \catcode`\} = \other \catcode`\[ = 1 \catcode`\] = 2 \catcode`\! = 0 \catcode`\\ = \other !gdef!lbracecmd[\{]% !gdef!rbracecmd[\}]% !gdef!lbraceatcmd[@{]% !gdef!rbraceatcmd[@}]% !endgroup % @comma{} to avoid , parsing problems. \let\comma = , % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \ptexc \let\dotaccent = \ptexdot \def\ringaccent#1{{\accent23 #1}} \let\tieaccent = \ptext \let\ubaraccent = \ptexb \let\udotaccent = \d % Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} \def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} \def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} \def\jmacro{j} \def\dotless#1{% \def\temp{#1}% \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi \else \errmessage{@dotless can be used only with i or j}% \fi\fi } % The \TeX{} logo, as in plain, but resetting the spacing so that a % period following counts as ending a sentence. (Idea found in latex.) % \edef\TeX{\TeX \spacefactor=1000 } % @LaTeX{} logo. Not quite the same results as the definition in % latex.ltx, since we use a different font for the raised A; it's most % convenient for us to use an explicitly smaller font, rather than using % the \scriptstyle font (since we don't reset \scriptstyle and % \scriptscriptstyle). % \def\LaTeX{% L\kern-.36em {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{% \ifx\textnominalsize\xwordpt % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX. % Revert to plain's \scriptsize, which is 7pt. \count255=\the\fam $\fam\count255 \scriptstyle A$% \else % For 11pt, we can use our lllsize. \selectfonts\lllsize A% \fi }% \vss }}% \kern-.15em \TeX } % Some math mode symbols. \def\bullet{$\ptexbullet$} \def\geq{\ifmmode \ge\else $\ge$\fi} \def\leq{\ifmmode \le\else $\le$\fi} \def\minus{\ifmmode -\else $-$\fi} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in the cm % typewriter fonts as three actual period characters; on the other hand, % in other typewriter fonts three periods are wider than 1.5em. So do % whichever is larger. % \def\dots{% \leavevmode \setbox0=\hbox{...}% get width of three periods \ifdim\wd0 > 1.5em \dimen0 = \wd0 \else \dimen0 = 1.5em \fi \hbox to \dimen0{% \hskip 0pt plus.25fil .\hskip 0pt plus1fil .\hskip 0pt plus1fil .\hskip 0pt plus.5fil }% } % @enddots{} is an end-of-sentence ellipsis. % \def\enddots{% \dots \spacefactor=\endofsentencespacefactor } % @point{}, @result{}, @expansion{}, @print{}, @equiv{}. % % Since these characters are used in examples, they should be an even number of % \tt widths. Each \tt character is 1en, so two makes it 1em. % \def\point{$\star$} \def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} \def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} \def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} \def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} % The @error{} command. % Adapted from the TeXbook's \boxit. % \newbox\errorbox % {\tentt \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} % \setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. \kern3pt\vrule width\dimen2}% Space to right. \hrule height\dimen2} \hfil} % \def\error{\leavevmode\lower.7ex\copy\errorbox} % @pounds{} is a sterling sign, which Knuth put in the CM italic font. % \def\pounds{{\it\$}} % @euro{} comes from a separate font, depending on the current style. % We use the free feym* fonts from the eurosym package by Henrik % Theiling, which support regular, slanted, bold and bold slanted (and % "outlined" (blackboard board, sort of) versions, which we don't need). % It is available from http://www.ctan.org/tex-archive/fonts/eurosym. % % Although only regular is the truly official Euro symbol, we ignore % that. The Euro is designed to be slightly taller than the regular % font height. % % feymr - regular % feymo - slanted % feybr - bold % feybo - bold slanted % % There is no good (free) typewriter version, to my knowledge. % A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. % Hmm. % % Also doesn't work in math. Do we need to do math with euro symbols? % Hope not. % % \def\euro{{\eurofont e}} \def\eurofont{% % We set the font at each command, rather than predefining it in % \textfonts and the other font-switching commands, so that % installations which never need the symbol don't have to have the % font installed. % % There is only one designed size (nominal 10pt), so we always scale % that to the current nominal size. % % By the way, simply using "at 1em" works for cmr10 and the like, but % does not work for cmbx10 and other extended/shrunken fonts. % \def\eurosize{\csname\curfontsize nominalsize\endcsname}% % \ifx\curfontstyle\bfstylename % bold: \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize \else % regular: \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize \fi \thiseurofont } % Glyphs from the EC fonts. We don't use \let for the aliases, because % sometimes we redefine the original macro, and the alias should reflect % the redefinition. % % Use LaTeX names for the Icelandic letters. \def\DH{{\ecfont \char"D0}} % Eth \def\dh{{\ecfont \char"F0}} % eth \def\TH{{\ecfont \char"DE}} % Thorn \def\th{{\ecfont \char"FE}} % thorn % \def\guillemetleft{{\ecfont \char"13}} \def\guillemotleft{\guillemetleft} \def\guillemetright{{\ecfont \char"14}} \def\guillemotright{\guillemetright} \def\guilsinglleft{{\ecfont \char"0E}} \def\guilsinglright{{\ecfont \char"0F}} \def\quotedblbase{{\ecfont \char"12}} \def\quotesinglbase{{\ecfont \char"0D}} % % This positioning is not perfect (see the ogonek LaTeX package), but % we have the precomposed glyphs for the most common cases. We put the % tests to use those glyphs in the single \ogonek macro so we have fewer % dummy definitions to worry about for index entries, etc. % % ogonek is also used with other letters in Lithuanian (IOU), but using % the precomposed glyphs for those is not so easy since they aren't in % the same EC font. \def\ogonek#1{{% \def\temp{#1}% \ifx\temp\macrocharA\Aogonek \else\ifx\temp\macrochara\aogonek \else\ifx\temp\macrocharE\Eogonek \else\ifx\temp\macrochare\eogonek \else \ecfont \setbox0=\hbox{#1}% \ifdim\ht0=1ex\accent"0C #1% \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% \fi \fi\fi\fi\fi }% } \def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} \def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} \def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} \def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} % % Use the ec* fonts (cm-super in outline format) for non-CM glyphs. \def\ecfont{% % We can't distinguish serif/sans and italic/slanted, but this % is used for crude hacks anyway (like adding French and German % quotes to documents typeset with CM, where we lose kerning), so % hopefully nobody will notice/care. \edef\ecsize{\csname\curfontsize ecsize\endcsname}% \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% \ifmonospace % typewriter: \font\thisecfont = ectt\ecsize \space at \nominalsize \else \ifx\curfontstyle\bfstylename % bold: \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize \else % regular: \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize \fi \fi \thisecfont } % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% \hfil\crcr\Orb}}% }$% } % @textdegree - the normal degrees sign. % \def\textdegree{$^\circ$} % Laurent Siebenmann reports \Orb undefined with: % Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 % so we'll define it if necessary. % \ifx\Orb\thisisundefined \def\Orb{\mathhexbox20D} \fi % Quotes. \chardef\quotedblleft="5C \chardef\quotedblright=`\" \chardef\quoteleft=`\` \chardef\quoteright=`\' \message{page headings,} \newskip\titlepagetopglue \titlepagetopglue = 1.5in \newskip\titlepagebottomglue \titlepagebottomglue = 2pc % First the title page. Must do @settitle before @titlepage. \newif\ifseenauthor \newif\iffinishedtitlepage % Do an implicit @contents or @shortcontents after @end titlepage if the % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. % \newif\ifsetcontentsaftertitlepage \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue \parseargdef\shorttitlepage{% \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. \begingroup \parindent=0pt \textfonts % Leave some space at the very top of the page. \vglue\titlepagetopglue % No rule at page bottom unless we print one at the top with @title. \finishedtitlepagetrue % % Most title ``pages'' are actually two pages long, with space % at the top of the second. We don't want the ragged left on the second. \let\oldpage = \page \def\page{% \iffinishedtitlepage\else \finishtitlepage \fi \let\page = \oldpage \page \null }% } \def\Etitlepage{% \iffinishedtitlepage\else \finishtitlepage \fi % It is important to do the page break before ending the group, % because the headline and footline are only empty inside the group. % If we use the new definition of \page, we always get a blank page % after the title page, which we certainly don't want. \oldpage \endgroup % % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon % % If they want short, they certainly want long too. \ifsetshortcontentsaftertitlepage \shortcontents \contents \global\let\shortcontents = \relax \global\let\contents = \relax \fi % \ifsetcontentsaftertitlepage \contents \global\let\contents = \relax \global\let\shortcontents = \relax \fi } \def\finishtitlepage{% \vskip4pt \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } % Settings used for typesetting titles: no hyphenation, no indentation, % don't worry much about spacing, ragged right. This should be used % inside a \vbox, and fonts need to be set appropriately first. Because % it is always used for titles, nothing else, we call \rmisbold. \par % should be specified before the end of the \vbox, since a vbox is a group. % \def\raggedtitlesettings{% \rmisbold \hyphenpenalty=10000 \parindent=0pt \tolerance=5000 \ptexraggedright } % Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \parseargdef\title{% \checkenv\titlepage \vbox{\titlefonts \raggedtitlesettings #1\par}% % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt } \parseargdef\subtitle{% \checkenv\titlepage {\subtitlefont \rightline{#1}}% } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% \def\temp{\quotation}% \ifx\thisenv\temp \def\quotationauthor{#1}% printed in \Equotation. \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi {\secfonts\rmisbold \leftline{#1}}% \fi } % Set up page headings and footings. \let\thispage=\folio \newtoks\evenheadline % headline on even pages \newtoks\oddheadline % headline on odd pages \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages % Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}\HEADINGShook} \let\HEADINGShook=\relax % Commands to set those variables. % For example, this is what @headings on does % @evenheading @thistitle|@thispage|@thischapter % @oddheading @thischapter|@thispage|@thistitle % @evenfooting @thisfile|| % @oddfooting ||@thisfile \def\evenheading{\parsearg\evenheadingxxx} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddheading{\parsearg\oddheadingxxx} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \def\evenfooting{\parsearg\evenfootingxxx} \def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} \def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddfooting{\parsearg\oddfootingxxx} \def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} \def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. \global\advance\pageheight by -12pt \global\advance\vsize by -12pt } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} % @evenheadingmarks top \thischapter <- chapter at the top of a page % @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page % % The same set of arguments for: % % @oddheadingmarks % @evenfootingmarks % @oddfootingmarks % @everyheadingmarks % @everyfootingmarks \def\evenheadingmarks{\headingmarks{even}{heading}} \def\oddheadingmarks{\headingmarks{odd}{heading}} \def\evenfootingmarks{\headingmarks{even}{footing}} \def\oddfootingmarks{\headingmarks{odd}{footing}} \def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} \headingmarks{odd}{heading}{#1} } \def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} \headingmarks{odd}{footing}{#1} } % #1 = even/odd, #2 = heading/footing, #3 = top/bottom. \def\headingmarks#1#2#3 {% \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname \global\expandafter\let\csname get#1#2marks\endcsname \temp } \everyheadingmarks bottom \everyfootingmarks bottom % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. % @headings off turns them off. % @headings on same as @headings double, retained for compatibility. % @headings after turns on double-sided headings after this page. % @headings doubleafter turns on double-sided headings after this page. % @headings singleafter turns on single-sided headings after this page. % By default, they are off at the start of a document, % and turned `on' after @end titlepage. \def\headings #1 {\csname HEADINGS#1\endcsname} \def\headingsoff{% non-global headings elimination \evenheadline={\hfil}\evenfootline={\hfil}% \oddheadline={\hfil}\oddfootline={\hfil}% } \def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting \HEADINGSoff % it's the default % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. \def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. \def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} \let\HEADINGSdoubleafter=\HEADINGSafter \def\HEADINGSdoublex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). \ifx\today\thisisundefined \def\today{% \number\day\space \ifcase\month \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec \fi \space\number\year} \fi % @settitle line... specifies the title of the document, for headings. % It generates no output of its own. \def\thistitle{\putwordNoTitle} \def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} % Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in % default indentation of @itemize and @enumerate text \newdimen\itemindent \itemindent=.3in % margin between end of table item and start of table text. \newdimen\itemmargin \itemmargin=.1in % used internally for \itemindent minus \itemmargin \newdimen\itemmax % Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). \newif\ifitemxneedsnegativevskip \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % % If the item text does not fit in the space we have, put it on a line % by itself, and do not allow a page break either before or after that % line. We do not start a paragraph here because then if the next % command is, e.g., @kindex, the whatsit would get put into the % horizontal list on a line by itself, resulting in extra blank space. \ifdim \wd0>\itemmax % % Make this a paragraph so we get the \parskip glue and wrapping, % but leave it ragged-right. \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent \advance\rightskip by0pt plus1fil\relax \leavevmode\unhbox0\par \endgroup % % We're going to be starting a paragraph, but we don't want the % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % % Stop a page break at the \parskip glue coming up. However, if % what follows is an environment such as @example, there will be no % \parskip glue; then the negative vskip we just inserted would % cause the example and the item to crash together. So we use this % bizarre value of 10001 as a signal to \aboveenvbreak to insert % \parskip glue after all. Section titles are handled this way also. % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and % eventually be printed. \nobreak\kern-\tableindent \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 \unhbox0 \nobreak\kern\dimen0 \endgroup \itemxneedsnegativevskiptrue \fi } \def\item{\errmessage{@item while not in a list environment}} \def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble \tablecheck{table}% } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% \tablecheck{ftable}% } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% \tablecheck{vtable}% } \def\tablecheck#1{% \ifnum \the\catcode`\^^M=\active \endgroup \errmessage{This command won't work in this context; perhaps the problem is that we are \inenvironment\thisenv}% \def\next{\doignore{#1}}% \else \let\next\tablex \fi \next } \def\tablex#1{% \def\itemindicate{#1}% \parsearg\tabley } \def\tabley#1{% {% \makevalueexpandable \edef\temp{\noexpand\tablez #1\space\space\space}% \expandafter }\temp \endtablez } \def\tablez #1 #2 #3 #4\endtablez{% \aboveenvbreak \ifnum 0#1>0 \advance \leftskip by #1\mil \fi \ifnum 0#2>0 \tableindent=#2\mil \fi \ifnum 0#3>0 \advance \rightskip by #3\mil \fi \itemmax=\tableindent \advance \itemmax by -\itemmargin \advance \leftskip by \tableindent \exdentamount=\tableindent \parindent = 0pt \parskip = \smallskipamount \ifdim \parskip=0pt \parskip=2pt \fi \let\item = \internalBitem \let\itemx = \internalBitemx } \def\Etable{\endgraf\afterenvbreak} \let\Eftable\Etable \let\Evtable\Etable \let\Eitemize\Etable \let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno \envdef\itemize{\parsearg\doitemize} \def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin \advance\leftskip by \itemindent \exdentamount=\itemindent \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi % % Try typesetting the item mark that if the document erroneously says % something like @itemize @samp (intending @table), there's an error % right away at the @itemize. It's not the best error message in the % world, but it's better than leaving it to the @item. This means if % the user wants an empty mark, they have to say @w{} not just @w. \def\itemcontents{#1}% \setbox0 = \hbox{\itemcontents}% % % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi % \let\item=\itemizeitem } % Definition of @item while inside @itemize and @enumerate. % \def\itemizeitem{% \advance\itemno by 1 % for enumerations {\let\par=\endgraf \smallbreak}% reasonable place to break {% % If the document has an @itemize directly after a section title, a % \nobreak will be last on the list, and \sectionheading will have % done a \vskip-\parskip. In that case, we don't want to zero % parskip, or the item text will crash with the heading. On the % other hand, when there is normal text preceding the item (as there % usually is), we do want to zero parskip, or there would be too much % space. In that case, we won't have a \nobreak before. At least % that's the theory. \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% % \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% % Allow an optional argument of an uppercase letter, lowercase letter, % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % \envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi % % Detect if the argument is a single token. If so, it might be a % letter. Otherwise, the only valid thing it can be is a number. % (We will always have one token, because of the test we just made. % This is a good thing, since \splitoff doesn't work given nothing at % all -- the first parameter is undelimited.) \expandafter\splitoff\thearg\endmark \ifx\rest\empty % Only one token in the argument. It could still be anything. % A ``lowercase letter'' is one whose \lccode is nonzero. % An ``uppercase letter'' is one whose \lccode is both nonzero, and % not equal to itself. % Otherwise, we assume it's a number. % % We need the \relax at the end of the \ifnum lines to stop TeX from % continuing to look for a . % \ifnum\lccode\expandafter`\thearg=0\relax \numericenumerate % a number (we hope) \else % It's a letter. \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax \lowercaseenumerate % lowercase letter \else \uppercaseenumerate % uppercase letter \fi \fi \else % Multiple tokens in the argument. We hope it's a number. \numericenumerate \fi } % An @enumerate whose labels are integers. The starting integer is % given in \thearg. % \def\numericenumerate{% \itemno = \thearg \startenumeration{\the\itemno}% } % The starting (lowercase) letter is in \thearg. \def\lowercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more lowercase letters in @enumerate; get a bigger alphabet}% \fi \char\lccode\itemno }% } % The starting (uppercase) letter is in \thearg. \def\uppercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more uppercase letters in @enumerate; get a bigger alphabet} \fi \char\uccode\itemno }% } % Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg % to @enumerate. % \def\alphaenumerate{\enumerate{a}} \def\capsenumerate{\enumerate{A}} \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 % % @multitable ... @end multitable will make as many columns as desired. % Contents of each column will wrap at width given in preamble. Width % can be specified either with sample text given in a template line, % or in percent of \hsize, the current width of text on page. % Table can continue over pages but will only break between lines. % To make preamble: % % Either define widths of columns in terms of percent of \hsize: % @multitable @columnfractions .25 .3 .45 % @item ... % % Numbers following @columnfractions are the percent of the total % current hsize to be used for each column. You may use as many % columns as desired. % Or use a template: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. % @item, @tab do not need to be on their own lines, but it will not hurt % if they are. % Sample multitable: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item first col stuff @tab second col stuff @tab third col % @item % first col stuff % @tab % second col stuff % @tab % third col % @item first col stuff @tab second col stuff % @tab Many paragraphs of text may be used in any column. % % They will wrap at the width determined by the template. % @item@tab@tab This will be in third column. % @end multitable % Default dimensions may be reset by user. % @multitableparskip is vertical space between paragraphs in table. % @multitableparindent is paragraph indent in table. % @multitablecolmargin is horizontal space to be left between columns. % @multitablelinespace is space to leave between table items, baseline % to baseline. % 0pt means it depends on current normal line spacing. % \newskip\multitableparskip \newskip\multitableparindent \newdimen\multitablecolspace \newskip\multitablelinespace \multitableparskip=0pt \multitableparindent=6pt \multitablecolspace=12pt \multitablelinespace=0pt % Macros used to set up halign preamble: % \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent % #1 is the @columnfraction, usually a decimal number like .5, but might % be just 1. We just use it, whatever it is. % \def\pickupwholefraction#1 {% \global\advance\colcount by 1 \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } \newcount\colcount \def\setuptable#1{% \def\firstarg{#1}% \ifx\firstarg\xendsetuptable \let\go = \relax \else \ifx\firstarg\xcolumnfractions \global\setpercenttrue \else \ifsetpercent \let\go\pickupwholefraction \else \global\advance\colcount by 1 \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi \ifx\go\pickupwholefraction % Put the argument back for the \pickupwholefraction call, so % we'll always have a period there to be parsed. \def\go{\pickupwholefraction#1}% \else \let\go = \setuptable \fi% \fi \go } % multitable-only commands. % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group % of an alignment entry. \everycr resets \everytab so we don't have to % undo it ourselves. \def\headitemfont{\b}% for people to use in the template row; not changeable \def\headitem{% \checkenv\multitable \crcr \global\everytab={\bf}% can't use \headitemfont since the parsing differs \the\everytab % for the first item }% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we again encounter the problem the 1sp was intended to solve. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % \newtoks\everytab % insert after every tab. % \envdef\multitable{% \vskip\parskip \startsavinginserts % % @item within a multitable starts a normal row. % We use \def instead of \let so that if one of the multitable entries % contains an @itemize, we don't choke on the \item (seen as \crcr aka % \endtemplate) expanding \doitemize. \def\item{\crcr}% % \tolerance=9500 \hbadness=9500 \setmultitablespacing \parskip=\multitableparskip \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 % \everycr = {% \noalign{% \global\everytab={}% \global\colcount=0 % Reset the column counter. % Check for saved footnotes, etc. \checkinserts % Keeps underfull box messages off when table breaks over pages. %\filbreak % Maybe so, but it also creates really weird page breaks when the % table breaks over pages. Wouldn't \vfil be better? Wait until the % problem manifests itself, so it can be fixed for real --karl. }% }% % \parsearg\domultitable } \def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. \halign\bgroup &% \global\advance\colcount by 1 \multistrut \vtop{% % Use the current \colcount to find the correct column width: \hsize=\expandafter\csname col\the\colcount\endcsname % % In order to keep entries from bumping into each other % we will add a \leftskip of \multitablecolspace to all columns after % the first one. % % If a template has been used, we will add \multitablecolspace % to the width of each template entry. % % If the user has set preamble in terms of percent of \hsize we will % use that dimension as the width of the column, and the \leftskip % will keep entries from bumping into each other. Table will start at % left margin and final column will justify at right margin. % % Make sure we don't inherit \rightskip from the outer environment. \rightskip=0pt \ifnum\colcount=1 % The first column will be indented with the surrounding text. \advance\hsize by\leftskip \else \ifsetpercent \else % If user has not set preamble in terms of percent of \hsize % we will advance \hsize by \multitablecolspace. \advance\hsize by \multitablecolspace \fi % In either case we will make \leftskip=\multitablecolspace: \leftskip=\multitablecolspace \fi % Ignoring space at the beginning and end avoids an occasional spurious % blank line, when TeX decides to break the line at the space before the % box from the multistrut, so the strut ends up on a line by itself. % For example: % @multitable @columnfractions .11 .89 % @item @code{#} % @tab Legal holiday which is valid in major parts of the whole country. % Is automatically provided with highlighting sequences respectively % marking characters. \noindent\ignorespaces##\unskip\multistrut }\cr } \def\Emultitable{% \crcr \egroup % end the \halign \global\setpercentfalse } \def\setmultitablespacing{% \def\multistrut{\strut}% just use the standard line spacing % % Compute \multitablelinespace (if not defined by user) for use in % \multitableparskip calculation. We used define \multistrut based on % this, but (ironically) that caused the spacing to be off. % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 \fi % Test to see if parskip is larger than space between lines of % table. If not, do nothing. % If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt % to keep parskip somewhat smaller % than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt % to keep parskip somewhat smaller % than skip between lines in the table. \fi} \message{conditionals,} % @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't % attempt to close an environment group. % \def\makecond#1{% \expandafter\let\csname #1\endcsname = \relax \expandafter\let\csname iscond.#1\endcsname = 1 } \makecond{iftex} \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} \makecond{ifnotplaintext} \makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} \def\documentdescription{\doignore{documentdescription}} \def\docbook{\doignore{docbook}} \def\html{\doignore{html}} \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} % Ignore text until a line `@end #1', keeping track of nested conditionals. % % A count to remember the depth of nesting. \newcount\doignorecount \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: \obeylines \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. \spaceisspace % % Count number of #1's that we've seen. \doignorecount = 0 % % Swallow text until we reach the matching `@end #1'. \dodoignore{#1}% } { \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. \obeylines % % \gdef\dodoignore#1{% % #1 contains the command name as a string, e.g., `ifinfo'. % % Define a command to find the next `@end #1'. \long\def\doignoretext##1^^M@end #1{% \doignoretextyyy##1^^M@#1\_STOP_}% % % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. \doignoretext ^^M% }% } \def\doignoreyyy#1{% \def\temp{#1}% \ifx\temp\empty % Nothing found. \let\next\doignoretextzzz \else % Found a nested condition, ... \advance\doignorecount by 1 \let\next\doignoretextyyy % ..., look for another. % If we're here, #1 ends with ^^M\ifinfo (for example). \fi \next #1% the token \_STOP_ is present just after this macro. } % We have to swallow the remaining "\_STOP_". % \def\doignoretextzzz#1{% \ifnum\doignorecount = 0 % We have just found the outermost @end. \let\next\enddoignore \else % Still inside a nested condition. \advance\doignorecount by -1 \let\next\doignoretext % Look for the next @end. \fi \next } % Finish off ignored text. { \obeylines% % Ignore anything after the last `@end #1'; this matters in verbatim % environments, where otherwise the newline after an ignored conditional % would result in a blank line in the output. \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% } % @set VAR sets the variable VAR to an empty value. % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. % % Since we want to separate VAR from REST-OF-LINE (which might be % empty), we can't just use \parsearg; we have to insert a space of our % own to delimit the rest of the line, and then take it out again if we % didn't need it. % We rely on the fact that \parsearg sets \catcode`\ =10. % \parseargdef\set{\setyyy#1 \endsetyyy} \def\setyyy#1 #2\endsetyyy{% {% \makevalueexpandable \def\temp{#2}% \edef\next{\gdef\makecsname{SET#1}}% \ifx\temp\empty \next{}% \else \setzzz#2\endsetzzz \fi }% } % Remove the trailing space \setxxx inserted. \def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % \parseargdef\clear{% {% \makevalueexpandable \global\expandafter\let\csname SET#1\endcsname=\relax }% } % @value{foo} gets the text saved in variable foo. \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { \catcode`\- = \active \catcode`\_ = \active % \gdef\makevalueexpandable{% \let\value = \expandablevalue % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. \let-\normaldash \let_\normalunderscore } } % We have this subroutine so that we can handle at least some @value's % properly in indexes (we call \makevalueexpandable in \indexdummies). % The command has to be fully expandable (if the variable is set), since % the result winds up in the index file. This means that if the % variable's value contains other Texinfo commands, it's almost certain % it will fail (although perhaps we could fix that with sufficient work % to do a one-level expansion on the result, instead of complete). % \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% \message{Variable `#1', used in @value, is not set.}% \else \csname SET#1\endcsname \fi } % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % % To get special treatment of `@end ifset,' call \makeond and the redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} \def\doifset#1#2{% {% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname SET#2\endcsname\relax #1% If not set, redefine \next. \fi \expandafter }\next } \def\ifsetfail{\doignore{ifset}} % @ifclear VAR ... @end executes the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the % above code: if the variable is not set, do nothing, if it is set, % then redefine \next to \ifclearfail. % \makecond{ifclear} \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} % @ifcommandisdefined CMD ... @end executes the `...' if CMD (written % without the @) is in fact defined. We can only feasibly check at the % TeX level, so something like `mathcode' is going to considered % defined even though it is not a Texinfo command. % \makecond{ifcommanddefined} \def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} % \def\doifcmddefined#1#2{{% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname #2\endcsname\relax #1% If not defined, \let\next as above. \fi \expandafter }\next } \def\ifcmddefinedfail{\doignore{ifcommanddefined}} % @ifcommandnotdefined CMD ... handled similar to @ifclear above. \makecond{ifcommandnotdefined} \def\ifcommandnotdefined{% \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} \def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} % Set the `txicommandconditionals' variable, so documents have a way to % test if the @ifcommand...defined conditionals are available. \set txicommandconditionals % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite % except not \outer, so it can be used within macros and \if's. \edef\newwrite{\makecsname{ptexnewwrite}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that % \fooindex ...rest of line... puts an entry in the index foo. % It also defines \fooindfile to be the number of the output channel for % the file that accumulates this index. The file's extension is foo. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 % Open the file \fi \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} % \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. % \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 \fi \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. % % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. % \def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} \def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. \expandafter \ifx\csname donesynindex#2\endcsname \relax % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname \expandafter\let\csname donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp % redefine \fooindex: \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } % Define \doindex, the driver for all \fooindex macros. % Argument #1 is generated by the calling \fooindex macro, % and it is "foo", the name of the index. % \doindex just uses \parsearg; it calls \doind for the actual work. % This is because \doind is more useful to call from other macros. % There is also \dosubind {index}{topic}{subtopic} % which makes an entry in a two-level index such as the operation index. \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} \def\singleindexer #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} % Take care of Texinfo commands that can appear in an index entry. % Since there are some commands we want to expand, and others we don't, % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% \escapechar = `\\ % use backslash in output files. \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% % % Need these unexpandable (because we define \tt as a dummy) % definitions when @{ or @} appear in index entry text. Also, more % complicated, when \tex is in effect and \{ is a \delimiter again. % We can't use \lbracecmd and \rbracecmd because texindex assumes % braces and backslashes are used only as delimiters. Perhaps we % should define @lbrace and @rbrace commands a la @comma. \def\{{{\tt\char123}}% \def\}{{\tt\char125}}% % % I don't entirely understand this, but when an index entry is % generated from a macro call, the \endinput which \scanmacro inserts % causes processing to be prematurely terminated. This is, % apparently, because \indexsorttmp is fully expanded, and \endinput % is an expandable command. The redefinition below makes \endinput % disappear altogether for that purpose -- although logging shows that % processing continues to some further point. On the other hand, it % seems \endinput does not hurt in the printed index arg, since that % is still getting written without apparent harm. % % Sample source (mac-idx3.tex, reported by Graham Percival to % help-texinfo, 22may06): % @macro funindex {WORD} % @findex xyz % @end macro % ... % @funindex commtest % % The above is not enough to reproduce the bug, but it gives the flavor. % % Sample whatsit resulting: % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} % % So: \let\endinput = \empty % % Do the redefinitions. \commondummies } % For the aux and toc files, @ is the escape character. So we want to % redefine everything using @ as the escape character (instead of % \realbackslash, still used for index files). When everything uses @, % this will be simpler. % \def\atdummies{% \def\@{@@}% \def\ {@ }% \let\{ = \lbraceatcmd \let\} = \rbraceatcmd % % Do the redefinitions. \commondummies \otherbackslash } % Called from \indexdummies and \atdummies. % \def\commondummies{% % % \definedummyword defines \#1 as \string\#1\space, thus effectively % preventing its expansion. This is used only for control words, % not control letters, because the \space would be incorrect for % control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the % space. % % These can be used both for control words that take an argument and % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % \def\definedummyword ##1{\def##1{\string##1\space}}% \def\definedummyletter##1{\def##1{\string##1}}% \let\definedummyaccent\definedummyletter % \commondummiesnofonts % \definedummyletter\_% \definedummyletter\-% % % Non-English letters. \definedummyword\AA \definedummyword\AE \definedummyword\DH \definedummyword\L \definedummyword\O \definedummyword\OE \definedummyword\TH \definedummyword\aa \definedummyword\ae \definedummyword\dh \definedummyword\exclamdown \definedummyword\l \definedummyword\o \definedummyword\oe \definedummyword\ordf \definedummyword\ordm \definedummyword\questiondown \definedummyword\ss \definedummyword\th % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword\bf \definedummyword\gtr \definedummyword\hat \definedummyword\less \definedummyword\sf \definedummyword\sl \definedummyword\tclose \definedummyword\tt % \definedummyword\LaTeX \definedummyword\TeX % % Assorted special characters. \definedummyword\arrow \definedummyword\bullet \definedummyword\comma \definedummyword\copyright \definedummyword\registeredsymbol \definedummyword\dots \definedummyword\enddots \definedummyword\entrybreak \definedummyword\equiv \definedummyword\error \definedummyword\euro \definedummyword\expansion \definedummyword\geq \definedummyword\guillemetleft \definedummyword\guillemetright \definedummyword\guilsinglleft \definedummyword\guilsinglright \definedummyword\lbracechar \definedummyword\leq \definedummyword\minus \definedummyword\ogonek \definedummyword\pounds \definedummyword\point \definedummyword\print \definedummyword\quotedblbase \definedummyword\quotedblleft \definedummyword\quotedblright \definedummyword\quoteleft \definedummyword\quoteright \definedummyword\quotesinglbase \definedummyword\rbracechar \definedummyword\result \definedummyword\textdegree % % We want to disable all macros so that they are not expanded by \write. \macrolist % \normalturnoffactive % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % \def\commondummiesnofonts{% % Control letters and accents. \definedummyletter\!% \definedummyaccent\"% \definedummyaccent\'% \definedummyletter\*% \definedummyaccent\,% \definedummyletter\.% \definedummyletter\/% \definedummyletter\:% \definedummyaccent\=% \definedummyletter\?% \definedummyaccent\^% \definedummyaccent\`% \definedummyaccent\~% \definedummyword\u \definedummyword\v \definedummyword\H \definedummyword\dotaccent \definedummyword\ogonek \definedummyword\ringaccent \definedummyword\tieaccent \definedummyword\ubaraccent \definedummyword\udotaccent \definedummyword\dotless % % Texinfo font commands. \definedummyword\b \definedummyword\i \definedummyword\r \definedummyword\sansserif \definedummyword\sc \definedummyword\slanted \definedummyword\t % % Commands that take arguments. \definedummyword\abbr \definedummyword\acronym \definedummyword\anchor \definedummyword\cite \definedummyword\code \definedummyword\command \definedummyword\dfn \definedummyword\dmn \definedummyword\email \definedummyword\emph \definedummyword\env \definedummyword\file \definedummyword\image \definedummyword\indicateurl \definedummyword\inforef \definedummyword\kbd \definedummyword\key \definedummyword\math \definedummyword\option \definedummyword\pxref \definedummyword\ref \definedummyword\samp \definedummyword\strong \definedummyword\tie \definedummyword\uref \definedummyword\url \definedummyword\var \definedummyword\verb \definedummyword\w \definedummyword\xref } % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string % would be for a given command (usually its argument). % \def\indexnofonts{% % Accent commands should become @asis. \def\definedummyaccent##1{\let##1\asis}% % We can just ignore other control letters. \def\definedummyletter##1{\let##1\empty}% % All control words become @asis by default; overrides below. \let\definedummyword\definedummyaccent % \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command % and is used in the definitions of the active chars like <, >, |, etc. % Likewise with the other plain tex font commands. %\let\tt=\asis % \def\ { }% \def\@{@}% \def\_{\normalunderscore}% \def\-{}% @- shouldn't affect sorting % % Unfortunately, texindex is not prepared to handle braces in the % content at all. So for index sorting, we map @{ and @} to strings % starting with |, since that ASCII character is between ASCII { and }. \def\{{|a}% \def\lbracechar{|a}% % \def\}{|b}% \def\rbracechar{|b}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\DH{DZZ}% \def\L{L}% \def\OE{OE}% \def\O{O}% \def\TH{ZZZ}% \def\aa{aa}% \def\ae{ae}% \def\dh{dzz}% \def\exclamdown{!}% \def\l{l}% \def\oe{oe}% \def\ordf{a}% \def\ordm{o}% \def\o{o}% \def\questiondown{?}% \def\ss{ss}% \def\th{zzz}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) \def\arrow{->}% \def\bullet{bullet}% \def\comma{,}% \def\copyright{copyright}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% \def\euro{euro}% \def\expansion{==>}% \def\geq{>=}% \def\guillemetleft{<<}% \def\guillemetright{>>}% \def\guilsinglleft{<}% \def\guilsinglright{>}% \def\leq{<=}% \def\minus{-}% \def\point{.}% \def\pounds{pounds}% \def\print{-|}% \def\quotedblbase{"}% \def\quotedblleft{"}% \def\quotedblright{"}% \def\quoteleft{`}% \def\quoteright{'}% \def\quotesinglbase{,}% \def\registeredsymbol{R}% \def\result{=>}% \def\textdegree{o}% % \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax \else \indexlquoteignore \fi % % We need to get rid of all macros, leaving only the arguments (if present). % Of course this is not nearly correct, but it is the best we can do for now. % makeinfo does not expand macros in the argument to @deffn, which ends up % writing an index entry, and texindex isn't prepared for an index sort entry % that starts with \. % % Since macro invocations are followed by braces, we can just redefine them % to take a single TeX argument. The case of a macro invocation that % goes to end-of-line is not handled. % \macrolist } % Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us % ignore left quotes in the sort term. {\catcode`\`=\active \gdef\indexlquoteignore{\let`=\empty}} \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? % Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. \def\doind#1#2{\dosubind{#1}{#2}{}} % Workhorse for all \fooindexes. % #1 is name of index, #2 is stuff to put there, #3 is subentry -- % empty if called from \doind, as we usually are (the main exception % is with most defuns, which call us directly). % \def\dosubind#1#2#3{% \iflinks {% % Store the main index entry text (including the third arg). \toks0 = {#2}% % If third arg is present, precede it with a space. \def\thirdarg{#3}% \ifx\thirdarg\empty \else \toks0 = \expandafter{\the\toks0 \space #3}% \fi % \edef\writeto{\csname#1indfile\endcsname}% % \safewhatsit\dosubindwrite }% \fi } % Write the entry in \toks0 to the index file: % \def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % % Process the index entry with all font commands turned off, to % get the string to sort by. {\indexnofonts \edef\temp{\the\toks0}% need full expansion \xdef\indexsorttmp{\temp}% }% % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. \edef\temp{% \write\writeto{% \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% \temp } % Take care of unwanted page breaks/skips around a whatsit: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the % \write or \pdfdest will make \lastskip zero. The result is that % sequences like this: % @end defun % @tindex whatever % @defun ... % will have extra space inserted, because the \medbreak in the % start of the @defun won't see the skip inserted by the @end of % the previous defun. % % But don't do any of this if we're not in vertical mode. We % don't want to do a \vskip and prematurely end a paragraph. % % Avoid page breaks due to these extra skips, too. % % But wait, there is a catch there: % We'll have to check whether \lastskip is zero skip. \ifdim is not % sufficient for this purpose, as it ignores stretch and shrink parts % of the skip. The only way seems to be to check the textual % representation of the skip. % % The following is almost like \def\zeroskipmacro{0.0pt} except that % the ``p'' and ``t'' characters have catcode \other, not 11 (letter). % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % \newskip\whatsitskip \newcount\whatsitpenalty % % ..., ready, GO: % \def\safewhatsit#1{\ifhmode #1% \else % \lastskip and \lastpenalty cannot both be nonzero simultaneously. \whatsitskip = \lastskip \edef\lastskipmacro{\the\lastskip}% \whatsitpenalty = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this % -\whatsitskip glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else \vskip-\whatsitskip \fi % #1% % \ifx\lastskipmacro\zeroskipmacro % If \lastskip was zero, perhaps the last item was a penalty, and % perhaps it was >=10000, e.g., a \nobreak. In that case, we want % to re-insert the same penalty (values >10000 are used for various % signals); since we just inserted a non-discardable item, any % following glue (such as a \parskip) would be a breakpoint. For example: % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. \nobreak\vskip\whatsitskip \fi \fi} % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or % \entry {sortstring}{page}{topic}{subtopic} % The texindex program reads in these files and writes files % containing these kinds of lines: % \initial {c} % before the first topic whose initial is c % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. \def\findex {\fnindex} \def\kindex {\kyindex} \def\cindex {\cpindex} \def\vindex {\vrindex} \def\tindex {\tpindex} \def\pindex {\pgindex} \def\cindexsub {\begingroup\obeylines\cindexsub} {\obeylines % \gdef\cindexsub "#1" #2^^M{\endgroup % \dosubind{cp}{#2}{#1}}} % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % \parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % \smallfonts \rm \tolerance = 9500 \plainfrenchspacing \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. % Change catcode of @ here so that if the index file contains % \initial {@} % as its first line, TeX doesn't complain about mismatched braces % (because it thinks @} is a control sequence). \catcode`\@ = 11 \openin 1 \jobname.#1s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent \else % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. \read 1 to \temp \ifeof 1 \putwordIndexIsEmpty \else % Index files are almost Texinfo source, but we use \ as the escape % character. It would be better to use @, but that's too big a change % to make right now. \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns \input \jobname.#1s \enddoublecolumns \fi \fi \closein 1 \endgroup} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. \def\initial#1{{% % Some minor font changes for the special characters. \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt % % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. \nobreak \vskip 0pt plus 3\baselineskip \penalty 0 \vskip 0pt plus -3\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus .5\baselineskip \leftline{\secbf #1}% % Do our best not to break after the initial. \nobreak \vskip .33\baselineskip plus .1\baselineskip }} % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % % A straightforward implementation would start like this: % \def\entry#1#2{... % But this freezes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% \begingroup % % Start a new paragraph if necessary, so our assignments below can't % affect previous text. \par % % Do not fill out the last line with white space. \parfillskip = 0in % % No extra space above this paragraph. \parskip = 0in % % Do not prefer a separate line ending with a hyphen to fewer lines. \finalhyphendemerits = 0 % % \hangindent is only relevant when the entry text and page number % don't both fit on one line. In that case, bob suggests starting the % dots pretty far over on the line. Unfortunately, a large % indentation looks wrong when the entry text itself is broken across % lines. So we use a small indentation and put up with long leaders. % % \hangafter is reset to 1 (which is the value we want) at the start % of each paragraph, so we need not do anything with that. \hangindent = 2em % % When the entry text needs to be broken, just fill out the first line % with blank space. \rightskip = 0pt plus1fil % % A bit of stretch before each entry for the benefit of balancing % columns. \vskip 0pt plus1pt % % When reading the text of entry, convert explicit line breaks % from @* into spaces. The user might give these in long section % titles, for instance. \def\*{\unskip\space\ignorespaces}% \def\entrybreak{\hfil\break}% % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } \def\entrybreak{\unskip\space\ignorespaces}% \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. } \def\finishentry#1{% % #1 is the page number. % % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. \setbox\boxA = \hbox{#1}% \ifdim\wd\boxA = 0pt \ % \else % % If we must, put the page number on a line of its own, and fill out % this line with blank space. (The \hfil is overwhelmed with the % fill leaders glue in \indexdotfill if the page number does fit.) \hfil\penalty50 \null\nobreak\indexdotfill % Have leaders before the page number. % % The `\ ' here is removed by the implicit \unskip that TeX does as % part of (the primitive) \par. Without it, a spurious underfull % \hbox ensues. \ifpdf \pdfgettoks#1.% \ \the\toksA \else \ #1% \fi \fi \par \endgroup } % Like plain.tex's \dotfill, except uses up at least 1 em. \def\indexdotfill{\cleaders \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} \newskip\secondaryindent \secondaryindent=0.5cm \def\secondary#1#2{{% \parfillskip=0in \parskip=0in \hangindent=1in \hangafter=1 \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill \ifpdf \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. \else #2 \fi \par }} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. \catcode`\@=11 \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns % Grab any single-column material above us. \output = {% % % Here is a possibility not foreseen in manmac: if we accumulate a % whole lot of material, we might end up calling this \output % routine twice in a row (see the doublecol-lose test, which is % essentially a couple of indexes with @setchapternewpage off). In % that case we just ship out what is in \partialpage with the normal % output routine. Generally, \partialpage will be empty when this % runs and this will be a no-op. See the indexspread.tex test case. \ifvoid\partialpage \else \onepageout{\pagecontents\partialpage}% \fi % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. \unvbox\PAGE \kern-\topskip \kern\baselineskip }% }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. \output = {\doublecolumnout}% % % Change the page size parameters. We could do this once outside this % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 % format, but then we repeat the same computation. Repeating a couple % of assignments once per index is clearly meaningless for the % execution time, so we may as well do it in one place. % % First we halve the line length, less a little for the gutter between % the columns. We compute the gutter based on the line length, so it % changes automatically with the paper format. The magic constant % below is chosen so that the gutter has the same value (well, +-<1pt) % as it did when we hard-coded it. % % We put the result in a separate register, \doublecolumhsize, so we % can restore it in \pagesofar, after \hsize itself has (potentially) % been clobbered. % \doublecolumnhsize = \hsize \advance\doublecolumnhsize by -.04154\hsize \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % % Double the \vsize as well. (We don't need a separate register here, % since nobody clobbers \vsize.) \vsize = 2\vsize } % The double-column output routine for all double-column pages except % the last. % \def\doublecolumnout{% \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. \dimen@ = \vsize \divide\dimen@ by 2 \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty } % % Re-output the contents of the output page -- any previous material, % followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% } % % All done with double columns. \def\enddoublecolumns{% % The following penalty ensures that the page builder is exercised % _before_ we change the output routine. This is necessary in the % following situation: % % The last section of the index consists only of a single entry. % Before this section, \pagetotal is less than \pagegoal, so no % break occurs before the last section starts. However, the last % section, consisting of \initial and the single \entry, does not % fit on the page and has to be broken off. Without the following % penalty the page builder will not be exercised until \eject % below, and by that time we'll already have changed the output % routine to the \balancecolumns version, so the next-to-last % double-column page will be processed with \balancecolumns, which % is wrong: The two columns will go to the main vertical list, with % the broken-off section in the recent contributions. As soon as % the output routine finishes, TeX starts reconsidering the page % break. The two columns and the broken-off section both fit on the % page, because the two columns now take up only half of the page % goal. When TeX sees \eject from below which follows the final % section, it invokes the new output routine that we've set after % \balancecolumns below; \onepageout will try to fit the two columns % and the final section into the vbox of \pageheight (see % \pagebody), causing an overfull box. % % Note that glue won't work here, because glue does not exercise the % page builder, unlike penalties (see The TeXbook, pp. 280-281). \penalty0 % \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. \balancecolumns % % If we end up splitting too much material for the current page, % though, there will be another page break right after this \output % invocation ends. Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal % definition right away. (We hope \balancecolumns will never be % called on to balance too much material, but if it is, this makes % the output somewhat more palatable.) \global\output = {\onepageout{\pagecontents\PAGE}}% }% \eject \endgroup % started in \begindoublecolumns % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column % typesetting, so reset \pagegoal to the normal \vsize (after the % \endgroup where \vsize got restored). \pagegoal = \vsize } % % Called at the end of the double column material. \def\balancecolumns{% \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip \divide\dimen@ by 2 % target to split to %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% \splittopskip = \topskip % Loop until we get a decent breakpoint. {% \vbadness = 10000 \loop \global\setbox3 = \copy0 \global\setbox1 = \vsplit3 to \dimen@ \ifdim\ht3>\dimen@ \global\advance\dimen@ by 1pt \repeat }% %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% \setbox0=\vbox to\dimen@{\unvbox1}% \setbox2=\vbox to\dimen@{\unvbox3}% % \pagesofar } \catcode`\@ = \other \message{sectioning,} % Chapters, sections, etc. % Let's start with @part. \outer\parseargdef\part{\partzzz{#1}} \def\partzzz#1{% \chapoddpage \null \vskip.3\vsize % move it down on the page a bit \begingroup \noindent \titlefonts\rmisbold #1\par % the text \let\lastnode=\empty % no node to associate with \writetocentry{part}{#1}{}% but put it in the toc \headingsoff % no headline or footline on the part page \chapoddpage \endgroup } % \unnumberedno is an oxymoron. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 % chapters, we're in trouble anyway, I'm sure.) \newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 \newcount\subsubsecno \subsubsecno=0 % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ % % \def\appendixletter{\char\the\appendixno} % We do the following ugly conditional instead of the above simple % construct for the sake of pdftex, which needs the actual % letter in the expansion, not just typeset. % \def\appendixletter{% \ifnum\appendixno=`A A% \else\ifnum\appendixno=`B B% \else\ifnum\appendixno=`C C% \else\ifnum\appendixno=`D D% \else\ifnum\appendixno=`E E% \else\ifnum\appendixno=`F F% \else\ifnum\appendixno=`G G% \else\ifnum\appendixno=`H H% \else\ifnum\appendixno=`I I% \else\ifnum\appendixno=`J J% \else\ifnum\appendixno=`K K% \else\ifnum\appendixno=`L L% \else\ifnum\appendixno=`M M% \else\ifnum\appendixno=`N N% \else\ifnum\appendixno=`O O% \else\ifnum\appendixno=`P P% \else\ifnum\appendixno=`Q Q% \else\ifnum\appendixno=`R R% \else\ifnum\appendixno=`S S% \else\ifnum\appendixno=`T T% \else\ifnum\appendixno=`U U% \else\ifnum\appendixno=`V V% \else\ifnum\appendixno=`W W% \else\ifnum\appendixno=`X X% \else\ifnum\appendixno=`Y Y% \else\ifnum\appendixno=`Z Z% % The \the is necessary, despite appearances, because \appendixletter is % expanded while writing the .toc file. \char\appendixno is not % expandable, thus it is written literally, thus all appendixes come out % with the same letter (or @) in the toc without it. \else\char\the\appendixno \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % Each @chapter defines these (using marks) as the number+name, number % and name of the chapter. Page headings and footings can use % these. @section does likewise. \def\thischapter{} \def\thischapternum{} \def\thischaptername{} \def\thissection{} \def\thissectionnum{} \def\thissectionname{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} \let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} \let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. % To achieve this, remember the "biggest" unnum. sec. we are currently in: \chardef\unnlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. \def\chapheadtype{N} % Choose a heading macro % #1 is heading type % #2 is heading level % #3 is text for heading \def\genhead#1#2#3{% % Compute the abs. sec. level: \absseclevel=#2 \advance\absseclevel by \secbase % Make sure \absseclevel doesn't fall outside the range: \ifnum \absseclevel < 0 \absseclevel = 0 \else \ifnum \absseclevel > 3 \absseclevel = 3 \fi \fi % The heading type: \def\headtype{#1}% \if \headtype U% \ifnum \absseclevel < \unnlevel \chardef\unnlevel = \absseclevel \fi \else % Check for appendix sections: \ifnum \absseclevel = 0 \edef\chapheadtype{\headtype}% \else \if \headtype A\if \chapheadtype N% \errmessage{@appendix... within a non-appendix chapter}% \fi\fi \fi % Check for numbered within unnumbered: \ifnum \absseclevel > \unnlevel \def\headtype{U}% \else \chardef\unnlevel = 3 \fi \fi % Now print the heading: \if \headtype U% \ifcase\absseclevel \unnumberedzzz{#3}% \or \unnumberedseczzz{#3}% \or \unnumberedsubseczzz{#3}% \or \unnumberedsubsubseczzz{#3}% \fi \else \if \headtype A% \ifcase\absseclevel \appendixzzz{#3}% \or \appendixsectionzzz{#3}% \or \appendixsubseczzz{#3}% \or \appendixsubsubseczzz{#3}% \fi \else \ifcase\absseclevel \chapterzzz{#3}% \or \seczzz{#3}% \or \numberedsubseczzz{#3}% \or \numberedsubsubseczzz{#3}% \fi \fi \fi \suppressfirstparagraphindent } % an interface: \def\numhead{\genhead N} \def\apphead{\genhead A} \def\unnmhead{\genhead U} % @chapter, @appendix, @unnumbered. Increment top-level counter, reset % all lower-level sectioning counters to zero. % % Also set \chaplevelprefix, which we prepend to @float sequence numbers % (e.g., figures), q.v. By default (before any chapter), that is empty. \let\chaplevelprefix = \empty % \outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz \def\chapterzzz#1{% % section resetting is \global in case the chapter is in a group, such % as an @include file. \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\chapno by 1 % % Used for \float. \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % % \putwordChapter can contain complex things in translations. \toks0=\expandafter{\putwordChapter}% \message{\the\toks0 \space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% % % So @section and the like are numbered underneath this chapter. \global\let\section = \numberedsec \global\let\subsection = \numberedsubsec \global\let\subsubsection = \numberedsubsubsec } \outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz % \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % % \putwordAppendix can contain complex things in translations. \toks0=\expandafter{\putwordAppendix}% \message{\the\toks0 \space \appendixletter}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % \global\let\section = \appendixsec \global\let\subsection = \appendixsubsec \global\let\subsubsection = \appendixsubsubsec } % normally unnmhead0 calls unnumberedzzz: \outer\parseargdef\unnumbered{\unnmhead0{#1}} \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 % % Since an unnumbered has no number, no prefix for figures. \global\let\chaplevelprefix = \empty \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX % expanded them. For example, in `@unnumbered The @cite{Book}', TeX % expanded @cite (which turns out to cause errors because \cite is meant % to be executed, not expanded). % % Anyway, we don't want the fully-expanded definition of @cite to appear % as a result of the \message, we just want `@cite' itself. We use % \the to achieve this: TeX expands \the only once, % simply yielding the contents of . (We also do this for % the toc entries.) \toks0 = {#1}% \message{(\the\toks0)}% % \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % \global\let\section = \unnumberedsec \global\let\subsection = \unnumberedsubsec \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% % Well, we could do the following in a group, but that would break % an assumption that \chapmacro is called at the outermost level. % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax } % @top is like @unnumbered. \let\top\unnumbered % Sections. % \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } % normally calls appendixsectionzzz: \outer\parseargdef\appendixsection{\apphead1{#1}} \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection % normally calls unnumberedseczzz: \outer\parseargdef\unnumberedsec{\unnmhead1{#1}} \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. % % normally calls numberedsubseczzz: \outer\parseargdef\numberedsubsec{\numhead2{#1}} \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } % normally calls appendixsubseczzz: \outer\parseargdef\appendixsubsec{\apphead2{#1}} \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } % normally calls unnumberedsubseczzz: \outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. % % normally numberedsubsubseczzz: \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } % normally appendixsubsubseczzz: \outer\parseargdef\appendixsubsubsec{\apphead3{#1}} \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } % normally unnumberedsubsubseczzz: \outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. \let\section = \numberedsec \let\subsection = \numberedsubsec \let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz } \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% \vbox{\chapfonts \raggedtitlesettings #1\par}% \nobreak\bigskip \nobreak \suppressfirstparagraphindent } % @heading, @subheading, @subsubheading. \parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. % Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} % Parameter controlling skip before chapter headings (if needed) \newskip\chapheadingskip % Define plain chapter starts, and page on/off switching for it. \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} % Because \domark is called before \chapoddpage, the filler page will % get the headings for the next chapter, which is wrong. But we don't % care -- we just disable all headings on the filler page. \def\chapoddpage{% \chappager \ifodd\pageno \else \begingroup \headingsoff \null \chappager \endgroup \fi } \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chapbreak \global\let\pagealignmacro=\chappager} \def\CHAPPAGon{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chappager \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} \def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage \global\def\HEADINGSon{\HEADINGSdouble}} \CHAPPAGon % Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. % % To test against our argument. \def\Ynothingkeyword{Ynothing} \def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% % Insert the first mark before the heading break (see notes for \domark). \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% \gdef\thissection{}}% % \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{\thischaptername}}% \else\ifx\temptype\Yomitfromtockeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{}}% \else\ifx\temptype\Yappendixkeyword \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\appendixletter}% % \noexpand\putwordAppendix avoids expanding indigestible % commands in some of the translations. \gdef\noexpand\thischapter{\noexpand\putwordAppendix{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \else \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\the\chapno}% % \noexpand\putwordChapter avoids expanding indigestible % commands in some of the translations. \gdef\noexpand\thischapter{\noexpand\putwordChapter{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \fi\fi\fi % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert the chapter heading break. \pchapsepmacro % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \domark % {% \chapfonts \rmisbold % % Have to define \lastsection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. \gdef\lastsection{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the % \donoderef, because we include the current node name in the toc % entry, and \donoderef resets it to empty. \writetocentry{\toctype}{#1}{#3}% % % For pdftex, we have to write out the node definition (aka, make % the pdfdest) after any page break, but before the actual text has % been typeset. If the destination for the pdf outline is after the % text, then jumping from the outline may wind up with the text not % being visible, for instance under high magnification. \donoderef{#2}% % % Typeset the actual heading. \nobreak % Avoid page breaks at the interline glue. \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax \def\centerparameters{% \advance\rightskip by 3\rightskip \leftskip = \rightskip \parfillskip = 0pt } % I don't think this chapter style is supported any more, so I'm not % updating it with the new noderef stuff. We'll see. --karl, 11aug03. % \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% \chapoddpage \vbox{\chapfonts \raggedtitlesettings #1\par}% \nobreak\bigskip\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% \chapoddpage \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% \nobreak\bigskip \nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen \global\let\centerchapmacro=\centerchfopen} % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % \newskip\secheadingskip \def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. \newskip\subsecheadingskip \def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. \def\subsubsecheadingskip{\subsecheadingskip} \def\subsubsecheadingbreak{\subsecheadingbreak} % Print any size, any type, section title. % % #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % \def\seckeyword{sec} % \def\sectionheading#1#2#3#4{% {% \checkenv{}% should not be in an environment. % % Switch to the right set of fonts. \csname #2fonts\endcsname \rmisbold % \def\sectionlevel{#2}% \def\temptype{#3}% % % Insert first mark before the heading break (see notes for \domark). \let\prevsectiondefs=\lastsectiondefs \ifx\temptype\Ynothingkeyword \ifx\sectionlevel\seckeyword \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% \gdef\thissection{\thissectionname}}% \fi \else\ifx\temptype\Yomitfromtockeyword % Don't redefine \thissection. \else\ifx\temptype\Yappendixkeyword \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% % \noexpand\putwordSection avoids expanding indigestible % commands in some of the translations. \gdef\noexpand\thissection{\noexpand\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \else \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% % \noexpand\putwordSection avoids expanding indigestible % commands in some of the translations. \gdef\noexpand\thissection{\noexpand\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \fi\fi\fi % % Go into vertical mode. Usually we'll already be there, but we % don't want the following whatsit to end up in a preceding paragraph % if the document didn't happen to have a blank line. \par % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert space above the heading. \csname #2headingbreak\endcsname % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevsectiondefs=\lastsectiondefs \domark % % Only insert the space after the number if we have a section number. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% \gdef\lastsection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, % and don't redefine \lastsection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% \gdef\lastsection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% \gdef\lastsection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chapmacro. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). % Again, see comments in \chapmacro. \donoderef{#3}% % % Interline glue will be inserted when the vbox is completed. % That glue will be a valid breakpoint for the page, since it'll be % preceded by a whatsit (usually from the \donoderef, or from the % \writetocentry if there was no node). We don't want to allow that % break, since then the whatsits could end up on page n while the % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. \nobreak % % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% % Add extra space after the heading -- half of whatever came above it. % Don't allow stretch, though. \kern .5 \csname #2headingskip\endcsname % % Do not let the kern be a potential breakpoint, as it would be if it % was followed by glue. \nobreak % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a % discardable item.) However, when a paragraph is not started next % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out % or the negative glue will cause weirdly wrong output, typically % obscuring the section heading with something else. \vskip-\parskip % % This is so the last item on the main vertical list is a known % \penalty > 10000, so \startdefun, etc., can recognize the situation % and do the needful. \penalty 10001 } \message{toc,} % Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. % Called from @chapter, etc. % % Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} % We append the current node name (if any) and page number as additional % arguments for the \{chap,sec,...}entry macros which will eventually % read this. The node name is used in the pdf outlines as the % destination to jump to. % % We open the .toc file for writing here instead of at @setfilename (or % any other fixed time) so that @contents can be anywhere in the document. % But if #1 is `omit', then we don't do anything. This is used for the % table of contents chapter openings themselves. % \newif\iftocfileopened \def\omitkeyword{omit}% % \def\writetocentry#1#2#3{% \edef\writetoctype{#1}% \ifx\writetoctype\omitkeyword \else \iftocfileopened\else \immediate\openout\tocfile = \jobname.toc \global\tocfileopenedtrue \fi % \iflinks {\atdummies \edef\temp{% \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% \temp }% \fi \fi % % Tell \shipout to create a pdf destination on each page, if we're % writing pdf. These are used in the table of contents. We can't % just write one on every page because the title pages are numbered % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. \ifpdf \global\pdfmakepagedesttrue \fi } % These characters do not print properly in the Computer Modern roman % fonts, so we must take special care. This is more or less redundant % with the Texinfo input format setup at the end of this file. % \def\activecatcodes{% \catcode`\"=\active \catcode`\$=\active \catcode`\<=\active \catcode`\>=\active \catcode`\\=\active \catcode`\^=\active \catcode`\_=\active \catcode`\|=\active \catcode`\~=\active } % Read the toc file, which is essentially Texinfo input. \def\readtocfile{% \setupdatafile \activecatcodes \input \tocreadfilename } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 % Prepare to read what we've written to \tocfile. % \def\startcontents#1{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. Thus, we maintain % \contentsalignmacro in parallel with \pagealignmacro. % From: Torbjorn Granlund \contentsalignmacro \immediate\closeout\tocfile % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } % redefined for the two-volume lispref. We always output on % \jobname.toc even if this is redefined. % \def\tocreadfilename{\jobname.toc} % Normal (long) toc. % \def\contents{% \startcontents{\putwordTOC}% \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \ifeof 1 \else \pdfmakeoutlines \fi \closein 1 \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% \startcontents{\putwordShortTOC}% % \let\partentry = \shortpartentry \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry % We want a true roman here for the page numbers. \secfonts \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl \let\tt=\shortconttt \rm \hyphenpenalty = 10000 \advance\baselineskip by 1pt % Open it up a little. \def\numsecentry##1##2##3##4{} \let\appsecentry = \numsecentry \let\unnsecentry = \numsecentry \let\numsubsecentry = \numsecentry \let\appsubsecentry = \numsecentry \let\unnsubsecentry = \numsecentry \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \closein 1 \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } \let\shortcontents = \summarycontents % Typeset the label for a chapter or appendix for the short contents. % The arg is, e.g., `A' for an appendix, or `3' for a chapter. % \def\shortchaplabel#1{% % This space should be enough, since a single number is .5em, and the % widest letter (M) is 1em, at least in the Computer Modern fonts. % But use \hss just in case. % (This space doesn't include the extra space that gets added after % the label; that gets put in by \shortchapentry above.) % % We'd like to right-justify chapter numbers, but that looks strange % with appendix letters. And right-justifying numbers and % left-justifying letters looks strange when there is less than 10 % chapters. Have to read the whole toc once to know how many chapters % there are before deciding ... \hbox to 1em{#1\hss}% } % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... % Parts, in the main contents. Replace the part number, which doesn't % exist, with an empty box. Let's hope all the numbers have the same width. % Also ignore the page number, which is conventionally not printed. \def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} \def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}} % % Parts, in the short toc. \def\shortpartentry#1#2#3#4{% \penalty-300 \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip \shortchapentry{{\bf #1}}{\numeralbox}{}{}% } % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } % Appendices, in the main contents. % Need the word Appendix, and a fixed-size box. % \def\appendixbox#1{% % We use M since it's probably the widest letter. \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % \def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} \def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. \def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} \let\appsecentry=\numsecentry \def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. \def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} \let\appsubsecentry=\numsubsecentry \def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. \def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} \let\appsubsubsecentry=\numsubsubsecentry \def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. % Same as \defaultparindent. \newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. % % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} % We use the same \entry macro as for the index entries. \let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} \def\dopageno#1{{\rm #1}} \def\doshortpageno#1{{\rm #1}} \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} \def\subsecentryfonts{\textfonts} \def\subsubsecentryfonts{\textfonts} \message{environments,} % @foo ... @end foo. % @tex ... @end tex escapes into raw TeX temporarily. % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain @ character. \envdef\tex{% \setupmarkupstyle{tex}% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 \catcode `\+=\other \catcode `\"=\other \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other \catcode`\`=\other \catcode`\'=\other \escapechar=`\\ % % ' is active in math mode (mathcode"8000). So reset it, and all our % other math active characters (just in case), to plain's definitions. \mathactive % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc \let\,=\ptexcomma \let\.=\ptexdot \let\dots=\ptexdots \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext \expandafter \let\csname top\endcsname=\ptextop % outer \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% } % There is no need to define \Etex. % Define @lisp ... @end lisp. % @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in % This is the definition that ^^M gets inside @lisp, @example, and other % such environments. \null is better than a space, since it doesn't % have any width. \def\lisppar{\null\endgraf} % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz and % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf \ifdim\lastskip<\envskipamount \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi }} \let\afterenvbreak = \aboveenvbreak % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will % also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. \font\circle=lcircle10 \newdimen\circthick \newdimen\cartouter\newdimen\cartinner \newskip\normbskip\newskip\normpskip\newskip\normlskip \circthick=\fontdimen8\circle % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} \def\cbl{{\circle\char'012\hskip -6pt}} \def\cbr{{\hskip 6pt\circle\char'011}} \def\carttop{\hbox to \cartouter{\hskip\lskip \ctl\leaders\hrule height\circthick\hfil\ctr \hskip\rskip}} \def\cartbot{\hbox to \cartouter{\hskip\lskip \cbl\leaders\hrule height\circthick\hfil\cbr \hskip\rskip}} % \newskip\lskip\newskip\rskip \envdef\cartouche{% \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip \leftskip=0pt\rightskip=0pt % we want these *outside*. \cartinner=\hsize \advance\cartinner by-\lskip \advance\cartinner by-\rskip \cartouter=\hsize \advance\cartouter by 18.4pt % allow for 3pt kerns on either % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. \let\nonarrowing = t% % % If this cartouche directly follows a sectioning command, we need the % \parskip glue (backspaced over by default) or the cartouche can % collide with the section heading. \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi % \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup \hskip\lskip \vrule\kern3pt \vbox\bgroup \kern3pt \hsize=\cartinner \baselineskip=\normbskip \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip \comment % For explanation, see the end of def\group. } \def\Ecartouche{% \ifhmode\par\fi \kern3pt \egroup \kern3pt\vrule \hskip\rskip \egroup \cartbot \egroup \checkinserts } % This macro is called at the beginning of all the @example variants, % inside a group. \newdimen\nonfillparindent \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt % Turn off paragraph indentation but redefine \indent to emulate % the normal \indent. \nonfillparindent=\parindent \parindent = 0pt \let\indent\nonfillindent % \emergencystretch = 0pt % don't try to avoid overfull boxes \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing \else \let\nonarrowing = \relax \fi \let\exdent=\nofillexdent } \begingroup \obeyspaces % We want to swallow spaces (but not other tokens) after the fake % @indent in our nonfill-environments, where spaces are normally % active and set to @tie, resulting in them not being ignored after % @indent. \gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}% \gdef\nonfillindentcheck{% \ifx\temp % \expandafter\nonfillindentgobble% \else% \leavevmode\nonfillindentbox% \fi% }% \endgroup \def\nonfillindentgobble#1{\nonfillindent} \def\nonfillindentbox{\hbox to \nonfillparindent{\hss}} % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: % @example, @display, @format, @lisp % \def\smallword{small} \def\nosmallword{nosmall} \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword % end paragraph for sake of leading, in case document has no blank % line. This is redundant with what happens in \aboveenvbreak, but % we need to do it before changing the fonts, and it's inconvenient % to change the fonts afterward. \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. % Let's do it in one command. #1 is the env name, #2 the definition. \def\makedispenvdef#1#2{% \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}% \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}% \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } % Define two environment synonyms (#1 and #2) for an environment. \def\maketwodispenvdef#1#2#3{% \makedispenvdef{#1}{#3}% \makedispenvdef{#2}{#3}% } % % @lisp: indented, narrowed, typewriter font; % @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % \maketwodispenvdef{lisp}{example}{% \nonfillstart \tt\setupmarkupstyle{example}% \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. \gobble % eat return } % @display/@smalldisplay: same as @lisp except keep current font. % \makedispenvdef{display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % \makedispenvdef{format}{% \let\nonarrowing = t% \nonfillstart \gobble } % @flushleft: same as @format, but doesn't obey \SETdispenvsize. \envdef\flushleft{% \let\nonarrowing = t% \nonfillstart \gobble } \let\Eflushleft = \afterenvbreak % @flushright. % \envdef\flushright{% \let\nonarrowing = t% \nonfillstart \advance\leftskip by 0pt plus 1fill\relax \gobble } \let\Eflushright = \afterenvbreak % @raggedright does more-or-less normal line breaking but no right % justification. From plain.tex. \envdef\raggedright{% \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax } \let\Eraggedright\par \envdef\raggedleft{% \parindent=0pt \leftskip0pt plus2em \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt \hbadness=10000 % Last line will usually be underfull, so turn off % badness reporting. } \let\Eraggedleft\par \envdef\raggedcenter{% \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt \hbadness=10000 % Last line will usually be underfull, so turn off % badness reporting. } \let\Eraggedcenter\par % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % \makedispenvdef{quotation}{\quotationstart} % \def\quotationstart{% \indentedblockstart % same as \indentedblock, but increase right margin too. \ifx\nonarrowing\relax \advance\rightskip by \lispnarrowing \fi \parsearg\quotationlabel } % We have retained a nonzero parskip for the environment, since we're % doing normal filling. % \def\Equotation{% \par \ifx\quotationauthor\thisisundefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } \def\Esmallquotation{\Equotation} % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% \def\temp{#1}% \ifx\temp\empty \else {\bf #1: }% \fi } % @indentedblock is like @quotation, but indents only on the left and % has no optional argument. % \makedispenvdef{indentedblock}{\indentedblockstart} % \def\indentedblockstart{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip \parindent=0pt % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing \exdentamount = \lispnarrowing \else \let\nonarrowing = \relax \fi } % Keep a nonzero parskip for the environment, since we're doing normal filling. % \def\Eindentedblock{% \par {\parskip=0pt \afterenvbreak}% } \def\Esmallindentedblock{\Eindentedblock} % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, % we need the curly braces so that makeinfo sees the @verb command, eg: % `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org % % [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. % % [Knuth] p.344; only we need to do the other characters Texinfo sets % active too. Otherwise, they get lost as the first character on a % verbatim line. \def\dospecials{% \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% % Don't do the quotes -- if we do, @set txicodequoteundirected and % @set txicodequotebacktick will not have effect on @verb and % @verbatim, and ?` and !` ligatures won't get disabled. %\do\`\do\'% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % % Setup for the @verb command. % % Eight spaces for a tab \begingroup \catcode`\^^I=\active \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} \endgroup % \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% \setupmarkupstyle{verb}% \tabeightspaces % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces } % Setup for the @verbatim environment % % Real tab expansion. \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % % We typeset each line of the verbatim in an \hbox, so we can handle % tabs. The \global is in case the verbatim line starts with an accent, % or some other command that starts with a begin-group. Otherwise, the % entire \verbbox would disappear at the corresponding end-group, before % it is typeset. Meanwhile, we can't have nested verbatim commands % (can we?), so the \global won't be overwriting itself. \newbox\verbbox \def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} % \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab \divide\dimen\verbbox by\tabw \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox }% } \endgroup % start the verbatim environment. \def\setupverbatim{% \let\nonarrowing = t% \nonfillstart \tt % easiest (and conventionally used) font for verbatim % The \leavevmode here is for blank lines. Otherwise, we would % never \starttabox and the \egroup would end verbatim mode. \def\par{\leavevmode\egroup\box\verbbox\endgraf}% \tabexpand \setupmarkupstyle{verbatim}% % Respect line breaks, % print special symbols as themselves, and % make each space count. % Must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } % Do the @verb magic: verbatim text is quoted by unique % delimiter characters. Before first delimiter expect a % right brace, after last delimiter expect closing brace: % % \def\doverb'{'#1'}'{#1} % % [Knuth] p. 382; only eat outer {} \begingroup \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % \def\verb{\begingroup\setupverb\doverb} % % % Do the @verbatim magic: define the macro \doverbatim so that % the (first) argument ends when '@end verbatim' is reached, ie: % % \def\doverbatim#1@end verbatim{#1} % % For Texinfo it's a lot easier than for LaTeX, % because texinfo's \verbatim doesn't stop at '\end{verbatim}': % we need not redefine '\', '{' and '}'. % % Inspired by LaTeX's verbatim command set [latex.ltx] % \begingroup \catcode`\ =\active \obeylines % % ignore everything up to the first ^^M, that's the newline at the end % of the @verbatim input line itself. Otherwise we get an extra blank % line in the output. \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% % We really want {...\end verbatim} in the body of the macro, but % without the active space; thus we have to use \xdef and \gobble. \endgroup % \envdef\verbatim{% \setupverbatim\doverbatim } \let\Everbatim = \afterenvbreak % @verbatiminclude FILE - insert text of file in verbatim environment. % \def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \def\doverbatiminclude#1{% {% \makevalueexpandable \setupverbatim \indexnofonts % Allow `@@' and other weird things in file names. \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% \input #1 \afterenvbreak }% } % @copying ... @end copying. % Save the text away for @insertcopying later. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as % possible is very desirable. % \def\copying{\checkenv{}\begingroup\scanargctxt\docopying} \def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} % \def\insertcopying{% \begingroup \parindent = 0pt % paragraph indentation looks wrong on title page \scanexp\copyingtext \endgroup } \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt \newcount\defunpenalty % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak \defunpenalty=10003 % Will keep this @deffn together with the % following @def command, see below. \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check specifically for penalty 10002, inserted % by \printdefunline, instead of 10000, since the sectioning % commands also insert a nobreak penalty, and we don't want to allow % a break between a section heading and a defun. % % As a further refinement, we avoid "club" headers by signalling % with penalty of 10003 after the very first @deffn in the % sequence (see above), and penalty of 10002 after any following % @def command. \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. \medskip % preceded by discardable penalty, so not a breakpoint \fi % \parindent=0in \advance\leftskip by \defbodyindent \exdentamount=\defbodyindent } \def\dodefunx#1{% % First, check whether we are in the right environment: \checkenv#1% % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% } \def\gobbledefun#1\startdefun{} % \printdefunline \deffnheader{text} % \def\printdefunline#1#2{% \begingroup % call \deffnheader: #1#2 \endheader % common ending: \interlinepenalty = 10000 \advance\rightskip by 0pt plus 1fil\relax \endgraf \nobreak\vskip -\parskip \penalty\defunpenalty % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts \endgroup } \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; % the only thing remaining is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } % \domakedefun \deffn \deffnx \deffnheader % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. % \def\domakedefun#1#2#3{% \envdef#1{% \startdefun \doingtypefnfalse % distinguish typed functions from all else \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } \newif\ifdoingtypefn % doing typed function? \newif\ifrettypeownline % typeset return type on its own line? % @deftypefnnewline on|off says whether the return type of typed functions % are printed on their own line. This affects @deftypefn, @deftypefun, % @deftypeop, and @deftypemethod. % \parseargdef\deftypefnnewline{% \def\temp{#1}% \ifx\temp\onword \expandafter\let\csname SETtxideftypefnnl\endcsname = \empty \else\ifx\temp\offword \expandafter\let\csname SETtxideftypefnnl\endcsname = \relax \else \errhelp = \EMsimple \errmessage{Unknown @txideftypefnnl value `\temp', must be on|off}% \fi\fi } % Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} % @deffn category class name args \makedefun{defop}#1 {\defopon{#1\ \putwordon}} % \defopon {category on}class name args \def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } % Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} % @deftypeop category class type name args \makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} % \deftypeopon {category on}class type name args \def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deftypefngeneral {subind}category type name args % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% \doingtypefntrue \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } % Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} % @deftypecv category class type var args \makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} % \deftypecvof {category of}class type var args \def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } % \deftypecvgeneral {subind}category type var args % \def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% \dosubind{vr}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } % Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args \makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } % Types: % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% \defname{#1}{}{#2}\defunargs{#3\unskip}% } % Remaining @defun-like shortcuts: \makedefun{defun}{\deffnheader{\putwordDeffunc} } \makedefun{defmac}{\deffnheader{\putwordDefmac} } \makedefun{defspec}{\deffnheader{\putwordDefspec} } \makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } \makedefun{defmethod}{\defopon\putwordMethodon} \makedefun{deftypemethod}{\deftypeopon\putwordMethodon} \makedefun{defivar}{\defcvof\putwordInstanceVariableof} \makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". % #2 is the return type, if any. % #3 is the function name. % % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% \par % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % % Determine if we are typesetting the return type of a typed function % on a line by itself. \rettypeownlinefalse \ifdoingtypefn % doing a typed function specifically? % then check user option for putting return type on its own line: \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else \rettypeownlinetrue \fi \fi % % How we'll format the category name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % % Figure out line sizes for the paragraph shape. We'll always have at % least two. \tempnum = 2 % % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip % % If doing a return type on its own line, we'll have another line. \ifrettypeownline \advance\tempnum by 1 \def\maybeshapeline{0in \hsize}% \else \def\maybeshapeline{}% \fi % % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent % % The final paragraph shape: \parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2 % % Put the category name at the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize % \hsize has to be shortened this way: \kern\leftskip % Intentionally do not respect \rightskip, since we need the space. }% % % Allow all lines to be underfull without complaint: \tolerance=10000 \hbadness=10000 \exdentamount=\defbodyindent {% % defun fonts. We use typewriter by default (used to be bold) because: % . we're printing identifiers, they should be in tt in principle. % . in languages with many accents, such as Czech or French, it's % common to leave accents off identifiers. The result looks ok in % tt, but exceedingly strange in rm. % . we don't want -- and --- to be treated as ligatures. % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt \def\temp{#2}% text of the return type \ifx\temp\empty\else \tclose{\temp}% typeset the return type \ifrettypeownline % put return type on its own line; prohibit line break following: \hfil\vadjust{\nobreak}\break \else \space % type on same line, so just followed by a space \fi \fi % no return type #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm % \boldbrax % arguments will be output next, if any. } % Print arguments in slanted roman (not ttsl), inconsistently with using % tt for the name. This is because literal text is sometimes needed in % the argument list (groff manual), and ttsl and tt are not very % distinguishable. Prevent hyphenation at `-' chars. % \def\defunargs#1{% % use sl by default (not ttsl), % tt for the names. \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we % want a way to get ttsl. We used to recommend @var for that, so % leave the code in, but it's strange for @var to lead to typewriter. % Nowadays we recommend @code, since the difference between a ttsl hyphen % and a tt hyphen is pretty tiny. @code also disables ?` !`. \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% #1% \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. % \def\activeparens{% \catcode`\(=\active \catcode`\)=\active \catcode`\[=\active \catcode`\]=\active \catcode`\&=\active } % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. { \activeparens \global\let(=\lparen \global\let)=\rparen \global\let[=\lbrack \global\let]=\rbrack \global\let& = \& \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \newcount\parencount % If we encounter &foo, then turn on ()-hacking afterwards \newif\ifampseen \def\amprm#1 {\ampseentrue{\bf\ }} \def\parenfont{% \ifampseen % At the first level, print parens in roman, % otherwise use the default font. \ifnum \parencount=1 \rm \fi \else % The \sf parens (in \boldbrax) actually are a little bolder than % the contained text. This is especially needed for [ and ] . \sf \fi } \def\infirstlevel#1{% \ifampseen \ifnum\parencount=1 #1% \fi \fi } \def\bfafterword#1 {#1 \bf} \def\opnr{% \global\advance\parencount by 1 {\parenfont(}% \infirstlevel \bfafterword } \def\clnr{% {\parenfont)}% \infirstlevel \sl \global\advance\parencount by -1 } \newcount\brackcount \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% } \def\rbrb{% {\bf]}% \global\advance\brackcount by -1 } \def\checkparencounts{% \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } % these should not use \errmessage; the glibc manual, at least, actually % has such constructs (when documenting function pointers). \def\badparencount{% \message{Warning: unbalanced parentheses in @def...}% \global\parencount=0 } \def\badbrackcount{% \message{Warning: unbalanced square brackets in @def...}% \global\brackcount=0 } \message{macros,} % @macro. % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. \ifx\eTeXversion\thisisundefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1}% \immediate\openout\macscribble=\jobname.tmp \immediate\write\macscribble{\the\toks0}% \immediate\closeout\macscribble \input \jobname.tmp } \fi \def\scanmacro#1{\begingroup \newlinechar`\^^M \let\xeatspaces\eatspaces % % Undo catcode changes of \startcontents and \doprintindex % When called from @insertcopying or (short)caption, we need active % backslash to get it printed correctly. Previously, we had % \catcode`\\=\other instead. We'll see whether a problem appears % with macro expansion. --kasal, 19aug04 \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ % % ... and for \example: \spaceisspace % % The \empty here causes a following catcode 5 newline to be eaten as % part of reading whitespace after a control sequence. It does not % eat a catcode 13 newline. There's no good way to handle the two % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX % would then have different behavior). See the Macro Details node in % the manual for the workaround we recommend for macros and % line-oriented commands. % \scantokens{#1\empty}% \endgroup} \def\scanexp#1{% \edef\temp{\noexpand\scanmacro{#1}}% \temp } \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? % List of all defined macros in the form % \definedummyword\macro1\definedummyword\macro2... % Currently is also contains all @aliases; the list can be split % if there is a need. \def\macrolist{} % Add the macro to \macrolist \def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} \def\addtomacrolistxxx#1{% \toks0 = \expandafter{\macrolist\definedummyword#1}% \xdef\macrolist{\the\toks0}% } % Utility routines. % This does \let #1 = #2, with \csnames; that is, % \let \csname#1\endcsname = \csname#2\endcsname % (except of course we have to play expansion games). % \def\cslet#1#2{% \expandafter\let \csname#1\expandafter\endcsname \csname#2\endcsname } % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). {\catcode`\@=11 \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} \def\unbrace#1{#1} \unbrace{\gdef\trim@@@ #1 } #2@{#1} } % Trim a single trailing ^^M off a string. {\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% } % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active % (as in normal texinfo). It is necessary to change the definition of \ % to recognize macro arguments; this is the job of \mbodybackslash. % % Non-ASCII encodings make 8-bit characters active, so un-activate % them to avoid their expansion. Must do this non-globally, to % confine the change to the current group. % % It's necessary to have hard CRs when the macro is executed. This is % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. % \def\scanctxt{% used as subroutine \catcode`\"=\other \catcode`\+=\other \catcode`\<=\other \catcode`\>=\other \catcode`\@=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi } \def\scanargctxt{% used for copying and captions, not macros. \scanctxt \catcode`\\=\other \catcode`\^^M=\other } \def\macrobodyctxt{% used for @macro definitions \scanctxt \catcode`\{=\other \catcode`\}=\other \catcode`\^^M=\other \usembodybackslash } \def\macroargctxt{% used when scanning invocations \scanctxt \catcode`\\=0 } % why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes" % for the single characters \ { }. Thus, we end up with the "commands" % that would be written @\ @{ @} in a Texinfo document. % % We already have @{ and @}. For @\, we define it here, and only for % this purpose, to produce a typewriter backslash (so, the @\ that we % define for @math can't be used with @macro calls): % \def\\{\normalbackslash}% % % We would like to do this for \, too, since that is what makeinfo does. % But it is not possible, because Texinfo already has a command @, for a % cedilla accent. Documents must use @comma{} instead. % % \anythingelse will almost certainly be an error of some kind. % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. % {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} \def\margbackslash#1{\char`\#1 } \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments \paramno=0\relax \else \expandafter\parsemargdef \argl;% \if\paramno>256\relax \ifx\eTeXversion\thisisundefined \errhelp = \EMsimple \errmessage{You need eTeX to compile a file with macros with more than 256 arguments} \fi \fi \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% \else \expandafter\ifx\csname \the\macname\endcsname \relax \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% \addtomacrolist{\the\macname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} \parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax \let\definedummyword\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else \errmessage{Macro #1 not defined}% \fi } % Called by \do from \dounmacro on each macro. The idea is to omit any % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% \ifx #1\relax % remove this \else \noexpand\definedummyword \noexpand#1% \fi } % This makes use of the obscure feature that if the last token of a % is #, then the preceding argument is delimited by % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname#1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} % For macro processing make @ a letter so that we can make Texinfo private macro names. \edef\texiatcatcode{\the\catcode`\@} \catcode `@=11\relax % Parse the optional {params} list. Set up \paramno and \paramlist % so \defmacro knows what to do. Define \macarg.BLAH for each BLAH % in the params list to some hook where the argument si to be expanded. If % there are less than 10 arguments that hook is to be replaced by ##N where N % is the position in that list, that is to say the macro arguments are to be % defined `a la TeX in the macro body. % % That gets used by \mbodybackslash (above). % % We need to get `macro parameter char #' into several definitions. % The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. % % If there are 10 or more arguments, a different technique is used, where the % hook remains in the body, and when macro is to be expanded the body is % processed again to replace the arguments. % % In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the % argument N value and then \edef the body (nothing else will expand because of % the catcode regime underwhich the body was input). % % If you compile with TeX (not eTeX), and you have macros with 10 or more % arguments, you need that no macro has more than 256 arguments, otherwise an % error is produced. \def\parsemargdef#1;{% \paramno=0\def\paramlist{}% \let\hash\relax \let\xeatspaces\relax \parsemargdefxxx#1,;,% % In case that there are 10 or more arguments we parse again the arguments % list to set new definitions for the \macarg.BLAH macros corresponding to % each BLAH argument. It was anyhow needed to parse already once this list % in order to count the arguments, and as macros with at most 9 arguments % are by far more frequent than macro with 10 or more arguments, defining % twice the \macarg.BLAH macros does not cost too much processing power. \ifnum\paramno<10\relax\else \paramno0\relax \parsemmanyargdef@@#1,;,% 10 or more arguments \fi } \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx \advance\paramno by 1 \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} \def\parsemmanyargdef@@#1,{% \if#1;\let\next=\relax \else \let\next=\parsemmanyargdef@@ \edef\tempb{\eatspaces{#1}}% \expandafter\def\expandafter\tempa \expandafter{\csname macarg.\tempb\endcsname}% % Note that we need some extra \noexpand\noexpand, this is because we % don't want \the to be expanded in the \parsermacbody as it uses an % \xdef . \expandafter\edef\tempa {\noexpand\noexpand\noexpand\the\toks\the\paramno}% \advance\paramno by 1\relax \fi\next} % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) % \catcode `\@\texiatcatcode \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \catcode `\@=11\relax \let\endargs@\relax \let\nil@\relax \def\nilm@{\nil@}% \long\def\nillm@{\nil@}% % This macro is expanded during the Texinfo macro expansion, not during its % definition. It gets all the arguments values and assigns them to macros % macarg.ARGNAME % % #1 is the macro name % #2 is the list of argument names % #3 is the list of argument values \def\getargvals@#1#2#3{% \def\macargdeflist@{}% \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion. \def\paramlist{#2,\nil@}% \def\macroname{#1}% \begingroup \macroargctxt \def\argvaluelist{#3,\nil@}% \def\@tempa{#3}% \ifx\@tempa\empty \setemptyargvalues@ \else \getargvals@@ \fi } % \def\getargvals@@{% \ifx\paramlist\nilm@ % Some sanity check needed here that \argvaluelist is also empty. \ifx\argvaluelist\nillm@ \else \errhelp = \EMsimple \errmessage{Too many arguments in macro `\macroname'!}% \fi \let\next\macargexpandinbody@ \else \ifx\argvaluelist\nillm@ % No more arguments values passed to macro. Set remaining named-arg % macros to empty. \let\next\setemptyargvalues@ \else % pop current arg name into \@tempb \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}% \expandafter\@tempa\expandafter{\paramlist}% % pop current argument value into \@tempc \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}% \expandafter\@tempa\expandafter{\argvaluelist}% % Here \@tempb is the current arg name and \@tempc is the current arg value. % First place the new argument macro definition into \@tempd \expandafter\macname\expandafter{\@tempc}% \expandafter\let\csname macarg.\@tempb\endcsname\relax \expandafter\def\expandafter\@tempe\expandafter{% \csname macarg.\@tempb\endcsname}% \edef\@tempd{\long\def\@tempe{\the\macname}}% \push@\@tempd\macargdeflist@ \let\next\getargvals@@ \fi \fi \next } \def\push@#1#2{% \expandafter\expandafter\expandafter\def \expandafter\expandafter\expandafter#2% \expandafter\expandafter\expandafter{% \expandafter#1#2}% } % Replace arguments by their values in the macro body, and place the result % in macro \@tempa \def\macvalstoargs@{% % To do this we use the property that token registers that are \the'ed % within an \edef expand only once. So we are going to place all argument % values into respective token registers. % % First we save the token context, and initialize argument numbering. \begingroup \paramno0\relax % Then, for each argument number #N, we place the corresponding argument % value into a new token list register \toks#N \expandafter\putargsintokens@\saveparamlist@,;,% % Then, we expand the body so that argument are replaced by their % values. The trick for values not to be expanded themselves is that they % are within tokens and that tokens expand only once in an \edef . \edef\@tempc{\csname mac.\macroname .body\endcsname}% % Now we restore the token stack pointer to free the token list registers % which we have used, but we make sure that expanded body is saved after % group. \expandafter \endgroup \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% } \def\macargexpandinbody@{% %% Define the named-macro outside of this group and then close this group. \expandafter \endgroup \macargdeflist@ % First the replace in body the macro arguments by their values, the result % is in \@tempa . \macvalstoargs@ % Then we point at the \norecurse or \gobble (for recursive) macro value % with \@tempb . \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname % Depending on whether it is recursive or not, we need some tailing % \egroup . \ifx\@tempb\gobble \let\@tempc\relax \else \let\@tempc\egroup \fi % And now we do the real job: \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}% \@tempd } \def\putargsintokens@#1,{% \if#1;\let\next\relax \else \let\next\putargsintokens@ % First we allocate the new token list register, and give it a temporary % alias \@tempb . \toksdef\@tempb\the\paramno % Then we place the argument value into that token list register. \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname \expandafter\@tempb\expandafter{\@tempa}% \advance\paramno by 1\relax \fi \next } % Save the token stack pointer into macro #1 \def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}} % Restore the token stack pointer from number in macro #1 \def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax} % newtoks that can be used non \outer . \def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi} % Tailing missing arguments are set to empty \def\setemptyargvalues@{% \ifx\paramlist\nilm@ \let\next\macargexpandinbody@ \else \expandafter\setemptyargvaluesparser@\paramlist\endargs@ \let\next\setemptyargvalues@ \fi \next } \def\setemptyargvaluesparser@#1,#2\endargs@{% \expandafter\def\expandafter\@tempa\expandafter{% \expandafter\def\csname macarg.#1\endcsname{}}% \push@\@tempa\macargdeflist@ \def\paramlist{#2}% } % #1 is the element target macro % #2 is the list macro % #3,#4\endargs@ is the list value \def\pop@#1#2#3,#4\endargs@{% \def#1{#3}% \def#2{#4}% } \long\def\longpop@#1#2#3,#4\endargs@{% \long\def#1{#3}% \long\def#2{#4}% } % This defines a Texinfo @macro. There are eight cases: recursive and % nonrecursive macros of zero, one, up to nine, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. % \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\scanmacro{\temp}}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% \else \ifnum\paramno<10\relax % at most 9 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{\egroup\noexpand\scanmacro{\temp}}% \else % 10 or more \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\getargvals@{\the\macname}{\argl}% }% \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble \fi \fi \else \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % at most 9 \ifnum\paramno<10\relax \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \expandafter\noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % 10 or more: \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\getargvals@{\the\macname}{\argl}% }% \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse \fi \fi \fi} \catcode `\@\texiatcatcode\relax \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence % as an argument (by \parsebrace or \parsearg). % \def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg \fi \macnamexxx} % @alias. % We need some trickery to remove the optional spaces around the equal % sign. Make them active and then expand them all to nothing. % \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty \addtomacrolist{#1}% \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next } \message{cross references,} \newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} \def\inforefzzz #1,#2,#3,#4**{% \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in % cross-references. The @node line might or might not have commas, and % might or might not have spaces before the first comma, like: % @node foo , bar , ... % We don't want such trailing spaces in the node name. % \parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} % % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} \let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the % type (Ynumbered, Yappendix, Ynothing). % \def\donoderef#1{% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty \fi } % @anchor{NAME} -- define xref target at arbitrary point. % \newcount\savesfregister % \def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} \def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} \def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: % 1) NAME-title - the current sectioning name taken from \lastsection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. % 3) NAME-pg - the page number. % % This is called from \donoderef, \anchor, and \dofloat. In the case of % floats, there is an additional part, which is not written here: % 4) NAME-lof - the text as it should appear in a @listoffloats. % \def\setref#1#2{% \pdfmkdest{#1}% \iflinks {% \atdummies % preserve commands, but don't expand them \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = \expandafter{\lastsection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout }% \fi } % @xrefautosectiontitle on|off says whether @section(ing) names are used % automatically in xrefs, if the third arg is not explicitly specified. % This was provided as a "secret" @set xref-automatic-section-title % variable, now it's official. % \parseargdef\xrefautomaticsectiontitle{% \def\temp{#1}% \ifx\temp\onword \expandafter\let\csname SETxref-automatic-section-title\endcsname = \empty \else\ifx\temp\offword \expandafter\let\csname SETxref-automatic-section-title\endcsname = \relax \else \errhelp = \EMsimple \errmessage{Unknown @xrefautomaticsectiontitle value `\temp', must be on|off}% \fi\fi } % % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} % \newbox\toprefbox \newbox\printedrefnamebox \newbox\infofilenamebox \newbox\printedmanualbox % \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces % % Get args without leading/trailing spaces. \def\printedrefname{\ignorespaces #3}% \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% % \def\infofilename{\ignorespaces #4}% \setbox\infofilenamebox = \hbox{\infofilename\unskip}% % \def\printedmanual{\ignorespaces #5}% \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% % % If the printed reference name (arg #3) was not explicitly given in % the @xref, figure out what we want to use. \ifdim \wd\printedrefnamebox = 0pt % No printed node name was explicitly given. \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax % Not auto section-title: use node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else % Auto section-title: use chapter/section title inside % the square brackets if we have it. \ifdim \wd\printedmanualbox > 0pt % It is in another manual, so we don't have it; use node name. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We (should) know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % % Make link in pdf output. \ifpdf {\indexnofonts \turnoffactive \makevalueexpandable % This expands tokens, so do it after making catcode changes, so _ % etc. don't get their TeX definitions. This ignores all spaces in % #4, including (wrongly) those in the middle of the filename. \getfilename{#4}% % % This (wrongly) does not take account of leading or trailing % spaces in #1, which should be ignored. \edef\pdfxrefdest{#1}% \ifx\pdfxrefdest\empty \def\pdfxrefdest{Top}% no empty targets \else \txiescapepdf\pdfxrefdest % escape PDF special chars \fi % \leavevmode \startlink attr{/Border [0 0 0]}% \ifnum\filenamelength>0 goto file{\the\filename.pdf} name{\pdfxrefdest}% \else goto name{\pdfmkpgn{\pdfxrefdest}}% \fi }% \setcolor{\linkcolor}% \fi % % Float references are printed completely differently: "Figure 1.2" % instead of "[somenode], p.3". We distinguish them by the % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". \ifdim\wd\printedrefnamebox = 0pt \refx{#1-snt}{}% \else \printedrefname \fi % % If the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". \ifdim \wd\printedmanualbox > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. % % If we use \unhbox to print the node names, TeX does not insert % empty discretionaries after hyphens, which means that it will not % find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, % this is a loss. Therefore, we give the text of the node name % again, so it is as if TeX is seeing it for the first time. % \ifdim \wd\printedmanualbox > 0pt % Cross-manual reference with a printed manual name. % \crossmanualxref{\cite{\printedmanual\unskip}}% % \else\ifdim \wd\infofilenamebox > 0pt % Cross-manual reference with only an info filename (arg 4), no % printed manual name (arg 5). This is essentially the same as % the case above; we output the filename, since we have nothing else. % \crossmanualxref{\code{\infofilename\unskip}}% % \else % Reference within this manual. % % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. {\turnoffactive % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% % output the `[mynode]' via the macro below so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. \turnoffactive \putwordpage\tie\refx{#1-pg}{}% \fi\fi \fi \endlink \endgroup} % Output a cross-manual xref to #1. Used just above (twice). % % Only include the text "Section ``foo'' in" if the foo is neither % missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply % "see The Foo Manual", the idea being to refer to the whole manual. % % But, this being TeX, we can't easily compare our node name against the % string "Top" while ignoring the possible spaces before and after in % the input. By adding the arbitrary 7sp below, we make it much less % likely that a real node name would have the same width as "Top" (e.g., % in a monospaced font). Hopefully it will never happen in practice. % % For the same basic reason, we retypeset the "Top" at every % reference, since the current font is indeterminate. % \def\crossmanualxref#1{% \setbox\toprefbox = \hbox{Top\kern7sp}% \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% \ifdim \wd2 > 7sp % nonempty? \ifdim \wd2 = \wd\toprefbox \else % same as Top? \putwordSection{} ``\printedrefname'' \putwordin{}\space \fi \fi #1% } % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly % one that Bob is working on :). % \def\xrefprintnodename#1{[#1]} % Things referred to by \setref. % \def\Ynothing{} \def\Yomitfromtoc{} \def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 \putwordSection@tie \the\chapno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie \the\chapno.\the\secno.\the\subsecno \else \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } \def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno \else \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. % If its value is nonempty, SUFFIX is output afterward. % \def\refx#1#2{% {% \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs {\toks0 = {#1}% avoid expansion of possibly-complex value \message{\linenumber Undefined cross reference `\the\toks0'.}}% \else \ifwarnedxrefs\else \global\warnedxrefstrue \message{Cross reference values unknown; you must run TeX again.}% \fi \fi \fi \else % It's defined, so just use it. \thisrefX \fi #2% Output the suffix in any case. } % This is the macro invoked by entries in the aux file. Usually it's % just a \def (we prepend XR to the control sequence name to avoid % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% {% The node name might contain 8-bit characters, which in our current % implementation are changed to commands like @'e. Don't let these % mess up the control sequence name. \indexnofonts \turnoffactive \xdef\safexrefname{#1}% }% % \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR\safexrefname\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname % % Is this the first time we've seen this float type? \expandafter\ifx\floatlist\relax \toks0 = {\do}% yes, so just \do \else % had it before, so preserve previous elements in list. \toks0 = \expandafter{\floatlist\do}% \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 {\safexrefname}}% \fi } % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else \readdatafile{aux}% \global\havexrefstrue \fi \closein 1 } \def\setupdatafile{% \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other \catcode`\^^C=\other \catcode`\^^D=\other \catcode`\^^E=\other \catcode`\^^F=\other \catcode`\^^G=\other \catcode`\^^H=\other \catcode`\^^K=\other \catcode`\^^L=\other \catcode`\^^N=\other \catcode`\^^P=\other \catcode`\^^Q=\other \catcode`\^^R=\other \catcode`\^^S=\other \catcode`\^^T=\other \catcode`\^^U=\other \catcode`\^^V=\other \catcode`\^^W=\other \catcode`\^^X=\other \catcode`\^^Z=\other \catcode`\^^[=\other \catcode`\^^\=\other \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. % in xref tags, i.e., node names. But since ^^e4 notation isn't % supported in the main text, it doesn't seem desirable. Furthermore, % that is not enough: for node names that actually contain a ^ % character, we would end up writing a line like this: 'xrdef {'hat % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first % argument, and \hat is not an expandable control sequence. It could % all be worked out, but why? Either we support ^^ or we don't. % % The other change necessary for this was to define \auxhat: % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter % and then to call \auxhat in \setq. % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other \catcode`\"=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % % This is to support \ in node names and titles, since the \ % characters end up in a \csname. It's easier than % leaving it active and making its active definition an actual \ % character. What I don't understand is why it works in the *value* % of the xrdef. Seems like it should be a catcode12 \, and that % should not typeset properly. But it works, so I'm moving on for % now. --karl, 15jan04. \catcode`\\=\other % % Make the characters 128-255 be printing characters. {% \count1=128 \def\loop{% \catcode\count1=\other \advance\count1 by 1 \ifnum \count1<256 \loop \fi }% }% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 } \def\readdatafile#1{% \begingroup \setupdatafile \input\jobname.#1 \endgroup} \message{insertions,} % including footnotes. \newcount \footnoteno % The trailing space in the following definition for supereject is % vital for proper filling; pages come out unaligned when you do a % pagealignmacro call if that space before the closing brace is % removed. (Generally, numeric constants should always be followed by a % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } % @footnotestyle is meaningful for Info output only. \let\footnotestyle=\comment {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% \let\indent=\ptexindent \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % % Oh yes, they do; otherwise, @ifset (and anything else that uses % \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % \gdef\dofootnote{% \insert\footins\bgroup % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. \hsize=\pagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox \floatingpenalty\@MM \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip \parindent\defaultparindent % \smallfonts \rm % % Because we use hanging indentation in footnotes, a @noindent appears % to exdent this text, so make it be a no-op. makeinfo does not use % hanging indentation so @noindent can still be needed within footnote % text after an @example or the like (not that this is good style). \let\noindent = \relax % % Hang the footnote text off the number. Use \everypar in case the % footnote extends for more than one paragraph. \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut % % Invoke rest of plain TeX footnote routine. \futurelet\next\fo@t } }%end \catcode `\@=11 % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarly, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. % \def\startsavinginserts{% \ifx \insert\ptexinsert \let\insert\saveinsert \else \let\checkinserts\relax \fi } % This \insert replacement works for both \insert\footins{foo} and % \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % \def\saveinsert#1{% \edef\next{\noexpand\savetobox \makeSAVEname#1}% \afterassignment\next % swallow the left brace \let\temp = } \def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} \def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} \def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} \def\placesaveins#1{% \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname {\box#1}% } % eat @SAVE -- beware, all of them have catcode \other: { \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) \gdef\gobblesave @SAVE{} } % initialization: \def\newsaveins #1{% \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% \next } \def\newsaveinsX #1{% \csname newbox\endcsname #1% \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts \checksaveins #1}% } % initialize: \let\checkinserts\empty \newsaveins\footins \newsaveins\margin % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. % % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else % Do not bother showing banner with epsf.tex v2.7k (available in % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi \closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% \ifx\epsfbox\thisisundefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. % #6 is just the usual extra ignored arg for parsing stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names % If the image is by itself, center it. \ifvmode \imagevmodetrue \else \ifx\centersub\centerV % for @center @image, we need a vbox so we can have our vertical space \imagevmodetrue \vbox\bgroup % vbox has better behavior than vtop herev \fi\fi % \ifimagevmode \nobreak\medskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak \fi % % Leave vertical mode so that indentation from an enclosing % environment such as @quotation is respected. % However, if we're at the top level, we don't want the % normal paragraph indentation. % On the other hand, if we are in the case of @center @image, we don't % want to start a paragraph, which will create a hsize-width box and % eradicate the centering. \ifx\centersub\centerV\else \noindent \fi % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% \else % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% \fi % \ifimagevmode \medskip % space after a standalone image \fi \ifx\centersub\centerV \egroup \fi \endgroup} % @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, % etc. We don't actually implement floating yet, we always include the % float "here". But it seemed the best name for the future. % \envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} % There may be a space before second and/or third parameter; delete it. \def\eatcommaspace#1, {#1,} % #1 is the optional FLOATTYPE, the text label for this float, typically % "Figure", "Table", "Example", etc. Can't contain commas. If omitted, % this float will not be numbered and cannot be referred to. % % #2 is the optional xref label. Also must be present for the float to % be referable. % % #3 is the optional positioning argument; for now, it is ignored. It % will somehow specify the positions allowed to float to (here, top, bottom). % % We keep a separate counter for each FLOATTYPE, which we reset at each % chapter-level command. \let\resetallfloatnos=\empty % \def\dofloat#1,#2,#3,#4\finish{% \let\thiscaption=\empty \let\thisshortcaption=\empty % % don't lose footnotes inside @float. % % BEWARE: when the floats start float, we have to issue warning whenever an % insert appears inside a float which could possibly float. --kasal, 26may04 % \startsavinginserts % % We can't be used inside a paragraph. \par % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% \def\floatloc{#3}% we do nothing with this yet. % \ifx\floattype\empty \let\safefloattype=\empty \else {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% \fi % % If label is given but no type, we handle that as the empty type. \ifx\floatlabel\empty \else % We want each FLOATTYPE to be numbered separately (Figure 1, % Table 1, Figure 2, ...). (And if no label, no number.) % \expandafter\getfloatno\csname\safefloattype floatno\endcsname \global\advance\floatno by 1 % {% % This magic value for \lastsection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % \edef\lastsection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi % % start with \parskip glue, I guess. \vskip\parskip % % Don't suppress indentation if a float happens to start a section. \restorefirstparagraphindent } % we have these possibilities: % @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap % @float Foo,lbl & no caption: Foo 1.1 % @float Foo & @caption{Cap}: Foo: Cap % @float Foo & no caption: Foo % @float ,lbl & Caption{Cap}: 1.1: Cap % @float ,lbl & no caption: 1.1 % @float & @caption{Cap}: Cap % @float & no caption: % \def\Efloat{% \let\floatident = \empty % % In all cases, if we have a float type, it comes first. \ifx\floattype\empty \else \def\floatident{\floattype}\fi % % If we have an xref label, the number comes next. \ifx\floatlabel\empty \else \ifx\floattype\empty \else % if also had float type, need tie first. \appendtomacro\floatident{\tie}% \fi % the number. \appendtomacro\floatident{\chaplevelprefix\the\floatno}% \fi % % Start the printed caption with what we've constructed in % \floatident, but keep it separate; we need \floatident again. \let\captionline = \floatident % \ifx\thiscaption\empty \else \ifx\floatident\empty \else \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. \appendtomacro\captionline{\scanexp\thiscaption}% \fi % % If we have anything to print, print it, with space before. % Eventually this needs to become an \insert. \ifx\captionline\empty \else \vskip.5\parskip \captionline % % Space below caption. \vskip\parskip \fi % % If have an xref label, write the list of floats info. Do this % after the caption, to avoid chance of it being a breakpoint. \ifx\floatlabel\empty \else % Write the text that goes in the lof to the aux file as % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% \atdummies % % since we read the caption text in the macro world, where ^^M % is turned into a normal character, we have to scan it back, so % we don't write the literal three characters "^^M" into the aux file. \scanexp{% \xdef\noexpand\gtemp{% \ifx\thisshortcaption\empty \thiscaption \else \thisshortcaption \fi }% }% \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident \ifx\gtemp\empty \else : \gtemp \fi}}% }% \fi \egroup % end of \vtop % % place the captured inserts % % BEWARE: when the floats start floating, we have to issue warning % whenever an insert appears inside a float which could possibly % float. --kasal, 26may04 % \checkinserts } % Append the tokens #2 to the definition of macro #1, not expanding either. % \def\appendtomacro#1#2{% \expandafter\def\expandafter#1\expandafter{#1#2}% } % @caption, @shortcaption % \def\caption{\docaption\thiscaption} \def\shortcaption{\docaption\thisshortcaption} \def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} \def\defcaption#1#2{\egroup \def#1{#2}} % The parameter is the control sequence identifying the counter we are % going to use. Create it if it doesn't exist and assign it to \floatno. \def\getfloatno#1{% \ifx#1\relax % Haven't seen this figure type before. \csname newcount\endcsname #1% % % Remember to reset this floatno at the next chap. \expandafter\gdef\expandafter\resetallfloatnos \expandafter{\resetallfloatnos #1=0 }% \fi \let\floatno#1% } % \setref calls this to get the XREFLABEL-snt value. We want an @xref % to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we % first read the @float command. % \def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% % Magic string used for the XREFLABEL-title value, so \xrefX can % distinguish floats from other xref types. \def\floatmagic{!!float!!} % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic % \lastsection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % % #1 is (maybe) the \floatmagic string. If so, #2 will be the % (safe) float type for this float. We set \iffloattype to #2. % \def\doiffloat#1=#2=#3\finish{% \def\temp{#1}% \def\iffloattype{#2}% \ifx\temp\floatmagic } % @listoffloats FLOATTYPE - print a list of floats like a table of contents. % \parseargdef\listoffloats{% \def\floattype{#1}% floattype {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% % % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax \ifhavexrefs % if the user said @listoffloats foo but never @float foo. \message{\linenumber No `\safefloattype' floats to list.}% \fi \else \begingroup \leftskip=\tocindent % indent these entries like a toc \let\do=\listoffloatsdo \csname floatlist\safefloattype\endcsname \endgroup \fi } % This is called on each entry in a list of floats. We're passed the % xref label, in the form LABEL-title, which is how we save it in the % aux file. We strip off the -title and look up \XRLABEL-lof, which % has the text we're supposed to typeset here. % % Figures without xref labels will not be included in the list (since % they won't appear in the aux file). % \def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} \def\listoffloatsdoentry#1-title\finish{{% % Can't fully expand XR#1-lof because it can contain anything. Just % pass the control sequence. On the other hand, XR#1-pg is just the % page number, and we want to fully expand that so we can get a link % in pdf output. \toksA = \expandafter{\csname XR#1-lof\endcsname}% % % use the same \entry macro we use to generate the TOC and index. \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% \writeentry }} \message{localization,} % For single-language documents, @documentlanguage is usually given very % early, just after @documentencoding. Single argument is the language % (de) or locale (de_DE) abbreviation. % { \catcode`\_ = \active \globaldefs=1 \parseargdef\documentlanguage{\begingroup \let_=\normalunderscore % normal _ character for filenames \tex % read txi-??.tex file in plain TeX. % Read the file by the name they passed if it exists. \openin 1 txi-#1.tex \ifeof 1 \documentlanguagetrywithoutunderscore{#1_\finish}% \else \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex \fi \closein 1 \endgroup % end raw TeX \endgroup} % % If they passed de_DE, and txi-de_DE.tex doesn't exist, % try txi-de.tex. % \gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% \openin 1 txi-#1.tex \ifeof 1 \errhelp = \nolanghelp \errmessage{Cannot read language file txi-#1.tex}% \else \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex \fi \closein 1 } }% end of special _ catcode % \newhelp\nolanghelp{The given language definition file cannot be found or is empty. Maybe you need to install it? Putting it in the current directory should work if nowhere else does.} % This macro is called from txi-??.tex files; the first argument is the % \language name to set (without the "\lang@" prefix), the second and % third args are \{left,right}hyphenmin. % % The language names to pass are determined when the format is built. % See the etex.log file created at that time, e.g., % /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. % % With TeX Live 2008, etex now includes hyphenation patterns for all % available languages. This means we can support hyphenation in % Texinfo, at least to some extent. (This still doesn't solve the % accented characters problem.) % \catcode`@=11 \def\txisetlanguage#1#2#3{% % do not set the language if the name is undefined in the current TeX. \expandafter\ifx\csname lang@#1\endcsname \relax \message{no patterns for #1}% \else \global\language = \csname lang@#1\endcsname \fi % but there is no harm in adjusting the hyphenmin values regardless. \global\lefthyphenmin = #2\relax \global\righthyphenmin = #3\relax } % Helpers for encodings. % Set the catcode of characters 128 through 255 to the specified number. % \def\setnonasciicharscatcode#1{% \count255=128 \loop\ifnum\count255<256 \global\catcode\count255=#1\relax \advance\count255 by 1 \repeat } \def\setnonasciicharscatcodenonglobal#1{% \count255=128 \loop\ifnum\count255<256 \catcode\count255=#1\relax \advance\count255 by 1 \repeat } % @documentencoding sets the definition of non-ASCII characters % according to the specified encoding. % \parseargdef\documentencoding{% % Encoding being declared for the document. \def\declaredencoding{\csname #1.enc\endcsname}% % % Supported encodings: names converted to tokens in order to be able % to compare them with \ifx. \def\ascii{\csname US-ASCII.enc\endcsname}% \def\latnine{\csname ISO-8859-15.enc\endcsname}% \def\latone{\csname ISO-8859-1.enc\endcsname}% \def\lattwo{\csname ISO-8859-2.enc\endcsname}% \def\utfeight{\csname UTF-8.enc\endcsname}% % \ifx \declaredencoding \ascii \asciichardefs % \else \ifx \declaredencoding \lattwo \setnonasciicharscatcode\active \lattwochardefs % \else \ifx \declaredencoding \latone \setnonasciicharscatcode\active \latonechardefs % \else \ifx \declaredencoding \latnine \setnonasciicharscatcode\active \latninechardefs % \else \ifx \declaredencoding \utfeight \setnonasciicharscatcode\active \utfeightchardefs % \else \message{Unknown document encoding #1, ignoring.}% % \fi % utfeight \fi % latnine \fi % latone \fi % lattwo \fi % ascii } % A message to be logged when using a character that isn't available % the default font encoding (OT1). % \def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} % Take account of \c (plain) vs. \, (Texinfo) difference. \def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} % First, make active non-ASCII characters in order for them to be % correctly categorized when TeX reads the replacement text of % macros containing the character definitions. \setnonasciicharscatcode\active % % Latin1 (ISO-8859-1) character definitions. \def\latonechardefs{% \gdef^^a0{\tie} \gdef^^a1{\exclamdown} \gdef^^a2{\missingcharmsg{CENT SIGN}} \gdef^^a3{{\pounds}} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\missingcharmsg{YEN SIGN}} \gdef^^a6{\missingcharmsg{BROKEN BAR}} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\copyright} \gdef^^aa{\ordf} \gdef^^ab{\guillemetleft} \gdef^^ac{$\lnot$} \gdef^^ad{\-} \gdef^^ae{\registeredsymbol} \gdef^^af{\={}} % \gdef^^b0{\textdegree} \gdef^^b1{$\pm$} \gdef^^b2{$^2$} \gdef^^b3{$^3$} \gdef^^b4{\'{}} \gdef^^b5{$\mu$} \gdef^^b6{\P} % \gdef^^b7{$^.$} \gdef^^b8{\cedilla\ } \gdef^^b9{$^1$} \gdef^^ba{\ordm} % \gdef^^bb{\guillemetright} \gdef^^bc{$1\over4$} \gdef^^bd{$1\over2$} \gdef^^be{$3\over4$} \gdef^^bf{\questiondown} % \gdef^^c0{\`A} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\~A} \gdef^^c4{\"A} \gdef^^c5{\ringaccent A} \gdef^^c6{\AE} \gdef^^c7{\cedilla C} \gdef^^c8{\`E} \gdef^^c9{\'E} \gdef^^ca{\^E} \gdef^^cb{\"E} \gdef^^cc{\`I} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\"I} % \gdef^^d0{\DH} \gdef^^d1{\~N} \gdef^^d2{\`O} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\~O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\O} \gdef^^d9{\`U} \gdef^^da{\'U} \gdef^^db{\^U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\TH} \gdef^^df{\ss} % \gdef^^e0{\`a} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\~a} \gdef^^e4{\"a} \gdef^^e5{\ringaccent a} \gdef^^e6{\ae} \gdef^^e7{\cedilla c} \gdef^^e8{\`e} \gdef^^e9{\'e} \gdef^^ea{\^e} \gdef^^eb{\"e} \gdef^^ec{\`{\dotless i}} \gdef^^ed{\'{\dotless i}} \gdef^^ee{\^{\dotless i}} \gdef^^ef{\"{\dotless i}} % \gdef^^f0{\dh} \gdef^^f1{\~n} \gdef^^f2{\`o} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\~o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\o} \gdef^^f9{\`u} \gdef^^fa{\'u} \gdef^^fb{\^u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\th} \gdef^^ff{\"y} } % Latin9 (ISO-8859-15) encoding character definitions. \def\latninechardefs{% % Encoding is almost identical to Latin1. \latonechardefs % \gdef^^a4{\euro} \gdef^^a6{\v S} \gdef^^a8{\v s} \gdef^^b4{\v Z} \gdef^^b8{\v z} \gdef^^bc{\OE} \gdef^^bd{\oe} \gdef^^be{\"Y} } % Latin2 (ISO-8859-2) character definitions. \def\lattwochardefs{% \gdef^^a0{\tie} \gdef^^a1{\ogonek{A}} \gdef^^a2{\u{}} \gdef^^a3{\L} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\v L} \gdef^^a6{\'S} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\v S} \gdef^^aa{\cedilla S} \gdef^^ab{\v T} \gdef^^ac{\'Z} \gdef^^ad{\-} \gdef^^ae{\v Z} \gdef^^af{\dotaccent Z} % \gdef^^b0{\textdegree} \gdef^^b1{\ogonek{a}} \gdef^^b2{\ogonek{ }} \gdef^^b3{\l} \gdef^^b4{\'{}} \gdef^^b5{\v l} \gdef^^b6{\'s} \gdef^^b7{\v{}} \gdef^^b8{\cedilla\ } \gdef^^b9{\v s} \gdef^^ba{\cedilla s} \gdef^^bb{\v t} \gdef^^bc{\'z} \gdef^^bd{\H{}} \gdef^^be{\v z} \gdef^^bf{\dotaccent z} % \gdef^^c0{\'R} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\u A} \gdef^^c4{\"A} \gdef^^c5{\'L} \gdef^^c6{\'C} \gdef^^c7{\cedilla C} \gdef^^c8{\v C} \gdef^^c9{\'E} \gdef^^ca{\ogonek{E}} \gdef^^cb{\"E} \gdef^^cc{\v E} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\v D} % \gdef^^d0{\DH} \gdef^^d1{\'N} \gdef^^d2{\v N} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\H O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\v R} \gdef^^d9{\ringaccent U} \gdef^^da{\'U} \gdef^^db{\H U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\cedilla T} \gdef^^df{\ss} % \gdef^^e0{\'r} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\u a} \gdef^^e4{\"a} \gdef^^e5{\'l} \gdef^^e6{\'c} \gdef^^e7{\cedilla c} \gdef^^e8{\v c} \gdef^^e9{\'e} \gdef^^ea{\ogonek{e}} \gdef^^eb{\"e} \gdef^^ec{\v e} \gdef^^ed{\'{\dotless{i}}} \gdef^^ee{\^{\dotless{i}}} \gdef^^ef{\v d} % \gdef^^f0{\dh} \gdef^^f1{\'n} \gdef^^f2{\v n} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\H o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\v r} \gdef^^f9{\ringaccent u} \gdef^^fa{\'u} \gdef^^fb{\H u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\cedilla t} \gdef^^ff{\dotaccent{}} } % UTF-8 character definitions. % % This code to support UTF-8 is based on LaTeX's utf8.def, with some % changes for Texinfo conventions. It is included here under the GPL by % permission from Frank Mittelbach and the LaTeX team. % \newcount\countUTFx \newcount\countUTFy \newcount\countUTFz \gdef\UTFviiiTwoOctets#1#2{\expandafter \UTFviiiDefined\csname u8:#1\string #2\endcsname} % \gdef\UTFviiiThreeOctets#1#2#3{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} % \gdef\UTFviiiFourOctets#1#2#3#4{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} \gdef\UTFviiiDefined#1{% \ifx #1\relax \message{\linenumber Unicode char \string #1 not defined for Texinfo}% \else \expandafter #1% \fi } \begingroup \catcode`\~13 \catcode`\"12 \def\UTFviiiLoop{% \global\catcode\countUTFx\active \uccode`\~\countUTFx \uppercase\expandafter{\UTFviiiTmp}% \advance\countUTFx by 1 \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} \countUTFx = "C2 \countUTFy = "E0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiTwoOctets\string~}} \UTFviiiLoop \countUTFx = "E0 \countUTFy = "F0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiThreeOctets\string~}} \UTFviiiLoop \countUTFx = "F0 \countUTFy = "F4 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiFourOctets\string~}} \UTFviiiLoop \endgroup \begingroup \catcode`\"=12 \catcode`\<=12 \catcode`\.=12 \catcode`\,=12 \catcode`\;=12 \catcode`\!=12 \catcode`\~=13 \gdef\DeclareUnicodeCharacter#1#2{% \countUTFz = "#1\relax %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% \begingroup \parseXMLCharref \def\UTFviiiTwoOctets##1##2{% \csname u8:##1\string ##2\endcsname}% \def\UTFviiiThreeOctets##1##2##3{% \csname u8:##1\string ##2\string ##3\endcsname}% \def\UTFviiiFourOctets##1##2##3##4{% \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% \expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter \gdef\UTFviiiTmp{#2}% \endgroup} \gdef\parseXMLCharref{% \ifnum\countUTFz < "A0\relax \errhelp = \EMsimple \errmessage{Cannot define Unicode char value < 00A0}% \else\ifnum\countUTFz < "800\relax \parseUTFviiiA,% \parseUTFviiiB C\UTFviiiTwoOctets.,% \else\ifnum\countUTFz < "10000\relax \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% \else \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiA!% \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% \fi\fi\fi } \gdef\parseUTFviiiA#1{% \countUTFx = \countUTFz \divide\countUTFz by 64 \countUTFy = \countUTFz \multiply\countUTFz by 64 \advance\countUTFx by -\countUTFz \advance\countUTFx by 128 \uccode `#1\countUTFx \countUTFz = \countUTFy} \gdef\parseUTFviiiB#1#2#3#4{% \advance\countUTFz by "#10\relax \uccode `#3\countUTFz \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} \endgroup \def\utfeightchardefs{% \DeclareUnicodeCharacter{00A0}{\tie} \DeclareUnicodeCharacter{00A1}{\exclamdown} \DeclareUnicodeCharacter{00A3}{\pounds} \DeclareUnicodeCharacter{00A8}{\"{ }} \DeclareUnicodeCharacter{00A9}{\copyright} \DeclareUnicodeCharacter{00AA}{\ordf} \DeclareUnicodeCharacter{00AB}{\guillemetleft} \DeclareUnicodeCharacter{00AD}{\-} \DeclareUnicodeCharacter{00AE}{\registeredsymbol} \DeclareUnicodeCharacter{00AF}{\={ }} \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} \DeclareUnicodeCharacter{00B4}{\'{ }} \DeclareUnicodeCharacter{00B8}{\cedilla{ }} \DeclareUnicodeCharacter{00BA}{\ordm} \DeclareUnicodeCharacter{00BB}{\guillemetright} \DeclareUnicodeCharacter{00BF}{\questiondown} \DeclareUnicodeCharacter{00C0}{\`A} \DeclareUnicodeCharacter{00C1}{\'A} \DeclareUnicodeCharacter{00C2}{\^A} \DeclareUnicodeCharacter{00C3}{\~A} \DeclareUnicodeCharacter{00C4}{\"A} \DeclareUnicodeCharacter{00C5}{\AA} \DeclareUnicodeCharacter{00C6}{\AE} \DeclareUnicodeCharacter{00C7}{\cedilla{C}} \DeclareUnicodeCharacter{00C8}{\`E} \DeclareUnicodeCharacter{00C9}{\'E} \DeclareUnicodeCharacter{00CA}{\^E} \DeclareUnicodeCharacter{00CB}{\"E} \DeclareUnicodeCharacter{00CC}{\`I} \DeclareUnicodeCharacter{00CD}{\'I} \DeclareUnicodeCharacter{00CE}{\^I} \DeclareUnicodeCharacter{00CF}{\"I} \DeclareUnicodeCharacter{00D0}{\DH} \DeclareUnicodeCharacter{00D1}{\~N} \DeclareUnicodeCharacter{00D2}{\`O} \DeclareUnicodeCharacter{00D3}{\'O} \DeclareUnicodeCharacter{00D4}{\^O} \DeclareUnicodeCharacter{00D5}{\~O} \DeclareUnicodeCharacter{00D6}{\"O} \DeclareUnicodeCharacter{00D8}{\O} \DeclareUnicodeCharacter{00D9}{\`U} \DeclareUnicodeCharacter{00DA}{\'U} \DeclareUnicodeCharacter{00DB}{\^U} \DeclareUnicodeCharacter{00DC}{\"U} \DeclareUnicodeCharacter{00DD}{\'Y} \DeclareUnicodeCharacter{00DE}{\TH} \DeclareUnicodeCharacter{00DF}{\ss} \DeclareUnicodeCharacter{00E0}{\`a} \DeclareUnicodeCharacter{00E1}{\'a} \DeclareUnicodeCharacter{00E2}{\^a} \DeclareUnicodeCharacter{00E3}{\~a} \DeclareUnicodeCharacter{00E4}{\"a} \DeclareUnicodeCharacter{00E5}{\aa} \DeclareUnicodeCharacter{00E6}{\ae} \DeclareUnicodeCharacter{00E7}{\cedilla{c}} \DeclareUnicodeCharacter{00E8}{\`e} \DeclareUnicodeCharacter{00E9}{\'e} \DeclareUnicodeCharacter{00EA}{\^e} \DeclareUnicodeCharacter{00EB}{\"e} \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} \DeclareUnicodeCharacter{00F0}{\dh} \DeclareUnicodeCharacter{00F1}{\~n} \DeclareUnicodeCharacter{00F2}{\`o} \DeclareUnicodeCharacter{00F3}{\'o} \DeclareUnicodeCharacter{00F4}{\^o} \DeclareUnicodeCharacter{00F5}{\~o} \DeclareUnicodeCharacter{00F6}{\"o} \DeclareUnicodeCharacter{00F8}{\o} \DeclareUnicodeCharacter{00F9}{\`u} \DeclareUnicodeCharacter{00FA}{\'u} \DeclareUnicodeCharacter{00FB}{\^u} \DeclareUnicodeCharacter{00FC}{\"u} \DeclareUnicodeCharacter{00FD}{\'y} \DeclareUnicodeCharacter{00FE}{\th} \DeclareUnicodeCharacter{00FF}{\"y} \DeclareUnicodeCharacter{0100}{\=A} \DeclareUnicodeCharacter{0101}{\=a} \DeclareUnicodeCharacter{0102}{\u{A}} \DeclareUnicodeCharacter{0103}{\u{a}} \DeclareUnicodeCharacter{0104}{\ogonek{A}} \DeclareUnicodeCharacter{0105}{\ogonek{a}} \DeclareUnicodeCharacter{0106}{\'C} \DeclareUnicodeCharacter{0107}{\'c} \DeclareUnicodeCharacter{0108}{\^C} \DeclareUnicodeCharacter{0109}{\^c} \DeclareUnicodeCharacter{0118}{\ogonek{E}} \DeclareUnicodeCharacter{0119}{\ogonek{e}} \DeclareUnicodeCharacter{010A}{\dotaccent{C}} \DeclareUnicodeCharacter{010B}{\dotaccent{c}} \DeclareUnicodeCharacter{010C}{\v{C}} \DeclareUnicodeCharacter{010D}{\v{c}} \DeclareUnicodeCharacter{010E}{\v{D}} \DeclareUnicodeCharacter{0112}{\=E} \DeclareUnicodeCharacter{0113}{\=e} \DeclareUnicodeCharacter{0114}{\u{E}} \DeclareUnicodeCharacter{0115}{\u{e}} \DeclareUnicodeCharacter{0116}{\dotaccent{E}} \DeclareUnicodeCharacter{0117}{\dotaccent{e}} \DeclareUnicodeCharacter{011A}{\v{E}} \DeclareUnicodeCharacter{011B}{\v{e}} \DeclareUnicodeCharacter{011C}{\^G} \DeclareUnicodeCharacter{011D}{\^g} \DeclareUnicodeCharacter{011E}{\u{G}} \DeclareUnicodeCharacter{011F}{\u{g}} \DeclareUnicodeCharacter{0120}{\dotaccent{G}} \DeclareUnicodeCharacter{0121}{\dotaccent{g}} \DeclareUnicodeCharacter{0124}{\^H} \DeclareUnicodeCharacter{0125}{\^h} \DeclareUnicodeCharacter{0128}{\~I} \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} \DeclareUnicodeCharacter{012A}{\=I} \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} \DeclareUnicodeCharacter{012C}{\u{I}} \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} \DeclareUnicodeCharacter{0130}{\dotaccent{I}} \DeclareUnicodeCharacter{0131}{\dotless{i}} \DeclareUnicodeCharacter{0132}{IJ} \DeclareUnicodeCharacter{0133}{ij} \DeclareUnicodeCharacter{0134}{\^J} \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} \DeclareUnicodeCharacter{0139}{\'L} \DeclareUnicodeCharacter{013A}{\'l} \DeclareUnicodeCharacter{0141}{\L} \DeclareUnicodeCharacter{0142}{\l} \DeclareUnicodeCharacter{0143}{\'N} \DeclareUnicodeCharacter{0144}{\'n} \DeclareUnicodeCharacter{0147}{\v{N}} \DeclareUnicodeCharacter{0148}{\v{n}} \DeclareUnicodeCharacter{014C}{\=O} \DeclareUnicodeCharacter{014D}{\=o} \DeclareUnicodeCharacter{014E}{\u{O}} \DeclareUnicodeCharacter{014F}{\u{o}} \DeclareUnicodeCharacter{0150}{\H{O}} \DeclareUnicodeCharacter{0151}{\H{o}} \DeclareUnicodeCharacter{0152}{\OE} \DeclareUnicodeCharacter{0153}{\oe} \DeclareUnicodeCharacter{0154}{\'R} \DeclareUnicodeCharacter{0155}{\'r} \DeclareUnicodeCharacter{0158}{\v{R}} \DeclareUnicodeCharacter{0159}{\v{r}} \DeclareUnicodeCharacter{015A}{\'S} \DeclareUnicodeCharacter{015B}{\'s} \DeclareUnicodeCharacter{015C}{\^S} \DeclareUnicodeCharacter{015D}{\^s} \DeclareUnicodeCharacter{015E}{\cedilla{S}} \DeclareUnicodeCharacter{015F}{\cedilla{s}} \DeclareUnicodeCharacter{0160}{\v{S}} \DeclareUnicodeCharacter{0161}{\v{s}} \DeclareUnicodeCharacter{0162}{\cedilla{t}} \DeclareUnicodeCharacter{0163}{\cedilla{T}} \DeclareUnicodeCharacter{0164}{\v{T}} \DeclareUnicodeCharacter{0168}{\~U} \DeclareUnicodeCharacter{0169}{\~u} \DeclareUnicodeCharacter{016A}{\=U} \DeclareUnicodeCharacter{016B}{\=u} \DeclareUnicodeCharacter{016C}{\u{U}} \DeclareUnicodeCharacter{016D}{\u{u}} \DeclareUnicodeCharacter{016E}{\ringaccent{U}} \DeclareUnicodeCharacter{016F}{\ringaccent{u}} \DeclareUnicodeCharacter{0170}{\H{U}} \DeclareUnicodeCharacter{0171}{\H{u}} \DeclareUnicodeCharacter{0174}{\^W} \DeclareUnicodeCharacter{0175}{\^w} \DeclareUnicodeCharacter{0176}{\^Y} \DeclareUnicodeCharacter{0177}{\^y} \DeclareUnicodeCharacter{0178}{\"Y} \DeclareUnicodeCharacter{0179}{\'Z} \DeclareUnicodeCharacter{017A}{\'z} \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} \DeclareUnicodeCharacter{017C}{\dotaccent{z}} \DeclareUnicodeCharacter{017D}{\v{Z}} \DeclareUnicodeCharacter{017E}{\v{z}} \DeclareUnicodeCharacter{01C4}{D\v{Z}} \DeclareUnicodeCharacter{01C5}{D\v{z}} \DeclareUnicodeCharacter{01C6}{d\v{z}} \DeclareUnicodeCharacter{01C7}{LJ} \DeclareUnicodeCharacter{01C8}{Lj} \DeclareUnicodeCharacter{01C9}{lj} \DeclareUnicodeCharacter{01CA}{NJ} \DeclareUnicodeCharacter{01CB}{Nj} \DeclareUnicodeCharacter{01CC}{nj} \DeclareUnicodeCharacter{01CD}{\v{A}} \DeclareUnicodeCharacter{01CE}{\v{a}} \DeclareUnicodeCharacter{01CF}{\v{I}} \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} \DeclareUnicodeCharacter{01D1}{\v{O}} \DeclareUnicodeCharacter{01D2}{\v{o}} \DeclareUnicodeCharacter{01D3}{\v{U}} \DeclareUnicodeCharacter{01D4}{\v{u}} \DeclareUnicodeCharacter{01E2}{\={\AE}} \DeclareUnicodeCharacter{01E3}{\={\ae}} \DeclareUnicodeCharacter{01E6}{\v{G}} \DeclareUnicodeCharacter{01E7}{\v{g}} \DeclareUnicodeCharacter{01E8}{\v{K}} \DeclareUnicodeCharacter{01E9}{\v{k}} \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} \DeclareUnicodeCharacter{01F1}{DZ} \DeclareUnicodeCharacter{01F2}{Dz} \DeclareUnicodeCharacter{01F3}{dz} \DeclareUnicodeCharacter{01F4}{\'G} \DeclareUnicodeCharacter{01F5}{\'g} \DeclareUnicodeCharacter{01F8}{\`N} \DeclareUnicodeCharacter{01F9}{\`n} \DeclareUnicodeCharacter{01FC}{\'{\AE}} \DeclareUnicodeCharacter{01FD}{\'{\ae}} \DeclareUnicodeCharacter{01FE}{\'{\O}} \DeclareUnicodeCharacter{01FF}{\'{\o}} \DeclareUnicodeCharacter{021E}{\v{H}} \DeclareUnicodeCharacter{021F}{\v{h}} \DeclareUnicodeCharacter{0226}{\dotaccent{A}} \DeclareUnicodeCharacter{0227}{\dotaccent{a}} \DeclareUnicodeCharacter{0228}{\cedilla{E}} \DeclareUnicodeCharacter{0229}{\cedilla{e}} \DeclareUnicodeCharacter{022E}{\dotaccent{O}} \DeclareUnicodeCharacter{022F}{\dotaccent{o}} \DeclareUnicodeCharacter{0232}{\=Y} \DeclareUnicodeCharacter{0233}{\=y} \DeclareUnicodeCharacter{0237}{\dotless{j}} \DeclareUnicodeCharacter{02DB}{\ogonek{ }} \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} \DeclareUnicodeCharacter{1E20}{\=G} \DeclareUnicodeCharacter{1E21}{\=g} \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} \DeclareUnicodeCharacter{1E26}{\"H} \DeclareUnicodeCharacter{1E27}{\"h} \DeclareUnicodeCharacter{1E30}{\'K} \DeclareUnicodeCharacter{1E31}{\'k} \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} \DeclareUnicodeCharacter{1E3E}{\'M} \DeclareUnicodeCharacter{1E3F}{\'m} \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} \DeclareUnicodeCharacter{1E54}{\'P} \DeclareUnicodeCharacter{1E55}{\'p} \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} \DeclareUnicodeCharacter{1E7C}{\~V} \DeclareUnicodeCharacter{1E7D}{\~v} \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} \DeclareUnicodeCharacter{1E80}{\`W} \DeclareUnicodeCharacter{1E81}{\`w} \DeclareUnicodeCharacter{1E82}{\'W} \DeclareUnicodeCharacter{1E83}{\'w} \DeclareUnicodeCharacter{1E84}{\"W} \DeclareUnicodeCharacter{1E85}{\"w} \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} \DeclareUnicodeCharacter{1E8C}{\"X} \DeclareUnicodeCharacter{1E8D}{\"x} \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} \DeclareUnicodeCharacter{1E90}{\^Z} \DeclareUnicodeCharacter{1E91}{\^z} \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} \DeclareUnicodeCharacter{1E97}{\"t} \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} \DeclareUnicodeCharacter{1EBC}{\~E} \DeclareUnicodeCharacter{1EBD}{\~e} \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} \DeclareUnicodeCharacter{1EF2}{\`Y} \DeclareUnicodeCharacter{1EF3}{\`y} \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} \DeclareUnicodeCharacter{1EF8}{\~Y} \DeclareUnicodeCharacter{1EF9}{\~y} \DeclareUnicodeCharacter{2013}{--} \DeclareUnicodeCharacter{2014}{---} \DeclareUnicodeCharacter{2018}{\quoteleft} \DeclareUnicodeCharacter{2019}{\quoteright} \DeclareUnicodeCharacter{201A}{\quotesinglbase} \DeclareUnicodeCharacter{201C}{\quotedblleft} \DeclareUnicodeCharacter{201D}{\quotedblright} \DeclareUnicodeCharacter{201E}{\quotedblbase} \DeclareUnicodeCharacter{2022}{\bullet} \DeclareUnicodeCharacter{2026}{\dots} \DeclareUnicodeCharacter{2039}{\guilsinglleft} \DeclareUnicodeCharacter{203A}{\guilsinglright} \DeclareUnicodeCharacter{20AC}{\euro} \DeclareUnicodeCharacter{2192}{\expansion} \DeclareUnicodeCharacter{21D2}{\result} \DeclareUnicodeCharacter{2212}{\minus} \DeclareUnicodeCharacter{2217}{\point} \DeclareUnicodeCharacter{2261}{\equiv} }% end of \utfeightchardefs % US-ASCII character definitions. \def\asciichardefs{% nothing need be done \relax } % Make non-ASCII characters printable again for compatibility with % existing Texinfo documents that may use them, even without declaring a % document encoding. % \setnonasciicharscatcode \other \message{formatting,} \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt \secheadingskip = 12pt plus 3pt minus 2pt \subsecheadingskip = 9pt plus 2pt minus 2pt % Prevent underfull vbox error messages. \vbadness = 10000 % Don't be very finicky about underfull hboxes, either. \hbadness = 6666 % Following George Bush, get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on % \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else \emergencystretch = .15\hsize \fi } % Parameters in order: 1) textheight; 2) textwidth; % 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; % 7) physical page height; 8) physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. % \def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip % \vsize = #1\relax \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin \pageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in \pagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax % if we don't reset these, they will remain at "1 true in" of % whatever layout pdftex was dumped with. \pdfhorigin = 1 true in \pdfvorigin = 1 true in \fi % \setleading{\textleading} % \parindent = \defaultparindent \setemergencystretch } % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % If page is nothing but text, make it come out even. \internalpagesizes{607.2pt}{6in}% that's 46 lines {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} % Use @smallbook to reset parameters for 7x9.25 trim size. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% {-.2in}{0in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} % Use @smallerbook to reset parameters for 6x9 trim size. % (Just testing, parameters still in flux.) \def\smallerbook{{\globaldefs = 1 \parskip = 1.5pt plus 1pt \textleading = 12pt % \internalpagesizes{7.4in}{4.8in}% {-.2in}{-.4in}% {0pt}{14pt}% {9in}{6in}% % \lispnarrowing = 0.25in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .4cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % Double-side printing via postscript on Laserjet 4050 % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. % To change the settings for a different printer or situation, adjust % \normaloffset until the front-side and back-side texts align. Then % do the same for \bindingoffset. You can set these for testing in % your texinfo source file like this: % @tex % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex \internalpagesizes{673.2pt}{160mm}% that's 51 lines {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% % \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} % Use @afivepaper to print on European A5 paper. % From romildo@urano.iceb.ufop.br, 2 July 2000. % He also recommends making @example and @lisp be small. \def\afivepaper{{\globaldefs = 1 \parskip = 2pt plus 1pt minus 0.1pt \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% {\voffset}{\hoffset}% {\bindingoffset}{8pt}% {210mm}{148mm}% % \lispnarrowing = 0.2in \tolerance = 800 \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm }} % A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 \afourpaper \internalpagesizes{237mm}{150mm}% {\voffset}{4.6mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% % % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} % Use @afourwide to print on A4 paper in landscape format. \def\afourwide{{\globaldefs = 1 \afourpaper \internalpagesizes{241mm}{165mm}% {\voffset}{-2.95mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% \globaldefs = 0 }} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. % \parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % \dimen0 = #1\relax \advance\dimen0 by \voffset % \dimen2 = \hsize \advance\dimen2 by \normaloffset % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% {\bindingoffset}{44pt}% {\dimen0}{\dimen2}% }} % Set default to letter. % \letterpaper \message{and turning on texinfo input format.} \def^^L{\par} % remove \outer, so ^L can appear in an @comment % DEL is a comment character, in case @c does not suffice. \catcode`\^^? = 14 % Define macros to output various characters with catcode for normal text. \catcode`\"=\other \def\normaldoublequote{"} \catcode`\$=\other \def\normaldollar{$}%$ font-lock fix \catcode`\+=\other \def\normalplus{+} \catcode`\<=\other \def\normalless{<} \catcode`\>=\other \def\normalgreater{>} \catcode`\^=\other \def\normalcaret{^} \catcode`\_=\other \def\normalunderscore{_} \catcode`\|=\other \def\normalverticalbar{|} \catcode`\~=\other \def\normaltilde{~} % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print % otherwise. Since all the Computer Modern typewriter fonts have zero % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % \def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} % Same as above, but check for italic font. Actually this also catches % non-italic slanted fonts since it is impossible to distinguish them from % italic fonts. But since this is only used by $ and it uses \sl anyway % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} % Turn off all special characters except @ % (and those which the user can use as if they were ordinary). % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote \catcode`\~=\active \def~{{\tt\char126}} \chardef\hat=`\^ \catcode`\^=\active \def^{{\tt \hat}} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} \let\realunder=_ % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } \catcode`\|=\active \def|{{\tt\char124}} \chardef \less=`\< \catcode`\<=\active \def<{{\tt \less}} \chardef \gtr=`\> \catcode`\>=\active \def>{{\tt \gtr}} \catcode`\+=\active \def+{{\tt \char 43}} \catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix % If a .fmt file is being used, characters that might appear in a file % name cannot be active until we have parsed the command line. % So turn them off again, and have \everyjob (or @setfilename) turn them on. % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} % Used sometimes to turn off (effectively) the active characters even after % parsing them. \def\turnoffactive{% \normalturnoffactive \otherbackslash } \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work % \realbackslash is an actual character `\' with catcode other, and % \doublebackslash is two of them (for the pdf outlines). {\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} % In texinfo, backslash is an active character; it prints the backslash % in fixed width font. \catcode`\\=\active % @ for escape char from now on. % The story here is that in math mode, the \char of \backslashcurfont % ends up printing the roman \ from the math symbol font (because \char % in math mode uses the \mathcode, and plain.tex sets % \mathcode`\\="026E). It seems better for @backslashchar{} to always % print a typewriter backslash, hence we use an explicit \mathchar, % which is the decimal equivalent of "715c (class 7, e.g., use \fam; % ignored family value; char position "5C). We can't use " for the % usual hex value because it has already been made active. @def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} @let@backslashchar = @normalbackslash % @backslashchar{} is for user documents. % On startup, @fixbackslash assigns: % @let \ = @normalbackslash % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. We switch back and forth between these. @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of % the literal character `\'. Also revert - to its normal character, in % case the active - from code has slipped in. % {@catcode`- = @active @gdef@normalturnoffactive{% @let-=@normaldash @let"=@normaldoublequote @let$=@normaldollar %$ font-lock fix @let+=@normalplus @let<=@normalless @let>=@normalgreater @let\=@normalbackslash @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let~=@normaltilde @markupsetuplqdefault @markupsetuprqdefault @unsepspaces } } % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @otherifyactive % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. % @gdef@eatinput input texinfo{@fixbackslash} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then % the first `\' in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. % Also turn back on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @ifx\@eatinput @let\ = @normalbackslash @fi @catcode`+=@active @catcode`@_=@active } % Say @foo, not \foo, in error messages. @escapechar = `@@ % These (along with & and #) are made active for url-breaking, so need % active definitions as the normal characters. @def@normaldot{.} @def@normalquest{?} @def@normalslash{/} % These look ok in all fonts, so just make them not special. % @hashchar{} gets its own user-level command, because of #line. @catcode`@& = @other @def@normalamp{&} @catcode`@# = @other @def@normalhash{#} @catcode`@% = @other @def@normalpercent{%} @let @hashchar = @normalhash @c Finally, make ` and ' active, so that txicodequoteundirected and @c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we @c don't make ` and ' active, @code will not get them as active chars. @c Do this last of all since we use ` in the previous @catcode assignments. @catcode`@'=@active @catcode`@`=@active @markupsetuplqdefault @markupsetuprqdefault @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @c page-delimiter: "^\\\\message" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: @c vim:sw=2: @ignore arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 @end ignore openocd-0.9.0/doc/INSTALL.txt0000644000175000017500000002030112315575360012507 00000000000000TODO!!! this should be merged into openocd.texi!!! Prerequisites ============= When building with support for FTDI FT2232 based devices, you need at least one of the following libraries: - libftdi (http://www.intra2net.com/opensource/ftdi/) - libftd2xx (http://www.ftdichip.com/Drivers/D2XX.htm) On Windows, you need either Cygwin or MinGW, but compilation for MinGW is also possible using a Cygwin host. Basic Installation ================== OpenOCD is distributed without autotools generated files, i.e. without a configure script. Run ./bootstrap in the openocd directory to have all necessary files generated. You have to explicitly enable desired JTAG interfaces during configure: ./configure --enable-parport --enable-ft2232-libftdi (OR --enable-ft2232-ftd2xx) \ --enable-amtjtagaccel Under Windows/Cygwin, only the ftd2xx driver is supported for FT2232 based devices. You have to specify the location of the FTDI driver package with the --with-ftd2xx=/full/path/name option. Under Linux you can choose to build the parport driver with support for /dev/parportN instead of the default access with direct port I/O using --enable-parport_ppdev. This has the advantage of running OpenOCD without root privileges at the expense of a slight performance decrease. This is also available on FreeBSD using PPI, but the naming of the devices is different. Generic installation instructions ================================= These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Type `make install' to install the programs and any data files and documentation. 4. You can remove the program binaries and object files from the source code directory by typing `make clean'. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. openocd-0.9.0/tcl/0000755000175000017500000000000012526202245010732 500000000000000openocd-0.9.0/tcl/cpu/0000755000175000017500000000000012526202234011517 500000000000000openocd-0.9.0/tcl/cpu/arm/0000755000175000017500000000000012526202234012276 500000000000000openocd-0.9.0/tcl/cpu/arm/arm7tdmi.tcl0000644000175000017500000000016312526202234014446 00000000000000set CPU_TYPE arm set CPU_NAME arm7tdmi set CPU_ARCH armv4t set CPU_MAX_ADDRESS 0xFFFFFFFF set CPU_NBITS 32 openocd-0.9.0/tcl/cpu/arm/cortex_m3.tcl0000644000175000017500000000016312526202234014625 00000000000000set CPU_TYPE arm set CPU_NAME cortex_m3 set CPU_ARCH armv7 set CPU_MAX_ADDRESS 0xFFFFFFFF set CPU_NBITS 32 openocd-0.9.0/tcl/cpu/arm/arm920.tcl0000644000175000017500000000016112526202234013732 00000000000000set CPU_TYPE arm set CPU_NAME arm920 set CPU_ARCH armv4t set CPU_MAX_ADDRESS 0xFFFFFFFF set CPU_NBITS 32 openocd-0.9.0/tcl/cpu/arm/arm946.tcl0000644000175000017500000000016212526202234013743 00000000000000set CPU_TYPE arm set CPU_NAME arm946 set CPU_ARCH armv5te set CPU_MAX_ADDRESS 0xFFFFFFFF set CPU_NBITS 32 openocd-0.9.0/tcl/cpu/arm/arm966.tcl0000644000175000017500000000016212526202234013745 00000000000000set CPU_TYPE arm set CPU_NAME arm966 set CPU_ARCH armv5te set CPU_MAX_ADDRESS 0xFFFFFFFF set CPU_NBITS 32 openocd-0.9.0/tcl/chip/0000755000175000017500000000000012526202235011654 500000000000000openocd-0.9.0/tcl/chip/st/0000755000175000017500000000000012526202235012302 500000000000000openocd-0.9.0/tcl/chip/st/spear/0000755000175000017500000000000012526202235013414 500000000000000openocd-0.9.0/tcl/chip/st/spear/spear3xx.tcl0000644000175000017500000000715412526202235015624 00000000000000# Generic init scripts for all ST SPEAr3xx family # http://www.st.com/spear # # Date: 2010-09-23 # Author: Antonio Borneo # Initialize internal clock # Default: # - Crystal = 24 MHz # - PLL1 = 332 MHz # - PLL2 = 332 MHz # - CPU_CLK = 332 MHz # - DDR_CLK = 332 MHz async # - HCLK = 166 MHz # - PCLK = 83 MHz proc sp3xx_clock_default {} { mww 0xfca00000 0x00000002 ;# set sysclk slow mww 0xfca00014 0x0ffffff8 ;# set pll timeout to minimum (100us ?!?) # DDRCORE disable to change frequency set val [expr ([mrw 0xfca8002c] & ~0x20000000) | 0x40000000] mww 0xfca8002c $val mww 0xfca8002c $val ;# Yes, write twice! # programming PLL1 mww 0xfca8000c 0xa600010c ;# M=166 P=1 N=12 mww 0xfca80008 0x00001c0a ;# power down mww 0xfca80008 0x00001c0e ;# enable mww 0xfca80008 0x00001c06 ;# strobe mww 0xfca80008 0x00001c0e while { [expr [mrw 0xfca80008] & 0x01] == 0x00 } { sleep 1 } # programming PLL2 mww 0xfca80018 0xa600010c ;# M=166, P=1, N=12 mww 0xfca80014 0x00001c0a ;# power down mww 0xfca80014 0x00001c0e ;# enable mww 0xfca80014 0x00001c06 ;# strobe mww 0xfca80014 0x00001c0e while { [expr [mrw 0xfca80014] & 0x01] == 0x00 } { sleep 1 } mww 0xfca80028 0x00000082 ;# enable plltimeen mww 0xfca80024 0x00000511 ;# set hclkdiv="/2" & pclkdiv="/2" mww 0xfca00000 0x00000004 ;# setting SYSCTL to NORMAL mode while { [expr [mrw 0xfca00000] & 0x20] != 0x20 } { sleep 1 } # Select source of DDR clock #mmw 0xfca80020 0x10000000 0x70000000 ;# PLL1 mmw 0xfca80020 0x30000000 0x70000000 ;# PLL2 # DDRCORE enable after change frequency mmw 0xfca8002c 0x20000000 0x00000000 } proc sp3xx_common_init {} { mww 0xfca8002c 0xfffffff8 ;# enable clock of all peripherals mww 0xfca80038 0x00000000 ;# remove reset of all peripherals mww 0xfca80034 0x0000ffff ;# enable all RAS clocks mww 0xfca80040 0x00000000 ;# remove all RAS resets mww 0xfca800e4 0x78000008 ;# COMP1V8_REG mww 0xfca800ec 0x78000008 ;# COMP3V3_REG mww 0xfc000000 0x10000f5f ;# init SMI and set HW mode mww 0xfc000000 0x00000f5f # Initialize Bus Interconnection Matrix # All ports Round-Robin and lowest priority mww 0xfca8007c 0x80000007 mww 0xfca80080 0x80000007 mww 0xfca80084 0x80000007 mww 0xfca80088 0x80000007 mww 0xfca8008c 0x80000007 mww 0xfca80090 0x80000007 mww 0xfca80094 0x80000007 mww 0xfca80098 0x80000007 mww 0xfca8009c 0x80000007 } # Specific init scripts for ST SPEAr300 proc sp300_init {} { mww 0x99000000 0x00003fff ;# RAS function enable } # Specific init scripts for ST SPEAr310 proc sp310_init {} { mww 0xb4000008 0x00002ff4 ;# RAS function enable mww 0xfca80050 0x00000001 ;# Enable clk mem port 1 mww 0xfca8013c 0x2f7bc210 ;# plgpio_pad_drv mww 0xfca80140 0x017bdef6 } proc sp310_emi_init {} { # set EMI pad strength mmw 0xfca80134 0x0e000000 0x00000000 mmw 0xfca80138 0x0e739ce7 0x00000000 mmw 0xfca8013c 0x00039ce7 0x00000000 # set safe EMI timing as in BootROM #mww 0x4f000000 0x0000000f ;# tAP_0_reg #mww 0x4f000004 0x00000000 ;# tSDP_0_reg #mww 0x4f000008 0x000000ff ;# tDPw_0_reg #mww 0x4f00000c 0x00000111 ;# tDPr_0_reg #mww 0x4f000010 0x00000002 ;# tDCS_0_reg # set fast EMI timing as in Linux mww 0x4f000000 0x00000010 ;# tAP_0_reg mww 0x4f000004 0x00000005 ;# tSDP_0_reg mww 0x4f000008 0x0000000a ;# tDPw_0_reg mww 0x4f00000c 0x0000000a ;# tDPr_0_reg mww 0x4f000010 0x00000005 ;# tDCS_0_re # 32bit wide, 8/16/32bit access mww 0x4f000014 0x0000000e ;# control_0_reg mww 0x4f000094 0x0000003f ;# ack_reg } # Specific init scripts for ST SPEAr320 proc sp320_init {} { mww 0xb300000c 0xffffac04 ;# RAS function enable mww 0xb3000010 0x00000001 ;# RAS mode select } openocd-0.9.0/tcl/chip/st/spear/quirk_no_srst.tcl0000644000175000017500000000335112526202235016744 00000000000000# Quirks to bypass missing SRST on JTAG connector # EVALSPEAr310 Rev. 2.0 # http://www.st.com/spear # # Date: 2010-08-17 # Author: Antonio Borneo # For boards that have JTAG SRST not connected. # We use "arm9 vector_catch reset" to catch button reset event. $_TARGETNAME configure -event reset-assert sp_reset_assert $_TARGETNAME configure -event reset-deassert-post sp_reset_deassert_post # keeps the name of the SPEAr target global sp_target_name set sp_target_name $_TARGETNAME # Keeps the argument of "reset" command (run, init, halt). global sp_reset_mode set sp_reset_mode "" # Helper procedure. Returns 0 is target is halted. proc sp_is_halted {} { global sp_target_name return [expr [string compare [$sp_target_name curstate] "halted" ] == 0] } # wait for reset button to be pressed, causing CPU to get halted proc sp_reset_deassert_post {} { global sp_reset_mode set bar(0) | set bar(1) / set bar(2) - set bar(3) \\ poll on echo "====> Press reset button on the board <====" for {set i 0} { [sp_is_halted] == 0 } { set i [expr $i + 1]} { echo -n "$bar([expr $i & 3])\r" sleep 200 } # Remove catch reset event arm9 vector_catch none # CPU is halted, but we typed "reset run" ... if { [string compare $sp_reset_mode "run"] == 0 } { resume } } # Override reset-assert, since no SRST available # Catch reset event proc sp_reset_assert {} { arm9 vector_catch reset } # Override default init_reset{mode} to catch parameter "mode" proc init_reset {mode} { global sp_reset_mode set sp_reset_mode $mode # We need to detect CPU get halted, so exit from halt if { [sp_is_halted] } { echo "Resuming CPU to detect reset" resume } # Execute default init_reset{mode} jtag arp_init-reset } openocd-0.9.0/tcl/chip/st/spear/spear3xx_ddr.tcl0000644000175000017500000001150412526202235016447 00000000000000# Init scripts to configure DDR controller of SPEAr3xx # http://www.st.com/spear # Original values taken from XLoader source code # # Date: 2010-09-23 # Author: Antonio Borneo proc sp3xx_ddr_init {ddr_type {ddr_chips 1}} { if { $ddr_chips != 1 && $ddr_chips != 2 } { error "Only 1 or 2 DDR chips permitted. Wrong value "$ddr_chips } if { $ddr_type == "mt47h64m16_3_333_cl5_async" } { ddr_spr3xx_mt47h64m16_3_333_cl5_async $ddr_chips set ddr_size 0x08000000 ## add here new DDR chip definition. Prototype: #} elseif { $ddr_type == "?????" } { # ????? $ddr_chips # set ddr_size 0x????? } else { error "sp3xx_ddr_init: unrecognized DDR type "$ddr_type } # MPMC START mww 0xfc60001c 0x01000100 if { $ddr_chips == 2 } { echo [format \ "Double chip DDR memory. Total memory size 0x%08x byte" \ [expr 2 * $ddr_size]] } else { echo [format \ "Single chip DDR memory. Memory size 0x%08x byte" \ $ddr_size] } } # from Xloader file ddr/spr300_mt47h64m16_3_333_cl5_async.S proc ddr_spr3xx_mt47h64m16_3_333_cl5_async {ddr_chips} { # DDR_PAD_REG mww 0xfca800f0 0x00003aa5 # Use "1:2 sync" only when DDR clock source is PLL1 and # HCLK is half of PLL1 mww 0xfc600000 0x00000001 ;# MEMCTL_AHB_SET_00 # This is async mww 0xfc600004 0x00000000 ;# MEMCTL_AHB_SET_01 # mww 0xfc600000 0x02020201 ;# MEMCTL_AHB_SET_00 # This is 1:2 sync # mww 0xfc600004 0x02020202 ;# MEMCTL_AHB_SET_01 mww 0xfc600008 0x01000000 ;# MEMCTL_RFSH_SET_00 mww 0xfc60000c 0x00000101 ;# MEMCTL_DLL_SET_00 mww 0xfc600010 0x00000101 ;# MEMCTL_GP_00 mww 0xfc600014 0x01000000 ;# MEMCTL_GP_01 mww 0xfc600018 0x00010001 ;# MEMCTL_GP_02 mww 0xfc60001c 0x00000100 ;# MEMCTL_GP_03 mww 0xfc600020 0x00010001 ;# MEMCTL_GP_04 if { $ddr_chips == 2 } { mww 0xfc600024 0x01020203 ;# MEMCTL_GP_05 mww 0xfc600028 0x01000102 ;# MEMCTL_GP_06 mww 0xfc60002c 0x02000202 ;# MEMCTL_AHB_SET_02 } else { mww 0xfc600024 0x00000201 ;# MEMCTL_GP_05 mww 0xfc600028 0x02000001 ;# MEMCTL_GP_06 mww 0xfc60002c 0x02000201 ;# MEMCTL_AHB_SET_02 } mww 0xfc600030 0x04040105 ;# MEMCTL_AHB_SET_03 mww 0xfc600034 0x03030302 ;# MEMCTL_AHB_SET_04 mww 0xfc600038 0x02040101 ;# MEMCTL_AHB_SET_05 mww 0xfc60003c 0x00000002 ;# MEMCTL_AHB_SET_06 mww 0xfc600044 0x03000405 ;# MEMCTL_DQS_SET_0 mww 0xfc600048 0x03040002 ;# MEMCTL_TIME_SET_01 mww 0xfc60004c 0x04000305 ;# MEMCTL_TIME_SET_02 mww 0xfc600050 0x0505053f ;# MEMCTL_AHB_RELPR_00 mww 0xfc600054 0x05050505 ;# MEMCTL_AHB_RELPR_01 mww 0xfc600058 0x04040405 ;# MEMCTL_AHB_RELPR_02 mww 0xfc60005c 0x04040404 ;# MEMCTL_AHB_RELPR_03 mww 0xfc600060 0x03030304 ;# MEMCTL_AHB_RELPR_04 mww 0xfc600064 0x03030303 ;# MEMCTL_AHB_RELPR_05 mww 0xfc600068 0x02020203 ;# MEMCTL_AHB_RELPR_06 mww 0xfc60006c 0x02020202 ;# MEMCTL_AHB_RELPR_07 mww 0xfc600070 0x01010102 ;# MEMCTL_AHB_RELPR_08 mww 0xfc600074 0x01010101 ;# MEMCTL_AHB_RELPR_09 mww 0xfc600078 0x00000001 ;# MEMCTL_AHB_RELPR_10 mww 0xfc600088 0x0a0c0a00 ;# MEMCTL_DQS_SET_1 mww 0xfc60008c 0x0000023f ;# MEMCTL_GP_07 mww 0xfc600090 0x00050a00 ;# MEMCTL_GP_08 mww 0xfc600094 0x11000000 ;# MEMCTL_GP_09 mww 0xfc600098 0x00001302 ;# MEMCTL_GP_10 mww 0xfc60009c 0x00001c1c ;# MEMCTL_DLL_SET_01 mww 0xfc6000a0 0x7c000000 ;# MEMCTL_DQS_OUT_SHIFT mww 0xfc6000a4 0x005c0000 ;# MEMCTL_WR_DQS_SHIFT mww 0xfc6000a8 0x2b050e00 ;# MEMCTL_TIME_SET_03 mww 0xfc6000ac 0x00640064 ;# MEMCTL_AHB_PRRLX_00 mww 0xfc6000b0 0x00640064 ;# MEMCTL_AHB_PRRLX_01 mww 0xfc6000b4 0x00000064 ;# MEMCTL_AHB_PRRLX_02 mww 0xfc6000b8 0x00000000 ;# MEMCTL_OUTRANGE_LGTH mww 0xfc6000bc 0x00200020 ;# MEMCTL_AHB_RW_SET_00 mww 0xfc6000c0 0x00200020 ;# MEMCTL_AHB_RW_SET_01 mww 0xfc6000c4 0x00200020 ;# MEMCTL_AHB_RW_SET_02 mww 0xfc6000c8 0x00200020 ;# MEMCTL_AHB_RW_SET_03 mww 0xfc6000cc 0x00200020 ;# MEMCTL_AHB_RW_SET_04 mww 0xfc6000d8 0x00000a24 ;# MEMCTL_TREF mww 0xfc6000dc 0x00000000 ;# MEMCTL_EMRS3_DATA mww 0xfc6000e0 0x5b1c00c8 ;# MEMCTL_TIME_SET_04 mww 0xfc6000e4 0x00c8002e ;# MEMCTL_TIME_SET_05 mww 0xfc6000e8 0x00000000 ;# MEMCTL_VERSION mww 0xfc6000ec 0x0001046b ;# MEMCTL_TINIT mww 0xfc6000f0 0x00000000 ;# MEMCTL_OUTRANGE_ADDR_01 mww 0xfc6000f4 0x00000000 ;# MEMCTL_OUTRANGE_ADDR_02 mww 0xfc600104 0x001c0000 ;# MEMCTL_DLL_DQS_DELAY_BYPASS_0 mww 0xfc600108 0x0019001c ;# MEMCTL_DLL_SET_02 mww 0xfc60010c 0x00100000 ;# MEMCTL_DLL_SET_03 mww 0xfc600110 0x001e007a ;# MEMCTL_DQS_SET_2 mww 0xfc600188 0x00000000 ;# MEMCTL_USER_DEF_REG_0 mww 0xfc60018c 0x00000000 ;# MEMCTL_USER_DEF_REG_1 mww 0xfc600190 0x01010001 ;# MEMCTL_GP_11 mww 0xfc600194 0x01000000 ;# MEMCTL_GP_12 mww 0xfc600198 0x00000001 ;# MEMCTL_GP_13 mww 0xfc60019c 0x00400000 ;# MEMCTL_GP_14 mww 0xfc6001a0 0x00000000 ;# MEMCTL_EMRS2_DATA_X mww 0xfc6001a4 0x00000000 ;# MEMCTL_LWPWR_CNT mww 0xfc6001a8 0x00000000 ;# MEMCTL_LWPWR_REG mww 0xfc6001ac 0x00860000 ;# MEMCTL_GP_15 mww 0xfc6001b0 0x00000002 ;# MEMCTL_TPDEX } openocd-0.9.0/tcl/chip/st/stm32/0000755000175000017500000000000012526202235013252 500000000000000openocd-0.9.0/tcl/chip/st/stm32/stm32_regs.tcl0000644000175000017500000001062712526202235015674 00000000000000# /* Peripheral and SRAM base address in the alias region */ set PERIPH_BB_BASE 0x42000000 set SRAM_BB_BASE 0x22000000 # /*Peripheral and SRAM base address in the bit-band region */ set SRAM_BASE 0x20000000 set PERIPH_BASE 0x40000000 # /*FSMC registers base address */ set FSMC_R_BASE 0xA0000000 # /*Peripheral memory map */ set APB1PERIPH_BASE [set PERIPH_BASE] set APB2PERIPH_BASE [expr $PERIPH_BASE + 0x10000] set AHBPERIPH_BASE [expr $PERIPH_BASE + 0x20000] set TIM2_BASE [expr $APB1PERIPH_BASE + 0x0000] set TIM3_BASE [expr $APB1PERIPH_BASE + 0x0400] set TIM4_BASE [expr $APB1PERIPH_BASE + 0x0800] set TIM5_BASE [expr $APB1PERIPH_BASE + 0x0C00] set TIM6_BASE [expr $APB1PERIPH_BASE + 0x1000] set TIM7_BASE [expr $APB1PERIPH_BASE + 0x1400] set RTC_BASE [expr $APB1PERIPH_BASE + 0x2800] set WWDG_BASE [expr $APB1PERIPH_BASE + 0x2C00] set IWDG_BASE [expr $APB1PERIPH_BASE + 0x3000] set SPI2_BASE [expr $APB1PERIPH_BASE + 0x3800] set SPI3_BASE [expr $APB1PERIPH_BASE + 0x3C00] set USART2_BASE [expr $APB1PERIPH_BASE + 0x4400] set USART3_BASE [expr $APB1PERIPH_BASE + 0x4800] set UART4_BASE [expr $APB1PERIPH_BASE + 0x4C00] set UART5_BASE [expr $APB1PERIPH_BASE + 0x5000] set I2C1_BASE [expr $APB1PERIPH_BASE + 0x5400] set I2C2_BASE [expr $APB1PERIPH_BASE + 0x5800] set CAN_BASE [expr $APB1PERIPH_BASE + 0x6400] set BKP_BASE [expr $APB1PERIPH_BASE + 0x6C00] set PWR_BASE [expr $APB1PERIPH_BASE + 0x7000] set DAC_BASE [expr $APB1PERIPH_BASE + 0x7400] set AFIO_BASE [expr $APB2PERIPH_BASE + 0x0000] set EXTI_BASE [expr $APB2PERIPH_BASE + 0x0400] set GPIOA_BASE [expr $APB2PERIPH_BASE + 0x0800] set GPIOB_BASE [expr $APB2PERIPH_BASE + 0x0C00] set GPIOC_BASE [expr $APB2PERIPH_BASE + 0x1000] set GPIOD_BASE [expr $APB2PERIPH_BASE + 0x1400] set GPIOE_BASE [expr $APB2PERIPH_BASE + 0x1800] set GPIOF_BASE [expr $APB2PERIPH_BASE + 0x1C00] set GPIOG_BASE [expr $APB2PERIPH_BASE + 0x2000] set ADC1_BASE [expr $APB2PERIPH_BASE + 0x2400] set ADC2_BASE [expr $APB2PERIPH_BASE + 0x2800] set TIM1_BASE [expr $APB2PERIPH_BASE + 0x2C00] set SPI1_BASE [expr $APB2PERIPH_BASE + 0x3000] set TIM8_BASE [expr $APB2PERIPH_BASE + 0x3400] set USART1_BASE [expr $APB2PERIPH_BASE + 0x3800] set ADC3_BASE [expr $APB2PERIPH_BASE + 0x3C00] set SDIO_BASE [expr $PERIPH_BASE + 0x18000] set DMA1_BASE [expr $AHBPERIPH_BASE + 0x0000] set DMA1_Channel1_BASE [expr $AHBPERIPH_BASE + 0x0008] set DMA1_Channel2_BASE [expr $AHBPERIPH_BASE + 0x001C] set DMA1_Channel3_BASE [expr $AHBPERIPH_BASE + 0x0030] set DMA1_Channel4_BASE [expr $AHBPERIPH_BASE + 0x0044] set DMA1_Channel5_BASE [expr $AHBPERIPH_BASE + 0x0058] set DMA1_Channel6_BASE [expr $AHBPERIPH_BASE + 0x006C] set DMA1_Channel7_BASE [expr $AHBPERIPH_BASE + 0x0080] set DMA2_BASE [expr $AHBPERIPH_BASE + 0x0400] set DMA2_Channel1_BASE [expr $AHBPERIPH_BASE + 0x0408] set DMA2_Channel2_BASE [expr $AHBPERIPH_BASE + 0x041C] set DMA2_Channel3_BASE [expr $AHBPERIPH_BASE + 0x0430] set DMA2_Channel4_BASE [expr $AHBPERIPH_BASE + 0x0444] set DMA2_Channel5_BASE [expr $AHBPERIPH_BASE + 0x0458] set RCC_BASE [expr $AHBPERIPH_BASE + 0x1000] set CRC_BASE [expr $AHBPERIPH_BASE + 0x3000] # /*Flash registers base address */ set FLASH_R_BASE [expr $AHBPERIPH_BASE + 0x2000] # /*Flash Option Bytes base address */ set OB_BASE 0x1FFFF800 # /*FSMC Bankx registers base address */ set FSMC_Bank1_R_BASE [expr $FSMC_R_BASE + 0x0000] set FSMC_Bank1E_R_BASE [expr $FSMC_R_BASE + 0x0104] set FSMC_Bank2_R_BASE [expr $FSMC_R_BASE + 0x0060] set FSMC_Bank3_R_BASE [expr $FSMC_R_BASE + 0x0080] set FSMC_Bank4_R_BASE [expr $FSMC_R_BASE + 0x00A0] # /*Debug MCU registers base address */ set DBGMCU_BASE 0xE0042000 # /*System Control Space memory map */ set SCS_BASE 0xE000E000 set SysTick_BASE [expr $SCS_BASE + 0x0010] set NVIC_BASE [expr $SCS_BASE + 0x0100] set SCB_BASE [expr $SCS_BASE + 0x0D00] openocd-0.9.0/tcl/chip/st/stm32/stm32.tcl0000644000175000017500000000031512526202235014645 00000000000000source [find bitsbytes.tcl] source [find cpu/arm/cortex_m3.tcl] source [find memory.tcl] source [find mmr_helpers.tcl] source [find chip/st/stm32/stm32_regs.tcl] source [find chip/st/stm32/stm32_rcc.tcl] openocd-0.9.0/tcl/chip/st/stm32/stm32_rcc.tcl0000644000175000017500000001627312526202235015506 00000000000000 set RCC_CR [expr $RCC_BASE + 0x00] set RCC_CFGR [expr $RCC_BASE + 0x04] set RCC_CIR [expr $RCC_BASE + 0x08] set RCC_APB2RSTR [expr $RCC_BASE + 0x0c] set RCC_APB1RSTR [expr $RCC_BASE + 0x10] set RCC_AHBENR [expr $RCC_BASE + 0x14] set RCC_APB2ENR [expr $RCC_BASE + 0x18] set RCC_APB1ENR [expr $RCC_BASE + 0x1c] set RCC_BDCR [expr $RCC_BASE + 0x20] set RCC_CSR [expr $RCC_BASE + 0x24] proc show_RCC_CR { } { if [ catch { set val [show_mmr32_reg RCC_CR] } msg ] { error $msg } show_mmr_bitfield 0 0 $val HSI { OFF ON } show_mmr_bitfield 1 1 $val HSIRDY { NOTRDY RDY } show_mmr_bitfield 7 3 $val HSITRIM { _NUMBER_ } show_mmr_bitfield 15 8 $val HSICAL { _NUMBER_ } show_mmr_bitfield 16 16 $val HSEON { OFF ON } show_mmr_bitfield 17 17 $val HSERDY { NOTRDY RDY } show_mmr_bitfield 18 18 $val HSEBYP { NOTBYPASSED BYPASSED } show_mmr_bitfield 19 19 $val CSSON { OFF ON } show_mmr_bitfield 24 24 $val PLLON { OFF ON } show_mmr_bitfield 25 25 $val PLLRDY { NOTRDY RDY } } proc show_RCC_CFGR { } { if [ catch { set val [show_mmr32_reg RCC_CFGR] } msg ] { error $msg } show_mmr_bitfield 1 0 $val SW { HSI HSE PLL ILLEGAL } show_mmr_bitfield 3 2 $val SWS { HSI HSE PLL ILLEGAL } show_mmr_bitfield 7 4 $val HPRE { sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_1 sysclk_div_2 sysclk_div_4 sysclk_div_8 sysclk_div_16 sysclk_div_64 sysclk_div_128 sysclk_div_256 sysclk_div_512 } show_mmr_bitfield 10 8 $val PPRE1 { hclk_div1 hclk_div1 hclk_div1 hclk_div1 hclk_div2 hclk_div4 hclk_div8 hclk_div16 } show_mmr_bitfield 13 11 $val PPRE2 { hclk_div1 hclk_div1 hclk_div1 hclk_div1 hclk_div2 hclk_div4 hclk_div8 hclk_div16 } show_mmr_bitfield 15 14 $val ADCPRE { pclk2_div1 pclk2_div1 pclk2_div1 pclk2_div1 pclk2_div2 pclk2_div4 pclk2_div8 pclk2_div16 } show_mmr_bitfield 16 16 $val PLLSRC { HSI_div_2 HSE } show_mmr_bitfield 17 17 $val PLLXTPRE { hse_div1 hse_div2 } show_mmr_bitfield 21 18 $val PLLMUL { x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x16 } show_mmr_bitfield 22 22 $val USBPRE { div1 div1_5 } show_mmr_bitfield 26 24 $val MCO { none none none none SysClk HSI HSE PLL_div2 } } proc show_RCC_CIR { } { if [ catch { set val [show_mmr32_reg RCC_CIR] } msg ] { error $msg } } proc show_RCC_APB2RSTR { } { if [ catch { set val [ show_mmr32_reg RCC_APB2RSTR] } msg ] { error $msg } for { set x 0 } { $x < 32 } { incr x } { set bits($x) xxx } set bits(15) adc3 set bits(14) usart1 set bits(13) tim8 set bits(12) spi1 set bits(11) tim1 set bits(10) adc2 set bits(9) adc1 set bits(8) iopg set bits(7) iopf set bits(6) iope set bits(5) iopd set bits(4) iopc set bits(3) iopb set bits(2) iopa set bits(1) xxx set bits(0) afio show_mmr32_bits bits $val } proc show_RCC_APB1RSTR { } { if [ catch { set val [ show_mmr32_reg RCC_APB1RSTR] } msg ] { error $msg } set bits(31) xxx set bits(30) xxx set bits(29) dac set bits(28) pwr set bits(27) bkp set bits(26) xxx set bits(25) can set bits(24) xxx set bits(23) usb set bits(22) i2c2 set bits(21) i2c1 set bits(20) uart5 set bits(19) uart4 set bits(18) uart3 set bits(17) uart2 set bits(16) xxx set bits(15) spi3 set bits(14) spi2 set bits(13) xxx set bits(12) xxx set bits(11) wwdg set bits(10) xxx set bits(9) xxx set bits(8) xxx set bits(7) xxx set bits(6) xxx set bits(5) tim7 set bits(4) tim6 set bits(3) tim5 set bits(2) tim4 set bits(1) tim3 set bits(0) tim2 show_mmr32_bits bits $val } proc show_RCC_AHBENR { } { if [ catch { set val [ show_mmr32_reg RCC_AHBENR ] } msg ] { error $msg } set bits(31) xxx set bits(30) xxx set bits(29) xxx set bits(28) xxx set bits(27) xxx set bits(26) xxx set bits(25) xxx set bits(24) xxx set bits(23) xxx set bits(22) xxx set bits(21) xxx set bits(20) xxx set bits(19) xxx set bits(18) xxx set bits(17) xxx set bits(16) xxx set bits(15) xxx set bits(14) xxx set bits(13) xxx set bits(12) xxx set bits(11) xxx set bits(10) sdio set bits(9) xxx set bits(8) fsmc set bits(7) xxx set bits(6) crce set bits(5) xxx set bits(4) flitf set bits(3) xxx set bits(2) sram set bits(1) dma2 set bits(0) dma1 show_mmr32_bits bits $val } proc show_RCC_APB2ENR { } { if [ catch { set val [ show_mmr32_reg RCC_APB2ENR ] } msg ] { error $msg } set bits(31) xxx set bits(30) xxx set bits(29) xxx set bits(28) xxx set bits(27) xxx set bits(26) xxx set bits(25) xxx set bits(24) xxx set bits(23) xxx set bits(22) xxx set bits(21) xxx set bits(20) xxx set bits(19) xxx set bits(18) xxx set bits(17) xxx set bits(16) xxx set bits(15) adc3 set bits(14) usart1 set bits(13) tim8 set bits(12) spi1 set bits(11) tim1 set bits(10) adc2 set bits(9) adc1 set bits(8) iopg set bits(7) iopf set bits(6) iope set bits(5) iopd set bits(4) iopc set bits(3) iopb set bits(2) iopa set bits(1) xxx set bits(0) afio show_mmr32_bits bits $val } proc show_RCC_APB1ENR { } { if [ catch { set val [ show_mmr32_reg RCC_APB1ENR ] } msg ] { error $msg } set bits(31) xxx set bits(30) xxx set bits(29) dac set bits(28) pwr set bits(27) bkp set bits(26) xxx set bits(25) can set bits(24) xxx set bits(23) usb set bits(22) i2c2 set bits(21) i2c1 set bits(20) usart5 set bits(19) usart4 set bits(18) usart3 set bits(17) usart2 set bits(16) xxx set bits(15) spi3 set bits(14) spi2 set bits(13) xxx set bits(12) xxx set bits(11) wwdg set bits(10) xxx set bits(9) xxx set bits(8) xxx set bits(7) xxx set bits(6) xxx set bits(5) tim7 set bits(4) tim6 set bits(3) tim5 set bits(2) tim4 set bits(1) tim3 set bits(0) tim2 show_mmr32_bits bits $val } proc show_RCC_BDCR { } { if [ catch { set val [ show_mmr32_reg RCC_BDCR ] } msg ] { error $msg } for { set x 0 } { $x < 32 } { incr x } { set bits($x) xxx } set bits(0) lseon set bits(1) lserdy set bits(2) lsebyp set bits(8) rtcsel0 set bits(9) rtcsel1 set bits(15) rtcen set bits(16) bdrst show_mmr32_bits bits $val } proc show_RCC_CSR { } { if [ catch { set val [ show_mmr32_reg RCC_CSR ] } msg ] { error $msg } for { set x 0 } { $x < 32 } { incr x } { set bits($x) xxx } set bits(0) lsion set bits(1) lsirdy set bits(24) rmvf set bits(26) pin set bits(27) por set bits(28) sft set bits(29) iwdg set bits(30) wwdg set bits(31) lpwr show_mmr32_bits bits $val } proc show_RCC { } { show_RCC_CR show_RCC_CFGR show_RCC_CIR show_RCC_APB2RSTR show_RCC_APB1RSTR show_RCC_AHBENR show_RCC_APB2ENR show_RCC_APB1ENR show_RCC_BDCR show_RCC_CSR } openocd-0.9.0/tcl/chip/ti/0000755000175000017500000000000012526202235012270 500000000000000openocd-0.9.0/tcl/chip/ti/lm3s/0000755000175000017500000000000012526202235013146 500000000000000openocd-0.9.0/tcl/chip/ti/lm3s/lm3s_regs.tcl0000644000175000017500000001201412526202235015466 00000000000000#***************************************************************************** # # The following are defines for the System Control register addresses. # #***************************************************************************** set SYSCTL_DID0 0x400FE000 ;# Device Identification 0 set SYSCTL_DID1 0x400FE004 ;# Device Identification 1 set SYSCTL_DC0 0x400FE008 ;# Device Capabilities 0 set SYSCTL_DC1 0x400FE010 ;# Device Capabilities 1 set SYSCTL_DC2 0x400FE014 ;# Device Capabilities 2 set SYSCTL_DC3 0x400FE018 ;# Device Capabilities 3 set SYSCTL_DC4 0x400FE01C ;# Device Capabilities 4 set SYSCTL_DC5 0x400FE020 ;# Device Capabilities 5 set SYSCTL_DC6 0x400FE024 ;# Device Capabilities 6 set SYSCTL_DC7 0x400FE028 ;# Device Capabilities 7 set SYSCTL_DC8 0x400FE02C ;# Device Capabilities 8 ADC ;# Channels set SYSCTL_PBORCTL 0x400FE030 ;# Brown-Out Reset Control set SYSCTL_LDOPCTL 0x400FE034 ;# LDO Power Control set SYSCTL_SRCR0 0x400FE040 ;# Software Reset Control 0 set SYSCTL_SRCR1 0x400FE044 ;# Software Reset Control 1 set SYSCTL_SRCR2 0x400FE048 ;# Software Reset Control 2 set SYSCTL_RIS 0x400FE050 ;# Raw Interrupt Status set SYSCTL_IMC 0x400FE054 ;# Interrupt Mask Control set SYSCTL_MISC 0x400FE058 ;# Masked Interrupt Status and ;# Clear set SYSCTL_RESC 0x400FE05C ;# Reset Cause set SYSCTL_RCC 0x400FE060 ;# Run-Mode Clock Configuration set SYSCTL_PLLCFG 0x400FE064 ;# XTAL to PLL Translation set SYSCTL_GPIOHSCTL 0x400FE06C ;# GPIO High-Speed Control set SYSCTL_GPIOHBCTL 0x400FE06C ;# GPIO High-Performance Bus ;# Control set SYSCTL_RCC2 0x400FE070 ;# Run-Mode Clock Configuration 2 set SYSCTL_MOSCCTL 0x400FE07C ;# Main Oscillator Control set SYSCTL_RCGC0 0x400FE100 ;# Run Mode Clock Gating Control ;# Register 0 set SYSCTL_RCGC1 0x400FE104 ;# Run Mode Clock Gating Control ;# Register 1 set SYSCTL_RCGC2 0x400FE108 ;# Run Mode Clock Gating Control ;# Register 2 set SYSCTL_SCGC0 0x400FE110 ;# Sleep Mode Clock Gating Control ;# Register 0 set SYSCTL_SCGC1 0x400FE114 ;# Sleep Mode Clock Gating Control ;# Register 1 set SYSCTL_SCGC2 0x400FE118 ;# Sleep Mode Clock Gating Control ;# Register 2 set SYSCTL_DCGC0 0x400FE120 ;# Deep Sleep Mode Clock Gating ;# Control Register 0 set SYSCTL_DCGC1 0x400FE124 ;# Deep-Sleep Mode Clock Gating ;# Control Register 1 set SYSCTL_DCGC2 0x400FE128 ;# Deep Sleep Mode Clock Gating ;# Control Register 2 set SYSCTL_DSLPCLKCFG 0x400FE144 ;# Deep Sleep Clock Configuration set SYSCTL_CLKVCLR 0x400FE150 ;# Clock Verification Clear set SYSCTL_PIOSCCAL 0x400FE150 ;# Precision Internal Oscillator ;# Calibration set SYSCTL_PIOSCSTAT 0x400FE154 ;# Precision Internal Oscillator ;# Statistics set SYSCTL_LDOARST 0x400FE160 ;# Allow Unregulated LDO to Reset ;# the Part set SYSCTL_I2SMCLKCFG 0x400FE170 ;# I2S MCLK Configuration set SYSCTL_DC9 0x400FE190 ;# Device Capabilities 9 ADC ;# Digital Comparators set SYSCTL_NVMSTAT 0x400FE1A0 ;# Non-Volatile Memory Information set SYSCTL_RCC_USESYSDIV 0x00400000 ;# Enable System Clock Divider set SYSCTL_RCC2_BYPASS2 0x00000800 ;# PLL Bypass 2 set SYSCTL_RCC_MOSCDIS 0x00000001 ;# Main Oscillator Disable set SYSCTL_SRCR0 0x400FE040 ;# Software Reset Control 0 set SYSCTL_SRCR1 0x400FE044 ;# Software Reset Control 1 set SYSCTL_SRCR2 0x400FE048 ;# Software Reset Control 2 set SYSCTL_MISC 0x400FE058 ;# Masked Interrupt Status and Clear set FLASH_FMA 0x400FD000 ;# Flash Memory Address set FLASH_FMD 0x400FD004 ;# Flash Memory Data set FLASH_FMC 0x400FD008 ;# Flash Memory Control set FLASH_FCRIS 0x400FD00C ;# Flash Controller Raw Interrupt Status set FLASH_FCIM 0x400FD010 ;# Flash Controller Interrupt Mask set FLASH_FCMISC 0x400FD014 ;# Flash Controller Masked Interrupt Status and Clear set FLASH_FMC2 0x400FD020 ;# Flash Memory Control 2 set FLASH_FWBVAL 0x400FD030 ;# Flash Write Buffer Valid openocd-0.9.0/tcl/chip/ti/lm3s/lm3s.tcl0000644000175000017500000000005112526202235014444 00000000000000source [find chip/ti/lm3s/lm3s_regs.tcl] openocd-0.9.0/tcl/chip/atmel/0000755000175000017500000000000012526202235012756 500000000000000openocd-0.9.0/tcl/chip/atmel/at91/0000755000175000017500000000000012526202236013535 500000000000000openocd-0.9.0/tcl/chip/atmel/at91/hardware.cfg0000644000175000017500000000043612526202235015735 00000000000000# External Memory Map set AT91_CHIPSELECT_0 0x10000000 set AT91_CHIPSELECT_1 0x20000000 set AT91_CHIPSELECT_2 0x30000000 set AT91_CHIPSELECT_3 0x40000000 set AT91_CHIPSELECT_4 0x50000000 set AT91_CHIPSELECT_5 0x60000000 set AT91_CHIPSELECT_6 0x70000000 set AT91_CHIPSELECT_7 0x80000000 openocd-0.9.0/tcl/chip/atmel/at91/at91sam7x128.tcl0000644000175000017500000000720112526202235016151 00000000000000source [find bitsbytes.tcl] source [find cpu/arm/arm7tdmi.tcl] source [find memory.tcl] source [find mmr_helpers.tcl] set CHIP_MAKER atmel set CHIP_FAMILY at91sam7 set CHIP_NAME at91sam7x128 # how many flash regions. set N_FLASH 1 set FLASH(0,CHIPSELECT) -1 set FLASH(0,BASE) 0x00100000 set FLASH(0,LEN) $__128K set FLASH(0,HUMAN) "internal flash" set FLASH(0,TYPE) "flash" set FLASH(0,RWX) $RWX_R_X set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # how many ram regions. set N_RAM 1 set RAM(0,CHIPSELECT) -1 set RAM(0,BASE) 0x00200000 set RAM(0,LEN) $__32K set RAM(0,HUMAN) "internal ram" set RAM(0,TYPE) "ram" set RAM(0,RWX) $RWX_RWX set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # I AM LAZY... I create 1 region for all MMRs. set N_MMREGS 1 set MMREGS(0,CHIPSELECT) -1 set MMREGS(0,BASE) 0xfff00000 set MMREGS(0,LEN) 0x000fffff set MMREGS(0,HUMAN) "mm-regs" set MMREGS(0,TYPE) "mmr" set MMREGS(0,RWX) $RWX_RW set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # no external memory set N_XMEM 0 set AT91C_BASE_SYS 0xFFFFF000 set AT91C_BASE_AIC 0xFFFFF000 set AT91C_BASE_PDC_DBGU 0xFFFFF300 set AT91C_BASE_DBGU 0xFFFFF200 set AT91C_BASE_PIOA 0xFFFFF400 set AT91C_BASE_PIOB 0xFFFFF600 set AT91C_BASE_CKGR 0xFFFFFC20 set AT91C_BASE_PMC 0xFFFFFC00 set AT91C_BASE_RSTC 0xFFFFFD00 set AT91C_BASE_RTTC 0xFFFFFD20 set AT91C_BASE_PITC 0xFFFFFD30 set AT91C_BASE_WDTC 0xFFFFFD40 set AT91C_BASE_VREG 0xFFFFFD60 set AT91C_BASE_MC 0xFFFFFF00 set AT91C_BASE_PDC_SPI1 0xFFFE4100 set AT91C_BASE_SPI1 0xFFFE4000 set AT91C_BASE_PDC_SPI0 0xFFFE0100 set AT91C_BASE_SPI0 0xFFFE0000 set AT91C_BASE_PDC_US1 0xFFFC4100 set AT91C_BASE_US1 0xFFFC4000 set AT91C_BASE_PDC_US0 0xFFFC0100 set AT91C_BASE_US0 0xFFFC0000 set AT91C_BASE_PDC_SSC 0xFFFD4100 set AT91C_BASE_SSC 0xFFFD4000 set AT91C_BASE_TWI 0xFFFB8000 set AT91C_BASE_PWMC_CH3 0xFFFCC260 set AT91C_BASE_PWMC_CH2 0xFFFCC240 set AT91C_BASE_PWMC_CH1 0xFFFCC220 set AT91C_BASE_PWMC_CH0 0xFFFCC200 set AT91C_BASE_PWMC 0xFFFCC000 set AT91C_BASE_UDP 0xFFFB0000 set AT91C_BASE_TC0 0xFFFA0000 set AT91C_BASE_TC1 0xFFFA0040 set AT91C_BASE_TC2 0xFFFA0080 set AT91C_BASE_TCB 0xFFFA0000 set AT91C_BASE_CAN_MB0 0xFFFD0200 set AT91C_BASE_CAN_MB1 0xFFFD0220 set AT91C_BASE_CAN_MB2 0xFFFD0240 set AT91C_BASE_CAN_MB3 0xFFFD0260 set AT91C_BASE_CAN_MB4 0xFFFD0280 set AT91C_BASE_CAN_MB5 0xFFFD02A0 set AT91C_BASE_CAN_MB6 0xFFFD02C0 set AT91C_BASE_CAN_MB7 0xFFFD02E0 set AT91C_BASE_CAN 0xFFFD0000 set AT91C_BASE_EMAC 0xFFFDC000 set AT91C_BASE_PDC_ADC 0xFFFD8100 set AT91C_BASE_ADC 0xFFFD8000 set AT91C_ID(0) FIQ set AT91C_ID(1) SYS set AT91C_ID(2) PIOA set AT91C_ID(3) PIOB set AT91C_ID(4) SPI0 set AT91C_ID(5) SPI1 set AT91C_ID(6) US0 set AT91C_ID(7) US1 set AT91C_ID(8) SSC set AT91C_ID(9) TWI set AT91C_ID(10) PWMC set AT91C_ID(11) UDP set AT91C_ID(12) TC0 set AT91C_ID(13) TC1 set AT91C_ID(14) TC2 set AT91C_ID(15) CAN set AT91C_ID(16) EMAC set AT91C_ID(17) ADC set AT91C_ID(18) "" set AT91C_ID(19) "" set AT91C_ID(20) "" set AT91C_ID(21) "" set AT91C_ID(22) "" set AT91C_ID(23) "" set AT91C_ID(24) "" set AT91C_ID(25) "" set AT91C_ID(26) "" set AT91C_ID(27) "" set AT91C_ID(28) "" set AT91C_ID(29) "" set AT91C_ID(30) IRQ0 set AT91C_ID(31) IRQ1 source [find chip/atmel/at91/aic.tcl] source [find chip/atmel/at91/usarts.tcl] source [find chip/atmel/at91/pmc.tcl] source [find chip/atmel/at91/rtt.tcl] openocd-0.9.0/tcl/chip/atmel/at91/at91sam9261_matrix.cfg0000644000175000017500000000520412526202235017323 00000000000000 set AT91_MATRIX_MCFG [expr ($AT91_MATRIX + 0x00)] ;# Master Configuration Register # set AT91_MATRIX_RCB0 [expr (1 << 0)] ;# Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) set AT91_MATRIX_RCB1 [expr (1 << 1)] ;# Remap Command for AHB Master 1 (ARM926EJ-S Data Master) set AT91_MATRIX_SCFG0 [expr ($AT91_MATRIX + 0x04)] ;# Slave Configuration Register 0 set AT91_MATRIX_SCFG1 [expr ($AT91_MATRIX + 0x08)] ;# Slave Configuration Register 1 set AT91_MATRIX_SCFG2 [expr ($AT91_MATRIX + 0x0C)] ;# Slave Configuration Register 2 set AT91_MATRIX_SCFG3 [expr ($AT91_MATRIX + 0x10)] ;# Slave Configuration Register 3 set AT91_MATRIX_SCFG4 [expr ($AT91_MATRIX + 0x14)] ;# Slave Configuration Register 4 set AT91_MATRIX_SLOT_CYCLE [expr (0xff << 0)] ;# Maximum Number of Allowed Cycles for a Burst set AT91_MATRIX_DEFMSTR_TYPE [expr (3 << 16)] ;# Default Master Type set AT91_MATRIX_DEFMSTR_TYPE_NONE [expr (0 << 16)] set AT91_MATRIX_DEFMSTR_TYPE_LAST [expr (1 << 16)] set AT91_MATRIX_DEFMSTR_TYPE_FIXED [expr (2 << 16)] set AT91_MATRIX_FIXED_DEFMSTR [expr (7 << 18)] ;# Fixed Index of Default Master set AT91_MATRIX_TCR [expr ($AT91_MATRIX + 0x24)] ;# TCM Configuration Register set AT91_MATRIX_ITCM_SIZE [expr (0xf << 0)] ;# Size of ITCM enabled memory block set AT91_MATRIX_ITCM_0 [expr (0 << 0)] set AT91_MATRIX_ITCM_16 [expr (5 << 0)] set AT91_MATRIX_ITCM_32 [expr (6 << 0)] set AT91_MATRIX_ITCM_64 [expr (7 << 0)] set AT91_MATRIX_DTCM_SIZE [expr (0xf << 4)] ;# Size of DTCM enabled memory block set AT91_MATRIX_DTCM_0 [expr (0 << 4)] set AT91_MATRIX_DTCM_16 [expr (5 << 4)] set AT91_MATRIX_DTCM_32 [expr (6 << 4)] set AT91_MATRIX_DTCM_64 [expr (7 << 4)] set AT91_MATRIX_EBICSA [expr ($AT91_MATRIX + 0x30)] ;# EBI Chip Select Assignment Register set AT91_MATRIX_CS1A [expr (1 << 1)] ;# Chip Select 1 Assignment set AT91_MATRIX_CS1A_SMC [expr (0 << 1)] set AT91_MATRIX_CS1A_SDRAMC [expr (1 << 1)] set AT91_MATRIX_CS3A [expr (1 << 3)] ;# Chip Select 3 Assignment set AT91_MATRIX_CS3A_SMC [expr (0 << 3)] set AT91_MATRIX_CS3A_SMC_SMARTMEDIA [expr (1 << 3)] set AT91_MATRIX_CS4A [expr (1 << 4)] ;# Chip Select 4 Assignment set AT91_MATRIX_CS4A_SMC [expr (0 << 4)] set AT91_MATRIX_CS4A_SMC_CF1 [expr (1 << 4)] set AT91_MATRIX_CS5A [expr (1 << 5)] ;# Chip Select 5 Assignment set AT91_MATRIX_CS5A_SMC [expr (0 << 5)] set AT91_MATRIX_CS5A_SMC_CF2 [expr (1 << 5)] set AT91_MATRIX_DBPUC [expr (1 << 8)] ;# Data Bus Pull-up Configuration set AT91_MATRIX_USBPUCR [expr ($AT91_MATRIX + 0x34)] ;# USB Pad Pull-Up Control Register set AT91_MATRIX_USBPUCR_PUON [expr (1 << 30)] ;# USB Device PAD Pull-up Enable openocd-0.9.0/tcl/chip/atmel/at91/at91sam7x256.tcl0000644000175000017500000001001312526202235016146 00000000000000source [find bitsbytes.tcl] source [find cpu/arm/arm7tdmi.tcl] source [find memory.tcl] source [find mmr_helpers.tcl] set CHIP_MAKER atmel set CHIP_FAMILY at91sam7 set CHIP_NAME at91sam7x256 # how many flash regions. set N_FLASH 1 set FLASH(0,CHIPSELECT) -1 set FLASH(0,BASE) 0x00100000 set FLASH(0,LEN) $__256K set FLASH(0,HUMAN) "internal flash" set FLASH(0,TYPE) "flash" set FLASH(0,RWX) $RWX_R_X set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # how many ram regions. set N_RAM 1 set RAM(0,CHIPSELECT) -1 set RAM(0,BASE) 0x00200000 set RAM(0,LEN) $__64K set RAM(0,HUMAN) "internal ram" set RAM(0,TYPE) "ram" set RAM(0,RWX) $RWX_RWX set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # I AM LAZY... I create 1 region for all MMRs. set N_MMREGS 1 set MMREGS(0,CHIPSELECT) -1 set MMREGS(0,BASE) 0xfff00000 set MMREGS(0,LEN) 0x000fffff set MMREGS(0,HUMAN) "mm-regs" set MMREGS(0,TYPE) "mmr" set MMREGS(0,RWX) $RWX_RW set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # no external memory set N_XMEM 0 set AT91C_BASE_SYS 0xFFFFF000 set AT91C_BASE_AIC 0xFFFFF000 set AT91C_BASE_PDC_DBGU 0xFFFFF300 set AT91C_BASE_DBGU 0xFFFFF200 set AT91C_BASE_PIOA 0xFFFFF400 set AT91C_BASE_PIOB 0xFFFFF600 set AT91C_BASE_CKGR 0xFFFFFC20 set AT91C_BASE_PMC 0xFFFFFC00 set AT91C_BASE_RSTC 0xFFFFFD00 set AT91C_BASE_RTTC 0xFFFFFD20 set AT91C_BASE_PITC 0xFFFFFD30 set AT91C_BASE_WDTC 0xFFFFFD40 set AT91C_BASE_VREG 0xFFFFFD60 set AT91C_BASE_MC 0xFFFFFF00 set AT91C_BASE_PDC_SPI1 0xFFFE4100 set AT91C_BASE_SPI1 0xFFFE4000 set AT91C_BASE_PDC_SPI0 0xFFFE0100 set AT91C_BASE_SPI0 0xFFFE0000 set AT91C_BASE_PDC_US1 0xFFFC4100 set AT91C_BASE_US1 0xFFFC4000 set AT91C_BASE_PDC_US0 0xFFFC0100 set AT91C_BASE_US0 0xFFFC0000 set AT91C_BASE_PDC_SSC 0xFFFD4100 set AT91C_BASE_SSC 0xFFFD4000 set AT91C_BASE_TWI 0xFFFB8000 set AT91C_BASE_PWMC_CH3 0xFFFCC260 set AT91C_BASE_PWMC_CH2 0xFFFCC240 set AT91C_BASE_PWMC_CH1 0xFFFCC220 set AT91C_BASE_PWMC_CH0 0xFFFCC200 set AT91C_BASE_PWMC 0xFFFCC000 set AT91C_BASE_UDP 0xFFFB0000 set AT91C_BASE_TC0 0xFFFA0000 set AT91C_BASE_TC1 0xFFFA0040 set AT91C_BASE_TC2 0xFFFA0080 set AT91C_BASE_TCB 0xFFFA0000 set AT91C_BASE_CAN_MB0 0xFFFD0200 set AT91C_BASE_CAN_MB1 0xFFFD0220 set AT91C_BASE_CAN_MB2 0xFFFD0240 set AT91C_BASE_CAN_MB3 0xFFFD0260 set AT91C_BASE_CAN_MB4 0xFFFD0280 set AT91C_BASE_CAN_MB5 0xFFFD02A0 set AT91C_BASE_CAN_MB6 0xFFFD02C0 set AT91C_BASE_CAN_MB7 0xFFFD02E0 set AT91C_BASE_CAN 0xFFFD0000 set AT91C_BASE_EMAC 0xFFFDC000 set AT91C_BASE_PDC_ADC 0xFFFD8100 set AT91C_BASE_ADC 0xFFFD8000 set AT91C_ID(0) "FIQ" set AT91C_ID(1) "SYS" set AT91C_ID(2) "PIOA" set AT91C_ID(3) "PIOB" set AT91C_ID(4) "SPI0" set AT91C_ID(5) "SPI1" set AT91C_ID(6) "US0" set AT91C_ID(7) "US1" set AT91C_ID(8) "SSC" set AT91C_ID(9) "TWI" set AT91C_ID(10) "PWMC" set AT91C_ID(11) "UDP" set AT91C_ID(12) "TC0" set AT91C_ID(13) "TC1" set AT91C_ID(14) "TC2" set AT91C_ID(15) "CAN" set AT91C_ID(16) "EMAC" set AT91C_ID(17) "ADC" set AT91C_ID(18) "" set AT91C_ID(19) "" set AT91C_ID(20) "" set AT91C_ID(21) "" set AT91C_ID(22) "" set AT91C_ID(23) "" set AT91C_ID(24) "" set AT91C_ID(25) "" set AT91C_ID(26) "" set AT91C_ID(27) "" set AT91C_ID(28) "" set AT91C_ID(29) "" set AT91C_ID(30) "IRQ0" set AT91C_ID(31) "IRQ1" source [find chip/atmel/at91/aic.tcl] source [find chip/atmel/at91/usarts.tcl] source [find chip/atmel/at91/pmc.tcl] source [find chip/atmel/at91/rtt.tcl] openocd-0.9.0/tcl/chip/atmel/at91/rtt.tcl0000644000175000017500000000256212526202235014776 00000000000000 set RTTC_RTMR [expr $AT91C_BASE_RTTC + 0x00] set RTTC_RTAR [expr $AT91C_BASE_RTTC + 0x04] set RTTC_RTVR [expr $AT91C_BASE_RTTC + 0x08] set RTTC_RTSR [expr $AT91C_BASE_RTTC + 0x0c] global RTTC_RTMR global RTTC_RTAR global RTTC_RTVR global RTTC_RTSR proc show_RTTC_RTMR_helper { NAME ADDR VAL } { set rtpres [expr $VAL & 0x0ffff] global BIT16 BIT17 if { $rtpres == 0 } { set rtpres 65536; } global AT91C_SLOWOSC_FREQ # Nasty hack, make this a float by tacking a .0 on the end # otherwise, jim makes the value an integer set f [expr $AT91C_SLOWOSC_FREQ.0 / $rtpres.0] echo [format "\tPrescale value: 0x%04x (%5d) => %f Hz" $rtpres $rtpres $f] if { $VAL & $BIT16 } { echo "\tBit16 -> Alarm IRQ Enabled" } else { echo "\tBit16 -> Alarm IRQ Disabled" } if { $VAL & $BIT17 } { echo "\tBit17 -> RTC Inc IRQ Enabled" } else { echo "\tBit17 -> RTC Inc IRQ Disabled" } # Bit 18 is write only. } proc show_RTTC_RTSR_helper { NAME ADDR VAL } { global BIT0 BIT1 if { $VAL & $BIT0 } { echo "\tBit0 -> ALARM PENDING" } else { echo "\tBit0 -> alarm not pending" } if { $VAL & $BIT1 } { echo "\tBit0 -> RTINC PENDING" } else { echo "\tBit0 -> rtinc not pending" } } proc show_RTTC { } { show_mmr32_reg RTTC_RTMR show_mmr32_reg RTTC_RTAR show_mmr32_reg RTTC_RTVR show_mmr32_reg RTTC_RTSR } openocd-0.9.0/tcl/chip/atmel/at91/at91sam9263_matrix.cfg0000644000175000017500000001573012526202235017332 00000000000000set AT91_MATRIX_MCFG0 [expr ($AT91_MATRIX + 0x00)] ;# Master Configuration Register 0 set AT91_MATRIX_MCFG1 [expr ($AT91_MATRIX + 0x04)] ;# Master Configuration Register 1 set AT91_MATRIX_MCFG2 [expr ($AT91_MATRIX + 0x08)] ;# Master Configuration Register 2 set AT91_MATRIX_MCFG3 [expr ($AT91_MATRIX + 0x0C)] ;# Master Configuration Register 3 set AT91_MATRIX_MCFG4 [expr ($AT91_MATRIX + 0x10)] ;# Master Configuration Register 4 set AT91_MATRIX_MCFG5 [expr ($AT91_MATRIX + 0x14)] ;# Master Configuration Register 5 set AT91_MATRIX_MCFG6 [expr ($AT91_MATRIX + 0x18)] ;# Master Configuration Register 6 set AT91_MATRIX_MCFG7 [expr ($AT91_MATRIX + 0x1C)] ;# Master Configuration Register 7 set AT91_MATRIX_MCFG8 [expr ($AT91_MATRIX + 0x20)] ;# Master Configuration Register 8 set AT91_MATRIX_ULBT [expr (7 << 0)] ;# Undefined Length Burst Type set AT91_MATRIX_ULBT_INFINITE [expr (0 << 0)] set AT91_MATRIX_ULBT_SINGLE [expr (1 << 0)] set AT91_MATRIX_ULBT_FOUR [expr (2 << 0)] set AT91_MATRIX_ULBT_EIGHT [expr (3 << 0)] set AT91_MATRIX_ULBT_SIXTEEN [expr (4 << 0)] set AT91_MATRIX_SCFG0 [expr ($AT91_MATRIX + 0x40)] ;# Slave Configuration Register 0 set AT91_MATRIX_SCFG1 [expr ($AT91_MATRIX + 0x44)] ;# Slave Configuration Register 1 set AT91_MATRIX_SCFG2 [expr ($AT91_MATRIX + 0x48)] ;# Slave Configuration Register 2 set AT91_MATRIX_SCFG3 [expr ($AT91_MATRIX + 0x4C)] ;# Slave Configuration Register 3 set AT91_MATRIX_SCFG4 [expr ($AT91_MATRIX + 0x50)] ;# Slave Configuration Register 4 set AT91_MATRIX_SCFG5 [expr ($AT91_MATRIX + 0x54)] ;# Slave Configuration Register 5 set AT91_MATRIX_SCFG6 [expr ($AT91_MATRIX + 0x58)] ;# Slave Configuration Register 6 set AT91_MATRIX_SCFG7 [expr ($AT91_MATRIX + 0x5C)] ;# Slave Configuration Register 7 set AT91_MATRIX_SLOT_CYCLE [expr (0xff << 0)] ;# Maximum Number of Allowed Cycles for a Burst set AT91_MATRIX_DEFMSTR_TYPE [expr (3 << 16)] ;# Default Master Type set AT91_MATRIX_DEFMSTR_TYPE_NONE [expr (0 << 16)] set AT91_MATRIX_DEFMSTR_TYPE_LAST [expr (1 << 16)] set AT91_MATRIX_DEFMSTR_TYPE_FIXED [expr (2 << 16)] set AT91_MATRIX_FIXED_DEFMSTR [expr (0xf << 18)] ;# Fixed Index of Default Master set AT91_MATRIX_ARBT [expr (3 << 24)] ;# Arbitration Type set AT91_MATRIX_ARBT_ROUND_ROBIN [expr (0 << 24)] set AT91_MATRIX_ARBT_FIXED_PRIORITY [expr (1 << 24)] set AT91_MATRIX_PRAS0 [expr ($AT91_MATRIX + 0x80)] ;# Priority Register A for Slave 0 set AT91_MATRIX_PRBS0 [expr ($AT91_MATRIX + 0x84)] ;# Priority Register B for Slave 0 set AT91_MATRIX_PRAS1 [expr ($AT91_MATRIX + 0x88)] ;# Priority Register A for Slave 1 set AT91_MATRIX_PRBS1 [expr ($AT91_MATRIX + 0x8C)] ;# Priority Register B for Slave 1 set AT91_MATRIX_PRAS2 [expr ($AT91_MATRIX + 0x90)] ;# Priority Register A for Slave 2 set AT91_MATRIX_PRBS2 [expr ($AT91_MATRIX + 0x94)] ;# Priority Register B for Slave 2 set AT91_MATRIX_PRAS3 [expr ($AT91_MATRIX + 0x98)] ;# Priority Register A for Slave 3 set AT91_MATRIX_PRBS3 [expr ($AT91_MATRIX + 0x9C)] ;# Priority Register B for Slave 3 set AT91_MATRIX_PRAS4 [expr ($AT91_MATRIX + 0xA0)] ;# Priority Register A for Slave 4 set AT91_MATRIX_PRBS4 [expr ($AT91_MATRIX + 0xA4)] ;# Priority Register B for Slave 4 set AT91_MATRIX_PRAS5 [expr ($AT91_MATRIX + 0xA8)] ;# Priority Register A for Slave 5 set AT91_MATRIX_PRBS5 [expr ($AT91_MATRIX + 0xAC)] ;# Priority Register B for Slave 5 set AT91_MATRIX_PRAS6 [expr ($AT91_MATRIX + 0xB0)] ;# Priority Register A for Slave 6 set AT91_MATRIX_PRBS6 [expr ($AT91_MATRIX + 0xB4)] ;# Priority Register B for Slave 6 set AT91_MATRIX_PRAS7 [expr ($AT91_MATRIX + 0xB8)] ;# Priority Register A for Slave 7 set AT91_MATRIX_PRBS7 [expr ($AT91_MATRIX + 0xBC)] ;# Priority Register B for Slave 7 set AT91_MATRIX_M0PR [expr (3 << 0)] ;# Master 0 Priority set AT91_MATRIX_M1PR [expr (3 << 4)] ;# Master 1 Priority set AT91_MATRIX_M2PR [expr (3 << 8)] ;# Master 2 Priority set AT91_MATRIX_M3PR [expr (3 << 12)] ;# Master 3 Priority set AT91_MATRIX_M4PR [expr (3 << 16)] ;# Master 4 Priority set AT91_MATRIX_M5PR [expr (3 << 20)] ;# Master 5 Priority set AT91_MATRIX_M6PR [expr (3 << 24)] ;# Master 6 Priority set AT91_MATRIX_M7PR [expr (3 << 28)] ;# Master 7 Priority set AT91_MATRIX_M8PR [expr (3 << 0)] ;# Master 8 Priority (in Register B) set AT91_MATRIX_MRCR [expr ($AT91_MATRIX + 0x100)] ;# Master Remap Control Register set AT91_MATRIX_RCB0 [expr (1 << 0)] ;# Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) set AT91_MATRIX_RCB1 [expr (1 << 1)] ;# Remap Command for AHB Master 1 (ARM926EJ-S Data Master) set AT91_MATRIX_RCB2 [expr (1 << 2)] set AT91_MATRIX_RCB3 [expr (1 << 3)] set AT91_MATRIX_RCB4 [expr (1 << 4)] set AT91_MATRIX_RCB5 [expr (1 << 5)] set AT91_MATRIX_RCB6 [expr (1 << 6)] set AT91_MATRIX_RCB7 [expr (1 << 7)] set AT91_MATRIX_RCB8 [expr (1 << 8)] set AT91_MATRIX_TCMR [expr ($AT91_MATRIX + 0x114)] ;# TCM Configuration Register set AT91_MATRIX_ITCM_SIZE [expr (0xf << 0)] ;# Size of ITCM enabled memory block set AT91_MATRIX_ITCM_0 [expr (0 << 0)] set AT91_MATRIX_ITCM_16 [expr (5 << 0)] set AT91_MATRIX_ITCM_32 [expr (6 << 0)] set AT91_MATRIX_DTCM_SIZE [expr (0xf << 4)] ;# Size of DTCM enabled memory block set AT91_MATRIX_DTCM_0 [expr (0 << 4)] set AT91_MATRIX_DTCM_16 [expr (5 << 4)] set AT91_MATRIX_DTCM_32 [expr (6 << 4)] set AT91_MATRIX_EBI0CSA [expr ($AT91_MATRIX + 0x120)] ;# EBI0 Chip Select Assignment Register set AT91_MATRIX_EBI0_CS1A [expr (1 << 1)] ;# Chip Select 1 Assignment set AT91_MATRIX_EBI0_CS1A_SMC [expr (0 << 1)] set AT91_MATRIX_EBI0_CS1A_SDRAMC [expr (1 << 1)] set AT91_MATRIX_EBI0_CS3A [expr (1 << 3)] ;# Chip Select 3 Assignmen set AT91_MATRIX_EBI0_CS3A_SMC [expr (0 << 3)] set AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA [expr (1 << 3)] set AT91_MATRIX_EBI0_CS4A [expr (1 << 4)] ;# Chip Select 4 Assignment set AT91_MATRIX_EBI0_CS4A_SMC [expr (0 << 4)] set AT91_MATRIX_EBI0_CS4A_SMC_CF1 [expr (1 << 4)] set AT91_MATRIX_EBI0_CS5A [expr (1 << 5)] ;# Chip Select 5 Assignment set AT91_MATRIX_EBI0_CS5A_SMC [expr (0 << 5)] set AT91_MATRIX_EBI0_CS5A_SMC_CF2 [expr (1 << 5)] set AT91_MATRIX_EBI0_DBPUC [expr (1 << 8)] ;# Data Bus Pull-up Configuration set AT91_MATRIX_EBI0_VDDIOMSEL [expr (1 << 16)] ;# Memory voltage selection set AT91_MATRIX_EBI0_VDDIOMSEL_1_8V [expr (0 << 16)] set AT91_MATRIX_EBI0_VDDIOMSEL_3_3V [expr (1 << 16)] set AT91_MATRIX_EBI1CSA [expr ($AT91_MATRIX + 0x124)] ;# EBI1 Chip Select Assignment Register set AT91_MATRIX_EBI1_CS1A [expr (1 << 1)] ;# Chip Select 1 Assignment set AT91_MATRIX_EBI1_CS1A_SMC [expr (0 << 1)] set AT91_MATRIX_EBI1_CS1A_SDRAMC [expr (1 << 1)] set AT91_MATRIX_EBI1_CS2A [expr (1 << 3)] ;# Chip Select 3 Assignment set AT91_MATRIX_EBI1_CS2A_SMC [expr (0 << 3)] set AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA [expr (1 << 3)] set AT91_MATRIX_EBI1_DBPUC [expr (1 << 8)] ;# Data Bus Pull-up Configuration set AT91_MATRIX_EBI1_VDDIOMSEL [expr (1 << 16)] ;# Memory voltage selection set AT91_MATRIX_EBI1_VDDIOMSEL_1_8V [expr (0 << 16)] set AT91_MATRIX_EBI1_VDDIOMSEL_3_3V [expr (1 << 16)] openocd-0.9.0/tcl/chip/atmel/at91/at91sam9_sdramc.cfg0000644000175000017500000000642512526202235017045 00000000000000 # SDRAM Controller (SDRAMC) registers set AT91_SDRAMC_MR [expr ($AT91_SDRAMC + 0x00)] ;# SDRAM Controller Mode Register set AT91_SDRAMC_MODE [expr (0xf << 0)] ;# Command Mode set AT91_SDRAMC_MODE_NORMAL 0 set AT91_SDRAMC_MODE_NOP 1 set AT91_SDRAMC_MODE_PRECHARGE 2 set AT91_SDRAMC_MODE_LMR 3 set AT91_SDRAMC_MODE_REFRESH 4 set AT91_SDRAMC_MODE_EXT_LMR 5 set AT91_SDRAMC_MODE_DEEP 6 set AT91_SDRAMC_TR [expr ($AT91_SDRAMC + 0x04)] ;# SDRAM Controller Refresh Timer Register set AT91_SDRAMC_COUNT [expr (0xfff << 0)] ;# Refresh Timer Counter set AT91_SDRAMC_CR [expr ($AT91_SDRAMC + 0x08)] ;# SDRAM Controller Configuration Register set AT91_SDRAMC_NC [expr (3 << 0)] ;# Number of Column Bits set AT91_SDRAMC_NC_8 [expr (0 << 0)] set AT91_SDRAMC_NC_9 [expr (1 << 0)] set AT91_SDRAMC_NC_10 [expr (2 << 0)] set AT91_SDRAMC_NC_11 [expr (3 << 0)] set AT91_SDRAMC_NR [expr (3 << 2)] ;# Number of Row Bits set AT91_SDRAMC_NR_11 [expr (0 << 2)] set AT91_SDRAMC_NR_12 [expr (1 << 2)] set AT91_SDRAMC_NR_13 [expr (2 << 2)] set AT91_SDRAMC_NB [expr (1 << 4)] ;# Number of Banks set AT91_SDRAMC_NB_2 [expr (0 << 4)] set AT91_SDRAMC_NB_4 [expr (1 << 4)] set AT91_SDRAMC_CAS [expr (3 << 5)] ;# CAS Latency set AT91_SDRAMC_CAS_1 [expr (1 << 5)] set AT91_SDRAMC_CAS_2 [expr (2 << 5)] set AT91_SDRAMC_CAS_3 [expr (3 << 5)] set AT91_SDRAMC_DBW [expr (1 << 7)] ;# Data Bus Width set AT91_SDRAMC_DBW_32 [expr (0 << 7)] set AT91_SDRAMC_DBW_16 [expr (1 << 7)] set AT91_SDRAMC_TWR [expr (0xf << 8)] ;# Write Recovery Delay set AT91_SDRAMC_TRC [expr (0xf << 12)] ;# Row Cycle Delay set AT91_SDRAMC_TRP [expr (0xf << 16)] ;# Row Precharge Delay set AT91_SDRAMC_TRCD [expr (0xf << 20)] ;# Row to Column Delay set AT91_SDRAMC_TRAS [expr (0xf << 24)] ;# Active to Precharge Delay set AT91_SDRAMC_TXSR [expr (0xf << 28)] ;# Exit Self Refresh to Active Delay set AT91_SDRAMC_LPR [expr ($AT91_SDRAMC + 0x10)] ;# SDRAM Controller Low Power Register set AT91_SDRAMC_LPCB [expr (3 << 0)] ;# Low-power Configurations set AT91_SDRAMC_LPCB_DISABLE 0 set AT91_SDRAMC_LPCB_SELF_REFRESH 1 set AT91_SDRAMC_LPCB_POWER_DOWN 2 set AT91_SDRAMC_LPCB_DEEP_POWER_DOWN 3 set AT91_SDRAMC_PASR [expr (7 << 4)] ;# Partial Array Self Refresh set AT91_SDRAMC_TCSR [expr (3 << 8)] ;# Temperature Compensated Self Refresh set AT91_SDRAMC_DS [expr (3 << 10)] ;# Drive Strength set AT91_SDRAMC_TIMEOUT [expr (3 << 12)] ;# Time to define when Low Power Mode is enabled set AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES [expr (0 << 12)] set AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES [expr (1 << 12)] set AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES [expr (2 << 12)] set AT91_SDRAMC_IER [expr ($AT91_SDRAMC + 0x14)] ;# SDRAM Controller Interrupt Enable Register set AT91_SDRAMC_IDR [expr ($AT91_SDRAMC + 0x18)] ;# SDRAM Controller Interrupt Disable Register set AT91_SDRAMC_IMR [expr ($AT91_SDRAMC + 0x1C)] ;# SDRAM Controller Interrupt Mask Register set AT91_SDRAMC_ISR [expr ($AT91_SDRAMC + 0x20)] ;# SDRAM Controller Interrupt Status Register set AT91_SDRAMC_RES [expr (1 << 0)] ;# Refresh Error Status set AT91_SDRAMC_MDR [expr ($AT91_SDRAMC + 0x24)] ;# SDRAM Memory Device Register set AT91_SDRAMC_MD [expr (3 << 0)] ;# Memory Device Type set AT91_SDRAMC_MD_SDRAM 0 set AT91_SDRAMC_MD_LOW_POWER_SDRAM 1 openocd-0.9.0/tcl/chip/atmel/at91/usarts.tcl0000644000175000017500000000707512526202235015512 00000000000000# the DBGU and USARTs are 'almost' indentical' set DBGU_CR [expr $AT91C_BASE_DBGU + 0x00000000] set DBGU_MR [expr $AT91C_BASE_DBGU + 0x00000004] set DBGU_IER [expr $AT91C_BASE_DBGU + 0x00000008] set DBGU_IDR [expr $AT91C_BASE_DBGU + 0x0000000C] set DBGU_IMR [expr $AT91C_BASE_DBGU + 0x00000010] set DBGU_CSR [expr $AT91C_BASE_DBGU + 0x00000014] set DBGU_RHR [expr $AT91C_BASE_DBGU + 0x00000018] set DBGU_THR [expr $AT91C_BASE_DBGU + 0x0000001C] set DBGU_BRGR [expr $AT91C_BASE_DBGU + 0x00000020] # no RTOR # no TTGR # no FIDI # no NER set DBGU_CIDR [expr $AT91C_BASE_DBGU + 0x00000040] set DBGU_EXID [expr $AT91C_BASE_DBGU + 0x00000044] set DBGU_FNTR [expr $AT91C_BASE_DBGU + 0x00000048] set USx_CR 0x00000000 set USx_MR 0x00000004 set USx_IER 0x00000008 set USx_IDR 0x0000000C set USx_IMR 0x00000010 set USx_CSR 0x00000014 set USx_RHR 0x00000018 set USx_THR 0x0000001C set USx_BRGR 0x00000020 set USx_RTOR 0x00000024 set USx_TTGR 0x00000028 set USx_FIDI 0x00000040 set USx_NER 0x00000044 set USx_IF 0x0000004C # Create all the uarts that exist.. # we blow up if there are >9 proc show_mmr_USx_MR_helper { NAME ADDR VAL } { # First - just print it set x [show_normalize_bitfield $VAL 3 0] if { $x == 0 } { echo "\tNormal operation" } else { echo [format "\tNon Normal operation mode: 0x%02x" $x] } set x [show_normalize_bitfield $VAL 11 9] set s "unknown" switch -exact $x { 0 { set s "Even" } 1 { set s "Odd" } 2 { set s "Force=0" } 3 { set s "Force=1" } * { set $x [expr $x & 6] switch -exact $x { 4 { set s "None" } 6 { set s "Multidrop Mode" } } } } echo [format "\tParity: %s " $s] set x [expr 5 + [show_normalize_bitfield $VAL 7 6]] echo [format "\tDatabits: %d" $x] set x [show_normalize_bitfield $VAL 13 12] switch -exact $x { 0 { echo "\tStop bits: 1" } 1 { echo "\tStop bits: 1.5" } 2 { echo "\tStop bits: 2" } 3 { echo "\tStop bits: Illegal/Reserved" } } } # For every possbile usart... foreach WHO { US0 US1 US2 US3 US4 US5 US6 US7 US8 US9 } { set n AT91C_BASE_[set WHO] set str "" # Only if it exists on the chip if [ info exists $n ] { # Hence: $n - is like AT91C_BASE_USx # For every sub-register foreach REG {CR MR IER IDR IMR CSR RHR THR BRGR RTOR TTGR FIDI NER IF} { # vn = variable name set vn [set WHO]_[set REG] # vn = USx_IER # vv = variable value set vv [expr $$n + [set USx_[set REG]]] # And VV is the address in memory of that register # make that VN a GLOBAL so others can find it global $vn set $vn $vv # Create a command for this specific register. proc show_$vn { } "show_mmr32_reg $vn" # Add this command to the Device(as a whole) command set str "$str\nshow_$vn" } # Now - create the DEVICE(as a whole) command set fn show_$WHO proc $fn { } $str } } # The Debug Uart is special.. set str "" # For every sub-register foreach REG {DBGU_CR DBGU_MR DBGU_IER DBGU_IDR DBGU_IMR DBGU_CSR DBGU_RHR DBGU_THR DBGU_BRGR DBGU_CIDR DBGU_EXID DBGU_FNTR} { # Create a command for this specific register. proc show_$REG { } "show_mmr32_reg $REG" # Add this command to the Device(as a whole) command set str "$str\nshow_$REG" } # Now - create the DEVICE(as a whole) command proc show_DBGU { } $str unset str proc show_DBGU_MR_helper { NAME ADDR VAL } { show_mmr_USx_MR_helper $NAME $ADDR $VAL } openocd-0.9.0/tcl/chip/atmel/at91/at91_rstc.cfg0000644000175000017500000000220412526202235015744 00000000000000set AT91_RSTC_CR [expr ($AT91_RSTC + 0x00)] ;# Reset Controller Control Register set AT91_RSTC_PROCRST [expr (1 << 0)] ;# Processor Reset set AT91_RSTC_PERRST [expr (1 << 2)] ;# Peripheral Reset set AT91_RSTC_EXTRST [expr (1 << 3)] ;# External Reset set AT91_RSTC_KEY [expr (0xa5 << 24)] ;# KEY Password set AT91_RSTC_SR [expr ($AT91_RSTC + 0x04)] ;# Reset Controller Status Register set AT91_RSTC_URSTS [expr (1 << 0)] ;# User Reset Status set AT91_RSTC_RSTTYP [expr (7 << 8)] ;# Reset Type set AT91_RSTC_RSTTYP_GENERAL [expr (0 << 8)] set AT91_RSTC_RSTTYP_WAKEUP [expr (1 << 8)] set AT91_RSTC_RSTTYP_WATCHDOG [expr (2 << 8)] set AT91_RSTC_RSTTYP_SOFTWARE [expr (3 << 8)] set AT91_RSTC_RSTTYP_USER [expr (4 << 8)] set AT91_RSTC_NRSTL [expr (1 << 16)] ;# NRST Pin Level set AT91_RSTC_SRCMP [expr (1 << 17)] ;# Software Reset Command in Progress set AT91_RSTC_MR [expr ($AT91_RSTC + 0x08)] ;# Reset Controller Mode Register set AT91_RSTC_URSTEN [expr (1 << 0)] ;# User Reset Enable set AT91_RSTC_URSTIEN [expr (1 << 4)] ;# User Reset Interrupt Enable set AT91_RSTC_ERSTL [expr (0xf << 8)] ;# External Reset Length openocd-0.9.0/tcl/chip/atmel/at91/at91sam9_smc.cfg0000644000175000017500000000170512526202235016352 00000000000000set AT91_SMC_READMODE [expr (1 << 0)] ;# Read Mode set AT91_SMC_WRITEMODE [expr (1 << 1)] ;# Write Mode set AT91_SMC_EXNWMODE [expr (3 << 4)] ;# NWAIT Mode set AT91_SMC_EXNWMODE_DISABLE [expr (0 << 4)] set AT91_SMC_EXNWMODE_FROZEN [expr (2 << 4)] set AT91_SMC_EXNWMODE_READY [expr (3 << 4)] set AT91_SMC_BAT [expr (1 << 8)] ;# Byte Access Type set AT91_SMC_BAT_SELECT [expr (0 << 8)] set AT91_SMC_BAT_WRITE [expr (1 << 8)] set AT91_SMC_DBW [expr (3 << 12)] ;# Data Bus Width */ set AT91_SMC_DBW_8 [expr (0 << 12)] set AT91_SMC_DBW_16 [expr (1 << 12)] set AT91_SMC_DBW_32 [expr (2 << 12)] set AT91_SMC_TDFMODE [expr (1 << 20)] ;# TDF Optimization - Enabled set AT91_SMC_PMEN [expr (1 << 24)] ;# Page Mode Enabled set AT91_SMC_PS [expr (3 << 28)] ;# Page Size set AT91_SMC_PS_4 [expr (0 << 28)] set AT91_SMC_PS_8 [expr (1 << 28)] set AT91_SMC_PS_16 [expr (2 << 28)] set AT91_SMC_PS_32 [expr (3 << 28)] openocd-0.9.0/tcl/chip/atmel/at91/aic.tcl0000644000175000017500000000554412526202235014724 00000000000000set AIC_SMR [expr $AT91C_BASE_AIC + 0x00000000 ] global AIC_SMR set AIC_SVR [expr $AT91C_BASE_AIC + 0x00000080 ] global AIC_SVR set AIC_IVR [expr $AT91C_BASE_AIC + 0x00000100 ] global AIC_IVR set AIC_FVR [expr $AT91C_BASE_AIC + 0x00000104 ] global AIC_FVR set AIC_ISR [expr $AT91C_BASE_AIC + 0x00000108 ] global AIC_ISR set AIC_IPR [expr $AT91C_BASE_AIC + 0x0000010C ] global AIC_IPR set AIC_IMR [expr $AT91C_BASE_AIC + 0x00000110 ] global AIC_IMR set AIC_CISR [expr $AT91C_BASE_AIC + 0x00000114 ] global AIC_CISR set AIC_IECR [expr $AT91C_BASE_AIC + 0x00000120 ] global AIC_IECR set AIC_IDCR [expr $AT91C_BASE_AIC + 0x00000124 ] global AIC_IDCR set AIC_ICCR [expr $AT91C_BASE_AIC + 0x00000128 ] global AIC_ICCR set AIC_ISCR [expr $AT91C_BASE_AIC + 0x0000012C ] global AIC_ISCR set AIC_EOICR [expr $AT91C_BASE_AIC + 0x00000130 ] global AIC_EOICR set AIC_SPU [expr $AT91C_BASE_AIC + 0x00000134 ] global AIC_SPU set AIC_DCR [expr $AT91C_BASE_AIC + 0x00000138 ] global AIC_DCR set AIC_FFER [expr $AT91C_BASE_AIC + 0x00000140 ] global AIC_FFER set AIC_FFDR [expr $AT91C_BASE_AIC + 0x00000144 ] global AIC_FFDR set AIC_FFSR [expr $AT91C_BASE_AIC + 0x00000148 ] global AIC_FFSR proc aic_enable_disable_list { VAL ENAME DNAME } { global AT91C_ID show_mmr32_bits AT91C_ID $VAL } proc show_AIC_IPR_helper { NAME ADDR VAL } { aic_enable_disable_list $VAL "IRQ PENDING" "irq not-pending" } proc show_AIC_IMR_helper { NAME ADDR VAL } { aic_enable_disable_list $VAL "IRQ ENABLED" "irq disabled" } proc show_AIC { } { global AIC_SMR if [catch { mem2array aaa 32 $AIC_SMR [expr 32 * 4] } msg ] { error [format "%s (%s)" $msg AIC_SMR] } echo "AIC_SMR: Mode & Type" global AT91C_ID for { set x 0 } { $x < 32 } { } { echo -n " " echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] incr x } global AIC_SVR if [catch { mem2array aaa 32 $AIC_SVR [expr 32 * 4] } msg ] { error [format "%s (%s)" $msg AIC_SVR] } echo "AIC_SVR: Vectors" for { set x 0 } { $x < 32 } { } { echo -n " " echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] incr x echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] incr x } foreach REG { AIC_IVR AIC_FVR AIC_ISR AIC_IPR AIC_IMR AIC_CISR AIC_IECR AIC_IDCR AIC_ICCR AIC_ISCR AIC_EOICR AIC_SPU AIC_DCR AIC_FFER AIC_FFDR AIC_FFSR } { if [catch { show_mmr32_reg $REG } msg ] { error $msg break } } } openocd-0.9.0/tcl/chip/atmel/at91/sam9_smc.cfg0000644000175000017500000000256312526202235015656 00000000000000# Setup register # # ncs_read_setup # nrd_setup # ncs_write_setup # set nwe_setup # # # Pulse register # # ncs_read_pulse # nrd_pulse # ncs_write_pulse # nwe_pulse # # # Cycle register # # read_cycle 0 # write_cycle 0 # # # Mode register # # mode # tdf_cycles proc sam9_smc_config { cs smc_config } { ;# Setup Register for CS n set AT91_SMC_SETUP [expr ($::AT91_SMC + 0x00 + ((cs)*0x10))] set val [expr ($smc_config(nwe_setup) << 0)] set val [expr ($val | $smc_config(ncs_write_setup) << 8] set val [expr ($val | $smc_config(nrd_setup)) << 16] set val [expr ($val | $smc_config(ncs_read_setup) << 24] mww $AT91_SMC_SETUP $val ;# Pulse Register for CS n set AT91_SMC_PULSE [expr ($::AT91_SMC + 0x04 + ((cs)*0x10))] set val [expr ($smc_config(nwe_pulse) << 0)] set val [expr ($val | $smc_config(ncs_write_pulse) << 8] set val [expr ($val | $smc_config(nrd_pulse) << 16] set val [expr ($val | $smc_config(ncs_read_pulse) << 24] mww $AT91_SMC_PULSE $val ;# Cycle Register for CS n set AT91_SMC_CYCLE [expr ($::AT91_SMC + 0x08 + ((cs)*0x10))] set val [expr ($smc_config(write_cycle) << 0)] set val [expr ($val | $smc_config(read_cycle) << 16] mww $AT91_SMC_CYCLE $val ;# Mode Register for CS n set AT91_SMC_MODE [expr ($::AT91_SMC + 0x0c + ((cs)*0x10))] set val [expr ($smc_config(mode) << 0)] set val [expr ($val | $smc_config(tdf_cycles) << 16] mww $AT91_SMC_MODE $val } openocd-0.9.0/tcl/chip/atmel/at91/at91sam9261.cfg0000644000175000017500000000555412526202235015747 00000000000000# # Peripheral identifiers/interrupts. # set AT91_ID_FIQ 0 ;# Advanced Interrupt Controller (FIQ) set AT91_ID_SYS 1 ;# System Peripherals set AT91SAM9261_ID_PIOA 2 ;# Parallel IO Controller A set AT91SAM9261_ID_PIOB 3 ;# Parallel IO Controller B set AT91SAM9261_ID_PIOC 4 ;# Parallel IO Controller C set AT91SAM9261_ID_US0 6 ;# USART 0 set AT91SAM9261_ID_US1 7 ;# USART 1 set AT91SAM9261_ID_US2 8 ;# USART 2 set AT91SAM9261_ID_MCI 9 ;# Multimedia Card Interface set AT91SAM9261_ID_UDP 10 ;# USB Device Port set AT91SAM9261_ID_TWI 11 ;# Two-Wire Interface set AT91SAM9261_ID_SPI0 12 ;# Serial Peripheral Interface 0 set AT91SAM9261_ID_SPI1 13 ;# Serial Peripheral Interface 1 set AT91SAM9261_ID_SSC0 14 ;# Serial Synchronous Controller 0 set AT91SAM9261_ID_SSC1 15 ;# Serial Synchronous Controller 1 set AT91SAM9261_ID_SSC2 16 ;# Serial Synchronous Controller 2 set AT91SAM9261_ID_TC0 17 ;# Timer Counter 0 set AT91SAM9261_ID_TC1 18 ;# Timer Counter 1 set AT91SAM9261_ID_TC2 19 ;# Timer Counter 2 set AT91SAM9261_ID_UHP 20 ;# USB Host port set AT91SAM9261_ID_LCDC 21 ;# LDC Controller set AT91SAM9261_ID_IRQ0 29 ;# Advanced Interrupt Controller (IRQ0) set AT91SAM9261_ID_IRQ1 30 ;# Advanced Interrupt Controller (IRQ1) set AT91SAM9261_ID_IRQ2 31 ;# Advanced Interrupt Controller (IRQ2) # # User Peripheral physical base addresses. # set AT91SAM9261_BASE_TCB0 0xfffa0000 set AT91SAM9261_BASE_TC0 0xfffa0000 set AT91SAM9261_BASE_TC1 0xfffa0040 set AT91SAM9261_BASE_TC2 0xfffa0080 set AT91SAM9261_BASE_UDP 0xfffa4000 set AT91SAM9261_BASE_MCI 0xfffa8000 set AT91SAM9261_BASE_TWI 0xfffac000 set AT91SAM9261_BASE_US0 0xfffb0000 set AT91SAM9261_BASE_US1 0xfffb4000 set AT91SAM9261_BASE_US2 0xfffb8000 set AT91SAM9261_BASE_SSC0 0xfffbc000 set AT91SAM9261_BASE_SSC1 0xfffc0000 set AT91SAM9261_BASE_SSC2 0xfffc4000 set AT91SAM9261_BASE_SPI0 0xfffc8000 set AT91SAM9261_BASE_SPI1 0xfffcc000 set AT91_BASE_SYS 0xffffea00 # # System Peripherals (offset from AT91_BASE_SYS) # set AT91_SDRAMC 0xffffea00 set AT91_SMC 0xffffec00 set AT91_MATRIX 0xffffee00 set AT91_AIC 0xfffff000 set AT91_DBGU 0xfffff200 set AT91_PIOA 0xfffff400 set AT91_PIOB 0xfffff600 set AT91_PIOC 0xfffff800 set AT91_PMC 0xfffffc00 set AT91_RSTC 0xfffffd00 set AT91_SHDWC 0xfffffd10 set AT91_RTT 0xfffffd20 set AT91_PIT 0xfffffd30 set AT91_WDT 0xfffffd40 set AT91_GPBR 0xfffffd50 set AT91_USART0 $AT91SAM9261_BASE_US0 set AT91_USART1 $AT91SAM9261_BASE_US1 set AT91_USART2 $AT91SAM9261_BASE_US2 # # Internal Memory. # set AT91SAM9261_SRAM_BASE 0x00300000 ;# Internal SRAM base address set AT91SAM9261_SRAM_SIZE 0x00028000 ;# Internal SRAM size (160Kb) set AT91SAM9261_ROM_BASE 0x00400000 ;# Internal ROM base address set AT91SAM9261_ROM_SIZE 0x00008000 ;# Internal ROM size (32Kb) set AT91SAM9261_UHP_BASE 0x00500000 ;# USB Host controller set AT91SAM9261_LCDC_BASE 0x00600000 ;# LDC controller # # Cpu Name # set AT91_CPU_NAME "AT91SAM9261" openocd-0.9.0/tcl/chip/atmel/at91/at91sam9263.cfg0000644000175000017500000000735712526202235015754 00000000000000# # Peripheral identifiers/interrupts. # set AT91_ID_FIQ 0 ;# Advanced Interrupt Controller (FIQ) set AT91_ID_SYS 1 ;# System Peripherals set AT91SAM9263_ID_PIOA 2 ;# Parallel IO Controller A set AT91SAM9263_ID_PIOB 3 ;# Parallel IO Controller B set AT91SAM9263_ID_PIOCDE 4 ;# Parallel IO Controller C, D and E set AT91SAM9263_ID_US0 7 ;# USART 0 set AT91SAM9263_ID_US1 8 ;# USART 1 set AT91SAM9263_ID_US2 9 ;# USART 2 set AT91SAM9263_ID_MCI0 10 ;# Multimedia Card Interface 0 set AT91SAM9263_ID_MCI1 11 ;# Multimedia Card Interface 1 set AT91SAM9263_ID_CAN 12 ;# CAN set AT91SAM9263_ID_TWI 13 ;# Two-Wire Interface set AT91SAM9263_ID_SPI0 14 ;# Serial Peripheral Interface 0 set AT91SAM9263_ID_SPI1 15 ;# Serial Peripheral Interface 1 set AT91SAM9263_ID_SSC0 16 ;# Serial Synchronous Controller 0 set AT91SAM9263_ID_SSC1 17 ;# Serial Synchronous Controller 1 set AT91SAM9263_ID_AC97C 18 ;# AC97 Controller set AT91SAM9263_ID_TCB 19 ;# Timer Counter 0, 1 and 2 set AT91SAM9263_ID_PWMC 20 ;# Pulse Width Modulation Controller set AT91SAM9263_ID_EMAC 21 ;# Ethernet set AT91SAM9263_ID_2DGE 23 ;# 2D Graphic Engine set AT91SAM9263_ID_UDP 24 ;# USB Device Port set AT91SAM9263_ID_ISI 25 ;# Image Sensor Interface set AT91SAM9263_ID_LCDC 26 ;# LCD Controller set AT91SAM9263_ID_DMA 27 ;# DMA Controller set AT91SAM9263_ID_UHP 29 ;# USB Host port set AT91SAM9263_ID_IRQ0 30 ;# Advanced Interrupt Controller (IRQ0) set AT91SAM9263_ID_IRQ1 31 ;# Advanced Interrupt Controller (IRQ1) # # User Peripheral physical base addresses. # set AT91SAM9263_BASE_UDP 0xfff78000 set AT91SAM9263_BASE_TCB0 0xfff7c000 set AT91SAM9263_BASE_TC0 0xfff7c000 set AT91SAM9263_BASE_TC1 0xfff7c040 set AT91SAM9263_BASE_TC2 0xfff7c080 set AT91SAM9263_BASE_MCI0 0xfff80000 set AT91SAM9263_BASE_MCI1 0xfff84000 set AT91SAM9263_BASE_TWI 0xfff88000 set AT91SAM9263_BASE_US0 0xfff8c000 set AT91SAM9263_BASE_US1 0xfff90000 set AT91SAM9263_BASE_US2 0xfff94000 set AT91SAM9263_BASE_SSC0 0xfff98000 set AT91SAM9263_BASE_SSC1 0xfff9c000 set AT91SAM9263_BASE_AC97C 0xfffa0000 set AT91SAM9263_BASE_SPI0 0xfffa4000 set AT91SAM9263_BASE_SPI1 0xfffa8000 set AT91SAM9263_BASE_CAN 0xfffac000 set AT91SAM9263_BASE_PWMC 0xfffb8000 set AT91SAM9263_BASE_EMAC 0xfffbc000 set AT91SAM9263_BASE_ISI 0xfffc4000 set AT91SAM9263_BASE_2DGE 0xfffc8000 set AT91_BASE_SYS 0xffffe000 # # System Peripherals (offset from AT91_BASE_SYS) # set AT91_ECC0 0xffffe000 set AT91_SDRAMC0 0xffffe200 set AT91_SMC0 0xffffe400 set AT91_ECC1 0xffffe600 set AT91_SDRAMC1 0xffffe800 set AT91_SMC1 0xffffea00 set AT91_MATRIX 0xffffec00 set AT91_CCFG 0xffffed10 set AT91_DBGU 0xffffee00 set AT91_AIC 0xfffff000 set AT91_PIOA 0xfffff200 set AT91_PIOB 0xfffff400 set AT91_PIOC 0xfffff600 set AT91_PIOD 0xfffff800 set AT91_PIOE 0xfffffa00 set AT91_PMC 0xfffffc00 set AT91_RSTC 0xfffffd00 set AT91_SHDWC 0xfffffd10 set AT91_RTT0 0xfffffd20 set AT91_PIT 0xfffffd30 set AT91_WDT 0xfffffd40 set AT91_RTT1 0xfffffd50 set AT91_GPBR 0xfffffd60 set AT91_USART0 $AT91SAM9263_BASE_US0 set AT91_USART1 $AT91SAM9263_BASE_US1 set AT91_USART2 $AT91SAM9263_BASE_US2 set AT91_SMC $AT91_SMC0 set AT91_SDRAMC $AT91_SDRAMC0 # # Internal Memory. # set AT91SAM9263_SRAM0_BASE 0x00300000 ;# Internal SRAM 0 base address set AT91SAM9263_SRAM0_SIZE 0x00014000 ;# Internal SRAM 0 size (80Kb) set AT91SAM9263_ROM_BASE 0x00400000 ;# Internal ROM base address set AT91SAM9263_ROM_SIZE 0x00020000 ;# Internal ROM size (128Kb) set AT91SAM9263_SRAM1_BASE 0x00500000 ;# Internal SRAM 1 base address set AT91SAM9263_SRAM1_SIZE 0x00004000 ;# Internal SRAM 1 size (16Kb) set AT91SAM9263_LCDC_BASE 0x00700000 ;# LCD Controller set AT91SAM9263_DMAC_BASE 0x00800000 ;# DMA Controller set AT91SAM9263_UHP_BASE 0x00a00000 ;# USB Host controller # # Cpu Name # set AT91_CPU_NAME "AT91SAM9263" openocd-0.9.0/tcl/chip/atmel/at91/at91_wdt.cfg0000644000175000017500000000162512526202235015575 00000000000000set AT91_WDT_CR [expr ($AT91_WDT + 0x00)] ;# Watchdog Control Register set AT91_WDT_WDRSTT [expr (1 << 0)] ;# Restart set AT91_WDT_KEY [expr (0xa5 << 24)] ;# KEY Password set AT91_WDT_MR [expr ($AT91_WDT + 0x04)] ;# Watchdog Mode Register set AT91_WDT_WDV [expr (0xfff << 0)] ;# Counter Value set AT91_WDT_WDFIEN [expr (1 << 12)] ;# Fault Interrupt Enable set AT91_WDT_WDRSTEN [expr (1 << 13)] ;# Reset Processor set AT91_WDT_WDRPROC [expr (1 << 14)] ;# Timer Restart set AT91_WDT_WDDIS [expr (1 << 15)] ;# Watchdog Disable set AT91_WDT_WDD [expr (0xfff << 16)] ;# Delta Value set AT91_WDT_WDDBGHLT [expr (1 << 28)] ;# Debug Halt set AT91_WDT_WDIDLEHLT [expr (1 << 29)] ;# Idle Halt set AT91_WDT_SR [expr ($AT91_WDT + 0x08)] ;# Watchdog Status Register set AT91_WDT_WDUNF [expr (1 << 0)] ;# Watchdog Underflow set AT91_WDT_WDERR [expr (1 << 1)] ;# Watchdog Error openocd-0.9.0/tcl/chip/atmel/at91/at91_pio.cfg0000644000175000017500000000246412526202235015570 00000000000000set PIO_PER 0x00 ;# Enable Register set PIO_PDR 0x04 ;# Disable Register set PIO_PSR 0x08 ;# Status Register set PIO_OER 0x10 ;# Output Enable Register set PIO_ODR 0x14 ;# Output Disable Register set PIO_OSR 0x18 ;# Output Status Register set PIO_IFER 0x20 ;# Glitch Input Filter Enable set PIO_IFDR 0x24 ;# Glitch Input Filter Disable set PIO_IFSR 0x28 ;# Glitch Input Filter Status set PIO_SODR 0x30 ;# Set Output Data Register set PIO_CODR 0x34 ;# Clear Output Data Register set PIO_ODSR 0x38 ;# Output Data Status Register set PIO_PDSR 0x3c ;# Pin Data Status Register set PIO_IER 0x40 ;# Interrupt Enable Register set PIO_IDR 0x44 ;# Interrupt Disable Register set PIO_IMR 0x48 ;# Interrupt Mask Register set PIO_ISR 0x4c ;# Interrupt Status Register set PIO_MDER 0x50 ;# Multi-driver Enable Register set PIO_MDDR 0x54 ;# Multi-driver Disable Register set PIO_MDSR 0x58 ;# Multi-driver Status Register set PIO_PUDR 0x60 ;# Pull-up Disable Register set PIO_PUER 0x64 ;# Pull-up Enable Register set PIO_PUSR 0x68 ;# Pull-up Status Register set PIO_ASR 0x70 ;# Peripheral A Select Register set PIO_BSR 0x74 ;# Peripheral B Select Register set PIO_ABSR 0x78 ;# AB Status Register set PIO_OWER 0xa0 ;# Output Write Enable Register set PIO_OWDR 0xa4 ;# Output Write Disable Register set PIO_OWSR 0xa8 ;# Output Write Status Register openocd-0.9.0/tcl/chip/atmel/at91/pmc.tcl0000644000175000017500000000052512526202236014742 00000000000000 if [info exists AT91C_MAINOSC_FREQ] { # user set this... let it be. } { # 18.432mhz is a common thing... set AT91C_MAINOSC_FREQ 18432000 } global AT91C_MAINOSC_FREQ if [info exists AT91C_SLOWOSC_FREQ] { # user set this... let it be. } { # 32khz is the norm set AT91C_SLOWOSC_FREQ 32768 } global AT91C_SLOWOSC_FREQ openocd-0.9.0/tcl/chip/atmel/at91/at91sam9_init.cfg0000644000175000017500000000772512526202236016544 00000000000000uplevel #0 [list source [find chip/atmel/at91/at91sam9_sdramc.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91_pmc.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91_pio.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91_rstc.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91_wdt.cfg]] proc at91sam9_reset_start { } { arm7_9 fast_memory_access disable jtag_rclk 8 halt wait_halt 10000 set rstc_mr_val [expr $::AT91_RSTC_KEY] set rstc_mr_val [expr ($rstc_mr_val | (5 << 8))] set rstc_mr_val [expr ($rstc_mr_val | $::AT91_RSTC_URSTEN)] mww $::AT91_RSTC_MR $rstc_mr_val ;# RSTC_MR : enable user reset. } proc at91sam9_reset_init { config } { mww $::AT91_WDT_MR $config(wdt_mr_val) ;# disable watchdog set ckgr_mor [expr ($::AT91_PMC_MOSCEN | (255 << 8))] mww $::AT91_CKGR_MOR $ckgr_mor ;# CKGR_MOR - enable main osc. while { [expr [mrw $::AT91_PMC_SR] & $::AT91_PMC_MOSCS] != $::AT91_PMC_MOSCS } { sleep 1 } set pllar_val [expr $::AT91_PMC_PLLA_WR_ERRATA] ;# Bit 29 must be 1 when prog set pllar_val [expr ($pllar_val | $::AT91_PMC_OUT)] set pllar_val [expr ($pllar_val | $::AT91_PMC_PLLCOUNT)] set pllar_val [expr ($pllar_val | ($config(master_pll_mul) - 1) << 16)] set pllar_val [expr ($pllar_val | $config(master_pll_div))] mww $::AT91_CKGR_PLLAR $pllar_val ;# CKGR_PLLA - (18.432MHz/13)*141 = 199.9 MHz while { [expr [mrw $::AT91_PMC_SR] & $::AT91_PMC_LOCKA] != $::AT91_PMC_LOCKA } { sleep 1 } ;# PCK/2 = MCK Master Clock from PLLA set mckr_val [expr $::AT91_PMC_CSS_PLLA] set mckr_val [expr ($mckr_val | $::AT91_PMC_PRES_1)] set mckr_val [expr ($mckr_val | $::AT91SAM9_PMC_MDIV_2)] set mckr_val [expr ($mckr_val | $::AT91_PMC_PDIV_1)] mww $::AT91_PMC_MCKR $mckr_val ;# PMC_MCKR (MCLK: 0x102 - (CLK/2)MHZ, 0x202 - (CLK/3)MHz) while { [expr [mrw $::AT91_PMC_SR] & $::AT91_PMC_MCKRDY] != $::AT91_PMC_MCKRDY } { sleep 1 } ## switch JTAG clock to highspeed clock jtag_rclk 0 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads arm7_9 fast_memory_access enable set rstc_mr_val [expr ($::AT91_RSTC_KEY)] set rstc_mr_val [expr ($rstc_mr_val | $::AT91_RSTC_URSTEN)] mww $::AT91_RSTC_MR $rstc_mr_val ;# user reset enable if { [info exists config(sdram_piod)] } { set pdr_addr [expr ($::AT91_PIOD + $::PIO_PDR)] set pudr_addr [expr ($::AT91_PIOD + $::PIO_PUDR)] set asr_addr [expr ($::AT91_PIOD + $::PIO_ASR)] mww $pdr_addr 0xffff0000 ;# define PDC[31:16] as DATA[31:16] mww $pudr_addr 0xffff0000 ;# no pull-up for D[31:16] mww $asr_addr 0xffff0000 } else { set pdr_addr [expr ($::AT91_PIOC + $::PIO_PDR)] set pudr_addr [expr ($::AT91_PIOC + $::PIO_PUDR)] mww $pdr_addr 0xffff0000 ;# define PDC[31:16] as DATA[31:16] mww $pudr_addr 0xffff0000 ;# no pull-up for D[31:16] } mww $config(matrix_ebicsa_addr) $config(matrix_ebicsa_val) mww $::AT91_SDRAMC_MR $::AT91_SDRAMC_MODE_NORMAL ;# SDRAMC_MR Mode register mww $::AT91_SDRAMC_TR $config(sdram_tr_val) ;# SDRAMC_TR - Refresh Timer register mww $::AT91_SDRAMC_CR $config(sdram_cr_val) ;# SDRAMC_CR - Configuration register mww $::AT91_SDRAMC_MDR $::AT91_SDRAMC_MD_SDRAM ;# Memory Device Register -> SDRAM mww $::AT91_SDRAMC_MR $::AT91_SDRAMC_MODE_PRECHARGE ;# SDRAMC_MR mww $config(sdram_base) 0 ;# SDRAM_BASE mww $::AT91_SDRAMC_MR $::AT91_SDRAMC_MODE_REFRESH ;# SDRC_MR mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $config(sdram_base) 0 ;# SDRAM_BASE mww $::AT91_SDRAMC_MR $::AT91_SDRAMC_MODE_LMR ;# SDRC_MR mww $config(sdram_base) 0 ;# SDRAM_BASE mww $::AT91_SDRAMC_MR $::AT91_SDRAMC_MODE_NORMAL ;# SDRC_MR mww $config(sdram_base) 0 ;# SDRAM_BASE mww $::AT91_SDRAMC_TR 1200 ;# SDRAM_TR mww $config(sdram_base) 0 ;# SDRAM_BASE mww $::AT91_MATRIX 0xf ;# MATRIX_MCFG - REMAP all masters } openocd-0.9.0/tcl/chip/atmel/at91/at91_pmc.cfg0000644000175000017500000001454712526202236015566 00000000000000set AT91_PMC_SCER [expr ($AT91_PMC + 0x00)] ;# System Clock Enable Register set AT91_PMC_SCDR [expr ($AT91_PMC + 0x04)] ;# System Clock Disable Register set AT91_PMC_SCSR [expr ($AT91_PMC + 0x08)] ;# System Clock Status Register set AT91_PMC_PCK [expr (1 << 0)] ;# Processor Clock set AT91RM9200_PMC_UDP [expr (1 << 1)] ;# USB Devcice Port Clock [AT91RM9200 only] set AT91RM9200_PMC_MCKUDP [expr (1 << 2)] ;# USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] set AT91CAP9_PMC_DDR [expr (1 << 2)] ;# DDR Clock [CAP9 revC & some SAM9 only] set AT91RM9200_PMC_UHP [expr (1 << 4)] ;# USB Host Port Clock [AT91RM9200 only] set AT91SAM926x_PMC_UHP [expr (1 << 6)] ;# USB Host Port Clock [AT91SAM926x only] set AT91CAP9_PMC_UHP [expr (1 << 6)] ;# USB Host Port Clock [AT91CAP9 only] set AT91SAM926x_PMC_UDP [expr (1 << 7)] ;# USB Devcice Port Clock [AT91SAM926x only] set AT91_PMC_PCK0 [expr (1 << 8)] ;# Programmable Clock 0 set AT91_PMC_PCK1 [expr (1 << 9)] ;# Programmable Clock 1 set AT91_PMC_PCK2 [expr (1 << 10)] ;# Programmable Clock 2 set AT91_PMC_PCK3 [expr (1 << 11)] ;# Programmable Clock 3 set AT91_PMC_HCK0 [expr (1 << 16)] ;# AHB Clock (USB host) [AT91SAM9261 only] set AT91_PMC_HCK1 [expr (1 << 17)] ;# AHB Clock (LCD) [AT91SAM9261 only] set AT91_PMC_PCER [expr ($AT91_PMC + 0x10)] ;# Peripheral Clock Enable Register set AT91_PMC_PCDR [expr ($AT91_PMC + 0x14)] ;# Peripheral Clock Disable Register set AT91_PMC_PCSR [expr ($AT91_PMC + 0x18)] ;# Peripheral Clock Status Register set AT91_CKGR_UCKR [expr ($AT91_PMC + 0x1C)] ;# UTMI Clock Register [some SAM9, CAP9] set AT91_PMC_UPLLEN [expr (1 << 16)] ;# UTMI PLL Enable set AT91_PMC_UPLLCOUNT [expr (0xf << 20)] ;# UTMI PLL Start-up Time set AT91_PMC_BIASEN [expr (1 << 24)] ;# UTMI BIAS Enable set AT91_PMC_BIASCOUNT [expr (0xf << 28)] ;# UTMI BIAS Start-up Time set AT91_CKGR_MOR [expr ($AT91_PMC + 0x20)] ;# Main Oscillator Register [not on SAM9RL] set AT91_PMC_MOSCEN [expr (1 << 0)] ;# Main Oscillator Enable set AT91_PMC_OSCBYPASS [expr (1 << 1)] ;# Oscillator Bypass [SAM9x, CAP9] set AT91_PMC_OSCOUNT [expr (0xff << 8)] ;# Main Oscillator Start-up Time set AT91_CKGR_MCFR [expr ($AT91_PMC + 0x24)] ;# Main Clock Frequency Register set AT91_PMC_MAINF [expr (0xffff << 0)] ;# Main Clock Frequency set AT91_PMC_MAINRDY [expr (1 << 16)] ;# Main Clock Ready set AT91_CKGR_PLLAR [expr ($AT91_PMC + 0x28)] ;# PLL A Register set AT91_CKGR_PLLBR [expr ($AT91_PMC + 0x2c)] ;# PLL B Register set AT91_PMC_DIV [expr (0xff << 0)] ;# Divider set AT91_PMC_PLLCOUNT [expr (0x3f << 8)] ;# PLL Counter set AT91_PMC_OUT [expr (3 << 14)] ;# PLL Clock Frequency Range set AT91_PMC_MUL [expr (0x7ff << 16)] ;# PLL Multiplier set AT91_PMC_USBDIV [expr (3 << 28)] ;# USB Divisor (PLLB only) set AT91_PMC_USBDIV_1 [expr (0 << 28)] set AT91_PMC_USBDIV_2 [expr (1 << 28)] set AT91_PMC_USBDIV_4 [expr (2 << 28)] set AT91_PMC_USB96M [expr (1 << 28)] ;# Divider by 2 Enable (PLLB only) set AT91_PMC_PLLA_WR_ERRATA [expr (1 << 29)] ;# Bit 29 must always be set to 1 when programming the CKGR_PLLAR register set AT91_PMC_MCKR [expr ($AT91_PMC + 0x30)] ;# Master Clock Register set AT91_PMC_CSS [expr (3 << 0)] ;# Master Clock Selection set AT91_PMC_CSS_SLOW [expr (0 << 0)] set AT91_PMC_CSS_MAIN [expr (1 << 0)] set AT91_PMC_CSS_PLLA [expr (2 << 0)] set AT91_PMC_CSS_PLLB [expr (3 << 0)] set AT91_PMC_CSS_UPLL [expr (3 << 0)] ;# [some SAM9 only] set AT91_PMC_PRES [expr (7 << 2)] ;# Master Clock Prescaler set AT91_PMC_PRES_1 [expr (0 << 2)] set AT91_PMC_PRES_2 [expr (1 << 2)] set AT91_PMC_PRES_4 [expr (2 << 2)] set AT91_PMC_PRES_8 [expr (3 << 2)] set AT91_PMC_PRES_16 [expr (4 << 2)] set AT91_PMC_PRES_32 [expr (5 << 2)] set AT91_PMC_PRES_64 [expr (6 << 2)] set AT91_PMC_MDIV [expr (3 << 8)] ;# Master Clock Division set AT91RM9200_PMC_MDIV_1 [expr (0 << 8)] ;# [AT91RM9200 only] set AT91RM9200_PMC_MDIV_2 [expr (1 << 8)] set AT91RM9200_PMC_MDIV_3 [expr (2 << 8)] set AT91RM9200_PMC_MDIV_4 [expr (3 << 8)] set AT91SAM9_PMC_MDIV_1 [expr (0 << 8)] ;# [SAM9,CAP9 only] set AT91SAM9_PMC_MDIV_2 [expr (1 << 8)] set AT91SAM9_PMC_MDIV_4 [expr (2 << 8)] set AT91SAM9_PMC_MDIV_6 [expr (3 << 8)] ;# [some SAM9 only] set AT91SAM9_PMC_MDIV_3 [expr (3 << 8)] ;# [some SAM9 only] set AT91_PMC_PDIV [expr (1 << 12)] ;# Processor Clock Division [some SAM9 only] set AT91_PMC_PDIV_1 [expr (0 << 12)] set AT91_PMC_PDIV_2 [expr (1 << 12)] set AT91_PMC_PLLADIV2 [expr (1 << 12)] ;# PLLA divisor by 2 [some SAM9 only] set AT91_PMC_PLLADIV2_OFF [expr (0 << 12)] set AT91_PMC_PLLADIV2_ON [expr (1 << 12)] set AT91_PMC_USB [expr ($AT91_PMC + 0x38)] ;# USB Clock Register [some SAM9 only] set AT91_PMC_USBS [expr (0x1 << 0)] ;# USB OHCI Input clock selection set AT91_PMC_USBS_PLLA [expr (0 << 0)] set AT91_PMC_USBS_UPLL [expr (1 << 0)] set AT91_PMC_OHCIUSBDIV [expr (0xF << 8)] ;# Divider for USB OHCI Clock ;# set AT91_PMC_PCKR(n) [expr ($AT91_PMC + 0x40 + ((n) * 4))] ;# Programmable Clock 0-N Registers set AT91_PMC_CSSMCK [expr (0x1 << 8)] ;# CSS or Master Clock Selection set AT91_PMC_CSSMCK_CSS [expr (0 << 8)] set AT91_PMC_CSSMCK_MCK [expr (1 << 8)] set AT91_PMC_IER [expr ($AT91_PMC + 0x60)] ;# Interrupt Enable Register set AT91_PMC_IDR [expr ($AT91_PMC + 0x64)] ;# Interrupt Disable Register set AT91_PMC_SR [expr ($AT91_PMC + 0x68)] ;# Status Register set AT91_PMC_MOSCS [expr (1 << 0)] ;# MOSCS Flag set AT91_PMC_LOCKA [expr (1 << 1)] ;# PLLA Lock set AT91_PMC_LOCKB [expr (1 << 2)] ;# PLLB Lock set AT91_PMC_MCKRDY [expr (1 << 3)] ;# Master Clock set AT91_PMC_LOCKU [expr (1 << 6)] ;# UPLL Lock [some SAM9, AT91CAP9 only] set AT91_PMC_OSCSEL [expr (1 << 7)] ;# Slow Clock Oscillator [AT91CAP9 revC only] set AT91_PMC_PCK0RDY [expr (1 << 8)] ;# Programmable Clock 0 set AT91_PMC_PCK1RDY [expr (1 << 9)] ;# Programmable Clock 1 set AT91_PMC_PCK2RDY [expr (1 << 10)] ;# Programmable Clock 2 set AT91_PMC_PCK3RDY [expr (1 << 11)] ;# Programmable Clock 3 set AT91_PMC_IMR [expr ($AT91_PMC + 0x6c)] ;# Interrupt Mask Register set AT91_PMC_PROT [expr ($AT91_PMC + 0xe4)] ;# Protect Register [AT91CAP9 revC only] set AT91_PMC_PROTKEY 0x504d4301 ;# Activation Code set AT91_PMC_VER [expr ($AT91_PMC + 0xfc)] ;# PMC Module Version [AT91CAP9 only] openocd-0.9.0/tcl/cpld/0000755000175000017500000000000012526202236011654 500000000000000openocd-0.9.0/tcl/cpld/xilinx-xcr3256.cfg0000644000175000017500000000022412526202236014700 00000000000000#xilinx coolrunner xcr3256 #simple device - just configure a tap jtag newtap xcr tap -irlen 5 -ircapture 0x01 -irmask 0x1f -expected-id 0x0494c093 openocd-0.9.0/tcl/cpld/lattice-lc4032ze.cfg0000644000175000017500000000020312526202236015141 00000000000000# Lattice ispMACH 4000ZE family, device LC4032ZE # just configure a tap jtag newtap LC4032ZE tap -irlen 8 -expected-id 0x01806043 openocd-0.9.0/tcl/test/0000755000175000017500000000000012526202236011711 500000000000000openocd-0.9.0/tcl/test/selftest.cfg0000644000175000017500000000063512526202236014147 00000000000000 add_help_text selftest "run selftest using working ram
" proc selftest {tmpfile address size} { for {set i 0} {$i < $size } {set i [expr $i+4]} { mww [expr $address+$i] $i } for {set i 0} {$i < 10 } {set i [expr $i+1]} { echo "Test iteration $i" dump_image $tmpfile $address $size verify_image $tmpfile $address bin load_image $tmpfile $address bin } } openocd-0.9.0/tcl/test/syntax1.cfg0000644000175000017500000000152512526202236013724 00000000000000adapter_nsrst_delay 200 jtag_ntrst_delay 200 #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst #LPCs need reset pulled while RTCK is low. 0 to activate JTAG, power-on reset is not enough jtag_reset 1 1 jtag_reset 0 0 #jtag scan chain #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag newtap lpc2148 one -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4f1f0f0f #target configuration #daemon_startup reset set _TARGETNAME [format "%s.cpu" lpc2148] target create lpc2148.cpu arm7tdmi -endian little -work-area-size 0x4000 -work-area-phys 0x40000000 -work-area-backup 0 $_TARGETNAME configure -event reset-init { soft_reset_halt mvb 0xE01FC040 0x01 } set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME lpc2000 0x0 0x7d000 0 0 0 lpc2000_v2 14765 openocd-0.9.0/tcl/memory.tcl0000644000175000017500000000671612526202236012700 00000000000000# MEMORY # # All Memory regions have two components. # (1) A count of regions, in the form N_NAME # (2) An array within info about each region. # # The ARRAY # # ( RegionNumber , ATTRIBUTE ) # # Where is one of: # # N_FLASH & FLASH (internal memory) # N_RAM & RAM (internal memory) # N_MMREGS & MMREGS (for memory mapped registers) # N_XMEM & XMEM (off chip memory, ie: flash on cs0, sdram on cs2) # or N_UNKNOWN & UNKNOWN for things that do not exist. # # We have 1 unknown region. set N_UNKNOWN 1 # All MEMORY regions must have these attributes # CS - chip select (if internal, use -1) set UNKNOWN(0,CHIPSELECT) -1 # BASE - base address in memory set UNKNOWN(0,BASE) 0 # LEN - length in bytes set UNKNOWN(0,LEN) $CPU_MAX_ADDRESS # HUMAN - human name of the region set UNKNOWN(0,HUMAN) "unknown" # TYPE - one of: # flash, ram, mmr, unknown # For harvard arch: # iflash, dflash, iram, dram set UNKNOWN(0,TYPE) "unknown" # RWX - access ablity # unix style chmod bits # 0 - no access # 1 - execute # 2 - write # 4 - read # hence: 7 - readwrite execute set RWX_NO_ACCESS 0 set RWX_X_ONLY $BIT0 set RWX_W_ONLY $BIT1 set RWX_R_ONLY $BIT2 set RWX_RW [expr $RWX_R_ONLY + $RWX_W_ONLY] set RWX_R_X [expr $RWX_R_ONLY + $RWX_X_ONLY] set RWX_RWX [expr $RWX_R_ONLY + $RWX_W_ONLY + $RWX_X_ONLY] set UNKNOWN(0,RWX) $RWX_NO_ACCESS # WIDTH - access width # 8,16,32 [0 means ANY] set ACCESS_WIDTH_NONE 0 set ACCESS_WIDTH_8 $BIT0 set ACCESS_WIDTH_16 $BIT1 set ACCESS_WIDTH_32 $BIT2 set ACCESS_WIDTH_ANY [expr $ACCESS_WIDTH_8 + $ACCESS_WIDTH_16 + $ACCESS_WIDTH_32] set UNKNOWN(0,ACCESS_WIDTH) $ACCESS_WIDTH_NONE proc iswithin { ADDRESS BASE LEN } { return [expr ((($ADDRESS - $BASE) > 0) && (($ADDRESS - $BASE + $LEN) > 0))] } proc address_info { ADDRESS } { foreach WHERE { FLASH RAM MMREGS XMEM UNKNOWN } { if { info exists $WHERE } { set lmt [set N_[set WHERE]] for { set region 0 } { $region < $lmt } { incr region } { if { iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN) } { return "$WHERE $region"; } } } } # Return the 'unknown' return "UNKNOWN 0" } proc memread32 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { return $foo(0) } else { error "memread32: $msg" } } proc memread16 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { return $foo(0) } else { error "memread16: $msg" } } proc memread8 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { return $foo(0) } else { error "memread8: $msg" } } proc memwrite32 {ADDR DATA} { set foo(0) $DATA if ![ catch { array2mem foo 32 $ADDR 1 } msg ] { return $foo(0) } else { error "memwrite32: $msg" } } proc memwrite16 {ADDR DATA} { set foo(0) $DATA if ![ catch { array2mem foo 16 $ADDR 1 } msg ] { return $foo(0) } else { error "memwrite16: $msg" } } proc memwrite8 {ADDR DATA} { set foo(0) $DATA if ![ catch { array2mem foo 8 $ADDR 1 } msg ] { return $foo(0) } else { error "memwrite8: $msg" } } openocd-0.9.0/tcl/board/0000755000175000017500000000000012526202243012017 500000000000000openocd-0.9.0/tcl/board/stm32439i_eval_stlink.cfg0000644000175000017500000000066112526202236016401 00000000000000# STM32439I-EVAL: This is an STM32F4 eval board with a single STM32F439NIH6 # (2048KB) chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1199/PF259094 # # This is for using the onboard STLINK/V2 source [find interface/stlink-v2.cfg] transport select hla_swd # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F439NIH6 source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/ek-tm4c1294xl.cfg0000644000175000017500000000037712526202236014561 00000000000000# # TI Tiva C Series ek-tm4c1294xl Launchpad Evaluation Kit # # http://www.ti.com/tool/ek-tm4c1294xl # source [find interface/ti-icdi.cfg] transport select hla_jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c1294ncpdt source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/ti_beaglebone.cfg0000644000175000017500000000034512526202236015203 00000000000000# AM335x Beaglebone # http://beagleboard.org/bone # The JTAG interface is built directly on the board. source [find interface/ftdi/xds100v2.cfg] adapter_khz 16000 source [find target/am335x.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/phone_se_j100i.cfg0000644000175000017500000000042112526202236015122 00000000000000# # Sony Ericsson J100I Phone # # more informations can be found on # http://bb.osmocom.org/trac/wiki/SonyEricssonJ100i # source [find target/ti_calypso.cfg] # external flash set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x400000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/ti_beagleboard_xm.cfg0000644000175000017500000000042212526202236016047 00000000000000# BeagleBoard xM (DM37x) # http://beagleboard.org set CHIPTYPE "dm37x" source [find target/amdm37x.cfg] # The TI-14 JTAG connector does not have srst. CPU reset is handled in # hardware. reset_config trst_only # "amdm37x_dbginit dm37x.cpu" needs to be run after init. openocd-0.9.0/tcl/board/ek-lm3s8962.cfg0000644000175000017500000000057512526202236014235 00000000000000# # TI/Luminary Stellaris LM3S8962 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s8962 # # NOTE: using the on-board FT2232 JTAG/SWD/SWO interface is optional! # so is using it in JTAG mode, as done here. source [find interface/ftdi/luminary.cfg] # 64k working area set WORKAREASIZE 0x10000 set CHIPNAME lm3s8962 # include the target config source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/imx27lnst.cfg0000644000175000017500000000251112526202236014270 00000000000000# The Linuxstamp-mx27 is board has a single IMX27 chip # For further info see http://opencircuits.com/Linuxstamp_mx27#OpenOCD source [find target/imx27.cfg] $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { imx27lnst_init } proc imx27lnst_init { } { # This setup puts RAM at 0xA0000000 # reset the board correctly adapter_khz 500 reset run reset halt mww 0x10000000 0x20040304 mww 0x10020000 0x00000000 mww 0x10000004 0xDFFBFCFB mww 0x10020004 0xFFFFFFFF sleep 100 # ======================================== # Configure DDR on CSD0 -- initial reset # ======================================== mww 0xD8001010 0x00000008 sleep 100 # ======================================== # Configure DDR on CSD0 -- wait 5000 cycle # ======================================== mww 0x10027828 0x55555555 mww 0x10027830 0x55555555 mww 0x10027834 0x55555555 mww 0x10027838 0x00005005 mww 0x1002783C 0x15555555 mww 0xD8001010 0x00000004 mww 0xD8001004 0x00795729 #mww 0xD8001000 0x92200000 mww 0xD8001000 0x91120000 mww 0xA0000F00 0x0 #mww 0xD8001000 0xA2200000 mww 0xD8001000 0xA1120000 mww 0xA0000F00 0x0 mww 0xA0000F00 0x0 #mww 0xD8001000 0xB2200000 mww 0xD8001000 0xB1120000 mwb 0xA0000033 0xFF mwb 0xA1000000 0xAA #mww 0xD8001000 0x82228085 mww 0xD8001000 0x81128080 } openocd-0.9.0/tcl/board/mbed-lpc1768.cfg0000644000175000017500000000026412526202236014435 00000000000000# This is an mbed eval board with a single NXP LPC1768 chip. # http://mbed.org/handbook/mbed-NXP-LPC1768 # source [find interface/cmsis-dap.cfg] source [find target/lpc17xx.cfg] openocd-0.9.0/tcl/board/digilent_zedboard.cfg0000644000175000017500000000034412526202237016075 00000000000000# # Digilent Zedboard Rev.C, Rev.D with Xilinx Zynq chip # # http://zedboard.com/product/zedboard # source [find interface/ftdi/digilent_jtag_smt2.cfg] reset_config srst_only srst_push_pull source [find target/zynq_7000.cfg] openocd-0.9.0/tcl/board/hammer.cfg0000644000175000017500000000206712526202237013701 00000000000000# Target Configuration for the TinCanTools S3C2410 Based Hammer Module # http://www.tincantools.com source [find target/samsung_s3c2410.cfg] $_TARGETNAME configure -event reset-init { # Reset Script for the TinCanTools S3C2410 Based Hammer Module # http://www.tincantools.com # # Setup primary clocks and initialize the SDRAM mww 0x53000000 0x00000000 mww 0x4a000008 0xffffffff mww 0x4a00000c 0x000007ff mww 0x4c000000 0x00ffffff mww 0x4c000014 0x00000003 mww 0x4c000004 0x000a1031 mww 0x48000000 0x11111122 mww 0x48000004 0x00000700 mww 0x48000008 0x00000700 mww 0x4800000c 0x00000700 mww 0x48000010 0x00000700 mww 0x48000014 0x00000700 mww 0x48000018 0x00000700 mww 0x4800001c 0x00018005 mww 0x48000020 0x00018005 mww 0x48000024 0x009c0459 mww 0x48000028 0x000000b2 mww 0x4800002c 0x00000030 mww 0x48000030 0x00000030 flash probe 0 } #flash configuration #flash bank [driver_options ...] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x1000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/efm32.cfg0000644000175000017500000000057312526202237013344 00000000000000# Configuration for EFM32 boards with Segger J-Link on board # # Tested with TINY GECKO and Zero Gecko demo board # source [find interface/jlink.cfg] transport select swd adapter_khz 1000 set CHIPNAME efm32 source [find target/efm32.cfg] # EFM32 SWD doesn't work with RST asserted # So don't use srst_nogate! # Attach to running target with "mon halt" reset_config srst_only openocd-0.9.0/tcl/board/arm_evaluator7t.cfg0000644000175000017500000000030312526202237015533 00000000000000# This board is from ARM and has an samsung s3c45101x01 chip source [find target/samsung_s3c4510.cfg] # # FIXME: # Add (A) sdram configuration # Add (B) flash cfi programing configuration # openocd-0.9.0/tcl/board/stm320518_eval_stlink.cfg0000644000175000017500000000063512526202237016310 00000000000000# STM320518-EVAL: This is an STM32F0 eval board with a single STM32F051R8T6 # (64KB) chip. # http://www.st.com/internet/evalboard/product/252994.jsp # # This is for using the onboard STLINK/V2 source [find interface/stlink-v2.cfg] transport select hla_swd # increase working area to 8KB set WORKAREASIZE 0x2000 # chip name set CHIPNAME STM32F051R8T6 source [find target/stm32f0x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/imx53-m53evk.cfg0000644000175000017500000002116312526202237014503 00000000000000####################################### # DENX M53EVK # # http://www.denx-cs.de/?q=M53EVK # # Author: Marek Vasut # # Based on imx53loco.cfg # ####################################### # The DENX M53EVK has on-board JTAG adapter source [find interface/ftdi/m53evk.cfg] # The DENX M53EVK board has a single i.MX53 chip source [find target/imx53.cfg] # Helper for common memory read/modify/write procedures source [find mem_helper.tcl] echo "iMX53 M53EVK board lodaded." # Set reset type reset_config trst_and_srst separate trst_open_drain srst_open_drain # Run at 6 MHz adapter_khz 6000 $_TARGETNAME configure -event "reset-assert" { echo "Reseting ...." #cortex_a dbginit } $_TARGETNAME configure -event reset-init { m53evk_init } global AIPS1_BASE_ADDR set AIPS1_BASE_ADDR 0x53F00000 global AIPS2_BASE_ADDR set AIPS2_BASE_ADDR 0x63F00000 proc m53evk_init { } { echo "Reset-init..." ; # halt the CPU halt echo "HW version [format %x [mrw 0x48]]" dap apsel 1 DCD ; # ARM errata ID #468414 set tR [arm mrc 15 0 1 0 1] arm mcr 15 0 1 0 1 [expr $tR | (1<<5)] ; # enable L1NEON bit init_l2cc init_aips init_clock dap apsel 0 ; # Force ARM state ; #reg cpsr 0x000001D3 arm core_state arm } # L2CC Cache setup/invalidation/disable proc init_l2cc { } { ; #/* explicitly disable L2 cache */ ; #mrc 15, 0, r0, c1, c0, 1 set tR [arm mrc 15 0 1 0 1] ; #bic r0, r0, #0x2 ; #mcr 15, 0, r0, c1, c0, 1 arm mcr 15 0 1 0 1 [expr $tR & ~(1<<2)] ; #/* reconfigure L2 cache aux control reg */ ; #mov r0, #0xC0 /* tag RAM */ ; #add r0, r0, #0x4 /* data RAM */ ; #orr r0, r0, #(1 << 24) /* disable write allocate delay */ ; #orr r0, r0, #(1 << 23) /* disable write allocate combine */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] } # AIPS setup - Only setup MPROTx registers. # The PACR default values are good. proc init_aips { } { ; # Set all MPROTx to be non-bufferable, trusted for R/W, ; # not forced to user-mode. global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set VAL 0x77777777 # dap apsel 1 mww [expr $AIPS1_BASE_ADDR + 0x0] $VAL mww [expr $AIPS1_BASE_ADDR + 0x4] $VAL mww [expr $AIPS2_BASE_ADDR + 0x0] $VAL mww [expr $AIPS2_BASE_ADDR + 0x4] $VAL # dap apsel 0 } proc init_clock { } { global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set CCM_BASE_ADDR [expr $AIPS1_BASE_ADDR + 0x000D4000] set CLKCTL_CCSR 0x0C set CLKCTL_CBCDR 0x14 set CLKCTL_CBCMR 0x18 set PLL1_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00080000] set PLL2_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00084000] set PLL3_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00088000] set PLL4_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x0008C000] set CLKCTL_CSCMR1 0x1C set CLKCTL_CDHIPR 0x48 set PLATFORM_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x000A0000] set CLKCTL_CSCDR1 0x24 set CLKCTL_CCDR 0x04 ; # Switch ARM to step clock mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x4 return echo "not returned" setup_pll $PLL1_BASE_ADDR 800 setup_pll $PLL3_BASE_ADDR 400 ; # Switch peripheral to PLL3 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00015154 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x02888945 | (1<<16)] while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL2_BASE_ADDR 400 ; # Switch peripheral to PLL2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x00808145 | (2<<10) | (9<<16) | (1<<19)] mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00016154 ; # change uart clk parent to pll2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1]] & 0xfcffffff | 0x01000000] ; # make sure change is effective while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL3_BASE_ADDR 216 setup_pll $PLL4_BASE_ADDR 455 ; # Set the platform clock dividers mww [expr $PLATFORM_BASE_ADDR + 0x14] 0x00000124 mww [expr $CCM_BASE_ADDR + 0x10] 0 ; # Switch ARM back to PLL 1. mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x0 ; # make uart div=6 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1]] & 0xffffffc0 | 0x0a] ; # Restore the default values in the Gate registers mww [expr $CCM_BASE_ADDR + 0x68] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x6C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x70] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x74] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x78] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x7C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x80] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x84] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + $CLKCTL_CCDR] 0x00000 ; # for cko - for ARM div by 8 mww [expr $CCM_BASE_ADDR + 0x60] [expr 0x000A0000 & 0x00000F0] } proc setup_pll { PLL_ADDR CLK } { set PLL_DP_CTL 0x00 set PLL_DP_CONFIG 0x04 set PLL_DP_OP 0x08 set PLL_DP_HFS_OP 0x1C set PLL_DP_MFD 0x0C set PLL_DP_HFS_MFD 0x20 set PLL_DP_MFN 0x10 set PLL_DP_HFS_MFN 0x24 if {$CLK == 1000} { set DP_OP [expr (10 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (12 - 1)] set DP_MFN 5 } elseif {$CLK == 850} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 41 } elseif {$CLK == 800} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 700} { set DP_OP [expr (7 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 7 } elseif {$CLK == 600} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 1 } elseif {$CLK == 665} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (96 - 1)] set DP_MFN 89 } elseif {$CLK == 532} { set DP_OP [expr (5 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 13 } elseif {$CLK == 455} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 71 } elseif {$CLK == 400} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 216} { set DP_OP [expr (6 << 4) + ((3 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 3 } else { error "Error (setup_dll): clock not found!" } mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 mww [expr $PLL_ADDR + $PLL_DP_CONFIG] 0x2 mww [expr $PLL_ADDR + $PLL_DP_OP] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_HFS_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 while {[expr [mrw [expr $PLL_ADDR + $PLL_DP_CTL]] & 0x1] == 0} { sleep 1 } } proc CPU_2_BE_32 { L } { return [expr (($L & 0x000000FF) << 24) | (($L & 0x0000FF00) << 8) | (($L & 0x00FF0000) >> 8) | (($L & 0xFF000000) >> 24)] } # Device Configuration Data proc DCD { } { # dap apsel 1 mww 0x53fa86f4 0x00000000 ;# GRP_DDRMODE_CTL mww 0x53fa8714 0x00000000 ;# GRP_DDRMODE mww 0x53fa86fc 0x00000000 ;# GRP_DDRPKE mww 0x53fa8724 0x04000000 ;# GRP_DDR_TYPE mww 0x53fa872c 0x00300000 ;# GRP_B3DS mww 0x53fa8554 0x00300000 ;# DRAM_DQM3 mww 0x53fa8558 0x00300040 ;# DRAM_SDQS3 mww 0x53fa8728 0x00300000 ;# GRP_B2DS mww 0x53fa8560 0x00300000 ;# DRAM_DQM2 mww 0x53fa8568 0x00300040 ;# DRAM_SDQS2 mww 0x53fa871c 0x00300000 ;# GRP_B1DS mww 0x53fa8594 0x00300000 ;# DRAM_DQM1 mww 0x53fa8590 0x00300040 ;# DRAM_SDQS1 mww 0x53fa8718 0x00300000 ;# GRP_B0DS mww 0x53fa8584 0x00300000 ;# DRAM_DQM0 mww 0x53fa857c 0x00300040 ;# DRAM_SDQS0 mww 0x53fa8578 0x00300000 ;# DRAM_SDCLK_0 mww 0x53fa8570 0x00300000 ;# DRAM_SDCLK_1 mww 0x53fa8574 0x00300000 ;# DRAM_CAS mww 0x53fa8588 0x00300000 ;# DRAM_RAS mww 0x53fa86f0 0x00300000 ;# GRP_ADDDS mww 0x53fa8720 0x00300000 ;# GRP_CTLDS mww 0x53fa8564 0x00300040 ;# DRAM_SDODT1 mww 0x53fa8580 0x00300040 ;# DRAM_SDODT0 # Initialize DDR2 memory mww 0x63fd9088 0x32383535 mww 0x63fd9090 0x40383538 mww 0x63fd907c 0x0136014d mww 0x63fd9080 0x01510141 mww 0x63fd9018 0x00011740 mww 0x63fd9000 0xc3190000 mww 0x63fd900c 0x555952e3 mww 0x63fd9010 0xb68e8b63 mww 0x63fd9014 0x01ff00db mww 0x63fd902c 0x000026d2 mww 0x63fd9030 0x009f0e21 mww 0x63fd9008 0x12273030 mww 0x63fd9004 0x0002002d mww 0x63fd901c 0x00008032 mww 0x63fd901c 0x00008033 mww 0x63fd901c 0x00028031 mww 0x63fd901c 0x092080b0 mww 0x63fd901c 0x04008040 mww 0x63fd901c 0x0000803a mww 0x63fd901c 0x0000803b mww 0x63fd901c 0x00028039 mww 0x63fd901c 0x09208138 mww 0x63fd901c 0x04008048 mww 0x63fd9020 0x00001800 mww 0x63fd9040 0x04b80003 mww 0x63fd9058 0x00022227 mww 0x63fd901c 0x00000000 # dap apsel 0 } # vim:filetype=tcl openocd-0.9.0/tcl/board/atmel_samd20_xplained_pro.cfg0000644000175000017500000000032412526202237017436 00000000000000# # Atmel SAMD20 Xplained Pro evaluation kit. # http://www.atmel.com/tools/ATSAMD20-XPRO.aspx # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME at91samd20j18 source [find target/at91samdXX.cfg] openocd-0.9.0/tcl/board/hilscher_nxhx500.cfg0000644000175000017500000000203412526202237015515 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx500.cfg] reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x1000 -work-area-phys 0x1000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -event reset-init { halt arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable sleep 100 sdram_fix puts "Configuring SDRAM controller for MT48LC2M32 (8MB) " mww 0x00100140 0 mww 0x00100144 0x03C23251 mww 0x00100140 0x030D0001 puts "Configuring SRAM nCS0 for 90ns Par. Flash (x16)" mww 0x00100100 0x01010008 flash probe 0 } ##################### # Flash configuration ##################### #flash bank flash bank parflash cfi 0xC0000000 0x01000000 2 2 $_TARGETNAME init reset init openocd-0.9.0/tcl/board/actux3.cfg0000644000175000017500000000410412526202237013631 00000000000000# board config file for AcTux3/XBA IXP42x board # Date: 2010-12-16 # Author: Michael Schwingen reset_config trst_and_srst separate adapter_nsrst_delay 100 jtag_ntrst_delay 100 source [find target/ixp42x.cfg] $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 0x10000 -work-area-backup 0 $_TARGETNAME configure -event reset-init { init_actux3 } proc init_actux3 { } { ########################################################################## # setup expansion bus CS ########################################################################## mww 0xc4000000 0xbd113842 ;#CS0 : Flash, write enabled @0x50000000 mww 0xc4000004 0x94d10013 ;#CS1 mww 0xc4000008 0x95960003 ;#CS2 mww 0xc400000c 0x00000000 ;#CS3 mww 0xc4000010 0x80900003 ;#CS4 mww 0xc4000014 0x9d520003 ;#CS5 mww 0xc4000018 0x81860001 ;#CS6 mww 0xc400001c 0x80900003 ;#CS7 ixp42x_init_sdram $::IXP42x_SDRAM_16MB_4Mx16_1BANK 2100 3 #mww 0xc4000020 0xffffee ;# CFG0: remove expansion bus boot flash mirror at 0x00000000 ixp42x_set_bigendian flash probe 0 } proc flash_boot { {FILE "/tftpboot/actux3/u-boot.bin"} } { echo "writing bootloader: $FILE" flash write_image erase $FILE 0x50000000 bin } set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x50000000 0x400000 2 2 $_TARGETNAME init reset init # setup to debug u-boot in flash proc uboot_debug {} { gdb_breakpoint_override hard xscale vector_catch 0xFF xscale vector_table low 1 0xe59ff018 xscale vector_table low 2 0xe59ff018 xscale vector_table low 3 0xe59ff018 xscale vector_table low 4 0xe59ff018 xscale vector_table low 5 0xe59ff018 xscale vector_table low 6 0xe59ff018 xscale vector_table low 7 0xe59ff018 xscale vector_table high 1 0xe59ff018 xscale vector_table high 2 0xe59ff018 xscale vector_table high 3 0xe59ff018 xscale vector_table high 4 0xe59ff018 xscale vector_table high 5 0xe59ff018 xscale vector_table high 6 0xe59ff018 xscale vector_table high 7 0xe59ff018 } openocd-0.9.0/tcl/board/spansion_sk-fm4-176l-s6e2cc.cfg0000644000175000017500000000036012526202237017207 00000000000000# # Spansion SK-FM4-176L-S6E2CC # # # FM3 MB9AF312K # source [find interface/cmsis-dap.cfg] # There's also an unpopulated 10-pin 0.05" pinout. # # FM4 S6E2CCAJ0A # set CHIPNAME s6e2cc source [find target/fm4.cfg] reset_config srst_only openocd-0.9.0/tcl/board/stm32vldiscovery.cfg0000644000175000017500000000042312526202237015664 00000000000000# This is an STM32VL discovery board with a single STM32F100RB chip. # http://www.st.com/internet/evalboard/product/250863.jsp source [find interface/stlink-v1.cfg] transport select hla_swd set WORKAREASIZE 0x2000 source [find target/stm32f1x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/hitex_stm32-performancestick.cfg0000644000175000017500000000066112526202237020134 00000000000000# Hitex stm32 performance stick reset_config trst_and_srst source [find interface/ftdi/stm32-stick.cfg] set CHIPNAME stm32_hitex source [find target/stm32f1x.cfg] # configure str750 connected to jtag chain # FIXME -- source [find target/str750.cfg] after cleaning that up jtag newtap str750 cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id 0x4f1f0041 # for some reason this board like to startup @ 500kHz adapter_khz 500 openocd-0.9.0/tcl/board/olimex_stm32_h103.cfg0000644000175000017500000000027512526202237015507 00000000000000# Olimex STM32-H103 eval board # http://olimex.com/dev/stm32-h103.html # Work-area size (RAM size) = 20kB for STM32F103RB device set WORKAREASIZE 0x5000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/hitex_lpc1768stick.cfg0000644000175000017500000000032312526202237015764 00000000000000# Hitex LPC1768 Stick # # http://www.hitex.com/?id=1602 # reset_config trst_and_srst source [find interface/ftdi/hitex_lpc1768stick.cfg] source [find target/lpc17xx.cfg] # startup @ 500kHz adapter_khz 500 openocd-0.9.0/tcl/board/olimex_stm32_h107.cfg0000644000175000017500000000027112526202237015507 00000000000000# # Olimex STM32-H107 # # http://olimex.com/dev/stm32-h107.html # # Work-area size (RAM size) = 64kB for STM32F107VC device set WORKAREASIZE 0x10000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/hitex_str9-comstick.cfg0000644000175000017500000000420412526202237016337 00000000000000# Hitex STR9-comStick # http://www.hitex.com/index.php?id=383 # This works for the STR9-comStick revisions STR912CS-A1 and STR912CS-A2. source [find interface/ftdi/hitex_str9-comstick.cfg] # set jtag speed adapter_khz 3000 adapter_nsrst_delay 100 jtag_ntrst_delay 100 #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst # # FIXME use the standard str912 target config; that script might need # updating to "-ignore-version" for the boundary scan TAP # # source [find target/str912.cfg] # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str912 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists FLASHTAPID] } { set _FLASHTAPID $FLASHTAPID } else { set _FLASHTAPID 0x04570041 } jtag newtap $_CHIPNAME flash -irlen 8 -ircapture 0x1 -irmask 0x1 -expected-id $_FLASHTAPID if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x25966041 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { # Found on STR9-comStick, revision STR912CS-A1 set _BSTAPID1 0x1457f041 # Found on STR9-comStick, revision STR912CS-A2 set _BSTAPID2 0x2457f041 } jtag newtap $_CHIPNAME bs -irlen 5 -ircapture 0x1 -irmask 0x1 -expected-id $_BSTAPID1 -expected-id $_BSTAPID2 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { # We can increase speed now that we know the target is halted. #jtag_rclk 3000 # -- Enable 96K RAM # PFQBC enabled / DTCM & AHB wait-states disabled mww 0x5C002034 0x0191 str9x flash_config 0 4 2 0 0x80000 flash protect 0 0 7 off } $_TARGETNAME configure -work-area-phys 0x50000000 -work-area-size 16384 -work-area-backup 0 #flash bank set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME str9x 0x00000000 0x00080000 0 0 0 set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME str9x 0x00080000 0x00008000 0 0 0 openocd-0.9.0/tcl/board/iar_lpc1768.cfg0000644000175000017500000000055212526202240014356 00000000000000# Board from IAR KickStart Kit for LPC1768 # See www.iar.com and also # http://www.olimex.com/dev/lpc-1766stk.html # source [find target/lpc17xx.cfg] # The chip has just been reset. # $_TARGETNAME configure -event reset-init { # FIXME update the core clock to run at 100 MHz; # and update JTAG clocking similarly; then # make CCLK match, flash probe 0 } openocd-0.9.0/tcl/board/or1k_generic.cfg0000644000175000017500000000216012526202240014764 00000000000000# If you want to use the VJTAG TAP or the XILINX BSCAN, # you must set your FPGA TAP ID here set FPGATAPID 0x020b30dd # Choose your TAP core (VJTAG , MOHOR or XILINX_BSCAN) if { [info exists TAP_TYPE] == 0} { set TAP_TYPE VJTAG } # Set your chip name set CHIPNAME or1200 source [find target/or1k.cfg] # Set the servers polling period to 1ms (needed to JSP Server) poll_period 1 # Set the adapter speed adapter_khz 3000 # Enable the target description feature gdb_target_description enable # Add a new register in the cpu register list. This register will be # included in the generated target descriptor file. # format is addreg [name] [address] [feature] [reg_group] addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system # Override default init_reset proc init_reset {mode} { soft_reset_halt resume } # Target initialization init echo "Halting processor" halt foreach name [target names] { set y [$name cget -endian] set z [$name cget -type] puts [format "Chip is %s, Endian: %s, type: %s" \ $name $y $z] } set c_blue "\033\[01;34m" set c_reset "\033\[0m" puts [format "%sTarget ready...%s" $c_blue $c_reset] openocd-0.9.0/tcl/board/icnova_sam9g45_sodimm.cfg0000644000175000017500000002114412526202240016517 00000000000000################################################################################################# # # # Author: Lars Poeschel (larsi@wh2.tu-dresden.de) # # Generated for In-Circuit ICnova SAM9G45 SODIMM # # http://www.ic-board.de/product_info.php?info=p214_ICnova-SAM9G45-SODIMM.html|ICnova # # # ################################################################################################# # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] source [find target/at91sam9g45.cfg] # Set reset type. # reset_config trst_and_srst # adapter_nsrst_delay 200 # jtag_ntrst_delay 200 # If you don't want to execute built-in boot rom code (and there are good reasons at times not to do that) in the # AT91SAM9 family, the microcontroller is a lump on a log without initialization. Because this family has # some powerful features, we want to have a special function that handles "reset init". To do this we declare # an event handler where these special activities can take place. scan_chain $_TARGETNAME configure -event reset-init {at91sam9g45_init} # Set fallback clock to 1/6 of worst-case clock speed (which would be the 32.768 kHz slow clock). # Slow-speed oscillator enabled at reset, so run jtag speed slow. $_TARGETNAME configure -event reset-start {at91sam9g45_start} # NandFlash configuration and definition # Future TBD # Flash configuration # flash bank cfi set _FLASHNAME $_CHIPNAME.flash # set _NANDNAME $_CHIPNAME.nand flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME # nand device $_NANDNAME at91sam9 $_TARGETNAME 0x40000000 0xFFFFE800 proc read_register {register} { set result "" mem2array result 32 $register 1 return $result(0) } proc at91sam9g45_start { } { # Make sure that the the jtag is running slow, since there are a number of different ways the board # can be configured coming into this state that can cause communication problems with the jtag # adapter. Also since this call can be made following a "reset init" where fast memory accesses # are enabled, need to temporarily shut this down so that the RSTC_MR register can be written at slower # jtag speed without causing GDB keep alive problem. arm7_9 fast_memory_access disable # Slow-speed oscillator enabled at reset, so run jtag speed slow. adapter_khz 4 # Make sure processor is halted, or error will result in following steps. halt wait_halt 10000 # RSTC_MR : enable user reset. mww 0xfffffd08 0xa5000501 } proc at91sam9g45_init { } { # At reset AT91SAM9G45 chip runs on slow clock (32.768 kHz). To shift over to a normal clock requires # a number of steps that must be carefully performed. The process outline below follows the # recommended procedure outlined in the AT91SAM9G45 technical manual. # # Several key and very important things to keep in mind: # The SDRAM parts used currently on the board are -75 grade parts. This # means the master clock (MCLK) must be at or below 133 MHz or timing errors will occur. The processor # core can operate up to 400 MHz and therefore PCLK must be at or below this to function properly. # Make sure processor is halted, or error will result in following steps. halt # RSTC_MR : enable user reset. mww 0xfffffd08 0xa5000501 # WDT_MR : disable watchdog. mww 0xfffffd44 0x00008000 # Enable the main 15.000 MHz oscillator in CKGR_MOR register. # Wait for MOSCS in PMC_SR to assert indicating oscillator is again stable after change to CKGR_MOR. mww 0xfffffc20 0x00004001 while { [expr [read_register 0xfffffc68] & 0x01] != 1 } { sleep 1 } # Set PLLA Register for 792.576 MHz (divider: bypass, multiplier: 43). # Wait for LOCKA signal in PMC_SR to assert indicating PLLA is stable. #mww 0xfffffc28 0x202a3f01 mww 0xfffffc28 0x20c73f03 while { [expr [read_register 0xfffffc68] & 0x02] != 2 } { sleep 1 } # Set master system clock prescaler divide by 6 and processor clock divide by 2 in PMC_MCKR. # Wait for MCKRDY signal from PMC_SR to assert. #mww 0xfffffc30 0x00000101 mww 0xfffffc30 0x00001301 while { [expr [read_register 0xfffffc68] & 0x08] != 8 } { sleep 1 } # Now change PMC_MCKR register to select PLLA. # Wait for MCKRDY signal from PMC_SR to assert. mww 0xfffffc30 0x00001302 while { [expr [read_register 0xfffffc68] & 0x08] != 8 } { sleep 1 } # Processor and master clocks are now operating and stable at maximum frequency possible: # -> MCLK = 132.096 MHz # -> PCLK = 396.288 MHz # Switch over to adaptive clocking. adapter_khz 6000 # Enable faster DCC downloads. arm7_9 dcc_downloads enable # To be able to use external SDRAM, several peripheral configuration registers must # be modified. The first change is made to PIO_ASR to select peripheral functions # for D15 through D31. The second change is made to the PIO_PDR register to disable # this for D15 through D31. # mww 0xfffff870 0xffff0000 # mww 0xfffff804 0xffff0000 # The EBI chip select register EBI_CS must be specifically configured to enable the internal SDRAM controller # using CS1. Additionally we want CS3 assigned to NandFlash. Also VDDIO is connected physically on # the board to the 3.3 VDC power supply so set the appropriate register bit to notify the micrcontroller. # mww 0xffffef1c 0x000100a # The ICnova SAM9G45 SODIMM has built-in NandFlash. The exact physical timing characteristics # for the memory type used on the current board (MT29F2G08AACWP) can be established by setting # four registers in order: SMC_SETUP3, SMC_PULSE3, SMC_CYCLE3, and SMC_MODE3. # mww 0xffffec30 0x00020002 # mww 0xffffec34 0x04040404 # mww 0xffffec38 0x00070007 # mww 0xffffec3c 0x00030003 # Identify NandFlash bank 0. Disabled at the moment because a memory driver is not yet complete. # nand probe 0 # SMC_SETUP0 : Setup SMC for NOR Flash mww 0xffffe800 0x0012000a # SMC_PULSE0 mww 0xffffe804 0x3b38343b # SMC_CYCLE0 mww 0xffffe808 0x003f003f # SMC_MODE0 mww 0xffffe80c 0x00001000 # Identify flash bank 0 flash probe 0 # Now setup SDRAM. This is tricky and configuration is very important for reliability! The current calculations # are based on 2 x Samsung K4T51083QG memory. # 0. Enable DDR2 Clock mww 0xfffffc00 0x4 # 1. Program memory device type # 1.1 configure the DDR controller mww 0xffffe620 0x16 # 1.2 program the DDR controller mww 0xffffe608 0x3d # 2. program memory device features # 2.1 assume timings for 7.5ns min clock period mww 0xffffe60c 0x21128226 # 2.2 pSDDRC->HDDRSDRC2_T1PR mww 0xffffe610 0x02c8100e # 2.3 pSDDRC->HDDRSDRC2_T2PR mww 0xffffe614 0x01000702 # 3. NOP mww 0xffffe600 0x1 mww 0x70000000 0x1 # 3.1 delay 200us sleep 1 # jim tcl alternative: after ms # after 0.2 # 4. NOP mww 0xffffe600 0x1 mww 0x70000000 0x1 # 4.1 delay 400ns # 5. set all bank precharge mww 0xffffe600 0x2 mww 0x70000000 0x1 # 5.1 delay 400ns # 6. set EMR operation (EMRS2) mww 0xffffe600 0x5 mww 0x74000000 0x1 # 6.1 delay 2 cycles # 7. set EMR operation (EMRS3) mww 0xffffe600 0x5 mww 0x76000000 0x1 # 7.1 delay 2 cycles # 8. set EMR operation (EMRS1) mww 0xffffe600 0x5 mww 0x72000000 0x1 # 8.1 delay 200 cycles (400Mhz -> 5 * 10^-7s) sleep 1 # 9. Enable DLL Reset (set DLL bit) set CR [expr [read_register 0xffffe608] | 0x80] mww 0xffffe608 $CR # 10. mode register cycle to reset the DLL mww 0xffffe600 0x5 mww 0x70000000 0x1 # 10.1 delay 2 cycles # 11. set all bank precharge mww 0xffffe600 0x2 mww 0x70000000 0x1 # 11.1 delay 400 ns # 12. two auto-refresh (CBR) cycles are provided. mww 0xffffe600 0x4 mww 0x70000000 0x1 # 12.1 delay 10 cycles # 12.2 2nd cycle (schreiben des Mode Register sparen wir uns) mww 0x70000000 0x1 # 12.3 delay 10 cycles # 13. disable DLL reset (clear DLL bit) set CR [expr [read_register 0xffffe608] & 0xffffff7f] mww 0xffffe608 $CR # 14. mode register set cycle mww 0xffffe600 0x3 mww 0x70000000 0x1 # 15. program OCD field (set OCD bits) set CR [expr [read_register 0xffffe608] | 0x7000] mww 0xffffe608 $CR # 16. (EMRS1) mww 0xffffe600 0x5 mww 0x72000000 0x1 # 16.1 delay 2 cycles # 17. disable OCD field (clear OCD bits) set CR [expr [read_register 0xffffe608] & 0xffff8fff] mww 0xffffe608 $CR # 18. (EMRS1) mww 0xffffe600 0x5 mww 0x76000000 0x1 # 18.1 delay 2 cycles # 19. normal mode command mww 0xffffe600 0x0 mww 0x70000000 0x1 # 20. perform write to any address #mww 0x70000000 0x1 # 21. write refresh rate into the count field of the refresh rate register mww 0xffffe604 0x24b # 21.1 delay (500 * 6 cycles) arm7_9 fast_memory_access enable } openocd-0.9.0/tcl/board/atmel_samg53_xplained_pro.cfg0000644000175000017500000000032212526202240017437 00000000000000# # Atmel SAMG53 Xplained Pro evaluation kit. # http://www.atmel.com/tools/ATSAMG53-XPRO.aspx # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME ATSAMG53N19 source [find target/at91samg5x.cfg] openocd-0.9.0/tcl/board/stm32f3discovery.cfg0000644000175000017500000000037512526202240015553 00000000000000# This is an STM32F3 discovery board with a single STM32F303VCT6 chip. # http://www.st.com/internet/evalboard/product/254044.jsp source [find interface/stlink-v2.cfg] transport select hla_swd source [find target/stm32f3x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/iar_str912_sk.cfg0000644000175000017500000000013612526202240015011 00000000000000# The IAR str912-sk evaluation kick start board has an str912 source [find target/str912.cfg]openocd-0.9.0/tcl/board/ti_blaze.cfg0000644000175000017500000000011712526202240014205 00000000000000jtag_rclk 6000 source [find target/omap4430.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/twr-k60f120m.cfg0000644000175000017500000000066512526202240014404 00000000000000# # Freescale TWRK60F120M development board # source [find target/k60.cfg] $_TARGETNAME configure -event reset-init { puts "-event reset-init occured" } # # Definitions for the additional 'program flash' banks # (instructions and/or data) # flash bank pflash.1 kinetis 0x00040000 0x40000 0 4 $_TARGETNAME flash bank pflash.2 kinetis 0x00080000 0x40000 0 4 $_TARGETNAME flash bank pflash.3 kinetis 0x000c0000 0x40000 0 4 $_TARGETNAME openocd-0.9.0/tcl/board/voltcraft_dso-3062c.cfg0000644000175000017500000000136512526202240016026 00000000000000# # Voltcraft DSO-3062C digital oscilloscope (uses a Samsung S3C2440) # # http://www.eevblog.com/forum/general-chat/hantek-tekway-dso-hack-get-200mhz-bw-for-free/ # http://www.mikrocontroller.net/topic/249628 # http://elinux.org/Das_Oszi # http://randomprojects.org/wiki/Voltcraft_DSO-3062C # # Enable this if your JTAG adapter supports multiple transports (JTAG or SWD). # Otherwise comment it out, as it will cause an OpenOCD error. ### transport select jtag source [find target/samsung_s3c2440.cfg] adapter_khz 16000 # Samsung K9F1208U0C NAND flash chip (64MiB, 3.3V, 8-bit) nand device $_CHIPNAME.nand s3c2440 $_TARGETNAME # arm7_9 fast_memory_access enable # arm7_9 dcc_downloads enable init reset halt scan_chain targets nand probe 0 nand list openocd-0.9.0/tcl/board/stm32ldiscovery.cfg0000644000175000017500000000042312526202240015470 00000000000000# This is an STM32L discovery board with a single STM32L152RBT6 chip. # http://www.st.com/internet/evalboard/product/250990.jsp source [find interface/stlink-v2.cfg] transport select hla_swd set WORKAREASIZE 0x4000 source [find target/stm32l1.cfg] reset_config srst_only openocd-0.9.0/tcl/board/hilscher_nxdb500sys.cfg0000644000175000017500000000204112526202240016212 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx500.cfg] reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x1000 -work-area-phys 0x1000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -event reset-init { halt arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable sdram_fix puts "Configuring SDRAM controller for paired K4S561632C (64MB) " mww 0x00100140 0 mww 0x00100144 0x03C13261 mww 0x00100140 0x030D0121 puts "Configuring SRAM nCS0 for 150ns paired Par. Flash (x32)" mww 0x00100100 0x0201000E flash probe 0 } ##################### # Flash configuration ##################### #flash bank flash bank parflash cfi 0xC0000000 0x02000000 4 4 $_TARGETNAME init reset init openocd-0.9.0/tcl/board/imx31pdk.cfg0000644000175000017500000000375612526202240014070 00000000000000# The IMX31PDK eval board has a single IMX31 chip source [find target/imx31.cfg] source [find target/imx.cfg] $_TARGETNAME configure -event reset-init { imx31pdk_init } proc self_test {} { echo "Running 100 iterations of test." dump_image /ram/test 0x80000000 0x40000 for {set i 0} {$i < 100} {set i [expr $i+1]} { echo "Iteration $i" reset init mww 0x80000000 0x12345678 0x10000 load_image /ram/test 0x80000000 bin verify_image /ram/test 0x80000000 bin } } # Slow fallback frequency # measure_clk indicates ca. 3-4MHz. jtag_rclk 1000 proc imx31pdk_init { } { imx3x_reset # This setup puts RAM at 0x80000000 mww 0x53FC0000 0x040 mww 0x53F80000 0x074B0B7D # 399MHz - 26MHz input, PD=1,MFI=7, MFN=27, MFD=40 #mww 0x53F80004 0xFF871D50 #mww 0x53F80010 0x00271C1B # Start 16 bit NorFlash Initialization on CS0 mww 0xb8002000 0x0000CC03 mww 0xb8002004 0xa0330D01 mww 0xb8002008 0x00220800 # Configure CPLD on CS4 mww 0xb8002040 0x0000DCF6 mww 0xb8002044 0x444A4541 mww 0xb8002048 0x44443302 # SDCLK mww 0x43FAC26C 0 # CAS mww 0x43FAC270 0 # RAS mww 0x43FAC274 0 # CS2 (CSD0) mww 0x43FAC27C 0x1000 # DQM3 mww 0x43FAC284 0 # DQM2, DQM1, DQM0, SD31-SD0, A25-A0, MA10 (0x288..0x2DC) mww 0x43FAC288 0 mww 0x43FAC28C 0 mww 0x43FAC290 0 mww 0x43FAC294 0 mww 0x43FAC298 0 mww 0x43FAC29C 0 mww 0x43FAC2A0 0 mww 0x43FAC2A4 0 mww 0x43FAC2A8 0 mww 0x43FAC2AC 0 mww 0x43FAC2B0 0 mww 0x43FAC2B4 0 mww 0x43FAC2B8 0 mww 0x43FAC2BC 0 mww 0x43FAC2C0 0 mww 0x43FAC2C4 0 mww 0x43FAC2C8 0 mww 0x43FAC2CC 0 mww 0x43FAC2D0 0 mww 0x43FAC2D4 0 mww 0x43FAC2D8 0 mww 0x43FAC2DC 0 # Initialization script for 32 bit DDR on MX31 ADS mww 0xB8001010 0x00000004 mww 0xB8001004 0x006ac73a mww 0xB8001000 0x92100000 mww 0x80000f00 0x12344321 mww 0xB8001000 0xa2100000 mww 0x80000000 0x12344321 mww 0x80000000 0x12344321 mww 0xB8001000 0xb2100000 mwb 0x80000033 0xda mwb 0x81000000 0xff mww 0xB8001000 0x82226080 mww 0x80000000 0xDEADBEEF mww 0xB8001010 0x0000000c } openocd-0.9.0/tcl/board/ek-lm4f120xl.cfg0000644000175000017500000000055412526202240014447 00000000000000# # TI Stellaris Launchpad ek-lm4f120xl Evaluation Kits # # http://www.ti.com/tool/ek-lm4f120xl # # # NOTE: using the bundled ICDI interface is optional! # This interface is not ftdi based as previous boards were # source [find interface/ti-icdi.cfg] transport select hla_jtag set WORKAREASIZE 0x8000 set CHIPNAME lm4f120h5qr source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/olimex_sam7_ex256.cfg0000644000175000017500000000014012526202240015565 00000000000000# Olimex SAM7-EX256 has a single Atmel at91sam7ex256 on it. source [find target/sam7x256.cfg] openocd-0.9.0/tcl/board/mcb1700.cfg0000644000175000017500000000351212526202240013467 00000000000000# Keil MCB1700 PCB with 1768 # # Reset init script sets it to 100MHz set CCLK 100000 source [find target/lpc17xx.cfg] global MCB1700_CCLK set MCB1700_CCLK $CCLK $_TARGETNAME configure -event reset-start { # Start *real slow* as we do not know the # state the boot rom left the clock in adapter_khz 10 } # Set up 100MHz clock to CPU $_TARGETNAME configure -event reset-init { # PLL0CON: Disable PLL mww 0x400FC080 0x00000000 # PLLFEED mww 0x400FC08C 0x000000AA # PLLFEED mww 0x400FC08C 0x00000055 # CCLK=PLL/4 (=100 MHz) mww 0x400FC104 0x00000003 # CLKSRCSEL: Clock source = internal RC oscillator mww 0x400FC10C 0x00000000 # PLL0CFG: M=50,N=1 -> PLL=400 MHz mww 0x400FC084 0x00000031 # PLLFEED mww 0x400FC08C 0x000000AA # PLLFEED mww 0x400FC08C 0x00000055 # PLL0CON: Enable PLL mww 0x400FC080 0x00000001 # PLLFEED mww 0x400FC08C 0x000000AA # PLLFEED mww 0x400FC08C 0x00000055 sleep 50 # PLL0CON: Connect PLL mww 0x400FC080 0x00000003 # PLLFEED mww 0x400FC08C 0x000000AA # PLLFEED mww 0x400FC08C 0x00000055 # Dividing CPU clock by 8 should be pretty conservative # # global MCB1700_CCLK adapter_khz [expr $MCB1700_CCLK / 8] # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select # "User Flash Mode" where interrupt vectors are _not_ remapped, # and reside in flash instead). # # See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description # Bit Symbol Value Description Reset # value # 0 MAP Memory map control. 0 # 0 Boot mode. A portion of the Boot ROM is mapped to address 0. # 1 User mode. The on-chip Flash memory is mapped to address 0. # 31:1 - Reserved. The value read from a reserved bit is not defined. NA # # http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user mww 0x400FC040 0x01 } openocd-0.9.0/tcl/board/topasa900.cfg0000644000175000017500000000574312526202240014146 00000000000000# Thanks to Pieter Conradie for this script! # Target: Toshiba TOPAS900 -- TMPA900 Starterkit ###################################### # We add to the minimal configuration. source [find target/tmpa900.cfg] ###################### # Target configuration ###################### #$_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { topasa900_init } proc topasa900_init { } { # Init PLL # my settings mww 0xf005000c 0x00000007 mww 0xf0050010 0x00000065 mww 0xf005000c 0x000000a7 sleep 10 mdw 0xf0050008 mww 0xf0050008 0x00000002 mww 0xf0050004 0x00000000 # NEW: set CLKCR5 mww 0xf0050054 0x00000040 # # bplan settings # mww 0xf0050004 0x00000000 # mww 0xf005000c 0x000000a7 # sleep 10 # mdw 0xf0050008 # mww 0xf0050008 0x00000002 # mww 0xf0050010 0x00000065 # mww 0xf0050054 0x00000040 sleep 10 # Init SDRAM # _PMCDRV = 0x00000071; # // # // Initialize SDRAM timing paramater # // # _DMC_CAS_LATENCY = 0x00000006; # _DMC_T_DQSS = 0x00000000; # _DMC_T_MRD = 0x00000002; # _DMC_T_RAS = 0x00000007; # # _DMC_T_RC = 0x0000000A; # _DMC_T_RCD = 0x00000013; # # _DMC_T_RFC = 0x0000010A; # # _DMC_T_RP = 0x00000013; # _DMC_T_RRD = 0x00000002; # _DMC_T_WR = 0x00000002; # _DMC_T_WTR = 0x00000001; # _DMC_T_XP = 0x0000000A; # _DMC_T_XSR = 0x0000000B; # _DMC_T_ESR = 0x00000014; # # // # // Configure SDRAM type parameter # _DMC_MEMORY_CFG = 0x00008011; # _DMC_USER_CONFIG = 0x00000011; // 32 bit memory interface # # # _DMC_REFRESH_PRD = 0x00000A60; # _DMC_CHIP_0_CFG = 0x000140FC; # # _DMC_DIRECT_CMD = 0x000C0000; # _DMC_DIRECT_CMD = 0x00000000; # # _DMC_DIRECT_CMD = 0x00040000; # _DMC_DIRECT_CMD = 0x00040000; # _DMC_DIRECT_CMD = 0x00080031; # // # // Finally start SDRAM # // # _DMC_MEMC_CMD = MEMC_CMD_GO; # */ mww 0xf0020260 0x00000071 mww 0xf4300014 0x00000006 mww 0xf4300018 0x00000000 mww 0xf430001C 0x00000002 mww 0xf4300020 0x00000007 mww 0xf4300024 0x0000000A mww 0xf4300028 0x00000013 mww 0xf430002C 0x0000010A mww 0xf4300030 0x00000013 mww 0xf4300034 0x00000002 mww 0xf4300038 0x00000002 mww 0xf430003C 0x00000001 mww 0xf4300040 0x0000000A mww 0xf4300044 0x0000000B mww 0xf4300048 0x00000014 mww 0xf430000C 0x00008011 mww 0xf4300304 0x00000011 mww 0xf4300010 0x00000A60 mww 0xf4300200 0x000140FC mww 0xf4300008 0x000C0000 mww 0xf4300008 0x00000000 mww 0xf4300008 0x00040000 mww 0xf4300008 0x00040000 mww 0xf4300008 0x00080031 mww 0xf4300004 0x00000000 sleep 10 # adapter_khz NNNN # remap off in case of IROM boot mww 0xf0000004 0x00000001 } # comment the following out if usinf J-Link, it soes not support DCC arm7_9 dcc_downloads enable ;# Enable faster DCC downloads ##################### # Flash configuration ##################### #flash bank cfi set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x20000000 0x1000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/xmc4500-relax.cfg0000644000175000017500000000037712526202240014635 00000000000000# # Infineon XMC4500 Relax Kit / Relax Lite Kit # # # Segger J-Link Lite XMC4500 on-board # source [find interface/jlink.cfg] transport select swd # There's also an unpopulated 10-pin 0.05" pinout. set CHIPNAME xmc4500 source [find target/xmc4xxx.cfg] openocd-0.9.0/tcl/board/mini2440.cfg0000644000175000017500000002636312526202240013675 00000000000000#------------------------------------------------------------------------- # Mini2440 Samsung s3c2440A Processor with 64MB DRAM, 64MB NAND, 2 MB N0R # NOTE: Configured for NAND boot (switch S2 in NANDBOOT) # 64 MB NAND (Samsung K9D1208V0M) # B Findlay 08/09 # # ----------- Important notes to help you on your way ---------- # README: # NOR/NAND Boot Switch - I have not read the vivi source, but from # what I could tell from reading the registers it appears that vivi # loads itself into DRAM and then flips NFCONT (0x4E000004) bits # Mode (bit 0 = 1), and REG_nCE (bit 1 = 0) which maps the NAND # FLASH at the bottom 64MB of memory. This essentially takes the # NOR Flash out of the circuit so you can't trash it. # # I adapted the samsung_s3c2440.cfg file which is why I did not # include "source [find target/samsung_s3c2440.cfg]". I believe # the -work-area-phys 0x200000 is incorrect, but also had to pad # some additional resets. I didn't modify it as if it is working # for someone, the work-area-phys is not used by most. # # JTAG ADAPTER SPECIFIC # IMPORTANT! Any JTAG device that uses ADAPTIVE CLOCKING will likely # FAIL as the pin RTCK on the mini2440 10 pin JTAG Conn doesn't exist. # This is Pin 11 (RTCK) on 20 pin JTAG connector. Therefore it is # necessary to FORCE setting the clock. Normally this should be configured # in the openocd.cfg file, but was placed here as it can be a tough # problem to figure out. THIS MAY NOT FIX YOUR PROBLEM.. I modified # the openOCD driver jlink.c and posted it here. It may eventually end # up changed in openOCD, but its a hack in the driver and really should # be in the jtag layer (core.c me thinks), but haven't done it yet. My # hack for jlink.c may be found here. # # http://forum.sparkfun.com/viewtopic.php?t=16763&sid=946e65abdd3bab39cc7d90dee33ff135 # # Note: Also if you have a USB JTAG, you will need the USB library installed # on your system "libusb-dev" or the make of openocd will fail. I *think* # it's apt-get install libusb-dev. When I made my config I only included # --enable-jlink and --enable-usbdevs # # I HAVE NOT Tested this throughly, so there could still be problems. # But it should get you way ahead of the game from where I started. # If you find problems (and fixes) please post them to # openocd-development@lists.berlios.de and join the developers and # check in fixes to this and anything else you find. I do not # provide support, but if you ask really nice and I see anything # obvious I will tell you.. mostly just dig, fix, and submit to openocd. # # best! brfindla@yahoo.com Nashua, NH USA # # Recommended resources: # - first two are the best Mini2440 resources anywhere # - maintained by buserror... thanks guy! # # http://bliterness.blogspot.com/ # http://code.google.com/p/mini2440/ # # others.... # # http://forum.sparkfun.com/viewforum.php?f=18 # http://labs.kernelconcepts.de/Publications/Micro24401/ # http://www.friendlyarm.net/home # http://www.amontec.com/jtag_pinout.shtml # #------------------------------------------------------------------------- # # # Your openocd.cfg file should contain: # source [find interface/.cfg] # source [find board/mini2440.cfg] # # # # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] #------------------------------------------------------------------------- # Target configuration for the Samsung 2440 system on chip # Tested on a S3C2440 Evaluation board by keesj # Processor : ARM920Tid(wb) rev 0 (v4l) # Info: JTAG tap: s3c2440.cpu tap/device found: 0x0032409d # (Manufacturer: 0x04e, Part: 0x0324, Version: 0x0) #------------------------------------------------------------------------- if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c2440 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0032409d } #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup 1 #reset configuration adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst #------------------------------------------------------------------------- # JTAG ADAPTER SPECIFIC # IMPORTANT! See README at top of this file. #------------------------------------------------------------------------- adapter_khz 12000 jtag interface #------------------------------------------------------------------------- # GDB Setup #------------------------------------------------------------------------- gdb_breakpoint_override hard #------------------------------------------------ # ARM SPECIFIC #------------------------------------------------ targets # arm7_9 dcc_downloads enable # arm7_9 fast_memory_access enable nand device s3c2440 0 adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst init echo " " echo "-------------------------------------------" echo "--- login with - telnet localhost 4444 ---" echo "--- then type help_2440 ---" echo "-------------------------------------------" echo " " #------------------------------------------------ # Processor Initialialization # Note: Processor writes can only occur when # the state is in SYSTEM. When you call init_2440 # one of the first lines will tell you what state # you are in. If a linux image is booting # when you run this, it will not work # a vivi boot loader will run with this just # fine. The reg values were obtained by a combination # of figuring them out fromt the manual, and looking # at post vivi values with the debugger. Don't # place too much faith in them, but seem to work. #------------------------------------------------ proc init_2440 { } { halt s3c2440.cpu curstate #----------------------------------------------- # Set Processor Clocks - mini2440 xtal=12mHz # we set main clock for 405mHZ # we set the USB Clock for 48mHz # OM2 OM3 pulled to ground so main clock and # usb clock are off 12mHz xtal #----------------------------------------------- mww phys 0x4C000014 0x00000005 ;# Clock Divider control Reg mww phys 0x4C000000 0xFFFFFFFF ;# LOCKTIME count register mww phys 0x4C000008 0x00038022 ;# UPPLCON USB clock config Reg mww phys 0x4C000004 0x0007F021 ;# MPPLCON Proc clock config Reg #----------------------------------------------- # Configure Memory controller # BWSCON configures all banks, NAND, NOR, DRAM # DRAM - 64MB - 32 bit bus, uses BANKCON6 BANKCON7 #----------------------------------------------- mww phys 0x48000000 0x22111112 ;# BWSCON - Bank and Bus Width mww phys 0x48000010 0x00001112 ;# BANKCON4 - ? mww phys 0x4800001c 0x00018009 ;# BANKCON6 - DRAM mww phys 0x48000020 0x00018009 ;# BANKCON7 - DRAM mww phys 0x48000024 0x008E04EB ;# REFRESH - DRAM mww phys 0x48000028 0x000000B2 ;# BANKSIZE - DRAM mww phys 0x4800002C 0x00000030 ;# MRSRB6 - DRAM mww phys 0x48000030 0x00000030 ;# MRSRB7 - DRAM #----------------------------------------------- # Now port configuration for enables for memory # and other stuff. #----------------------------------------------- mww phys 0x56000000 0x007FFFFF ;# GPACON mww phys 0x56000010 0x00295559 ;# GPBCON mww phys 0x56000018 0x000003FF ;# GPBUP (PULLUP ENABLE) mww phys 0x56000014 0x000007C2 ;# GPBDAT mww phys 0x56000020 0xAAAAA6AA ;# GPCCON mww phys 0x56000028 0x0000FFFF ;# GPCUP mww phys 0x56000024 0x00000020 ;# GPCDAT mww phys 0x56000030 0xAAAAAAAA ;# GPDCON mww phys 0x56000038 0x0000FFFF ;# GPDUP mww phys 0x56000040 0xAAAAAAAA ;# GPECON mww phys 0x56000048 0x0000FFFF ;# GPEUP mww phys 0x56000050 0x00001555 ;# GPFCON mww phys 0x56000058 0x0000007F ;# GPFUP mww phys 0x56000054 0x00000000 ;# GPFDAT mww phys 0x56000060 0x00150114 ;# GPGCON mww phys 0x56000068 0x0000007F ;# GPGUP mww phys 0x56000070 0x0015AAAA ;# GPHCON mww phys 0x56000078 0x000003FF ;# GPGUP } proc flash_config { } { #----------------------------------------- # Finish Flash Configuration #----------------------------------------- halt #flash configuration (K9D1208V0M: 512Mbit, x8, 3.3V, Mode: Normal, 1st gen) nand probe 0 nand list } proc flash_uboot { } { # flash the u-Boot binary and reboot into it init_2440 flash_config nand erase 0 0x0 0x40000 nand write 0 /tftpboot/u-boot-nand512.bin 0 oob_softecc_kw resume } proc load_uboot { } { echo " " echo " " echo "----------------------------------------------------------" echo "---- Load U-Boot into RAM and execute it. ---" echo "---- NOTE: loads, partially runs, and hangs ---" echo "---- U-Boot is fine, this image runs from vivi. ---" echo "---- I burned u-boot into NAND so I didn't finish ---" echo "---- debugging it. I am leaving this here as it is ---" echo "---- part of the way there if you want to fix it. ---" echo "---- ---" echo "---- mini2440 U-boot here: ---" echo "---- http://repo.or.cz/w/u-boot-openmoko/mini2440.git ---" echo "---- Also this: ---" echo "---- http://code.google.com/p/mini2440/wiki/MiniBringup --" echo "----------------------------------------------------------" init_2440 echo "Loading /tftpboot/u-boot-nand512.bin" load_image /tftpboot/u-boot-nand512.bin 0x33f80000 bin echo "Verifying image...." verify_image /tftpboot/u-boot-nand512.bin 0x33f80000 bin echo "jumping to u-boot" #bp 0x33f80068 4 hw reg 0 0 reg 1 0 reg 2 0 reg 3 0 reg 4 0x33f80000 resume 0x33f80000 } # this may help a little bit debugging the load_uboot proc s {} { step reg arm disassemble 0x33F80068 0x10 } proc help_2440 {} { echo " " echo " " echo "-----------------------------------------------------------" echo "---- The following mini2440 funcs are supported ----" echo "---- init_2440 - initialize clocks, DRAM, IO ----" echo "---- flash_config - configures nand flash ----" echo "---- load_uboot - loads uboot into ram ----" echo "---- flash_uboot - flashes uboot to nand (untested) ----" echo "---- help_2440 - this help display ----" echo "-----------------------------------------------------------" echo " " echo " " } #---------------------------------------------------------------------------- #----------------------------------- END ------------------------------------ #---------------------------------------------------------------------------- openocd-0.9.0/tcl/board/pic-p32mx.cfg0000644000175000017500000000013712526202240014140 00000000000000# The Olimex PIC-P32MX has a PIC32MX set CPUTAPID 0x40916053 source [find target/pic32mx.cfg] openocd-0.9.0/tcl/board/olimex_lpc_h2148.cfg0000644000175000017500000000016212526202240015375 00000000000000# # Olimex LPC-H2148 eval board # # http://www.olimex.com/dev/lpc-h2148.html # source [find target/lpc2148.cfg] openocd-0.9.0/tcl/board/stm3210e_eval.cfg0000644000175000017500000000233112526202240014701 00000000000000# This is an STM32 eval board with a single STM32F103ZET6 chip. # http://www.st.com/internet/evalboard/product/204176.jsp # increase working area to 32KB for faster flash programming set WORKAREASIZE 0x8000 source [find target/stm32f1x.cfg] # # configure FSMC Bank 1 (NOR/PSRAM Bank 2) NOR flash # M29W128GL70ZA6E # set _FLASHNAME $_CHIPNAME.norflash flash bank $_FLASHNAME cfi 0x64000000 0x01000000 2 2 $_TARGETNAME proc stm32_enable_fsmc {} { echo "Enabling FSMC Bank 1 (NOR/PSRAM Bank 2)" # enable gpio (defg) clocks for fsmc # RCC_APB2ENR mww 0x40021018 0x000001E0 # enable fsmc clock # RCC_AHBENR mww 0x40021014 0x00000114 # configure gpio to alternate function # GPIOD_CRL mww 0x40011400 0x44BB44BB # GPIOD_CRH mww 0x40011404 0xBBBBBBBB # GPIOE_CRL mww 0x40011800 0xBBBBB444 # GPIOE_CRH mww 0x40011804 0xBBBBBBBB # GPIOF_CRL mww 0x40011C00 0x44BBBBBB # GPIOF_CRH mww 0x40011C04 0xBBBB4444 # GPIOG_CRL mww 0x40012000 0x44BBBBBB # GPIOG_CRH mww 0x40012004 0x444444B4 # setup fsmc timings # FSMC_BCR1 mww 0xA0000008 0x00001058 # FSMC_BTR1 mww 0xA000000C 0x10000502 # FSMC_BCR1 - enable fsmc mww 0xA0000008 0x00001059 } $_TARGETNAME configure -event reset-init { stm32_enable_fsmc } openocd-0.9.0/tcl/board/atmel_at91sam9260-ek.cfg0000644000175000017500000000633412526202240016002 00000000000000################################################################################ # Atmel AT91SAM9260-EK eval board # # http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933 # # Atmel AT91SAM9260 : PLLA = 198.656 MHz, MCK = 99.328 MHz # OSCSEL configured for external 32.768 kHz crystal # # 32-bit SDRAM : 2 x Micron MT48LC16M16A2, 4M x 16Bit x 4 Banks # ################################################################################ # We add to the minimal configuration. source [find target/at91sam9260.cfg] # By default S1 is open and this means that NTRST is not connected. # The reset_config in target/at91sam9260.cfg is overridden here. # (or S1 must be populated with a 0 Ohm resistor) reset_config srst_only $_TARGETNAME configure -event reset-start { # At reset CPU runs at 32.768 kHz. # JTAG Frequency must be 6 times slower if RCLK is not supported. jtag_rclk 5 halt # RSTC_MR : enable user reset, MMU may be enabled... use physical address mww phys 0xfffffd08 0xa5000501 } $_TARGETNAME configure -event reset-init { mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable the main oscillator sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator sleep 10 ;# wait 10 ms mww 0xfffffc28 0x2060bf09 ;# CKGR_PLLAR: Set PLLA Register for 198.656 MHz sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000101 ;# PMC_MCKR : Select prescaler (divide by 2) sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : Clock from PLLA is selected (99.328 MHz) sleep 10 ;# wait 10 ms # Increase JTAG Speed to 6 MHz if RCLK is not supported jtag_rclk 6000 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads mww 0xfffff870 0xffff0000 ;# PIO_ASR : Select peripheral function for D15..D31 mww 0xfffff804 0xffff0000 ;# PIO_PDR : Disable PIO function for D15..D31 mww 0xffffef1c 0x00010002 ;# EBI_CSA : Assign EBI Chip Select 1 to SDRAM, VDDIOMSEL set for +3V3 memory mww 0xffffea08 0x85227259 ;# SDRAMC_CR : Configure SDRAM (2 x Micron MT48LC16M16A2 : 4M x 16Bit x 4 Banks) mww 0xffffea00 0x1 ;# SDRAMC_MR : issue a NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue 8 x 'Auto-Refresh' Command mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : normal mode mww 0x20000000 0 mww 0xffffea04 0x2b6 ;# SDRAMC_TR : Set refresh timer count to 7us } openocd-0.9.0/tcl/board/icnova_imx53_sodimm.cfg0000644000175000017500000003751512526202240016304 00000000000000################################################################################################# # Author: Benjamin Tietz ;# # based on work from: Wjatscheslaw Stoljarski (Slawa) ;# # Kiwigrid GmbH ;# # Generated for In-Circuit i.MX53 SO-Dimm ;# ################################################################################################# # The In-Circuit ICnova IMX53SODIMM board has a single IMX53 chip source [find target/imx53.cfg] # Helper for common memory read/modify/write procedures source [find mem_helper.tcl] echo "i.MX53 SO-Dimm board lodaded." # Set reset type #reset_config srst_only adapter_khz 3000 # Slow speed to be sure it will work jtag_rclk 1000 $_TARGETNAME configure -event "reset-start" { jtag_rclk 1000 } $_TARGETNAME configure -event "reset-assert" { echo "Reseting ...." #cortex_a dbginit } $_TARGETNAME configure -event reset-init { sodimm_init } global AIPS1_BASE_ADDR set AIPS1_BASE_ADDR 0x53F00000 global AIPS2_BASE_ADDR set AIPS2_BASE_ADDR 0x63F00000 proc sodimm_init { } { echo "Reset-init..." ; # halt the CPU halt echo "HW version [format %x [mrw 0x48]]" dap apsel 1 DCD ; # ARM errata ID #468414 set tR [arm mrc 15 0 1 0 1] arm mcr 15 0 1 0 1 [expr $tR | (1<<5)] ; # enable L1NEON bit init_l2cc init_aips init_clock dap apsel 0 ; # Force ARM state ; #reg cpsr 0x000001D3 arm core_state arm jtag_rclk 3000 # adapter_khz 3000 } # L2CC Cache setup/invalidation/disable proc init_l2cc { } { ; #/* explicitly disable L2 cache */ ; #mrc 15, 0, r0, c1, c0, 1 set tR [arm mrc 15 0 1 0 1] ; #bic r0, r0, #0x2 ; #mcr 15, 0, r0, c1, c0, 1 arm mcr 15 0 1 0 1 [expr $tR & ~(1<<2)] ; #/* reconfigure L2 cache aux control reg */ ; #mov r0, #0xC0 /* tag RAM */ ; #add r0, r0, #0x4 /* data RAM */ ; #orr r0, r0, #(1 << 24) /* disable write allocate delay */ ; #orr r0, r0, #(1 << 23) /* disable write allocate combine */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] } # AIPS setup - Only setup MPROTx registers. # The PACR default values are good. proc init_aips { } { ; # Set all MPROTx to be non-bufferable, trusted for R/W, ; # not forced to user-mode. global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set VAL 0x77777777 # dap apsel 1 mww [expr $AIPS1_BASE_ADDR + 0x0] $VAL mww [expr $AIPS1_BASE_ADDR + 0x4] $VAL mww [expr $AIPS2_BASE_ADDR + 0x0] $VAL mww [expr $AIPS2_BASE_ADDR + 0x4] $VAL # dap apsel 0 } proc init_clock { } { global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set CCM_BASE_ADDR [expr $AIPS1_BASE_ADDR + 0x000D4000] set CLKCTL_CCSR 0x0C set CLKCTL_CBCDR 0x14 set CLKCTL_CBCMR 0x18 set PLL1_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00080000] set PLL2_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00084000] set PLL3_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00088000] set PLL4_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x0008C000] set CLKCTL_CSCMR1 0x1C set CLKCTL_CDHIPR 0x48 set PLATFORM_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x000A0000] set CLKCTL_CSCDR1 0x24 set CLKCTL_CCDR 0x04 ; # Switch ARM to step clock mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x4 return echo "not returned" setup_pll $PLL1_BASE_ADDR 800 setup_pll $PLL3_BASE_ADDR 400 ; # Switch peripheral to PLL3 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00015154 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x02888945 | (1<<16)] while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL2_BASE_ADDR 400 ; # Switch peripheral to PLL2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x00808145 | (2<<10) | (9<<16) | (1<<19)] mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00016154 ; # change uart clk parent to pll2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1]] & 0xfcffffff | 0x01000000] ; # make sure change is effective while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL3_BASE_ADDR 216 setup_pll $PLL4_BASE_ADDR 455 ; # Set the platform clock dividers mww [expr $PLATFORM_BASE_ADDR + 0x14] 0x00000124 mww [expr $CCM_BASE_ADDR + 0x10] 0 ; # Switch ARM back to PLL 1. mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x0 ; # make uart div=6 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1]] & 0xffffffc0 | 0x0a] ; # Restore the default values in the Gate registers mww [expr $CCM_BASE_ADDR + 0x68] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x6C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x70] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x74] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x78] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x7C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x80] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x84] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + $CLKCTL_CCDR] 0x00000 ; # for cko - for ARM div by 8 mww [expr $CCM_BASE_ADDR + 0x60] [expr 0x000A0000 & 0x00000F0] } proc setup_pll { PLL_ADDR CLK } { set PLL_DP_CTL 0x00 set PLL_DP_CONFIG 0x04 set PLL_DP_OP 0x08 set PLL_DP_HFS_OP 0x1C set PLL_DP_MFD 0x0C set PLL_DP_HFS_MFD 0x20 set PLL_DP_MFN 0x10 set PLL_DP_HFS_MFN 0x24 if {$CLK == 1000} { set DP_OP [expr (10 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (12 - 1)] set DP_MFN 5 } elseif {$CLK == 850} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 41 } elseif {$CLK == 800} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 700} { set DP_OP [expr (7 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 7 } elseif {$CLK == 600} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 1 } elseif {$CLK == 665} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (96 - 1)] set DP_MFN 89 } elseif {$CLK == 532} { set DP_OP [expr (5 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 13 } elseif {$CLK == 455} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 71 } elseif {$CLK == 400} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 216} { set DP_OP [expr (6 << 4) + ((3 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 3 } else { error "Error (setup_dll): clock not found!" } mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 mww [expr $PLL_ADDR + $PLL_DP_CONFIG] 0x2 mww [expr $PLL_ADDR + $PLL_DP_OP] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_HFS_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 while {[expr [mrw [expr $PLL_ADDR + $PLL_DP_CTL]] & 0x1] == 0} { sleep 1 } } proc CPU_2_BE_32 { L } { return [expr (($L & 0x000000FF) << 24) | (($L & 0x0000FF00) << 8) | (($L & 0x00FF0000) >> 8) | (($L & 0xFF000000) >> 24)] } # Device Configuration Data proc DCD { } { # dap apsel 1 #*========================================================================================== ====== # Initialization script for 32 bit DDR3 (CS0+CS1) #*========================================================================================== ====== # Remux D24/D25 to perform Flash-access mww 0x53fa818C 0x00000000 ; #EIM_RW mww 0x53fa8180 0x00000000 ; #EIM_CS0 mww 0x53fa8188 0x00000000 ; #EIM_OE mww 0x53fa817C 0x00000000 ; #A16 mww 0x53fa8178 0x00000000 ; #A17 mww 0x53fa8174 0x00000000 ; #A18 mww 0x53fa8170 0x00000000 ; #A19 mww 0x53fa816C 0x00000000 ; #A20 mww 0x53fa8168 0x00000000 ; #A21 mww 0x53fa819C 0x00000000 ; #DA0 mww 0x53fa81A0 0x00000000 ; #DA1 mww 0x53fa81A4 0x00000000 ; #DA2 mww 0x53fa81A8 0x00000000 ; #DA3 mww 0x53fa81AC 0x00000000 ; #DA4 mww 0x53fa81B0 0x00000000 ; #DA5 mww 0x53fa81B4 0x00000000 ; #DA6 mww 0x53fa81B8 0x00000000 ; #DA7 mww 0x53fa81BC 0x00000000 ; #DA8 mww 0x53fa81C0 0x00000000 ; #DA9 mww 0x53fa81C4 0x00000000 ; #DA10 mww 0x53fa81C8 0x00000000 ; #DA11 mww 0x53fa81CC 0x00000000 ; #DA12 mww 0x53fa81D0 0x00000000 ; #DA13 mww 0x53fa81D4 0x00000000 ; #DA14 mww 0x53fa81D8 0x00000000 ; #DA15 mww 0x53fa8118 0x00000000 ; #D16 mww 0x53fa811C 0x00000000 ; #D17 mww 0x53fa8120 0x00000000 ; #D18 mww 0x53fa8124 0x00000000 ; #D19 mww 0x53fa8128 0x00000000 ; #D20 mww 0x53fa812C 0x00000000 ; #D21 mww 0x53fa8130 0x00000000 ; #D22 mww 0x53fa8134 0x00000000 ; #D23 mww 0x53fa813c 0x00000000 ; #IOMUXC_SW_PAD_CTL_PAD_EIM_D24 mww 0x53fa8140 0x00000000 ; #IOMUXC_SW_PAD_CTL_PAD_EIM_D25 mww 0x53fa8144 0x00000000 ; #D26 mww 0x53fa8148 0x00000000 ; #D27 mww 0x53fa814C 0x00000000 ; #D28 mww 0x53fa8150 0x00000000 ; #D29 mww 0x53fa8154 0x00000000 ; #D30 mww 0x53fa8158 0x00000000 ; #D31 # DDR3 IOMUX configuration #* Global pad control options */ mww 0x53fa8554 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 mww 0x53fa8558 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 mww 0x53fa8560 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 mww 0x53fa8564 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 mww 0x53fa8568 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 mww 0x53fa8570 0x00200000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1 - boazp: weaker sdclk EVK DDR max frequency mww 0x53fa8574 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS mww 0x53fa8578 0x00200000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 - boazp: weaker sdclk EVK DDR max frequency mww 0x53fa857c 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 mww 0x53fa8580 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 mww 0x53fa8584 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 mww 0x53fa8588 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS mww 0x53fa8590 0x00380040 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 mww 0x53fa8594 0x00380000 ; #IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 mww 0x53fa86f0 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_ADDDS mww 0x53fa86f4 0x00000200 ; #IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL mww 0x53fa86fc 0x00000000 ; #IOMUXC_SW_PAD_CTL_GRP_DDRPKE # mww 0x53fa8714 0x00000200 ; #IOMUXC_SW_PAD_CTL_GRP_DDRMODE - CMOS mode XXX mww 0x53fa8714 0x00000000 ; #IOMUXC_SW_PAD_CTL_GRP_DDRMODE - CMOS mode XXX mww 0x53fa8718 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_B0DS mww 0x53fa871c 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_B1DS mww 0x53fa8720 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_CTLDS mww 0x53fa8724 0x00000000 ; #IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE - DDR_SEL=0 XXX mww 0x53fa8728 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_B2DS mww 0x53fa872c 0x00380000 ; #IOMUXC_SW_PAD_CTL_GRP_B3DS # mww 0x53fa86f4 0x00000000 ;IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL for sDQS[3:0], 1=DDR2, 0=CMOS mode # mww 0x53fa8714 0x00000000 ;IOMUXC_SW_PAD_CTL_GRP_DDRMODE for D[31:0], 1=DDR2, 0=CMOS mode # mww 0x53fa86fc 0x00000000 ;IOMUXC_SW_PAD_CTL_GRP_DDRPKE # mww 0x53fa8724 0x00000000 ;IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE - DDR_SEL=00 #* Data bus byte lane pad drive strength control options */ # mww 0x53fa872c 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_B3DS # mww 0x53fa8554 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 # mww 0x53fa8558 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 # mww 0x53fa8728 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_B2DS # mww 0x53fa8560 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 # mww 0x53fa8568 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 # mww 0x53fa871c 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_B1DS # mww 0x53fa8594 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 # mww 0x53fa8590 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 # mww 0x53fa8718 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_B0DS # mww 0x53fa8584 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 # mww 0x53fa857c 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 #* SDCLK pad drive strength control options */ # mww 0x53fa8578 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 # mww 0x53fa8570 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1 #* Control and addr bus pad drive strength control options */ # mww 0x53fa8574 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS # mww 0x53fa8588 0x00300000 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS # mww 0x53fa86f0 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_ADDDS for DDR addr bus # mww 0x53fa8720 0x00300000 ;IOMUXC_SW_PAD_CTL_GRP_CTLDS for CSD0, CSD1, SDCKE0, SDCKE1, SDWE # mww 0x53fa8564 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 # mww 0x53fa8580 0x00300040 ;IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 # Initialize DDR3 memory - Micron MT41J128M16-187Er #** Keep for now, same setting as CPU3 board **# mww 0x63fd901c 0x00008000 # mww 0x63fd904c 0x01680172 ; #write leveling reg 0 # mww 0x63fd9050 0x0021017f ; #write leveling reg 1 mww 0x63fd9088 0x32383535 ; #read delay lines mww 0x63fd9090 0x40383538 ; #write delay lines # mww 0x63fd90F8 0x00000800 ; #Measure unit mww 0x63fd907c 0x0136014d ; #DQS gating 0 mww 0x63fd9080 0x01510141 ; #DQS gating 1 #* CPU3 Board settingr # Enable bank interleaving, Address mirror on, WALAT 0x1, RALAT = 0x5, DDR2_EN = 0 # mww 0x63fd9018 0x00091740 ; #Misc register: #* Quick Silver board setting # Enable bank interleaving, Address mirror off, WALAT 0x1, RALAT = 0x5, DDR2_EN = 0 mww 0x63fd9018 0x00011740 ; #Misc register # Enable CSD0 and CSD1, row width = 14, column width = 10, burst length = 8, data width = 32bit # mww 0x63fd9000 0xc3190000 ; #Main control register # Enable CSD0 and CSD1, row width = 14, column width = 10, burst length = 8, data width = 32bit mww 0x63fd9000 0x83190000 ; #Main control register # tRFC=64ck;tXS=68;tXP=3;tXPDLL=10;tFAW=15;CAS=6ck mww 0x63fd900C 0x555952E3 ; #timing configuration Reg 0 # tRCD=6;tRP=6;tRC=21;tRAS=15;tRPA=1;tWR=6;tMRD=4;tCWL=5ck mww 0x63fd9010 0xb68e8b63 ; #timing configuration Reg 1 # tDLLK(tXSRD)=512 cycles; tRTP=4;tWTR=4;tRRD=4 mww 0x63fd9014 0x01ff00db ; #timing configuration Reg 2 mww 0x63fd902c 0x000026d2 ; #command delay (default) mww 0x63fd9030 0x009f0e21 ; #out of reset delays # Keep tAOFPD, tAONPD, tANPD, and tAXPD as default since they are bigger than calc values mww 0x63fd9008 0x12273030 ; #ODT timings # tCKE=3; tCKSRX=5; tCKSRE=5 mww 0x63fd9004 0x0002002d #Power down control #********************************** #DDR device configuration: #********************************** #********************************** # CS0: #********************************** mww 0x63fd901c 0x00008032 ; #write mode reg MR2 with cs0 (see below for settings) # Full array self refresh # Rtt_WR disabled (no ODT at IO CMOS operation) # Manual self refresh # CWS=5 mww 0x63fd901c 0x00008033 ; #write mode reg MR3 with cs0. mww 0x63fd901c 0x00028031 ; #write mode reg MR1 with cs0. ODS=01: out buff= RZQ/7 (see below for settings) # out impedance = RZQ/7 # Rtt_nom disabled (no ODT at IO CMOS operation) # Aditive latency off # write leveling disabled # tdqs (differential?) disabled mww 0x63fd901c 0x09208030 ; #write mode reg MR0 with cs0 , with dll_rst0 mww 0x63fd901c 0x04008040 ; #ZQ calibration with cs0 (A10 high indicates ZQ cal long ZQCL) #********************************** # CS1: #********************************** # mww 0x63fd901c 0x0000803a ; #write mode reg MR2 with cs1. # mww 0x63fd901c 0x0000803b ; #write mode reg MR3 with cs1. # mww 0x63fd901c 0x00028039 ; #write mode reg MR1 with cs1. ODS=01: out buff= RZQ/7 # mww 0x63fd901c 0x09208138 ; #write mode reg MR0 with cs1. # mww 0x63fd901c 0x04008048 ; #ZQ calibration with cs1(A10 high indicates ZQ cal long ZQCL) #********************************** mww 0x63fd9020 0x00001800 ; # Refresh control register mww 0x63fd9040 0x04b80003 ; # ZQ HW control mww 0x63fd9058 0x00022227 ; # ODT control register mww 0x63fd901c 0x00000000 # CLKO muxing (comment out for now till needed to avoid conflicts with intended usage of signals) # mww 0x53FA8314 = 0 # mww 0x53FA8320 0x4 # mww 0x53FD4060 0x01e900f0 # dap apsel 0 } # IRAM $_TARGETNAME configure -work-area-phys 0xF8000000 -work-area-size 0x20000 -work-area-backup 1 flash bank mx535_nor cfi 0xf0000000 0x800000 2 2 $_TARGETNAME # vim:filetype=tcl openocd-0.9.0/tcl/board/stm32429i_eval.cfg0000644000175000017500000000045412526202240015007 00000000000000# STM32429I-EVAL: This is an STM32F4 eval board with a single STM32F429NIH6 # (2048KB) chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1199/PF259093 # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F429NIH6 source [find target/stm32f4x.cfg] openocd-0.9.0/tcl/board/at91sam9g20-ek.cfg0000644000175000017500000002156412526202240014703 00000000000000################################################################################################# # # # Author: Gary Carlson (gcarlson@carlson-minot.com) # # Generated for Atmel AT91SAM9G20-EK evaluation board using Atmel SAM-ICE (J-Link) version 8. # # # ################################################################################################# # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] source [find target/at91sam9g20.cfg] set _FLASHTYPE nandflash_cs3 # Set reset type. Note that the AT91SAM9G20-EK board has the trst signal disconnected. Therefore # the reset needs to be configured for "srst_only". If for some reason, a zero-ohm jumper is # added to the board to connect the trst signal, then this parameter may need to be changed. reset_config srst_only adapter_nsrst_delay 200 jtag_ntrst_delay 200 # If you don't want to execute built-in boot rom code (and there are good reasons at times not to do that) in the # AT91SAM9 family, the microcontroller is a lump on a log without initialization. Because this family has # some powerful features, we want to have a special function that handles "reset init". To do this we declare # an event handler where these special activities can take place. scan_chain $_TARGETNAME configure -event reset-init {at91sam9g20_reset_init} $_TARGETNAME configure -event reset-start {at91sam9g20_reset_start} # NandFlash configuration and definition nand device nandflash_cs3 at91sam9 $_TARGETNAME 0x40000000 0xfffffe800 at91sam9 cle 0 22 at91sam9 ale 0 21 at91sam9 rdy_busy 0 0xfffff800 13 at91sam9 ce 0 0xfffff800 14 proc read_register {register} { set result "" mem2array result 32 $register 1 return $result(0) } proc at91sam9g20_reset_start { } { # Make sure that the the jtag is running slow, since there are a number of different ways the board # can be configured coming into this state that can cause communication problems with the jtag # adapter. Also since this call can be made following a "reset init" where fast memory accesses # are enabled, need to temporarily shut this down so that the RSTC_MR register can be written at slower # jtag speed without causing GDB keep alive problem. arm7_9 fast_memory_access disable adapter_khz 2 ;# Slow-speed oscillator enabled at reset, so run jtag speed slow. halt ;# Make sure processor is halted, or error will result in following steps. wait_halt 10000 mww 0xfffffd08 0xa5000501 ;# RSTC_MR : enable user reset. } proc at91sam9g20_reset_init { } { # At reset AT91SAM9G20 chip runs on slow clock (32.768 kHz). To shift over to a normal clock requires # a number of steps that must be carefully performed. The process outline below follows the # recommended procedure outlined in the AT91SAM9G20 technical manual. # # Several key and very important things to keep in mind: # The SDRAM parts used currently on the Atmel evaluation board are -75 grade parts. This # means the master clock (MCLK) must be at or below 133 MHz or timing errors will occur. The processor # core can operate up to 400 MHz and therefore PCLK must be at or below this to function properly. mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog. # Enable the main 18.432 MHz oscillator in CKGR_MOR register. # Wait for MOSCS in PMC_SR to assert indicating oscillator is again stable after change to CKGR_MOR. mww 0xfffffc20 0x00004001 while { [expr [read_register 0xfffffc68] & 0x01] != 1 } { sleep 1 } # Set PLLA Register for 792.576 MHz (divider: bypass, multiplier: 43). # Wait for LOCKA signal in PMC_SR to assert indicating PLLA is stable. mww 0xfffffc28 0x202a3f01 while { [expr [read_register 0xfffffc68] & 0x02] != 2 } { sleep 1 } # Set master system clock prescaler divide by 6 and processor clock divide by 2 in PMC_MCKR. # Wait for MCKRDY signal from PMC_SR to assert. mww 0xfffffc30 0x00000101 while { [expr [read_register 0xfffffc68] & 0x08] != 8 } { sleep 1 } # Now change PMC_MCKR register to select PLLA. # Wait for MCKRDY signal from PMC_SR to assert. mww 0xfffffc30 0x00001302 while { [expr [read_register 0xfffffc68] & 0x08] != 8 } { sleep 1 } # Processor and master clocks are now operating and stable at maximum frequency possible: # -> MCLK = 132.096 MHz # -> PCLK = 396.288 MHz # Switch over to adaptive clocking. adapter_khz 0 # Enable faster DCC downloads and memory accesses. arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable # To be able to use external SDRAM, several peripheral configuration registers must # be modified. The first change is made to PIO_ASR to select peripheral functions # for D15 through D31. The second change is made to the PIO_PDR register to disable # this for D15 through D31. mww 0xfffff870 0xffff0000 mww 0xfffff804 0xffff0000 # The EBI chip select register EBI_CS must be specifically configured to enable the internal SDRAM controller # using CS1. Additionally we want CS3 assigned to NandFlash. Also VDDIO is connected physically on # the board to the 3.3 VDC power supply so set the appropriate register bit to notify the micrcontroller. mww 0xffffef1c 0x000100a # The AT91SAM9G20-EK evaluation board has built-in NandFlash. The exact physical timing characteristics # for the memory type used on the current board (MT29F2G08AACWP) can be established by setting # a number of registers. The first step involves setting up the general I/O pins on the processor # to be able to interface and support the external memory. mww 0xfffffc10 0x00000010 ;# PMC_PCER : enable PIOC clock mww 0xfffff800 0x00006000 ;# PIOC_PER : enable PIO function for 13(RDY/~BSY) and 14(~CS) mww 0xfffff810 0x00004000 ;# PIOC_OER : enable output on 14 mww 0xfffff814 0x00002000 ;# PIOC_ODR : disable output on 13 mww 0xfffff830 0x00004000 ;# PIOC_SODR : set 14 to disable NAND # The exact physical timing characteristics for the memory type used on the current board # (MT29F2G08AACWP) can be established by setting four registers in order: SMC_SETUP3, # SMC_PULSE3, SMC_CYCLE3, and SMC_MODE3. Computing the exact values of these registers # is a little tedious to do here. If you have questions about how to do this, Atmel has # a decent application note #6255B that covers this process. mww 0xffffec30 0x00020002 ;# SMC_SETUP3 : 2 clock cycle setup for NRD and NWE mww 0xffffec34 0x04040404 ;# SMC_PULSE3 : 4 clock cycle pulse for all signals mww 0xffffec38 0x00070006 ;# SMC_CYCLE3 : 7 clock cycle NRD and 6 NWE cycle mww 0xffffec3C 0x00020003 ;# SMC_MODE3 : NRD and NWE control, no NWAIT, 8-bit DBW, mww 0xffffe800 0x00000001 ;# ECC_CR : reset the ECC parity registers mww 0xffffe804 0x00000002 ;# ECC_MR : page size is 2112 words (word is 8 bits) # Identify NandFlash bank 0. nand probe nandflash_cs3 # The AT91SAM9G20-EK evaluation board has build-in serial data flash also. # Now setup SDRAM. This is tricky and configuration is very important for reliability! The current calculations # are based on 2 x Micron MT48LC16M16A2-75 memory (4 M x 16 bit x 4 banks). If you use this file as a reference # for a new board that uses different SDRAM devices or clock rates, you need to recalculate the value inserted # into the SDRAM_CR register. Using the memory datasheet for the -75 grade part and assuming a master clock # of 132.096 MHz then the SDCLK period is equal to 7.6 ns. This means the device requires: # # CAS latency = 3 cycles # TXSR = 10 cycles # TRAS = 6 cycles # TRCD = 3 cycles # TRP = 3 cycles # TRC = 9 cycles # TWR = 2 cycles # 9 column, 13 row, 4 banks # refresh equal to or less then 7.8 us for commerical/industrial rated devices # # Thus SDRAM_CR = 0xa6339279 mww 0xffffea08 0xa6339279 # Next issue a 'NOP' command through the SDRAMC_MR register followed by writing a zero value into # the starting memory location for the SDRAM. mww 0xffffea00 0x00000001 mww 0x20000000 0 # Issue an 'All Banks Precharge' command through the SDRAMC_MR register followed by writing a zero # value into the starting memory location for the SDRAM. mww 0xffffea00 0x00000002 mww 0x20000000 0 # Now issue an 'Auto-Refresh' command through the SDRAMC_MR register. Follow this operation by writing # zero values eight times into the starting memory location for the SDRAM. mww 0xffffea00 0x4 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 # Almost done, so next issue a 'Load Mode Register' command followed by a zero value write to the # the starting memory location for the SDRAM. mww 0xffffea00 0x3 mww 0x20000000 0 # Signal normal mode using the SDRAMC_MR register and follow with a zero value write the the starting # memory location for the SDRAM. mww 0xffffea00 0x0 mww 0x20000000 0 # Finally set the refresh rate to about every 7 us (7.5 ns x 924 cycles). mww 0xffffea04 0x0000039c } openocd-0.9.0/tcl/board/stm320518_eval.cfg0000644000175000017500000000043212526202240014711 00000000000000# STM320518-EVAL: This is an STM32F0 eval board with a single STM32F051R8T6 # (64KB) chip. # http://www.st.com/internet/evalboard/product/252994.jsp # # increase working area to 8KB set WORKAREASIZE 0x2000 # chip name set CHIPNAME STM32F051R8T6 source [find target/stm32f0x.cfg] openocd-0.9.0/tcl/board/telo.cfg0000644000175000017500000000321412526202240013360 00000000000000source [find target/c100.cfg] # basic register defintion for C100 source [find target/c100regs.tcl] # board-config info source [find target/c100config.tcl] # C100 helper functions source [find target/c100helper.tcl] # Telo board & C100 support trst and srst # Note that libftd2xx.so tries to assert srst # which break this script # use libftdi.so library instead with this script # make the reset asserted to # allow RC circuit to discharge for: [ms] adapter_nsrst_assert_width 100 jtag_ntrst_assert_width 100 # don't talk to JTAG after reset for: [ms] adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst separate # issue telnet: reset init # issue gdb: monitor reset init $_TARGETNAME configure -event reset-init { adapter_khz 100 # this will setup Telo board setupTelo #turn up the JTAG speed adapter_khz 3000 echo "JTAG speek now 3MHz" echo "type helpC100 to get help on C100" } $_TARGETNAME configure -event reset-deassert-post { # Force target into ARM state. # soft_reset_halt ;# not implemented on ARM11 echo "Detected SRSRT asserted on C100.CPU" } $_TARGETNAME configure -event reset-assert-post { echo "Assering reset" #sleep 10 } proc power_restore {} { echo "Sensed power restore. No action." } proc srst_deasserted {} { echo "Sensed nSRST deasserted. No action." } # boots from NOR on CS0: 8 MBytes CFI flash, 16-bit bus # it's really 16MB but the upper 8mb is controller via gpio # openocd does not support 'complex reads/writes' to NOR set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x20000000 0x01000000 2 2 $_TARGETNAME # writing data to memory does not work without this arm11 memwrite burst disable openocd-0.9.0/tcl/board/eir.cfg0000644000175000017500000000441412526202240013177 00000000000000# Elector Internet Radio board # http://www.ethernut.de/en/hardware/eir/index.html source [find target/sam7se512.cfg] $_TARGETNAME configure -event reset-init { # WDT_MR, disable watchdog mww 0xFFFFFD44 0x00008000 # RSTC_MR, enable user reset mww 0xfffffd08 0xa5000001 # CKGR_MOR mww 0xFFFFFC20 0x00000601 sleep 10 # CKGR_PLLR mww 0xFFFFFC2C 0x00481c0e sleep 10 # PMC_MCKR mww 0xFFFFFC30 0x00000007 sleep 10 # PMC_IER mww 0xFFFFFF60 0x00480100 # # Enable SDRAM interface. # # Enable SDRAM control at PIO A. mww 0xfffff474 0x3f800000 ;# PIO_BSR_OFF mww 0xfffff404 0x3f800000 ;# PIO_PDR_OFF # Enable address bus (A0, A2-A11, A13-A17) at PIO B mww 0xfffff674 0x0003effd ;# PIO_BSR_OFF mww 0xfffff604 0x0003effd ;# PIO_PDR_OFF # Enable 16 bit data bus at PIO C mww 0xfffff870 0x0000ffff ;# PIO_ASR_OFF mww 0xfffff804 0x0000ffff ;# PIO_PDR_OFF # Enable SDRAM chip select mww 0xffffff80 0x00000002 ;# EBI_CSA_OFF # Set SDRAM characteristics in configuration register. # Hard coded values for MT48LC32M16A2 with 48MHz CPU. mww 0xffffffb8 0x2192215a ;# SDRAMC_CR_OFF sleep 10 # Issue 16 bit SDRAM command: NOP mww 0xffffffb0 0x00000011 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 # Issue 16 bit SDRAM command: Precharge all mww 0xffffffb0 0x00000012 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 # Issue 8 auto-refresh cycles mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 mww 0xffffffb0 0x00000014 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000000 # Issue 16 bit SDRAM command: Set mode register mww 0xffffffb0 0x00000013 ;# SDRAMC_MR_OFF mww 0x20000014 0xcafedede # Set refresh rate count ??? mww 0xffffffb4 0x00000013 ;# SDRAMC_TR_OFF # Issue 16 bit SDRAM command: Normal mode mww 0xffffffb0 0x00000010 ;# SDRAMC_MR_OFF mww 0x20000000 0x00000180 # # Enable external reset key. # mww 0xfffffd08 0xa5000001 } openocd-0.9.0/tcl/board/dm355evm.cfg0000644000175000017500000001223012526202240013760 00000000000000# DM355 EVM board # http://focus.ti.com/docs/toolsw/folders/print/tmdsevm355.html # http://c6000.spectrumdigital.com/evmdm355/ source [find target/ti_dm355.cfg] reset_config trst_and_srst separate # NOTE: disable or replace this call to dm355evm_init if you're # debugging new UBL code from SRAM. $_TARGETNAME configure -event reset-init { dm355evm_init } # # This post-reset init is called when the MMU isn't active, all IRQs # are disabled, etc. It should do most of what a UBL does, except for # loading code (like U-Boot) into DRAM and running it. # proc dm355evm_init {} { global dm355 echo "Initialize DM355 EVM board" # CLKIN = 24 MHz ... can't talk quickly to ARM yet jtag_rclk 1500 ######################## # PLL1 = 432 MHz (/8, x144) # ...SYSCLK1 = 216 MHz (/2) ... ARM, MJCP # ...SYSCLK2 = 108 MHz (/4) ... Peripherals # ...SYSCLK3 = 27 MHz (/16) ... VPBE, DAC # ...SYSCLK4 = 108 MHz (/4) ... VPSS # pll1.{prediv,div1,div2} are fixed # pll1.postdiv set in MISC (for *this* speed grade) set addr [dict get $dm355 pllc1] set pll_divs [dict create] dict set pll_divs div3 16 dict set pll_divs div4 4 pll_v02_setup $addr 144 $pll_divs # ARM is now running at 216 MHz, so JTAG can go faster jtag_rclk 20000 ######################## # PLL2 = 342 MHz (/8, x114) # ....SYSCLK1 = 342 MHz (/1) ... DDR PHY at 171 MHz, 2x clock # pll2.{postdiv,div1} are fixed set addr [dict get $dm355 pllc2] set pll_divs [dict create] dict set pll_divs div1 1 dict set pll_divs prediv 8 pll_v02_setup $addr 114 $pll_divs ######################## # PINMUX # All Video Inputs davinci_pinmux $dm355 0 0x00007f55 # All Video Outputs davinci_pinmux $dm355 1 0x00145555 # EMIFA (NOTE: more could be set up for use as GPIOs) davinci_pinmux $dm355 2 0x00000c08 # SPI0, SPI1, UART1, I2C, SD0, SD1, McBSP0, CLKOUTs davinci_pinmux $dm355 3 0x1bff55ff # MMC/SD0 instead of MS; SPI0 davinci_pinmux $dm355 4 0x00000000 ######################## # PSC setup (minimal) # DDR EMIF/13, AEMIF/14, UART0/19 psc_enable 13 psc_enable 14 psc_enable 19 psc_go ######################## # DDR2 EMIF # VTPIOCR impedance calibration set addr [dict get $dm355 sysbase] set addr [expr $addr + 0x70] # clear CLR, LOCK, PWRDN; wait a clock; set CLR mmw $addr 0 0x20c0 mmw $addr 0x2000 0 # wait for READY while { [expr [mrw $addr] & 0x8000] == 0 } { sleep 1 } # set IO_READY; then LOCK and PWRSAVE; then PWRDN mmw $addr 0x4000 0 mmw $addr 0x0180 0 mmw $addr 0x0040 0 # NOTE: this DDR2 initialization sequence borrows from # both UBL 1.50 and the SPRUEH7D DDR2 EMIF spec. # reset (then re-enable) DDR controller psc_reset 13 psc_go psc_enable 13 psc_go # now set it up for Micron MT47H64M16HR-37E @ 171 MHz set addr [dict get $dm355 ddr_emif] # DDRPHYCR1 mww [expr $addr + 0xe4] 0x50006404 # PBBPR -- burst priority mww [expr $addr + 0x20] 0xfe # SDCR -- unlock boot config; init for DDR2, relock, unlock SDTIM* mmw [expr $addr + 0x08] 0x00800000 0 mmw [expr $addr + 0x08] 0x0013c632 0x03870fff # SDTIMR0, SDTIMR1 mww [expr $addr + 0x10] 0x2a923249 mww [expr $addr + 0x14] 0x4c17c763 # SDCR -- relock SDTIM* mmw [expr $addr + 0x08] 0 0x00008000 # SDRCR -- refresh rate (171 MHz * 7.8usec) mww [expr $addr + 0x0c] 1336 ######################## # ASYNC EMIF set addr [dict get $dm355 a_emif] # slow/pessimistic timings set nand_timings 0x40400204 # fast (25% faster page reads) #set nand_timings 0x0400008c # AWCCR mww [expr $addr + 0x04] 0xff # CS0 == socketed NAND (default MT29F16G08FAA, 2GByte) mww [expr $addr + 0x10] $nand_timings # CS1 == dm9000 Ethernet mww [expr $addr + 0x14] 0x00a00505 # NANDFCR -- only CS0 has NAND mww [expr $addr + 0x60] 0x01 # default: both chipselects to the NAND socket are used nand probe 0 nand probe 1 ######################## # UART0 set addr [dict get $dm355 uart0] # PWREMU_MGNT -- rx + tx in reset mww [expr $addr + 0x30] 0 # DLL, DLH -- 115200 baud mwb [expr $addr + 0x20] 0x0d mwb [expr $addr + 0x24] 0x00 # FCR - clear and disable FIFOs mwb [expr $addr + 0x08] 0x07 mwb [expr $addr + 0x08] 0x00 # IER - disable IRQs mwb [expr $addr + 0x04] 0x00 # LCR - 8-N-1 mwb [expr $addr + 0x0c] 0x03 # MCR - no flow control or loopback mwb [expr $addr + 0x10] 0x00 # PWREMU_MGNT -- rx + tx normal, free running during JTAG halt mww [expr $addr + 0x30] 0xe001 ######################## # turn on icache - set I bit in cp15 register c1 arm mcr 15 0 0 1 0 0x00051078 } # NAND -- socket has two chipselects, MT29F16G08FAA puts 1GByte on each one. # # NOTE: "hwecc4" here presumes that if you're using the standard 2GB NAND # you either (a) have 'new' DM355 chips, with boot ROMs that don't need to # use "hwecc4_infix" for the UBL; or else (b) aren't updating anything that # needs infix layout ... like an old UBL, old U-Boot, old MVL kernel, etc. set _FLASHNAME $_CHIPNAME.boot nand device $_FLASHNAME davinci $_TARGETNAME 0x02000000 hwecc4 0x01e10000 set _FLASHNAME $_CHIPNAME.flash nand device $_FLASHNAME davinci $_TARGETNAME 0x02004000 hwecc4 0x01e10000 # FIXME # - support writing UBL with its header (new layout only with new ROMs) # - support writing ABL/U-Boot with its header (new layout) openocd-0.9.0/tcl/board/spear320cpu.cfg0000644000175000017500000000250512526202241014467 00000000000000# Configuration for the ST SPEAr320 CPU board # EVAL_SPEAr320CPU Rev. 2.0 # http://www.st.com/spear # # Date: 2011-11-18 # Author: Antonio Borneo # The standard board has JTAG SRST not connected. # This script targets such boards using quirky code to bypass the issue. source [find mem_helper.tcl] source [find target/spear3xx.cfg] source [find chip/st/spear/spear3xx_ddr.tcl] source [find chip/st/spear/spear3xx.tcl] arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable # Serial NOR on SMI CS0. 8Mbyte. set _FLASHNAME1 $_CHIPNAME.snor flash bank $_FLASHNAME1 stmsmi 0xf8000000 0 0 0 $_TARGETNAME if { [info exists BOARD_HAS_SRST] } { # Modified board has SRST on JTAG connector reset_config trst_and_srst separate srst_gates_jtag \ trst_push_pull srst_open_drain } else { # Standard board has no SRST on JTAG connector reset_config trst_only separate srst_gates_jtag trst_push_pull source [find chip/st/spear/quirk_no_srst.tcl] } $_TARGETNAME configure -event reset-init { spear320cpu_init } if { [info exists DDR_CHIPS] } { set _DDR_CHIPS $DDR_CHIPS } else { set _DDR_CHIPS 1 } proc spear320cpu_init {} { global _DDR_CHIPS reg pc 0xffff0020; # loop forever sp3xx_clock_default sp3xx_common_init sp3xx_ddr_init "mt47h64m16_3_333_cl5_async" $_DDR_CHIPS sp320_init } openocd-0.9.0/tcl/board/at91eb40a.cfg0000644000175000017500000000334112526202241014011 00000000000000#Script for AT91EB40a # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91eb40a } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1f0f0f0f } #Atmel ties SRST & TRST together, at which point it makes #no sense to use TRST, but use TMS instead. # #The annoying thing with tying SRST & TRST together is that #there is no way to halt the CPU *before and during* the #SRST reset, which means that the CPU will run a number #of cycles before it can be halted(as much as milliseconds). reset_config srst_only srst_pulls_trst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID #target configuration set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME # speed up memory downloads arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable #flash driver set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x01000000 0x200000 2 2 $_TARGETNAME # required for usable performance. Used for lots of # other things than flash programming. $_TARGETNAME configure -work-area-phys 0x00030000 -work-area-size 0x10000 -work-area-backup 0 $_TARGETNAME configure -event reset-init { echo "Running reset init script for AT91EB40A" # Reset script for AT91EB40a reg cpsr 0x000000D3 mww 0xFFE00020 0x1 mww 0xFFE00024 0x00000000 mww 0xFFE00000 0x01002539 mww 0xFFFFF124 0xFFFFFFFF mww 0xffff0010 0x100 mww 0xffff0034 0x100 } # This target is pretty snappy... adapter_khz 16000 openocd-0.9.0/tcl/board/smdk6410.cfg0000644000175000017500000000054412526202241013672 00000000000000# Target configuration for the Samsung s3c6410 system on chip # Tested on a SMDK6410 # Processor : ARM1176 # Info: JTAG device found: 0x0032409d (Manufacturer: 0x04e, Part: 0x0324, Version: 0x0) source [find target/samsung_s3c6410.cfg] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x00100000 2 2 $_TARGETNAME jedec_probe openocd-0.9.0/tcl/board/microchip_explorer16.cfg0000644000175000017500000000043712526202241016466 00000000000000# Microchip Explorer 16 with PIC32MX360F512L PIM module. # http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en024858 # TAPID for PIC32MX360F512L set CPUTAPID 0x30938053 # use 32k working area set WORKAREASIZE 32768 source [find target/pic32mx.cfg] openocd-0.9.0/tcl/board/stm3220g_eval_stlink.cfg0000644000175000017500000000064012526202241016272 00000000000000# STM3220G-EVAL: This is an STM32F2 eval board with a single STM32F207IGH6 # (128KB) chip. # http://www.st.com/internet/evalboard/product/250374.jsp # # This is for using the onboard STLINK/V2 source [find interface/stlink-v2.cfg] transport select hla_swd # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F207IGH6 source [find target/stm32f2x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/ti_tmdx570ls31usb.cfg0000644000175000017500000000016712526202241015543 00000000000000adapter_khz 1500 source [find interface/ftdi/xds100v2.cfg] source [find target/ti_tms570.cfg] reset_config trst_only openocd-0.9.0/tcl/board/lpc1850_spifi_generic.cfg0000644000175000017500000000111212526202241016373 00000000000000# # Generic LPC1850 board w/ SPIFI flash. # This config file is intended as an example of how to # use the lpcspifi flash driver, but it should be functional # for most LPC1850 boards utilizing SPIFI flash. set CHIPNAME lpc1850 source [find target/lpc1850.cfg] #A large working area greatly reduces flash write times set _WORKAREASIZE 0x4000 $_CHIPNAME.m3 configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE #Configure the flash bank; 0x14000000 is the base address for #lpc43xx/lpc18xx family micros. flash bank SPIFI_FLASH lpcspifi 0x14000000 0 0 0 $_CHIPNAME.m3 openocd-0.9.0/tcl/board/atmel_sam4s_ek.cfg0000644000175000017500000000013612526202241015306 00000000000000source [find target/at91sam4sXX.cfg] $_TARGETNAME configure -event gdb-attach { reset init } openocd-0.9.0/tcl/board/linksys_nslu2.cfg0000644000175000017500000000037212526202241015237 00000000000000# This is for the LinkSys (CISCO) NSLU2 board # It is an Intel XSCALE IXP420 CPU. source [find target/ixp42x.cfg] # The _TARGETNAME is set by the above. $_TARGETNAME configure -work-area-phys 0x00020000 -work-area-size 0x10000 -work-area-backup 0 openocd-0.9.0/tcl/board/nds32_xc5.cfg0000644000175000017500000000013112526202241014121 00000000000000set _CPUTAPID 0x1000063d set _CHIPNAME nds32 source [find target/nds32v3.cfg] jtag init openocd-0.9.0/tcl/board/stm32439i_eval.cfg0000644000175000017500000000045412526202241015011 00000000000000# STM32439I-EVAL: This is an STM32F4 eval board with a single STM32F439NIH6 # (2048KB) chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1199/PF259094 # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F439NIH6 source [find target/stm32f4x.cfg] openocd-0.9.0/tcl/board/twr-k60n512.cfg0000644000175000017500000000054512526202241014242 00000000000000# # Freescale TWRK60N512 development board # source [find target/k60.cfg] $_TARGETNAME configure -event reset-init { puts "-event reset-init occured" } # # Bank definition for the 'program flash' (instructions and/or data) # flash bank pflash.0 kinetis 0x00000000 0x40000 0 4 $_TARGETNAME flash bank pflash.1 kinetis 0x00040000 0x40000 0 4 $_TARGETNAME openocd-0.9.0/tcl/board/uptech_2410.cfg0000644000175000017500000000312612526202241014356 00000000000000# Target Configuration for the Uptech 2410 board. # This configuration hould also work on smdk2410, but I havn't tested it yet. # Author: xionglingfeng@Gmail.com source [find target/samsung_s3c2410.cfg] $_TARGETNAME configure -event reset-init { uptech2410_init } $_TARGETNAME configure -event gdb-attach { reset init } proc init_pll_sdram { } { #echo "---------- Initializing PLL and SDRAM ---------" #watchdog timer disable mww phys 0x53000000 0x00000000 #disable all interrupts mww phys 0x4a000008 0xffffffff #disable all sub-interrupts mww phys 0x4a00001c 0x000007ff #clear all source pending bits mww phys 0x4a000000 0xffffffff #clear all sub-source pending bits mww phys 0x4a000018 0x000007ff #clear interrupt pending bit mww phys 0x4a000010 0xffffffff #PLL locktime counter mww phys 0x4c000000 0x00ffffff #Fin=12MHz Fout=202.8MHz #mww phys 0x4c000004 0x000a1031 #FCLK:HCLK:PCLK = 1:2:4 mww phys 0x4c000014 0x00000003 mww phys 0x48000000 0x11111110 mww phys 0x48000004 0x00007FFC mww phys 0x48000008 0x00007FFC mww phys 0x4800000c 0x00000700 mww phys 0x48000010 0x00000700 mww phys 0x48000014 0x00002E50 mww phys 0x48000018 0x00002E50 mww phys 0x4800001c 0x00018005 mww phys 0x48000020 0x00018005 mww phys 0x48000024 0x008c04e9 mww phys 0x48000028 0x000000b2 mww phys 0x4800002c 0x00000030 mww phys 0x48000030 0x00000030 } proc uptech2410_init { } { init_pll_sdram #echo "---------- Probing Nand flash ----------" nand probe 0 #echo "---------- Enable some functions ----------" } set _NANDNAME $_CHIPNAME.nand nand device $_NANDNAME s3c2410 $_TARGETNAME openocd-0.9.0/tcl/board/hitex_lpc2929.cfg0000644000175000017500000001026712526202241014731 00000000000000# Hitex eval board for LPC2929/LPC2939 # http://www.hitex.com/ # Delays on reset lines adapter_nsrst_delay 50 jtag_ntrst_delay 1 # Maximum of 1/8 of clock frequency (XTAL = 16 MHz). # Adaptive clocking through RTCK is not supported. adapter_khz 2000 # Target device: LPC29xx with ETB # The following variables are used by the LPC2900 script: # HAS_ETB Must be set to 1. The CPU on this board has ETB. # FLASH_CLOCK CPU frequency at the time of flash programming (in kHz) set HAS_ETB 1 set FLASH_CLOCK 112000 source [find target/lpc2900.cfg] # A working area will help speeding the flash programming #$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 0x2000 -work-area-backup 0 $_TARGETNAME configure -work-area-phys 0x58000000 -work-area-size 0x10000 -work-area-backup 0 # Event handlers $_TARGETNAME configure -event reset-start { # Back to the slow JTAG clock adapter_khz 2000 } # External 16-bit flash at chip select CS7 (SST39VF3201-70, 4 MiB) set _FLASHNAME $_CHIPNAME.extflash flash bank $_FLASHNAME cfi 0x5C000000 0x400000 2 2 $_TARGETNAME jedec_probe $_TARGETNAME configure -event reset-init { # Flash mww 0x20200010 0x00000007 ;# FBWST: 7 wait states, not chached # Use PLL mww 0xFFFF8020 0x00000001 ;# XTAL_OSC_CONTROL: enable, 1-20 MHz mww 0xFFFF8070 0x01000000 ;# SYS_CLK_CONF: Crystal mww 0xFFFF8028 0x00000005 ;# PLL: (power down) mww 0xFFFF8028 0x01060004 ;# PLL: M=7, 2P=2 (power up) # --> f=112 MHz, fcco=224 MHz sleep 100 mww 0xFFFF8070 0x02000000 ;# SYS_CLK_CONF: PLL # Increase JTAG speed adapter_khz 6000 # Enable external memory bus (16-bit SRAM at CS6, 16-bit flash at CS7) mww 0xE0001138 0x0000001F ;# P1.14 = D0 mww 0xE000113C 0x0000001F ;# P1.15 = D1 mww 0xE0001140 0x0000001F ;# P1.16 = D2 mww 0xE0001144 0x0000001F ;# P1.17 = D3 mww 0xE0001148 0x0000001F ;# P1.18 = D4 mww 0xE000114C 0x0000001F ;# P1.19 = D5 mww 0xE0001150 0x0000001F ;# P1.20 = D6 mww 0xE0001154 0x0000001F ;# P1.21 = D7 mww 0xE0001200 0x0000001F ;# P2.0 = D8 mww 0xE0001204 0x0000001F ;# P2.1 = D9 mww 0xE0001208 0x0000001F ;# P2.2 = D10 mww 0xE000120C 0x0000001F ;# P2.3 = D11 mww 0xE0001210 0x0000001F ;# P2.4 = D12 mww 0xE0001214 0x0000001F ;# P2.5 = D13 mww 0xE0001218 0x0000001F ;# P2.6 = D14 mww 0xE000121C 0x0000001F ;# P2.7 = D15 mww 0xE0001104 0x00000007 ;# P1.1 = A1 mww 0xE0001108 0x00000007 ;# P1.2 = A2 mww 0xE000110C 0x00000007 ;# P1.3 = A3 mww 0xE0001110 0x00000007 ;# P1.4 = A4 mww 0xE0001114 0x00000007 ;# P1.5 = A5 mww 0xE0001118 0x00000007 ;# P1.6 = A6 mww 0xE000111C 0x00000007 ;# P1.7 = A7 mww 0xE0001028 0x00000007 ;# P0.10 = A8 mww 0xE000102C 0x00000007 ;# P0.11 = A9 mww 0xE0001030 0x00000007 ;# P0.12 = A10 mww 0xE0001034 0x00000007 ;# P0.13 = A11 mww 0xE0001038 0x00000007 ;# P0.14 = A12 mww 0xE000103C 0x00000007 ;# P0.15 = A13 mww 0xE0001048 0x00000007 ;# P0.18 = A14 mww 0xE000104C 0x00000007 ;# P0.19 = A15 mww 0xE0001050 0x00000007 ;# P0.20 = A16 mww 0xE0001054 0x00000007 ;# P0.21 = A17 mww 0xE0001058 0x00000007 ;# P0.22 = A18 mww 0xE000105C 0x00000007 ;# P0.23 = A19 mww 0xE0001238 0x00000007 ;# P2.14 = BLS0 mww 0xE000123C 0x00000007 ;# P2.15 = BLS1 mww 0xE0001300 0x00000007 ;# P3.0 = CS6 mww 0xE0001304 0x00000007 ;# P3.1 = CS7 mww 0xE0001130 0x00000007 ;# P1.12 = OE_N mww 0xE0001134 0x00000007 ;# P1.13 = WE_N mww 0x600000BC 0x00000041 ;# Bank6 16-bit mode, RBLE=1 mww 0x600000B4 0x00000000 ;# Bank6 WSTOEN=0 mww 0x600000AC 0x00000005 ;# Bank6 WST1=5 mww 0x600000B8 0x00000001 ;# Bank6 WSTWEN=1 mww 0x600000B0 0x00000006 ;# Bank6 WST2=6 mww 0x600000A8 0x00000002 ;# Bank6 IDCY=2 mww 0x600000D8 0x00000041 ;# Bank7 16-bit mode, RBLE=1 mww 0x600000D0 0x00000000 ;# Bank7 WSTOEN=0 mww 0x600000C8 0x0000000A ;# Bank7 WST1=10 mww 0x600000D4 0x00000001 ;# Bank7 WSTWEN=1 mww 0x600000CC 0x0000000C ;# Bank7 WST2=8 mww 0x600000C4 0x00000002 ;# Bank7 IDCY=2 } openocd-0.9.0/tcl/board/kwikstik.cfg0000644000175000017500000000025112526202241014254 00000000000000# # Freescale KwikStik development board # # # JLINK interface is onboard # source [find interface/jlink.cfg] source [find target/k40.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/quark_x10xx_board.cfg0000644000175000017500000000034512526202241015762 00000000000000# There are many Quark boards that can host the quark_x10xx SoC # Galileo is an example board source [find target/quark_x10xx.cfg] #default frequency but this can be adjusted at runtime adapter_khz 4000 reset_config trst_only openocd-0.9.0/tcl/board/x300t.cfg0000644000175000017500000000160212526202241013273 00000000000000# This is for the T-Home X300T / X301T IPTV box, # which are based on IPTV reference designs from Kiss/Cisco KMM-3*** # # It has Sigma Designs SMP8634 chip. source [find target/smp8634.cfg] $_TARGETNAME configure -event reset-init { x300t_init } # 1MB CFI capable flash # flash bank set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0xac000000 0x100000 2 2 $_TARGETNAME proc x300t_init { } { # Setup SDRAM config and flash mapping # initialize ram mww 0xa003fffc 3 mww 0xa003fffc 2 mww 0xa0030000 0xE34111BA mww 0xa003fffc 0xa4444 mww 0xa003fffc 0 # remap boot vector in CPU local RAM mww 0xa006f000 0x60000 # map flash to CPU address space REG_BASE_cpu_block+CPU_remap4 mww 0x0006f010 0x48000000 # map flash addr to REG_BASE_cpu_block + LR_XENV_LOCATION (normally done by XOS) mww 0x00061ff0 0x48000000 } openocd-0.9.0/tcl/board/crossbow_tech_imote2.cfg0000644000175000017500000000045212526202241016542 00000000000000# Crossbow Technology iMote2 set CHIPNAME imote2 source [find target/pxa270.cfg] # longer-than-normal reset delay adapter_nsrst_delay 800 reset_config trst_and_srst separate # works for P30 flash set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x2000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/stm32f334discovery.cfg0000644000175000017500000000043212526202241015715 00000000000000# This is an STM32F334 discovery board with a single STM32F334C8T6 chip. # As it is one of the few boards with stlink V.2-1, we source the corresponding # nucleo file. # http://www.st.com/web/en/catalog/tools/FM116/SC959/SS1532/LN1848/PF260318 source [find board/st_nucleo_f3.cfg] openocd-0.9.0/tcl/board/open-bldc.cfg0000644000175000017500000000026712526202241014266 00000000000000# Open Source Brush Less DC Motor Controller # http://open-bldc.org # Work-area size (RAM size) = 20kB for STM32F103RB device set WORKAREASIZE 0x5000 source [find target/stm32.cfg] openocd-0.9.0/tcl/board/altera_sockit.cfg0000644000175000017500000000074312526202241015246 00000000000000# # Cyclone V SocKit board # http://www.altera.com/b/arrow-sockit.html # # Software support page: # http://www.rocketboards.org/ # openocd does not currently support the on-board USB Blaster II. # Install the JTAG header and use a USB Blaster instead. interface usb_blaster source [find target/altera_fpgasoc.cfg] # If the USB Blaster II were supported, these settings would be needed #usb_blaster_vid_pid 0x6810 0x09fb #usb_blaster_device_desc "USB-Blaster II" adapter_khz 100 openocd-0.9.0/tcl/board/imx28evk.cfg0000644000175000017500000001176412526202241014104 00000000000000# The IMX28EVK eval board has a IMX28 chip # Tested on SCH-26241 Rev D board with Olimex ARM-USB-OCD # Date: 201-02-01 # Authors: James Robinson & Fabio Estevam source [find target/imx28.cfg] $_TARGETNAME configure -event gdb-attach { imx28evk_init } $_TARGETNAME configure -event reset-init { imx28evk_init } proc imx28evk_init { } { halt #**************************** # VDDD setting #**************************** # set VDDD =1.55V =(0.8v + TRIG x 0.025v), TRIG=0x1e mww 0x80044010 0x0003F503 mww 0x80044040 0x0002041E #**************************** # CLOCK set up #**************************** # Power up PLL0 HW_CLKCTRL_PLL0CTRL0 mww 0x80040000 0x00020000 # Set up fractional dividers for CPU and EMI - HW_CLKCTRL_FRAC0 # EMI - first set DIV_EMI to div-by-2 before programming frac divider mww 0x800400F0 0x80000002 # CPU: CPUFRAC=19 480*18/29=454.7MHz, EMI: EMIFRAC=22, (480/2)*18/22=196.4MHz mww 0x800401B0 0x92921613 # Clear the bypass bits for CPU and EMI clocks in HW_CLKCTRL_CLKSEQ_CLR mww 0x800401D8 0x00040080 # HCLK = 227MHz,HW_CLKCTRL_HBUS DIV =0x2 mww 0x80040060 0x00000002 #**************************** # POWER up DCDD_VDDA (DDR2) #**************************** # Now set the voltage level to 1.8V HW_POWER_VDDACTRL bits TRC=0xC mww 0x80044050 0x0000270C #**************************** # DDR2 DCDD_VDDA #**************************** # First set up pin muxing and drive strength # Ungate module clock and bring out of reset HW_PINCTRL_CTRL_CLR mww 0x80018008 0xC0000000 #**************************** # EMI PAD setting #**************************** # Set up drive strength for EMI pins mww 0x80019B80 0x00030000 #IOMUXC_SW_PAD_CTL_GRP_CTLDS # Set up pin muxing for EMI, HW_PINCTRL_MUXSEL10, 11, 12, 13 mww 0x800181A8 0xFFFFFFFF mww 0x800181B8 0xFFFFFFFF mww 0x800181C8 0xFFFFFFFF mww 0x800181D8 0xFFFFFFFF #** Ungate EMI clock in CCM mww 0x800400F0 0x00000002 #============================================================================ # DDR Controller Registers #============================================================================ # Manufacturer: Elpida # Device Part Number: EDE1116AEBG # Clock Freq.: 200MHz # Density: 1Gb # Chip Selects: 1 # Number of Banks: 8 # Row address: 13 # Column address: 10 #============================================================================ mww 0x800E0000 0x00000000 mww 0x800E0040 0x00000000 mww 0x800E0054 0x00000000 mww 0x800E0058 0x00000000 mww 0x800E005C 0x00000000 mww 0x800E0060 0x00000000 mww 0x800E0064 0x00000000 mww 0x800E0068 0x00010101 mww 0x800E006C 0x01010101 mww 0x800E0070 0x000f0f01 mww 0x800E0074 0x0102020A mww 0x800E007C 0x00010101 mww 0x800E0080 0x00000100 mww 0x800E0084 0x00000100 mww 0x800E0088 0x00000000 mww 0x800E008C 0x00000002 mww 0x800E0090 0x01010000 mww 0x800E0094 0x07080403 mww 0x800E0098 0x06005003 mww 0x800E009C 0x0A0000C8 mww 0x800E00A0 0x02009C40 mww 0x800E00A4 0x0002030C mww 0x800E00A8 0x0036B009 mww 0x800E00AC 0x031A0612 mww 0x800E00B0 0x02030202 mww 0x800E00B4 0x00C8001C mww 0x800E00C0 0x00011900 mww 0x800E00C4 0xffff0303 mww 0x800E00C8 0x00012100 mww 0x800E00CC 0xffff0303 mww 0x800E00D0 0x00012100 mww 0x800E00D4 0xffff0303 mww 0x800E00D8 0x00012100 mww 0x800E00DC 0xffff0303 mww 0x800E00E0 0x00000003 mww 0x800E00E8 0x00000000 mww 0x800E0108 0x00000612 mww 0x800E010C 0x01000f02 mww 0x800E0114 0x00000200 mww 0x800E0118 0x00020007 mww 0x800E011C 0xf4004a27 mww 0x800E0120 0xf4004a27 mww 0x800E012C 0x07400300 mww 0x800E0130 0x07400300 mww 0x800E013C 0x00000005 mww 0x800E0140 0x00000000 mww 0x800E0144 0x00000000 mww 0x800E0148 0x01000000 mww 0x800E014C 0x01020408 mww 0x800E0150 0x08040201 mww 0x800E0154 0x000f1133 mww 0x800E015C 0x00001f04 mww 0x800E0160 0x00001f04 mww 0x800E016C 0x00001f04 mww 0x800E0170 0x00001f04 mww 0x800E0288 0x00010000 mww 0x800E028C 0x00030404 mww 0x800E0290 0x00000003 mww 0x800E02AC 0x01010000 mww 0x800E02B0 0x01000000 mww 0x800E02B4 0x03030000 mww 0x800E02B8 0x00010303 mww 0x800E02BC 0x01020202 mww 0x800E02C0 0x00000000 mww 0x800E02C4 0x02030303 mww 0x800E02C8 0x21002103 mww 0x800E02CC 0x00061200 mww 0x800E02D0 0x06120612 mww 0x800E02D4 0x04420442 # Mode register 0 for CS1 and CS0, ok to program CS1 even if not used mww 0x800E02D8 0x00000000 # Mode register 0 for CS2 and CS3, not supported in this processor mww 0x800E02DC 0x00040004 # Mode register 1 for CS1 and CS0, ok to program CS1 even if not used mww 0x800E02E0 0x00000000 # Mode register 1 for CS2 and CS3, not supported in this processor mww 0x800E02E4 0x00000000 # Mode register 2 for CS1 and CS0, ok to program CS1 even if not used mww 0x800E02E8 0x00000000 # Mode register 2 for CS2 and CS3, not supported in this processor mww 0x800E02EC 0x00000000 # Mode register 3 for CS1 and CS0, ok to program CS1 even if not used mww 0x800E02F0 0x00000000 # Mode register 3 for CS2 and CS3, not supported in this processor mww 0x800E02F4 0xffffffff #** start controller **# mww 0x800E0040 0x00000001 # bit[0]: start } openocd-0.9.0/tcl/board/hilscher_nxhx10.cfg0000644000175000017500000000437612526202241015437 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx10.cfg] # Usually it is not needed to set srst_pulls_trst # but sometimes it does not work without it. If you encounter # problems try to line below # reset_config trst_and_srst srst_pulls_trst reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x08000000 -work-area-phys 0x08000000 -work-area-size 0x4000 -work-area-backup 1 # Par. Flash can only be accessed if DIP switch on the board is set in proper # position and init_sdrambus was called. Don't call these functions if the DIP # switch is in invalid position, as some outputs may collide. This is why this # function is not called automatically proc flash_init { } { puts "Configuring SRAM nCS0 for 90ns Par. Flash (x16)" mww 0x101C0100 0x01010008 flash probe 0 } proc mread32 {addr} { set value(0) 0 mem2array value 32 $addr 1 return $value(0) } proc init_clocks { } { puts "Enabling all clocks " set accesskey [mread32 0x101c0070] mww 0x101c0070 [expr $accesskey] mww 0x101c0028 0x00007511 } proc init_sdrambus { } { puts "Initializing external SDRAM Bus 16 Bit " set accesskey [mread32 0x101c0070] mww 0x101c0070 [expr $accesskey] mww 0x101c0C40 0x00000050 puts "Configuring SDRAM controller for K4S561632E (32MB) " mww 0x101C0140 0 sleep 100 #mww 0x101C0144 0x00a13262 mww 0x101C0144 0x00a13251 mww 0x101C0148 0x00000033 mww 0x101C0140 0x030d0121 } $_TARGETNAME configure -event reset-init { halt wait_halt 1000 arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable init_clocks # init_sdrambus puts "" puts "-------------------------------------------------" puts "Call 'init_clocks' to enable all clocks" puts "Call 'init_sdrambus' to enable external SDRAM bus" puts "-------------------------------------------------" } ##################### # Flash configuration ##################### #flash bank #flash bank parflash cfi 0xC0000000 0x01000000 2 2 $_TARGETNAME init reset initopenocd-0.9.0/tcl/board/csb337.cfg0000644000175000017500000000562012526202241013425 00000000000000# Cogent CSB337 # http://cogcomp.com/csb_csb337.htm source [find target/at91rm9200.cfg] # boots from NOR on CS0: 8 MBytes CFI flash, 16-bit bus set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME # ETM9 trace port connector present on this board, 16 data pins. if { [info exists ETM_DRIVER] } { etm config $_TARGETNAME 16 normal half $ETM_DRIVER # OpenOCD may someday support a real trace port driver... # system config file would need to configure it. } else { etm config $_TARGETNAME 16 normal half dummy etm_dummy config $_TARGETNAME } proc csb337_clk_init { } { # CPU is in Slow Clock Mode (32KiHz) ... needs slow JTAG clock adapter_khz 8 # CKGR_MOR: start main oscillator (3.6864 MHz) mww 0xfffffc20 0xff01 sleep 10 # CKGR_PLLAR: start PLL A for CPU and peripherals (184.32 MHz) mww 0xfffffc28 0x20313e01 # CKGR_PLLBR: start PLL B for USB timing (96 MHz, with div2) mww 0xfffffc2c 0x12703e18 # let PLLs lock sleep 10 # PMC_MCKR: switch to CPU clock = PLLA, master clock = CPU/4 mww 0xfffffc30 0x0302 sleep 20 # CPU is in Normal Mode ... allows faster JTAG clock speed adapter_khz 40000 } proc csb337_nor_init { } { # SMC_CSR0: adjust timings (10 wait states) mww 0xffffff70 0x1100318a flash probe 0 } proc csb337_sdram_init { } { # enable PIOC clock mww 0xfffffc10 0x0010 # PC31..PC16 are D31..D16, with internal pullups like D15..D0 mww 0xfffff870 0xffff0000 mww 0xfffff874 0x0 mww 0xfffff804 0xffff0000 # SDRC_CR: set timings mww 0xffffff98 0x2188b0d5 # SDRC_MR: issue all banks precharge to SDRAM mww 0xffffff90 2 mww 0x20000000 0 # SDRC_MR: 8 autorefresh cycles mww 0xffffff90 4 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 # SDRC_MR: set SDRAM mode registers (CAS, burst len, etc) mww 0xffffff90 3 mww 0x20000080 0 # SDRC_TR: set refresh rate mww 0xffffff94 0x200 mww 0x20000000 0 # SDRC_MR: normal mode, 32 bit bus mww 0xffffff90 0 mww 0x20000000 0 } # The rm9200 chip has just been reset. Bring it up far enough # that we can write flash or run code from SDRAM. proc csb337_reset_init { } { csb337_clk_init # EBI_CSA: CS0 = NOR, CS1 = SDRAM mww 0xffffff60 0x02 csb337_nor_init csb337_sdram_init # Update CP15 control register ... we don't seem to be able to # read/modify/write its value through a TCL variable, so just # write it. Fields are zero unless listed here ... and note # that OpenOCD numbers this register "2", not "1" (!). # # - Core to use Async Clocking mode (so it uses 184 MHz most # of the time instead of limiting to the master clock rate): # iA(31) = 1, nF(30) = 1 # - Icache on (it's disabled now, slowing i-fetches) # I(12) = 1 # - Reserved/ones # 6:3 = 1 arm920t cp15 2 0xc0001078 } $_TARGETNAME configure -event reset-init {csb337_reset_init} arm7_9 fast_memory_access enable openocd-0.9.0/tcl/board/pxa255_sst.cfg0000644000175000017500000000452412526202241014340 00000000000000# A PXA255 test board with SST 39LF400A flash # # At reset the memory map is as follows. Note that # the memory map changes later on as the application # starts... # # RAM at 0x4000000 # Flash at 0x00000000 # source [find target/pxa255.cfg] # Target name is set by above $_TARGETNAME configure -work-area-phys 0x4000000 -work-area-size 0x4000 -work-area-backup 0 # flash bank [options] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x80000 2 2 $_TARGETNAME jedec_probe proc pxa255_sst_init {} { xscale cp15 15 0x00002001 ;#Enable CP0 and CP13 access # # setup GPIO # mww 0x40E00018 0x00008000 ;#CPSR0 sleep 20 mww 0x40E0001C 0x00000002 ;#GPSR1 sleep 20 mww 0x40E00020 0x00000008 ;#GPSR2 sleep 20 mww 0x40E0000C 0x00008000 ;#GPDR0 sleep 20 mww 0x40E00054 0x80000000 ;#GAFR0_L sleep 20 mww 0x40E00058 0x00188010 ;#GAFR0_H sleep 20 mww 0x40E0005C 0x60908018 ;#GAFR1_L sleep 20 mww 0x40E0000C 0x0280E000 ;#GPDR0 sleep 20 mww 0x40E00010 0x821C88B2 ;#GPDR1 sleep 20 mww 0x40E00014 0x000F03DB ;#GPDR2 sleep 20 mww 0x40E00000 0x000F03DB ;#GPLR0 sleep 20 mww 0x40F00004 0x00000020 ;#PSSR sleep 20 # # setup memory controller # mww 0x48000008 0x01111998 ;#MSC0 sleep 20 mww 0x48000010 0x00047ff0 ;#MSC2 sleep 20 mww 0x48000014 0x00000000 ;#MECR sleep 20 mww 0x48000028 0x00010504 ;#MCMEM0 sleep 20 mww 0x4800002C 0x00010504 ;#MCMEM1 sleep 20 mww 0x48000030 0x00010504 ;#MCATT0 sleep 20 mww 0x48000034 0x00010504 ;#MCATT1 sleep 20 mww 0x48000038 0x00004715 ;#MCIO0 sleep 20 mww 0x4800003C 0x00004715 ;#MCIO1 sleep 20 # mww 0x48000004 0x03CA4018 ;#MDREF sleep 20 mww 0x48000004 0x004B4018 ;#MDREF sleep 20 mww 0x48000004 0x000B4018 ;#MDREF sleep 20 mww 0x48000004 0x000BC018 ;#MDREF sleep 20 mww 0x48000000 0x00001AC8 ;#MDCNFG sleep 20 sleep 20 mww 0x48000000 0x00001AC9 ;#MDCNFG sleep 20 mww 0x48000040 0x00000000 ;#MDMRS sleep 20 } $_TARGETNAME configure -event reset-init {pxa255_sst_init} reset_config trst_and_srst adapter_nsrst_delay 200 jtag_ntrst_delay 200 #xscale debug_handler 0 0xFFFF0800 ;# debug handler base address openocd-0.9.0/tcl/board/spear300evb_mod.cfg0000644000175000017500000000200212526202241015301 00000000000000# Configuration for the ST SPEAr300 Evaluation board # EVALSPEAr300 Rev. 1.0, modified to enable SRST on JTAG connector # http://www.st.com/spear # # List of board modifications to enable SRST, as reported in # ST Application Note (FIXME: add reference). # - Modifications on the top layer: # 1. replace reset chip U4 with a STM6315SDW13F; # - Modifications on the bottom layer: # 2. add 0 ohm resistor R10. It is located close to JTAG connector. # 3. add a 10K ohm pull-up resistor on the reset wire named as # POWERGOOD in the schematic. # # The easier way to do modification 3, is to use a resistor in package # 0603 and solder it between R10 and R54: # - one pad soldered with the pad of R54 connected to 3.3V (this # is the pad of R54 far from JTAG connector J4) # - the other pad soldered with the nearest pad of R10. # # Date: 2011-11-18 # Author: Antonio Borneo # Modified boards has SRST on JTAG connector set BOARD_HAS_SRST 1 source [find board/spear300evb.cfg] openocd-0.9.0/tcl/board/colibri.cfg0000644000175000017500000000051312526202241014040 00000000000000# Toradex Colibri PXA270 source [find target/pxa270.cfg] reset_config trst_and_srst srst_push_pull adapter_nsrst_assert_width 40 # CS0 -- one bank of CFI flash, 32 MBytes # the bank is 32-bits wide, two 16-bit chips in parallel set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME openocd-0.9.0/tcl/board/dp_busblaster_v3.cfg0000644000175000017500000000053612526202241015663 00000000000000# # Dangerous Prototypes - Bus Blaster # # http://dangerousprototypes.com/docs/Bus_Blaster # # To reprogram the on-board CPLD do: # openocd -f board/dp_busblaster_v3.cfg -c "adapter_khz 1000; init; svf ; shutdown" # source [find interface/ftdi/dp_busblaster.cfg] ftdi_channel 1 jtag newtap xc2c32a tap -expected-id 0x06e1c093 -irlen 8 openocd-0.9.0/tcl/board/tp-link_tl-mr3020.cfg0000644000175000017500000000323512526202242015420 00000000000000source [find target/atheros_ar9331.cfg] proc ar9331_25mhz_pll_init {} { mww 0xb8050008 0x00018004 ;# bypass PLL; AHB_POST_DIV - ratio 4 mww 0xb8050004 0x00000352 ;# 34000(ns)/40ns(25MHz) = 0x352 (850) mww 0xb8050000 0x40818000 ;# Power down control for CPU PLL ;# OUTDIV | REFDIV | DIV_INT mww 0xb8050010 0x001003e8 ;# CPU PLL Dither FRAC Register ;# (disabled?) mww 0xb8050000 0x00818000 ;# Power on | OUTDIV | REFDIV | DIV_INT mww 0xb8050008 0x00008000 ;# remove bypass; ;# AHB_POST_DIV - ratio 2 } proc ar9331_ddr1_init {} { mww 0xb8000000 0x7fbc8cd0 ;# DDR_CONFIG - lots of DRAM confs mww 0xb8000004 0x9dd0e6a8 ;# DDR_CONFIG2 - more DRAM confs mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle mww 0xb8000008 0x133 ;# mode reg: 0x133 - default mww 0xb8000010 0x1 ;# Forces an MRS update cycl mww 0xb800000c 0x2 ;# Extended mode register value. ;# default 0x2 - Reset to weak driver, DLL on mww 0xb8000010 0x2 ;# Forces an EMRS update cycle mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle mww 0xb8000008 0x33 ;# mode reg: remove some bit? mww 0xb8000010 0x1 ;# Forces an MRS update cycl mww 0xb8000014 0x4186 ;# enable refres: bit(14) - set refresh rate mww 0xb800001c 0x8 ;# This register is used along with DQ Lane 0, ;# DQ[7:0], DQS_0 mww 0xb8000020 0x9 ;# This register is used along with DQ Lane 1, ;# DQ[15:8], DQS_1. mww 0xb8000018 0xff ;# DDR read and capture bit mask. ;# Each bit represents a cycle of valid data. } $TARGETNAME configure -event reset-init { ar9331_25mhz_pll_init sleep 1 ar9331_ddr1_init } set ram_boot_address 0xa0000000 $TARGETNAME configure -work-area-phys 0xa1FFE000 -work-area-size 0x1000 openocd-0.9.0/tcl/board/atmel_sam4s_xplained_pro.cfg0000644000175000017500000000032312526202242017372 00000000000000# # Atmel SAM4S Xplained Pro evaluation kit. # http://www.atmel.com/tools/ATSAM4S-XPRO.aspx # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME ATSAM4SD32C source [find target/at91sam4sd32x.cfg] openocd-0.9.0/tcl/board/mbed-lpc11u24.cfg0000644000175000017500000000040512526202242014576 00000000000000# This is an mbed eval board with a single NXP LPC11U24 chip. # http://mbed.org/handbook/mbed-NXP-LPC11U24 # source [find interface/cmsis-dap.cfg] # NXP LPC11U24 Cortex-M0 with 32kB Flash and 8kB SRAM set WORKAREASIZE 0x2000 source [find target/lpc11xx.cfg] openocd-0.9.0/tcl/board/st_nucleo_f0.cfg0000644000175000017500000000071712526202242015004 00000000000000# This is for all ST NUCLEO with any STM32F0. Known boards at the moment: # STM32F030R8 # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259997 # NUCLEO-F072RB # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259997 # STM32F091RC # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260944 source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32f0x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/phytec_lpc3250.cfg0000644000175000017500000000406212526202242015065 00000000000000source [find target/lpc3250.cfg] adapter_nsrst_delay 200 jtag_ntrst_delay 1 adapter_khz 200 reset_config trst_and_srst separate arm7_9 dcc_downloads enable $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-start { arm7_9 fast_memory_access disable adapter_khz 200 } $_TARGETNAME configure -event reset-end { adapter_khz 6000 arm7_9 fast_memory_access enable } $_TARGETNAME configure -event reset-init { phytec_lpc3250_init } # Bare-bones initialization of core clocks and SDRAM proc phytec_lpc3250_init { } { # Set clock dividers # ARMCLK = 266.5 MHz # HCLK = 133.25 MHz # PERIPHCLK = 13.325 MHz mww 0x400040BC 0 mww 0x40004050 0x140 mww 0x40004040 0x4D mww 0x40004058 0x16250 # Init PLLs mww 0x40004044 0x006 sleep 1 busy mww 0x40004044 0x106 sleep 1 busy mww 0x40004044 0x006 sleep 1 busy mww 0x40004048 0x2 # Init SDRAM with 133 MHz timings mww 0x40028134 0x00FFFFFF mww 0x4002802C 0x00000008 mww 0x31080000 1 mww 0x31080008 0 mww 0x40004068 0x1C000 mww 0x31080028 0x11 mww 0x31080400 0 mww 0x31080440 0 mww 0x31080460 0 mww 0x31080480 0 # Delays mww 0x31080030 1 mww 0x31080034 6 mww 0x31080038 10 mww 0x31080044 1 mww 0x31080048 9 mww 0x3108004C 12 mww 0x31080050 10 mww 0x31080054 1 mww 0x31080058 1 mww 0x3108005C 0 mww 0x31080100 0x5680 mww 0x31080104 0x302 # Init sequence mww 0x31080020 0x193 sleep 1 busy mww 0x31080024 1 mww 0x31080020 0x113 sleep 1 busy mww 0x31080020 0x013 sleep 1 busy mww 0x31080024 65 mww 0x31080020 0x093 mdw 0x80020000 mww 0x31080020 0x013 # SYS_CTRL remapping mww 0x40004014 1 } openocd-0.9.0/tcl/board/st_nucleo_f3.cfg0000644000175000017500000000041512526202242015002 00000000000000# This is an ST NUCLEO F334R8 board with a single STM32F334R8T6 chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260004 source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32f3x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/st_nucleo_f4.cfg0000644000175000017500000000057212526202242015007 00000000000000# This is for all ST NUCLEO with any STM32F4. Known boards at the moment: # STM32F401RET6 # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260000 # STM32F411RET6 # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260320 source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/hilscher_nxhx50.cfg0000644000175000017500000000202612526202242015432 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx50.cfg] reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x10000000 -work-area-phys 0x10000000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -event reset-init { halt arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable sdram_fix puts "Configuring SDRAM controller for MT48LC2M32 (8MB) " mww 0x1C000140 0 mww 0x1C000144 0x00A12151 mww 0x1C000140 0x030D0001 puts "Configuring SRAM nCS0 for 90ns Par. Flash (x16)" mww 0x1C000100 0x01010008 flash probe 0 } ##################### # Flash configuration ##################### #flash bank flash bank parflash cfi 0xC0000000 0x01000000 2 2 $_TARGETNAME init reset init openocd-0.9.0/tcl/board/lubbock.cfg0000644000175000017500000000530012526202242014036 00000000000000# Intel "Lubbock" Development Board with PXA255 (dbpxa255) # Obsolete; this was Intel's original PXA255 development system # Board also had CPU cards for SA1100, PXA210, PXA250, and more. source [find target/pxa255.cfg] adapter_nsrst_delay 250 jtag_ntrst_delay 250 # NOTE: until after pinmux and such are set up, only CS0 is # available ... not 2nd bank of CFI, or FPGA, SRAM, ENET, etc. # CS0, CS1 -- two banks of CFI flash, 32 MBytes each # each bank is 32-bits wide, two 16-bit chips in parallel set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME cfi 0x04000000 0x02000000 2 4 $_TARGETNAME # CS2 low -- FPGA registers # CS2 high -- 1 MByte SRAM at 0x0a00.0000 ... last 64K for scratch $_TARGETNAME configure -work-area-phys 0x0a0f0000 $_TARGETNAME configure -event reset-assert-pre \ "$_TARGETNAME configure -work-area-size 0" # Make the hex led display a number, assuming CS2 is set up # and all digits have been enabled through the FPGA. proc hexled {u32} { mww 0x08000010 $u32 } # CS3 -- Ethernet # CS4 -- SA1111 # CS5 -- PCMCIA # NOTE: system console normally uses the FF UART connector proc lubbock_init {target} { echo "Initialize PXA255 Lubbock board" # (1) pinmux # GPSR0..GPSR2 mww 0x40e00018 0x00008000 mww 0x40e0001c 0x00FC0382 mww 0x40e00020 0x0001FFFF # GPDR0..GPDR2 mww 0x40e0000c 0x0060A800 mww 0x40e00010 0x00FF0382 mww 0x40e00014 0x0001C000 # GAFR0_[LU]..GAFR2_[LU] mww 0x40e00054 0x98400000 mww 0x40e00058 0x00002950 mww 0x40e0005c 0x000A9558 mww 0x40e00060 0x0005AAAA mww 0x40e00064 0xA0000000 mww 0x40e00068 0x00000002 # write PSSR, enable GPIOs mww 0x40f00000 0x00000020 # write LED ctrl register ... ones disable # high byte, 8 hex leds; low byte, 8 discretes mwh 0x08000040 0xf0ff hexled 0x0000 # (2) Address space setup # MSC0/MSC1/MSC2 mww 0x48000008 0x23f223f2 mww 0x4800000c 0x3ff1a441 mww 0x48000010 0x7ff97ff1 # pcmcia/cf mww 0x48000014 0x00000000 mww 0x48000028 0x00010504 mww 0x4800002c 0x00010504 mww 0x48000030 0x00010504 mww 0x48000034 0x00010504 mww 0x48000038 0x00004715 mww 0x4800003c 0x00004715 hexled 0x1111 # (3) SDRAM setup # REVISIT this looks dubious ... no refresh cycles mww 0x48000004 0x03CA4018 mww 0x48000004 0x004B4018 mww 0x48000004 0x000B4018 mww 0x48000004 0x000BC018 mww 0x48000000 0x00001AC8 mww 0x48000000 0x00001AC9 mww 0x48000040 0x00000000 # FIXME -- setup: # CLOCKS (and faster JTAG) # enable icache # FIXME SRAM isn't working # $target configure -work-area-size 0x10000 hexled 0x2222 flash probe 0 flash probe 1 hexled 0xcafe } $_TARGETNAME configure -event reset-init "lubbock_init $_TARGETNAME" openocd-0.9.0/tcl/board/spear300evb.cfg0000644000175000017500000000230112526202242014445 00000000000000# Configuration for the ST SPEAr300 Evaluation board # EVALSPEAr300 Rev. 1.0 # http://www.st.com/spear # # Date: 2010-11-27 # Author: Antonio Borneo # The standard board has JTAG SRST not connected. # This script targets such boards using quirky code to bypass the issue. source [find mem_helper.tcl] source [find target/spear3xx.cfg] source [find chip/st/spear/spear3xx_ddr.tcl] source [find chip/st/spear/spear3xx.tcl] arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable # Serial NOR on SMI CS0. 8Mbyte. set _FLASHNAME1 $_CHIPNAME.snor flash bank $_FLASHNAME1 stmsmi 0xf8000000 0 0 0 $_TARGETNAME if { [info exists BOARD_HAS_SRST] } { # Modified board has SRST on JTAG connector reset_config trst_and_srst separate srst_gates_jtag \ trst_push_pull srst_open_drain } else { # Standard board has no SRST on JTAG connector reset_config trst_only separate srst_gates_jtag trst_push_pull source [find chip/st/spear/quirk_no_srst.tcl] } $_TARGETNAME configure -event reset-init { spear300evb_init } proc spear300evb_init {} { reg pc 0xffff0020; # loop forever sp3xx_clock_default sp3xx_common_init sp3xx_ddr_init "mt47h64m16_3_333_cl5_async" sp300_init } openocd-0.9.0/tcl/board/olimex_LPC2378STK.cfg0000644000175000017500000000041212526202242015315 00000000000000##################################################### # Olimex LPC2378STK eval board # # http://olimex.com/dev/lpc-2378stk.html # # Author: Sten, debian@sansys-electronic.com ##################################################### # source [find target/lpc2378.cfg] openocd-0.9.0/tcl/board/stm3210b_eval.cfg0000644000175000017500000000036712526202242014707 00000000000000# This is an STM32 eval board with a single STM32F10x (128KB) chip. # http://www.st.com/internet/evalboard/product/176090.jsp # increase working area to 32KB for faster flash programming set WORKAREASIZE 0x8000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/tx27_stk5.cfg0000644000175000017500000000301312526202242014166 00000000000000# KaRo TX27 CPU Module on a StarterkitV base board # # http://www.karo-electronics.com/tx27.html # source [find target/imx27.cfg] $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { tx27_init } proc tx27_init { } { # This setup puts RAM at 0xA0000000 # init_aipi (AIPI1.PSR0, AIPI2.PSR0, AIPI1.PSR1 and AIPI2.PSR1) mww 0x10000000 0x20040304 mww 0x10020000 0x00000000 mww 0x10000004 0xDFFBFCFB mww 0x10020004 0xFFFFFFFF sleep 100 #init_max ( PORT0.MPR, #PORT0.AMPR, #PORT1.MPR, #PORT1.AMPR, #PORT2.MPR, #PORT2.AMPR) mww 0x1003F000 0x00302145 mww 0x1003F004 0x00302145 mww 0x1003F100 0x00302145 mww 0x1003F104 0x00302145 mww 0x1003F200 0x00302145 mww 0x1003F204 0x00302145 #init_drive_strength (#DSCR3, #DSCR5, #DSCR6, #DSCR7, #DSCR8 ) mww 0x10027828 0x55555555 mww 0x10027830 0x55555555 mww 0x10027834 0x55555555 mww 0x10027838 0x00005005 mww 0x1002783C 0x15555555 #init_sdram_speed #mww 0xD8001010 0x00000004 mww 0xD8001010 0x00000024 mww 0xD8001004 0x00395729 mww 0xD8001000 0x92120000 mww 0xA0000400 0x0 mww 0xD8001000 0xA2120000 mww 0xA0000000 0x0 mww 0xA0000000 0x0 mww 0xD8001000 0xB2120000 mdb 0xA0000000 mdb 0xA0000033 mww 0xD8001000 0x82126485 # ============================================= # Sync mode (AHB Clk = 133MHz ; BCLK = 44.3MHz) # ============================================= mww 0xD8002000 0x23524E80 mww 0xD8002004 0x10000D03 mww 0xD8002008 0x00720900 nand probe 0 } nand device tx27.nand mxc $_TARGETNAME mx27 hwecc biswap openocd-0.9.0/tcl/board/imx53loco.cfg0000644000175000017500000002326612526202242014252 00000000000000################################################################################## # Author: Wjatscheslaw Stoljarski (Slawa) # # Kiwigrid GmbH # ################################################################################## # The IMX53LOCO (QSB) board has a single IMX53 chip source [find target/imx53.cfg] # Helper for common memory read/modify/write procedures source [find mem_helper.tcl] echo "iMX53 Loco board lodaded." # Set reset type #reset_config srst_only adapter_khz 3000 # Slow speed to be sure it will work jtag_rclk 1000 $_TARGETNAME configure -event "reset-start" { jtag_rclk 1000 } #jtag_nsrst_delay 200 #jtag_ntrst_delay 200 $_TARGETNAME configure -event "reset-assert" { echo "Reseting ...." #cortex_a dbginit } $_TARGETNAME configure -event reset-init { loco_init } global AIPS1_BASE_ADDR set AIPS1_BASE_ADDR 0x53F00000 global AIPS2_BASE_ADDR set AIPS2_BASE_ADDR 0x63F00000 proc loco_init { } { echo "Reset-init..." ; # halt the CPU halt echo "HW version [format %x [mrw 0x48]]" dap apsel 1 DCD ; # ARM errata ID #468414 set tR [arm mrc 15 0 1 0 1] arm mcr 15 0 1 0 1 [expr $tR | (1<<5)] ; # enable L1NEON bit init_l2cc init_aips init_clock dap apsel 0 ; # Force ARM state ; #reg cpsr 0x000001D3 arm core_state arm jtag_rclk 3000 # adapter_khz 3000 } # L2CC Cache setup/invalidation/disable proc init_l2cc { } { ; #/* explicitly disable L2 cache */ ; #mrc 15, 0, r0, c1, c0, 1 set tR [arm mrc 15 0 1 0 1] ; #bic r0, r0, #0x2 ; #mcr 15, 0, r0, c1, c0, 1 arm mcr 15 0 1 0 1 [expr $tR & ~(1<<2)] ; #/* reconfigure L2 cache aux control reg */ ; #mov r0, #0xC0 /* tag RAM */ ; #add r0, r0, #0x4 /* data RAM */ ; #orr r0, r0, #(1 << 24) /* disable write allocate delay */ ; #orr r0, r0, #(1 << 23) /* disable write allocate combine */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] } # AIPS setup - Only setup MPROTx registers. # The PACR default values are good. proc init_aips { } { ; # Set all MPROTx to be non-bufferable, trusted for R/W, ; # not forced to user-mode. global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set VAL 0x77777777 # dap apsel 1 mww [expr $AIPS1_BASE_ADDR + 0x0] $VAL mww [expr $AIPS1_BASE_ADDR + 0x4] $VAL mww [expr $AIPS2_BASE_ADDR + 0x0] $VAL mww [expr $AIPS2_BASE_ADDR + 0x4] $VAL # dap apsel 0 } proc init_clock { } { global AIPS1_BASE_ADDR global AIPS2_BASE_ADDR set CCM_BASE_ADDR [expr $AIPS1_BASE_ADDR + 0x000D4000] set CLKCTL_CCSR 0x0C set CLKCTL_CBCDR 0x14 set CLKCTL_CBCMR 0x18 set PLL1_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00080000] set PLL2_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00084000] set PLL3_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x00088000] set PLL4_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x0008C000] set CLKCTL_CSCMR1 0x1C set CLKCTL_CDHIPR 0x48 set PLATFORM_BASE_ADDR [expr $AIPS2_BASE_ADDR + 0x000A0000] set CLKCTL_CSCDR1 0x24 set CLKCTL_CCDR 0x04 ; # Switch ARM to step clock mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x4 return echo "not returned" setup_pll $PLL1_BASE_ADDR 800 setup_pll $PLL3_BASE_ADDR 400 ; # Switch peripheral to PLL3 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00015154 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x02888945 | (1<<16)] while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL2_BASE_ADDR 400 ; # Switch peripheral to PLL2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCDR] [expr 0x00808145 | (2<<10) | (9<<16) | (1<<19)] mww [expr $CCM_BASE_ADDR + $CLKCTL_CBCMR] 0x00016154 ; # change uart clk parent to pll2 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCMR1]] & 0xfcffffff | 0x01000000] ; # make sure change is effective while {[mrw [expr $CCM_BASE_ADDR + $CLKCTL_CDHIPR]] != 0} { sleep 1 } setup_pll $PLL3_BASE_ADDR 216 setup_pll $PLL4_BASE_ADDR 455 ; # Set the platform clock dividers mww [expr $PLATFORM_BASE_ADDR + 0x14] 0x00000124 mww [expr $CCM_BASE_ADDR + 0x10] 0 ; # Switch ARM back to PLL 1. mww [expr $CCM_BASE_ADDR + $CLKCTL_CCSR] 0x0 ; # make uart div=6 mww [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1] [expr [mrw [expr $CCM_BASE_ADDR + $CLKCTL_CSCDR1]] & 0xffffffc0 | 0x0a] ; # Restore the default values in the Gate registers mww [expr $CCM_BASE_ADDR + 0x68] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x6C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x70] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x74] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x78] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x7C] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x80] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + 0x84] 0xFFFFFFFF mww [expr $CCM_BASE_ADDR + $CLKCTL_CCDR] 0x00000 ; # for cko - for ARM div by 8 mww [expr $CCM_BASE_ADDR + 0x60] [expr 0x000A0000 & 0x00000F0] } proc setup_pll { PLL_ADDR CLK } { set PLL_DP_CTL 0x00 set PLL_DP_CONFIG 0x04 set PLL_DP_OP 0x08 set PLL_DP_HFS_OP 0x1C set PLL_DP_MFD 0x0C set PLL_DP_HFS_MFD 0x20 set PLL_DP_MFN 0x10 set PLL_DP_HFS_MFN 0x24 if {$CLK == 1000} { set DP_OP [expr (10 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (12 - 1)] set DP_MFN 5 } elseif {$CLK == 850} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 41 } elseif {$CLK == 800} { set DP_OP [expr (8 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 700} { set DP_OP [expr (7 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 7 } elseif {$CLK == 600} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 1 } elseif {$CLK == 665} { set DP_OP [expr (6 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (96 - 1)] set DP_MFN 89 } elseif {$CLK == 532} { set DP_OP [expr (5 << 4) + ((1 - 1) << 0)] set DP_MFD [expr (24 - 1)] set DP_MFN 13 } elseif {$CLK == 455} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (48 - 1)] set DP_MFN 71 } elseif {$CLK == 400} { set DP_OP [expr (8 << 4) + ((2 - 1) << 0)] set DP_MFD [expr (3 - 1)] set DP_MFN 1 } elseif {$CLK == 216} { set DP_OP [expr (6 << 4) + ((3 - 1) << 0)] set DP_MFD [expr (4 - 1)] set DP_MFN 3 } else { error "Error (setup_dll): clock not found!" } mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 mww [expr $PLL_ADDR + $PLL_DP_CONFIG] 0x2 mww [expr $PLL_ADDR + $PLL_DP_OP] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_OP mww [expr $PLL_ADDR + $PLL_DP_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_HFS_MFD] $DP_MFD mww [expr $PLL_ADDR + $PLL_DP_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_HFS_MFN] $DP_MFN mww [expr $PLL_ADDR + $PLL_DP_CTL] 0x00001232 while {[expr [mrw [expr $PLL_ADDR + $PLL_DP_CTL]] & 0x1] == 0} { sleep 1 } } proc CPU_2_BE_32 { L } { return [expr (($L & 0x000000FF) << 24) | (($L & 0x0000FF00) << 8) | (($L & 0x00FF0000) >> 8) | (($L & 0xFF000000) >> 24)] } # Device Configuration Data proc DCD { } { # dap apsel 1 mww 0x53FA8554 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 mww 0x53FA8558 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 mww 0x53FA8560 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 mww 0x53FA8564 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT mww 0x53FA8568 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 mww 0x53FA8570 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1 mww 0x53FA8574 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS mww 0x53FA8578 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 mww 0x53FA857c 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 mww 0x53FA8580 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 mww 0x53FA8584 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 mww 0x53FA8588 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS mww 0x53FA8590 0x00300040 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 mww 0x53FA8594 0x00300000 ;# IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 mww 0x53FA86f0 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_ADDDS mww 0x53FA86f4 0x00000000 ;# IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL mww 0x53FA86fc 0x00000000 ;# IOMUXC_SW_PAD_CTL_GRP_DDRPKE mww 0x53FA8714 0x00000000 ;# IOMUXC_SW_PAD_CTL_GRP_DDRMODE - CMOS mode mww 0x53FA8718 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_B0DS mww 0x53FA871c 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_B1DS mww 0x53FA8720 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_CTLDS mww 0x53FA8724 0x04000000 ;# IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE - DDR_SEL0= mww 0x53FA8728 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_B2DS mww 0x53FA872c 0x00300000 ;# IOMUXC_SW_PAD_CTL_GRP_B3DS # Initialize DDR2 memory mww 0x63FD9088 0x35343535 ;# ESDCTL_RDDLCTL mww 0x63FD9090 0x4d444c44 ;# ESDCTL_WRDLCTL mww 0x63FD907c 0x01370138 ;# ESDCTL_DGCTRL0 mww 0x63FD9080 0x013b013c ;# ESDCTL_DGCTRL1 mww 0x63FD9018 0x00011740 ;# ESDCTL_ESDMISC mww 0x63FD9000 0xc3190000 ;# ESDCTL_ESDCTL mww 0x63FD900c 0x9f5152e3 ;# ESDCTL_ESDCFG0 mww 0x63FD9010 0xb68e8a63 ;# ESDCTL_ESDCFG1 mww 0x63FD9014 0x01ff00db ;# ESDCTL_ESDCFG2 mww 0x63FD902c 0x000026d2 ;# ESDCTL_ESDRWD mww 0x63FD9030 0x009f0e21 ;# ESDCTL_ESDOR mww 0x63FD9008 0x12273030 ;# ESDCTL_ESDOTC mww 0x63FD9004 0x0002002d ;# ESDCTL_ESDPDC mww 0x63FD901c 0x00008032 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x00008033 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x00028031 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x052080b0 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x04008040 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x0000803a ;# ESDCTL_ESDSCR mww 0x63FD901c 0x0000803b ;# ESDCTL_ESDSCR mww 0x63FD901c 0x00028039 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x05208138 ;# ESDCTL_ESDSCR mww 0x63FD901c 0x04008048 ;# ESDCTL_ESDSCR mww 0x63FD9020 0x00005800 ;# ESDCTL_ESDREF mww 0x63FD9040 0x04b80003 ;# ESDCTL_ZQHWCTRL mww 0x63FD9058 0x00022227 ;# ESDCTL_ODTCTRL mww 0x63FD901C 0x00000000 ;# ESDCTL_ESDSCR # dap apsel 0 } # vim:filetype=tcl openocd-0.9.0/tcl/board/ek-lm4f232.cfg0000644000175000017500000000052712526202242014111 00000000000000# # TI Stellaris LM4F232 Evaluation Kits # # http://www.ti.com/tool/ek-lm4f232 # # # NOTE: using the bundled ICDI interface is optional! # This interface is not ftdi based as previous boards were # source [find interface/ti-icdi.cfg] transport select hla_jtag set WORKAREASIZE 0x8000 set CHIPNAME lm4f23x source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/st_nucleo_f103rb.cfg0000644000175000017500000000041512526202242015467 00000000000000# This is an ST NUCLEO F103RB board with a single STM32F103RBT6 chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875 source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32f1x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/digi_connectcore_wi-9c.cfg0000644000175000017500000000732612526202242016735 00000000000000###################################### # Target: DIGI ConnectCore Wi-9C ###################################### reset_config trst_and_srst # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME ns9360 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # This config file was defaulting to big endian.. set _ENDIAN big } # What's a good fallback frequency for this board if RCLK is # not available?? jtag_rclk 1000 if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926031 } set _TARGETNAME $_CHIPNAME.cpu jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID adapter_nsrst_delay 200 jtag_ntrst_delay 0 ###################### # Target configuration ###################### target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { mww 0x90600104 0x33313333 mww 0xA0700000 0x00000001 ;# Enable the memory controller. mww 0xA0700024 0x00000006 ;# Set the refresh counter 6 mww 0xA0700028 0x00000001 ;# mww 0xA0700030 0x00000001 ;# Set the precharge period mww 0xA0700034 0x00000004 ;# Active to precharge command period is 16 clock cycles mww 0xA070003C 0x00000001 ;# tAPR mww 0xA0700040 0x00000005 ;# tDAL mww 0xA0700044 0x00000001 ;# tWR mww 0xA0700048 0x00000006 ;# tRC 32 clock cycles mww 0xA070004C 0x00000006 ;# tRFC 32 clock cycles mww 0xA0700054 0x00000001 ;# tRRD mww 0xA0700058 0x00000001 ;# tMRD mww 0xA0700100 0x00004280 ;# Dynamic Config 0 (cs4) mww 0xA0700120 0x00004280 ;# Dynamic Config 1 (cs5) mww 0xA0700140 0x00004280 ;# Dynamic Config 2 (cs6) mww 0xA0700160 0x00004280 ;# Dynamic Config 3 (cs7) # mww 0xA0700104 0x00000203 ;# CAS latency is 2 at 100 MHz mww 0xA0700124 0x00000203 ;# CAS latency is 2 at 100 MHz mww 0xA0700144 0x00000203 ;# CAS latency is 2 at 100 MHz mww 0xA0700164 0x00000203 ;# CAS latency is 2 at 100 MHz # mww 0xA0700020 0x00000103 ;# issue SDRAM PALL command # mww 0xA0700024 0x00000001 ;# Set the refresh counter to be as small as possible # # Add some dummy writes to give the SDRAM time to settle, it needs two # AHB clock cycles, here we poke in the debugger flag, this lets # the software know that we are in the debugger mww 0xA0900000 0x00000002 mww 0xA0900000 0x00000002 mww 0xA0900000 0x00000002 mww 0xA0900000 0x00000002 mww 0xA0900000 0x00000002 # mdw 0xA0900000 mdw 0xA0900000 mdw 0xA0900000 mdw 0xA0900000 mdw 0xA0900000 # mww 0xA0700024 0x00000030 ;# Set the refresh counter to 30 mww 0xA0700020 0x00000083 ;# Issue SDRAM MODE command # # Next we perform a read of RAM. # mw = move word. mdw 0x00022000 # mw 0x00022000:P, r3 # 22000 for cas2 latency, 32000 for cas 3 # mww 0xA0700020 0x00000003 ;# issue SDRAM NORMAL command mww 0xA0700100 0x00084280 ;# Enable buffer access mww 0xA0700120 0x00084280 ;# Enable buffer access mww 0xA0700140 0x00084280 ;# Enable buffer access mww 0xA0700160 0x00084280 ;# Enable buffer access #Set byte lane state (static mem 1)" mww 0xA0700220 0x00000082 #Flash Start mww 0xA09001F8 0x50000000 #Flash Mask Reg mww 0xA09001FC 0xFF000001 mww 0xA0700028 0x00000001 # RAMAddr = 0x00020000 # RAMSize = 0x00004000 # Set the processor mode reg cpsr 0xd3 } $_TARGETNAME configure -work-area-phys 0x00000000 -work-area-size 0x1000 -work-area-backup 1 ##################### # Flash configuration ##################### #M29DW323DB - not working #flash bank cfi set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x50000000 0x0400000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/ti_am437x_idk.cfg0000644000175000017500000000056012526202242014766 00000000000000# Texas Instruments AM437x Industrial Development Kit # The JTAG interface is built directly on the board. source [find interface/ftdi/xds100v2.cfg] transport select jtag adapter_khz 16000 source [find target/am437x.cfg] $_TARGETNAME configure -event reset-init { init_platform 0x61a11b32 } reset_config trst_and_srst init ftdi_set_signal PWR_RST 1 jtag arp_init openocd-0.9.0/tcl/board/hilscher_nxeb500hmi.cfg0000644000175000017500000000202412526202242016155 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx500.cfg] reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x1000 -work-area-phys 0x1000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -event reset-init { halt arm7_9 fast_memory_access enable arm7_9 dcc_downloads disable sdram_fix puts "Configuring SDRAM controller for MT48LC8M32 (32MB) " mww 0x00100140 0 mww 0x00100144 0x03C23251 mww 0x00100140 0x030D0111 puts "Configuring SRAM nCS0 for 150ns Par. Flash (x16)" mww 0x00100100 0x0101000E flash probe 0 } ##################### # Flash configuration ##################### #flash bank flash bank parflash cfi 0xC0000000 0x01000000 2 2 $_TARGETNAME init reset init openocd-0.9.0/tcl/board/ti_pandaboard_es.cfg0000644000175000017500000000011312526202242015670 00000000000000jtag_rclk 6000 source [find target/omap4460.cfg] reset_config trst_only openocd-0.9.0/tcl/board/ti-cc3200-launchxl.cfg0000644000175000017500000000046712526202242015546 00000000000000# # TI SimpleLink Wi-Fi CC3200 LaunchPad # # http://www.ti.com/tool/cc3200-launchxl # source [find interface/ftdi/ti-icdi.cfg] if { [info exists TRANSPORT] } { transport select $TRANSPORT } else { transport select jtag } set WORKAREASIZE 0x40000 source [find target/cc32xx.cfg] reset_config srst_only openocd-0.9.0/tcl/board/glyn_tonga2.cfg0000644000175000017500000001555412526202242014654 00000000000000# # Glyn Tonga2 SO-DIMM CPU module (Toshiba TMPA900CMXBG, ARM9) # # http://toshiba-mikrocontroller.de/sites/TMPA900CPUBOARDStarter.htm # # Hardware on the S0-DIMM module: # - Toshiba TMPA900CMXBG (ARM9, ARM926EJ-S, max. 200MHz) # - DDR SDRAM: Hynix H5MS5162DFR-J3M (64Mbyte, x16, 1.8V, 166/83MHz at CL3/2) # - NAND flash: Samsung K9F2G08U0B-PIB0 (256M x 8 Bit, 3.3V) # - Ethernet: SMSC LAN9221I-ABZJ (10/100Mbit, Non-PCI, 16 bit interface) # source [find target/tmpa900.cfg] ######################## # Target configuration # ######################## # Initial JTAG speed should not exceed 1/6 of the initial CPU clock # frequency (24MHz). Be conservative and use 1/8 of the frequency. # (24MHz / 8 = 3MHz) adapter_khz 3000 $_TARGETNAME configure -event reset-start { # Upon reset, set the JTAG frequency to 3MHz again, see above. echo "Setting JTAG speed to 3MHz until clocks are initialized." adapter_khz 3000 # Halt the CPU. halt # Disable faster memory access for now. arm7_9 fast_memory_access disable } $_TARGETNAME configure -event reset-init { # Setup clocks, and initialize SRAM and DDR SDRAM. tonga2_init # At this point the CPU is running at 192MHz, increase JTAG speed. # Tests showed that 15MHz works OK, higher speeds can cause problems, # though. Not sure if this is a CPU issue or JTAG adapter issue. echo "Increasing JTAG speed to 15MHz." adapter_khz 15000 # Enable faster memory access. arm7_9 fast_memory_access enable } proc tonga2_init { } { ###################### # PLL initialization # ###################### # Clock overview (see datasheet chapter 3.5.2, page 57): # - fs: Low-frequency oscillator # - fOSCH: High-frequency oscillator (24MHz on this board) # - fPLL = fOSCH * multiplier (where multiplier can be 6 or 8) # - fFCLK = fPLL / gear (where gear can be 1/2/4/8) # - fHCLK is always fFCLK/2. fPCLK is also fFCLK/2. # # We select multiplier = 8 and gear = 1, so # fFCLK = fOSCH * 8 / 1 = 192MHz. # SYSCR3 (System Control Register 3): Disable and configure PLL. # - PLL operation control: off # - PLL constant value setting 1: always 0, as per datasheet # - PLL constant value setting 2: x8 (multiplier = 8) mww 0xf005000c 0x00000007 # SYSCR4 (System Control Register 4): Configure PLL. # - PLL constant value setting 3: 140MHz or more # - PLL constant value setting 4: always 1, as per datasheet # - PLL constant value setting 5: 140MHz or more mww 0xf0050010 0x00000065 # SYSCR3 (System Control Register 3): Enable PLL. # - PLL operation control: on # - All other bits remain set as above. mww 0xf005000c 0x00000087 # Wait for PLL to stabilize. sleep 10 # SYSCR2 (System Control Register 2): Switch from fOSCH to fPLL. # - Selection of the PLL output clock: fPLL mww 0xf0050008 0x00000002 # SYSCR1 (System Control Register 1): # - Clock gear programming: fc/1 (i.e., gear = 1, don't divide). mww 0xf0050004 0x00000000 # CLKCR5 (Clock Control Register 5): Set bits 3 and 6. The datasheet # says the bits are reserved, but also recommends "Write as one". mww 0xf0050054 0x00000048 ############################################################## # Dynamic Memory Controller (DMC) / DDR SDRAM initialization # ############################################################## # PMC (Power Management Controller): # PMCDRV (External Port "Driverbility" control register): # Bits DRV_MEM0/DRV_MEM1 (memory relation port drive power): mww 0xf0020260 0x00000003 ;# Select 1.8V +/- 0.1V # Setup DDR SDRAM timing parameters for our specific chip. mww 0xf4310014 0x00000004 ;# cas_latency = 2 mww 0xf4310018 0x00000001 ;# t_dqss = 1 mww 0xf431001c 0x00000002 ;# t_mrd = 2 mww 0xf4310020 0x0000000a ;# t_ras = 10 mww 0xf4310024 0x0000000a ;# t_rc = 10 mww 0xf4310028 0x00000013 ;# t_rcd = 3, schedule_rcd = 2 mww 0xf431002c 0x0000010a ;# t_rfc = 10, schedule_rfc = 8 mww 0xf4310030 0x00000013 ;# t_rp = 3, schedule_rp = 2 mww 0xf4310034 0x00000002 ;# t_rrd = 2 mww 0xf4310038 0x00000002 ;# t_wr = 2 mww 0xf431003c 0x00000001 ;# t_wtr = 1 mww 0xf4310040 0x0000000a ;# t_xp = 10 mww 0xf4310044 0x0000000c ;# t_xsr = 12 mww 0xf4310048 0x00000014 ;# t_esr = 20 # dmc_memory_cfg_5 (DMC Memory Configuration register): # Set memory configuration: # column_bits = 10, row_bits = 13, ap-bit = 10, power_down_prd = 0, # auto_power_down = disable, stop_mem_clock = disable, memory_burst = 4 mww 0xf431000c 0x00010012 # dmc_user_config_5 (DMC user_config register): # Data bus width of DDR SDRAM: 16 bit mww 0xf4310304 0x00000058 # dmc_refresh_prd_5 (DMC Refresh Period register): # Auto refresh: every 2656 (0xa60) DMCSCLK periods. mww 0xf4310010 0x00000a60 # dmc_chip_0_cfg_5 (DMC chip_0_cfg registers): # - SDRAM address structure: bank, row, column # - address_match = 01000000 (start address [31:24]) # - address_mask = 11111100 (start address [31:24] mask value) mww 0xf4310200 0x000140fc # Initialize the DDR SDRAM chip. # dmc_direct_cmd_5 (DMC Direct Command register). # See datasheet chapter 3.10.5.1, page 268. mww 0xf4310008 0x000c0000 ;# RAM init: NOP mww 0xf4310008 0x00000000 ;# RAM init: Precharge all mww 0xf4310008 0x00040000 ;# RAM init: Autorefresh mww 0xf4310008 0x00040000 ;# RAM init: Autorefresh mww 0xf4310008 0x00080032 ;# RAM init: addr_13_to_0 = 0x32 mww 0xf4310008 0x000c0000 ;# RAM init: NOP mww 0xf4310008 0x000a0000 ;# RAM init: bank_addr = bank 2 # dmc_id_<0-5>_cfg_5 (DMC id_<0-5>_cfg registers): # Set min./max. QoS values. # - 0x5: Enable QoS, max. QoS = 1 # - 0xb: Enable QoS, min. QoS = 2 mww 0xf4310100 0x00000005 ;# AHB0: CPU Data mww 0xf4310104 0x00000005 ;# AHB1: CPU Inst mww 0xf4310108 0x0000000b ;# AHB2: LCDC mww 0xf431010c 0x00000005 ;# AHB3: LCDDA, USB mww 0xf4310110 0x00000005 ;# AHB4: DMA1 mww 0xf4310114 0x00000005 ;# AHB5: DMA2 # dmc_memc_cmd_5 (DMC Memory Controller Command register): # Change DMC state to ready. mww 0xf4310004 0x00000000 ;# memc_cmd = "Go" # EBI: SMC Timeout register mww 0xf00a0050 0x00000001 ;# smc_timeout = 1 ######################################################## # Static Memory Controller (SMC) / SRAM initialization # ######################################################## # smc_set_cycles_5 (SMC Set Cycles register): # tRC = 10, tWC = 10, tCEOE = 7, tWP = 5, tPC=2, tTR=2 mww 0xf4311014 0x0004afaa # smc_set_opmode_5 (SMC Set Opmode register): # Memory data bus width = 16 bits, async read mode, read burst # length = 1 beat, async write mode, write burst length = 1 beat, # byte enable (SMCBE0-1) timing = SMCCSn timing, memory burst boundary # split setting = burst can cross any address boundary mww 0xf4311018 0x00000001 # smc_direct_cmd_5 (SMC Direct Command register): # cmd_type = UpdateRegs, chip_select = CS1 mww 0xf4311010 0x00c00000 echo "Clocks, SRAM, and DDR SDRAM are now initialized." } ####################### # Flash configuration # ####################### # TODO: Implement NAND support. openocd-0.9.0/tcl/board/atmel_samd21_xplained_pro.cfg0000644000175000017500000000024412526202242017434 00000000000000# # Atmel SAMD21 Xplained Pro evaluation kit. # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME at91samd21j18 source [find target/at91samdXX.cfg] openocd-0.9.0/tcl/board/sheevaplug.cfg0000644000175000017500000001123612526202242014565 00000000000000# Marvell SheevaPlug source [find interface/ftdi/sheevaplug.cfg] source [find target/feroceon.cfg] adapter_khz 2000 $_TARGETNAME configure \ -work-area-phys 0x10000000 \ -work-area-size 65536 \ -work-area-backup 0 arm7_9 dcc_downloads enable # this assumes the hardware default peripherals location before u-Boot moves it set _FLASHNAME $_CHIPNAME.flash nand device $_FLASHNAME orion 0 0xd8000000 proc sheevaplug_init { } { # We need to assert DBGRQ while holding nSRST down. # However DBGACK will be set only when nSRST is released. # Furthermore, the JTAG interface doesn't respond at all when # the CPU is in the WFI (wait for interrupts) state, so it is # possible that initial tap examination failed. So let's # re-examine the target again here when nSRST is asserted which # should then succeed. jtag_reset 0 1 feroceon.cpu arp_examine halt 0 jtag_reset 0 0 wait_halt arm mcr 15 0 0 1 0 0x00052078 mww 0xD0001400 0x43000C30 ;# DDR SDRAM Configuration Register mww 0xD0001404 0x39543000 ;# Dunit Control Low Register mww 0xD0001408 0x22125451 ;# DDR SDRAM Timing (Low) Register mww 0xD000140C 0x00000833 ;# DDR SDRAM Timing (High) Register mww 0xD0001410 0x000000CC ;# DDR SDRAM Address Control Register mww 0xD0001414 0x00000000 ;# DDR SDRAM Open Pages Control Register mww 0xD0001418 0x00000000 ;# DDR SDRAM Operation Register mww 0xD000141C 0x00000C52 ;# DDR SDRAM Mode Register mww 0xD0001420 0x00000042 ;# DDR SDRAM Extended Mode Register mww 0xD0001424 0x0000F17F ;# Dunit Control High Register mww 0xD0001428 0x00085520 ;# Dunit Control High Register mww 0xD000147c 0x00008552 ;# Dunit Control High Register mww 0xD0001504 0x0FFFFFF1 ;# CS0n Size Register mww 0xD0001508 0x10000000 ;# CS1n Base Register mww 0xD000150C 0x0FFFFFF5 ;# CS1n Size Register mww 0xD0001514 0x00000000 ;# CS2n Size Register mww 0xD000151C 0x00000000 ;# CS3n Size Register mww 0xD0001494 0x003C0000 ;# DDR2 SDRAM ODT Control (Low) Register mww 0xD0001498 0x00000000 ;# DDR2 SDRAM ODT Control (High) REgister mww 0xD000149C 0x0000F80F ;# DDR2 Dunit ODT Control Register mww 0xD0001480 0x00000001 ;# DDR SDRAM Initialization Control Register mww 0xD0020204 0x00000000 ;# Main IRQ Interrupt Mask Register mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0010000 0x01111111 ;# MPP 0 to 7 mww 0xD0010004 0x11113322 ;# MPP 8 to 15 mww 0xD0010008 0x00001111 ;# MPP 16 to 23 mww 0xD0010418 0x003E07CF ;# NAND Read Parameters REgister mww 0xD001041C 0x000F0F0F ;# NAND Write Parameters Register mww 0xD0010470 0x01C7D943 ;# NAND Flash Control Register } proc sheevaplug_reflash_uboot { } { # reflash the u-Boot binary and reboot into it sheevaplug_init nand probe 0 nand erase 0 0x0 0xa0000 nand write 0 uboot.bin 0 oob_softecc_kw resume } proc sheevaplug_reflash_uboot_env { } { # reflash the u-Boot environment variables area sheevaplug_init nand probe 0 nand erase 0 0xa0000 0x40000 nand write 0 uboot-env.bin 0xa0000 oob_softecc_kw resume } proc sheevaplug_load_uboot { } { # load u-Boot into RAM and execute it sheevaplug_init load_image uboot.elf verify_image uboot.elf resume 0x00600000 } openocd-0.9.0/tcl/board/osk5912.cfg0000644000175000017500000000220212526202242013530 00000000000000# http://omap.spectrumdigital.com/osk5912/ source [find target/omap5912.cfg] # NOTE: this assumes you're using the ARM 20-pin ("Multi-ICE") # JTAG connector, and accordingly have J1 connecting pins 1 & 2. # The TI-14 pin needs "trst_only", and J1 connecting 2 & 3. reset_config trst_and_srst separate # NOTE: boards with XOMAP parts wire nSRST to nPWRON_RESET. # That resets everything -- including JTAG and EmbeddedICE. # So they must use "reset_config srst_pulls_trst". # NOTE: an expansion board could add a trace connector ... if # it does, change this appropriately. And reset_config too, # assuming JTAG_DIS reroutes JTAG to that connector. etm config $_TARGETNAME 8 demultiplexed full dummy etm_dummy config $_TARGETNAME # standard boards populate two 16 MB chips, but manufacturing # options or an expansion board could change this config. flash bank osk.u1 cfi 0x00000000 0x01000000 2 2 $_TARGETNAME flash bank osk.u2 cfi 0x01000000 0x01000000 2 2 $_TARGETNAME proc osk5912_init {} { omap5912_reset # detect flash flash probe 0 flash probe 1 } $_TARGETNAME configure -event reset-init { osk5912_init } arm7_9 dcc_downloads enable openocd-0.9.0/tcl/board/rsc-w910.cfg0000644000175000017500000000322212526202242013703 00000000000000# Avalue RSC-W8910 sbc # http://www.avalue.com.tw/products/RSC-W910.cfm # 2MB NOR Flash # 64MB SDRAM # 128MB NAND Flash # Based on Nuvoton nuc910 source [find target/nuc910.cfg] # # reset only behaves correctly if we use srst_pulls_trst # reset_config trst_and_srst srst_pulls_trst adapter_khz 1000 adapter_nsrst_delay 100 jtag_ntrst_delay 100 $_TARGETNAME configure -work-area-phys 0x00000000 -work-area-size 0x04000000 -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x20000000 0x00200000 2 2 $_TARGETNAME set _NANDNAME $_CHIPNAME.nand nand device $_NANDNAME nuc910 $_TARGETNAME # # Target events # $_TARGETNAME configure -event reset-start {adapter_khz 1000} $_TARGETNAME configure -event reset-init { # switch on PLL for 200MHz operation # running from 15MHz input clock mww 0xB0000200 0x00000030 ;# CLKEN mww 0xB0000204 0x00000f3c ;# CLKSEL mww 0xB0000208 0x05007000 ;# CLKDIV mww 0xB000020C 0x00004f24 ;# PLLCON0 mww 0xB0000210 0x00002b63 ;# PLLCON1 mww 0xB000000C 0x08817fa6 ;# MFSEL sleep 10 # we are now running @ 200MHz # enable all openocd speed tweaks arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable adapter_khz 15000 # map nor flash to 0x20000000 # map sdram to 0x00000000 mww 0xb0001000 0x000530c1 ;# EBICON mww 0xb0001004 0x40030084 ;# ROMCON mww 0xb0001008 0x000010ee ;# SDCONF0 mww 0xb000100C 0x00000000 ;# SDCONF1 mww 0xb0001010 0x0000015b ;# SDTIME0 mww 0xb0001014 0x0000015b ;# SDTIME1 mww 0xb0001018 0x00000000 ;# EXT0CON mww 0xb000101C 0x00000000 ;# EXT1CON mww 0xb0001020 0x00000000 ;# EXT2CON mww 0xb0001024 0x00000000 ;# EXT3CON mww 0xb000102c 0x00ff0048 ;# CKSKEW } openocd-0.9.0/tcl/board/st_nucleo_l1.cfg0000644000175000017500000000041412526202242015005 00000000000000# This is an ST NUCLEO L152RE board with a single STM32L152RET6 chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260002 source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32l1.cfg] reset_config srst_only openocd-0.9.0/tcl/board/stm32429i_eval_stlink.cfg0000644000175000017500000000066112526202242016375 00000000000000# STM32429I-EVAL: This is an STM32F4 eval board with a single STM32F429NIH6 # (2048KB) chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1199/PF259093 # # This is for using the onboard STLINK/V2 source [find interface/stlink-v2.cfg] transport select hla_swd # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F429NIH6 source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/imx35pdk.cfg0000644000175000017500000001503712526202242014071 00000000000000# The IMX35PDK eval board has a single IMX35 chip source [find target/imx35.cfg] source [find target/imx.cfg] $_TARGETNAME configure -event reset-init { imx35pdk_init } # Stick to *really* low clock rate or reset will fail # without RTCK / RCLK jtag_rclk 10 proc imx35pdk_init { } { imx3x_reset mww 0x43f00040 0x00000000 mww 0x43f00044 0x00000000 mww 0x43f00048 0x00000000 mww 0x43f0004C 0x00000000 mww 0x43f00050 0x00000000 mww 0x43f00000 0x77777777 mww 0x43f00004 0x77777777 mww 0x53f00040 0x00000000 mww 0x53f00044 0x00000000 mww 0x53f00048 0x00000000 mww 0x53f0004C 0x00000000 mww 0x53f00050 0x00000000 mww 0x53f00000 0x77777777 mww 0x53f00004 0x77777777 # clock setup mww 0x53F80004 0x00821000 ;# first need to set IPU_HND_BYP mww 0x53F80004 0x00821000 ;#arm clock is 399Mhz and ahb clock is 133Mhz. #================================================= # WEIM config #================================================= # CS0U mww 0xB8002000 0x0000CC03 # CS0L mww 0xB8002004 0xA0330D01 # CS0A mww 0xB8002008 0x00220800 # CS5U mww 0xB8002050 0x0000dcf6 # CS5L mww 0xB8002054 0x444a4541 # CS5A mww 0xB8002058 0x44443302 # IO SW PAD Control registers - setting of 0x0002 is high drive, mDDR mww 0x43FAC368 0x00000006 mww 0x43FAC36C 0x00000006 mww 0x43FAC370 0x00000006 mww 0x43FAC374 0x00000006 mww 0x43FAC378 0x00000006 mww 0x43FAC37C 0x00000006 mww 0x43FAC380 0x00000006 mww 0x43FAC384 0x00000006 mww 0x43FAC388 0x00000006 mww 0x43FAC38C 0x00000006 mww 0x43FAC390 0x00000006 mww 0x43FAC394 0x00000006 mww 0x43FAC398 0x00000006 mww 0x43FAC39C 0x00000006 mww 0x43FAC3A0 0x00000006 mww 0x43FAC3A4 0x00000006 mww 0x43FAC3A8 0x00000006 mww 0x43FAC3AC 0x00000006 mww 0x43FAC3B0 0x00000006 mww 0x43FAC3B4 0x00000006 mww 0x43FAC3B8 0x00000006 mww 0x43FAC3BC 0x00000006 mww 0x43FAC3C0 0x00000006 mww 0x43FAC3C4 0x00000006 mww 0x43FAC3C8 0x00000006 mww 0x43FAC3CC 0x00000006 mww 0x43FAC3D0 0x00000006 mww 0x43FAC3D4 0x00000006 mww 0x43FAC3D8 0x00000006 # DDR data bus SD 0 through 31 mww 0x43FAC3DC 0x00000082 mww 0x43FAC3E0 0x00000082 mww 0x43FAC3E4 0x00000082 mww 0x43FAC3E8 0x00000082 mww 0x43FAC3EC 0x00000082 mww 0x43FAC3F0 0x00000082 mww 0x43FAC3F4 0x00000082 mww 0x43FAC3F8 0x00000082 mww 0x43FAC3FC 0x00000082 mww 0x43FAC400 0x00000082 mww 0x43FAC404 0x00000082 mww 0x43FAC408 0x00000082 mww 0x43FAC40C 0x00000082 mww 0x43FAC410 0x00000082 mww 0x43FAC414 0x00000082 mww 0x43FAC418 0x00000082 mww 0x43FAC41c 0x00000082 mww 0x43FAC420 0x00000082 mww 0x43FAC424 0x00000082 mww 0x43FAC428 0x00000082 mww 0x43FAC42c 0x00000082 mww 0x43FAC430 0x00000082 mww 0x43FAC434 0x00000082 mww 0x43FAC438 0x00000082 mww 0x43FAC43c 0x00000082 mww 0x43FAC440 0x00000082 mww 0x43FAC444 0x00000082 mww 0x43FAC448 0x00000082 mww 0x43FAC44c 0x00000082 mww 0x43FAC450 0x00000082 mww 0x43FAC454 0x00000082 mww 0x43FAC458 0x00000082 # DQM setup mww 0x43FAC45c 0x00000082 mww 0x43FAC460 0x00000082 mww 0x43FAC464 0x00000082 mww 0x43FAC468 0x00000082 mww 0x43FAC46c 0x00000006 mww 0x43FAC470 0x00000006 mww 0x43FAC474 0x00000006 mww 0x43FAC478 0x00000006 mww 0x43FAC47c 0x00000006 mww 0x43FAC480 0x00000006 ;# CSD0 mww 0x43FAC484 0x00000006 ;# CSD1 mww 0x43FAC488 0x00000006 mww 0x43FAC48c 0x00000006 mww 0x43FAC490 0x00000006 mww 0x43FAC494 0x00000006 mww 0x43FAC498 0x00000006 mww 0x43FAC49c 0x00000006 mww 0x43FAC4A0 0x00000006 mww 0x43FAC4A4 0x00000006 ;# RAS mww 0x43FAC4A8 0x00000006 ;# CAS mww 0x43FAC4Ac 0x00000006 ;# SDWE mww 0x43FAC4B0 0x00000006 ;# SDCKE0 mww 0x43FAC4B4 0x00000006 ;# SDCKE1 mww 0x43FAC4B8 0x00000002 ;# SDCLK # SDQS0 through SDQS3 mww 0x43FAC4Bc 0x00000082 mww 0x43FAC4C0 0x00000082 mww 0x43FAC4C4 0x00000082 mww 0x43FAC4C8 0x00000082 # *================================================== # Initialization script for 32 bit DDR2 on RINGO 3DS # *================================================== #-------------------------------------------- # Init CCM #-------------------------------------------- mww 0x53F80028 0x7D000028 #-------------------------------------------- # Init IOMUX for JTAG #-------------------------------------------- mww 0x43FAC5EC 0x000000C3 mww 0x43FAC5F0 0x000000C3 mww 0x43FAC5F4 0x000000F3 mww 0x43FAC5F8 0x000000F3 mww 0x43FAC5FC 0x000000F3 mww 0x43FAC600 0x000000F3 mww 0x43FAC604 0x000000F3 # ESD_MISC : enable DDR2 mww 0xB8001010 0x00000304 #-------------------------------------------- # Init 32-bit DDR2 memeory on CSD0 # COL=10-bit, ROW=13-bit, BA[1:0]=Addr[26:25] #-------------------------------------------- # ESD_ESDCFG0 : set timing paramters mww 0xB8001004 0x007ffC2f # ESD_ESDCTL0 : select Prechare-All mode mww 0xB8001000 0x92220000 # DDR2 : Prechare-All mww 0x80000400 0x12345678 # ESD_ESDCTL0 : select Load-Mode-Register mode mww 0xB8001000 0xB2220000 # DDR2 : Load reg EMR2 mwb 0x84000000 0xda # DDR2 : Load reg EMR3 mwb 0x86000000 0xda # DDR2 : Load reg EMR1 -- enable DLL mwb 0x82000400 0xda # DDR2 : Load reg MR -- reset DLL mwb 0x80000333 0xda # ESD_ESDCTL0 : select Prechare-All mode mww 0xB8001000 0x92220000 # DDR2 : Prechare-All mwb 0x80000400 0x12345678 # ESD_ESDCTL0 : select Manual-Refresh mode mww 0xB8001000 0xA2220000 # DDR2 : Manual-Refresh 2 times mww 0x80000000 0x87654321 mww 0x80000000 0x87654321 # ESD_ESDCTL0 : select Load-Mode-Register mode mww 0xB8001000 0xB2220000 # DDR2 : Load reg MR -- CL=3, BL=8, end DLL reset mwb 0x80000233 0xda # DDR2 : Load reg EMR1 -- OCD default mwb 0x82000780 0xda # DDR2 : Load reg EMR1 -- OCD exit mwb 0x82000400 0xda ;# ODT disabled # ESD_ESDCTL0 : select normal-operation mode # DSIZ=32-bit, BL=8, COL=10-bit, ROW=13-bit # disable PWT & PRCT # disable Auto-Refresh mww 0xB8001000 0x82220080 ## ESD_ESDCTL0 : enable Auto-Refresh mww 0xB8001000 0x82228080 ## ESD_ESDCTL1 : enable Auto-Refresh mww 0xB8001008 0x00002000 #*********************************************** # Adjust the ESDCDLY5 register #*********************************************** # Vary DQS_ABS_OFFSET5 for writes mww 0xB8001020 0x00F48000 ;# this is the default value mww 0xB8001024 0x00F48000 ;# this is the default value mww 0xB8001028 0x00F48000 ;# this is the default value mww 0xB800102c 0x00F48000 ;# this is the default value #Then you can make force measure with the dedicated bit (Bit 7 at ESDMISC) mww 0xB8001010 0x00000384 # wait a while sleep 1000 # now clear the force measurement bit mww 0xB8001010 0x00000304 # dummy write to DDR memory to set DQS low mww 0x80000000 0x00000000 mww 0x30000100 0x0 mww 0x30000104 0x31024 } openocd-0.9.0/tcl/board/atmel_at91sam7s-ek.cfg0000644000175000017500000000022712526202242015730 00000000000000# Atmel AT91SAM7S-EK # http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3784 set CHIPNAME at91sam7s256 source [find target/at91sam7sx.cfg] openocd-0.9.0/tcl/board/mini6410.cfg0000644000175000017500000001016112526202242013665 00000000000000# Target configuration for the Samsung s3c6410 system on chip # Tested on a tiny6410 # Processor : ARM1176 # Info : JTAG tap: s3c6410.etb tap/device found: 0x2b900f0f (mfg: 0x787, part: 0xb900, ver: 0x2) # Info : JTAG tap: s3c6410.cpu tap/device found: 0x07b76f0f (mfg: 0x787, part: 0x7b76, ver: 0x0) source [find target/samsung_s3c6410.cfg] proc init_6410 {} { halt reg cpsr 0x1D3 arm mcr 15 0 15 2 4 0x70000013 #----------------------------------------------- # Clock and Timer Setting #----------------------------------------------- mww 0x7e004000 0 ;# WATCHDOG - Disable mww 0x7E00F120 0x0003 ;# MEM_SYS_CFG - CS0:8 bit, Mem1:32bit, CS2=NAND #mww 0x7E00F120 0x1000 ;# MEM_SYS_CFG - CS0:16bit, Mem1:32bit, CS2=SROMC #mww 0x7E00F120 0x1002 ;# MEM_SYS_CFG - CS0:16bit, Mem1:32bit, CS2=OND mww 0x7E00F900 0x805e ;# OTHERS - Change SYNCMUX[6] to “1†sleep 1000 mww 0x7E00F900 0x80de ;# OTHERS - Assert SYNCREQ&VICSYNCEN to “1â€(rb1004modify) sleep 1000 ;# - Others[11:8] to 0xF mww 0x7E00F000 0xffff ;# APLL_LOCK - APLL LockTime mww 0x7E00F004 0xffff ;# MPLL_LOCK - MPLL LockTime mww 0x7E00F020 0x1047310 ;# CLK_DIV0 - ARMCLK:HCLK:PCLK = 1:4:16 mww 0x7E00F00c 0x81900302 ;# APLL_CON - A:400, P:3, S:2 => 400MHz mww 0x7E00F010 0x81900303 ;# MPLL_CON - M:400, P:3, S:3 => 200MHz mww 0x7E00F01c 0x3 ;# CLK_SRC - APLL,MPLL Clock Select #----------------------------------------------- # DRAM initialization #----------------------------------------------- mww 0x7e001004 0x4 ;# P1MEMCCMD - Enter the config state mww 0x7e001010 0x30C ;# P1REFRESH - Refresh Period register (7800ns), 100MHz # mww 0x7e001010 0x40e ;# P1REFRESH - Refresh Period register (7800ns), 133MHz mww 0x7e001014 0x6 ;# P1CASLAT - CAS Latency = 3 mww 0x7e001018 0x1 ;# P1T_DQSS mww 0x7e00101c 0x2 ;# P1T_MRD mww 0x7e001020 0x7 ;# P1T_RAS - 45 ns mww 0x7e001024 0xA ;# P1T_RC - 67.5 ns mww 0x7e001028 0xC ;# P1T_RCD - 22.5 ns mww 0x7e00102C 0x10B ;# P1T_RFC - 80 ns mww 0x7e001030 0xC ;# P1T_RP - 22.5 ns mww 0x7e001034 0x3 ;# P1T_RRD - 15 ns mww 0x7e001038 0x3 ;# P1T_WR - 15 ns mww 0x7e00103C 0x2 ;# P1T_WTR mww 0x7e001040 0x2 ;# P1T_XP mww 0x7e001044 0x11 ;# P1T_XSR - 120 ns mww 0x7e001048 0x11 ;# P1T_ESR #----------------------------------------------- # Memory Configuration Registers #----------------------------------------------- mww 0x7e00100C 0x00010012 ;# P1MEMCFG - 1 CKE, 1Chip, 4burst, Alw, AP[10],ROW/Column bit mww 0x7e00104C 0x0B41 ;# P1MEMCFG2 - Read delay 1 Cycle, mDDR, 32bit, Sync. mww 0x7e001200 0x150F0 ;# CHIP_N_CFG - 0x150F0 for 256M, 0x150F8 for 128M #----------------------------------------------- # Memory Direct Commands #----------------------------------------------- mww 0x7e001008 0xc0000 ;# Chip0 Direct Command :NOP5 mww 0x7e001008 0x0 ;# Chip0 Direct Command :PreCharge al mww 0x7e001008 0x40000 ;# Chip0 Direct Command :AutoRefresh mww 0x7e001008 0x40000 ;# Chip0 Direct Command :AutoRefresh mww 0x7e001008 0xA0000 ;# EMRS, DS:Full, PASR:Full mww 0x7e001008 0x80032 ;# MRS, CAS3, BL4 mww 0x7e001004 0x0 ;# Enable DMC1 } proc install_6410_uboot {} { # write U-boot magic number mww 0x50000000 0x24564236 mww 0x50000004 0x20764316 load_image u-boot_nand-ram256.bin 0x50008000 bin load_image u-boot_nand-ram256.bin 0x57E00000 bin #Kick in reg pc 0x57E00000 resume } proc init_6410_flash {} { halt nand probe 0 nand list } adapter_khz 1000 adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst gdb_breakpoint_override hard targets nand device $_CHIPNAME.flash s3c6400 $_CHIPNAME.cpu init echo " " echo " " echo "-------------------------------------------------------------------" echo "---- The following mini6410/tiny6410 functions are available: ----" echo "---- init_6410 - initialize clock, timer, DRAM ----" echo "---- init_6410_flash - initializes NAND flash support ----" echo "---- install_6410_uboot - copies u-boot image into RAM and ----" echo "---- runs it ----" echo "-------------------------------------------------------------------" echo " " echo " " openocd-0.9.0/tcl/board/dk-tm4c129.cfg0000644000175000017500000000036512526202242014122 00000000000000# # TI Tiva C DK-TM4C129X Connected Development Kit # # http://www.ti.com/tool/dk-tm4c129x # source [find interface/ti-icdi.cfg] transport select hla_jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c129xnczad source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/at91rm9200-dk.cfg0000644000175000017500000000413412526202242014445 00000000000000# # This is for the "at91rm9200-DK" (not the EK) eval board. # # The two are probably very simular.... I have DK... # # It has atmel at91rm9200 chip. source [find target/at91rm9200.cfg] reset_config trst_and_srst $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { at91rm9200_dk_init } #flash bank set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x00200000 2 2 $_TARGETNAME proc at91rm9200_dk_init { } { # Try to run at 1khz... Yea, that slow! # Chip is really running @ 32khz adapter_khz 8 mww 0xfffffc64 0xffffffff ## disable all clocks but system clock mww 0xfffffc04 0xfffffffe ## disable all clocks to pioa and piob mww 0xfffffc14 0xffffffc3 ## master clock = slow cpu = slow ## (means the CPU is running at 32khz!) mww 0xfffffc30 0 ## main osc enable mww 0xfffffc20 0x0000ff01 ## program pllA mww 0xfffffc28 0x20263e04 ## program pllB mww 0xfffffc2c 0x10483e0e ## let pll settle... sleep 100msec sleep 100 ## switch to fast clock mww 0xfffffc30 0x202 ## Sleep some - (go read) sleep 100 #======================================== # CPU now runs at 180mhz # SYS runs at 60mhz. adapter_khz 40000 #======================================== ## set memc for all memories mww 0xffffff60 0x02 ## program smc controller mww 0xffffff70 0x3284 ## init sdram mww 0xffffff98 0x7fffffd0 ## all banks precharge mww 0xffffff80 0x02 ## touch sdram chip to make it work mww 0x20000000 0 ## sdram controller mode register mww 0xffffff90 0x04 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 mww 0x20000000 0 ## sdram controller mode register ## Refresh, etc.... mww 0xffffff90 0x03 mww 0x20000080 0 mww 0xffffff94 0x1f4 mww 0x20000080 0 mww 0xffffff90 0x10 mww 0x20000000 0 mww 0xffffff00 0x01 } openocd-0.9.0/tcl/board/atmel_sam4l8_xplained_pro.cfg0000644000175000017500000000032312526202242017453 00000000000000# # Atmel SAM4L8 Xplained Pro evaluation kit. # http://www.atmel.com/tools/ATSAM4L8-XPRO.aspx # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME ATSAM4LC8CA source [find target/at91sam4lXX.cfg] openocd-0.9.0/tcl/board/keil_mcb2140.cfg0000644000175000017500000000015512526202242014474 00000000000000# # Keil MCB2140 eval board # # http://www.keil.com/mcb2140/picture.asp # source [find target/lpc2148.cfg] openocd-0.9.0/tcl/board/at91rm9200-ek.cfg0000644000175000017500000000540212526202242014445 00000000000000# # Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD # # under GPLv2 Only # # This is for the "at91rm9200-ek" eval board. # # # It has atmel at91rm9200 chip. source [find target/at91rm9200.cfg] reset_config trst_and_srst $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { at91rm9200_ek_init } ## flash bank set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME # The chip may run @ 32khz, so set a really low JTAG speed adapter_khz 8 proc at91rm9200_ek_init { } { # Try to run at 1khz... Yea, that slow! # Chip is really running @ 32khz adapter_khz 8 mww 0xfffffc64 0xffffffff ## disable all clocks but system clock mww 0xfffffc04 0xfffffffe ## disable all clocks to pioa and piob mww 0xfffffc14 0xffffffc3 ## master clock = slow cpu = slow ## (means the CPU is running at 32khz!) mww 0xfffffc30 0 ## main osc enable mww 0xfffffc20 0x0000ff01 ## MC_PUP mww 0xFFFFFF50 0x00000000 ## MC_PUER: Memory controller protection unit disable mww 0xFFFFFF54 0x00000000 ## EBI_CFGR mww 0xFFFFFF64 0x00000000 ## SMC2_CSR[0]: 16bit, 2 TDF, 4 WS mww 0xFFFFFF70 0x00003284 ## Init Clocks ## CKGR_PLLAR mww 0xFFFFFC28 0x2000BF05 ## PLLAR: 179,712000 MHz for PCK mww 0xFFFFFC28 0x20263E04 sleep 100 ## PMC_MCKR mww 0xFFFFFC30 0x00000100 sleep 100 ## ;MCKR : PCK/3 = MCK Master Clock = 59,904000MHz from PLLA mww 0xFFFFFC30 0x00000202 sleep 100 #======================================== # CPU now runs at 180mhz # SYS runs at 60mhz. adapter_khz 40000 #======================================== ## Init SDRAM ## PIOC_ASR: Configure PIOC as peripheral (D16/D31) mww 0xFFFFF870 0xFFFF0000 ## PIOC_BSR: mww 0xFFFFF874 0x00000000 ## PIOC_PDR: mww 0xFFFFF804 0xFFFF0000 ## EBI_CSA : CS1=SDRAM mww 0xFFFFFF60 0x00000002 ## EBI_CFGR: mww 0xFFFFFF64 0x00000000 ## SDRC_CR : mww 0xFFFFFF98 0x2188c155 ## SDRC_MR : Precharge All mww 0xFFFFFF90 0x00000002 ## access SDRAM mww 0x20000000 0x00000000 ## SDRC_MR : Refresh mww 0xFFFFFF90 0x00000004 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 ## SDRC_MR : Load Mode Register mww 0xFFFFFF90 0x00000003 ## access SDRAM mww 0x20000080 0x00000000 ## SDRC_TR : Write refresh rate mww 0xFFFFFF94 0x000002E0 ## access SDRAM mww 0x20000000 0x00000000 ## SDRC_MR : Normal Mode mww 0xFFFFFF90 0x00000000 ## access SDRAM mww 0x20000000 0x00000000 } openocd-0.9.0/tcl/board/zy1000.cfg0000644000175000017500000000572012526202242013366 00000000000000#Script for ZY1000 #Atmel ties SRST & TRST together, at which point it makes #no sense to use TRST, but use TMS instead. # #The annoying thing with tying SRST & TRST together is that #there is no way to halt the CPU *before and during* the #SRST reset, which means that the CPU will run a number #of cycles before it can be halted(as much as milliseconds). reset_config srst_only srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME zy1000 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME # at CPU CLK <32kHz this must be disabled arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x01000000 0x200000 2 2 $_TARGETNAME $_TARGETNAME configure -event reset-init { # Set up chip selects & timings mww 0xFFE00000 0x0100273D mww 0xFFE00004 0x08002125 mww 0xFFEe0008 0x02002125 mww 0xFFE0000c 0x03002125 mww 0xFFE00010 0x40000000 mww 0xFFE00014 0x50000000 mww 0xFFE00018 0x60000000 mww 0xFFE0001c 0x70000000 mww 0xFFE00020 0x00000001 mww 0xFFE00024 0x00000000 # remap mww 0xFFFFF124 0xFFFFFFFF mww 0xffff0010 0x100 mww 0xffff0034 0x100 #disable 16x5x UART interrupts mww 0x08020004 0 } $_TARGETNAME configure -event gdb-attach { # Without this gdb-attach will first time as probe will fail reset init } # required for usable performance. Used for lots of # other things than flash programming. $_TARGETNAME configure -work-area-phys 0x00020000 -work-area-size 0x20000 -work-area-backup 0 adapter_khz 16000 proc production_info {} { return "Serial number is official MAC number. Format XXXXXXXXXXXX" } # There is no return value from this procedure. If it is # successful it does not throw an exception # # Progress messages are output via puts proc production {firmwarefile serialnumber} { if {[string length $serialnumber]!=12} { echo "Invalid serial number" return } echo "Power cycling target" power off sleep 3000 power on sleep 1000 reset init flash write_image erase $firmwarefile 0x1000000 bin verify_image $firmwarefile 0x1000000 bin # Big endian... weee!!!! echo "Setting MAC number to $serialnumber" flash fillw [expr 0x1030000-0x8] "0x[string range $serialnumber 2 3][string range $serialnumber 0 1]0000" 1 flash fillw [expr 0x1030000-0x4] "0x[string range $serialnumber 10 11][string range $serialnumber 8 9][string range $serialnumber 6 7][string range $serialnumber 4 5]" 1 echo "Production successful" } proc production_test {} { power on sleep 1000 target_request debugmsgs enable reset run sleep 25000 target_request debugmsgs disable return "See IP address above..." } openocd-0.9.0/tcl/board/voipac.cfg0000644000175000017500000000067012526202242013703 00000000000000# Config for Voipac PXA270/PXA270M module. set CHIPNAME voipac source [find target/pxa270.cfg] # The board supports separate reset lines # Override this in the interface config for parallel dongles reset_config trst_and_srst separate # flash bank flash bank $_CHIPNAME.flash0 cfi 0x00000000 0x2000000 2 2 $_TARGETNAME flash bank $_CHIPNAME.flash1 cfi 0x02000000 0x2000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/atmel_saml21_xplained_pro.cfg0000644000175000017500000000024412526202242017444 00000000000000# # Atmel SAML21 Xplained Pro evaluation kit. # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME at91saml21j18 source [find target/at91samdXX.cfg] openocd-0.9.0/tcl/board/nordic_nrf51822_mkit.cfg0000644000175000017500000000020412526202242016164 00000000000000# # Nordic Semiconductor PCA10024 board (aka nRF51822-mKIT) # source [find interface/cmsis-dap.cfg] source [find target/nrf51.cfg] openocd-0.9.0/tcl/board/olimex_sam9_l9260.cfg0000644000175000017500000001305512526202242015505 00000000000000################################################################################ # Olimex SAM9-L9260 Development Board # # http://www.olimex.com/dev/sam9-L9260.html # # Atmel AT91SAM9260 : PLLA = 198.656 MHz, MCK = 99.328 MHz # PMC configured for external 18.432 MHz crystal # # 32-bit SDRAM : 2 x Samsung K4S561632J-UC75, 4M x 16Bit x 4 Banks # 8-bit NAND Flash : 1 x Samsung K9F4G08U0M, 512M x 8Bit # Dataflash : 1 x Atmel AT45DB161D, 16Mbit # ################################################################################ source [find target/at91sam9260.cfg] # NTRST_E jumper is enabled by default, so we don't need to override the reset # config. #reset_config srst_only $_TARGETNAME configure -event reset-start { # At reset, CPU runs at 32.768 kHz. JTAG frequency must be 6 times slower if # RCLK is not supported. jtag_rclk 5 halt # RSTC_MR : enable user reset, reset length is 64 slow clock cycles. MMU may # be enabled... use physical address. mww phys 0xfffffd08 0xa5000501 } $_TARGETNAME configure -event reset-init { mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog ## # Clock configuration for 99.328 MHz main clock. ## echo "Setting up clock" mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable main oscillator, 512 slow clock startup sleep 20 ;# wait 20 ms (need 15.6 ms for startup) mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator (18.432 MHz) sleep 10 ;# wait 10 ms mww 0xfffffc28 0x2060bf09 ;# CKGR_PLLAR : 18.432 MHz / 9 * 97 = 198.656 MHz, 63 slow clock startup sleep 20 ;# wait 20 ms (need 1.9 ms for startup) mww 0xfffffc30 0x00000101 ;# PMC_MCKR : no scale on proc clock, master is proc / 2 sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : switch to PLLA (99.328 MHz) # Increase JTAG speed to 6 MHz if RCLK is not supported. jtag_rclk 6000 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads. ## # SDRAM configuration for 2 x Samsung K4S561632J-UC75, 4M x 16Bit x 4 Banks. ## echo "Configuring SDRAM" mww 0xfffff870 0xffff0000 ;# PIOC_ASR : select peripheral function for D15..D31 mww 0xfffff804 0xffff0000 ;# PIOC_PDR : disable PIO function for D15..D31 mww 0xffffef1c 0x00010002 ;# EBI_CSA : assign EBI CS1 to SDRAM, VDDIOMSEL set for +3V3 memory mww 0xffffea08 0x85237259 ;# SDRAMC_CR : configure SDRAM for Samsung chips mww 0xffffea00 0x1 ;# SDRAMC_MR : issue NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue 8 x 'Auto-Refresh' command mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : normal mode mww 0x20000000 0 mww 0xffffea04 0x2b6 ;# SDRAMC_TR : set refresh timer count to 7 us ## # NAND Flash Configuration for 1 x Samsung K9F4G08U0M, 512M x 8Bit. ## echo "Configuring NAND flash" mww 0xfffffc10 0x00000010 ;# PMC_PCER : enable PIOC clock mww 0xfffff800 0x00006000 ;# PIOC_PER : enable PIO function for 13(RDY/~BSY) and 14(~CS) mww 0xfffff810 0x00004000 ;# PIOC_OER : enable output on 14 mww 0xfffff814 0x00002000 ;# PIOC_ODR : disable output on 13 mww 0xfffff830 0x00004000 ;# PIOC_SODR : set 14 to disable NAND mww 0xfffff864 0x00002000 ;# PIOC_PUER : enable pull-up on 13 mww 0xffffef1c 0x0001000A ;# EBI_CSA : assign EBI CS3 to NAND, same settings as before mww 0xffffec30 0x00010001 ;# SMC_SETUP3 : 1 clock cycle setup for NRD and NWE mww 0xffffec34 0x03030303 ;# SMC_PULSE3 : 3 clock cycle pulse for all signals mww 0xffffec38 0x00050005 ;# SMC_CYCLE3 : 5 clock cycle NRD and NWE cycle mww 0xffffec3C 0x00020003 ;# SMC_MODE3 : NRD and NWE control, no NWAIT, 8-bit DBW, # 3 TDF cycles, no optimization mww 0xffffe800 0x00000001 ;# ECC_CR : reset the ECC parity registers mww 0xffffe804 0x00000002 ;# ECC_MR : page size is 2112 words (word is 8 bits) nand probe at91sam9260.flash ## # Dataflash configuration for 1 x Atmel AT45DB161D, 16Mbit ## echo "Setting up dataflash" mww 0xfffff404 0x00000807 ;# PIOA_PDR : disable PIO function for 0(SPI0_MISO), 1(SPI0_MOSI), # 2(SPI0_SPCK), and 11(SPI0_NPCS1) mww 0xfffff470 0x00000007 ;# PIOA_ASR : select peripheral A function for 0, 1, and 2 mww 0xfffff474 0x00000800 ;# PIOA_BSR : select peripheral B function for 11 mww 0xfffffc10 0x00001000 ;# PMC_PCER : enable SPI0 clock mww 0xfffc8000 0x00000080 ;# SPI0_CR : software reset SPI0 mww 0xfffc8000 0x00000080 ;# SPI0_CR : again to be sure mww 0xfffc8004 0x000F0011 ;# SPI0_MR : master mode with nothing selected mww 0xfffc8034 0x011a0302 ;# SPI0_CSR1 : capture on leading edge, 8-bits/tx. 33MHz baud, # 250ns delay before SPCK, 250ns b/n tx mww 0xfffc8004 0x000D0011 ;# SPI0_MR : same config, select NPCS1 mww 0xfffc8000 0x00000001 ;# SPI0_CR : enable SPI0 } nand device at91sam9260.flash at91sam9 at91sam9260.cpu 0x40000000 0xffffe800 at91sam9 cle 0 22 at91sam9 ale 0 21 at91sam9 rdy_busy 0 0xfffff800 13 at91sam9 ce 0 0xfffff800 14 openocd-0.9.0/tcl/board/frdm-kl25z.cfg0000644000175000017500000000053112526202242014313 00000000000000# This is an Freescale Freedom eval board with a single MKL25Z128VLK4 chip. # http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=FRDM-KL25Z # source [find interface/cmsis-dap.cfg] # increase working area to 16KB set WORKAREASIZE 0x4000 # chip name set CHIPNAME MKL25Z128VLK4 reset_config srst_only source [find target/kl25.cfg] openocd-0.9.0/tcl/board/ek-lm3s811.cfg0000644000175000017500000000064712526202242014133 00000000000000# # TI/Luminary Stellaris LM3S811 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s811 # # NOTE: using the on-board FT2232 JTAG/SWD/SWO interface is optional! # so is using it in JTAG mode, as done here. # NOTE: older '811-EK boards (before rev C) shouldn't use this. source [find interface/ftdi/luminary.cfg] # include the target config set WORKAREASIZE 0x2000 set CHIPNAME lm3s811 source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/gumstix-aerocore.cfg0000644000175000017500000000046012526202242015714 00000000000000# JTAG for the STM32F4x chip used on the Gumstix AeroCore is available on # the first interface of a Quad FTDI chip. nTRST is bit 4. interface ftdi ftdi_vid_pid 0x0403 0x6011 ftdi_layout_init 0x0000 0x001b ftdi_layout_signal nTRST -data 0x0010 source [find target/stm32f4x.cfg] reset_config trst_only openocd-0.9.0/tcl/board/stm3241g_eval_stlink.cfg0000644000175000017500000000064112526202242016277 00000000000000# STM3241G-EVAL: This is an STM32F4 eval board with a single STM32F417IGH6 # (1024KB) chip. # http://www.st.com/internet/evalboard/product/252216.jsp # # This is for using the onboard STLINK/V2 source [find interface/stlink-v2.cfg] transport select hla_swd # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F417IGH6 source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/hilscher_nxsb100.cfg0000644000175000017500000000133312526202242015473 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ source [find target/hilscher_netx500.cfg] reset_config trst_and_srst adapter_nsrst_delay 500 jtag_ntrst_delay 500 $_TARGETNAME configure -work-area-virt 0x1000 -work-area-phys 0x1000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -event reset-init { halt arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable sdram_fix puts "Configuring SDRAM controller for MT48LC2M32 (8MB) " mww 0x00100140 0 mww 0x00100144 0x03C23251 mww 0x00100140 0x030D0001 } init reset init openocd-0.9.0/tcl/board/unknown_at91sam9260.cfg0000644000175000017500000000727512526202242016011 00000000000000# Thanks to Pieter Conradie for this script! # # Unknown vendor board contains: # # Atmel AT91SAM9260 : PLLA = 192.512MHz, MCK = 96.256 MHz # OSCSEL configured for internal RC oscillator (22 to 42 kHz) # # 16-bit NOR FLASH : Intel JS28F128P30T85 128MBit # 32-bit SDRAM : 2 x Samsung K4S561632H-UC75, 4M x 16Bit x 4 Banks ################################################################## # We add to the minimal configuration. source [find target/at91sam9260.cfg] $_TARGETNAME configure -event reset-start { # At reset CPU runs at 22 to 42 kHz. # JTAG Frequency must be 6 times slower. jtag_rclk 3 halt # RSTC_MR : enable user reset, MMU may be enabled... use physical address mww phys 0xfffffd08 0xa5000501 } $_TARGETNAME configure -event reset-init { mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable the main oscillator sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator sleep 10 ;# wait 10 ms mww 0xfffffc28 0x205dbf09 ;# CKGR_PLLAR: Set PLLA Register for 192.512MHz sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000101 ;# PMC_MCKR : Select prescaler (divide by 2) sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : Clock from PLLA is selected (96.256 MHz) sleep 10 ;# wait 10 ms # Increase JTAG Speed to 6 MHz if RCLK is not supported jtag_rclk 6000 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads mww 0xffffec00 0x01020102 ;# SMC_SETUP0 : Setup SMC for Intel NOR Flash JS28F128P30T85 128MBit mww 0xffffec04 0x09070806 ;# SMC_PULSE0 mww 0xffffec08 0x000d000b ;# SMC_CYCLE0 mww 0xffffec0c 0x00001003 ;# SMC_MODE0 flash probe 0 ;# Identify flash bank 0 mww 0xfffff870 0xffff0000 ;# PIO_ASR : Select peripheral function for D15..D31 mww 0xfffff804 0xffff0000 ;# PIO_PDR : Disable PIO function for D15..D31 mww 0xfffff860 0xffff0000 ;# PIO_PUDR : Disable D15..D31 pull-ups mww 0xffffef1c 0x00010102 ;# EBI_CSA : Assign EBI Chip Select 1 to SDRAM # VDDIOMSEL set for +3V3 memory # Disable D0..D15 pull-ups mww 0xffffea08 0x85227259 ;# SDRAMC_CR : Configure SDRAM (2 x Samsung K4S561632H-UC75 : 4M x 16Bit x 4 Banks) mww 0xffffea00 0x1 ;# SDRAMC_MR : issue a NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue 8 x 'Auto-Refresh' Command mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : normal mode mww 0x20000000 0 mww 0xffffea04 0x2a2 ;# SDRAMC_TR : Set refresh timer count to 7us } ##################### # Flash configuration ##################### #flash bank cfi set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x01000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/ti_am43xx_evm.cfg0000644000175000017500000000022712526202242015107 00000000000000# Works on both AM437x GP EVM and AM438x ePOS EVM transport select jtag adapter_khz 16000 source [find target/am437x.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/spear310evb20.cfg0000644000175000017500000000275612526202242014626 00000000000000# Configuration for the ST SPEAr310 Evaluation board # EVALSPEAr310 Rev. 2.0 # http://www.st.com/spear # # Date: 2010-08-17 # Author: Antonio Borneo # The standard board has JTAG SRST not connected. # This script targets such boards using quirky code to bypass the issue. # # Check ST Application Note AN3321 on how to fix SRST on # the board, then use the script board/spear310evb20_mod.cfg source [find mem_helper.tcl] source [find target/spear3xx.cfg] source [find chip/st/spear/spear3xx_ddr.tcl] source [find chip/st/spear/spear3xx.tcl] arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable # CFI parallel NOR on EMI CS0. 2x 16bit 8M devices = 16Mbyte. set _FLASHNAME0 $_CHIPNAME.pnor flash bank $_FLASHNAME0 cfi 0x50000000 0x01000000 2 4 $_TARGETNAME # Serial NOR on SMI CS0. 8Mbyte. set _FLASHNAME1 $_CHIPNAME.snor flash bank $_FLASHNAME1 stmsmi 0xf8000000 0 0 0 $_TARGETNAME if { [info exists BOARD_HAS_SRST] } { # Modified board has SRST on JTAG connector reset_config trst_and_srst separate srst_gates_jtag \ trst_push_pull srst_open_drain } else { # Standard board has no SRST on JTAG connector reset_config trst_only separate srst_gates_jtag trst_push_pull source [find chip/st/spear/quirk_no_srst.tcl] } $_TARGETNAME configure -event reset-init { spear310evb20_init } proc spear310evb20_init {} { reg pc 0xffff0020 ;# loop forever sp3xx_clock_default sp3xx_common_init sp3xx_ddr_init "mt47h64m16_3_333_cl5_async" sp310_init sp310_emi_init } openocd-0.9.0/tcl/board/asus-rt-n66u.cfg0000644000175000017500000000117312526202242014613 00000000000000# # http://wikidevi.com/wiki/Asus_RT-N66U # echo "ATTENTION: you need to solder a 4.7-10k pullup resistor to pin 21 of flash IC" echo "to enable JTAG, see http://wl500g.info/album.php?albumid=28&attachmentid=8991 ," echo "there is an unpopulated footprint near U8.\n" set partition_list { CFE { Bootloader 0xbc000000 0x00040000 } firmware { "Kernel+rootfs" 0xbc040000 0x01fa0000 } nvram { "Config space" 0xbdfe0000 0x00020000 } } source [find target/bcm4706.cfg] # External 32MB NOR Flash (Spansion S29GL256P10TF101 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0xbc000000 0x02000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/propox_mmnet1001.cfg0000644000175000017500000000652512526202243015461 00000000000000 ## Chip: set CHIPNAME at91sam9260 set CPUTAPID 0x0792603f set ENDIAN little source [find target/at91sam9260.cfg] $_TARGETNAME configure -event reset-init {at91sam_init} proc at91sam_init { } { # at reset chip runs at 32 kHz => 1/8 * 32 kHz = 4 kHz jtag_rclk 4 # Enable user reset and disable watchdog mww 0xfffffd08 0xa5000501 ;# RSTC_MR : enable user reset mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog # Oscillator setup mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable the main oscillator (18.432 MHz) sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator sleep 10 ;# wait 10 ms # now we are running at 18.432 MHz kHz => 1/8 * 18.432 MHz = 2.304 MHz jtag_rclk 2000 mww 0xfffffc28 0x2060bf09 ;# CKGR_PLLAR: Set PLLA Register for 198,656MHz sleep 20 ;# wait 20 ms mww 0xfffffc2c 0x207c3f0c ;# CKGR_PLLBR: Set PLLB Register for USB usage (USB_CLK = 48 MHz) sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000101 ;# PMC_MCKR : Select prescaler sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : Clock from PLLA is selected sleep 10 ;# wait 10 ms # now we are running at 198.656 MHz kHz => full speed jtag jtag_rclk 30000 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads # Configure PIO Controller for SDRAM data-lines D16-D31 # PC16-PC31 = Peripheral A: D16-D32 mww 0xfffff844 0xffff0000 ;# Interrupt Disable mww 0xfffff854 0xffff0000 ;# Multi-Drive Disable mww 0xfffff860 0xffff0000 ;# Pull-Up Disable mww 0xfffff870 0xffff0000 ;# PIO_ASR : Select peripheral A function for D15..D31 mww 0xfffff804 0xffff0000 ;# PIO_PDR : Disable PIO function for D15..D31 (Peripheral function enable) mww 0xfffffc10 0x00000010 ;# Enable PIO-C Clock in PMC (PID=4) # SD-Ram setup mww 0xffffef1c 0x2 ;# EBI_CSA : Assign EBI Chip Select 1 to SDRAM mww 0xffffea08 0x85227259 ;# SDRAMC_CR : Configure SDRAM (IS42S32160A: 4M Words x 32 Bits x 4 Banks (512-Mbit)) mww 0xffffea00 0x1 ;# SDRAMC_MR : issue a NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (1st) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (2nd) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (3th) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (4th) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (5th) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (6th) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (7th) mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue an 'Auto-Refresh' command (8th) mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : Normal Mode mww 0x20000000 0 mww 0xFFFFEA04 0x30d ;# SDRAM Refresh Time Register # datasheet: 8k refresh cycles / 64 ms # MCLK / (8*1024 / 64e-3) = 100e6 / 128000 = 781 = 0x30d } openocd-0.9.0/tcl/board/ethernut3.cfg0000644000175000017500000000301612526202243014341 00000000000000# # Ethernut 3 board configuration file # # http://www.ethernut.de/en/hardware/enut3/ # AT91R40008-66AU ARM7TDMI Microcontroller # 256kB internal RAM source [find target/at91r40008.cfg] # AT49BV322A-70TU NOR Flash # 2M x 16 mode at address 0x10000000 # Common flash interface supported # set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x400000 2 2 $_TARGETNAME # Micrel MIC2775-29YM5 Supervisor # Reset output will remain active for 280ms (maximum) # adapter_nsrst_delay 300 jtag_ntrst_delay 300 arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable adapter_khz 16000 # Target events # $_TARGETNAME configure -event reset-init { board_init } # Initialize board hardware # proc board_init { } { board_remap flash probe 0 } # Memory remap # proc board_remap {{VERBOSE 0}} { # CS0: NOR flash # 16MB @ 0x10000000 # 16-bit data bus # 4 wait states # mww 0xffe00000 0x1000212d # CS1: Ethernet controller # 1MB @ 0x20000000 # 16-bit data bus # 2 wait states # Byte select access # mww 0xffe00004 0x20003025 # CS2: CPLD registers # 1MB @ 0x21000000 # 8-bit data bus # 2 wait states # mww 0xffe00008 0x21002026 # CS3: Expansion bus # 1MB @ 0x22000000 # 8-bit data bus # 8 wait states # mww 0xffe00010 0x22002e3e # Remap command # mww 0xffe00020 0x00000001 if {$VERBOSE != 0} { echo "0x00000000 RAM" echo "0x10000000 Flash" echo "0x20000000 Ethernet" echo "0x21000000 CPLD" echo "0x22000000 Expansion" } } openocd-0.9.0/tcl/board/da850evm.cfg0000644000175000017500000000067212526202243013756 00000000000000#DA850 EVM board # http://focus.ti.com/dsp/docs/thirdparty/catalog/devtoolsproductfolder.tsp?actionPerformed=productFolder&productId=5939 # http://www.logicpd.com/products/development-kits/zoom-omap-l138-evm-development-kit source [find target/omapl138.cfg] reset_config trst_and_srst separate #currently any pinmux/timing must be setup by UBL before openocd can do debug #TODO: implement pinmux/timing on reset like in board/dm365evm.cfg openocd-0.9.0/tcl/board/atmel_sam3n_ek.cfg0000644000175000017500000000023012526202243015275 00000000000000 # # Board configuration for Atmel's SAM3N-EK # reset_config srst_only set CHIPNAME at91sam3n4c adapter_khz 32 source [find target/at91sam3nXX.cfg] openocd-0.9.0/tcl/board/at91sam9261-ek.cfg0000644000175000017500000000461212526202243014621 00000000000000################################################################################ # Atmel AT91SAM9261-EK eval board ################################################################################ source [find mem_helper.tcl] source [find target/at91sam9261.cfg] uplevel #0 [list source [find chip/atmel/at91/hardware.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9261.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9261_matrix.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9_init.cfg]] # By default S1 is open and this means that NTRST is not connected. # The reset_config in target/at91sam9261.cfg is overridden here. # (or S1 must be populated with a 0 Ohm resistor) reset_config srst_only scan_chain $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { at91sam9261ek_reset_init } $_TARGETNAME configure -event reset-start { at91sam9_reset_start } proc at91sam9261ek_reset_init { } { ;# for ppla at 199 Mhz set config(master_pll_div) 15 set config(master_pll_mul) 162 ;# for ppla at 239 Mhz ;# set master_pll_div 1 ;# set master_pll_mul 13 set val [expr $::AT91_WDT_WDV] ;# Counter Value set val [expr ($val | $::AT91_WDT_WDDIS)] ;# Watchdog Disable set val [expr ($val | $::AT91_WDT_WDD)] ;# Delta Value set val [expr ($val | $::AT91_WDT_WDDBGHLT)] ;# Debug Halt set val [expr ($val | $::AT91_WDT_WDIDLEHLT)] ;# Idle Halt set config(wdt_mr_val) $val ;# EBI_CSA, no pull-ups for D[15:0], CS1 SDRAM, CS3 NAND Flash set config(matrix_ebicsa_addr) $::AT91_MATRIX_EBICSA set config(matrix_ebicsa_val) [expr ($::AT91_MATRIX_DBPUC | $::AT91_MATRIX_CS1A_SDRAMC)] ;# SDRAMC_CR - Configuration register set val [expr $::AT91_SDRAMC_NC_9] set val [expr ($val | $::AT91_SDRAMC_NR_13)] set val [expr ($val | $::AT91_SDRAMC_NB_4)] set val [expr ($val | $::AT91_SDRAMC_CAS_3)] set val [expr ($val | $::AT91_SDRAMC_DBW_32)] set val [expr ($val | (2 << 8))] ;# Write Recovery Delay set val [expr ($val | (7 << 12))] ;# Row Cycle Delay set val [expr ($val | (3 << 16))] ;# Row Precharge Delay set val [expr ($val | (2 << 20))] ;# Row to Column Delay set val [expr ($val | (5 << 24))] ;# Active to Precharge Delay set val [expr ($val | (8 << 28))] ;# Exit Self Refresh to Active Delay set config(sdram_cr_val) $val set config(sdram_tr_val) 0x13c set config(sdram_base) $::AT91_CHIPSELECT_1 at91sam9_reset_init $config } openocd-0.9.0/tcl/board/dm6446evm.cfg0000644000175000017500000000426512526202243014063 00000000000000# DM6446 EVM board # http://focus.ti.com/docs/toolsw/folders/print/tmdsevm6446.html # http://c6000.spectrumdigital.com/davincievm/ # EVM is just the board; buy that at Spectrum. # The "kit" from TI also has: video camera, LCD video monitor, more. source [find target/ti_dm6446.cfg] # J4 controls what CS2 hooks up to, usually NOR or NAND flash. # S3.1/S3.2 controls boot mode, which may force J4 and S3.3 settings. # S3.3 controls AEMIF bus width. if { [info exists J4_OPTION] } { # NOR, NAND, SRAM, ... set CS2_MODE $J4_OPTION } else { set CS2_MODE "" } # ARM boot: # S3.1 = 0, S3.2 = 0 ==> ROM/UBL boot via NAND (J4 == NAND) # S3.1 = 1, S3.2 = 0 ==> AEMIF boot (J4 == NOR or SRAM) # S3.1 = 0, S3.2 = 1 ==> ROM/UBL boot via HPI # S3.1 = 1, S3.2 = 1 ==> ROM/UBL boot via UART (J4 == don't care) # AEMIF bus width: # S3.3 = 0 ==> 8 bit bus width # S3.3 = 1 ==> 16 bit bus width # DSP boot: # S3.4 = 0 ==> controlled by ARM if { $CS2_MODE == "NOR" } { # 16 Mbytes address space; 16 bit bus width # (older boards used 32MB parts, with upper 16 MB unusable) set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x02000000 0x01000000 2 2 $_TARGETNAME proc flashprobe {} { flash probe 0 } } elseif { $CS2_MODE == "NAND" } { # 64 Mbyte small page; 8 bit bus width nand device davinci $_TARGETNAME 0x02000000 hwecc1 0x01e00000 proc flashprobe {} { nand probe 0 } } elseif { $CS2_MODE == "SRAM" } { # 4 Mbyte address space; 16 bit bus width # loaded via JTAG or HPI proc flashprobe {} {} } else { # maybe it's HPI boot? can't tell... echo "WARNING: CS2/flash configuration not recognized" proc flashprobe {} {} } # NOTE: disable or replace this call to dm6446evm_init if you're # debugging new UBL code from SRAM (for NAND boot). $_TARGETNAME configure -event reset-init { dm6446evm_init } # # This post-reset init is called when the MMU isn't active, all IRQs # are disabled, etc. It should do most of what a UBL does, except for # loading code (like U-Boot) into DRAM and running it. # proc dm6446evm_init {} { echo "Initialize DM6446 EVM board" # FIXME initialize everything: # - PLL1 # - PLL2 # - PINMUX # - PSC # - DDR # - AEMIF # - UART0 # - icache flashprobe } openocd-0.9.0/tcl/board/stm32f429discovery.cfg0000644000175000017500000000041112526202243015721 00000000000000# # This is an STM32F429 discovery board with a single STM32F429ZI chip. # http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF259090 # source [find interface/stlink-v2.cfg] transport select hla_swd source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/verdex.cfg0000644000175000017500000000110012526202243013705 00000000000000# Config for Gumstix Verdex XM4 and XL6P (PXA270) set CHIPNAME verdex source [find target/pxa270.cfg] # The board supports separate reset lines # Override this in the interface config for parallel dongles reset_config trst_and_srst separate # XM4 = 400MHz, XL6P = 600MHz...let's run at 0.1*400MHz=40MHz adapter_khz 40000 # flash bank # XL6P has 32 MB flash flash bank $_CHIPNAME.flash0 cfi 0x00000000 0x02000000 2 2 $_TARGETNAME # XM4 has 16 MB flash #flash bank $_CHIPNAME.flash0 cfi 0x00000000 0x01000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/xmc4500-application-kit-sdram.cfg0000644000175000017500000000025112526202243017710 00000000000000# # Infineon XMC4500 Application Kit - SDRAM # # # Segger J-Link Lite XMC4200 on-board # set CHIPNAME xmc4500 source [find target/xmc4xxx.cfg] reset_config srst_only openocd-0.9.0/tcl/board/ti_beagleboard.cfg0000644000175000017500000000033212526202243015341 00000000000000# OMAP3 BeagleBoard # http://beagleboard.org # Fall back to 6MHz if RTCK is not supported jtag_rclk 6000 source [find target/omap3530.cfg] # TI-14 JTAG connector reset_config trst_only # Later run: omap3_dbginit openocd-0.9.0/tcl/board/asus-rt-n16.cfg0000644000175000017500000000064712526202243014427 00000000000000# # http://wikidevi.com/wiki/ASUS_RT-N16 # set partition_list { CFE { Bootloader 0xbc000000 0x00040000 } firmware { "Kernel+rootfs" 0xbc040000 0x01fa0000 } nvram { "Config space" 0xbdfe0000 0x00020000 } } source [find target/bcm4718.cfg] # External 32MB NOR Flash (Macronix MX29GL256EHTI2I-90Q) set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0xbc000000 0x02000000 1 1 $_TARGETNAME x16_as_x8 openocd-0.9.0/tcl/board/steval_pcc010.cfg0000644000175000017500000000053312526202243014765 00000000000000# Use for the STM207VG plug-in board (1 MiB Flash and 112+16 KiB Ram # comming with the STEVAL-PCC010 board # http://www.st.com/internet/evalboard/product/251530.jsp # or any other board with only a STM32F2x in the JTAG chain # increase working area to 32KB for faster flash programming set WORKAREASIZE 0x8000 source [find target/stm32f2x.cfg] openocd-0.9.0/tcl/board/xmc4500-application-kit-general.cfg0000644000175000017500000000021012526202243020212 00000000000000# # Infineon XMC4500 Application Kit - General Purpose # set CHIPNAME xmc4500 source [find target/xmc4xxx.cfg] reset_config srst_only openocd-0.9.0/tcl/board/stm3210c_eval.cfg0000644000175000017500000000036212526202243014704 00000000000000# This is an STM32 eval board with a single STM32F107VCT chip. # http://www.st.com/internet/evalboard/product/217965.jsp # increase working area to 32KB for faster flash programming set WORKAREASIZE 0x8000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/spear310evb20_mod.cfg0000644000175000017500000000200612526202243015452 00000000000000# Configuration for the ST SPEAr310 Evaluation board # EVALSPEAr310 Rev. 2.0, modified to enable SRST on JTAG connector # http://www.st.com/spear # # List of board modifications to enable SRST, as reported in # ST Application Note AN3321. # - Modifications on the top layer: # 1. remove R137 and C57, located near the SMII PHY U18; # 2. remove R172 and C75, located near the SMII PHY U19; # 3. remove R207 and C90, located near the SMII PHY U20; # 4. remove C236, located near the SMII PHY U21; # 5. remove U12, located near the JTAG connector; # 6. solder together pins 7, 8 and 9 of U12; # 7. solder together pins 11, 12, 13, 14, 15, 16, 17 and 18 of U12. # - Modifications on the bottom layer: # 8. replace reset chip U11 with a STM6315SDW13F; # 9. add 0 ohm resistor R329. It is located close to JTAG connector. # # Date: 2009-10-31 # Author: Antonio Borneo # Modified boards has SRST on JTAG connector set BOARD_HAS_SRST 1 source [find board/spear310evb20.cfg] openocd-0.9.0/tcl/board/atmel_sam3x_ek.cfg0000644000175000017500000000007712526202243015320 00000000000000source [find target/at91sam3ax_8x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/atmel_sam3s_ek.cfg0000644000175000017500000000013612526202243015307 00000000000000source [find target/at91sam3sXX.cfg] $_TARGETNAME configure -event gdb-attach { reset init } openocd-0.9.0/tcl/board/ek-lm3s9b9x.cfg0000644000175000017500000000056312526202243014413 00000000000000# # TI/Luminary Stellaris LM3S9B9x Evaluation Kits # # http://www.ti.com/tool/ek-lm3s9b90 # http://www.ti.com/tool/ek-lm3s9b92 # # NOTE: using the bundled FT2232 JTAG/SWD/SWO interface is optional! # so is using in JTAG mode, as done here. source [find interface/ftdi/luminary-icdi.cfg] set WORKAREASIZE 0x4000 set CHIPNAME lm3s9b9x source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/ti_am335xevm.cfg0000644000175000017500000000026512526202243014647 00000000000000# # TI AM335x Evaluation Module # # For more information please see http://www.ti.com/tool/tmdxevm3358 # jtag_rclk 6000 source [find target/am335x.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/ek-lm3s3748.cfg0000644000175000017500000000054012526202243014220 00000000000000# # TI/Luminary Stellaris lm3s3748 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s3748 # # NOTE: using the on-board FT2232 JTAG/SWD/SWO interface is optional! # so is using it in JTAG mode, as done here. source [find interface/ftdi/luminary.cfg] # 20k working area set WORKAREASIZE 0x4000 set CHIPNAME lm3s3748 source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/logicpd_imx27.cfg0000644000175000017500000000051612526202243015071 00000000000000# The LogicPD Eval IMX27 eval board has a single IMX27 chip source [find target/imx27.cfg] # The Logic PD board has a NOR flash on CS0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0xc0000000 0x00200000 2 2 $_TARGETNAME # # FIX ME, Add support to # # (A) hard reset the board. # (B) Initialize the SDRAM on the board # openocd-0.9.0/tcl/board/alphascale_asm9260_ek.cfg0000644000175000017500000000334012526202243016355 00000000000000source [find target/alphascale_asm9260t.cfg] reset_config trst_and_srst $_TARGETNAME configure -event reset-init { echo "Configure clock" # Enable SRAM clk mww 0x80040024 0x4 # Enable IRQ clk mww 0x80040034 0x100 # Enable DMA0,1 clk mww 0x80040024 0x600 # Make sysre syspll is enabled mww 0x80040238 0x750 #CPU = PLLCLK/2 mww 0x8004017C 0x2 #SYSAHBCLK = CPUCLK/2 mww 0x80040180 0x2 # Set PLL freq to 480MHz mww 0x80040100 480 # normally we shoul waiting here until we get 0x1 (0x80040104)&0x1)==0x0) sleep 100 # select PLL as main source mww 0x80040120 0x1 # disable and enble main clk to update changes? mww 0x80040124 0x0 mww 0x80040124 0x1 echo "Configure memory" #enable EMI CLK mww 0x80040024 0x40 # configure memory controller for internal SRAM mww 0x80700000 0x1188 # change default emi clk delay mww 0x8004034C 0xA0503 # make sure chip_select_register2_low has correct value (why?) mww 0x8070001c 0x20000000 # set type to sdram and size to 32MB mww 0x8070005c 0xa # configure internal SDRAM timing mww 0x80700004 0x024996d9 # configure Static Memory timing mww 0x80700094 0x00542b4f echo "Configure uart4" # enable pinctrl clk mww 0x80040024 0x2000000 # mux GPIO3_0 and GPIO3_1 to UART4 mww 0x80044060 0x2 mww 0x80044064 0x2 # configure UART4CLKDIV mww 0x800401a8 0x1 # enable uart4 clk mww 0x80040024 0x8000 # clear softrst and clkgate on uart4 mww 0x80010008 0xC0000000 # set bandrate 115200 12M mww 0x80010030 0x00062070 # enable Rx&Tx mww 0x80010024 0x301 # clear hw control mww 0x80010028 0xc000 } $_TARGETNAME configure -work-area-phys 0x21ffe000 -work-area-virt 0xc1ffe000 -work-area-size 0x1000 $_TARGETNAME arm7_9 fast_memory_access enable $_TARGETNAME arm7_9 dcc_downloads enable openocd-0.9.0/tcl/board/keil_mcb1700.cfg0000644000175000017500000000015512526202243014476 00000000000000# # Keil MCB1700 eval board # # http://www.keil.com/mcb1700/picture.asp # source [find target/lpc17xx.cfg] openocd-0.9.0/tcl/board/stm3241g_eval.cfg0000644000175000017500000000043412526202243014714 00000000000000# STM3241G-EVAL: This is an STM32F4 eval board with a single STM32F417IGH6 # (1024KB) chip. # http://www.st.com/internet/evalboard/product/252216.jsp # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F417IGH6 source [find target/stm32f4x.cfg] openocd-0.9.0/tcl/board/topas910.cfg0000644000175000017500000000544412526202243014007 00000000000000###################################### # Target: Toshiba TOPAS910 -- TMPA910 Starterkit # ###################################### # We add to the minimal configuration. source [find target/tmpa910.cfg] ###################### # Target configuration ###################### #$_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { topas910_init } proc topas910_init { } { # Init PLL # my settings mww 0xf005000c 0x00000007 mww 0xf0050010 0x00000065 mww 0xf005000c 0x000000a7 sleep 10 mdw 0xf0050008 mww 0xf0050008 0x00000002 mww 0xf0050004 0x00000000 # NEW: set CLKCR5 mww 0xf0050054 0x00000040 # sleep 10 # Init SDRAM # _PMCDRV = 0x00000071; # // # // Initialize SDRAM timing paramater # // # _DMC_CAS_LATENCY = 0x00000006; # _DMC_T_DQSS = 0x00000000; # _DMC_T_MRD = 0x00000002; # _DMC_T_RAS = 0x00000007; # # _DMC_T_RC = 0x0000000A; # _DMC_T_RCD = 0x00000013; # # _DMC_T_RFC = 0x0000010A; # # _DMC_T_RP = 0x00000013; # _DMC_T_RRD = 0x00000002; # _DMC_T_WR = 0x00000002; # _DMC_T_WTR = 0x00000001; # _DMC_T_XP = 0x0000000A; # _DMC_T_XSR = 0x0000000B; # _DMC_T_ESR = 0x00000014; # # // # // Configure SDRAM type parameter # _DMC_MEMORY_CFG = 0x00008011; # _DMC_USER_CONFIG = 0x00000011; # // 32 bit memory interface # # # _DMC_REFRESH_PRD = 0x00000A60; # _DMC_CHIP_0_CFG = 0x000140FC; # # _DMC_DIRECT_CMD = 0x000C0000; # _DMC_DIRECT_CMD = 0x00000000; # # _DMC_DIRECT_CMD = 0x00040000; # _DMC_DIRECT_CMD = 0x00040000; # _DMC_DIRECT_CMD = 0x00080031; # // # // Finally start SDRAM # // # _DMC_MEMC_CMD = MEMC_CMD_GO; # */ mww 0xf0020260 0x00000071 mww 0xf4300014 0x00000006 mww 0xf4300018 0x00000000 mww 0xf430001C 0x00000002 mww 0xf4300020 0x00000007 mww 0xf4300024 0x0000000A mww 0xf4300028 0x00000013 mww 0xf430002C 0x0000010A mww 0xf4300030 0x00000013 mww 0xf4300034 0x00000002 mww 0xf4300038 0x00000002 mww 0xf430003C 0x00000001 mww 0xf4300040 0x0000000A mww 0xf4300044 0x0000000B mww 0xf4300048 0x00000014 mww 0xf430000C 0x00008011 mww 0xf4300304 0x00000011 mww 0xf4300010 0x00000A60 mww 0xf4300200 0x000140FC mww 0xf4300008 0x000C0000 mww 0xf4300008 0x00000000 mww 0xf4300008 0x00040000 mww 0xf4300008 0x00040000 mww 0xf4300008 0x00080031 mww 0xf4300004 0x00000000 sleep 10 # adapter_khz NNNN # remap off in case of IROM boot mww 0xf0000004 0x00000001 } # comment the following out if usinf J-Link, it soes not support DCC arm7_9 dcc_downloads enable ;# Enable faster DCC downloads ##################### # Flash configuration ##################### #flash bank cfi set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x20000000 0x2000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/xmc-2go.cfg0000644000175000017500000000032412526202243013673 00000000000000# # Infineon XMC 2Go # # # Segger J-Link Lite XMC4200 on-board # source [find interface/jlink.cfg] transport select swd set CHIPNAME xmc1100 source [find target/xmc1xxx.cfg] reset_config srst_only srst_nogate openocd-0.9.0/tcl/board/lisa-l.cfg0000644000175000017500000000031012526202243013573 00000000000000# the Lost Illusions Serendipitous Autopilot # http://paparazzi.enac.fr/wiki/Lisa # Work-area size (RAM size) = 20kB for STM32F103RB device set WORKAREASIZE 0x5000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/embedded-artists_lpc2478-32.cfg0000644000175000017500000001420712526202243017251 00000000000000# Embedded Artists eval board for LPC2478 # http://www.embeddedartists.com/ # Target device: LPC2478 set CCLK 72000 source [find target/lpc2478.cfg] # Helper # proc read_register {register} { set result "" mem2array result 32 $register 1 return $result(0) } proc init_board {} { # Delays on reset lines adapter_nsrst_delay 500 jtag_ntrst_delay 1 # Adaptive JTAG clocking through RTCK. # jtag_rclk 20 global _TARGETNAME global _CHIPNAME # A working area will help speeding the flash programming $_TARGETNAME configure -work-area-phys 0x40000200 -work-area-size [expr 0x10000-0x200-0x20] -work-area-backup 0 # External 16-bit flash at chip select CS0 (SST39VF3201-70, 4 MiB) flash bank $_CHIPNAME.extflash cfi 0x80000000 0x400000 2 2 $_TARGETNAME jedec_probe # Event handlers # $_TARGETNAME configure -event reset-start { # Back to the slow JTAG clock jtag_rclk 20 } $_TARGETNAME configure -event reset-init { arm core_state arm arm7_9 dcc_downloads enable ;# Speed up downloads by using DCC transfer arm7_9 fast_memory_access enable # Peripheral clocks mww 0xE01FC0C4 0x04280FFE ;# PCONP: (reset value) # Map the user flash to the vector table area (0x00...0x3F) mww 0xE01FC040 0x00000001 ;# MEMMAP: User flash # Memory accelerator module mww 0xE01FC004 0x00000003 ;# MAMTIM: 3 clock cycles mww 0xE01FC000 0x00000002 ;# MAMCR: fully enabled # Enable external memory bus (32-bit SDRAM at DYCS0, 16-bit flash at CS0) mww 0xE002C014 0x55010115 ;# PINSEL5: P2.16=CAS, P2.17=RAS, P2.18=CLKOUT0, # P2.20=DYCS0, P2.24=CKEOUT0, P2.28=DQMOUT0, # P2.29=DQMOUT1, P2.30=DQMOUT2, P2.31=DQMOUT3 mww 0xE002C018 0x55555555 ;# PINSEL6: P3.0...P3.15=D0...D15 mww 0xE002C01C 0x55555555 ;# PINSEL7: P3.16...P3.31=D16...D31 mww 0xE002C020 0x55555555 ;# PINSEL8: P4.0...P4.15=A0...A15 mww 0xE002C024 0x50051555 ;# PINSEL9: P4.16...P4.22=A16...A22, P4.24=OE, # P4.25=WE, P4.30=CS0, P4.31=CS1 mww 0xFFE08000 0x00000001 ;# EMCControl: Enable EMC # Start PLL, then use faster JTAG clock enable_pll jtag_rclk 3000 # 16-bit flash @ CS0 (SST39VF3201-70) mww 0xFFE08200 0x00080081 ;# EMCStaticConfig0: 16 bit, PB=1, buffers on mww 0xFFE08204 0x00000000 ;# EMCStaticWaitWen0 mww 0xFFE08208 0x00000000 ;# EMCStaticWaitOen0 mww 0xFFE0820C 0x00000005 ;# EMCStaticWaitRd0 mww 0xFFE08210 0x00000005 ;# EMCStaticWaitPage0 mww 0xFFE08214 0x00000003 ;# EMCStaticWaitWr0 mww 0xFFE08218 0x00000001 ;# EMCStaticWaitTurn0 # 8-bit NAND @ CS1 # TODO # 32-bit SDRAM @ DYCS0 (K4M563233G-HN75) mww 0xFFE08028 0x00000001 ;# EMCDynamicReadConfig mww 0xFFE08030 0x00000001 ;# EMCDynamicRP mww 0xFFE08034 0x00000003 ;# EMCDynamicRAS mww 0xFFE08038 0x00000005 ;# EMCDynamicSREX mww 0xFFE0803C 0x00000001 ;# EMCDynamicAPR mww 0xFFE08040 0x00000005 ;# EMCDynamicDAL mww 0xFFE08044 0x00000001 ;# EMCDynamicWR mww 0xFFE08048 0x00000005 ;# EMCDynamicRC mww 0xFFE0804C 0x00000005 ;# EMCDynamicRFC mww 0xFFE08050 0x00000005 ;# EMCDynamicXSR mww 0xFFE08054 0x00000001 ;# EMCDynamicRRD mww 0xFFE08058 0x00000001 ;# EMCDynamicMRD # mww 0xFFE08104 0x00000202 ;# EMCDynamicRasCas0 mww 0xFFE08100 0x00005488 ;# EMCDynamicConfig0 sleep 100 mww 0xFFE08020 0x00000183 ;# EMCDynamicControl: Clock on continuously, NOP sleep 10 mww 0xFFE08020 0x00000103 ;# EMCDynamicControl: PRECHARGE-ALL mww 0xFFE08024 0x00000046 ;# EMCDynamicRefresh sleep 100 mww 0xFFE08020 0x00000083 ;# EMCDynamicControl: MODE mdw 0xA0011000 1 ;# Set SDRAM mode register mww 0xFFE08020 0x00000000 ;# EMCDynamicControl: NORMAL mww 0xFFE08100 0x00085488 ;# EMCDynamicConfig0: Enable buffers } $_TARGETNAME configure -event gdb-attach { # Without this gdb-attach will first time as probe will fail reset init } } # Enable the PLL. # Generate maximum CPU clock (72 MHz) Run from internal RC oscillator. # Note: The PLL output runs at a frequency N times the desired CPU clock. # It in unavoidable that the CPU clock drops down to (4 MHz/N) during # the initialization! # Here: N=4 # Note that if the PLL is already active at the time this script is # called, the effective value of N is the value of CCLKCFG at that time! # proc enable_pll {} { # Disconnect PLL in case it is already connected if {[expr [read_register 0xE01FC080] & 0x03] == 3} { # Disconnect it, but leave it enabled # (This MUST be done in two steps) mww 0xE01FC080 0x00000001 ;# PLLCON: disconnect PLL mww 0xE01FC08C 0x000000AA ;# PLLFEED mww 0xE01FC08C 0x00000055 ;# PLLFEED } # Disable PLL (as it might already be enabled at this time!) mww 0xE01FC080 0x00000000 ;# PLLCON: disable PLL mww 0xE01FC08C 0x000000AA ;# PLLFEED mww 0xE01FC08C 0x00000055 ;# PLLFEED # Setup PLL to generate 288 MHz from internal RC oscillator mww 0xE01FC10C 0x00000000 ;# CLKSRCSEL: IRC mww 0xE01FC084 0x00000023 ;# PLLCFG: N=1, M=36 mww 0xE01FC08C 0x000000AA ;# PLLFEED mww 0xE01FC08C 0x00000055 ;# PLLFEED mww 0xE01FC080 0x00000001 ;# PLLCON: enable PLL mww 0xE01FC08C 0x000000AA ;# PLLFEED mww 0xE01FC08C 0x00000055 ;# PLLFEED sleep 100 mww 0xE01FC104 0x00000003 ;# CCLKCFG: divide by 4 (72 MHz) mww 0xE01FC080 0x00000003 ;# PLLCON: connect PLL mww 0xE01FC08C 0x000000AA ;# PLLFEED mww 0xE01FC08C 0x00000055 ;# PLLFEED } openocd-0.9.0/tcl/board/ti_pandaboard.cfg0000644000175000017500000000011312526202243015202 00000000000000jtag_rclk 6000 source [find target/omap4430.cfg] reset_config trst_only openocd-0.9.0/tcl/board/bt-homehubv1.cfg0000644000175000017500000000066412526202243014727 00000000000000# # BT HomeHub v1 # set partition_list { CFE { Bootloader 0xbe400000 0x00020000 } firmware { "Kernel+rootfs" 0xbe420000 0x007d0000 } fisdir { "FIS Directory" 0xbebf0000 0x0000f000 } nvram { "Config space" 0xbebff000 0x00001000 } } source [find target/bcm6348.cfg] set _FLASHNAME $_CHIPNAME.norflash flash bank $_FLASHNAME cfi 0xbe400000 0x00800000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/omap2420_h4.cfg0000644000175000017500000000064612526202243014265 00000000000000# OMAP2420 SDP board ("H4") source [find target/omap2420.cfg] # NOTE: this assumes you're *NOT* using a TI-14 connector. reset_config trst_and_srst separate # Board configs can vary a *LOT* ... parts, jumpers, etc. # This GP board boots from cs0 using NOR (2x32M), and also # has 64M NAND on cs6. flash bank h4.u10 cfi 0x04000000 0x02000000 2 2 $_TARGETNAME flash bank h4.u11 cfi 0x06000000 0x02000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/dm365evm.cfg0000644000175000017500000000725412526202243013776 00000000000000# DM365 EVM board -- Beta # http://focus.ti.com/docs/toolsw/folders/print/tmdxevm365.html # http://support.spectrumdigital.com/boards/evmdm365 source [find target/ti_dm365.cfg] # NOTE: in Rev C boards, the CPLD ignores SRST from the ARM-20 JTAG # connector, so it doesn't affect generation of the reset signal. # Accordingly, resets require something else. ICEpick could do it; # but its docs aren't generally available. # # At this writing, newer boards aren't available ... so assume no SRST. # Also ICEpick docs aren't available ... so we must use watchdog reset, # and hope the CPU isn't wedged or in a WFI loop (either of which can # block access to CPU and thus watchdog registers). reset_config trst_only $_TARGETNAME configure -event reset-assert "davinci_wdog_reset" # SW5.1 routes CS0: NAND vs OneNAND. # SW4.6:4 controls AEMIF width (8 for NAND, 16 for OneNand) # for boot-from-flash, those must agree with SW4.3:1 settings. if { [info exists CS0MODE] } { # NAND or OneNAND set CS0 $CS0MODE } else { set CS0 "" echo "WARNING: CS0 configuration not known" proc cs0_setup {a_emif} {} proc flashprobe {} {} } set a_emif [dict get $dm365 a_emif] # As shipped: boot from NAND. if { $CS0 == "NAND" } { echo "CS0 NAND" # NAND socket has two chipselects. Default MT29F16G08FAA chip # has 1GByte on each one. # NOTE: "hwecc4" here presumes that you're not updating anything # that needs infix layout (e.g. UBL, old U-Boot, etc) nand device low davinci $_TARGETNAME 0x02000000 hwecc4 $a_emif nand device high davinci $_TARGETNAME 0x02004000 hwecc4 $a_emif proc cs0_setup {a_emif} { global dm365 # 8 bit EMIF davinci_pinmux $dm365 2 0x00000016 # slow/pessimistic timings set nand_timings 0x40400204 # fast (25% faster page reads) #set nand_timings 0x0400008c # CS0 == socketed NAND (default MT29F16G08FAA, 2 GBytes) mww [expr $a_emif + 0x10] $nand_timings # NANDFCR -- CS0 has NAND mww [expr $a_emif + 0x60] 0x01 } proc flashprobe {} { nand probe 0 nand probe 1 } } elseif { $CS0 == "OneNAND" } { echo "CS0 OneNAND" # No support for this OneNAND in OpenOCD (yet) or Linux ... # REVISIT OneNAND timings not verified to work! echo "WARNING -- OneNAND not yet tested!" proc cs0_setup {a_emif} { global dm365 # 16 bit EMIF davinci_pinmux $dm365 2 0x00000055 # CS0 == OneNAND (KFG1G16U2B-DIB6, 128 KBytes) mww [expr $a_emif + 0x10] 0x00000001 # ONENANDCTRL -- CS0 has OneNAND, enable sync reads mww [expr $a_emif + 0x5c] 0x0441 } proc flashprobe {} { } } # NOTE: disable or replace this call to dm365evm_init if you're # debugging new UBL/NANDboot code from SRAM. $_TARGETNAME configure -event reset-init { dm365evm_init } # # This post-reset init is called when the MMU isn't active, all IRQs # are disabled, etc. It should do most of what a UBL does, except for # loading code (like U-Boot) into DRAM and running it. # proc dm365evm_init {} { global dm365 echo "Initialize DM365 EVM board" # CLKIN = 24 MHz ... can't talk quickly to ARM yet adapter_khz 1500 # FIXME -- PLL init ######################## # PINMUX setup davinci_pinmux $dm365 0 0x00fd0000 davinci_pinmux $dm365 1 0x00145555 # mux2 controls AEMIF ... 8 bit for NAND, 16 for OneNand davinci_pinmux $dm365 3 0x375affff davinci_pinmux $dm365 4 0x55556555 ######################## # PSC setup (minimal) # DDR EMIF/13, AEMIF/14, UART0/19 psc_enable 13 psc_enable 14 psc_enable 19 psc_go # FIXME setup DDR2 (needs PLL) ######################## # ASYNC EMIF set a_emif [dict get $dm365 a_emif] # AWCCR mww [expr $a_emif + 0x04] 0xff # CS0 == NAND or OneNAND cs0_setup $a_emif # CS1 == CPLD mww [expr $a_emif + 0x14] 0x00a00505 # FIXME setup UART0 flashprobe } openocd-0.9.0/tcl/board/stm3220g_eval.cfg0000644000175000017500000000043312526202243014710 00000000000000# STM3220G-EVAL: This is an STM32F2 eval board with a single STM32F207IGH6 # (128KB) chip. # http://www.st.com/internet/evalboard/product/250374.jsp # increase working area to 128KB set WORKAREASIZE 0x20000 # chip name set CHIPNAME STM32F207IGH6 source [find target/stm32f2x.cfg] openocd-0.9.0/tcl/board/spear320cpu_mod.cfg0000644000175000017500000000173512526202243015334 00000000000000# Configuration for the ST SPEAr320 Evaluation board # EVAL_SPEAr320CPU Rev. 2.0, modified to enable SRST on JTAG connector # http://www.st.com/spear # # List of board modifications to enable SRST, as reported in # ST Application Note (FIXME: add reference). # - Modifications on the bottom layer: # 1. replace reset chip U7 with a STM6315SDW13F; # 2. add 0 ohm resistor R45. It is located close to JTAG connector. # 3. add a 10K ohm pull-up resistor on the reset wire named as # POWERGOOD in the schematic. # # The easier way to do modification 3, is to use a resistor in package # 0603 or 0402 and solder it between R15 and R45: # - one pad soldered with the pad of R15 connected to 3.3V (this # is the pad of R15 closer to R45) # - the other pad soldered with the nearest pad of R45. # # Date: 2011-11-18 # Author: Antonio Borneo # Modified boards has SRST on JTAG connector set BOARD_HAS_SRST 1 source [find board/spear320cpu.cfg] openocd-0.9.0/tcl/board/ti_tmdx570ls20susb.cfg0000644000175000017500000000064612526202243015730 00000000000000# TMS570 Microcontroller USB Kit # http://www.ti.com/tool/TMDX570LS20SUSB # Board uses a FT2232H to emulate an XDS100v2 JTAG debugger # TODO: board also supports an SCI UART on the 2232's B Bus source [find interface/ftdi/xds100v2.cfg] # Processor is TMS570LS20216 source [find target/ti_tms570ls20xxx.cfg] reset_config trst_only # xds100v2 config says add this to the end init ftdi_set_signal PWR_RST 1 jtag arp_init openocd-0.9.0/tcl/board/bcm28155_ap.cfg0000644000175000017500000000016712526202243014252 00000000000000# BCM28155_AP adapter_khz 20000 set CHIPNAME bcm28155 source [find target/bcm281xx.cfg] reset_config trst_and_srst openocd-0.9.0/tcl/board/ek-tm4c123gxl.cfg0000644000175000017500000000037512526202243014632 00000000000000# # TI Tiva C Series ek-tm4c123gxl Launchpad Evaluation Kit # # http://www.ti.com/tool/ek-tm4c123gxl # source [find interface/ti-icdi.cfg] transport select hla_jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c123gh6pm source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/stm32l0discovery.cfg0000644000175000017500000000041412526202243015553 00000000000000# This is an STM32L053 discovery board with a single STM32L053 chip. # http://www.st.com/web/en/catalog/tools/PF260319 source [find interface/stlink-v2-1.cfg] transport select hla_swd set WORKAREASIZE 0x2000 source [find target/stm32l0.cfg] reset_config srst_only openocd-0.9.0/tcl/board/ek-lm3s811-revb.cfg0000644000175000017500000000055312526202243015064 00000000000000# # TI/Luminary Stellaris LM3S811 Evaluation Kits (rev B and earlier) # # http://www.ti.com/tool/ek-lm3s811 # # NOTE: newer 811-EK boards (rev C and above) shouldn't use this. # use board/ek-lm3s811.cfg source [find interface/ftdi/luminary-lm3s811.cfg] # include the target config set WORKAREASIZE 0x2000 set CHIPNAME lm3s811 source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/am3517evm.cfg0000644000175000017500000000122112526202243014041 00000000000000# DANGER!!!! early work in progress for this PCB/target. # # The most basic operations work well enough that it is # useful to have this in the repository for cooperation # alpha testing purposes. # # TI AM3517 # # http://focus.ti.com/docs/prod/folders/print/am3517.html # http://processors.wiki.ti.com/index.php/Debug_Access_Port_(DAP) # http://processors.wiki.ti.com/index.php?title=How_to_Find_the_Silicon_Revision_of_your_OMAP35x set CHIPTYPE "am35x" source [find target/amdm37x.cfg] # The TI-14 JTAG connector does not have srst. CPU reset is handled in # hardware. reset_config trst_only # "amdm37x_dbginit am35x.cpu" needs to be run after init. openocd-0.9.0/tcl/board/stm32f4discovery.cfg0000644000175000017500000000037512526202243015557 00000000000000# This is an STM32F4 discovery board with a single STM32F407VGT6 chip. # http://www.st.com/internet/evalboard/product/252419.jsp source [find interface/stlink-v2.cfg] transport select hla_swd source [find target/stm32f4x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/atmel_sam4e_ek.cfg0000644000175000017500000000025412526202243015273 00000000000000# This is an SAM4E-EK board with a single SAM4E16 chip. # http://www.atmel.com/tools/sam4e-ek.aspx # chip name set CHIPNAME SAM4E16E source [find target/at91sam4sXX.cfg] openocd-0.9.0/tcl/board/stm32100b_eval.cfg0000644000175000017500000000032312526202243014760 00000000000000# This is an STM32 eval board with a single STM32F100VBT6 chip. # http://www.st.com/internet/evalboard/product/247099.jsp # The chip has only 8KB sram set WORKAREASIZE 0x2000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/board/ek-lm3s6965.cfg0000644000175000017500000000057412526202243014233 00000000000000# # TI/Luminary Stellaris LM3S6965 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s6965 # # NOTE: using the on-board FT2232 JTAG/SWD/SWO interface is optional! # so is using it in JTAG mode, as done here. source [find interface/ftdi/luminary.cfg] # 20k working area set WORKAREASIZE 0x5000 set CHIPNAME lm3s6965 # include the target config source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/linksys-wrt54gl.cfg0000644000175000017500000000062012526202243015420 00000000000000# # Linksys WRT54GL v1.1 # source [find target/bcm5352e.cfg] set partition_list { CFE { Bootloader 0x1c000000 0x00040000 } firmware { "Kernel+rootfs" 0x1c040000 0x003b0000 } nvram { "Config space" 0x1c3f0000 0x00010000 } } # External 4MB NOR Flash (Intel TE28F320C3BD90 or similar) set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x1c000000 0x00400000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/atmel_at91sam9rl-ek.cfg0000644000175000017500000000577212526202243016120 00000000000000################################################################################ # # Generated for Atmel AT91SAM9RL-EK evaluation board using Atmel SAM-ICE (J-Link) V6 # # Atmel AT91SAM9RL : PLL = 200 MHz, MCK = 100 MHz # OSCSEL configured for external 32.768 kHz crystal # # 32-bit SDRAM : 2 x Micron MT48LC16M16A2, 4M x 16Bit x 4 Banks # ################################################################################ # We add to the minimal configuration. source [find target/at91sam9rl.cfg] $_TARGETNAME configure -event reset-start { # At reset CPU runs at 32.768 kHz. # JTAG Frequency must be 6 times slower if RCLK is not supported. jtag_rclk 5 halt # RSTC_MR : enable user reset, MMU may be enabled... use physical address mww phys 0xfffffd08 0xa5000501 } $_TARGETNAME configure -event reset-init { mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable the main oscillator sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator sleep 10 ;# wait 10 ms mww 0xfffffc28 0x2031bf03 ;# CKGR_PLLR: Set PLL Register for 200 MHz sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000101 ;# PMC_MCKR : Select prescaler (divide by 2) sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : Clock from PLL is selected (100 MHz) sleep 10 ;# wait 10 ms # Increase JTAG Speed to 6 MHz if RCLK is not supported jtag_rclk 6000 arm7_9 dcc_downloads enable ;# Enable faster DCC downloads mww 0xfffff670 0xffff0000 ;# PIO_ASR : Select peripheral function for D16..D31 (PIOB) mww 0xfffff604 0xffff0000 ;# PIO_PDR : Disable PIO function for D16..D31 (PIOB) mww 0xffffef20 0x00010002 ;# EBI_CSA : Assign EBI Chip Select 1 to SDRAM, VDDIOMSEL set for +3V3 memory mww 0xffffea08 0x85227259 ;# SDRAMC_CR : Configure SDRAM (2 x Micron MT48LC16M16A2 : 4M x 16Bit x 4 Banks) mww 0xffffea00 0x1 ;# SDRAMC_MR : issue a NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue 8 x 'Auto-Refresh' Command mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : normal mode mww 0x20000000 0 mww 0xffffea04 0x2b6 ;# SDRAMC_TR : Set refresh timer count to 7us } openocd-0.9.0/tcl/board/at91sam9263-ek.cfg0000644000175000017500000000465312526202243014630 00000000000000################################################################################ # Atmel AT91SAM9263-EK eval board ################################################################################ source [find mem_helper.tcl] source [find target/at91sam9263.cfg] uplevel #0 [list source [find chip/atmel/at91/hardware.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9263.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9263_matrix.cfg]] uplevel #0 [list source [find chip/atmel/at91/at91sam9_init.cfg]] # By default S1 is open and this means that NTRST is not connected. # The reset_config in target/at91sam9263.cfg is overridden here. # (or S1 must be populated with a 0 Ohm resistor) reset_config srst_only scan_chain $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { at91sam9263ek_reset_init } $_TARGETNAME configure -event reset-start { at91sam9_reset_start } proc at91sam9263ek_reset_init { } { set config(master_pll_div) 14 set config(master_pll_mul) 171 set val [expr $::AT91_WDT_WDV] ;# Counter Value set val [expr ($val | $::AT91_WDT_WDDIS)] ;# Watchdog Disable set val [expr ($val | $::AT91_WDT_WDD)] ;# Delta Value set val [expr ($val | $::AT91_WDT_WDDBGHLT)] ;# Debug Halt set val [expr ($val | $::AT91_WDT_WDIDLEHLT)] ;# Idle Halt set config(wdt_mr_val) $val set config(sdram_piod) 1 ;# EBI_CSA, no pull-ups for D[15:0], CS1 SDRAM, CS3 NAND Flash set config(matrix_ebicsa_addr) $::AT91_MATRIX_EBI0CSA set val [expr $::AT91_MATRIX_EBI0_DBPUC] set val [expr ($val | $::AT91_MATRIX_EBI0_VDDIOMSEL_3_3V)] set val [expr ($val | $::AT91_MATRIX_EBI0_CS1A_SDRAMC)] set config(matrix_ebicsa_val) $val ;# SDRAMC_CR - Configuration register set val [expr $::AT91_SDRAMC_NC_9] set val [expr ($val | $::AT91_SDRAMC_NR_13)] set val [expr ($val | $::AT91_SDRAMC_NB_4)] set val [expr ($val | $::AT91_SDRAMC_CAS_3)] set val [expr ($val | $::AT91_SDRAMC_DBW_32)] set val [expr ($val | (1 << 8))] ;# Write Recovery Delay set val [expr ($val | (7 << 12))] ;# Row Cycle Delay set val [expr ($val | (2 << 16))] ;# Row Precharge Delay set val [expr ($val | (2 << 20))] ;# Row to Column Delay set val [expr ($val | (5 << 24))] ;# Active to Precharge Delay set val [expr ($val | (1 << 28))] ;# Exit Self Refresh to Active Delay set config(sdram_cr_val) $val set config(sdram_tr_val) 0x13c set config(sdram_base) $::AT91_CHIPSELECT_1 at91sam9_reset_init $config } openocd-0.9.0/tcl/board/at91cap7a-stk-sdram.cfg0000644000175000017500000000714612526202243016025 00000000000000# http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4394 # # use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cap7 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x40700f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-start { # start off real slow when we're running off internal RC oscillator adapter_khz 32 } proc peek32 {address} { mem2array t 32 $address 1 return $t(0) } # Wait for an expression to be true with a timeout proc wait_state {expression} { for {set i 0} {$i < 1000} {set i [expr $i + 1]} { if {[uplevel 1 $expression] == 0} { return } } return -code 1 "Timed out" } # Use a global variable here to be able to tinker interactively with # post reset jtag frequency. global post_reset_khz # Danger!!!! Even 16MHz kinda works with this target, but # it needs to be as low as 2000kHz to be stable. set post_reset_khz 2000 $_TARGETNAME configure -event reset-init { echo "Configuring master clock" # disable watchdog mww 0xfffffd44 0xff008000 # enable user reset mww 0xfffffd08 0xa5000001 # Enable main oscillator mww 0xFFFFFc20 0x00000f01 wait_state {expr {([peek32 0xFFFFFC68] & 0x1) == 0}} # Set PLLA to 96MHz mww 0xFFFFFc28 0x20072801 wait_state {expr {([peek32 0xFFFFFC68] & 0x2) == 0}} # Select prescaler mww 0xFFFFFC30 0x00000004 wait_state {expr {([peek32 0xFFFFFC68] & 0x8) == 0}} # Select master clock to 48MHz mww 0xFFFFFC30 0x00000006 wait_state {expr {([peek32 0xFFFFFC68] & 0x8) == 0}} echo "Master clock ok." # Now that we're up and running, crank up speed! global post_reset_khz ; adapter_khz $post_reset_khz echo "Configuring the SDRAM controller..." # Configure EBI Chip select for SDRAM mww 0xFFFFEF30 0x00000102 # Enable clock on EBI PIOs mww 0xFFFFFC10 0x00000004 # Configure PIO for SDRAM mww 0xFFFFF470 0xFFFF0000 mww 0xFFFFF474 0x00000000 mww 0xFFFFF404 0xFFFF0000 # Configure SDRAMC CR mww 0xFFFFEA08 0xA63392F9 # NOP command mww 0xFFFFEA00 0x1 mww 0x20000000 0 # Precharge All Banks command mww 0xFFFFEA00 0x2 mww 0x20000000 0 # Set 1st CBR mww 0xFFFFEA00 0x00000004 mww 0x20000010 0x00000001 # Set 2nd CBR mww 0xFFFFEA00 0x00000004 mww 0x20000020 0x00000002 # Set 3rd CBR mww 0xFFFFEA00 0x00000004 mww 0x20000030 0x00000003 # Set 4th CBR mww 0xFFFFEA00 0x00000004 mww 0x20000040 0x00000004 # Set 5th CBR mww 0xFFFFEA00 0x00000004 mww 0x20000050 0x00000005 # Set 6th CBR mww 0xFFFFEA00 0x00000004 mww 0x20000060 0x00000006 # Set 7th CBR mww 0xFFFFEA00 0x00000004 mww 0x20000070 0x00000007 # Set 8th CBR mww 0xFFFFEA00 0x00000004 mww 0x20000080 0x00000008 # Set LMR operation mww 0xFFFFEA00 0x00000003 # Perform LMR burst=1, lat=2 mww 0x20000020 0xCAFEDEDE # Set Refresh Timer mww 0xFFFFEA04 0x00000203 # Set Normal mode mww 0xFFFFEA00 0x00000000 mww 0x20000000 0x00000000 #remap internal memory at address 0x0 mww 0xffffef00 0x3 echo "SDRAM configuration ok." } $_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0 arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable #set _FLASHNAME $_CHIPNAME.flash #flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432 openocd-0.9.0/tcl/board/ek-lm3s1968.cfg0000644000175000017500000000110312526202243014216 00000000000000# # TI/Luminary Stellaris LM3S1968 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s1968 # # NOTE: to use J-Link instead of the on-board interface, # you may also need to reduce adapter_khz to be about 1200. # source [find interface/jlink.cfg] # include the FT2232 interface config for on-board JTAG interface # NOTE: using the on-board FT2232 JTAG/SWD/SWO interface is optional! # so is using in JTAG mode, as done here. source [find interface/ftdi/luminary.cfg] # include the target config set WORKAREASIZE 0x2000 set CHIPNAME lm3s1968 source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/stm32f0discovery.cfg0000644000175000017500000000042512526202243015547 00000000000000# This is an STM32F0 discovery board with a single STM32F051R8T6 chip. # http://www.st.com/internet/evalboard/product/253215.jsp source [find interface/stlink-v2.cfg] transport select hla_swd set WORKAREASIZE 0x2000 source [find target/stm32f0x.cfg] reset_config srst_only openocd-0.9.0/tcl/board/xmc1100-boot-kit.cfg0000644000175000017500000000033512526202243015240 00000000000000# # Infineon XMC1100 Boot Kit # # # Segger J-Link Lite XMC4200 on-board # source [find interface/jlink.cfg] transport select swd set CHIPNAME xmc1100 source [find target/xmc1xxx.cfg] reset_config srst_only srst_nogate openocd-0.9.0/tcl/board/netgear-dg834v3.cfg0000644000175000017500000000117612526202243015152 00000000000000# # Netgear DG834v3 Router # Internal 4Kb RAM (@0x80000000) # Flash is located at 0x90000000 (CS0) and RAM is located at 0x94000000 (CS1) # set partition_list { loader { "Bootloader (ADAM2)" 0x90000000 0x00020000 } firmware { "Kernel+rootfs" 0x90020000 0x003d0000 } config { "Bootloader config space" 0x903f0000 0x00010000 } } source [find target/ti-ar7.cfg] # External 16MB SDRAM - disabled as we use internal sram #$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 0x00001000 # External 4MB NOR Flash set _FLASHNAME $_CHIPNAME.norflash flash bank $_FLASHNAME cfi 0x90000000 0x00400000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/balloon3-cpu.cfg0000644000175000017500000000105112526202243014713 00000000000000# Config for balloon3 board, cpu JTAG port. http://balloonboard.org/ # The board has separate JTAG ports for cpu and CPLD/FPGA devices # Chaining is done on IO interfaces if desired. source [find target/pxa270.cfg] # The board supports separate reset lines # Override this in the interface config for parallel dongles reset_config trst_and_srst separate # flash bank # 29LV650 64Mbit Flash set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x00000000 0x800000 2 2 $_TARGETNAME openocd-0.9.0/tcl/board/frdm-kl46z.cfg0000644000175000017500000000053112526202243014317 00000000000000# This is an Freescale Freedom eval board with a single MKL46Z256VLL4 chip. # http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=FRDM-KL46Z # source [find interface/cmsis-dap.cfg] # increase working area to 16KB set WORKAREASIZE 0x4000 # chip name set CHIPNAME MKL46Z256VLL4 reset_config srst_only source [find target/kl46.cfg] openocd-0.9.0/tcl/board/str910-eval.cfg0000644000175000017500000000317312526202243014413 00000000000000# str910-eval eval board # # Need reset scripts reset_config trst_and_srst # FIXME use some standard target config, maybe create one from this # # source [find target/...cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str912 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists FLASHTAPID] } { set _FLASHTAPID $FLASHTAPID } else { set _FLASHTAPID 0x04570041 } jtag newtap $_CHIPNAME flash -irlen 8 -ircapture 0x1 -irmask 0x1 -expected-id $_FLASHTAPID if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x25966041 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { set _BSTAPID 0x1457f041 } jtag newtap $_CHIPNAME bs -irlen 5 -ircapture 0x1 -irmask 0x1 -expected-id $_BSTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x50000000 -work-area-size 16384 -work-area-backup 1 $_TARGETNAME configure -event reset-init { # We can increase speed now that we know the target is halted. #jtag_rclk 3000 # -- Enable 96K RAM # PFQBC enabled / DTCM & AHB wait-states disabled mww 0x5C002034 0x0191 str9x flash_config 0 4 2 0 0x80000 flash protect 0 0 7 off } #flash bank str9x 0 0 set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME str9x 0x00000000 0x00080000 0 0 0 set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME str9x 0x00080000 0x00008000 0 0 0 openocd-0.9.0/tcl/board/diolan_lpc4350-db1.cfg0000644000175000017500000000014512526202243015504 00000000000000 # # Diolan LPC-4350-DB1 development board # set CHIPNAME lpc4350 source [find target/lpc4350.cfg] openocd-0.9.0/tcl/board/redbee.cfg0000644000175000017500000000004212526202243013642 00000000000000source [find target/mc13224v.cfg] openocd-0.9.0/tcl/board/efikamx.cfg0000644000175000017500000000036512526202243014050 00000000000000# Genesi USA EfikaMX # http://www.genesi-usa.com/products/efika # Fall back to 6MHz if RTCK is not supported jtag_rclk 6000 $_TARGETNAME configure -event "reset-start" { jtag_rclk 6000 } source [find target/imx51.cfg] reset_config trst_only openocd-0.9.0/tcl/board/atmel_sam3u_ek.cfg0000644000175000017500000000007612526202243015314 00000000000000source [find target/at91sam3u4e.cfg] reset_config srst_only openocd-0.9.0/tcl/board/xmc4200-application-kit-actuator.cfg0000644000175000017500000000031312526202243020420 00000000000000# # Infineon XMC4200 Application Kit - Actuator # # # Segger J-Link Lite XMC4200 on-board # source [find interface/jlink.cfg] transport select swd set CHIPNAME xmc4200 source [find target/xmc4xxx.cfg] openocd-0.9.0/tcl/board/olimex_sam7_la2.cfg0000644000175000017500000000376112526202243015411 00000000000000source [find target/at91sam7a2.cfg] # delays needed to get stable reads of cpu state jtag_ntrst_delay 10 adapter_nsrst_delay 200 # board uses pullup and connects only srst reset_config srst_open_drain # srst is connected to NRESET of CPU and fully resets everything... reset_config srst_only srst_pulls_trst adapter_khz 1 $_TARGETNAME configure -event reset-start { adapter_khz 1 } $_TARGETNAME configure -event reset-init { # init script from http://www.mikrocontroller.net/topic/107462 # AT91SAM7A2 # AMC (advanced memory controller) echo "setting up AMC" # AMC_CS0 - FLASH 1MB (0x40000000-0x400FFFFF) + DM9000E (0x40100000) mww 0xFFE00000 0x40003EBD # AMC_CS1 - RAM low 2MB (0x40400000-0x405FFFFF) mww 0xFFE00004 0x404030A9 # AMC_CS2 - RAM high 2MB (0x40800000-0x405FFFFF) #mww 0xFFE00008 0x404030A9 # changed to 0x40_8_ mww 0xFFE00008 0x408030A9 # AMC_MCR mww 0xFFE00024 0x00000004 # AMC_RCR force remap mww 0xFFE00020 0x00000001 echo "set up AMC" sleep 100 # the following base addresses from the original script did not correspond to those from datasheet # changed bases from 0xFF000000 to 0xFFF00000 # disable watchdog, to prevent unwanted resets mww 0xFFFA0068 0x00000000 echo "disabled watchdog" sleep 50 # disable PLL mww 0xFFFEC004 0x18070004 # PLL = 10 ==> Coreclock = 6Mhz*10/2 = 30 Mhz mww 0xFFFEC010 0x762D800A # enable PLL mww 0xFFFEC000 0x23050004 echo "set up pll" sleep 100 adapter_khz 5000 } $_TARGETNAME arm7_9 dcc_downloads enable $_TARGETNAME arm7_9 fast_memory_access enable # remap: ram at 0, flash at 0x40000000, like reset-init above does $_TARGETNAME configure -work-area-phys 0x00000000 -work-area-size 0x4000 -work-area-backup 1 flash bank onboard.flash cfi 0x40000000 0x00100000 2 2 at91sam7a2.cpu # boot: ram at 0x300000, flash at 0x0, useful if board is in funny configuration #$_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x4000 -work-area-backup 1 #flash bank onboard1.flash cfi 0x00000000 0x00100000 2 2 at91sam7a2.cpu openocd-0.9.0/tcl/board/openrd.cfg0000644000175000017500000001063212526202243013711 00000000000000# Marvell OpenRD source [find interface/ftdi/openrd.cfg] source [find target/feroceon.cfg] $_TARGETNAME configure \ -work-area-phys 0x10000000 \ -work-area-size 65536 \ -work-area-backup 0 arm7_9 dcc_downloads enable # this assumes the hardware default peripherals location before u-Boot moves it set _FLASHNAME $_CHIPNAME.flash nand device $_FLASHNAME orion 0 0xd8000000 proc openrd_init { } { # We need to assert DBGRQ while holding nSRST down. # However DBGACK will be set only when nSRST is released. # Furthermore, the JTAG interface doesn't respond at all when # the CPU is in the WFI (wait for interrupts) state, so it is # possible that initial tap examination failed. So let's # re-examine the target again here when nSRST is asserted which # should then succeed. jtag_reset 0 1 feroceon.cpu arp_examine halt 0 jtag_reset 0 0 wait_halt arm mcr 15 0 0 1 0 0x00052078 mww 0xD0001400 0x43000C30 ;# DDR SDRAM Configuration Register mww 0xD0001404 0x37543000 ;# Dunit Control Low Register mww 0xD0001408 0x22125451 ;# DDR SDRAM Timing (Low) Register mww 0xD000140C 0x00000A33 ;# DDR SDRAM Timing (High) Register mww 0xD0001410 0x000000CC ;# DDR SDRAM Address Control Register mww 0xD0001414 0x00000000 ;# DDR SDRAM Open Pages Control Register mww 0xD0001418 0x00000000 ;# DDR SDRAM Operation Register mww 0xD000141C 0x00000C52 ;# DDR SDRAM Mode Register mww 0xD0001420 0x00000004 ;# DDR SDRAM Extended Mode Register mww 0xD0001424 0x0000F17F ;# Dunit Control High Register mww 0xD0001428 0x00085520 ;# Dunit Control High Register mww 0xD000147c 0x00008552 ;# Dunit Control High Register mww 0xD0001504 0x0FFFFFF1 ;# CS0n Size Register mww 0xD0001508 0x10000000 ;# CS1n Base Register mww 0xD000150C 0x0FFFFFF5 ;# CS1n Size Register mww 0xD0001514 0x00000000 ;# CS2n Size Register mww 0xD000151C 0x00000000 ;# CS3n Size Register mww 0xD0001494 0x00120012 ;# DDR2 SDRAM ODT Control (Low) Register mww 0xD0001498 0x00000000 ;# DDR2 SDRAM ODT Control (High) REgister mww 0xD000149C 0x0000E40F ;# DDR2 Dunit ODT Control Register mww 0xD0001480 0x00000001 ;# DDR SDRAM Initialization Control Register mww 0xD0020204 0x00000000 ;# Main IRQ Interrupt Mask Register mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0020204 0x00000000 ;# " mww 0xD0010000 0x01111111 ;# MPP 0 to 7 mww 0xD0010004 0x11113322 ;# MPP 8 to 15 mww 0xD0010008 0x00001111 ;# MPP 16 to 23 mww 0xD0010418 0x003E07CF ;# NAND Read Parameters REgister mww 0xD001041C 0x000F0F0F ;# NAND Write Parameters Register mww 0xD0010470 0x01C7D943 ;# NAND Flash Control Register } proc openrd_reflash_uboot { } { # reflash the u-Boot binary and reboot into it openrd_init nand probe 0 nand erase 0 0x0 0xa0000 nand write 0 uboot.bin 0 oob_softecc_kw resume } proc openrd_load_uboot { } { # load u-Boot into RAM and execute it openrd_init load_image uboot.elf verify_image uboot.elf resume 0x00600000 } openocd-0.9.0/tcl/board/atmel_samr21_xplained_pro.cfg0000644000175000017500000000024412526202243017453 00000000000000# # Atmel SAMR21 Xplained Pro evaluation kit. # source [find interface/cmsis-dap.cfg] # chip name set CHIPNAME at91samr21g18 source [find target/at91samdXX.cfg] openocd-0.9.0/tcl/board/ek-lm3s9d92.cfg0000644000175000017500000000054212526202243014304 00000000000000# # TI/Luminary Stellaris LM3S9D92 Evaluation Kits # # http://www.ti.com/tool/ek-lm3s9d92 # # NOTE: using the bundled FT2232 JTAG/SWD/SWO interface is optional! # so is using in JTAG mode, as done here. source [find interface/ftdi/luminary-icdi.cfg] # 64k working area set WORKAREASIZE 0x10000 set CHIPNAME lm3s9d92 source [find target/stellaris.cfg] openocd-0.9.0/tcl/board/lpc4350_spifi_generic.cfg0000644000175000017500000000111212526202243016373 00000000000000# # Generic LPC4350 board w/ SPIFI flash. # This config file is intended as an example of how to # use the lpcspifi flash driver, but it should be functional # for most LPC4350 boards utilizing SPIFI flash. set CHIPNAME lpc4350 source [find target/lpc4350.cfg] #A large working area greatly reduces flash write times set _WORKAREASIZE 0x2000 $_CHIPNAME.m4 configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE #Configure the flash bank; 0x14000000 is the base address for #lpc43xx/lpc18xx family micros. flash bank SPIFI_FLASH lpcspifi 0x14000000 0 0 0 $_CHIPNAME.m4 openocd-0.9.0/tcl/board/tx25_stk5.cfg0000644000175000017500000001102212526202243014164 00000000000000# ------------------------------------------------------------------------- # KaRo TX25 CPU Module on a StarterkitV base board # http://www.karo-electronics.com/tx25.html # ------------------------------------------------------------------------- source [find tcl/target/imx25.cfg] #------------------------------------------------------------------------- # Declare Nand #------------------------------------------------------------------------- nand device K9F1G08UOC mxc imx25.cpu mx25 hwecc biswap $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { tx25_init } proc tx25_init { } { #------------------------------------------------------------------------- # AIPS setup - Only setup MPROTx registers. The PACR default values are good. # Set all MPROTx to be non-bufferable, trusted for R/W, # not forced to user-mode. #------------------------------------------------------------------------- mww 0x43f00000 0x77777777 mww 0x43f00004 0x77777777 mww 0x53f00000 0x77777777 mww 0x53f00004 0x77777777 sleep 100 #------------------------------------------------------------------------- # MAX (Multi-Layer AHB Crossbar Switch) setup # MPR - priority for MX25 is (SDHC2/SDMA)>USBOTG>RTIC>IAHB>DAHB #------------------------------------------------------------------------- mww 0x43f04000 0x00043210 mww 0x43f04100 0x00043210 mww 0x43f04200 0x00043210 mww 0x43f04300 0x00043210 mww 0x43f04400 0x00043210 # SGPCR - always park on last master mww 0x43f04010 0x10 mww 0x43f04110 0x10 mww 0x43f04210 0x10 mww 0x43f04310 0x10 mww 0x43f04410 0x10 # MGPCR - restore default values mww 0x43f04800 0x0 mww 0x43f04900 0x0 mww 0x43f04a00 0x0 mww 0x43f04b00 0x0 mww 0x43f04c00 0x0 # Configure M3IF registers # M3IF Control Register (M3IFCTL) for MX25 # MRRP[0] = LCDC on priority list (1 << 0) = 0x00000001 # MRRP[1] = MAX1 not on priority list (0 << 1) = 0x00000000 # MRRP[2] = MAX0 not on priority list (0 << 2) = 0x00000000 # MRRP[3] = USB HOST not on priority list (0 << 3) = 0x00000000 # MRRP[4] = SDMA not on priority list (0 << 4) = 0x00000000 # MRRP[5] = SD/ATA/FEC not on priority list (0 << 5) = 0x00000000 # MRRP[6] = SCMFBC not on priority list (0 << 6) = 0x00000000 # MRRP[7] = CSI not on priority list (0 << 7) = 0x00000000 # ---------- # 0x00000001 mww 0xb8003000 0x00000001 #------------------------------------------------------------------------- # configure ARM CLK #------------------------------------------------------------------------- # Set the Clock CTL (HRM p. 355) mww 0x53F80008 0x20034000 # Setup Clock Gating CTL 0-2 (HRM p. 357) mww 0x53F8000C 0x1fffffff mww 0x53F80010 0xffffffff mww 0x53F80014 0x000fdfff #------------------------------------------------------------------------- # SDRAM initialization #------------------------------------------------------------------------- # set to 3.3v SDRAM mww 0x43FAC454 0x00000800 # reset (set up ESDMISC) mww 0xB8001010 0x00000002 # Setup for SDRAM Bank 0 #------------------------------------------------------------------------- # Write ESDCFG0 mww 0xB8001004 0x00095728 # CTL SMode = Precharge command mww 0xB8001000 0x92116480 mww 0x80000400 0x00000000 # CTL SMode = Auto Refresh command mww 0xB8001000 0xA2116480 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 mww 0x80000000 0x0 # CTL SMode = Load Mode Register command mww 0xB8001000 0xB2116480 mwb 0x80000033 0x00 # CTL SMode = normal mww 0xB8001000 0x82116480 # Setup for SDRAM Bank 1 #------------------------------------------------------------------------- # Write ESDCFG1 mww 0xB800100C 0x00095728 # CTL SMode = Precharge command mww 0xB8001008 0x92116480 mww 0x90000400 0x00000000 # CTL SMode = Auto Refresh command mww 0xB8001008 0xA2116480 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 mww 0x90000000 0x00000000 # CTL SMode = Load Mode Register command mww 0xB8001008 0xB2116480 mwb 0x90000033 0x00 # CTL SMode = normal mww 0xB8001008 0x82116480 # GPIO configuration #------------------------------------------------------------------------- mww 0x43FAC02C 0x00000015 mww 0x53FD0000 0x01000000 mww 0x53FD0004 0x00000080 } openocd-0.9.0/tcl/board/csb732.cfg0000644000175000017500000000263612526202243013432 00000000000000# The Cogent CSB732 board has a single i.MX35 chip source [find target/imx35.cfg] # Determined by trial and error reset_config trst_and_srst combined adapter_nsrst_delay 200 jtag_ntrst_delay 200 $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { csb732_init } # Bare-bones initialization of core clocks and SDRAM proc csb732_init { } { # Disable fast writing only for init memwrite burst disable # All delay loops are omitted. # We assume the interpreter latency is enough. # Allow access to all coprocessors arm mcr 15 0 15 1 0 0x2001 # Disable MMU, caches, write buffer arm mcr 15 0 1 0 0 0x78 # Grant manager access to all domains arm mcr 15 0 3 0 0 0xFFFFFFFF # Set ARM clock to 532 MHz, AHB to 133 MHz mww 0x53F80004 0x1000 # Set core clock to 2 * 24 MHz * (11 + 1/12) = 532 MHz mww 0x53F8001C 0xB2C01 set ESDMISC 0xB8001010 set ESDCFG0 0xB8001004 set ESDCTL0 0xB8001000 # Enable DDR mww $ESDMISC 0x4 # Timing mww $ESDCFG0 0x007fff3f # CS0 mww $ESDCTL0 0x92120080 # Precharge all dummy write mww 0x80000400 0 # Enable CS) auto-refresh mww $ESDCTL0 0xA2120080 # Refresh twice (dummy writes) mww 0x80000000 0 mww 0x80000000 0 # Enable CS0 load mode register mww $ESDCTL0 0xB2120080 # Dummy writes mwb 0x80000033 0x01 mwb 0x81000000 0x01 mww $ESDCTL0 0x82226080 mww 0x80000000 0 # Re-enable fast writing memwrite burst enable } openocd-0.9.0/tcl/board/imx27ads.cfg0000644000175000017500000000362312526202243014062 00000000000000# The IMX27 ADS eval board has a single IMX27 chip # Note: tested on IMX27ADS Board REV-2.6 and REV-2.8 source [find target/imx27.cfg] $_TARGETNAME configure -event gdb-attach { reset init } $_TARGETNAME configure -event reset-init { imx27ads_init } # The IMX27 ADS board has a NOR flash on CS0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0xc0000000 0x00200000 2 2 $_TARGETNAME proc imx27ads_init { } { # This setup puts RAM at 0xA0000000 # reset the board correctly reset run reset halt mww 0x10000000 0x20040304 mww 0x10020000 0x00000000 mww 0x10000004 0xDFFBFCFB mww 0x10020004 0xFFFFFFFF sleep 100 # ======================================== # Configure DDR on CSD0 -- initial reset # ======================================== mww 0xD8001010 0x00000008 # ======================================== # Configure PSRAM on CS5 # ======================================== mww 0xd8002050 0x0000dcf6 mww 0xd8002054 0x444a4541 mww 0xd8002058 0x44443302 # ======================================== # Configure16 bit NorFlash on CS0 # ======================================== mww 0xd8002000 0x0000CC03 mww 0xd8002004 0xa0330D01 mww 0xd8002008 0x00220800 # ======================================== # Configure CPLD on CS4 # ======================================== mww 0xd8002040 0x0000DCF6 mww 0xd8002044 0x444A4541 mww 0xd8002048 0x44443302 # ======================================== # Configure DDR on CSD0 -- wait 5000 cycle # ======================================== mww 0x10027828 0x55555555 mww 0x10027830 0x55555555 mww 0x10027834 0x55555555 mww 0x10027838 0x00005005 mww 0x1002783C 0x15555555 mww 0xD8001010 0x00000004 mww 0xD8001004 0x00795729 mww 0xD8001000 0x92200000 mww 0xA0000F00 0x0 mww 0xD8001000 0xA2200000 mww 0xA0000F00 0x0 mww 0xA0000F00 0x0 mww 0xD8001000 0xB2200000 mwb 0xA0000033 0xFF mwb 0xA1000000 0xAA mww 0xD8001000 0x82228085 } openocd-0.9.0/tcl/board/olimex_stm32_p107.cfg0000644000175000017500000000027112526202243015514 00000000000000# # Olimex STM32-P107 # # http://olimex.com/dev/stm32-p107.html # # Work-area size (RAM size) = 64kB for STM32F107VC device set WORKAREASIZE 0x10000 source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/tools/0000755000175000017500000000000012526202243012070 500000000000000openocd-0.9.0/tcl/tools/memtest.tcl0000644000175000017500000001636012526202243014200 00000000000000# Algorithms by Michael Barr, released into public domain # Ported to OpenOCD by Shane Volpe, additional fixes by Paul Fertser set CPU_MAX_ADDRESS 0xFFFFFFFF source [find bitsbytes.tcl] source [find memory.tcl] proc runAllMemTests { baseAddress nBytes } { memTestDataBus $baseAddress memTestAddressBus $baseAddress $nBytes memTestDevice $baseAddress $nBytes } #*********************************************************************************** # * # * Function: memTestDataBus() # * # * Description: Test the data bus wiring in a memory region by # * performing a walking 1's test at a fixed address # * within that region. The address (and hence the # * memory region) is selected by the caller. # * Ported from: # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C # * Notes: # * # * Returns: Empty string if the test succeeds. # * A non-zero result is the first pattern that failed. # * #*********************************************************************************** proc memTestDataBus { address } { echo "Running memTestDataBus" for {set i 0} {$i < 32} {incr i} { # Shift bit set pattern [expr {1 << $i}] # Write pattern to memory memwrite32 $address $pattern # Read pattern from memory set data [memread32 $address] if {$data != $pattern} { echo "FAILED DATABUS: Address: $address, Pattern: $pattern, Returned: $data" return $pattern } } } #*********************************************************************************** # * # * Function: memTestAddressBus() # * # * Description: Perform a walking 1's test on the relevant bits # * of the address and check for aliasing. This test # * will find single-bit address failures such as stuck # * -high, stuck-low, and shorted pins. The base address # * and size of the region are selected by the caller. # * Ported from: # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C # * # * Notes: For best results, the selected base address should # * have enough LSB 0's to guarantee single address bit # * changes. For example, to test a 64-Kbyte region, # * select a base address on a 64-Kbyte boundary. Also, # * select the region size as a power-of-two--if at all # * possible. # * # * Returns: Empty string if the test succeeds. # * A non-zero result is the first address at which an # * aliasing problem was uncovered. By examining the # * contents of memory, it may be possible to gather # * additional information about the problem. # * #*********************************************************************************** proc memTestAddressBus { baseAddress nBytes } { set addressMask [expr $nBytes - 1] set pattern 0xAAAAAAAA set antipattern 0x55555555 echo "Running memTestAddressBus" echo "addressMask: [convertToHex $addressMask]" echo "memTestAddressBus: Writing the default pattern at each of the power-of-two offsets..." for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1] } { set addr [expr $baseAddress + $offset] memwrite32 $addr $pattern } echo "memTestAddressBus: Checking for address bits stuck high..." memwrite32 $baseAddress $antipattern for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1]} { set addr [expr $baseAddress + $offset] set data [memread32 $addr] if {$data != $pattern} { echo "FAILED DATA_ADDR_BUS_SHIGH: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]" return $pattern } } echo "memTestAddressBus: Checking for address bits stuck low or shorted..." memwrite32 $baseAddress $pattern for {set testOffset 32} {[expr $testOffset & $addressMask] != 0} {set testOffset [expr $testOffset << 1] } { set addr [expr $baseAddress + $testOffset] memwrite32 $addr $antipattern set data [memread32 $baseAddress] if {$data != $pattern} { echo "FAILED DATA_ADDR_BUS_SLOW: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]" return $pattern } for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1]} { set addr [expr $baseAddress + $offset] set data [memread32 $baseAddress] if {(($data != $pattern) && ($offset != $testOffset))} { echo "FAILED DATA_ADDR_BUS_SLOW2: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset], testOffset [convertToHex $testOffset]" return $pattern } } set addr [expr $baseAddress + $testOffset] memwrite32 $addr $pattern } } #*********************************************************************************** # * # * Function: memTestDevice() # * # * Description: Test the integrity of a physical memory device by # * performing an increment/decrement test over the # * entire region. In the process every storage bit # * in the device is tested as zero and as one. The # * base address and the size of the region are # * selected by the caller. # * Ported from: # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C # * Notes: # * # * Returns: Empty string if the test succeeds. # * A non-zero result is the first address at which an # * incorrect value was read back. By examining the # * contents of memory, it may be possible to gather # * additional information about the problem. # * #*********************************************************************************** proc memTestDevice { baseAddress nBytes } { echo "Running memTestDevice" echo "memTestDevice: Filling memory with a known pattern..." for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} { memwrite32 [expr $baseAddress + $offset] $pattern } echo "memTestDevice: Checking each location and inverting it for the second pass..." for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} { set addr [expr $baseAddress + $offset] set data [memread32 $addr] if {$data != $pattern} { echo "FAILED memTestDevice_pattern: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset]" return $pattern } set antiPattern [expr ~$pattern] memwrite32 [expr $baseAddress + $offset] $antiPattern } echo "memTestDevice: Checking each location for the inverted pattern and zeroing it..." for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} { set antiPattern [expr ~$pattern & ((1<<32) - 1)] set addr [expr $baseAddress + $offset] set data [memread32 $addr] set dataHex [convertToHex $data] set antiPatternHex [convertToHex $antiPattern] if {[expr $dataHex != $antiPatternHex]} { echo "FAILED memTestDevice_antipattern: Address: [convertToHex $addr], antiPattern: $antiPatternHex, Returned: $dataHex, offset: $offset" return $pattern } } } proc convertToHex { value } { format 0x%08x $value } openocd-0.9.0/tcl/tools/firmware-recovery.tcl0000644000175000017500000000634012526202243016167 00000000000000echo "\n\nFirmware recovery helpers" echo "Use -c firmware_help to get help\n" set known_boards { "asus-rt-n16 ASUS RT-N16" "asus-rt-n66u ASUS RT-N66U" "linksys-wrt54gl Linksys WRT54GL v1.1" "netgear-dg834v3 Netgear DG834G v3" "tp-link_tl-mr3020 TP-LINK TL-MR3020" "bt-homehubv1 BT HomeHub v1" } proc firmware_help { } { echo " Your OpenOCD command should look like this: openocd -f interface/.cfg -f tools/firmware-recovery.tcl -c \"*; shutdown\" Where: is one of the supported devices, e.g. ftdi/jtagkey2 are firmware-recovery commands separated by semicolon Supported commands: firmware_help get this help list_boards list known boards and exit board select board you work with list_partitions list partitions of the currently selected board dump_part save partition's contents to a file erase_part erase the given partition flash_part erase, flash and verify the given partition ram_boot load binary file to RAM and run it adapter_khz set JTAG clock frequency in kHz For example, to clear nvram and reflash CFE on an RT-N16 using TUMPA, run: openocd -f interface/ftdi/tumpa.cfg -f tools/firmware-recovery.tcl \\ -c \"board asus-rt-n16; erase_part nvram; flash_part CFE cfe-n16.bin; shutdown\" \n\n" shutdown } # set default, can be overriden later adapter_khz 1000 proc get_partition { name } { global partition_list dict get $partition_list $name } proc partition_desc { name } { lindex [get_partition $name] 0 } proc partition_start { name } { lindex [get_partition $name] 1 } proc partition_size { name } { lindex [get_partition $name] 2 } proc list_boards { } { global known_boards echo "List of the supported boards:\n" echo "Board name\t\tDescription" echo "-----------------------------------" foreach i $known_boards { echo $i } echo "\n\n" } proc board { name } { script [find board/$name.cfg] } proc list_partitions { } { global partition_list set fstr "%-16s%-14s%-14s%s" echo "\nThe currently selected board is known to have these partitions:\n" echo [format $fstr Name Start Size Description] echo "-------------------------------------------------------" for {set i 0} {$i < [llength $partition_list]} {incr i 2} { set key [lindex $partition_list $i] echo [format $fstr $key [partition_start $key] [partition_size $key] [partition_desc $key]] } echo "\n\n" } # Magic to work with any targets, including semi-functional proc prepare_target { } { init catch {halt} catch {reset init} catch {halt} } proc dump_part { name filename } { prepare_target dump_image $filename [partition_start $name] [partition_size $name] } proc erase_part { name } { prepare_target flash erase_address [partition_start $name] [partition_size $name] } proc flash_part { name filename } { prepare_target flash write_image erase $filename [partition_start $name] bin echo "Verifying:" verify_image $filename [partition_start $name] } proc ram_boot { filename } { global ram_boot_address prepare_target load_image $filename $ram_boot_address bin resume $ram_boot_address } echo "" openocd-0.9.0/tcl/mmr_helpers.tcl0000644000175000017500000000316012526202243013671 00000000000000 proc proc_exists { NAME } { set n [info commands $NAME] set l [string length $n] return [expr $l != 0] } # Give: REGISTER name - must be a global variable. proc show_mmr32_reg { NAME } { global $NAME # we want $($NAME) set a [set [set NAME]] if ![catch { set v [memread32 $a] } msg ] { echo [format "%15s: (0x%08x): 0x%08x" $NAME $a $v] # Was a helper defined? set fn show_${NAME}_helper if [ proc_exists $fn ] { # Then call it $fn $NAME $a $v } return $v; } else { error [format "%s (%s)" $msg $NAME ] } } # Give: NAMES - an array of names accessable # in the callers symbol-scope. # VAL - the bits to display. proc show_mmr32_bits { NAMES VAL } { upvar $NAMES MYNAMES set w 5 foreach {IDX N} $MYNAMES { set l [string length $N] if { $l > $w } { set w $l } } for { set x 24 } { $x >= 0 } { incr x -8 } { echo -n " " for { set y 7 } { $y >= 0 } { incr y -1 } { set s $MYNAMES([expr $x + $y]) echo -n [format "%2d: %-*s | " [expr $x + $y] $w $s ] } echo "" echo -n " " for { set y 7 } { $y >= 0 } { incr y -1 } { echo -n [format " %d%*s | " [expr !!($VAL & (1 << ($x + $y)))] [expr $w -1] ""] } echo "" } } proc show_mmr_bitfield { MSB LSB VAL FIELDNAME FIELDVALUES } { set width [expr (($MSB - $LSB + 1) + 7) / 4] set nval [show_normalize_bitfield $VAL $MSB $LSB ] set name0 [lindex $FIELDVALUES 0 ] if [ string compare $name0 _NUMBER_ ] { set sval [lindex $FIELDVALUES $nval] } else { set sval "" } echo [format "%-15s: %d (0x%0*x) %s" $FIELDNAME $nval $width $nval $sval ] } openocd-0.9.0/tcl/target/0000755000175000017500000000000012526202245012220 500000000000000openocd-0.9.0/tcl/target/davinci.cfg0000644000175000017500000002543712526202243014247 00000000000000# # Utility code for DaVinci-family chips # # davinci_pinmux: assigns PINMUX$reg <== $value proc davinci_pinmux {soc reg value} { mww [expr [dict get $soc sysbase] + 4 * $reg] $value } source [find mem_helper.tcl] # # pll_setup: initialize PLL # - pll_addr ... physical addr of controller # - mult ... pll multiplier # - config ... dict mapping { prediv, postdiv, div[1-9] } to dividers # # For PLLs that don't have a given register (e.g. plldiv8), or where a # given divider is non-programmable, caller provides *NO* config mapping. # # PLL version 0x02: tested on dm355 # REVISIT: On dm6446/dm357 the PLLRST polarity is different. proc pll_v02_setup {pll_addr mult config} { set pll_ctrl_addr [expr $pll_addr + 0x100] set pll_ctrl [mrw $pll_ctrl_addr] # 1 - clear CLKMODE (bit 8) iff using on-chip oscillator # NOTE: this assumes we should clear that bit set pll_ctrl [expr $pll_ctrl & ~0x0100] mww $pll_ctrl_addr $pll_ctrl # 2 - clear PLLENSRC (bit 5) set pll_ctrl [expr $pll_ctrl & ~0x0020] mww $pll_ctrl_addr $pll_ctrl # 3 - clear PLLEN (bit 0) ... enter bypass mode set pll_ctrl [expr $pll_ctrl & ~0x0001] mww $pll_ctrl_addr $pll_ctrl # 4 - wait at least 4 refclk cycles sleep 1 # 5 - set PLLRST (bit 3) set pll_ctrl [expr $pll_ctrl | 0x0008] mww $pll_ctrl_addr $pll_ctrl # 6 - set PLLDIS (bit 4) set pll_ctrl [expr $pll_ctrl | 0x0010] mww $pll_ctrl_addr $pll_ctrl # 7 - clear PLLPWRDN (bit 1) set pll_ctrl [expr $pll_ctrl & ~0x0002] mww $pll_ctrl_addr $pll_ctrl # 8 - clear PLLDIS (bit 4) set pll_ctrl [expr $pll_ctrl & ~0x0010] mww $pll_ctrl_addr $pll_ctrl # 9 - optional: write prediv, postdiv, and pllm # NOTE: for dm355 PLL1, postdiv is controlled via MISC register mww [expr $pll_addr + 0x0110] [expr ($mult - 1) & 0xff] if { [dict exists $config prediv] } { set div [dict get $config prediv] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0114] $div } if { [dict exists $config postdiv] } { set div [dict get $config postdiv] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0128] $div } # 10 - optional: set plldiv1, plldiv2, ... # NOTE: this assumes some registers have their just-reset values: # - PLLSTAT.GOSTAT is clear when we enter # - ALNCTL has everything set set go 0 if { [dict exists $config div1] } { set div [dict get $config div1] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0118] $div set go 1 } if { [dict exists $config div2] } { set div [dict get $config div2] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x011c] $div set go 1 } if { [dict exists $config div3] } { set div [dict get $config div3] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0120] $div set go 1 } if { [dict exists $config div4] } { set div [dict get $config div4] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0160] $div set go 1 } if { [dict exists $config div5] } { set div [dict get $config div5] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0164] $div set go 1 } if {$go != 0} { # write pllcmd.GO; poll pllstat.GO mww [expr $pll_addr + 0x0138] 0x01 set pllstat [expr $pll_addr + 0x013c] while {[expr [mrw $pllstat] & 0x01] != 0} { sleep 1 } } mww [expr $pll_addr + 0x0138] 0x00 # 11 - wait at least 5 usec for reset to finish # (assume covered by overheads including JTAG messaging) # 12 - clear PLLRST (bit 3) set pll_ctrl [expr $pll_ctrl & ~0x0008] mww $pll_ctrl_addr $pll_ctrl # 13 - wait at least 8000 refclk cycles for PLL to lock # if we assume 24 MHz (slowest osc), that's 1/3 msec sleep 3 # 14 - set PLLEN (bit 0) ... leave bypass mode set pll_ctrl [expr $pll_ctrl | 0x0001] mww $pll_ctrl_addr $pll_ctrl } # PLL version 0x03: tested on dm365 proc pll_v03_setup {pll_addr mult config} { set pll_ctrl_addr [expr $pll_addr + 0x100] set pll_secctrl_addr [expr $pll_addr + 0x108] set pll_ctrl [mrw $pll_ctrl_addr] # 1 - power up the PLL set pll_ctrl [expr $pll_ctrl & ~0x0002] mww $pll_ctrl_addr $pll_ctrl # 2 - clear PLLENSRC (bit 5) set pll_ctrl [expr $pll_ctrl & ~0x0020] mww $pll_ctrl_addr $pll_ctrl # 2 - clear PLLEN (bit 0) ... enter bypass mode set pll_ctrl [expr $pll_ctrl & ~0x0001] mww $pll_ctrl_addr $pll_ctrl # 3 - wait at least 4 refclk cycles sleep 1 # 4 - set PLLRST (bit 3) set pll_ctrl [expr $pll_ctrl | 0x0008] mww $pll_ctrl_addr $pll_ctrl # 5 - wait at least 5 usec sleep 1 # 6 - clear PLLRST (bit 3) set pll_ctrl [expr $pll_ctrl & ~0x0008] mww $pll_ctrl_addr $pll_ctrl # 9 - optional: write prediv, postdiv, and pllm mww [expr $pll_addr + 0x0110] [expr ($mult / 2) & 0x1ff] if { [dict exists $config prediv] } { set div [dict get $config prediv] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0114] $div } if { [dict exists $config postdiv] } { set div [dict get $config postdiv] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0128] $div } # 10 - write start sequence to PLLSECCTL mww $pll_secctrl_addr 0x00470000 mww $pll_secctrl_addr 0x00460000 mww $pll_secctrl_addr 0x00400000 mww $pll_secctrl_addr 0x00410000 # 11 - optional: set plldiv1, plldiv2, ... # NOTE: this assumes some registers have their just-reset values: # - PLLSTAT.GOSTAT is clear when we enter set aln 0 if { [dict exists $config div1] } { set div [dict get $config div1] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0118] $div set aln [expr $aln | 0x1] } else { mww [expr $pll_addr + 0x0118] 0 } if { [dict exists $config div2] } { set div [dict get $config div2] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x011c] $div set aln [expr $aln | 0x2] } else { mww [expr $pll_addr + 0x011c] 0 } if { [dict exists $config div3] } { set div [dict get $config div3] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0120] $div set aln [expr $aln | 0x4] } else { mww [expr $pll_addr + 0x0120] 0 } if { [dict exists $config oscdiv] } { set div [dict get $config oscdiv] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0124] $div } else { mww [expr $pll_addr + 0x0124] 0 } if { [dict exists $config div4] } { set div [dict get $config div4] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0160] $div set aln [expr $aln | 0x8] } else { mww [expr $pll_addr + 0x0160] 0 } if { [dict exists $config div5] } { set div [dict get $config div5] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0164] $div set aln [expr $aln | 0x10] } else { mww [expr $pll_addr + 0x0164] 0 } if { [dict exists $config div6] } { set div [dict get $config div6] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0168] $div set aln [expr $aln | 0x20] } else { mww [expr $pll_addr + 0x0168] 0 } if { [dict exists $config div7] } { set div [dict get $config div7] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x016c] $div set aln [expr $aln | 0x40] } else { mww [expr $pll_addr + 0x016c] 0 } if { [dict exists $config div8] } { set div [dict get $config div8] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0170] $div set aln [expr $aln | 0x80] } else { mww [expr $pll_addr + 0x0170] 0 } if { [dict exists $config div9] } { set div [dict get $config div9] set div [expr 0x8000 | ($div - 1)] mww [expr $pll_addr + 0x0174] $div set aln [expr $aln | 0x100] } else { mww [expr $pll_addr + 0x0174] 0 } if {$aln != 0} { # clear pllcmd.GO mww [expr $pll_addr + 0x0138] 0x00 # write alingment flags mww [expr $pll_addr + 0x0140] $aln # write pllcmd.GO; poll pllstat.GO mww [expr $pll_addr + 0x0138] 0x01 set pllstat [expr $pll_addr + 0x013c] while {[expr [mrw $pllstat] & 0x01] != 0} { sleep 1 } } mww [expr $pll_addr + 0x0138] 0x00 set addr [dict get $config ctladdr] while {[expr [mrw $addr] & 0x0e000000] != 0x0e000000} { sleep 1 } # 12 - set PLLEN (bit 0) ... leave bypass mode set pll_ctrl [expr $pll_ctrl | 0x0001] mww $pll_ctrl_addr $pll_ctrl } # NOTE: dm6446 requires EMURSTIE set in MDCTL before certain # modules can be enabled. # prepare a non-DSP module to be enabled; finish with psc_go proc psc_enable {module} { set psc_addr 0x01c41000 # write MDCTL mmw [expr $psc_addr + 0x0a00 + (4 * $module)] 0x03 0x1f } # prepare a non-DSP module to be reset; finish with psc_go proc psc_reset {module} { set psc_addr 0x01c41000 # write MDCTL mmw [expr $psc_addr + 0x0a00 + (4 * $module)] 0x01 0x1f } # execute non-DSP PSC transition(s) set up by psc_enable, psc_reset, etc proc psc_go {} { set psc_addr 0x01c41000 set ptstat_addr [expr $psc_addr + 0x0128] # just in case PTSTAT.go isn't clear while { [expr [mrw $ptstat_addr] & 0x01] != 0 } { sleep 1 } # write PTCMD.go ... ignoring any DSP power domain mww [expr $psc_addr + 0x0120] 1 # wait for PTSTAT.go to clear (again ignoring DSP power domain) while { [expr [mrw $ptstat_addr] & 0x01] != 0 } { sleep 1 } } # # A reset using only SRST is a "Warm Reset", resetting everything in the # chip except ARM emulation (and everything _outside_ the chip that hooks # up to SRST). But many boards don't expose SRST via their JTAG connectors # (it's not present on TI-14 headers). # # From the chip-only perspective, a "Max Reset" is a "Warm" reset ... except # without any board-wide side effects, since it's triggered using JTAG using # either (a) ARM watchdog timer, or (b) ICEpick. # proc davinci_wdog_reset {} { set timer2_phys 0x01c21c00 # NOTE -- on entry # - JTAG communication with the ARM *must* be working OK; this # may imply using adaptive clocking or disabling WFI-in-idle # - current target must be the DaVinci ARM # - that ARM core must be halted # - timer2 clock is still enabled (PSC 29 on most chips) # # Part I -- run regardless of being halted via JTAG # # NOTE: for now, we assume there's no DSP that could control the # watchdog; or, equivalently, SUSPSRC.TMR2SRC says the watchdog # suspend signal is controlled via ARM emulation suspend. # # EMUMGT_CLKSPEED: write FREE bit to run despite emulation halt mww phys [expr $timer2_phys + 0x28] 0x00004000 # # Part II -- in case watchdog hasn't been set up # # TCR: disable, force internal clock source mww phys [expr $timer2_phys + 0x20] 0 # TGCR: reset, force to 64-bit wdog mode, un-reset ("initial" state) mww phys [expr $timer2_phys + 0x24] 0 mww phys [expr $timer2_phys + 0x24] 0x110b # clear counter (TIM12, TIM34) and period (PRD12, PRD34) registers # so watchdog triggers ASAP mww phys [expr $timer2_phys + 0x10] 0 mww phys [expr $timer2_phys + 0x14] 0 mww phys [expr $timer2_phys + 0x18] 0 mww phys [expr $timer2_phys + 0x1c] 0 # WDTCR: put into pre-active state, then active mww phys [expr $timer2_phys + 0x28] 0xa5c64000 mww phys [expr $timer2_phys + 0x28] 0xda7e4000 # # Part III -- it's ready to rumble # # WDTCR: write invalid WDKEY to trigger reset mww phys [expr $timer2_phys + 0x28] 0x00004000 } openocd-0.9.0/tcl/target/at91sam3u4c.cfg0000644000175000017500000000052212526202243014574 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME # This is a 256K chip, it has the 2nd bank set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME at91sam3 0x000100000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91sam3u4e.cfg0000644000175000017500000000052312526202243014577 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME # This is a 256K chip - it has the 2nd bank set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME at91sam3 0x000100000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/tmpa910.cfg0000644000175000017500000000226012526202243014012 00000000000000###################################### # Target: Toshiba TMPA910 ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME tmpa910 } # Toshiba TMPA910 series MCUs are always little endian as per datasheet. set _ENDIAN little if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926031 } #TMPA910 has following IDs: # CP15.0 register 0x41069265 # CP15.1 register 0x1d152152 # ARM core 0x07926031 # jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst adapter_nsrst_delay 20 jtag_ntrst_delay 20 ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME # Internal RAM-0 (16kB): 0xf8004000 # Internal RAM-1 (16kB): 0xf8008000 # Internal RAM-2 (16kB): 0xf800c000 # Use internal RAM-0, RAM-1, and RAM-2 as working area (48kB total). $_TARGETNAME configure -work-area-phys 0xf8004000 -work-area-size 0xc000 \ -work-area-backup 0 openocd-0.9.0/tcl/target/sim3x.cfg0000644000175000017500000000224512526202243013665 00000000000000# # Silicon Laboratories SiM3x Cortex-M3 # # SiM3x devices support both JTAG and SWD transports. source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME SiM3x } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } if { [info exists CPURAMSIZE] } { set _CPURAMSIZE $CPURAMSIZE } else { # Minimum size of RAM in the Silicon Labs product matrix (8KB) set _CPURAMSIZE 0x2000 } if { [info exists CPUROMSIZE] } { set _CPUROMSIZE $CPUROMSIZE } else { # Minimum size of FLASH in the Silicon Labs product matrix (32KB) set _CPUROMSIZE 0x8000 } if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE $_CPURAMSIZE } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME sim3x 0 $_CPUROMSIZE 0 0 $_TARGETNAME adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } openocd-0.9.0/tcl/target/dragonite.cfg0000644000175000017500000000124712526202243014577 00000000000000###################################### # Target: Marvell Dragonite CPU core ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dragonite } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x121003d3 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME dragonite -endian $_ENDIAN -chain-position $_TARGETNAME reset_config trst_and_srst adapter_nsrst_delay 200 jtag_ntrst_delay 200 openocd-0.9.0/tcl/target/ti_tms570ls3137.cfg0000644000175000017500000000014512526202243015227 00000000000000# TMS570LS3137 set DAP_TAPID 0x0B8A002F set JRC_TAPID 0x0B8A002F source [find target/ti_tms570.cfg] openocd-0.9.0/tcl/target/spear3xx.cfg0000644000175000017500000000177612526202243014407 00000000000000# Target configuration for the ST SPEAr3xx family of system on chip # Supported SPEAr300, SPEAr310, SPEAr320 # http://www.st.com/spear # # Processor: ARM926ejs # Info: JTAG tap: spear3xx.cpu tap/device found: 0x07926041 # Date: 2009-10-31 # Author: Antonio Borneo if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME spear3xx } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926041 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x03 \ -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN \ -chain-position $_TARGETNAME # SPEAr3xx has a 8K block of sram @ 0xd280.0000 # REVISIT: what OS puts virtual address equal to phys? $_TARGETNAME configure \ -work-area-virt 0xd2800000 \ -work-area-phys 0xd2800000 \ -work-area-size 0x2000 \ -work-area-backup 0 openocd-0.9.0/tcl/target/samsung_s3c2440.cfg0000644000175000017500000000165412526202243015364 00000000000000# Target configuration for the Samsung 2440 system on chip # Tested on a S3C2440 Evaluation board by keesj # Processor : ARM920Tid(wb) rev 0 (v4l) # Info: JTAG tap: s3c2440.cpu tap/device found: 0x0032409d (Manufacturer: 0x04e, Part: 0x0324, Version: 0x0) if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c2440 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0032409d } #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x200000 -work-area-size 0x4000 -work-area-backup 1 #reset configuration reset_config trst_and_srst openocd-0.9.0/tcl/target/aduc702x.cfg0000644000175000017500000000271112526202243014155 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME aduc702x } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # This config file was defaulting to big endian.. set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } adapter_nsrst_delay 200 jtag_ntrst_delay 200 ## JTAG scan chain #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID ## ## Target configuration ## set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME # allocate the entire SRAM as working area $_TARGETNAME configure -work-area-phys 0x10000 -work-area-size 0x2000 ## flash configuration # only target number is needed set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME aduc702x 0 0 0 0 $_TARGETNAME ## If you use the watchdog, the following code makes sure that the board ## doesn't reboot when halted via JTAG. Yes, on the older generation ## AdUC702x, timer3 continues running even when the CPU is halted. proc watchdog_service {} { global watchdog_hdl mww 0xffff036c 0 # echo "watchdog!!" set watchdog_hdl [after 500 watchdog_service] } $_TARGETNAME configure -event reset-halt-post { watchdog_service } $_TARGETNAME configure -event resume-start { global watchdog_hdl; after cancel $watchdog_hdl } openocd-0.9.0/tcl/target/samsung_s3c2450.cfg0000644000175000017500000000215112526202243015356 00000000000000# Target configuration for the Samsung 2450 system on chip # Processor : ARM926ejs (wb) rev 0 (v4l) # Info: JTAG tap: s3c2450.cpu tap/device found: 0x07926F0F # FIX!!! what to use here? # # RCLK? # # adapter_khz 0 # # Really low clock during reset? # # adapter_khz 1 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c2450 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926f0f } #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0xE -irmask 0x0f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME # FIX!!!!! should this really use srst_pulls_trst? # With srst_pulls_trst "reset halt" will not reset into the # halted mode, but rather "reset run" and then halt the target. # # However, without "srst_pulls_trst", then "reset halt" produces weird # errors: # WARNING: unknown debug reason: 0x0 reset_config trst_and_srst openocd-0.9.0/tcl/target/lpc2103.cfg0000644000175000017500000000163512526202243013710 00000000000000# NXP LPC2103 ARM7TDMI-S with 32kB flash and 8kB SRAM, clocked with 12MHz crystal source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2103 {core_freq_khz adapter_freq_khz} { # 32kB flash and 8kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2103 0x4f1f0f0f 0x8000 lpc2000_v2 0x2000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 12MHz crystal echo "Warning - assuming default core clock 12MHz! Flashing may fail if actual core clock is different." # setup_lpc2103 setup_lpc2103 12000 1500 } openocd-0.9.0/tcl/target/c100helper.tcl0000644000175000017500000005361712526202243014521 00000000000000 proc helpC100 {} { echo "List of useful functions for C100 processor:" echo "1) reset init: will set up your Telo board" echo "2) setupNOR: will setup NOR access" echo "3) showNOR: will show current NOR config registers for 16-bit, 16MB NOR" echo "4) setupGPIO: will setup GPIOs for Telo board" echo "5) showGPIO: will show current GPIO config registers" echo "6) highGPIO5: will set GPIO5=NOR_addr22=1 to access upper 8MB" echo "7) lowGPIO5: will set GPIO5=NOR_addr22=0 to access lower 8MB" echo "8) showAmbaClk: will show current config registers for Amba Bus Clock" echo "9) setupAmbaClk: will setup Amba Bus Clock=165MHz" echo "10) showArmClk: will show current config registers for Arm Bus Clock" echo "11) setupArmClk: will setup Amba Bus Clock=450MHz" echo "12) ooma_board_detect: will show which version of Telo you have" echo "13) setupDDR2: will configure DDR2 controller, you must have PLLs configureg" echo "14) showDDR2: will show DDR2 config registers" echo "15) showWatchdog: will show current regster config for watchdog" echo "16) reboot: will trigger watchdog and reboot Telo (hw reset)" echo "17) bootNOR: will boot Telo from NOR" echo "18) setupUART0: will configure UART0 for 115200 8N1, PLLs have to be confiured" echo "19) putcUART0: will print a character on UART0" echo "20) putsUART0: will print a string on UART0" echo "21) trainDDR2: will run DDR2 training program" echo "22) flashUBOOT: will prgram NOR sectors 0-3 with u-boot.bin" } source [find mem_helper.tcl] # read a 64-bit register (memory mapped) proc mr64bit {reg} { set value "" mem2array value 32 $reg 2 return $value } # write a 64-bit register (memory mapped) proc mw64bit {reg value} { set high [expr $value >> 32] set low [expr $value & 0xffffffff] #echo [format "mw64bit(0x%x): 0x%08x%08x" $reg $high $low] mww $reg $low mww [expr $reg+4] $high } proc showNOR {} { echo "This is the current NOR setup" set EX_CSEN_REG [regs EX_CSEN_REG ] set EX_CS0_SEG_REG [regs EX_CS0_SEG_REG ] set EX_CS0_CFG_REG [regs EX_CS0_CFG_REG ] set EX_CS0_TMG1_REG [regs EX_CS0_TMG1_REG ] set EX_CS0_TMG2_REG [regs EX_CS0_TMG2_REG ] set EX_CS0_TMG3_REG [regs EX_CS0_TMG3_REG ] set EX_CLOCK_DIV_REG [regs EX_CLOCK_DIV_REG ] set EX_MFSM_REG [regs EX_MFSM_REG ] set EX_CSFSM_REG [regs EX_CSFSM_REG ] set EX_WRFSM_REG [regs EX_WRFSM_REG ] set EX_RDFSM_REG [regs EX_RDFSM_REG ] echo [format "EX_CSEN_REG (0x%x): 0x%x" $EX_CSEN_REG [mrw $EX_CSEN_REG]] echo [format "EX_CS0_SEG_REG (0x%x): 0x%x" $EX_CS0_SEG_REG [mrw $EX_CS0_SEG_REG]] echo [format "EX_CS0_CFG_REG (0x%x): 0x%x" $EX_CS0_CFG_REG [mrw $EX_CS0_CFG_REG]] echo [format "EX_CS0_TMG1_REG (0x%x): 0x%x" $EX_CS0_TMG1_REG [mrw $EX_CS0_TMG1_REG]] echo [format "EX_CS0_TMG2_REG (0x%x): 0x%x" $EX_CS0_TMG2_REG [mrw $EX_CS0_TMG2_REG]] echo [format "EX_CS0_TMG3_REG (0x%x): 0x%x" $EX_CS0_TMG3_REG [mrw $EX_CS0_TMG3_REG]] echo [format "EX_CLOCK_DIV_REG (0x%x): 0x%x" $EX_CLOCK_DIV_REG [mrw $EX_CLOCK_DIV_REG]] echo [format "EX_MFSM_REG (0x%x): 0x%x" $EX_MFSM_REG [mrw $EX_MFSM_REG]] echo [format "EX_CSFSM_REG (0x%x): 0x%x" $EX_CSFSM_REG [mrw $EX_CSFSM_REG]] echo [format "EX_WRFSM_REG (0x%x): 0x%x" $EX_WRFSM_REG [mrw $EX_WRFSM_REG]] echo [format "EX_RDFSM_REG (0x%x): 0x%x" $EX_RDFSM_REG [mrw $EX_RDFSM_REG]] } proc showGPIO {} { echo "This is the current GPIO register setup" # GPIO outputs register set GPIO_OUTPUT_REG [regs GPIO_OUTPUT_REG] # GPIO Output Enable register set GPIO_OE_REG [regs GPIO_OE_REG] set GPIO_HI_INT_ENABLE_REG [regs GPIO_HI_INT_ENABLE_REG] set GPIO_LO_INT_ENABLE_REG [regs GPIO_LO_INT_ENABLE_REG] # GPIO input register set GPIO_INPUT_REG [regs GPIO_INPUT_REG] set APB_ACCESS_WS_REG [regs APB_ACCESS_WS_REG] set MUX_CONF_REG [regs MUX_CONF_REG] set SYSCONF_REG [regs SYSCONF_REG] set GPIO_ARM_ID_REG [regs GPIO_ARM_ID_REG] set GPIO_BOOTSTRAP_REG [regs GPIO_BOOTSTRAP_REG] set GPIO_LOCK_REG [regs GPIO_LOCK_REG] set GPIO_IOCTRL_REG [regs GPIO_IOCTRL_REG] set GPIO_DEVID_REG [regs GPIO_DEVID_REG] echo [format "GPIO_OUTPUT_REG (0x%x): 0x%x" $GPIO_OUTPUT_REG [mrw $GPIO_OUTPUT_REG]] echo [format "GPIO_OE_REG (0x%x): 0x%x" $GPIO_OE_REG [mrw $GPIO_OE_REG]] echo [format "GPIO_HI_INT_ENABLE_REG(0x%x): 0x%x" $GPIO_HI_INT_ENABLE_REG [mrw $GPIO_HI_INT_ENABLE_REG]] echo [format "GPIO_LO_INT_ENABLE_REG(0x%x): 0x%x" $GPIO_LO_INT_ENABLE_REG [mrw $GPIO_LO_INT_ENABLE_REG]] echo [format "GPIO_INPUT_REG (0x%x): 0x%x" $GPIO_INPUT_REG [mrw $GPIO_INPUT_REG]] echo [format "APB_ACCESS_WS_REG (0x%x): 0x%x" $APB_ACCESS_WS_REG [mrw $APB_ACCESS_WS_REG]] echo [format "MUX_CONF_REG (0x%x): 0x%x" $MUX_CONF_REG [mrw $MUX_CONF_REG]] echo [format "SYSCONF_REG (0x%x): 0x%x" $SYSCONF_REG [mrw $SYSCONF_REG]] echo [format "GPIO_ARM_ID_REG (0x%x): 0x%x" $GPIO_ARM_ID_REG [mrw $GPIO_ARM_ID_REG]] echo [format "GPIO_BOOTSTRAP_REG (0x%x): 0x%x" $GPIO_BOOTSTRAP_REG [mrw $GPIO_BOOTSTRAP_REG]] echo [format "GPIO_LOCK_REG (0x%x): 0x%x" $GPIO_LOCK_REG [mrw $GPIO_LOCK_REG]] echo [format "GPIO_IOCTRL_REG (0x%x): 0x%x" $GPIO_IOCTRL_REG [mrw $GPIO_IOCTRL_REG]] echo [format "GPIO_DEVID_REG (0x%x): 0x%x" $GPIO_DEVID_REG [mrw $GPIO_DEVID_REG]] } # converted from u-boot/cpu/arm1136/comcerto/bsp100.c (HAL_get_amba_clk()) proc showAmbaClk {} { set CFG_REFCLKFREQ [config CFG_REFCLKFREQ] set CLKCORE_AHB_CLK_CNTRL [regs CLKCORE_AHB_CLK_CNTRL] set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] echo [format "CLKCORE_AHB_CLK_CNTRL (0x%x): 0x%x" $CLKCORE_AHB_CLK_CNTRL [mrw $CLKCORE_AHB_CLK_CNTRL]] mem2array value 32 $CLKCORE_AHB_CLK_CNTRL 1 # see if the PLL is in bypass mode set bypass [expr ($value(0) & $PLL_CLK_BYPASS) >> 24 ] echo [format "PLL bypass bit: %d" $bypass] if {$bypass == 1} { echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr $CFG_REFCLKFREQ/1000000]] } else { # nope, extract x,y,w and compute the PLL output freq. set x [expr ($value(0) & 0x0001F0000) >> 16] echo [format "x: %d" $x] set y [expr ($value(0) & 0x00000007F)] echo [format "y: %d" $y] set w [expr ($value(0) & 0x000000300) >> 8] echo [format "w: %d" $w] echo [format "Amba PLL Clk: %d (MHz)" [expr ($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000]] } } # converted from u-boot/cpu/arm1136/comcerto/bsp100.c (HAL_set_amba_clk()) # this clock is useb by all peripherals (DDR2, ethernet, ebus, etc) proc setupAmbaClk {} { set CLKCORE_PLL_STATUS [regs CLKCORE_PLL_STATUS] set CLKCORE_AHB_CLK_CNTRL [regs CLKCORE_AHB_CLK_CNTRL] set ARM_PLL_BY_CTRL [regs ARM_PLL_BY_CTRL] set ARM_AHB_BYP [regs ARM_AHB_BYP] set PLL_DISABLE [regs PLL_DISABLE] set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] set AHB_PLL_BY_CTRL [regs AHB_PLL_BY_CTRL] set DIV_BYPASS [regs DIV_BYPASS] set AHBCLK_PLL_LOCK [regs AHBCLK_PLL_LOCK] set CFG_REFCLKFREQ [config CFG_REFCLKFREQ] set CONFIG_SYS_HZ_CLOCK [config CONFIG_SYS_HZ_CLOCK] set w [config w_amba] set x [config x_amba] set y [config y_amba] echo [format "Setting Amba PLL to lock to %d MHz" [expr $CONFIG_SYS_HZ_CLOCK/1000000]] #echo [format "setupAmbaClk: w= %d" $w] #echo [format "setupAmbaClk: x= %d" $x] #echo [format "setupAmbaClk: y= %d" $y] # set PLL into BYPASS mode using MUX mmw $CLKCORE_AHB_CLK_CNTRL $PLL_CLK_BYPASS 0x0 # do an internal PLL bypass mmw $CLKCORE_AHB_CLK_CNTRL $AHB_PLL_BY_CTRL 0x0 # wait 500us (ARM running @24Mhz -> 12000 cycles => 500us) # openocd smallest resolution is 1ms so, wait 1ms sleep 1 # disable the PLL mmw $CLKCORE_AHB_CLK_CNTRL $PLL_DISABLE 0x0 # wait 1ms sleep 1 # enable the PLL mmw $CLKCORE_AHB_CLK_CNTRL 0x0 $PLL_DISABLE sleep 1 # set X, W and X mmw $CLKCORE_AHB_CLK_CNTRL 0x0 0xFFFFFF mmw $CLKCORE_AHB_CLK_CNTRL [expr (($x << 16) + ($w << 8) + $y)] 0x0 # wait for PLL to lock echo "Wating for Amba PLL to lock" while {[expr [mrw $CLKCORE_PLL_STATUS] & $AHBCLK_PLL_LOCK] == 0} { sleep 1 } # remove the internal PLL bypass mmw $CLKCORE_AHB_CLK_CNTRL 0x0 $AHB_PLL_BY_CTRL # remove PLL from BYPASS mode using MUX mmw $CLKCORE_AHB_CLK_CNTRL 0x0 $PLL_CLK_BYPASS } # converted from u-boot/cpu/arm1136/comcerto/bsp100.c (HAL_get_arm_clk()) proc showArmClk {} { set CFG_REFCLKFREQ [config CFG_REFCLKFREQ] set CLKCORE_ARM_CLK_CNTRL [regs CLKCORE_ARM_CLK_CNTRL] set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] echo [format "CLKCORE_ARM_CLK_CNTRL (0x%x): 0x%x" $CLKCORE_ARM_CLK_CNTRL [mrw $CLKCORE_ARM_CLK_CNTRL]] mem2array value 32 $CLKCORE_ARM_CLK_CNTRL 1 # see if the PLL is in bypass mode set bypass [expr ($value(0) & $PLL_CLK_BYPASS) >> 24 ] echo [format "PLL bypass bit: %d" $bypass] if {$bypass == 1} { echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr $CFG_REFCLKFREQ/1000000]] } else { # nope, extract x,y,w and compute the PLL output freq. set x [expr ($value(0) & 0x0001F0000) >> 16] echo [format "x: %d" $x] set y [expr ($value(0) & 0x00000007F)] echo [format "y: %d" $y] set w [expr ($value(0) & 0x000000300) >> 8] echo [format "w: %d" $w] echo [format "Arm PLL Clk: %d (MHz)" [expr ($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000]] } } # converted from u-boot/cpu/arm1136/comcerto/bsp100.c (HAL_set_arm_clk()) # Arm Clock is used by two ARM1136 cores proc setupArmClk {} { set CLKCORE_PLL_STATUS [regs CLKCORE_PLL_STATUS] set CLKCORE_ARM_CLK_CNTRL [regs CLKCORE_ARM_CLK_CNTRL] set ARM_PLL_BY_CTRL [regs ARM_PLL_BY_CTRL] set ARM_AHB_BYP [regs ARM_AHB_BYP] set PLL_DISABLE [regs PLL_DISABLE] set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] set AHB_PLL_BY_CTRL [regs AHB_PLL_BY_CTRL] set DIV_BYPASS [regs DIV_BYPASS] set FCLK_PLL_LOCK [regs FCLK_PLL_LOCK] set CFG_REFCLKFREQ [config CFG_REFCLKFREQ] set CFG_ARM_CLOCK [config CFG_ARM_CLOCK] set w [config w_arm] set x [config x_arm] set y [config y_arm] echo [format "Setting Arm PLL to lock to %d MHz" [expr $CFG_ARM_CLOCK/1000000]] #echo [format "setupArmClk: w= %d" $w] #echo [format "setupArmaClk: x= %d" $x] #echo [format "setupArmaClk: y= %d" $y] # set PLL into BYPASS mode using MUX mmw $CLKCORE_ARM_CLK_CNTRL $PLL_CLK_BYPASS 0x0 # do an internal PLL bypass mmw $CLKCORE_ARM_CLK_CNTRL $ARM_PLL_BY_CTRL 0x0 # wait 500us (ARM running @24Mhz -> 12000 cycles => 500us) # openocd smallest resolution is 1ms so, wait 1ms sleep 1 # disable the PLL mmw $CLKCORE_ARM_CLK_CNTRL $PLL_DISABLE 0x0 # wait 1ms sleep 1 # enable the PLL mmw $CLKCORE_ARM_CLK_CNTRL 0x0 $PLL_DISABLE sleep 1 # set X, W and X mmw $CLKCORE_ARM_CLK_CNTRL 0x0 0xFFFFFF mmw $CLKCORE_ARM_CLK_CNTRL [expr (($x << 16) + ($w << 8) + $y)] 0x0 # wait for PLL to lock echo "Wating for Amba PLL to lock" while {[expr [mrw $CLKCORE_PLL_STATUS] & $FCLK_PLL_LOCK] == 0} { sleep 1 } # remove the internal PLL bypass mmw $CLKCORE_ARM_CLK_CNTRL 0x0 $ARM_PLL_BY_CTRL # remove PLL from BYPASS mode using MUX mmw $CLKCORE_ARM_CLK_CNTRL 0x0 $PLL_CLK_BYPASS } proc setupPLL {} { echo "PLLs setup" setupAmbaClk setupArmClk } # converted from u-boot/cpu/arm1136/bsp100.c:SoC_mem_init() proc setupDDR2 {} { echo "Configuring DDR2" set MEMORY_BASE_ADDR [regs MEMORY_BASE_ADDR] set MEMORY_MAX_ADDR [regs MEMORY_MAX_ADDR] set MEMORY_CR [regs MEMORY_CR] set BLOCK_RESET_REG [regs BLOCK_RESET_REG] set DDR_RST [regs DDR_RST] # put DDR controller in reset (so that it is reset and correctly configured) # this is only necessary if DDR was previously confiured # and not reset. mmw $BLOCK_RESET_REG 0x0 $DDR_RST set M [expr 1024 * 1024] set DDR_SZ_1024M [expr 1024 * $M] set DDR_SZ_256M [expr 256 * $M] set DDR_SZ_128M [expr 128 * $M] set DDR_SZ_64M [expr 64 * $M] # ooma_board_detect returns DDR2 memory size set tmp [ooma_board_detect] if {$tmp == "128M"} { echo "DDR2 size 128MB" set ddr_size $DDR_SZ_128M } elseif {$tmp == "256M"} { echo "DDR2 size 256MB" set ddr_size $DDR_SZ_256M } else { echo "Don't know how to handle this DDR2 size?" } # Memory setup register mww $MEMORY_MAX_ADDR [expr ($ddr_size - 1) + $MEMORY_BASE_ADDR] # disbale ROM remap mww $MEMORY_CR 0x0 # Take DDR controller out of reset mmw $BLOCK_RESET_REG $DDR_RST 0x0 # min. 20 ops delay sleep 1 # This will setup Denali DDR2 controller if {$tmp == "128M"} { configureDDR2regs_128M } elseif {$tmp == "256M"} { configureDDR2regs_256M } else { echo "Don't know how to configure DDR2 setup?" } } proc showDDR2 {} { set DENALI_CTL_00_DATA [regs DENALI_CTL_00_DATA] set DENALI_CTL_01_DATA [regs DENALI_CTL_01_DATA] set DENALI_CTL_02_DATA [regs DENALI_CTL_02_DATA] set DENALI_CTL_03_DATA [regs DENALI_CTL_03_DATA] set DENALI_CTL_04_DATA [regs DENALI_CTL_04_DATA] set DENALI_CTL_05_DATA [regs DENALI_CTL_05_DATA] set DENALI_CTL_06_DATA [regs DENALI_CTL_06_DATA] set DENALI_CTL_07_DATA [regs DENALI_CTL_07_DATA] set DENALI_CTL_08_DATA [regs DENALI_CTL_08_DATA] set DENALI_CTL_09_DATA [regs DENALI_CTL_09_DATA] set DENALI_CTL_10_DATA [regs DENALI_CTL_10_DATA] set DENALI_CTL_11_DATA [regs DENALI_CTL_11_DATA] set DENALI_CTL_12_DATA [regs DENALI_CTL_12_DATA] set DENALI_CTL_13_DATA [regs DENALI_CTL_13_DATA] set DENALI_CTL_14_DATA [regs DENALI_CTL_14_DATA] set DENALI_CTL_15_DATA [regs DENALI_CTL_15_DATA] set DENALI_CTL_16_DATA [regs DENALI_CTL_16_DATA] set DENALI_CTL_17_DATA [regs DENALI_CTL_17_DATA] set DENALI_CTL_18_DATA [regs DENALI_CTL_18_DATA] set DENALI_CTL_19_DATA [regs DENALI_CTL_19_DATA] set DENALI_CTL_20_DATA [regs DENALI_CTL_20_DATA] set tmp [mr64bit $DENALI_CTL_00_DATA] echo [format "DENALI_CTL_00_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_00_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_01_DATA] echo [format "DENALI_CTL_01_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_01_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_02_DATA] echo [format "DENALI_CTL_02_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_02_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_03_DATA] echo [format "DENALI_CTL_03_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_03_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_04_DATA] echo [format "DENALI_CTL_04_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_04_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_05_DATA] echo [format "DENALI_CTL_05_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_05_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_06_DATA] echo [format "DENALI_CTL_06_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_06_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_07_DATA] echo [format "DENALI_CTL_07_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_07_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_08_DATA] echo [format "DENALI_CTL_08_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_08_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_09_DATA] echo [format "DENALI_CTL_09_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_09_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_10_DATA] echo [format "DENALI_CTL_10_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_10_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_11_DATA] echo [format "DENALI_CTL_11_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_11_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_12_DATA] echo [format "DENALI_CTL_12_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_12_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_13_DATA] echo [format "DENALI_CTL_13_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_13_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_14_DATA] echo [format "DENALI_CTL_14_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_14_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_15_DATA] echo [format "DENALI_CTL_15_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_15_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_16_DATA] echo [format "DENALI_CTL_16_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_16_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_17_DATA] echo [format "DENALI_CTL_17_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_17_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_18_DATA] echo [format "DENALI_CTL_18_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_18_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_19_DATA] echo [format "DENALI_CTL_19_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_19_DATA $tmp(1) $tmp(0)] set tmp [mr64bit $DENALI_CTL_20_DATA] echo [format "DENALI_CTL_20_DATA (0x%x): 0x%08x%08x" $DENALI_CTL_20_DATA $tmp(1) $tmp(0)] } proc initC100 {} { # this follows u-boot/cpu/arm1136/start.S set GPIO_LOCK_REG [regs GPIO_LOCK_REG] set GPIO_IOCTRL_REG [regs GPIO_IOCTRL_REG] set GPIO_IOCTRL_VAL [regs GPIO_IOCTRL_VAL] set APB_ACCESS_WS_REG [regs APB_ACCESS_WS_REG] set ASA_ARAM_BASEADDR [regs ASA_ARAM_BASEADDR] set ASA_ARAM_TC_CR_REG [regs ASA_ARAM_TC_CR_REG] set ASA_EBUS_BASEADDR [regs ASA_EBUS_BASEADDR] set ASA_EBUS_TC_CR_REG [regs ASA_EBUS_TC_CR_REG] set ASA_TC_REQIDMAEN [regs ASA_TC_REQIDMAEN] set ASA_TC_REQTDMEN [regs ASA_TC_REQTDMEN] set ASA_TC_REQIPSECUSBEN [regs ASA_TC_REQIPSECUSBEN] set ASA_TC_REQARM0EN [regs ASA_TC_REQARM0EN] set ASA_TC_REQARM1EN [regs ASA_TC_REQARM1EN] set ASA_TC_REQMDMAEN [regs ASA_TC_REQMDMAEN] set INTC_ARM1_CONTROL_REG [regs INTC_ARM1_CONTROL_REG] # unlock writing to IOCTRL register mww $GPIO_LOCK_REG $GPIO_IOCTRL_VAL # enable address lines A15-A21 mmw $GPIO_IOCTRL_REG 0xf 0x0 # set ARM into supervisor mode (SVC32) # disable IRQ, FIQ # Do I need this in JTAG mode? # it really should be done as 'and ~0x1f | 0xd3 but # openocd does not support this yet reg cpsr 0xd3 # /* # * flush v4 I/D caches # */ # mov r0, #0 # mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ arm mcr 15 0 7 7 0 0x0 # mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ arm mcr 15 0 8 7 0 0x0 # /* # * disable MMU stuff and caches # */ # mrc p15, 0, r0, c1, c0, 0 arm mrc 15 0 1 0 0 # bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) # bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) # orr r0, r0, #0x00000002 @ set bit 2 (A) Align # orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache # orr r0, r0, #0x00400000 @ set bit 22 (U) # mcr p15, 0, r0, c1, c0, 0 arm mcr 15 0 1 0 0 0x401002 # This is from bsp_init() in u-boot/boards/mindspeed/ooma-darwin/board.c # APB init # // Setting APB Bus Wait states to 1, set post write # (*(volatile u32*)(APB_ACCESS_WS_REG)) = 0x40; mww [expr $APB_ACCESS_WS_REG] 0x40 # AHB init # // enable all 6 masters for ARAM mmw $ASA_ARAM_TC_CR_REG [expr $ASA_TC_REQIDMAEN | $ASA_TC_REQTDMEN | $ASA_TC_REQIPSECUSBEN | $ASA_TC_REQARM0EN | $ASA_TC_REQARM1EN | $ASA_TC_REQMDMAEN] 0x0 # // enable all 6 masters for EBUS mmw $ASA_EBUS_TC_CR_REG [expr $ASA_TC_REQIDMAEN | $ASA_TC_REQTDMEN | $ASA_TC_REQIPSECUSBEN | $ASA_TC_REQARM0EN | $ASA_TC_REQARM1EN | $ASA_TC_REQMDMAEN] 0x0 # ARAM init # // disable pipeline mode in ARAM # I don't think this is documented anywhere? mww $INTC_ARM1_CONTROL_REG 0x1 # configure clocks setupPLL # setupUART0 must be run before setupDDR2 as setupDDR2 uses UART. setupUART0 # enable cache # ? (u-boot does nothing here) # DDR2 memory init setupDDR2 putsUART0 "C100 initialization complete.\n" echo "C100 initialization complete." } # show current state of watchdog timer proc showWatchdog {} { set TIMER_WDT_HIGH_BOUND [regs TIMER_WDT_HIGH_BOUND] set TIMER_WDT_CONTROL [regs TIMER_WDT_CONTROL] set TIMER_WDT_CURRENT_COUNT [regs TIMER_WDT_CURRENT_COUNT] echo [format "TIMER_WDT_HIGH_BOUND (0x%x): 0x%x" $TIMER_WDT_HIGH_BOUND [mrw $TIMER_WDT_HIGH_BOUND]] echo [format "TIMER_WDT_CONTROL (0x%x): 0x%x" $TIMER_WDT_CONTROL [mrw $TIMER_WDT_CONTROL]] echo [format "TIMER_WDT_CURRENT_COUNT (0x%x): 0x%x" $TIMER_WDT_CURRENT_COUNT [mrw $TIMER_WDT_CURRENT_COUNT]] } # converted from u-boot/cpu/arm1136/comcerto/intrrupts.c:void reset_cpu (ulong ignored) # this will trigger watchdog reset # the sw. reset does not work on C100 # watchdog reset effectively works as hw. reset proc reboot {} { set TIMER_WDT_HIGH_BOUND [regs TIMER_WDT_HIGH_BOUND] set TIMER_WDT_CONTROL [regs TIMER_WDT_CONTROL] set TIMER_WDT_CURRENT_COUNT [regs TIMER_WDT_CURRENT_COUNT] # allow the counter to count to high value before triggering # this is because regsiter writes are slow over JTAG and # I don't want to miss the high_bound==curr_count condition mww $TIMER_WDT_HIGH_BOUND 0xffffff mww $TIMER_WDT_CURRENT_COUNT 0x0 echo "JTAG speed lowered to 100kHz" adapter_khz 100 mww $TIMER_WDT_CONTROL 0x1 # wait until the reset echo -n "Wating for watchdog to trigger..." #while {[mrw $TIMER_WDT_CONTROL] == 1} { # echo [format "TIMER_WDT_CURRENT_COUNT (0x%x): 0x%x" $TIMER_WDT_CURRENT_COUNT [mrw $TIMER_WDT_CURRENT_COUNT]] # sleep 1 # #} while {[c100.cpu curstate] != "running"} { sleep 1} echo "done." echo [format "Note that C100 is in %s state, type halt to stop" [c100.cpu curstate]] } openocd-0.9.0/tcl/target/ar71xx.cfg0000644000175000017500000000373712526202243013763 00000000000000# Atheros AR71xx MIPS 24Kc SoC. # tested on PB44 refererence board adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst set CHIPNAME ar71xx jtag newtap $CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id 1 set TARGETNAME $CHIPNAME.cpu target create $TARGETNAME mips_m4k -endian big -chain-position $TARGETNAME $TARGETNAME configure -event reset-halt-post { #setup PLL to lowest common denominator 300/300/150 setting mww 0xb8050000 0x000f40a3 ;# reset val + CPU:3 DDR:3 AHB:0 mww 0xb8050000 0x800f40a3 ;# send to PLL #next command will reset for PLL changes to take effect mww 0xb8050008 3 ;# set reset_switch and clock_switch (resets SoC) } $TARGETNAME configure -event reset-init { #complete pll initialization mww 0xb8050000 0x800f0080 ;# set sw_update bit mww 0xb8050008 0 ;# clear reset_switch bit mww 0xb8050000 0x800f00e8 ;# clr pwrdwn & bypass mww 0xb8050008 1 ;# set clock_switch bit sleep 1 ;# wait for lock # Setup DDR config and flash mapping mww 0xb8000000 0xefbc8cd0 ;# DDR cfg cdl val (rst: 0x5bfc8d0) mww 0xb8000004 0x8e7156a2 ;# DDR cfg2 cdl val (rst: 0x80d106a8) mww 0xb8000010 8 ;# force precharge all banks mww 0xb8000010 1 ;# force EMRS update cycle mww 0xb800000c 0 ;# clr ext. mode register mww 0xb8000010 2 ;# force auto refresh all banks mww 0xb8000010 8 ;# force precharge all banks mww 0xb8000008 0x31 ;# set DDR mode value CAS=3 mww 0xb8000010 1 ;# force EMRS update cycle mww 0xb8000014 0x461b ;# DDR refresh value mww 0xb8000018 0xffff ;# DDR Read Data This Cycle value (16bit: 0xffff) mww 0xb800001c 0x7 ;# delay added to the DQS line (normal = 7) mww 0xb8000020 0 mww 0xb8000024 0 mww 0xb8000028 0 } # setup working area somewhere in RAM $TARGETNAME configure -work-area-phys 0xa0600000 -work-area-size 0x20000 # serial SPI capable flash # flash bank openocd-0.9.0/tcl/target/nrf51_stlink.tcl0000644000175000017500000000017012526202243015157 00000000000000echo "WARNING: target/nrf51_stlink.cfg is deprecated, please switch to target/nrf51.cfg" source [find target/nrf51.cfg] openocd-0.9.0/tcl/target/lpc2124.cfg0000644000175000017500000000164212526202243013711 00000000000000# NXP LPC2124 ARM7TDMI-S with 256kB flash and 16kB SRAM, clocked with 12MHz crystal source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2124 {core_freq_khz adapter_freq_khz} { # 256kB flash and 16kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2124 0x4f1f0f0f 0x40000 lpc2000_v1 0x4000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 12MHz crystal echo "Warning - assuming default core clock 12MHz! Flashing may fail if actual core clock is different." # setup_lpc2124 setup_lpc2124 12000 1500 } openocd-0.9.0/tcl/target/smp8634.cfg0000644000175000017500000000123212526202243013741 00000000000000# script for Sigma Designs SMP8634 (eventually even SMP8635) if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME smp8634 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x08630001 } adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst separate # jtag scan chain # format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian $_ENDIAN openocd-0.9.0/tcl/target/efm32.cfg0000644000175000017500000000162412526202243013536 00000000000000# # efm32 target # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME efm32 } # Work-area is a space in RAM used for flash programming # By default use 2kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x800 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x2ba01477 } swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID adapter_khz 1000 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/lpc2129.cfg0000644000175000017500000000164212526202243013716 00000000000000# NXP LPC2129 ARM7TDMI-S with 256kB flash and 16kB SRAM, clocked with 12MHz crystal source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2129 {core_freq_khz adapter_freq_khz} { # 256kB flash and 16kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2129 0xcf1f0f0f 0x40000 lpc2000_v1 0x4000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 12MHz crystal echo "Warning - assuming default core clock 12MHz! Flashing may fail if actual core clock is different." # setup_lpc2129 setup_lpc2129 12000 1500 } openocd-0.9.0/tcl/target/ti_tms570ls20xxx.cfg0000644000175000017500000000026212526202243015623 00000000000000# TMS570LS20216, TMS570LS20206, TMS570LS10216 # TMS570LS10206, TMS570LS10116, TMS570LS10106 set DAP_TAPID 0x0B7B302F set JRC_TAPID 0x0B7B302F source [find target/ti_tms570.cfg] openocd-0.9.0/tcl/target/ti_rm4x.cfg0000644000175000017500000000004312526202243014202 00000000000000source [find target/ti_tms570.cfg] openocd-0.9.0/tcl/target/stellaris_icdi.cfg0000644000175000017500000000020212526202243015603 00000000000000echo "WARNING: target/stellaris_icdi.cfg is deprecated, please switch to target/stellaris.cfg" source [find target/stellaris.cfg] openocd-0.9.0/tcl/target/lpc2148.cfg0000644000175000017500000000173312526202243013720 00000000000000# NXP LPC2148 ARM7TDMI-S with 512kB flash (12kB used by bootloader) and 40kB SRAM (8kB for USB DMA), clocked with 12MHz crystal source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2148 {core_freq_khz adapter_freq_khz} { # 500kB flash and 32kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2148 "0x3f0f0f0f 0x4f1f0f0f" 0x7d000 lpc2000_v2 0x8000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 12MHz crystal echo "Warning - assuming default core clock 12MHz! Flashing may fail if actual core clock is different." # setup_lpc2148 setup_lpc2148 12000 1500 } openocd-0.9.0/tcl/target/bcm4706.cfg0000644000175000017500000000036212526202243013702 00000000000000set _CHIPNAME bcm4706 set _CPUID 0x1008c17f jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian little -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/imx21.cfg0000644000175000017500000000135312526202243013561 00000000000000#use combined on interfaces or targets that can't set TRST/SRST separately # # Hmmm.... should srst_pulls_trst be used here like i.MX27??? reset_config trst_and_srst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx21 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Note above there is 1 tap # The CPU tap if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0792611f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the GDB Target. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/bcm4718.cfg0000644000175000017500000000014612526202243013705 00000000000000set _CHIPNAME bcm4718 set _LVTAPID 0x1471617f set _CPUID 0x0008c17f source [find target/bcm47xx.cfg] openocd-0.9.0/tcl/target/imx25.cfg0000644000175000017500000000175312526202243013571 00000000000000# # imx25 config # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx25 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x1b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0x0f -expected-id $_ETBTAPID if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926041 } jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0x0 -irmask 0x0 -expected-id 0x0 if { [info exists SDMATAPID] } { set _SDMATAPID $SDMATAPID } else { set _SDMATAPID 0x0882301d } jtag newtap $_CHIPNAME sdma -irlen 5 -expected-id $_SDMATAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN \ -chain-position $_TARGETNAME # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/imx27.cfg0000644000175000017500000000256512526202243013575 00000000000000# page 3-34 of "MCIMC27 Multimedia Applications Processor Reference Manual, Rev 0.3" # SRST pulls TRST # # Without setting these options correctly you'll see all sorts # of weird errors, e.g. MOE=0xe, invalid cpsr values, reset # failing, etc. reset_config trst_and_srst srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx27 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Note above there are 2 taps # trace buffer if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x1b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETBTAPID # The CPU tap if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926121 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the GDB Target. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME # REVISIT what operating environment sets up this virtual address mapping? $_TARGETNAME configure -work-area-virt 0xffff4c00 -work-area-phys 0xffff4c00 \ -work-area-size 0x8000 -work-area-backup 1 # Internal to the chip, there is 45K of SRAM # arm7_9 dcc_downloads enable # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/imx28.cfg0000644000175000017500000000135112526202243013566 00000000000000# i.MX28 config file. # based off of the imx21.cfg file. reset_config trst_and_srst #jtag nTRST and nSRST delay adapter_nsrst_delay 100 jtag_ntrst_delay 100 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx28 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Note above there is 1 tap # The CPU tap if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x079264f3 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the GDB Target. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/lpc40xx.cfg0000644000175000017500000000027712526202243014127 00000000000000# NXP LPC40xx Cortex-M4F with at least 16kB SRAM set CHIPNAME lpc40xx set CHIPSERIES lpc4000 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x4000 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/imx31.cfg0000644000175000017500000000343312526202243013563 00000000000000# imx31 config # reset_config trst_and_srst srst_gates_jtag adapter_nsrst_delay 5 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx31 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07b3601d } if { [info exists SDMATAPID] } { set _SDMATAPID $SDMATAPID } else { set _SDMATAPID 0x2190101d } if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x2b900f0f } #======================================== jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETBTAPID # The "SDMA" - mart controller debug tap # Based on some IO pins - this can be disabled & removed # See diagram: 6-14 # SIGNAL NAME: # SJC_MOD - controls multiplexer - disables ARM1136 # SDMA_BYPASS - disables SDMA - # # Per ARM: DDI0211J_arm1136_r1p5_trm.pdf - the ARM 1136 as a 5 bit IR register jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID # No IDCODE for this TAP jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0 -irmask 0xf -expected-id 0x0 # Per section 40.17.1, table 40-85 the IR register is 4 bits # But this conflicts with Diagram 6-13, "3bits ir and drs" jtag newtap $_CHIPNAME smda -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_SDMATAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME proc power_restore {} { echo "Sensed power restore. No action." } proc srst_deasserted {} { echo "Sensed nSRST deasserted. No action." } # trace setup ... NOTE, "normal full" mode fudges the real ETMv3.1 mode etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/at91rm9200.cfg0000644000175000017500000000273512526202243014256 00000000000000# Atmel AT91rm9200 # http://atmel.com/products/at91/ if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91rm9200 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x05b0203f } # Never allow the following! if { $_CPUTAPID == 0x15b0203f } { echo "-------------------------------------------------------" echo "- ERROR: -" echo "- ERROR: TapID 0x15b0203f is wrong for at91rm9200 -" echo "- ERROR: The chip/board has a JTAG select pin/jumper -" echo "- ERROR: -" echo "- ERROR: In one position (0x05b0203f) it selects the -" echo "- ERROR: ARM CPU, in the other position (0x1b0203f) -" echo "- ERROR: it selects boundry-scan not the ARM -" echo "- ERROR: -" echo "-------------------------------------------------------" } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the GDB Target. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME # AT91RM9200 has a 16K block of sram @ 0x0020.0000 $_TARGETNAME configure -work-area-phys 0x00200000 \ -work-area-size 0x4000 -work-area-backup 1 # This chip has a DCC ... use it arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/imx35.cfg0000644000175000017500000000254112526202243013566 00000000000000# imx35 config # reset_config trst_and_srst srst_gates_jtag jtag_ntrst_delay 100 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx35 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07b3601d } if { [info exists SDMATAPID] } { set _SDMATAPID $SDMATAPID } else { set _SDMATAPID 0x0882601d } if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x2b900f0f } #======================================== jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETBTAPID jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID # No IDCODE for this TAP jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0 -irmask 0x0 -expected-id 0x0 jtag newtap $_CHIPNAME smda -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_SDMATAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME proc power_restore {} { echo "Sensed power restore. No action." } proc srst_deasserted {} { echo "Sensed nSRST deasserted. No action." } # trace setup ... NOTE, "normal full" mode fudges the real ETMv3.1 mode etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/bcm47xx.cfg0000644000175000017500000000151512526202243014115 00000000000000echo "Forcing reset_config to none to prevent OpenOCD from pulling SRST after the switch from LV is already performed" reset_config none jtag newtap $_CHIPNAME-lv tap -irlen 32 -ircapture 0x1 -irmask 0x1f -expected-id $_LVTAPID -expected-id $_CPUID jtag configure $_CHIPNAME-lv.tap -event setup "jtag tapenable $_CHIPNAME.cpu" jtag configure $_CHIPNAME-lv.tap -event tap-disable {} jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUID -disable jtag configure $_CHIPNAME.cpu -event tap-enable "switch_lv_to_ejtag" set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian little -chain-position $_TARGETNAME proc switch_lv_to_ejtag {} { global _CHIPNAME poll 0 irscan $_CHIPNAME-lv.tap 0x143ff3a drscan $_CHIPNAME-lv.tap 32 1 jtag tapdisable $_CHIPNAME-lv.tap poll 1 } openocd-0.9.0/tcl/target/am335x.cfg0000644000175000017500000000267212526202243013646 00000000000000source [find target/icepick.cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME am335x } # # M3 DAP # if { [info exists M3_DAP_TAPID] } { set _M3_DAP_TAPID $M3_DAP_TAPID } else { set _M3_DAP_TAPID 0x4b6b902f } jtag newtap $_CHIPNAME m3_dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_M3_DAP_TAPID -disable jtag configure $_CHIPNAME.m3_dap -event tap-enable "icepick_d_tapenable $_CHIPNAME.jrc 11 0" # # Main DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x4b6b902f } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable "icepick_d_tapenable $_CHIPNAME.jrc 12 0" # # ICEpick-D (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b94402f } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.jrc -event post-reset "runtest 100" # # Cortex A8 target # set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -dbgbase 0x80001000 # SRAM: 64K at 0x4030.0000; use the first 16K $_TARGETNAME configure -work-area-phys 0x40300000 -work-area-size 0x4000 openocd-0.9.0/tcl/target/klx.cfg0000644000175000017500000000325012526202243013415 00000000000000# # Freescale Kinetis KL series devices # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME klx } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0bc11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu # It is important that "kinetis mdm check_security" is called for # 'examine-end' event and not 'eximine-start'. Calling it in 'examine-start' # causes "kinetis mdm check_security" to fail the first time openocd # calls it when it tries to connect after the CPU has been power-cycled. $_CHIPNAME.cpu configure -event examine-end { kinetis mdm check_security } $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME # Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual # specifies up to 1MHz for VLPR mode. adapter_khz 1000 reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } $_TARGETNAME configure -event reset-init { # Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual # specifies up to 24MHz for run mode; Table 17 of Sub-Family Data # Sheet rev4 lists 25MHz as the maximum frequency. adapter_khz 24000 } openocd-0.9.0/tcl/target/imx51.cfg0000644000175000017500000000226512526202243013567 00000000000000# Freescale i.MX51 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx51 } # CoreSight Debug Access Port if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x1ba00477 } jtag newtap $_CHIPNAME DAP -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_DAP_TAPID # SDMA / no IDCODE jtag newtap $_CHIPNAME SDMA -irlen 4 -ircapture 0x0 -irmask 0xf # SJC if { [info exists SJC_TAPID] } { set _SJC_TAPID SJC_TAPID } else { set _SJC_TAPID 0x0190c01d } jtag newtap $_CHIPNAME SJC -irlen 5 -ircapture 0x1 -irmask 0x1f \ -expected-id $_SJC_TAPID -ignore-version # GDB target: Cortex-A8, using DAP set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.DAP # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.SJC -event post-reset "runtest 100" # have the DAP "always" be active jtag configure $_CHIPNAME.SJC -event setup "jtag tapenable $_CHIPNAME.DAP" proc imx51_dbginit {target} { # General Cortex A8 debug initialisation cortex_a dbginit } $_TARGETNAME configure -event reset-assert-post "imx51_dbginit $_TARGETNAME" openocd-0.9.0/tcl/target/imx53.cfg0000644000175000017500000000226512526202243013571 00000000000000# Freescale i.MX53 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx53 } # CoreSight Debug Access Port if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x1ba00477 } jtag newtap $_CHIPNAME DAP -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_DAP_TAPID # SDMA / no IDCODE jtag newtap $_CHIPNAME SDMA -irlen 4 -ircapture 0x0 -irmask 0xf # SJC if { [info exists SJC_TAPID] } { set _SJC_TAPID SJC_TAPID } else { set _SJC_TAPID 0x0190d01d } jtag newtap $_CHIPNAME SJC -irlen 5 -ircapture 0x1 -irmask 0x1f \ -expected-id $_SJC_TAPID -ignore-version # GDB target: Cortex-A8, using DAP set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.DAP # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.SJC -event post-reset "runtest 100" # have the DAP "always" be active jtag configure $_CHIPNAME.SJC -event setup "jtag tapenable $_CHIPNAME.DAP" proc imx53_dbginit {target} { # General Cortex A8 debug initialisation cortex_a dbginit } $_TARGETNAME configure -event reset-assert-post "imx53_dbginit $_TARGETNAME" openocd-0.9.0/tcl/target/at91sam3sXX.cfg0000644000175000017500000000045712526202243014632 00000000000000# script for ATMEL sam3, a CORTEX-M3 chip # # at91sam3s4c # at91sam3s4b # at91sam3s4a # at91sam3s2c # at91sam3s2b # at91sam3s2a # at91sam3s1c # at91sam3s1b # at91sam3s1a source [find target/at91sam3XXX.cfg] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam3 0x00400000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/stm32f4x_stlink.cfg0000644000175000017500000000020112526202243015566 00000000000000echo "WARNING: target/stm32f4x_stlink.cfg is deprecated, please switch to target/stm32f4x.cfg" source [find target/stm32f4x.cfg] openocd-0.9.0/tcl/target/stm32f0x_stlink.cfg0000644000175000017500000000020112526202243015562 00000000000000echo "WARNING: target/stm32f0x_stlink.cfg is deprecated, please switch to target/stm32f0x.cfg" source [find target/stm32f0x.cfg] openocd-0.9.0/tcl/target/mc13224v.cfg0000644000175000017500000000304312526202243014000 00000000000000source [find bitsbytes.tcl] source [find cpu/arm/arm7tdmi.tcl] source [find memory.tcl] source [find mmr_helpers.tcl] set CHIP_MAKER freescale set CHIP_FAMILY mc1322x set CHIP_NAME mc13224 set N_RAM 1 set RAM(0,BASE) 0x00400000 set RAM(0,LEN) 0x18000 set RAM(0,HUMAN) "internal SRAM" set RAM(0,TYPE) "ram" set RAM(0,RWX) $RWX_RWX set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY # I AM LAZY... I create 1 region for all MMRs. set N_MMREGS 1 set MMREGS(0,CHIPSELECT) -1 set MMREGS(0,BASE) 0x80000000 set MMREGS(0,LEN) 0x00030000 set MMREGS(0,HUMAN) "mm-regs" set MMREGS(0,TYPE) "mmr" set MMREGS(0,RWX) $RWX_RW set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY set N_XMEM 0 set _CHIPNAME mc13224v set _CPUTAPID 0x1f1f001d jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID reset_config srst_only jtag_ntrst_delay 200 # rclk hasn't been working well. This maybe the mc13224v or something else. #adapter_khz 2000 adapter_khz 2000 ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME # Internal sram memory $_TARGETNAME configure -work-area-phys 0x00408000 \ -work-area-size 0x1000 \ -work-area-backup 1 # flash support is pending (should be straightforward to implement) #flash bank mc1322x 0 0 0 0 $_TARGETNAME openocd-0.9.0/tcl/target/ti_dm355.cfg0000644000175000017500000000660212526202244014155 00000000000000# # Texas Instruments DaVinci family: TMS320DM355 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dm355 } # TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled* # after JTAG reset until ICEpick is used to route them in. set EMU01 "-disable" # With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without # needing any ICEpick interaction. #set EMU01 "-enable" source [find target/icepick.cfg] # # Also note: when running without RTCK before the PLLs are set up, you # may need to slow the JTAG clock down quite a lot (under 2 MHz). # # Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer if { [info exists ETB_TAPID] } { set _ETB_TAPID $ETB_TAPID } else { set _ETB_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETB_TAPID $EMU01 jtag configure $_CHIPNAME.etb -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 1" # Subsidiary TAP: ARM926ejs with scan chains for ARM Debug, EmbeddedICE-RT, ETM. if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x07926001 } jtag newtap $_CHIPNAME arm -irlen 4 -irmask 0xf -expected-id $_CPU_TAPID $EMU01 jtag configure $_CHIPNAME.arm -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 0" # Primary TAP: ICEpick (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b73b02f } jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID jtag configure $_CHIPNAME.jrc -event setup \ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm" ################ # various symbol definitions, to avoid hard-wiring addresses # and enable some sharing of DaVinci-family utility code global dm355 set dm355 [ dict create ] # Physical addresses for controllers and memory # (Some of these are valid for many DaVinci family chips) dict set dm355 sram0 0x00010000 dict set dm355 sram1 0x00014000 dict set dm355 sysbase 0x01c40000 dict set dm355 pllc1 0x01c40800 dict set dm355 pllc2 0x01c40c00 dict set dm355 psc 0x01c41000 dict set dm355 gpio 0x01c67000 dict set dm355 a_emif 0x01e10000 dict set dm355 a_emif_cs0 0x02000000 dict set dm355 a_emif_cs1 0x04000000 dict set dm355 ddr_emif 0x20000000 dict set dm355 ddr 0x80000000 dict set dm355 uart0 0x01c20000 dict set dm355 uart1 0x01c20400 dict set dm355 uart2 0x01e06000 source [find target/davinci.cfg] ################ # GDB target: the ARM, using SRAM1 for scratch. SRAM0 (also 16K) # and the ETB memory (4K) are other options, while trace is unused. set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME # NOTE that work-area-virt presumes a Linux 2.6.30-rc2+ kernel, # and that the work area is used only with a kernel mmu context ... $_TARGETNAME configure \ -work-area-virt [expr 0xfffe0000 + 0x4000] \ -work-area-phys [dict get $dm355 sram1] \ -work-area-size 0x4000 \ -work-area-backup 0 # be absolutely certain the JTAG clock will work with the worst-case # CLKIN = 24 MHz (best case: 36 MHz) even when no bootloader turns # on the PLL and starts using it. OK to speed up after clock setup. adapter_khz 1500 $_TARGETNAME configure -event "reset-start" { adapter_khz 1500 } arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/omap2420.cfg0000644000175000017500000000366112526202244014072 00000000000000# Texas Instruments OMAP 2420 # http://www.ti.com/omap # as seen in Nokia N8x0 tablets if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omap2420 } # NOTE: likes slowish clock on reset (1.5 MBit/s or less) or use RCLK reset_config srst_nogate # Subsidiary TAP: ARM7TDMIr4 plus imaging ... must add via ICEpick (addr 6). jtag newtap $_CHIPNAME iva -irlen 4 -disable # Subsidiary TAP: C55x DSP ... must add via ICEpick (addr 2). jtag newtap $_CHIPNAME dsp -irlen 38 -disable # Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer if { [info exists ETB_TAPID] } { set _ETB_TAPID $ETB_TAPID } else { set _ETB_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -expected-id $_ETB_TAPID # Subsidiary TAP: ARM1136jf-s with scan chains for ARM Debug, EmbeddedICE-RT, ETM. if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x07b3602f } jtag newtap $_CHIPNAME arm -irlen 5 -expected-id $_CPU_TAPID # Primary TAP: ICEpick-B (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x01ce4801 } jtag newtap $_CHIPNAME jrc -irlen 2 -expected-id $_JRC_TAPID # GDB target: the ARM. set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm11 -chain-position $_TARGETNAME # scratch: framebuffer, may be initially unavailable in some chips $_TARGETNAME configure -work-area-phys 0x40210000 $_TARGETNAME configure -work-area-size 0x00081000 $_TARGETNAME configure -work-area-backup 0 # trace setup ... NOTE, "normal full" mode fudges the real ETMv3.1 mode etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb # RM_RSTCTRL_WKUP.RST.GS - Trigger a global software reset, and # give it a chance to finish before we talk to the chip again. set RM_RSTCTRL_WKUP 0x48008450 $_TARGETNAME configure -event reset-assert \ "halt; $_TARGETNAME mww $RM_RSTCTRL_WKUP 2; sleep 200" openocd-0.9.0/tcl/target/avr32.cfg0000644000175000017500000000070712526202244013561 00000000000000set _CHIPNAME avr32 set _ENDIAN big set _CPUTAPID 0x21e8203f adapter_nsrst_delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst separate # jtag scan chain # format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 -expected-id $_CPUTAPID set _TARGETNAME [format "%s.cpu" $_CHIPNAME] target create $_TARGETNAME avr32_ap7k -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/ti_dm365.cfg0000644000175000017500000000622312526202244014155 00000000000000# # Texas Instruments DaVinci family: TMS320DM365 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dm365 } # TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled* # after JTAG reset until ICEpick is used to route them in. set EMU01 "-disable" # With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without # needing any ICEpick interaction. #set EMU01 "-enable" source [find target/icepick.cfg] # Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer if { [info exists ETB_TAPID] } { set _ETB_TAPID $ETB_TAPID } else { set _ETB_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETB_TAPID $EMU01 jtag configure $_CHIPNAME.etb -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 1" # Subsidiary TAP: ARM926ejs with scan chains for ARM Debug, EmbeddedICE-RT, ETM. if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x0792602f } jtag newtap $_CHIPNAME arm -irlen 4 -irmask 0xf -expected-id $_CPU_TAPID $EMU01 jtag configure $_CHIPNAME.arm -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 0" # Primary TAP: ICEpick (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b83e02f } jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID jtag configure $_CHIPNAME.jrc -event setup \ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm" ################ # various symbol definitions, to avoid hard-wiring addresses # and enable some sharing of DaVinci-family utility code global dm365 set dm365 [ dict create ] # Physical addresses for controllers and memory # (Some of these are valid for many DaVinci family chips) dict set dm365 sram0 0x00010000 dict set dm365 sram1 0x00014000 dict set dm365 sysbase 0x01c40000 dict set dm365 pllc1 0x01c40800 dict set dm365 pllc2 0x01c40c00 dict set dm365 psc 0x01c41000 dict set dm365 gpio 0x01c67000 dict set dm365 a_emif 0x01d10000 dict set dm365 a_emif_cs0 0x02000000 dict set dm365 a_emif_cs1 0x04000000 dict set dm365 ddr_emif 0x20000000 dict set dm365 ddr 0x80000000 source [find target/davinci.cfg] ################ # GDB target: the ARM, using SRAM1 for scratch. SRAM0 (also 16K) # and the ETB memory (4K) are other options, while trace is unused. set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME # NOTE that work-area-virt presumes a Linux 2.6.30-rc2+ kernel, # and that the work area is used only with a kernel mmu context ... $_TARGETNAME configure \ -work-area-virt [expr 0xfffe0000 + 0x4000] \ -work-area-phys [dict get $dm365 sram1] \ -work-area-size 0x4000 \ -work-area-backup 0 # be absolutely certain the JTAG clock will work with the worst-case # CLKIN = 19.2 MHz (best case: 36 MHz) even when no bootloader turns # on the PLL and starts using it. OK to speed up after clock setup. adapter_khz 1500 $_TARGETNAME configure -event "reset-start" { adapter_khz 1500 } arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/hilscher_netx500.cfg0000644000175000017500000000213612526202244015706 00000000000000#Hilscher netX 500 CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME netx500 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926021 } # jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # that TAP is associated with a target set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME proc mread32 {addr} { set value(0) 0 mem2array value 32 $addr 1 return $value(0) } # This function must be called on netX100/500 right after halt # If it is called later the needed register cannot be written anymore proc sdram_fix { } { set accesskey [mread32 0x00100070] mww 0x00100070 [expr $accesskey] mww 0x0010002c 0x00000001 if {[expr [mread32 0x0010002c] & 0x07] == 0x07} { puts "SDRAM Fix was not executed. Probably your CPU halted too late and the register is already locked!" } else { puts "SDRAM Fix succeeded!" } } openocd-0.9.0/tcl/target/at32ap7000.cfg0000644000175000017500000000121312526202244014216 00000000000000# Atmel AT32AP7000 # # This is the only core in the now-inactive high end AVR32 product line, # with MMU, Java Acceleration, and "pixel coprocessor". The AP7 line # is for "Application Processors" (AP) with 7-stage pipelines. # # Most current AVR32 parts are in the UC3 flash based microcontroller (UC) # product line with 3-stage pipelines and without those extras. # # All AVR32 parts provide the Nexus Class 3 on-chip debug interfaces # through their JTAG interfaces. jtag newtap ap7 nexus -irlen 5 -expected-id 0x21e8203f # REVISIT declare an avr32 target ... needs OpenOCD infrastructure # for both Nexus (generic) and AVR32 (Atmel-specific). openocd-0.9.0/tcl/target/lpc2900.cfg0000644000175000017500000000365312526202244013720 00000000000000 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lpc2900 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0596802B } if { [info exists HAS_ETB] } { } else { # Set default (no ETB). # Show a warning, because this should have been configured explicitely. set HAS_ETB 0 # TODO: warning? } if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x1B900F0F } # TRST and SRST both exist, and can be controlled independently reset_config trst_and_srst separate # Define the _TARGETNAME set _TARGETNAME $_CHIPNAME.cpu # Include the ETB tap controller if asked for. # Has to be done manually for newer devices (not an "old" LPC2917/2919). if { $HAS_ETB == 1 } { # Clear the HAS_ETB flag. Must be set again for a new tap in the chain. set HAS_ETB 0 # Add the ETB tap controller and the ARM9 core debug tap jtag newtap $_CHIPNAME etb -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_ETBTAPID jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the ".cpu" target target create $_TARGETNAME arm966e -endian little -chain-position $_TARGETNAME # Configure ETM and ETB etm config $_TARGETNAME 8 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb } else { # Add the ARM9 core debug tap jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the ".cpu" target target create $_TARGETNAME arm966e -endian little -chain-position $_TARGETNAME } arm7_9 dbgrq enable arm7_9 dcc_downloads enable # Flash bank configuration: # Flash: flash bank lpc2900 0 0 0 0 # Flash base address, total flash size, and number of sectors are all configured automatically. set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME lpc2900 0 0 0 0 $_TARGETNAME $FLASH_CLOCK openocd-0.9.0/tcl/target/psoc4.cfg0000644000175000017500000001023212526202244013646 00000000000000# script for Cypress PSoC 41xx/42xx family # # PSoC 4 devices support SWD transports only. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME psoc4 } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0bb11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME adapter_khz 1500 # Reset, bloody PSoC 4 reset # # 1) XRES (nSRST) resets also SWD DP so SWD line reset and DP reinit is needed. # High level adapter stops working after SRST and needs OpenOCD restart. # If your hw does not use SRST for other circuits, use sysresetreq instead # # 2) PSoC 4 executes initialization code from system ROM after reset. # This code subsequently jumps to user flash reset vector address. # Unfortunately the system ROM code is protected from reading and debugging. # Protection breaks vector catch VC_CORERESET used for "reset halt" by cortex_m. # # Cypress uses TEST_MODE flag to loop CPU in system ROM before executing code # from user flash. Programming specifications states that TEST_MODE flag must be # set in time frame 400 usec delayed about 1 msec from reset. # # OpenOCD have no standard way how to set TEST_MODE in specified time frame. # TEST_MODE flag is set before reset instead. It worked for tested chips # despite it is not guaranteed by specification. # # 3) SWD cannot be connected during system initialization after reset. # This might be a reason for unconnecting ST-Link v2 when deasserting reset. # As a workaround arp_reset deassert is not called for hla if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } proc ocd_process_reset_inner { MODE } { if { 0 != [string compare psoc4.cpu [target names]] } { return -code error "PSoC 4 reset can handle only one psoc4.cpu target"; } set t psoc4.cpu # If this target must be halted... set halt -1 if { 0 == [string compare $MODE halt] } { set halt 1 } if { 0 == [string compare $MODE init] } { set halt 1; } if { 0 == [string compare $MODE run ] } { set halt 0; } if { $halt < 0 } { return -code error "Invalid mode: $MODE, must be one of: halt, init, or run"; } #$t invoke-event reset-start $t invoke-event reset-assert-pre set TEST_MODE 0x40030014 if { $halt == 1 } { mww $TEST_MODE 0x80000000 } else { mww $TEST_MODE 0 } $t arp_reset assert 0 $t invoke-event reset-assert-post $t invoke-event reset-deassert-pre if {![using_hla]} { # workaround ST-Link v2 fails and forcing reconnect $t arp_reset deassert 0 } $t invoke-event reset-deassert-post # Pass 1 - Now wait for any halt (requested as part of reset # assert/deassert) to happen. Ideally it takes effect without # first executing any instructions. if { $halt } { # Now PSoC CPU should loop in system ROM $t arp_waitstate running 200 $t arp_halt # Catch, but ignore any errors. catch { $t arp_waitstate halted 1000 } # Did we succeed? set s [$t curstate] if { 0 != [string compare $s "halted" ] } { return -code error [format "TARGET: %s - Not halted" $t] } # Check if PSoC CPU is stopped in system ROM set pc [ocd_reg pc] regsub {pc[^:]*: } $pc "" pc if { $pc < 0x10000000 || $pc > 0x1000ffff } { return -code error [format "TARGET: %s - Not halted is system ROM" $t] } # Set registers to reset vector values mem2array value 32 0 2 reg pc [expr $value(1) & 0xfffffffe ] reg msp $value(0) mww $TEST_MODE 0 } #Pass 2 - if needed "init" if { 0 == [string compare init $MODE] } { set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { $t invoke-event reset-init } } $t invoke-event reset-end } openocd-0.9.0/tcl/target/bcm5352e.cfg0000644000175000017500000000036312526202244014047 00000000000000set _CHIPNAME bcm5352e set _CPUID 0x0535217f jtag newtap $_CHIPNAME cpu -irlen 8 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian little -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/at91sam7x256.cfg0000644000175000017500000000261012526202244014612 00000000000000#use combined on interfaces or targets that can't set TRST/SRST separately reset_config srst_only srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam7x256 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { # disable watchdog mww 0xfffffd44 0x00008000 # enable user reset mww 0xfffffd08 0xa5000001 # CKGR_MOR : enable the main oscillator mww 0xfffffc20 0x00000601 sleep 10 # CKGR_PLLR: 96.1097 MHz mww 0xfffffc2c 0x00481c0e sleep 10 # PMC_MCKR : MCK = PLL / 2 ~= 48 MHz mww 0xfffffc30 0x00000007 sleep 10 # MC_FMR: flash mode (FWS=1,FMCN=60) mww 0xffffff60 0x003c0100 sleep 100 } $_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0 #flash bank [ ] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432 openocd-0.9.0/tcl/target/gp326xxxa.cfg0000644000175000017500000000524412526202244014377 00000000000000# # Support for General Plus GP326XXXA chips # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME gp326xxxa } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4f1f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME # Use internal SRAM as a work area $_TARGETNAME configure -work-area-phys 0xf8000000 -work-area-size 0x8000 -work-area-backup 0 # The chip has both lines connected together reset_config trst_and_srst srst_pulls_trst # This delay is needed otherwise communication with the target would # be unreliable adapter_nsrst_delay 100 # Set the adapter speed ridiculously low just in case we are # running off of a 32kHz clock adapter_khz 2 proc gp32xxxa_halt_and_reset_control_registers {} { # System control registers set P_SYSTEM_CTRL_NEW 0xD0000008 set P_SYSTEM_CTRL 0xD000000C set P_SYSTEM_CLK_EN0 0xD0000010 set P_SYSTEM_CLK_EN1 0xD0000014 set P_SYSTEM_RESET_FLAG 0xD0000018 set P_SYSTEM_CLK_CTRL 0xD000001C set P_SYSTEM_LVR_CTRL 0xD0000020 set P_SYSTEM_WATCHDOG_CTRL 0xD0000024 set P_SYSTEM_PLLEN 0xD000005C # Since we can't use SRST without pulling TRST # we can't assume the state of the clock configuration # or watchdog settings. So reset them before porceeding # Set the adapter speed ridiculously low just in case we are # running off of a 32kHz clock adapter_khz 2 # Disable any advanced features at this stage arm7_9 dcc_downloads disable arm7_9 fast_memory_access disable # Do a "soft reset" soft_reset_halt # Reset all system control registers to their default "after-reset" values mwh $P_SYSTEM_WATCHDOG_CTRL 0x0000 mwh $P_SYSTEM_LVR_CTRL 0x0000 mwh $P_SYSTEM_CTRL_NEW 0x0001 mwh $P_SYSTEM_CTRL 0x0001 # Clear all reset flags by writing 1's mwh $P_SYSTEM_RESET_FLAG 0x001C mwh $P_SYSTEM_CLK_CTRL 0x8000 mwh $P_SYSTEM_CLK_EN0 0xFFFF mwh $P_SYSTEM_CLK_EN1 0xFFFF mwh $P_SYSTEM_PLLEN 0x0010 # Unfortunately there's no register that would allow us to # know if PLL is locked. So just wait for 100ms in hopes that # it would be enough. sleep 100 # Now that we know that we are running at 48Mhz # Increase JTAG speed and enable speed optimization features adapter_khz 5000 arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable } $_TARGETNAME configure -event reset-end { gp32xxxa_halt_and_reset_control_registers } openocd-0.9.0/tcl/target/at91sam3XXX.cfg0000644000175000017500000000353112526202244014574 00000000000000# script for ATMEL sam3, a CORTEX-M3 chip # # at91sam3u4e # at91sam3u2e # at91sam3u1e # at91sam3u4c # at91sam3u2c # at91sam3u1c # # at91sam3s4c # at91sam3s4b # at91sam3s4a # at91sam3s2c # at91sam3s2b # at91sam3s2a # at91sam3s1c # at91sam3s1b # at91sam3s1a # # at91sam3A4C # at91sam3A8C # at91sam3X4C # at91sam3X4E # at91sam3X8C # at91sam3X8E # at91sam3X8H source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam3 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming # By default use 64kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME # 16K is plenty, the smallest chip has this much $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 $_TARGETNAME configure -event gdb-flash-erase-start { halt } # JTAG speed should be <= F_CPU/6. F_CPU after reset is 4 MHz, so use F_JTAG = 0.5MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 500 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/str710.cfg0000644000175000017500000000274512526202244013670 00000000000000#start slow, speed up after reset adapter_khz 10 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str710 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-start { adapter_khz 10 } $_TARGETNAME configure -event reset-init { adapter_khz 6000 # Because the hardware cannot be interrogated for the protection state # of sectors, initialize all the sectors to be unprotected. The initial # state is reflected by the driver, too. flash protect 0 0 last off flash protect 1 0 last off } $_TARGETNAME configure -event gdb-flash-erase-start { flash protect 0 0 7 off flash protect 1 0 1 off } $_TARGETNAME configure -work-area-phys 0x2000C000 -work-area-size 0x4000 -work-area-backup 0 #flash bank str7x 0 0 set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME str7x 0x40000000 0x00040000 0 0 $_TARGETNAME STR71x set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME str7x 0x400C0000 0x00004000 0 0 $_TARGETNAME STR71x openocd-0.9.0/tcl/target/lpc8xx.cfg0000644000175000017500000000027212526202244014047 00000000000000# NXP LPC8xx Cortex-M0+ with at least 1kB SRAM set CHIPNAME lpc8xx set CHIPSERIES lpc800 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x400 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/str730.cfg0000644000175000017500000000256112526202244013666 00000000000000#STR730 CPU adapter_khz 3000 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str730 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID #jtag nTRST and nSRST delay adapter_nsrst_delay 500 jtag_ntrst_delay 500 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian little -chain-position 0 $_TARGETNAME configure -event reset-start { adapter_khz 10 } $_TARGETNAME configure -event reset-init { adapter_khz 3000 # Because the hardware cannot be interrogated for the protection state # of sectors, initialize all the sectors to be unprotected. The initial # state is reflected by the driver, too. flash protect 0 0 last off } $_TARGETNAME configure -event gdb-flash-erase-start { flash protect 0 0 7 off } $_TARGETNAME configure -work-area-phys 0xA0000000 -work-area-size 0x4000 -work-area-backup 0 #flash bank set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME str7x 0x80000000 0x00040000 0 0 $_TARGETNAME STR73x openocd-0.9.0/tcl/target/or1k.cfg0000644000175000017500000000343012526202244013474 00000000000000set _ENDIAN big if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME or1k } if { [info exists TAP_TYPE] } { set _TAP_TYPE $TAP_TYPE } else { puts "You need to select a tap type" shutdown } # Configure the target if { [string compare $_TAP_TYPE "VJTAG"] == 0 } { if { [info exists FPGATAPID] } { set _FPGATAPID $FPGATAPID } else { puts "You need to set your FPGA JTAG ID" shutdown } jtag newtap $_CHIPNAME cpu -irlen 10 -expected-id $_FPGATAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME or1k -endian $_ENDIAN -chain-position $_TARGETNAME # Select the TAP core we are using tap_select vjtag } elseif { [string compare $_TAP_TYPE "XILINX_BSCAN"] == 0 } { if { [info exists FPGATAPID] } { set _FPGATAPID $FPGATAPID } else { puts "You need to set your FPGA JTAG ID" shutdown } jtag newtap $_CHIPNAME cpu -irlen 6 -expected-id $_FPGATAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME or1k -endian $_ENDIAN -chain-position $_TARGETNAME # Select the TAP core we are using tap_select xilinx_bscan } else { # OpenCores Mohor JTAG TAP ID set _CPUTAPID 0x14951185 jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME or1k -endian $_ENDIAN -chain-position $_TARGETNAME # Select the TAP core we are using tap_select mohor } # Select the debug unit core we are using. This debug unit as an option. set ADBG_USE_HISPEED 1 set ENABLE_JSP_SERVER 2 set ENABLE_JSP_MULTI 4 # If ADBG_USE_HISPEED is set (options bit 1), status bits will be skipped # on burst reads and writes to improve download speeds. # This option must match the RTL configured option. du_select adv [expr $ADBG_USE_HISPEED | $ENABLE_JSP_SERVER | $ENABLE_JSP_MULTI] openocd-0.9.0/tcl/target/ti-cjtag.cfg0000644000175000017500000000253212526202244014324 00000000000000# A start sequence to change from cJTAG to 4-pin JTAG # This is needed for CC2538 and CC26xx to be able to communicate through JTAG # Read section 6.3 in http://www.ti.com/lit/pdf/swru319 for more information. proc ti_cjtag_to_4pin_jtag {jrc} { # Bypass irscan $jrc 0x3f -endstate RUN/IDLE # Two zero bit scans and a one bit drshift pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRUPDATE RUN/IDLE pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRUPDATE RUN/IDLE pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DREXIT1 DRUPDATE RUN/IDLE pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE # A two bit drhift and a 9 bit drshift pathmove DRPAUSE DREXIT2 DRSHIFT DRSHIFT DREXIT1 DRUPDATE RUN/IDLE pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DRSHIFT DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DRSHIFT DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DRSHIFT DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DRSHIFT DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRSHIFT DREXIT1 DRPAUSE pathmove DRPAUSE DREXIT2 DRUPDATE RUN/IDLE pathmove RUN/IDLE DRSELECT DRCAPTURE DREXIT1 DRPAUSE # Bypass irscan $jrc 0x3f -endstate RUN/IDLE # Set ICEPick IDCODE in data register irscan $jrc 0x04 -endstate RUN/IDLE } openocd-0.9.0/tcl/target/c100config.tcl0000644000175000017500000003501412526202244014477 00000000000000 # board(-config) specfic parameters file. # set CFG_REFCLKFREQ [configC100 CFG_REFCLKFREQ] proc config {label} { return [dict get [configC100] $label ] } # show the value for the param. with label proc showconfig {label} { echo [format "0x%x" [dict get [configC100] $label ]] } # Telo board config # when there are more then one board config # use soft links to c100board-config.tcl # so that only the right board-config gets # included (just like include/configs/board-configs.h # in u-boot. proc configC100 {} { # xtal freq. 24MHz dict set configC100 CFG_REFCLKFREQ 24000000 # Amba Clk 165MHz dict set configC100 CONFIG_SYS_HZ_CLOCK 165000000 dict set configC100 w_amba 1 dict set configC100 x_amba 1 # y = amba_clk * (w+1)*(x+1)*2/xtal_clk dict set configC100 y_amba [expr ([dict get $configC100 CONFIG_SYS_HZ_CLOCK] * ( ([dict get $configC100 w_amba]+1 ) * ([dict get $configC100 x_amba]+1 ) *2 ) / [dict get $configC100 CFG_REFCLKFREQ]) ] # Arm Clk 450MHz, must be a multiple of 25 MHz dict set configC100 CFG_ARM_CLOCK 450000000 dict set configC100 w_arm 0 dict set configC100 x_arm 1 # y = arm_clk * (w+1)*(x+1)*2/xtal_clk dict set configC100 y_arm [expr ([dict get $configC100 CFG_ARM_CLOCK] * ( ([dict get $configC100 w_arm]+1 ) * ([dict get $configC100 x_arm]+1 ) *2 ) / [dict get $configC100 CFG_REFCLKFREQ]) ] } # This should be called for reset init event handler proc setupTelo {} { # setup GPIO used as control signals for C100 setupGPIO # This will allow acces to lower 8MB or NOR lowGPIO5 # setup NOR size,timing,etc. setupNOR # setup internals + PLL + DDR2 initC100 } proc setupNOR {} { echo "Setting up NOR: 16MB, 16-bit wide bus, CS0" # this is taken from u-boot/boards/mindspeed/ooma-darwin/board.c:nor_hw_init() set EX_CSEN_REG [regs EX_CSEN_REG ] set EX_CS0_SEG_REG [regs EX_CS0_SEG_REG ] set EX_CS0_CFG_REG [regs EX_CS0_CFG_REG ] set EX_CS0_TMG1_REG [regs EX_CS0_TMG1_REG ] set EX_CS0_TMG2_REG [regs EX_CS0_TMG2_REG ] set EX_CS0_TMG3_REG [regs EX_CS0_TMG3_REG ] set EX_CLOCK_DIV_REG [regs EX_CLOCK_DIV_REG ] set EX_MFSM_REG [regs EX_MFSM_REG ] set EX_CSFSM_REG [regs EX_CSFSM_REG ] set EX_WRFSM_REG [regs EX_WRFSM_REG ] set EX_RDFSM_REG [regs EX_RDFSM_REG ] # enable Expansion Bus Clock + CS0 (NOR) mww $EX_CSEN_REG 0x3 # set the address space for CS0=16MB mww $EX_CS0_SEG_REG 0x7ff # set the CS0 bus width to 16-bit mww $EX_CS0_CFG_REG 0x202 # set timings to NOR mww $EX_CS0_TMG1_REG 0x03034006 mww $EX_CS0_TMG2_REG 0x04040002 #mww $EX_CS0_TMG3_REG # set EBUS clock 165/5=33MHz mww $EX_CLOCK_DIV_REG 0x5 # everthing else is OK with default } proc bootNOR {} { set EXP_CS0_BASEADDR [regs EXP_CS0_BASEADDR] set BLOCK_RESET_REG [regs BLOCK_RESET_REG] set DDR_RST [regs DDR_RST] # put DDR controller in reset (so that it comes reset in u-boot) mmw $BLOCK_RESET_REG 0x0 $DDR_RST # setup CS0 controller for NOR setupNOR # make sure we are accessing the lower part of NOR lowGPIO5 # set PC to start of NOR (at boot 0x20000000 = 0x0) reg pc $EXP_CS0_BASEADDR # run resume } proc setupGPIO {} { echo "Setting up GPIO block for Telo" # This is current setup for Telo (see sch. for details): #GPIO0 reset for FXS-FXO IC, leave as input, the IC has internal pullup #GPIO1 irq line for FXS-FXO #GPIO5 addr22 for NOR flash (access to upper 8MB) #GPIO17 reset for DECT module. #GPIO29 CS_n for NAND set GPIO_OUTPUT_REG [regs GPIO_OUTPUT_REG] set GPIO_OE_REG [regs GPIO_OE_REG] # set GPIO29=GPIO17=1, GPIO5=0 mww $GPIO_OUTPUT_REG [expr 1<<29 | 1<<17] # enable [as output] GPIO29,GPIO17,GPIO5 mww $GPIO_OE_REG [expr 1<<29 | 1<<17 | 1<<5] } proc highGPIO5 {} { echo "GPIO5 high" set GPIO_OUTPUT_REG [regs GPIO_OUTPUT_REG] # set GPIO5=1 mmw $GPIO_OUTPUT_REG [expr 1 << 5] 0x0 } proc lowGPIO5 {} { echo "GPIO5 low" set GPIO_OUTPUT_REG [regs GPIO_OUTPUT_REG] # set GPIO5=0 mmw $GPIO_OUTPUT_REG 0x0 [expr 1 << 5] } proc boardID {id} { # so far built: # 4'b1111 dict set boardID 15 name "EVT1" dict set boardID 15 ddr2size 128M # dict set boardID 15 nandsize 1G # dict set boardID 15 norsize 16M # 4'b0000 dict set boardID 0 name "EVT2" dict set boardID 0 ddr2size 128M # 4'b0001 dict set boardID 1 name "EVT3" dict set boardID 1 ddr2size 256M # 4'b1110 dict set boardID 14 name "EVT3_old" dict set boardID 14 ddr2size 128M # 4'b0010 dict set boardID 2 name "EVT4" dict set boardID 2 ddr2size 256M return $boardID } # converted from u-boot/boards/mindspeed/ooma-darwin/board.c:ooma_board_detect() # figure out what board revision this is, uses BOOTSTRAP register to read stuffed resistors proc ooma_board_detect {} { set GPIO_BOOTSTRAP_REG [regs GPIO_BOOTSTRAP_REG] # read the current value of the BOOTSRAP pins set tmp [mrw $GPIO_BOOTSTRAP_REG] echo [format "GPIO_BOOTSTRAP_REG (0x%x): 0x%x" $GPIO_BOOTSTRAP_REG $tmp] # extract the GPBP bits set gpbt [expr ($tmp &0x1C00) >> 10 | ($tmp & 0x40) >>3] # display board ID echo [format "This is %s (0x%x)" [dict get [boardID $gpbt] $gpbt name] $gpbt] # show it on serial console putsUART0 [format "This is %s (0x%x)\n" [dict get [boardID $gpbt] $gpbt name] $gpbt] # return the ddr2 size, used to configure DDR2 on a given board. return [dict get [boardID $gpbt] $gpbt ddr2size] } proc configureDDR2regs_256M {} { set DENALI_CTL_00_DATA [regs DENALI_CTL_00_DATA] set DENALI_CTL_01_DATA [regs DENALI_CTL_01_DATA] set DENALI_CTL_02_DATA [regs DENALI_CTL_02_DATA] set DENALI_CTL_03_DATA [regs DENALI_CTL_03_DATA] set DENALI_CTL_04_DATA [regs DENALI_CTL_04_DATA] set DENALI_CTL_05_DATA [regs DENALI_CTL_05_DATA] set DENALI_CTL_06_DATA [regs DENALI_CTL_06_DATA] set DENALI_CTL_07_DATA [regs DENALI_CTL_07_DATA] set DENALI_CTL_08_DATA [regs DENALI_CTL_08_DATA] set DENALI_CTL_09_DATA [regs DENALI_CTL_09_DATA] set DENALI_CTL_10_DATA [regs DENALI_CTL_10_DATA] set DENALI_CTL_11_DATA [regs DENALI_CTL_11_DATA] set DENALI_CTL_12_DATA [regs DENALI_CTL_12_DATA] set DENALI_CTL_13_DATA [regs DENALI_CTL_13_DATA] set DENALI_CTL_14_DATA [regs DENALI_CTL_14_DATA] set DENALI_CTL_15_DATA [regs DENALI_CTL_15_DATA] set DENALI_CTL_16_DATA [regs DENALI_CTL_16_DATA] set DENALI_CTL_17_DATA [regs DENALI_CTL_17_DATA] set DENALI_CTL_18_DATA [regs DENALI_CTL_18_DATA] set DENALI_CTL_19_DATA [regs DENALI_CTL_19_DATA] set DENALI_CTL_20_DATA [regs DENALI_CTL_20_DATA] set DENALI_CTL_02_VAL 0x0100000000010100 set DENALI_CTL_11_VAL 0x433a32164a560a00 mw64bit $DENALI_CTL_00_DATA 0x0100000101010101 # 01_DATA mod [40]=1, enable BA2 mw64bit $DENALI_CTL_01_DATA 0x0100010100000001 mw64bit $DENALI_CTL_02_DATA $DENALI_CTL_02_VAL mw64bit $DENALI_CTL_03_DATA 0x0102020202020201 mw64bit $DENALI_CTL_04_DATA 0x0000010100000001 mw64bit $DENALI_CTL_05_DATA 0x0203010300010101 mw64bit $DENALI_CTL_06_DATA 0x060a020200020202 mw64bit $DENALI_CTL_07_DATA 0x0000000300000206 mw64bit $DENALI_CTL_08_DATA 0x6400003f3f0a0209 mw64bit $DENALI_CTL_09_DATA 0x1a000000001a1a1a mw64bit $DENALI_CTL_10_DATA 0x0120202020191a18 # 11_DATA mod [39-32]=16,more refresh mw64bit $DENALI_CTL_11_DATA $DENALI_CTL_11_VAL mw64bit $DENALI_CTL_12_DATA 0x0000000000000800 mw64bit $DENALI_CTL_13_DATA 0x0010002000100040 mw64bit $DENALI_CTL_14_DATA 0x0010004000100040 mw64bit $DENALI_CTL_15_DATA 0x04f8000000000000 mw64bit $DENALI_CTL_16_DATA 0x000000002cca0000 mw64bit $DENALI_CTL_17_DATA 0x0000000000000000 mw64bit $DENALI_CTL_18_DATA 0x0302000000000000 mw64bit $DENALI_CTL_19_DATA 0x00001300c8030600 mw64bit $DENALI_CTL_20_DATA 0x0000000081fe00c8 set wr_dqs_shift 0x40 # start DDRC mw64bit $DENALI_CTL_02_DATA [expr $DENALI_CTL_02_VAL | (1 << 32)] # wait int_status[2] (DRAM init complete) echo -n "Waiting for DDR2 controller to init..." set tmp [mrw [expr $DENALI_CTL_08_DATA + 4]] while { [expr $tmp & 0x040000] == 0 } { sleep 1 set tmp [mrw [expr $DENALI_CTL_08_DATA + 4]] } echo "done." # do ddr2 training sequence # TBD (for now, if you need it, run trainDDR command) } # converted from u-boot/cpu/arm1136/comcerto/bsp100.c:config_board99() # The values are computed based on Mindspeed and Nanya datasheets proc configureDDR2regs_128M {} { set DENALI_CTL_00_DATA [regs DENALI_CTL_00_DATA] set DENALI_CTL_01_DATA [regs DENALI_CTL_01_DATA] set DENALI_CTL_02_DATA [regs DENALI_CTL_02_DATA] set DENALI_CTL_03_DATA [regs DENALI_CTL_03_DATA] set DENALI_CTL_04_DATA [regs DENALI_CTL_04_DATA] set DENALI_CTL_05_DATA [regs DENALI_CTL_05_DATA] set DENALI_CTL_06_DATA [regs DENALI_CTL_06_DATA] set DENALI_CTL_07_DATA [regs DENALI_CTL_07_DATA] set DENALI_CTL_08_DATA [regs DENALI_CTL_08_DATA] set DENALI_CTL_09_DATA [regs DENALI_CTL_09_DATA] set DENALI_CTL_10_DATA [regs DENALI_CTL_10_DATA] set DENALI_CTL_11_DATA [regs DENALI_CTL_11_DATA] set DENALI_CTL_12_DATA [regs DENALI_CTL_12_DATA] set DENALI_CTL_13_DATA [regs DENALI_CTL_13_DATA] set DENALI_CTL_14_DATA [regs DENALI_CTL_14_DATA] set DENALI_CTL_15_DATA [regs DENALI_CTL_15_DATA] set DENALI_CTL_16_DATA [regs DENALI_CTL_16_DATA] set DENALI_CTL_17_DATA [regs DENALI_CTL_17_DATA] set DENALI_CTL_18_DATA [regs DENALI_CTL_18_DATA] set DENALI_CTL_19_DATA [regs DENALI_CTL_19_DATA] set DENALI_CTL_20_DATA [regs DENALI_CTL_20_DATA] set DENALI_CTL_02_VAL 0x0100010000010100 set DENALI_CTL_11_VAL 0x433A42124A650A37 # set some default values mw64bit $DENALI_CTL_00_DATA 0x0100000101010101 mw64bit $DENALI_CTL_01_DATA 0x0100000100000101 mw64bit $DENALI_CTL_02_DATA $DENALI_CTL_02_VAL mw64bit $DENALI_CTL_03_DATA 0x0102020202020201 mw64bit $DENALI_CTL_04_DATA 0x0201010100000201 mw64bit $DENALI_CTL_05_DATA 0x0203010300010101 mw64bit $DENALI_CTL_06_DATA 0x050A020200020202 mw64bit $DENALI_CTL_07_DATA 0x000000030E0B0205 mw64bit $DENALI_CTL_08_DATA 0x6427003F3F0A0209 mw64bit $DENALI_CTL_09_DATA 0x1A00002F00001A00 mw64bit $DENALI_CTL_10_DATA 0x01202020201A1A1A mw64bit $DENALI_CTL_11_DATA $DENALI_CTL_11_VAL mw64bit $DENALI_CTL_12_DATA 0x0000080000000800 mw64bit $DENALI_CTL_13_DATA 0x0010002000100040 mw64bit $DENALI_CTL_14_DATA 0x0010004000100040 mw64bit $DENALI_CTL_15_DATA 0x0508000000000000 mw64bit $DENALI_CTL_16_DATA 0x000020472D200000 mw64bit $DENALI_CTL_17_DATA 0x0000000008000000 mw64bit $DENALI_CTL_18_DATA 0x0302000000000000 mw64bit $DENALI_CTL_19_DATA 0x00001400C8030604 mw64bit $DENALI_CTL_20_DATA 0x00000000823600C8 set wr_dqs_shift 0x40 # start DDRC mw64bit $DENALI_CTL_02_DATA [expr $DENALI_CTL_02_VAL | (1 << 32)] # wait int_status[2] (DRAM init complete) echo -n "Waiting for DDR2 controller to init..." set tmp [mrw [expr $DENALI_CTL_08_DATA + 4]] while { [expr $tmp & 0x040000] == 0 } { sleep 1 set tmp [mrw [expr $DENALI_CTL_08_DATA + 4]] } # This is not necessary #mw64bit $DENALI_CTL_11_DATA [expr ($DENALI_CTL_11_VAL & ~0x00007F0000000000) | ($wr_dqs_shift << 40) ] echo "done." # do ddr2 training sequence # TBD (for now, if you need it, run trainDDR command) } proc setupUART0 {} { # configure UART0 to 115200, 8N1 set GPIO_LOCK_REG [regs GPIO_LOCK_REG] set GPIO_IOCTRL_REG [regs GPIO_IOCTRL_REG] set GPIO_IOCTRL_VAL [regs GPIO_IOCTRL_VAL] set GPIO_IOCTRL_UART0 [regs GPIO_IOCTRL_UART0] set UART0_LCR [regs UART0_LCR] set LCR_DLAB [regs LCR_DLAB] set UART0_DLL [regs UART0_DLL] set UART0_DLH [regs UART0_DLH] set UART0_IIR [regs UART0_IIR] set UART0_IER [regs UART0_IER] set LCR_ONE_STOP [regs LCR_ONE_STOP] set LCR_CHAR_LEN_8 [regs LCR_CHAR_LEN_8] set FCR_XMITRES [regs FCR_XMITRES] set FCR_RCVRRES [regs FCR_RCVRRES] set FCR_FIFOEN [regs FCR_FIFOEN] set IER_UUE [regs IER_UUE] # unlock writing to IOCTRL register mww $GPIO_LOCK_REG $GPIO_IOCTRL_VAL # enable UART0 mmw $GPIO_IOCTRL_REG $GPIO_IOCTRL_UART0 0x0 # baudrate 115200 # This should really be amba_clk/(16*115200) but amba_clk=165MHz set tmp 89 # Enable Divisor Latch access mmw $UART0_LCR $LCR_DLAB 0x0 # set the divisor to $tmp mww $UART0_DLL [expr $tmp & 0xff] mww $UART0_DLH [expr $tmp >> 8] # Disable Divisor Latch access mmw $UART0_LCR 0x0 $LCR_DLAB # set the UART to 8N1 mmw $UART0_LCR [expr $LCR_ONE_STOP | $LCR_CHAR_LEN_8 ] 0x0 # reset FIFO mmw $UART0_IIR [expr $FCR_XMITRES | $FCR_RCVRRES | $FCR_FIFOEN ] 0x0 # enable FFUART mww $UART0_IER $IER_UUE } proc putcUART0 {char} { set UART0_LSR [regs UART0_LSR] set UART0_THR [regs UART0_THR] set LSR_TEMT [regs LSR_TEMT] # convert the 'char' to digit set tmp [ scan $char %c ] # /* wait for room in the tx FIFO on FFUART */ while {[expr [mrw $UART0_LSR] & $LSR_TEMT] == 0} { sleep 1 } mww $UART0_THR $tmp if { $char == "\n" } { putcUART0 \r } } proc putsUART0 {str} { set index 0 set len [string length $str] while { $index < $len } { putcUART0 [string index $str $index] set index [expr $index + 1] } } proc trainDDR2 {} { set ARAM_BASEADDR [regs ARAM_BASEADDR] # you must have run 'reset init' or u-boot # load the training code to ARAM load_image ./images/ddr2train.bin $ARAM_BASEADDR bin # set PC to start of NOR (at boot 0x20000000 = 0x0) reg pc $ARAM_BASEADDR # run resume } proc flashUBOOT {file} { # this will update uboot on NOR partition set EXP_CS0_BASEADDR [regs EXP_CS0_BASEADDR] # setup CS0 controller for NOR setupNOR # make sure we are accessing the lower part of NOR lowGPIO5 flash probe 0 echo "Erasing sectors 0-3 for uboot" putsUART0 "Erasing sectors 0-3 for uboot\n" flash erase_sector 0 0 3 echo "Programming u-boot" putsUART0 "Programming u-boot..." arm11 memwrite burst enable flash write_image $file $EXP_CS0_BASEADDR arm11 memwrite burst disable putsUART0 "done.\n" putsUART0 "Rebooting, please wait!\n" reboot }openocd-0.9.0/tcl/target/stm32l0.cfg0000644000175000017500000000334512526202244014031 00000000000000# # M0+ devices only have SW-DP, but swj-dp code works, just don't # set any jtag related features # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32l0 } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 8kB (max ram on smallest part) if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x2000 } # JTAG speed should be <= F_CPU/6. # F_CPU after reset is ~2MHz, so use F_JTAG max = 333kHz adapter_khz 300 adapter_nsrst_delay 100 if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # Arm, m0+, non-multidrop. # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka16088.html set _CPUTAPID 0x0bc11477 } swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # flash size will be probed set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32lx 0x08000000 0 0 0 $_TARGETNAME reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } proc stm32l0_enable_HSI16 {} { # Enable HSI16 as clock source echo "STM32L0: Enabling HSI16" # Set HSI16ON in RCC_CR (leave MSI enabled) mww 0x40021000 0x00000101 # Set HSI16 as SYSCLK (RCC_CFGR) mww 0x4002100c 0x00000001 # Increase speed adapter_khz 2500 } $_TARGETNAME configure -event reset-init { stm32l0_enable_HSI16 } $_TARGETNAME configure -event reset-start { adapter_khz 300 } openocd-0.9.0/tcl/target/stm32l1.cfg0000644000175000017500000000575512526202244014041 00000000000000# # stm32l1 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32l1 } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 10kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x2800 } # JTAG speed should be <= F_CPU/6. # F_CPU after reset is 2MHz, so use F_JTAG max = 333kHz adapter_khz 300 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { # See STM Document RM0038 # Section 30.6.3 - corresponds to Cortex-M3 r2p0 set _CPUTAPID 0x4ba00477 } else { # SWD IDCODE (single drop, arm) set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { # FIXME this never gets used to override defaults... set _BSTAPID $BSTAPID } else { # See STM Document RM0038 Section 30.6.1 Rev. 12 # Low and medium density set _BSTAPID1 0x06416041 # Cat.2 device (medium+ density) set _BSTAPID2 0x06429041 # Cat.3 device (medium+ density) set _BSTAPID3 0x06427041 # Cat.4 device, STM32L15/6xxD or Cat.3 device, some STM32L15/6xxC-A models set _BSTAPID4 0x06436041 # Cat.5 device (high density), STM32L15/6xxE set _BSTAPID5 0x06437041 } if {[using_jtag]} { swj_newdap $_CHIPNAME bs -irlen 5 \ -expected-id $_BSTAPID1 -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # flash size will be probed set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32lx 0x08000000 0 0 0 $_TARGETNAME reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } proc stm32l_enable_HSI {} { # Enable HSI as clock source echo "STM32L: Enabling HSI" # Set HSION in RCC_CR mww 0x40023800 0x00000101 # Set HSI as SYSCLK mww 0x40023808 0x00000001 # Increase JTAG speed adapter_khz 2000 } $_TARGETNAME configure -event reset-init { stm32l_enable_HSI } $_TARGETNAME configure -event reset-start { adapter_khz 300 } $_TARGETNAME configure -event examine-end { # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP mmw 0xE0042004 0x00000007 0 # Stop watchdog counters during halt # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP mww 0xE0042008 0x00001800 } $_TARGETNAME configure -event trace-config { # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync # change this value accordingly to configure trace pins # assignment mmw 0xE0042004 0x00000020 0 } openocd-0.9.0/tcl/target/str750.cfg0000644000175000017500000000360512526202244013670 00000000000000#STR750 CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str750 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4f1f0041 } # jtag speed adapter_khz 10 #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID #jtag nTRST and nSRST delay adapter_nsrst_delay 500 jtag_ntrst_delay 500 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian little -chain-position 0 $_TARGETNAME configure -event reset-start { adapter_khz 10 } $_TARGETNAME configure -event reset-init { adapter_khz 3000 init_smi # Because the hardware cannot be interrogated for the protection state # of sectors, initialize all the sectors to be unprotected. The initial # state is reflected by the driver, too. flash protect 0 0 last off flash protect 1 0 last off } $_TARGETNAME configure -event gdb-flash-erase-start { flash protect 0 0 7 off flash protect 1 0 1 off } $_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup 0 #flash bank set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME str7x 0x20000000 0x00040000 0 0 $_TARGETNAME STR75x set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME str7x 0x200C0000 0x00004000 0 0 $_TARGETNAME STR75x # Serial NOR on SMI CS0. set _FLASHNAME $_CHIPNAME.snor flash bank $_FLASHNAME stmsmi 0x80000000 0 0 0 $_TARGETNAME source [find mem_helper.tcl] proc init_smi {} { mmw 0x60000030 0x01000000 0x00000000; # enable clock for GPIO regs mmw 0xffffe420 0x00000001 0x00000000; # set SMI_EN bit mmw 0x90000000 0x00000001 0x00000000; # set BLOCK_EN_1 } openocd-0.9.0/tcl/target/at91sam7a2.cfg0000644000175000017500000000074712526202244014421 00000000000000 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91sam7a2 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/u8500.cfg0000644000175000017500000001433712526202244013411 00000000000000# Copyright (C) ST-Ericsson SA 2011 # Author : michel.jaouen@stericsson.com # U8500 target proc mmu_off {} { set cp [arm mrc 15 0 1 0 0] set cp [expr ($cp & ~1)] arm mcr 15 0 1 0 0 $cp } proc mmu_on {} { set cp [arm mrc 15 0 1 0 0] set cp [expr ($cp | 1)] arm mcr 15 0 1 0 0 $cp } proc ocd_gdb_restart {target_id} { global _TARGETNAME_1 global _SMP targets $_TARGETNAME_1 if { [expr ($_SMP == 1)] } { cortex_a smp_off } rst_run halt if { [expr ($_SMP == 1)]} { cortex_a smp_on } } proc smp_reg {} { global _TARGETNAME_1 global _TARGETNAME_2 targets $_TARGETNAME_1 echo "$_TARGETNAME_1" set pc1 [reg pc] set stck1 [reg sp_svc] targets $_TARGETNAME_2 echo "$_TARGETNAME_1" set pc2 [reg pc] set stck2 [reg sp_svc] } proc u8500_tapenable {chip val} { echo "JTAG tap enable $chip" } proc pwrsts { } { global _CHIPNAME irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 0 set pwrsts [drscan $_CHIPNAME.jrc 16 0] echo "pwrsts ="$pwrsts set a9 [expr (0x$pwrsts & 0xc)] set ape [expr (0x$pwrsts & 0x3)] if {[string equal "0" $ape]} { echo "ape off" } else { echo "ape on" } echo "$a9" switch $a9 { 4 { echo "A9 in retention" } 8 { echo "A9 100% DVFS" } c { echo "A9 50% DVFS" } } } proc poll_pwrsts { } { global _CHIPNAME set result 1 set i 0 irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 0 set pwrsts [drscan $_CHIPNAME.jrc 16 0] set pwrsts [expr (0x$pwrsts & 0xc)] while {[string equal "4" $pwrsts] && $i<20} { irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 0; set pwrsts [drscan $_CHIPNAME.jrc 16 0] set pwrsts [expr (0x$pwrsts & 0xc)] if {![string equal "4" $pwrsts]} { set result 1 } else { set result 0 sleep 200 echo "loop $i" } incr i } return $result } proc halt_ { } { if {[poll_pwrsts]==1} { halt } else { echo "halt failed : target in retention" } } proc u8500_dapenable {chip} { } proc u8500_tapdisable {chip val} { echo "JTAG tap disable $chip" } proc enable_apetap {} { global _CHIPNAME global _TARGETNAME_2 global _TARGETNAME_1 poll off irscan $_CHIPNAME.jrc 0x3e drscan $_CHIPNAME.jrc 8 0xcf jtag tapenable $_CHIPNAME.dap irscan $_CHIPNAME.jrc 0x6 drscan $_CHIPNAME.jrc 32 0 irscan $_CHIPNAME.jrc 0x6 drscan $_CHIPNAME.jrc 32 0 set status [$_TARGETNAME_1 curstate] if {[string equal "unknown" $status]} { $_TARGETNAME_1 arp_examine cache_config l2x 0xa0412000 8 } set status [$_TARGETNAME_2 curstate] if {[string equal "unknown" $status]} { $_TARGETNAME_2 arp_examine } } tcl_port 5555 telnet_port 4444 gdb_port 3333 if { [info exists CHIPNAME] } { global _CHIPNAME set _CHIPNAME $CHIPNAME } else { global _CHIPNAME set _CHIPNAME u8500 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN little } # Subsidiary TAP: APE with scan chains for ARM Debug, EmbeddedICE-RT, if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0xe -irmask 0xf -expected-id $_CPUTAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable \ "u8500_dapenable $_CHIPNAME.dap" jtag configure $_CHIPNAME.dap -event tap-disable \ "u8500_tapdisable $_CHIPNAME.dap 0xc0" #CLTAPC TAP JRC equivalent if { [info exists CLTAPC_ID] } { set _CLTAPC_ID $CLTAPC_ID } else { set _CLTAPC_ID 0x22286041 } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x6 -irmask 0xf -expected-id $_CLTAPC_ID -ignore-version if { ![info exists TARGETNAME_1] } { global _TARGETNAME_1 set _TARGETNAME_1 $_CHIPNAME.cpu1 } else { global _TARGETNAME_1 set _TARGETNAME_1 $TARGETNAME_1 } if { [info exists DAP_DBG1] } { set _DAP_DBG1 $DAP_DBG1 } else { set _DAP_DBG1 0x801A8000 } if { [info exists DAP_DBG2] } { set _DAP_DBG2 $DAP_DBG2 } else { set _DAP_DBG2 0x801AA000 } target create $_TARGETNAME_1 cortex_a -chain-position $_CHIPNAME.dap -dbgbase $_DAP_DBG1 -coreid 0 -rtos linux $_TARGETNAME_1 configure -event gdb-attach { halt } if { ![info exists TARGETNAME_2] } { global _TARGETNAME_2 set _TARGETNAME_2 $_CHIPNAME.cpu2 } else { global _TARGETNAME_2 set _TARGETNAME_2 $TARGETNAME_2 } target create $_TARGETNAME_2 cortex_a -chain-position $_CHIPNAME.dap -dbgbase $_DAP_DBG2 -coreid 1 -rtos linux $_TARGETNAME_2 configure -event gdb-attach { halt } if {![info exists SMP]} { global _SMP set _SMP 1 } else { global _SMP set _SMP $SMP } global SMP if { $_SMP == 1} { target smp $_CHIPNAME.cpu2 $_CHIPNAME.cpu1 } proc secsts1 { } { global _CHIPNAME irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 4 set secsts1 [drscan $_CHIPNAME.jrc 16 0] echo "secsts1 ="$secsts1 set secsts1 [expr (0x$secsts1 & 0x4)] if {![string equal "4" $secsts1]} { echo "APE target secured" } else { echo "APE target not secured" } } proc att { } { global _CHIPNAME jtag arp_init irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 4 set secsts1 [drscan $_CHIPNAME.jrc 16 0] echo "secsts1 ="$secsts1 set secsts1 [expr (0x$secsts1 & 0x4)] if {[string equal "4" $secsts1]} { if {[poll_pwrsts]==1} { enable_apetap } else { echo "target in retention" } } else { echo "target secured" } } proc rst_run { } { global _CHIPNAME global _TARGETNAME_2 global _TARGETNAME_1 set status [$_TARGETNAME_1 curstate] if {[string equal "halted" $status]} { resume targets $_TARGETNAME_1 } set status [$_TARGETNAME_2 curstate] if {[string equal "halted" $status]} { resume targets $_TARGETNAME_2 } poll off jtag arp_init reset sleep 20 irscan $_CHIPNAME.jrc 0x3a drscan $_CHIPNAME.jrc 4 4 set secsts1 [drscan $_CHIPNAME.jrc 16 0] echo "secsts1 ="$secsts1 set secsts1 [expr (0x$secsts1 & 0x4)] while {![string equal "4" $secsts1]} { irscan u8500.jrc 0x3a drscan u8500.jrc 4 4 set secsts1 [drscan $_CHIPNAME.jrc 16 0] echo "secsts1 ="$secsts1 set secsts1 [expr (0x$secsts1 & 0x4)] } echo "ape debugable" enable_apetap poll on targets $_TARGETNAME_1 dap apsel 1 } if {![info exists MAXSPEED]} { global _MAXSPEED set _MAXSPEED 15000 } else { global _MAXSPEED set _MAXSPEED $MAXSPEED } global _MAXSPEED adapter_khz $_MAXSPEED gdb_breakpoint_override hard set mem inaccessible-by-default-off jtag_ntrst_delay 100 reset_config trst_and_srst combined openocd-0.9.0/tcl/target/stm32l1x_dual_bank.cfg0000644000175000017500000000036512526202244016221 00000000000000source [find target/stm32l1.cfg] # The stm32l1x 384kb have a dual bank flash. # Let's add a definition for the second bank here. # Add the second flash bank. set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME stm32lx 0 0 0 0 $_TARGETNAME openocd-0.9.0/tcl/target/lpc2294.cfg0000644000175000017500000000167312526202244013726 00000000000000# NXP LPC2294 ARM7TDMI-S with 256kB flash and 16kB SRAM, clocked with 12MHz crystal source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2294 {core_freq_khz adapter_freq_khz} { # 256kB flash and 16kB SRAM # setup_lpc2xxx # !! TAPID unknown !! setup_lpc2xxx lpc2294 0xffffffff 0x40000 lpc2000_v1 0x4000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 12MHz crystal echo "Warning - assuming default core clock 12MHz! Flashing may fail if actual core clock is different." # setup_lpc2294 setup_lpc2294 12000 1500 } openocd-0.9.0/tcl/target/nds32v2.cfg0000644000175000017500000000032212526202244014016 00000000000000# # Andes Core # # http://www.andestech.com # jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME nds32_v2 -endian little -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/nds32v3.cfg0000644000175000017500000000032212526202244014017 00000000000000# # Andes Core # # http://www.andestech.com # jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME nds32_v3 -endian little -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/samsung_s3c4510.cfg0000644000175000017500000000102112526202244015351 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c4510 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # This appears to be a "Version 1" arm7tdmi. if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/test_reset_syntax_error.cfg0000644000175000017500000000062412526202244017622 00000000000000# Test script to check that syntax error in reset # script is reported properly. # at91eb40a target #jtag scan chain set _CHIPNAME syntaxtest jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf #target configuration set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { syntax error } openocd-0.9.0/tcl/target/faux.cfg0000644000175000017500000000123612526202244013565 00000000000000#Script for faux target - used for testing if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91eb40a } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x00000000 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID #target configuration set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME #dummy flash driver set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME faux 0x01000000 0x200000 2 2 $_TARGETNAME openocd-0.9.0/tcl/target/k40.cfg0000644000175000017500000000012212526202244013211 00000000000000# # Freescale Kinetis K40 devices # set CHIPNAME k40 source [find target/kx.cfg] openocd-0.9.0/tcl/target/stm32_stlink.cfg0000644000175000017500000000013512526202244015153 00000000000000echo "WARNING: stm32_stlink.cfg is deprecated (and does nothing, you can safely remove it.)" openocd-0.9.0/tcl/target/swj-dp.tcl0000644000175000017500000000204512526202244014050 00000000000000# ARM Debug Interface V5 (ADI_V5) utility # ... Mostly for SWJ-DP (not SW-DP or JTAG-DP, since # SW-DP and JTAG-DP targets don't need to switch based # on which transport is active. # # declare a JTAG or SWD Debug Access Point (DAP) # based on the transport in use with this session. # You can't access JTAG ops when SWD is active, etc. # params are currently what "jtag newtap" uses # because OpenOCD internals are still strongly biased # to JTAG .... but for SWD, "irlen" etc are ignored, # and the internals work differently # for now, ignore non-JTAG and non-SWD transports # (e.g. initial flash programming via SPI or UART) # split out "chip" and "tag" so we can someday handle # them more uniformly irlen too...) if [catch {transport select}] { echo "Error: unable to select a session transport. Can't continue." shutdown } proc swj_newdap {chip tag args} { if [using_hla] { eval hla newtap $chip $tag $args } elseif [using_jtag] { eval jtag newtap $chip $tag $args } elseif [using_swd] { eval swd newdap $chip $tag $args } } openocd-0.9.0/tcl/target/epc9301.cfg0000644000175000017500000000161212526202244013704 00000000000000# Cirrus Logic EP9301 processor on an Olimex CS-E9301 board. if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME ep9301 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # Force an error until we get a good number. set _CPUTAPID 0xffffffff } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID adapter_nsrst_delay 100 jtag_ntrst_delay 100 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME -work-area-phys 0x80014000 -work-area-size 0x1000 -work-area-backup 1 #flash configuration #flash bank [driver_options ...] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x60000000 0x1000000 2 2 $_TARGETNAME openocd-0.9.0/tcl/target/c100regs.tcl0000644000175000017500000005771412526202244014205 00000000000000# Note that I basically converted # u-boot/include/asm-arm/arch/comcerto_100.h # defines # this is a work-around for 'global' not working under Linux # access registers by calling this routine. # For example: # set EX_CS_TMG1_REG [regs EX_CS0_TMG1_REG] proc regs {reg} { return [dict get [regsC100] $reg ] } proc showreg {reg} { echo [format "0x%x" [dict get [regsC100] $reg ]] } proc regsC100 {} { #/* memcore */ #/* device memory base addresses */ #// device memory sizes #/* ARAM SIZE=64K */ dict set regsC100 ARAM_SIZE 0x00010000 dict set regsC100 ARAM_BASEADDR 0x0A000000 #/* Hardware Interface Units */ dict set regsC100 APB_BASEADDR 0x10000000 #/* APB_SIZE=16M address range */ dict set regsC100 APB_SIZE 0x01000000 dict set regsC100 EXP_CS0_BASEADDR 0x20000000 dict set regsC100 EXP_CS1_BASEADDR 0x24000000 dict set regsC100 EXP_CS2_BASEADDR 0x28000000 dict set regsC100 EXP_CS3_BASEADDR 0x2C000000 dict set regsC100 EXP_CS4_BASEADDR 0x30000000 dict set regsC100 DDR_BASEADDR 0x80000000 dict set regsC100 TDM_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x000000] dict set regsC100 PHI_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x010000] dict set regsC100 TDMA_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x020000] dict set regsC100 ASA_DDR_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x040000] dict set regsC100 ASA_ARAM_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x048000] dict set regsC100 TIMER_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x050000] dict set regsC100 ASD_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x060000] dict set regsC100 GPIO_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x070000] dict set regsC100 UART0_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x090000] dict set regsC100 UART1_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x094000] dict set regsC100 SPI_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x098000] dict set regsC100 I2C_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x09C000] dict set regsC100 INTC_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0A0000] dict set regsC100 CLKCORE_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0B0000] dict set regsC100 PUI_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0B0000] dict set regsC100 GEMAC_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0D0000] dict set regsC100 IDMA_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0E0000] dict set regsC100 MEMCORE_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x0F0000] dict set regsC100 ASA_EBUS_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x100000] dict set regsC100 ASA_AAB_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x108000] dict set regsC100 GEMAC1_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x190000] dict set regsC100 EBUS_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x1A0000] dict set regsC100 MDMA_BASEADDR [expr [dict get $regsC100 APB_BASEADDR ] + 0x1E0000] #//////////////////////////////////////////////////////////// #// AHB block // #//////////////////////////////////////////////////////////// dict set regsC100 ASA_ARAM_PRI_REG [expr [dict get $regsC100 ASA_ARAM_BASEADDR ] + 0x00] dict set regsC100 ASA_ARAM_TC_REG [expr [dict get $regsC100 ASA_ARAM_BASEADDR ] + 0x04] dict set regsC100 ASA_ARAM_TC_CR_REG [expr [dict get $regsC100 ASA_ARAM_BASEADDR ] + 0x08] dict set regsC100 ASA_ARAM_STAT_REG [expr [dict get $regsC100 ASA_ARAM_BASEADDR ] + 0x0C] dict set regsC100 ASA_EBUS_PRI_REG [expr [dict get $regsC100 ASA_EBUS_BASEADDR ] + 0x00] dict set regsC100 ASA_EBUS_TC_REG [expr [dict get $regsC100 ASA_EBUS_BASEADDR ] + 0x04] dict set regsC100 ASA_EBUS_TC_CR_REG [expr [dict get $regsC100 ASA_EBUS_BASEADDR ] + 0x08] dict set regsC100 ASA_EBUS_STAT_REG [expr [dict get $regsC100 ASA_EBUS_BASEADDR ] + 0x0C] dict set regsC100 IDMA_MASTER 0 dict set regsC100 TDMA_MASTER 1 dict set regsC100 USBIPSEC_MASTER 2 dict set regsC100 ARM0_MASTER 3 dict set regsC100 ARM1_MASTER 4 dict set regsC100 MDMA_MASTER 5 #define IDMA_PRIORITY(level) (level) #define TDM_PRIORITY(level) (level << 4) #define USBIPSEC_PRIORITY(level) (level << 8) #define ARM0_PRIORITY(level) (level << 12) #define ARM1_PRIORITY(level) (level << 16) #define MDMA_PRIORITY(level) (level << 20) dict set regsC100 ASA_TC_REQIDMAEN [expr 1<<18] dict set regsC100 ASA_TC_REQTDMEN [expr 1<<19] dict set regsC100 ASA_TC_REQIPSECUSBEN [expr 1<<20] dict set regsC100 ASA_TC_REQARM0EN [expr 1<<21] dict set regsC100 ASA_TC_REQARM1EN [expr 1<<22] dict set regsC100 ASA_TC_REQMDMAEN [expr 1<<23] dict set regsC100 MEMORY_BASE_ADDR 0x80000000 dict set regsC100 MEMORY_MAX_ADDR [expr [dict get $regsC100 ASD_BASEADDR ] + 0x10] dict set regsC100 MEMORY_CR [expr [dict get $regsC100 ASD_BASEADDR ] + 0x14] dict set regsC100 ROM_REMAP_EN 0x1 #define HAL_asb_priority(level) \ #*(volatile unsigned *)ASA_PRI_REG = level #define HAL_aram_priority(level) \ #*(volatile unsigned *)ASA_ARAM_PRI_REG = level #define HAL_aram_arbitration(arbitration_mask) \ #*(volatile unsigned *)ASA_ARAM_TC_CR_REG |= arbitration_mask #define HAL_aram_defmaster(mask) \ #*(volatile unsigned *)ASA_ARAM_TC_CR_REG = (*(volatile unsigned *)ASA_TC_CR_REG & 0xFFFF) | (mask << 24) #//////////////////////////////////////////////////////////// #// INTC block // #//////////////////////////////////////////////////////////// dict set regsC100 INTC_ARM1_CONTROL_REG [expr [dict get $regsC100 INTC_BASEADDR ] + 0x18] #//////////////////////////////////////////////////////////// #// TIMER block // #//////////////////////////////////////////////////////////// dict set regsC100 TIMER0_CNTR_REG [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x00] dict set regsC100 TIMER0_CURR_COUNT [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x04] dict set regsC100 TIMER1_CNTR_REG [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x08] dict set regsC100 TIMER1_CURR_COUNT [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x0C] dict set regsC100 TIMER2_CNTR_REG [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x18] dict set regsC100 TIMER2_LBOUND_REG [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x10] dict set regsC100 TIMER2_HBOUND_REG [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x14] dict set regsC100 TIMER2_CURR_COUNT [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x1C] dict set regsC100 TIMER3_LOBND [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x20] dict set regsC100 TIMER3_HIBND [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x24] dict set regsC100 TIMER3_CTRL [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x28] dict set regsC100 TIMER3_CURR_COUNT [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x2C] dict set regsC100 TIMER_MASK [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x40] dict set regsC100 TIMER_STATUS [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x50] dict set regsC100 TIMER_ACK [expr [dict get $regsC100 TIMER_BASEADDR ] + 0x50] dict set regsC100 TIMER_WDT_HIGH_BOUND [expr [dict get $regsC100 TIMER_BASEADDR ] + 0xD0] dict set regsC100 TIMER_WDT_CONTROL [expr [dict get $regsC100 TIMER_BASEADDR ] + 0xD4] dict set regsC100 TIMER_WDT_CURRENT_COUNT [expr [dict get $regsC100 TIMER_BASEADDR ] + 0xD8] #//////////////////////////////////////////////////////////// #// EBUS block #//////////////////////////////////////////////////////////// dict set regsC100 EX_SWRST_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x00] dict set regsC100 EX_CSEN_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x04] dict set regsC100 EX_CS0_SEG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x08] dict set regsC100 EX_CS1_SEG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x0C] dict set regsC100 EX_CS2_SEG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x10] dict set regsC100 EX_CS3_SEG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x14] dict set regsC100 EX_CS4_SEG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x18] dict set regsC100 EX_CS0_CFG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x1C] dict set regsC100 EX_CS1_CFG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x20] dict set regsC100 EX_CS2_CFG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x24] dict set regsC100 EX_CS3_CFG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x28] dict set regsC100 EX_CS4_CFG_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x2C] dict set regsC100 EX_CS0_TMG1_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x30] dict set regsC100 EX_CS1_TMG1_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x34] dict set regsC100 EX_CS2_TMG1_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x38] dict set regsC100 EX_CS3_TMG1_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x3C] dict set regsC100 EX_CS4_TMG1_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x40] dict set regsC100 EX_CS0_TMG2_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x44] dict set regsC100 EX_CS1_TMG2_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x48] dict set regsC100 EX_CS2_TMG2_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x4C] dict set regsC100 EX_CS3_TMG2_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x50] dict set regsC100 EX_CS4_TMG2_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x54] dict set regsC100 EX_CS0_TMG3_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x58] dict set regsC100 EX_CS1_TMG3_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x5C] dict set regsC100 EX_CS2_TMG3_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x60] dict set regsC100 EX_CS3_TMG3_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x64] dict set regsC100 EX_CS4_TMG3_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x68] dict set regsC100 EX_CLOCK_DIV_REG [expr [dict get $regsC100 EBUS_BASEADDR ] + 0x6C] dict set regsC100 EX_MFSM_REG [expr [dict get $regsC100 EBUS_BASEADDR] + 0x100] dict set regsC100 EX_MFSM_REG [expr [dict get $regsC100 EBUS_BASEADDR] + 0x100] dict set regsC100 EX_CSFSM_REG [expr [dict get $regsC100 EBUS_BASEADDR] + 0x104] dict set regsC100 EX_WRFSM_REG [expr [dict get $regsC100 EBUS_BASEADDR] + 0x108] dict set regsC100 EX_RDFSM_REG [expr [dict get $regsC100 EBUS_BASEADDR] + 0x10C] dict set regsC100 EX_CLK_EN 0x00000001 dict set regsC100 EX_CSBOOT_EN 0x00000002 dict set regsC100 EX_CS0_EN 0x00000002 dict set regsC100 EX_CS1_EN 0x00000004 dict set regsC100 EX_CS2_EN 0x00000008 dict set regsC100 EX_CS3_EN 0x00000010 dict set regsC100 EX_CS4_EN 0x00000020 dict set regsC100 EX_MEM_BUS_8 0x00000000 dict set regsC100 EX_MEM_BUS_16 0x00000002 dict set regsC100 EX_MEM_BUS_32 0x00000004 dict set regsC100 EX_CS_HIGH 0x00000008 dict set regsC100 EX_WE_HIGH 0x00000010 dict set regsC100 EX_RE_HIGH 0x00000020 dict set regsC100 EX_ALE_MODE 0x00000040 dict set regsC100 EX_STRB_MODE 0x00000080 dict set regsC100 EX_DM_MODE 0x00000100 dict set regsC100 EX_NAND_MODE 0x00000200 dict set regsC100 EX_RDY_EN 0x00000400 dict set regsC100 EX_RDY_EDGE 0x00000800 #//////////////////////////////////////////////////////////// #// GPIO block #//////////////////////////////////////////////////////////// # GPIO outputs register dict set regsC100 GPIO_OUTPUT_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x00] # GPIO Output Enable register dict set regsC100 GPIO_OE_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x04] dict set regsC100 GPIO_HI_INT_ENABLE_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x08] dict set regsC100 GPIO_LO_INT_ENABLE_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x0C] # GPIO input register dict set regsC100 GPIO_INPUT_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x10] dict set regsC100 APB_ACCESS_WS_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x14] dict set regsC100 MUX_CONF_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x18] dict set regsC100 SYSCONF_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x1C] dict set regsC100 GPIO_ARM_ID_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x30] dict set regsC100 GPIO_BOOTSTRAP_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x40] dict set regsC100 GPIO_LOCK_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x38] dict set regsC100 GPIO_IOCTRL_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x44] dict set regsC100 GPIO_DEVID_REG [expr [dict get $regsC100 GPIO_BASEADDR ] + 0x50] dict set regsC100 GPIO_IOCTRL_A15A16 0x00000001 dict set regsC100 GPIO_IOCTRL_A17A18 0x00000002 dict set regsC100 GPIO_IOCTRL_A19A21 0x00000004 dict set regsC100 GPIO_IOCTRL_TMREVT0 0x00000008 dict set regsC100 GPIO_IOCTRL_TMREVT1 0x00000010 dict set regsC100 GPIO_IOCTRL_GPBT3 0x00000020 dict set regsC100 GPIO_IOCTRL_I2C 0x00000040 dict set regsC100 GPIO_IOCTRL_UART0 0x00000080 dict set regsC100 GPIO_IOCTRL_UART1 0x00000100 dict set regsC100 GPIO_IOCTRL_SPI 0x00000200 dict set regsC100 GPIO_IOCTRL_HBMODE 0x00000400 dict set regsC100 GPIO_IOCTRL_VAL 0x55555555 dict set regsC100 GPIO_0 0x01 dict set regsC100 GPIO_1 0x02 dict set regsC100 GPIO_2 0x04 dict set regsC100 GPIO_3 0x08 dict set regsC100 GPIO_4 0x10 dict set regsC100 GPIO_5 0x20 dict set regsC100 GPIO_6 0x40 dict set regsC100 GPIO_7 0x80 dict set regsC100 GPIO_RISING_EDGE 1 dict set regsC100 GPIO_FALLING_EDGE 2 dict set regsC100 GPIO_BOTH_EDGES 3 #//////////////////////////////////////////////////////////// #// UART #//////////////////////////////////////////////////////////// dict set regsC100 UART0_RBR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x00] dict set regsC100 UART0_THR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x00] dict set regsC100 UART0_DLL [expr [dict get $regsC100 UART0_BASEADDR ] + 0x00] dict set regsC100 UART0_IER [expr [dict get $regsC100 UART0_BASEADDR ] + 0x04] dict set regsC100 UART0_DLH [expr [dict get $regsC100 UART0_BASEADDR ] + 0x04] dict set regsC100 UART0_IIR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x08] dict set regsC100 UART0_FCR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x08] dict set regsC100 UART0_LCR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x0C] dict set regsC100 UART0_MCR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x10] dict set regsC100 UART0_LSR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x14] dict set regsC100 UART0_MSR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x18] dict set regsC100 UART0_SCR [expr [dict get $regsC100 UART0_BASEADDR ] + 0x1C] dict set regsC100 UART1_RBR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x00] dict set regsC100 UART1_THR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x00] dict set regsC100 UART1_DLL [expr [dict get $regsC100 UART1_BASEADDR ] + 0x00] dict set regsC100 UART1_IER [expr [dict get $regsC100 UART1_BASEADDR ] + 0x04] dict set regsC100 UART1_DLH [expr [dict get $regsC100 UART1_BASEADDR ] + 0x04] dict set regsC100 UART1_IIR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x08] dict set regsC100 UART1_FCR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x08] dict set regsC100 UART1_LCR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x0C] dict set regsC100 UART1_MCR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x10] dict set regsC100 UART1_LSR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x14] dict set regsC100 UART1_MSR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x18] dict set regsC100 UART1_SCR [expr [dict get $regsC100 UART1_BASEADDR ] + 0x1C] # /* default */ dict set regsC100 LCR_CHAR_LEN_5 0x00 dict set regsC100 LCR_CHAR_LEN_6 0x01 dict set regsC100 LCR_CHAR_LEN_7 0x02 dict set regsC100 LCR_CHAR_LEN_8 0x03 #/* One stop bit! - default */ dict set regsC100 LCR_ONE_STOP 0x00 #/* Two stop bit! */ dict set regsC100 LCR_TWO_STOP 0x04 #/* Parity Enable */ dict set regsC100 LCR_PEN 0x08 dict set regsC100 LCR_PARITY_NONE 0x00 #/* Even Parity Select */ dict set regsC100 LCR_EPS 0x10 #/* Enable Parity Stuff */ dict set regsC100 LCR_PS 0x20 #/* Start Break */ dict set regsC100 LCR_SBRK 0x40 #/* Parity Stuff Bit */ dict set regsC100 LCR_PSB 0x80 #/* UART 16550 Divisor Latch Assess */ dict set regsC100 LCR_DLAB 0x80 #/* FIFO Error Status */ dict set regsC100 LSR_FIFOE [expr 1 << 7] #/* Transmitter Empty */ dict set regsC100 LSR_TEMT [expr 1 << 6] #/* Transmit Data Request */ dict set regsC100 LSR_TDRQ [expr 1 << 5] #/* Break Interrupt */ dict set regsC100 LSR_BI [expr 1 << 4] #/* Framing Error */ dict set regsC100 LSR_FE [expr 1 << 3] #/* Parity Error */ dict set regsC100 LSR_PE [expr 1 << 2] #/* Overrun Error */ dict set regsC100 LSR_OE [expr 1 << 1] #/* Data Ready */ dict set regsC100 LSR_DR [expr 1 << 0] #/* DMA Requests Enable */ dict set regsC100 IER_DMAE [expr 1 << 7] #/* UART Unit Enable */ dict set regsC100 IER_UUE [expr 1 << 6] #/* NRZ coding Enable */ dict set regsC100 IER_NRZE [expr 1 << 5] #/* Receiver Time Out Interrupt Enable */ dict set regsC100 IER_RTIOE [expr 1 << 4] #/* Modem Interrupt Enable */ dict set regsC100 IER_MIE [expr 1 << 3] #/* Receiver Line Status Interrupt Enable */ dict set regsC100 IER_RLSE [expr 1 << 2] #/* Transmit Data request Interrupt Enable */ dict set regsC100 IER_TIE [expr 1 << 1] #/* Receiver Data Available Interrupt Enable */ dict set regsC100 IER_RAVIE [expr 1 << 0] #/* FIFO Mode Enable Status */ dict set regsC100 IIR_FIFOES1 [expr 1 << 7] #/* FIFO Mode Enable Status */ dict set regsC100 IIR_FIFOES0 [expr 1 << 6] #/* Time Out Detected */ dict set regsC100 IIR_TOD [expr 1 << 3] #/* Interrupt Source Encoded */ dict set regsC100 IIR_IID2 [expr 1 << 2] #/* Interrupt Source Encoded */ dict set regsC100 IIR_IID1 [expr 1 << 1] #/* Interrupt Pending (active low) */ dict set regsC100 IIR_IP [expr 1 << 0] #/* UART 16550 FIFO Control Register */ dict set regsC100 FCR_FIFOEN 0x01 dict set regsC100 FCR_RCVRRES 0x02 dict set regsC100 FCR_XMITRES 0x04 #/* Interrupt Enable Register */ #// UART 16550 #// Enable Received Data Available Interrupt dict set regsC100 IER_RXTH 0x01 #// Enable Transmitter Empty Interrupt dict set regsC100 IER_TXTH 0x02 #//////////////////////////////////////////////////////////// #// CLK + RESET block #//////////////////////////////////////////////////////////// dict set regsC100 CLKCORE_ARM_CLK_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x00] dict set regsC100 CLKCORE_AHB_CLK_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x04] dict set regsC100 CLKCORE_PLL_STATUS [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x08] dict set regsC100 CLKCORE_CLKDIV_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x0C] dict set regsC100 CLKCORE_TDM_CLK_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x10] dict set regsC100 CLKCORE_FSYNC_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x14] dict set regsC100 CLKCORE_CLK_PWR_DWN [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x18] dict set regsC100 CLKCORE_RNG_CNTRL [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x1C] dict set regsC100 CLKCORE_RNG_STATUS [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x20] dict set regsC100 CLKCORE_ARM_CLK_CNTRL2 [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x24] dict set regsC100 CLKCORE_TDM_REF_DIV_RST [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x40] dict set regsC100 ARM_PLL_BY_CTRL 0x80000000 dict set regsC100 ARM_AHB_BYP 0x04000000 dict set regsC100 PLL_DISABLE 0x02000000 dict set regsC100 PLL_CLK_BYPASS 0x01000000 dict set regsC100 AHB_PLL_BY_CTRL 0x80000000 dict set regsC100 DIV_BYPASS 0x40000000 dict set regsC100 SYNC_MODE 0x20000000 dict set regsC100 EPHY_CLKDIV_BYPASS 0x00200000 dict set regsC100 EPHY_CLKDIV_RATIO_SHIFT 16 dict set regsC100 PUI_CLKDIV_BYPASS 0x00004000 dict set regsC100 PUI_CLKDIV_SRCCLK 0x00002000 dict set regsC100 PUI_CLKDIV_RATIO_SHIFT 8 dict set regsC100 PCI_CLKDIV_BYPASS 0x00000020 dict set regsC100 PCI_CLKDIV_RATIO_SHIFT 0 dict set regsC100 ARM0_CLK_PD 0x00200000 dict set regsC100 ARM1_CLK_PD 0x00100000 dict set regsC100 EPHY_CLK_PD 0x00080000 dict set regsC100 TDM_CLK_PD 0x00040000 dict set regsC100 PUI_CLK_PD 0x00020000 dict set regsC100 PCI_CLK_PD 0x00010000 dict set regsC100 MDMA_AHBCLK_PD 0x00000400 dict set regsC100 I2CSPI_AHBCLK_PD 0x00000200 dict set regsC100 UART_AHBCLK_PD 0x00000100 dict set regsC100 IPSEC_AHBCLK_PD 0x00000080 dict set regsC100 TDM_AHBCLK_PD 0x00000040 dict set regsC100 USB1_AHBCLK_PD 0x00000020 dict set regsC100 USB0_AHBCLK_PD 0x00000010 dict set regsC100 GEMAC1_AHBCLK_PD 0x00000008 dict set regsC100 GEMAC0_AHBCLK_PD 0x00000004 dict set regsC100 PUI_AHBCLK_PD 0x00000002 dict set regsC100 HIF_AHBCLK_PD 0x00000001 dict set regsC100 ARM1_DIV_BP 0x00001000 dict set regsC100 ARM1_DIV_VAL_SHIFT 8 dict set regsC100 ARM0_DIV_BP 0x00000010 dict set regsC100 ARM0_DIV_VAL_SHIFT 0 dict set regsC100 AHBCLK_PLL_LOCK 0x00000002 dict set regsC100 FCLK_PLL_LOCK 0x00000001 #// reset block dict set regsC100 BLOCK_RESET_REG [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x100] dict set regsC100 CSP_RESET_REG [expr [dict get $regsC100 CLKCORE_BASEADDR ] + 0x104] dict set regsC100 RNG_RST 0x1000 dict set regsC100 IPSEC_RST 0x0800 dict set regsC100 DDR_RST 0x0400 dict set regsC100 USB1_PHY_RST 0x0200 dict set regsC100 USB0_PHY_RST 0x0100 dict set regsC100 USB1_RST 0x0080 dict set regsC100 USB0_RST 0x0040 dict set regsC100 GEMAC1_RST 0x0020 dict set regsC100 GEMAC0_RST 0x0010 dict set regsC100 TDM_RST 0x0008 dict set regsC100 PUI_RST 0x0004 dict set regsC100 HIF_RST 0x0002 dict set regsC100 PCI_RST 0x0001 #//////////////////////////////////////////////////////////////// #// DDR CONTROLLER block #//////////////////////////////////////////////////////////////// dict set regsC100 DDR_CONFIG_BASEADDR 0x0D000000 dict set regsC100 DENALI_CTL_00_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x00] dict set regsC100 DENALI_CTL_01_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x08] dict set regsC100 DENALI_CTL_02_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x10] dict set regsC100 DENALI_CTL_03_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x18] dict set regsC100 DENALI_CTL_04_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x20] dict set regsC100 DENALI_CTL_05_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x28] dict set regsC100 DENALI_CTL_06_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x30] dict set regsC100 DENALI_CTL_07_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x38] dict set regsC100 DENALI_CTL_08_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x40] dict set regsC100 DENALI_CTL_09_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x48] dict set regsC100 DENALI_CTL_10_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x50] dict set regsC100 DENALI_CTL_11_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x58] dict set regsC100 DENALI_CTL_12_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x60] dict set regsC100 DENALI_CTL_13_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x68] dict set regsC100 DENALI_CTL_14_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x70] dict set regsC100 DENALI_CTL_15_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x78] dict set regsC100 DENALI_CTL_16_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x80] dict set regsC100 DENALI_CTL_17_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x88] dict set regsC100 DENALI_CTL_18_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x90] dict set regsC100 DENALI_CTL_19_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x98] dict set regsC100 DENALI_CTL_20_DATA [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0xA0] # 32-bit value dict set regsC100 DENALI_READY_CHECK [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x44] # 8-bit dict set regsC100 DENALI_WR_DQS [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x5D] # 8-bit dict set regsC100 DENALI_DQS_OUT [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x5A] # 8-bit dict set regsC100 DENALI_DQS_DELAY0 [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] + 0x4F] # 8-bit dict set regsC100 DENALI_DQS_DELAY1 [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] +0x50] # 8-bit dict set regsC100 DENALI_DQS_DELAY2 [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] +0x51] # 8-bit dict set regsC100 DENALI_DQS_DELAY3 [expr [dict get $regsC100 DDR_CONFIG_BASEADDR ] +0x52] # end of proc regsC100 } openocd-0.9.0/tcl/target/k60.cfg0000644000175000017500000000012212526202244013213 00000000000000# # Freescale Kinetis K60 devices # set CHIPNAME k60 source [find target/kx.cfg] openocd-0.9.0/tcl/target/lpc17xx.cfg0000644000175000017500000000027512526202244014132 00000000000000# NXP LPC17xx Cortex-M3 with at least 8kB SRAM set CHIPNAME lpc17xx set CHIPSERIES lpc1700 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x2000 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/fm3.cfg0000644000175000017500000000222412526202244013305 00000000000000# MB9BF506 # Fujitsu Cortex-M3 with 512kB Flash and 64kB RAM source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME mb9bfxx6 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } # delays on reset lines adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } # Fujitsu cortex-M3 reset configuration reset_config trst_only swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME # MB9BF506 has 64kB of SRAM on its main system bus $_TARGETNAME configure -work-area-phys 0x1FFF8000 -work-area-size 0x10000 -work-area-backup 0 # MB9BF506 has 512kB internal FLASH set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME fm3 0 0 0 0 $_TARGETNAME # 4MHz / 6 = 666kHz, so use 500 adapter_khz 500 if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/fm4.cfg0000644000175000017500000000076512526202244013316 00000000000000# # Spansion FM4 (ARM Cortex-M4) # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME fm4 } source [find target/swj-dp.tcl] if { [info exists CPUTAPID] } { set _CPU_TAPID $CPUTAPID } else { set _CPU_TAPID 0x2ba01477 } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPU_TAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian little -chain-position $_TARGETNAME adapter_khz 500 if {![using_hla]} { cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/samsung_s3c6410.cfg0000644000175000017500000000246612526202244015370 00000000000000# -*- tcl -*- # Target configuration for the Samsung s3c6410 system on chip # Tested on a SMDK6410 # Processor : ARM1176 # Info: JTAG device found: 0x0032409d (Manufacturer: 0x04e, Part: 0x0324, Version: 0x0) # [Duane Ellis 27/nov/2008: Above 0x0032409d appears to be copy/paste from other places] # [and I do not believe it to be accurate, hence the 0xffffffff below] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c6410 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN little } # trace buffer if { [info exists ETBTAPID] } { set _ETBTAPID $ETBTAPID } else { set _ETBTAPID 0x2b900f0f } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07b76f0f } #jtag scan chain jtag newtap $_CHIPNAME etb -irlen 4 -expected-id $_ETBTAPID jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME adapter_nsrst_delay 500 jtag_ntrst_delay 500 #reset configuration reset_config trst_and_srst # trace setup ... NOTE, "normal full" mode fudges the real ETMv3.1 mode etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/dsp56321.cfg0000644000175000017500000000133112526202244014005 00000000000000# Script for freescale DSP56321 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dsp56321 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a big endian set _ENDIAN big } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1181501d } #jtag speed adapter_khz 4500 #has only srst reset_config srst_only #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 1 -irmask 0x1 -expected-id $_CPUTAPID #target configuration set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME dsp563xx -endian $_ENDIAN -chain-position $_TARGETNAME #working area at base of ram $_TARGETNAME configure -work-area-virt 0 openocd-0.9.0/tcl/target/cs351x.cfg0000644000175000017500000000143212526202244013646 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cs351x } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x00526fa1 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Create the GDB Target. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME fa526 -endian $_ENDIAN -chain-position $_TARGETNAME # There is 16K of SRAM on this chip # FIXME: flash programming is not working by using this work area. So comment this out for now. #$_TARGETNAME configure -work-area-phys 0x00000000 -work-area-size 0x4000 -work-area-backup 1 # This chip has a DCC ... use it arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/omap4430.cfg0000644000175000017500000000630712526202244014075 00000000000000# OMAP4430 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omap4430 } # Although the OMAP4430 supposedly has an ICEpick-D, only the # ICEpick-C router commands seem to work. # See http://processors.wiki.ti.com/index.php/ICEPICK source [find target/icepick.cfg] # # A9 DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x3BA00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 9" # # M3 DAPs, one per core # if { [info exists M3_DAP_TAPID] } { set _M3_DAP_TAPID $M3_DAP_TAPID } else { set _M3_DAP_TAPID 0x4BA00477 } jtag newtap $_CHIPNAME m31_dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M3_DAP_TAPID -disable jtag configure $_CHIPNAME.m31_dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 5" jtag newtap $_CHIPNAME m30_dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M3_DAP_TAPID -disable jtag configure $_CHIPNAME.m30_dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 4" # # ICEpick-D JRC (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x3b95c02f set _JRC_TAPID2 0x1b85202f } # PandaBoard REV EA1 (PEAP platforms) if { [info exists JRC_TAPID2] } { set _JRC_TAPID2 $JRC_TAPID2 } else { set _JRC_TAPID2 0x1b85202f } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \ -expected-id $_JRC_TAPID -expected-id $_JRC_TAPID2 # Required by ICEpick to power-up the debug domain jtag configure $_CHIPNAME.jrc -event post-reset "runtest 200" # # GDB target: Cortex-A9, using DAP # # The debugger can connect to either core of the A9, but currently # not both simultaneously. Change -coreid to 1 to connect to the # second core. # set _TARGETNAME $_CHIPNAME.cpu # APB DBGBASE reads 0x80040000, but this points to an empty ROM table. # 0x80000000 is cpu0 coresight region # # # CORTEX_A8_PADDRDBG_CPU_SHIFT 13 # 0x80000000 | (coreid << CORTEX_A8_PADDRDBG_CPU_SHIFT) set _coreid 0 set _dbgbase [expr 0x80000000 | ($_coreid << 13)] echo "Using dbgbase = [format 0x%x $_dbgbase]" target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase $_dbgbase # SRAM: 56KiB at 0x4030.0000 $_TARGETNAME configure -work-area-phys 0x40300000 -work-area-size 0x1000 # # M3 targets, separate TAP/DAP for each core # target create $_CHIPNAME.m30 cortex_m -chain-position $_CHIPNAME.m30_dap target create $_CHIPNAME.m31 cortex_m -chain-position $_CHIPNAME.m31_dap # Once the JRC is up, enable our TAPs jtag configure $_CHIPNAME.jrc -event setup " jtag tapenable $_CHIPNAME.dap jtag tapenable $_CHIPNAME.m30_dap jtag tapenable $_CHIPNAME.m31_dap " # Assume SRST is unavailable (e.g. TI-14 JTAG), so we must assert reset # ourselves using PRM_RSTCTRL. 1 is a warm reset, 2 a cold reset. set PRM_RSTCTRL 0x4A307B00 $_TARGETNAME configure -event reset-assert "$_TARGETNAME mww phys $PRM_RSTCTRL 0x1" $_CHIPNAME.m30 configure -event reset-assert { } $_CHIPNAME.m31 configure -event reset-assert { } # Soft breakpoints don't currently work due to broken cache handling gdb_breakpoint_override hard openocd-0.9.0/tcl/target/stm32f0x.cfg0000644000175000017500000000241512526202244014210 00000000000000# script for stm32f0x family # # stm32 devices support SWD transports only. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32f0x } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # See STM Document RM0091 # Section 29.5.3 set _CPUTAPID 0x0bb11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # flash size will be probed set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME # adapter speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 adapter_nsrst_delay 100 reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/efm32_stlink.cfg0000644000175000017500000000017012526202244015116 00000000000000echo "WARNING: target/efm32_stlink.cfg is deprecated, please switch to target/efm32.cfg" source [find target/efm32.cfg] openocd-0.9.0/tcl/target/ixp42x.cfg0000644000175000017500000000635112526202244013763 00000000000000#xscale ixp42x CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME ixp42x } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a bigendian set _ENDIAN big } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x19274013 } set _CPUTAPID2 0x19275013 set _CPUTAPID3 0x19277013 set _CPUTAPID4 0x29274013 set _CPUTAPID5 0x29275013 set _CPUTAPID6 0x29277013 jtag newtap $_CHIPNAME cpu -irlen 7 -ircapture 0x1 -irmask 0x7f -expected-id $_CPUTAPID -expected-id $_CPUTAPID2 -expected-id $_CPUTAPID3 -expected-id $_CPUTAPID4 -expected-id $_CPUTAPID5 -expected-id $_CPUTAPID6 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME xscale -endian $_ENDIAN -chain-position $_TARGETNAME # register constants for IXP42x SDRAM controller global IXP425_SDRAM_IR_MODE_SET_CAS2_CMD global IXP425_SDRAM_IR_MODE_SET_CAS3_CMD set IXP425_SDRAM_IR_MODE_SET_CAS2_CMD 0x0000 set IXP425_SDRAM_IR_MODE_SET_CAS3_CMD 0x0001 global IXP42x_SDRAM_CL3 global IXP42x_SDRAM_CL2 set IXP42x_SDRAM_CL3 0x0008 set IXP42x_SDRAM_CL2 0x0000 global IXP42x_SDRAM_8MB_2Mx32_1BANK global IXP42x_SDRAM_16MB_2Mx32_2BANK global IXP42x_SDRAM_16MB_4Mx16_1BANK global IXP42x_SDRAM_32MB_4Mx16_2BANK global IXP42x_SDRAM_32MB_8Mx16_1BANK global IXP42x_SDRAM_64MB_8Mx16_2BANK global IXP42x_SDRAM_64MB_16Mx16_1BANK global IXP42x_SDRAM_128MB_16Mx16_2BANK global IXP42x_SDRAM_128MB_32Mx16_1BANK global IXP42x_SDRAM_256MB_32Mx16_2BANK set IXP42x_SDRAM_8MB_2Mx32_1BANK 0x0030 set IXP42x_SDRAM_16MB_2Mx32_2BANK 0x0031 set IXP42x_SDRAM_16MB_4Mx16_1BANK 0x0032 set IXP42x_SDRAM_32MB_4Mx16_2BANK 0x0033 set IXP42x_SDRAM_32MB_8Mx16_1BANK 0x0010 set IXP42x_SDRAM_64MB_8Mx16_2BANK 0x0011 set IXP42x_SDRAM_64MB_16Mx16_1BANK 0x0012 set IXP42x_SDRAM_128MB_16Mx16_2BANK 0x0013 set IXP42x_SDRAM_128MB_32Mx16_1BANK 0x0014 set IXP42x_SDRAM_256MB_32Mx16_2BANK 0x0015 # helper function to init SDRAM on IXP42x. # SDRAM_CFG: one of IXP42X_SDRAM_xxx # REFRESH: refresh counter reload value (integer) # CASLAT: 2 or 3 proc ixp42x_init_sdram { SDRAM_CFG REFRESH CASLAT } { switch $CASLAT { 2 { set SDRAM_CFG [expr $SDRAM_CFG | $::IXP42x_SDRAM_CL2 ] set CASCMD $::IXP425_SDRAM_IR_MODE_SET_CAS2_CMD } 3 { set SDRAM_CFG [expr $SDRAM_CFG | $::IXP42x_SDRAM_CL3 ] set CASCMD $::IXP425_SDRAM_IR_MODE_SET_CAS3_CMD } default { error [format "unsupported cas latency \"%s\" " $CASLAT] } } echo [format "\tIXP42x SDRAM Config: 0x%x, Refresh %d " $SDRAM_CFG $REFRESH] mww 0xCC000000 $SDRAM_CFG ;# SDRAM_CFG: 0x2A: 64MBit, CL3 mww 0xCC000004 0 ;# disable refresh mww 0xCC000008 3 ;# NOP sleep 100 mww 0xCC000004 $REFRESH ;# set refresh counter mww 0xCC000008 2 ;# Precharge All Banks sleep 100 mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 4 ;# Auto Refresh mww 0xCC000008 $CASCMD ;# Mode Select CL2/CL3 } proc ixp42x_set_bigendian { } { reg XSCALE_CTRL 0xF8 } openocd-0.9.0/tcl/target/is5114.cfg0000644000175000017500000000236212526202244013551 00000000000000# script for Insilica IS-5114 # AKA: Atmel AT76C114 - an ARM946 chip # ATMEL sold his product line to Insilica... if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME is5114 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a little endian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # Force an error until we get a good number. set _CPUTAPID 0xffffffff } # jtag speed. We need to stick to 16kHz until we've finished reset. adapter_khz 16 reset_config trst_and_srst # Do not specify a tap id here... jtag newtap $_CHIPNAME unknown1 -irlen 8 -ircapture 0x01 -irmask 1 # This is the "arm946" chip. jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x0e -irmask 0xf jtag newtap $_CHIPNAME unknown2 -irlen 5 -ircapture 1 -irmask 1 #arm946e-s and set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-start { adapter_khz 16 } $_TARGETNAME configure -event reset-init { # We can increase speed now that we know the target is halted. adapter_khz 3000 } $_TARGETNAME configure -work-area-phys 0x50000000 -work-area-size 16384 -work-area-backup 1 openocd-0.9.0/tcl/target/stm32f1x.cfg0000644000175000017500000000560012526202244014210 00000000000000# script for stm32f1x family # # stm32 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32f1x } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 4kB (as found on some STM32F100s) if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { # See STM Document RM0008 Section 26.6.3 set _CPUTAPID 0x3ba00477 } { # this is the SW-DP tap id not the jtag tap id set _CPUTAPID 0x1ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { # FIXME this never gets used to override defaults... set _BSTAPID $BSTAPID } else { # See STM Document RM0008 # Section 29.6.2 # Low density devices, Rev A set _BSTAPID1 0x06412041 # Medium density devices, Rev A set _BSTAPID2 0x06410041 # Medium density devices, Rev B and Rev Z set _BSTAPID3 0x16410041 set _BSTAPID4 0x06420041 # High density devices, Rev A set _BSTAPID5 0x06414041 # Connectivity line devices, Rev A and Rev Z set _BSTAPID6 0x06418041 # XL line devices, Rev A set _BSTAPID7 0x06430041 # VL line devices, Rev A and Z In medium-density and high-density value line devices set _BSTAPID8 0x06420041 # VL line devices, Rev A set _BSTAPID9 0x06428041 } if {[using_jtag]} { swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \ -expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \ -expected-id $_BSTAPID8 -expected-id $_BSTAPID9 } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # flash size will be probed set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } $_TARGETNAME configure -event examine-end { # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP | # DBG_STANDBY | DBG_STOP | DBG_SLEEP mmw 0xE0042004 0x00000307 0 } $_TARGETNAME configure -event trace-config { # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync # change this value accordingly to configure trace pins # assignment mmw 0xE0042004 0x00000020 0 } openocd-0.9.0/tcl/target/stm32f2x.cfg0000644000175000017500000000455212526202244014216 00000000000000# script for stm32f2x family # # stm32 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32f2x } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 64kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x10000 } # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { # See STM Document RM0033 # Section 32.6.3 - corresponds to Cortex-M3 r2p0 set _CPUTAPID 0x4ba00477 } { set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { # See STM Document RM0033 # Section 32.6.2 # set _BSTAPID 0x06411041 } if {[using_jtag]} { swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } $_TARGETNAME configure -event examine-end { # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP mmw 0xE0042004 0x00000007 0 # Stop watchdog counters during halt # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP mww 0xE0042008 0x00001800 } $_TARGETNAME configure -event trace-config { # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync # change this value accordingly to configure trace pins # assignment mmw 0xE0042004 0x00000020 0 } openocd-0.9.0/tcl/target/stm32f1x_stlink.cfg0000644000175000017500000000020112526202244015564 00000000000000echo "WARNING: target/stm32f1x_stlink.cfg is deprecated, please switch to target/stm32f1x.cfg" source [find target/stm32f1x.cfg] openocd-0.9.0/tcl/target/lpc2xxx.cfg0000644000175000017500000000371512526202244014236 00000000000000# Common setup for the LPC2xxx parts # parameters: # - chip_name - name of the chip, e.g. lpc2103 # - cputapids - TAP IDs of the core, should be quoted if more than one, e.g. 0x4f1f0f0f or "0x3f0f0f0f 0x4f1f0f0f" # - flash_size - size of on-chip flash (available for code, not including the bootloader) in bytes, e.g. 0x8000 # - flash_variant - "type" of LPC2xxx device, lpc2000_v1 (LPC22xx and older LPC21xx) or lpc2000_v2 (LPC213x, LPC214x, LPC210[123], LPC23xx and LPC24xx) # - workarea_size - size of work-area in RAM for flashing procedures, must not exceed the size of RAM available at 0x40000000, e.g. 0x2000 # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2xxx {chip_name cputapids flash_size flash_variant workarea_size core_freq_khz adapter_freq_khz} { reset_config trst_and_srst # reset delays adapter_nsrst_delay 100 jtag_ntrst_delay 100 adapter_khz $adapter_freq_khz foreach i $cputapids { append expected_ids "-expected-id " $i " " } eval "jtag newtap $chip_name cpu -irlen 4 -ircapture 0x1 -irmask 0xf $expected_ids" global _TARGETNAME set _TARGETNAME $chip_name.cpu target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size $workarea_size -work-area-backup 0 if { $flash_size > 0 } { # flash bank lpc2000 0 0 [calc checksum] set _FLASHNAME $chip_name.flash flash bank $_FLASHNAME lpc2000 0x0 $flash_size 0 0 $_TARGETNAME $flash_variant $core_freq_khz calc_checksum } } proc init_targets {} { # FIX!!! read out CPUTAPID here and choose right setup. In addition to the # CPUTAPID some querying of the target would be required. return -error "This is a generic LPC2xxx configuration file, use a specific target file." } openocd-0.9.0/tcl/target/ti-ar7.cfg0000644000175000017500000000124512526202244013725 00000000000000# # Texas Instruments AR7 SOC - used in many adsl modems. # http://www.linux-mips.org/wiki/AR7 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME ti-ar7 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0000100f } jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian $_ENDIAN -chain-position $_CHIPNAME.cpu # use onboard 4k sram as working area $_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 0x00001000 openocd-0.9.0/tcl/target/at91sam3nXX.cfg0000644000175000017500000000126112526202244014620 00000000000000 # # Configuration for Atmel's SAM3N series # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91sam3n } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian little -chain-position $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash flash bank flash0 at91sam3 0x00400000 0 0 0 $_TARGETNAME if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/at91sam9g10.cfg0000644000175000017500000000076112526202244014504 00000000000000###################################### # Target: Atmel AT91SAM9G10 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9g10 } source [find target/at91sam9.cfg] # Establish internal SRAM memory work areas that are important to pre-bootstrap loaders, etc. The # AT91SAM9G10 has one SRAM area at 0x00300000 of 16KiB $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x4000 -work-area-backup 1 openocd-0.9.0/tcl/target/m051.cfg0000644000175000017500000000311212526202244013277 00000000000000# script for nuvoton M051 family transport select hla_swd source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME m051 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # See STM Document RM0091 # Section 29.5.3 set _CPUTAPID 0x0bb11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # flash size will be probed set _FLASHNAME $_CHIPNAME.flash_aprom flash bank $_FLASHNAME mini51 0x00000000 0x4000 0 0 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash_data flash bank $_FLASHNAME mini51 0x0001F000 0x1000 0 0 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash_ldrom flash bank $_FLASHNAME mini51 0x00100000 0x1000 0 0 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash_conf flash bank $_FLASHNAME mini51 0x00300000 0x0100 0 0 $_TARGETNAME # adapter speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 adapter_nsrst_delay 100 if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/omap4460.cfg0000644000175000017500000000630512526202244014076 00000000000000# OMAP4460 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omap4460 } # Although the OMAP4430 supposedly has an ICEpick-D, only the # ICEpick-C router commands seem to work. # See http://processors.wiki.ti.com/index.php/ICEPICK source [find target/icepick.cfg] # # A9 DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x3BA00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 9" # # M3 DAPs, one per core # if { [info exists M3_DAP_TAPID] } { set _M3_DAP_TAPID $M3_DAP_TAPID } else { set _M3_DAP_TAPID 0x4BA00477 } jtag newtap $_CHIPNAME m31_dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M3_DAP_TAPID -disable jtag configure $_CHIPNAME.m31_dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 5" jtag newtap $_CHIPNAME m30_dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M3_DAP_TAPID -disable jtag configure $_CHIPNAME.m30_dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 4" # # ICEpick-D JRC (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x2b94e02f set _JRC_TAPID2 0x1b85202f } # PandaBoard REV EA1 (PEAP platforms) if { [info exists JRC_TAPID2] } { set _JRC_TAPID2 $JRC_TAPID2 } else { set _JRC_TAPID2 0x1b85202f } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \ -expected-id $_JRC_TAPID -expected-id $_JRC_TAPID2 # Required by ICEpick to power-up the debug domain jtag configure $_CHIPNAME.jrc -event post-reset "runtest 200" # # GDB target: Cortex-A9, using DAP # # The debugger can connect to either core of the A9, but currently # not both simultaneously. Change -coreid to 1 to connect to the # second core. # set _TARGETNAME $_CHIPNAME.cpu # APB DBGBASE reads 0x80040000, but this points to an empty ROM table. # 0x80000000 is cpu0 coresight region # # # CORTEX_A8_PADDRDBG_CPU_SHIFT 13 # 0x80000000 | (coreid << CORTEX_A8_PADDRDBG_CPU_SHIFT) set _coreid 0 set _dbgbase [expr 0x80000000 | ($_coreid << 13)] echo "Using dbgbase = [format 0x%x $_dbgbase]" target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase $_dbgbase # SRAM: 56KiB at 0x4030.0000 $_TARGETNAME configure -work-area-phys 0x40300000 -work-area-size 0x1000 # # M3 targets, separate TAP/DAP for each core # target create $_CHIPNAME.m30 cortex_m -chain-position $_CHIPNAME.m30_dap target create $_CHIPNAME.m31 cortex_m -chain-position $_CHIPNAME.m31_dap # Once the JRC is up, enable our TAPs jtag configure $_CHIPNAME.jrc -event setup " jtag tapenable $_CHIPNAME.dap jtag tapenable $_CHIPNAME.m30_dap jtag tapenable $_CHIPNAME.m31_dap " # Assume SRST is unavailable (e.g. TI-14 JTAG), so we must assert reset # ourselves using PRM_RSTCTRL. 1 is a warm reset, 2 a cold reset. set PRM_RSTCTRL 0x4A307B00 $_TARGETNAME configure -event reset-assert "$_TARGETNAME mww phys $PRM_RSTCTRL 0x1" $_CHIPNAME.m30 configure -event reset-assert { } $_CHIPNAME.m31 configure -event reset-assert { } # Soft breakpoints don't currently work due to broken cache handling gdb_breakpoint_override hard openocd-0.9.0/tcl/target/lpc2378.cfg0000644000175000017500000000175212526202244013727 00000000000000# NXP LPC2378 ARM7TDMI-S with 512kB flash (8kB used by bootloader) and 56kB SRAM (16kB for ETH, 8kB for DMA), clocked with 4MHz internal oscillator source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2378 {core_freq_khz adapter_freq_khz} { # 504kB flash and 32kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2378 0x4f1f0f0f 0x7e000 lpc2000_v2 0x8000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 4MHz internal oscillator echo "Warning - assuming default core clock 4MHz! Flashing may fail if actual core clock is different." # setup_lpc2378 setup_lpc2378 4000 500 } openocd-0.9.0/tcl/target/at91sam7se512.cfg0000644000175000017500000000223412526202244014747 00000000000000# ATMEL sam7se512 # Example: the "Elektor Internet Radio" - EIR # http://www.ethernut.de/en/hardware/eir/index.html if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam7se512 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # Force an error until we get a good number. set _CPUTAPID 0xffffffff } #use combined on interfaces or targets that can't set TRST/SRST separately reset_config srst_only srst_pulls_trst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # The target set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0 #flash bank [ ] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432 openocd-0.9.0/tcl/target/stm32f3x.cfg0000644000175000017500000000721512526202244014216 00000000000000# script for stm32f3x family # # stm32 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32f3x } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 16kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { # See STM Document RM0316 # Section 29.6.3 - corresponds to Cortex-M4 r0p1 set _CPUTAPID 0x4ba00477 } { set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { # STM Document RM0316 rev 5 for STM32F302/303 B/C size set _BSTAPID1 0x06422041 # STM Document RM0313 rev 3 for STM32F37x set _BSTAPID2 0x06432041 # STM Document RM364 rev 1 for STM32F334 set _BSTAPID3 0x06438041 # STM Document RM316 rev 5 for STM32F303 6/8 size # STM Document RM365 rev 3 for STM32F302 6/8 size # STM Document RM366 rev 2 for STM32F301 6/8 size set _BSTAPID4 0x06439041 # STM Document RM016 rev 5 for STM32F303 D/E size set _BSTAPID5 0x06446041 } if {[using_jtag]} { swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } proc stm32f3x_default_reset_start {} { # Reset clock is HSI (8 MHz) adapter_khz 1000 } proc stm32f3x_default_examine_end {} { # Enable debug during low power modes (uses more power) mmw 0xe0042004 0x00000007 0 ;# DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP # Stop watchdog counters during halt mww 0xe0042008 0x00001800 ;# DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP } proc stm32f3x_default_reset_init {} { # Configure PLL to boost clock to HSI x 8 (64 MHz) mww 0x40021004 0x00380400 ;# RCC_CFGR = PLLMUL[3:1] | PPRE1[2] mmw 0x40021000 0x01000000 0 ;# RCC_CR |= PLLON mww 0x40022000 0x00000012 ;# FLASH_ACR = PRFTBE | LATENCY[1] sleep 10 ;# Wait for PLL to lock mmw 0x40021004 0x00000002 0 ;# RCC_CFGR |= SW[1] # Boost JTAG frequency adapter_khz 8000 } # Default hooks $_TARGETNAME configure -event examine-end { stm32f3x_default_examine_end } $_TARGETNAME configure -event reset-start { stm32f3x_default_reset_start } $_TARGETNAME configure -event reset-init { stm32f3x_default_reset_init } $_TARGETNAME configure -event trace-config { # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync # change this value accordingly to configure trace pins # assignment mmw 0xe0042004 0x00000020 0 } openocd-0.9.0/tcl/target/atmega128.cfg0000644000175000017500000000151512526202244014313 00000000000000# for avr set _CHIPNAME avr set _ENDIAN little # jtag speed adapter_khz 4500 reset_config srst_only adapter_nsrst_delay 100 #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x8970203F } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME avr -endian $_ENDIAN -chain-position $_TARGETNAME #$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 16384 -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME #to use it, script will be like: #init #adapter_khz 4500 #reset init #verify_ircapture disable # #halt #wait halt #poll #avr mass_erase 0 #flash write_image E:/Versaloon/Software/CAMERAPROTOCOLAGENT.hex #reset run #shutdown openocd-0.9.0/tcl/target/at91sam9g20.cfg0000644000175000017500000000141212526202244014477 00000000000000###################################### # Target: Atmel AT91SAM9G20 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9g20 } source [find target/at91sam9.cfg] # Set fallback clock to 1/6 of worst-case clock speed (which would be the 32.768 kHz slow clock). adapter_khz 5 # Establish internal SRAM memory work areas that are important to pre-bootstrap loaders, etc. The # AT91SAM9G20 has two SRAM areas, one starting at 0x00200000 and the other starting at 0x00300000. # Both areas are 16 kB long. #$_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 1 $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x4000 -work-area-backup 1 openocd-0.9.0/tcl/target/stm32f4x.cfg0000644000175000017500000000540512526202244014216 00000000000000# script for stm32f4x family # # stm32 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME stm32f4x } set _ENDIAN little # Work-area is a space in RAM used for flash programming # By default use 64kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x10000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { # See STM Document RM0090 # Section 38.6.3 - corresponds to Cortex-M4 r0p1 set _CPUTAPID 0x4ba00477 } { set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { # See STM Document RM0090 # Section 38.6.2 # STM32F405xx/07xx and STM32F415xx/17xx set _BSTAPID1 0x06413041 # STM32F42xxx and STM32F43xxx set _BSTAPID2 0x06419041 # See STM Document RM0368 (Rev. 3) # STM32F401B/C set _BSTAPID3 0x06423041 # STM32F401D/E set _BSTAPID4 0x06433041 # See STM Document RM0383 (Rev 2) # STM32F411 set _BSTAPID5 0x06431041 } if {[using_jtag]} { swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME # JTAG speed should be <= F_CPU/6. F_CPU after reset is 16MHz, so use F_JTAG = 2MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 2000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } $_TARGETNAME configure -event examine-end { # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP mmw 0xE0042004 0x00000007 0 # Stop watchdog counters during halt # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP mww 0xE0042008 0x00001800 } $_TARGETNAME configure -event trace-config { # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync # change this value accordingly to configure trace pins # assignment mmw 0xE0042004 0x00000020 0 } openocd-0.9.0/tcl/target/nrf51.cfg0000644000175000017500000000274412526202244013562 00000000000000# # script for Nordic nRF51 series, a CORTEX-M0 chip # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME nrf51 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming # By default use 16kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0bb11477 } swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 if {![using_hla]} { # The chip supports standard ARM/Cortex-M0 SYSRESETREQ signal cortex_m reset_config sysresetreq } flash bank $_CHIPNAME.flash nrf51 0x00000000 0 1 1 $_TARGETNAME flash bank $_CHIPNAME.uicr nrf51 0x10001000 0 1 1 $_TARGETNAME # # The chip should start up from internal 16Mhz RC, so setting adapter # clock to 1Mhz should be OK # adapter_khz 1000 proc enable_all_ram {} { # nRF51822 Product Anomaly Notice (PAN) #16 explains that not all RAM banks # are reliably enabled after reset on some revisions (contrary to spec.) So after # resetting we enable all banks via the RAMON register mww 0x40000524 0xF } $_TARGETNAME configure -event reset-end { enable_all_ram } openocd-0.9.0/tcl/target/stm32lx_stlink.cfg0000644000175000017500000000017612526202244015524 00000000000000echo "WARNING: target/stm32lx_stlink.cfg is deprecated, please switch to target/stm32l1.cfg" source [find target/stm32l1.cfg] openocd-0.9.0/tcl/target/at91sam9g45.cfg0000644000175000017500000000077612526202244014522 00000000000000###################################### # Target: Atmel AT91SAM9G45 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9g45 } source [find target/at91sam9.cfg] # Establish internal SRAM memory work areas that are important to pre-bootstrap loaders, etc. The # AT91SAM9G45 has one SRAM area starting at 0x00300000 of 64 KiB. $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x200000 -work-area-backup 1 openocd-0.9.0/tcl/target/lpc11xx.cfg0000644000175000017500000000027412526202244014123 00000000000000# NXP LPC11xx Cortex-M0 with at least 1kB SRAM set CHIPNAME lpc11xx set CHIPSERIES lpc1100 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x400 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/feroceon.cfg0000644000175000017500000000124412526202244014421 00000000000000###################################### # Target: Marvell Feroceon CPU core ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME feroceon } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x20a023d3 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME feroceon -endian $_ENDIAN -chain-position $_TARGETNAME reset_config trst_and_srst adapter_nsrst_delay 200 jtag_ntrst_delay 200 openocd-0.9.0/tcl/target/xmc4xxx.cfg0000644000175000017500000000144212526202244014244 00000000000000# # Infineon XMC4100/XMC4200/XMC4400/XMC4500 family (ARM Cortex-M4 @ 80-120 MHz) # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME xmc4000 } source [find target/swj-dp.tcl] # # SWJ-DP # if { [info exists CPU_JTAG_TAPID] } { set _CPU_JTAG_TAPID $CPU_JTAG_TAPID } else { set _CPU_JTAG_TAPID 0x4BA00477 } # # SW_DP # if { [info exists CPU_SWD_TAPID] } { set _CPU_SWD_TAPID $CPU_SWD_TAPID } else { set _CPU_SWD_TAPID 0x2BA01477 } if { [using_jtag] } { set _CPU_TAPID $_CPU_JTAG_TAPID } else { set _CPU_TAPID $_CPU_SWD_TAPID } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPU_TAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME if { ![using_hla] } { cortex_m reset_config sysresetreq } adapter_khz 1000 openocd-0.9.0/tcl/target/stm32xl.cfg0000644000175000017500000000031412526202244014132 00000000000000# script for stm32xl family (dual flash bank) source [find target/stm32f1x.cfg] # flash size will be probed set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME stm32f1x 0x08080000 0 0 0 $_TARGETNAME openocd-0.9.0/tcl/target/str912.cfg0000644000175000017500000000356712526202244013677 00000000000000# script for str9 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME str912 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # jtag speed. We need to stick to 16kHz until we've finished reset. adapter_khz 16 adapter_nsrst_delay 100 jtag_ntrst_delay 100 #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst if { [info exists FLASHTAPID] } { set _FLASHTAPID $FLASHTAPID } else { set _FLASHTAPID 0x04570041 } jtag newtap $_CHIPNAME flash -irlen 8 -ircapture 0x1 -irmask 0x1 -expected-id $_FLASHTAPID if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x25966041 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { # possible values: 0x1457f041, 0x2457f041 # we ignore version in check below set _BSTAPID 0x1457f041 } jtag newtap $_CHIPNAME bs -irlen 5 -ircapture 0x1 -irmask 0x1 -expected-id $_BSTAPID -ignore-version set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-start { adapter_khz 16 } $_TARGETNAME configure -event reset-init { # We can increase speed now that we know the target is halted. #adapter_khz 3000 # -- Enable 96K RAM # PFQBC enabled / DTCM & AHB wait-states disabled mww 0x5C002034 0x0191 str9x flash_config 0 4 2 0 0x80000 flash protect 0 0 7 off } $_TARGETNAME configure -work-area-phys 0x50000000 -work-area-size 16384 -work-area-backup 0 #flash bank str9x 0 0 set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME str9x 0x00000000 0x00080000 0 0 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME str9x 0x00080000 0x00008000 0 0 $_TARGETNAME openocd-0.9.0/tcl/target/stm32w108xx.cfg0000644000175000017500000000317112526202244014572 00000000000000# # Target configuration for the ST STM32W108xx chips # # Processor: ARM Cortex M3 # Date: 2013-06-09 # Author: Giuseppe Barba # # stm32 devices support both JTAG and SWD transports. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] == 0 } { set _CHIPNAME stm32w108 } else { set _CHIPNAME $CHIPNAME } # Work-area is a space in RAM used for flash programming # By default use 8kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x2000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { set _CPUTAPID 0x3ba00477 } { set _CPUTAPID 0x1ba01477 } } set _ENDIAN little swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID if {[using_jtag]} { if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID swj_newdap $_CHIPNAME bs -irlen 4 -ircapture 0xe -irmask 0xf -expected-id _BSTAPID } else { set _BSTAPID_1 0x169a862b set _BSTAPID_2 0x269a862b swj_newdap $_CHIPNAME bs -irlen 4 -ircapture 0xe -irmask 0xf \ -expected-id $_BSTAPID_1 -expected-id $_BSTAPID_2 } } # # Set Target # set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # Use the flash driver from the EM357 set _FLASHNAME $_CHIPNAME.flash # 64k (0x10000) of flash flash bank $_FLASHNAME em357 0x08000000 0x10000 0 0 $_TARGETNAME reset_config srst_nogate if {![using_hla]} { cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/lpc1850.cfg0000644000175000017500000000130112526202244013707 00000000000000source [find target/swj-dp.tcl] adapter_khz 500 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lpc1850 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # # M3 JTAG mode TAP # if { [info exists M3_JTAG_TAPID] } { set _M3_JTAG_TAPID $M3_JTAG_TAPID } else { set _M3_JTAG_TAPID 0x4ba00477 } swj_newdap $_CHIPNAME m3 -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_M3_JTAG_TAPID set _TARGETNAME $_CHIPNAME.m3 target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/readme.txt0000644000175000017500000000277512526202244014150 00000000000000Prerequisites: The users of OpenOCD as well as computer programs interacting with OpenOCD are expecting that certain commands do the same thing across all the targets. Rules to follow when writing scripts: 1. The configuration script should be defined such as , for example, the following sequences are working: reset flash info and reset flash erase_address and reset init load In most cases this can be accomplished by specifying the default startup mode as reset_init (target command in the configuration file). 2. If the target is correctly configured, flash must be writable without any other helper commands. It is assumed that all write-protect mechanisms should be disabled. 3. The configuration scripts should be defined such as the binary that was written to flash verifies (turn off remapping, checksums, etc...) flash write_image [file] verify_image [file] 4. adapter_khz sets the maximum speed (or alternatively RCLK). If invoked multiple times only the last setting is used. interface/xxx.cfg files are always executed *before* target/xxx.cfg files, so any adapter_khz in interface/xxx.cfg will be overridden by target/xxx.cfg. adapter_khz in interface/xxx.cfg would then, effectively, set the default JTAG speed. Note that a target/xxx.cfg file can invoke another target/yyy.cfg file, so one can create target subtype configurations where e.g. only amount of DRAM, oscillator speeds differ and having a single config file for the default/common settings. openocd-0.9.0/tcl/target/quark_x10xx.cfg0000644000175000017500000000226412526202244015017 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME quark_x10xx } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x18289013 } jtag newtap quark_x10xx cpu -irlen 8 -irmask 0xff -expected-id $_CPUTAPID -disable jtag newtap quark_x10xx cltap -irlen 8 -irmask 0xff -expected-id 0x0e681013 -enable #openocd puts tap at front of chain not end of chain proc quark_x10xx_tapenable {} { echo "enabling core tap" irscan quark_x10xx.cltap 0x11 drscan quark_x10xx.cltap 64 1 runtest 10 } proc quark_x10xx_tapdisable {} { echo "disabling core tap" irscan quark_x10xx.cltap 0x11 drscan quark_x10xx.cltap 64 0 runtest 10 } proc quark_x10xx_setup {} { jtag tapenable quark_x10xx.cpu } jtag configure $_CHIPNAME.cpu -event tap-enable \ "quark_x10xx_tapenable" jtag configure $_CHIPNAME.cpu -event tap-disable \ "quark_x10xx_tapdisable" set _TARGETNAME $_CHIPNAME.cpu target create quark_x10xx.cpu quark_x10xx -endian $_ENDIAN -chain-position quark_x10xx.cpu jtag configure $_CHIPNAME.cpu -event setup \ "quark_x10xx_setup" openocd-0.9.0/tcl/target/c100.cfg0000644000175000017500000000200312526202244013256 00000000000000# c100 config. # This is ARM1136 dual core # this script only configures one core (that is used to run Linux) # assume no PLL lock, start slowly adapter_khz 100 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME c100 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x27b3645b } if { [info exists DSPTAPID] } { set _DSPTAPID $DSPTAPID } else { set _DSPTAPID 0x27b3645b } jtag newtap $_CHIPNAME dsp -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_DSPTAPID # Per ARM: DDI0211J_arm1136_r1p5_trm.pdf - the ARM 1136 as a 5 bit IR register jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME # C100's ARAM 64k SRAM $_TARGETNAME configure -work-area-phys 0x0a000000 -work-area-size 0x10000 -work-area-backup 0 openocd-0.9.0/tcl/target/stm32w108_stlink.cfg0000644000175000017500000000021212526202244015567 00000000000000echo "WARNING: target/stm32w108xx_stlink.cfg is deprecated, please switch to target/stm32w108xx.cfg" source [find target/stm32w108xx.cfg] openocd-0.9.0/tcl/target/cc2538.cfg0000644000175000017500000000047612526202244013536 00000000000000# Config for Texas Instruments low power RF SoC CC2538 # http://www.ti.com/lit/pdf/swru319 if { [info exists CHIPNAME] } { set CHIPNAME $CHIPNAME } else { set CHIPNAME cc2538 } if { [info exists JRC_TAPID] } { set JRC_TAPID $JRC_TAPID } else { set JRC_TAPID 0x8B96402F } source [find target/cc26xx.cfg] openocd-0.9.0/tcl/target/test_syntax_error.cfg0000644000175000017500000000012512526202244016414 00000000000000# This script tests a syntax error in the startup # config script syntax error here openocd-0.9.0/tcl/target/kx.cfg0000644000175000017500000000263712526202244013252 00000000000000# # Freescale Kinetis Kx series devices # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME kx } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { set _CPUTAPID 0x4ba00477 } { set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu # It is important that "kinetis mdm check_security" is called for # 'examine-end' event and not 'eximine-start'. Calling it in 'examine-start' # causes "kinetis mdm check_security" to fail the first time openocd # calls it when it tries to connect after the CPU has been power-cycled. $_CHIPNAME.cpu configure -event examine-end { kinetis mdm check_security } $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME adapter_khz 1000 reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/lpc2460.cfg0000644000175000017500000000167212526202244013720 00000000000000# NXP LPC2460 ARM7TDMI-S with 98kB SRAM (16kB for ETH, 16kB for DMA, 2kB for RTC), clocked with 4MHz internal oscillator source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2460 {core_freq_khz adapter_freq_khz} { # 64kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2460 0x4f1f0f0f 0 lpc2000_v2 0x10000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 4MHz internal oscillator echo "Warning - assuming default core clock 4MHz! Flashing may fail if actual core clock is different." # setup_lpc2460 setup_lpc2460 4000 500 } openocd-0.9.0/tcl/target/lpc2478.cfg0000644000175000017500000000177112526202244013731 00000000000000# NXP LPC2478 ARM7TDMI-S with 512kB flash (8kB used by bootloader) and 98kB SRAM (16kB for ETH, 16kB for DMA, 2kB for RTC), clocked with 4MHz internal oscillator source [find target/lpc2xxx.cfg] # parameters: # - core_freq_khz - frequency of core in kHz during flashing, usually equal to connected crystal or internal oscillator, e.g. 12000 # - adapter_freq_khz - frequency of debug adapter in kHz, should be 8x slower than core_freq_khz, e.g. 1000 proc setup_lpc2478 {core_freq_khz adapter_freq_khz} { # 504kB flash and 64kB SRAM # setup_lpc2xxx setup_lpc2xxx lpc2478 0x4f1f0f0f 0x7e000 lpc2000_v2 0x10000 $core_freq_khz $adapter_freq_khz } proc init_targets {} { # default to core clocked with 4MHz internal oscillator echo "Warning - assuming default core clock 4MHz! Flashing may fail if actual core clock is different." # setup_lpc2478 setup_lpc2478 4000 500 } openocd-0.9.0/tcl/target/lpc4350.cfg0000644000175000017500000000241612526202244013715 00000000000000source [find target/swj-dp.tcl] adapter_khz 500 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lpc4350 } # # M4 JTAG mode TAP # if { [info exists M4_JTAG_TAPID] } { set _M4_JTAG_TAPID $M4_JTAG_TAPID } else { set _M4_JTAG_TAPID 0x4ba00477 } # # M4 SWD mode TAP # if { [info exists M4_SWD_TAPID] } { set _M4_SWD_TAPID $M4_SWD_TAPID } else { set _M4_SWD_TAPID 0x2ba01477 } if { [using_jtag] } { set _M4_TAPID $_M4_JTAG_TAPID } { set _M4_TAPID $_M4_SWD_TAPID } # # M0 TAP # if { [info exists M0_JTAG_TAPID] } { set _M0_JTAG_TAPID $M0_JTAG_TAPID } else { set _M0_JTAG_TAPID 0x0ba01477 } swj_newdap $_CHIPNAME m4 -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M4_TAPID target create $_CHIPNAME.m4 cortex_m -chain-position $_CHIPNAME.m4 if { [using_jtag] } { swj_newdap $_CHIPNAME m0 -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_M0_JTAG_TAPID target create $_CHIPNAME.m0 cortex_m -chain-position $_CHIPNAME.m0 } if {![using_hla]} { # on this CPU we should use VECTRESET to perform a soft reset and # manually reset the periphery # SRST or SYSRESETREQ disable the debug interface for the time of # the reset and will not fit our requirements for a consistent debug # session cortex_m reset_config vectreset } openocd-0.9.0/tcl/target/1986ве1Ñ‚.cfg0000644000175000017500000000313512526202244015444 00000000000000# 1986ВЕ1Т # http://milandr.ru/index.php?mact=Products,cntnt01,details,0&cntnt01productid=236&cntnt01returnid=68 source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME 1986ве1Ñ‚ } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { set _CPUTAPID 0x4ba00477 } { # SWD IDCODE set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME # use AHB-Lite SRAM for work area $_TARGETNAME configure -work-area-phys 0x20100000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # can't handle overlapping memory regions if { [info exists IMEMORY] && [string equal $IMEMORY true] } { flash bank ${_CHIPNAME}_info.flash mdr 0x00000000 0x01000 0 0 $_TARGETNAME 1 1 4 } else { flash bank $_CHIPNAME.flash mdr 0x00000000 0x20000 0 0 $_TARGETNAME 0 32 4 } # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/at91sam7x512.cfg0000644000175000017500000000273112526202244014611 00000000000000#use combined on interfaces or targets that can't set TRST/SRST separately reset_config srst_only srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam7x512 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { # disable watchdog mww 0xfffffd44 0x00008000 # enable user reset mww 0xfffffd08 0xa5000001 # CKGR_MOR : enable the main oscillator mww 0xfffffc20 0x00000601 sleep 10 # CKGR_PLLR: 96.1097 MHz mww 0xfffffc2c 0x00481c0e sleep 10 # PMC_MCKR : MCK = PLL / 2 ~= 48 MHz mww 0xfffffc30 0x00000007 sleep 10 # MC_FMR: flash mode (FWS=1,FMCN=60) mww 0xffffff60 0x003c0100 sleep 100 } $_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0 #flash bank [ ] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME.0 at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432 flash bank $_FLASHNAME.1 at91sam7 0 0 0 0 $_TARGETNAME 1 0 0 0 0 0 0 18432 openocd-0.9.0/tcl/target/ks869x.cfg0000644000175000017500000000132112526202244013671 00000000000000# ARM920T CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME ks869x } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x00922f0f } adapter_khz 6000 # jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000 -work-area-size 0x20000 -work-area-backup 0 # speed up memory downloads arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/at91sam7sx.cfg0000644000175000017500000000276012526202244014546 00000000000000#use combined on interfaces or targets that can't set TRST/SRST separately reset_config srst_only srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91sam7s } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -event reset-init { soft_reset_halt # RSTC_CR : Reset peripherals mww 0xfffffd00 0xa5000004 # disable watchdog mww 0xfffffd44 0x00008000 # enable user reset mww 0xfffffd08 0xa5000001 # CKGR_MOR : enable the main oscillator mww 0xfffffc20 0x00000601 sleep 10 # CKGR_PLLR: 96.1097 MHz mww 0xfffffc2c 0x00481c0e sleep 10 # PMC_MCKR : MCK = PLL / 2 ~= 48 MHz mww 0xfffffc30 0x00000007 sleep 10 # MC_FMR: flash mode (FWS=1,FMCN=73) mww 0xffffff60 0x00490100 sleep 100 } $_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0 #flash bank [ ] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432 openocd-0.9.0/tcl/target/lpc12xx.cfg0000644000175000017500000000027512526202244014125 00000000000000# NXP LPC12xx Cortex-M0 with at least 4kB SRAM set CHIPNAME lpc12xx set CHIPSERIES lpc1200 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x1000 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/nds32v3m.cfg0000644000175000017500000000032312526202244014175 00000000000000# # Andes Core # # http://www.andestech.com # jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME nds32_v3m -endian little -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/pic32mx.cfg0000644000175000017500000000520712526202244014111 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME pic32mx } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x30938053 } # default working area is 16384 if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } adapter_nsrst_delay 100 jtag_ntrst_delay 100 #jtag scan chain #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian $_ENDIAN -chain-position $_TARGETNAME # # At reset the pic32mx does not allow code execution from RAM # we have to setup the BMX registers to allow this. # One limitation is that we loose the first 2k of RAM. # global _PIC32MX_DATASIZE global _WORKAREASIZE set _PIC32MX_DATASIZE 0x800 set _PIC32MX_PROGSIZE [expr ($_WORKAREASIZE - $_PIC32MX_DATASIZE)] $_TARGETNAME configure -work-area-phys 0xa0000800 -work-area-size $_PIC32MX_PROGSIZE -work-area-backup 0 $_TARGETNAME configure -event reset-init { # # from reset the pic32 cannot execute code in ram - enable ram execution # minimum offset from start of ram is 2k # global _PIC32MX_DATASIZE global _WORKAREASIZE # BMXCON set 0 wait state option by clearing BMXWSDRM bit, bit 6 mww 0xbf882000 0x001f0000 # BMXDKPBA: 2k kernel data @ 0xa0000000 mww 0xbf882010 $_PIC32MX_DATASIZE # BMXDUDBA: 14k kernel program @ 0xa0000800 - (BMXDUDBA - BMXDKPBA) mww 0xbf882020 $_WORKAREASIZE # BMXDUPBA: 0k user program - (BMXDUPBA - BMXDUDBA) mww 0xbf882030 $_WORKAREASIZE # # Set system clock to 8Mhz if the default clock configuration is set # # SYSKEY register, make sure OSCCON is locked mww 0xbf80f230 0x0 # SYSKEY register, write unlock sequence mww 0xbf80f230 0xaa996655 mww 0xbf80f230 0x556699aa # OSCCON register + 4, clear OSCCON FRCDIV bits: 24, 25 and 26, divided by 1 mww 0xbf80f004 0x07000000 # SYSKEY register, relock OSCCON mww 0xbf80f230 0x0 } set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME # add virtual banks for kseg0 and kseg1 flash bank vbank0 virtual 0xbfc00000 0 0 0 $_TARGETNAME $_FLASHNAME flash bank vbank1 virtual 0x9fc00000 0 0 0 $_TARGETNAME $_FLASHNAME set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME pic32mx 0x1d000000 0 0 0 $_TARGETNAME # add virtual banks for kseg0 and kseg1 flash bank vbank2 virtual 0xbd000000 0 0 0 $_TARGETNAME $_FLASHNAME flash bank vbank3 virtual 0x9d000000 0 0 0 $_TARGETNAME $_FLASHNAME openocd-0.9.0/tcl/target/amdm37x.cfg0000644000175000017500000001622412526202244014105 00000000000000# # Copyright (C) 2010-2011 by Karl Kurbjun # Copyright (C) 2009-2011 by Øyvind Harboe # Copyright (C) 2009 by David Brownell # Copyright (C) 2009 by Magnus Lundin # # TI AM/DM37x Technical Reference Manual (Version R) # http://www.ti.com/lit/ug/sprugn4r/sprugn4r.pdf # # This script is based on the AM3517 initialization. It should be considered # preliminary since it needs more complete testing and only the basic # operations work. # ############################################################################### # User modifiable parameters ############################################################################### # This script uses the variable CHIPTYPE to determine whether this is an AM35x # or DM37x target. If CHIPTYPE is not set it will error out. if { [info exists CHIPTYPE] } { if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME $CHIPTYPE } switch $CHIPTYPE { dm37x { # Primary TAP: ICEPick-C (JTAG route controller) and boundary scan set _JRC_TAPID "-expected-id 0x2b89102f -expected-id 0x1b89102f -expected-id 0x0b89102f" } am35x { # Primary TAP: ICEPick-C (JTAG route controller) and boundary scan set _JRC_TAPID "-expected-id 0x0b7ae02f -expected-id 0x0b86802f" } default { error "ERROR: CHIPTYPE was set, but it was not set to a valid value. Acceptable values are \"dm37x\" or \"am35x\"." } } } else { error "ERROR: CHIPTYPE was not defined. Please set CHIPTYPE to \"am35x\" for the AM35x or \"dm37x\" for the DM37x series in the board configuration." } # Run the adapter at the fastest acceptable speed with the slowest possible # core clock. adapter_khz 10 ############################################################################### # JTAG setup # The OpenOCD commands are described in the TAP Declaration section # http://openocd.org/doc/html/TAP-Declaration.html ############################################################################### # The AM/DM37x has an ICEPick module in it like many of TI's other devices. More # can be read about this module in sprugn4r in chapter 27: "Debug and # Emulation". The module is used to route the JTAG chain to the various # subsystems in the chip. source [find target/icepick.cfg] # The TAP order should be described from the TDO connection in OpenOCD to the # TDI pin. The OpenOCD FAQ describes this in more detail: # http://openocd.org/doc/html/FAQ.html # From SPRUGN4R CH27 the available secondary TAPs are in this order from TDO: # # Device | TAP number # ---------|------------ # DAP | 3 # Sequencer| 2 Note: The sequencer is an ARM968 # DSP | 1 # D2D | 0 # # Right now the only secondary tap enabled is the DAP so the rest are left # undescribed. ###### # Start of Chain Description # The Secondary TAPs all have enable functions defined for use with the ICEPick # Only the DAP is enabled. The AM37xx does not have the Sequencer or DSP but # the TAP numbers for ICEPick do not change. # # TODO: A disable function should also be added. ###### # Secondary TAP: DAP is closest to the TDO output # The TAP enable event also needs to be described jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -disable jtag configure $_CHIPNAME.dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 3" # These taps are only present in the DM37x series. if { $CHIPTYPE == "dm37x" } { # Secondary TAP: Sequencer (ARM968) it is not in the chain by default # The ICEPick can be used to enable it in the chain. jtag newtap $_CHIPNAME arm2 -irlen 4 -ircapture 0x1 -irmask 0x0f -disable jtag configure $_CHIPNAME.arm2 -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 2" # Secondary TAP: C64x+ DSP - it is not in the chain by default (-disable) # The ICEPick can be used to enable it in the chain. jtag newtap $_CHIPNAME dsp -irlen 38 -ircapture 0x25 -irmask 0x3f -disable jtag configure $_CHIPNAME.dsp -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 1" } # Secondary TAP: D2D it is not in the chain by default (-disable) # The ICEPick can be used to enable it in the chain. # This IRLEN is probably incorrect - not sure where the documentation is. jtag newtap $_CHIPNAME d2d -irlen 4 -ircapture 0x1 -irmask 0x0f -disable jtag configure $_CHIPNAME.d2d -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 0" # Primary TAP: ICEPick - it is closest to TDI so last in the chain eval "jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f $_JRC_TAPID" ###### # End of Chain Description ###### ###### # Start JTAG TAP events ###### # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.jrc -event post-reset "runtest 100" # Enable the DAP TAP jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" ###### # End JTAG TAP events ###### ############################################################################### # Target Setup: # This section is described in the OpenOCD documentation under CPU Configuration # http://openocd.org/doc/html/CPU-Configuration.html ############################################################################### # Create the CPU target to be used with GDB: Cortex-A8, using DAP set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap # The DM37x has 64K of SRAM starting at address 0x4020_0000. Allow the first # 16K to be used as a scratchpad for OpenOCD. $_TARGETNAME configure -work-area-phys 0x40200000 -work-area-size 0x4000 ###### # Start Target Reset Event Setup: ###### # Set the JTAG clock down to 10 kHz to be sure that it will work with the # slowest possible core clock (16.8MHz/2 = 8.4MHz). It is OK to speed up # *after* PLL and clock tree setup. $_TARGETNAME configure -event "reset-start" { adapter_khz 10 } # Describe the reset assert process for openocd - this is asserted with the # ICEPick $_TARGETNAME configure -event "reset-assert" { global _CHIPNAME # assert warm system reset through ICEPick icepick_c_wreset $_CHIPNAME.jrc } # After the reset is asserted we need to re-initialize debugging and speed up # the JTAG clock. $_TARGETNAME configure -event reset-assert-post { global _TARGETNAME amdm37x_dbginit $_TARGETNAME adapter_khz 1000 } $_TARGETNAME configure -event gdb-attach { global _TARGETNAME amdm37x_dbginit $_TARGETNAME echo "Halting target" halt } ###### # End Target Reset Event Setup: ###### ############################################################################### # Target Functions # Add any functions needed for the target here ############################################################################### # Run this to enable invasive debugging. This is run automatically in the # reset sequence. proc amdm37x_dbginit {target} { # General Cortex A8 debug initialisation cortex_a dbginit # Enable DBGEN signal. This signal is described in the ARM v7 TRM, but # access to the signal appears to be implementation specific. TI does not # describe this register much except a quick line that states DBGEM (sic) is # at this address and this bit. $target mww phys 0x5401d030 0x00002000 } openocd-0.9.0/tcl/target/stm32f2x_stlink.cfg0000644000175000017500000000020112526202244015565 00000000000000echo "WARNING: target/stm32f2x_stlink.cfg is deprecated, please switch to target/stm32f2x.cfg" source [find target/stm32f2x.cfg] openocd-0.9.0/tcl/target/lpc3131.cfg0000644000175000017500000000371212526202244013711 00000000000000###################################### # Target: NXP lpc3131 ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lpc3131 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # ARM926EJS core if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926f0f } # Scan Tap # Wired to seperate STDO pin on the lpc3131, externally muxed to TDO on ea3131 module # JTAGSEL pin must be 0 to activate, which reassigns arm tdo to a pass through. if { [info exists SJCTAPID] } { set _SJCTAPID $SJCTAPID } else { set _SJCTAPID 0x1541E02B } jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID ################################################################## # various symbol definitions, to avoid hard-wiring addresses ################################################################## global lpc313x set lpc313x [ dict create ] # Physical addresses for controllers and memory dict set lpc313x sram0 0x11028000 dict set lpc313x sram1 0x11040000 dict set lpc313x uart 0x15001000 dict set lpc313x cgu 0x13004000 dict set lpc313x ioconfig 0x13003000 dict set lpc313x sysconfig 0x13002800 dict set lpc313x wdt 0x13002400 ################################################################## # Target configuration ################################################################## adapter_nsrst_delay 1000 jtag_ntrst_delay 0 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME invoke-event halted $_TARGETNAME configure -work-area-phys [dict get $lpc313x sram0] -work-area-size 0x30000 -work-area-backup 0 $_TARGETNAME configure -event reset-init { echo "\nRunning reset init script for LPC3131\n" halt wait_halt reg cpsr 0xa00000d3 ;#Supervisor mode reg pc 0x11029000 poll sleep 500 } arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/cc26xx.cfg0000644000175000017500000000224312526202244013736 00000000000000# Config for Texas Instruments low power SoC CC26xx family adapter_khz 100 source [find target/icepick.cfg] source [find target/ti-cjtag.cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cc26xx } # # Main DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x4BA00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" # # ICEpick-C (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x1B99A02F } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version # A start sequence is needed to change from cJTAG (Compact JTAG) to # 4-pin JTAG before talking via JTAG commands jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" jtag configure $_CHIPNAME.jrc -event post-reset "ti_cjtag_to_4pin_jtag $_CHIPNAME.jrc" # # Cortex M3 target # set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.dap openocd-0.9.0/tcl/target/omap5912.cfg0000644000175000017500000000215412526202244014077 00000000000000# TI OMAP5912 dual core processor # http://focus.ti.com/docs/prod/folders/print/omap5912.html if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omap5912 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # NOTE: validated with XOMAP5912 part set _CPUTAPID 0x0692602f } adapter_nsrst_delay 100 # NOTE: presumes irlen 38 is the C55x DSP, matching BSDL for # its standalone siblings (like TMS320VC5502) of the same era #jtag scan chain jtag newtap $_CHIPNAME dsp -irlen 38 -expected-id 0x03df1d81 jtag newtap $_CHIPNAME arm -irlen 4 -expected-id $_CPUTAPID jtag newtap $_CHIPNAME unknown -irlen 8 set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME proc omap5912_reset {} { # # halt target # poll sleep 1 halt wait_halt # # disable wdt # mww 0xfffec808 0x000000f5 mww 0xfffec808 0x000000a0 mww 0xfffeb048 0x0000aaaa sleep 500 mww 0xfffeb048 0x00005555 sleep 500 } # omap5912 lcd frame buffer as working area $_TARGETNAME configure -work-area-phys 0x20000000 \ -work-area-size 0x3e800 -work-area-backup 0 openocd-0.9.0/tcl/target/cc32xx.cfg0000644000175000017500000000222312526202244013731 00000000000000# Config for Texas Instruments SoC CC32xx family source [find target/swj-dp.tcl] adapter_khz 100 source [find target/icepick.cfg] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cc32xx } # # Main DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { if {[using_jtag]} { set _DAP_TAPID 0x4BA00477 } else { set _DAP_TAPID 0x2BA01477 } } if {[using_jtag]} { jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" } else { swj_newdap $_CHIPNAME dap -expected-id $_DAP_TAPID } # # ICEpick-C (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0B97C02F } if {[using_jtag]} { jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" } # # Cortex M3 target # set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.dap openocd-0.9.0/tcl/target/at91sam3ax_xx.cfg0000644000175000017500000000026412526202244015234 00000000000000# script for ATMEL sam3, a CORTEX-M3 chip # # at91sam3A4C # at91sam3A8C # at91sam3X4C # at91sam3X4E # at91sam3X8C # at91sam3X8E # at91sam3X8H source [find target/at91sam3XXX.cfg] openocd-0.9.0/tcl/target/omapl138.cfg0000644000175000017500000000410212526202244014161 00000000000000# # Texas Instruments DaVinci family: OMAPL138 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omapl138 } source [find target/icepick.cfg] # Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer if { [info exists ETB_TAPID] } { set _ETB_TAPID $ETB_TAPID } else { set _ETB_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETB_TAPID -disable jtag configure $_CHIPNAME.etb -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 3" # Subsidiary TAP: ARM926ejs with scan chains for ARM Debug, EmbeddedICE-RT, ETM. if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x07926001 } jtag newtap $_CHIPNAME arm -irlen 4 -irmask 0xf -expected-id $_CPU_TAPID -disable jtag configure $_CHIPNAME.arm -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 2" # Primary TAP: ICEpick-C (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b7d102f } jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version jtag configure $_CHIPNAME.jrc -event setup \ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm" ################ # GDB target: the ARM, using SRAM1 for scratch. SRAM0 (also 8K) # and the ETB memory (4K) are other options, while trace is unused. # Little-endian; use the OpenOCD default. set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 0x2000 # be absolutely certain the JTAG clock will work with the worst-case # CLKIN = 20 MHz (best case: 30 MHz) even when no bootloader turns # on the PLL and starts using it. OK to speed up after clock setup. adapter_khz 1500 $_TARGETNAME configure -event "reset-start" { adapter_khz 1500 } arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb gdb_breakpoint_override hard arm7_9 dbgrq enable openocd-0.9.0/tcl/target/nuc910.cfg0000644000175000017500000000105712526202244013642 00000000000000# # Nuvoton nuc910 (previously W90P910) based soc # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME nuc910 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # set useful default set _CPUTAPID 0x07926f0f } set _TARGETNAME $_CHIPNAME.cpu jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/xmc1xxx.cfg0000644000175000017500000000102112526202244014232 00000000000000# # Infineon XMC1100/XMC1200/XMC1300 family (ARM Cortex-M0 @ 32 MHz) # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME xmc1000 } # # Only SWD and SPD supported # source [find target/swj-dp.tcl] if { [info exists CPUTAPID] } { set _CPU_SWD_TAPID $CPUTAPID } else { set _CPU_SWD_TAPID 0x0BB11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPU_SWD_TAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian little -chain-position $_TARGETNAME adapter_khz 1000 openocd-0.9.0/tcl/target/zynq_7000.cfg0000644000175000017500000000143212526202244014267 00000000000000# # Xilinx Zynq-7000 All Programmable SoC # # http://www.xilinx.com/products/silicon-devices/soc/zynq-7000/index.htm # set _CHIPNAME zynq set _TARGETNAME $_CHIPNAME.cpu jtag newtap zynq_pl bs -irlen 6 -ircapture 0x1 -irmask 0x03 \ -expected-id 0x23727093 \ -expected-id 0x03727093 jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4ba00477 target create ${_TARGETNAME}0 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase 0x80090000 target create ${_TARGETNAME}1 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 1 -dbgbase 0x80092000 target smp ${_TARGETNAME}0 ${_TARGETNAME}1 adapter_khz 1000 ${_TARGETNAME}0 configure -event reset-assert-post "cortex_a dbginit" ${_TARGETNAME}1 configure -event reset-assert-post "cortex_a dbginit" openocd-0.9.0/tcl/target/kl25z_hla.cfg0000644000175000017500000000016312526202244014413 00000000000000echo "WARNING: target/kl25z_hla.cfg is deprecated, please switch to target/kl25.cfg" source [find target/kl25.cfg] openocd-0.9.0/tcl/target/at91sam4lXX.cfg0000644000175000017500000000177412526202244014630 00000000000000# script for ATMEL sam4l, a CORTEX-M4 chip # source [find target/at91sam4XXX.cfg] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam4l 0x00000000 0 1 1 $_TARGETNAME # SAM4L SMAP will hold the CPU in reset if TCK is low when RESET_N # deasserts (see datasheet 42023E-SAM-07/2013 sec 8.11.3). # # smap_reset_deassert configures whether we want to run or halt out of reset, # then instruct the SMAP to let us out of reset. $_TARGETNAME configure -event reset-deassert-post "at91sam4l smap_reset_deassert" # SRST (wired to RESET_N) resets debug circuitry # srst_pulls_trst is not configured here to avoid an error raised in reset halt reset_config srst_gates_jtag # SAM4L starts from POR with SYSCLK set to 115kHz RCSYS, needs slow JTAG speed. # Datasheet does not specify SYSCLK to JTAG/SWD clock ratio. # Usually used SYSCLK/6 is hell slow, testing shows that debugging can work @ SYSCLK/2 # but your mileage may vary. adapter_khz 50 # System RC oscillator RCSYS starts in 3 cycles adapter_nsrst_delay 0 openocd-0.9.0/tcl/target/at91sam4sXX.cfg0000644000175000017500000000026112526202244014625 00000000000000# script for ATMEL sam4, a CORTEX-M4 chip # source [find target/at91sam4XXX.cfg] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam4 0x00400000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/am437x.cfg0000644000175000017500000013645312526202245013660 00000000000000source [find target/icepick.cfg] source [find mem_helper.tcl] ############################################################################### ## AM437x Registers ## ############################################################################### set PRCM_BASE_ADDR 0x44df0000 set REVISION_PRM [expr $PRCM_BASE_ADDR + 0x0000] set PRM_IRQSTATUS_MPU [expr $PRCM_BASE_ADDR + 0x0004] set PRM_IRQENABLE_MPU [expr $PRCM_BASE_ADDR + 0x0008] set PRM_IRQSTATUS_M3 [expr $PRCM_BASE_ADDR + 0x000c] set PRM_IRQENABLE_M3 [expr $PRCM_BASE_ADDR + 0x0010] set PM_MPU_PWRSTCTRL [expr $PRCM_BASE_ADDR + 0x0300] set PM_MPU_PWRSTST [expr $PRCM_BASE_ADDR + 0x0304] set RM_MPU_RSTST [expr $PRCM_BASE_ADDR + 0x0314] set RM_MPU_CONTEXT [expr $PRCM_BASE_ADDR + 0x0324] set PM_GFX_PWRSTCTRL [expr $PRCM_BASE_ADDR + 0x0400] set PM_GFX_PWRSTST [expr $PRCM_BASE_ADDR + 0x0404] set RM_GFX_RSTCTRL [expr $PRCM_BASE_ADDR + 0x0410] set RM_GFX_RSTST [expr $PRCM_BASE_ADDR + 0x0414] set RM_GFX_CONTEXT [expr $PRCM_BASE_ADDR + 0x0424] set RM_RTC_CONTEXT [expr $PRCM_BASE_ADDR + 0x0524] set RM_WKUP_RSTCTRL [expr $PRCM_BASE_ADDR + 0x2010] set RM_WKUP_RSTST [expr $PRCM_BASE_ADDR + 0x2014] set CM_L3_AON_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x2800] set CM_WKUP_DEBUGSS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2820] set CM_L3S_TSC_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x2900] set CM_WKUP_ADC_TSC_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2920] set CM_L4_WKUP_AON_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x2a00] set CM_WKUP_L4WKUP_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a20] set CM_WKUP_WKUP_M3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a28] set CM_WKUP_SYNCTIMER_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a30] set CM_WKUP_CLKDIV32K_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a38] set CM_WKUP_USBPHY0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a40] set CM_WKUP_USBPHY1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2a48] set CM_WKUP_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x2b00] set CM_WKUP_TIMER0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b20] set CM_WKUP_TIMER1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b28] set CM_WKUP_WDT0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b30] set CM_WKUP_WDT1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b38] set CM_WKUP_I2C0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b40] set CM_WKUP_UART0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b48] set CM_WKUP_SMARTREFLEX0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b50] set CM_WKUP_SMARTREFLEX1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b58] set CM_WKUP_CONTROL_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b60] set CM_WKUP_GPIO0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x2b68] set CM_CLKMODE_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d20] set CM_IDLEST_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d24] set CM_CLKSEL_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d2c] set CM_DIV_M4_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d38] set CM_DIV_M5_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d3c] set CM_DIV_M6_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d40] set CM_SSC_DELTAMSTEP_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d48] set CM_SSC_MODFREQDIV_DPLL_CORE [expr $PRCM_BASE_ADDR + 0x2d4c] set CM_CLKMODE_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d60] set CM_IDLEST_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d64] set CM_CLKSEL_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d6c] set CM_DIV_M2_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d70] set CM_SSC_DELTAMSTEP_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d88] set CM_SSC_MODFREQDIV_DPLL_MPU [expr $PRCM_BASE_ADDR + 0x2d8c] set CM_CLKMODE_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2da0] set CM_IDLEST_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2da4] set CM_CLKSEL_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2dac] set CM_DIV_M2_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2db0] set CM_DIV_M4_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2db8] set CM_SSC_DELTAMSTEP_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2dc8] set CM_SSC_MODFREQDIV_DPLL_DDR [expr $PRCM_BASE_ADDR + 0x2dcc] set CM_CLKMODE_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2de0] set CM_IDLEST_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2de4] set CM_CLKSEL_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2dec] set CM_DIV_M2_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2df0] set CM_CLKSEL2_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2e04] set CM_SSC_DELTAMSTEP_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2e08] set CM_SSC_MODFREQDIV_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2e0c] set CM_CLKDCOLDO_DPLL_PER [expr $PRCM_BASE_ADDR + 0x2e14] set CM_CLKMODE_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e20] set CM_IDLEST_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e24] set CM_CLKSEL_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e2c] set CM_DIV_M2_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e30] set CM_SSC_DELTAMSTEP_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e48] set CM_SSC_MODFREQDIV_DPLL_DISP [expr $PRCM_BASE_ADDR + 0x2e4c] set CM_CLKMODE_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e60] set CM_IDLEST_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e64] set CM_CLKSEL_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e6c] set CM_DIV_M2_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e70] set CM_CLKSEL2_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e84] set CM_SSC_DELTAMSTEP_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e88] set CM_SSC_MODFREQDIV_DPLL_EXTDEV [expr $PRCM_BASE_ADDR + 0x2e8c] set CM_SHADOW_FREQ_CONFIG1 [expr $PRCM_BASE_ADDR + 0x2fa0] set CM_SHADOW_FREQ_CONFIG2 [expr $PRCM_BASE_ADDR + 0x2fa4] set CM_CLKOUT1_CTRL [expr $PRCM_BASE_ADDR + 0x4100] set CM_DLL_CTRL [expr $PRCM_BASE_ADDR + 0x4104] set CM_CLKOUT2_CTRL [expr $PRCM_BASE_ADDR + 0x4108] set CLKSEL_TIMER1MS_CLK [expr $PRCM_BASE_ADDR + 0x4200] set CLKSEL_TIMER2_CLK [expr $PRCM_BASE_ADDR + 0x4204] set CLKSEL_TIMER3_CLK [expr $PRCM_BASE_ADDR + 0x4208] set CLKSEL_TIMER4_CLK [expr $PRCM_BASE_ADDR + 0x420c] set CLKSEL_TIMER5_CLK [expr $PRCM_BASE_ADDR + 0x4210] set CLKSEL_TIMER6_CLK [expr $PRCM_BASE_ADDR + 0x4214] set CLKSEL_TIMER7_CLK [expr $PRCM_BASE_ADDR + 0x4218] set CLKSEL_TIMER8_CLK [expr $PRCM_BASE_ADDR + 0x421c] set CLKSEL_TIMER9_CLK [expr $PRCM_BASE_ADDR + 0x4220] set CLKSEL_TIMER10_CLK [expr $PRCM_BASE_ADDR + 0x4224] set CLKSEL_TIMER11_CLK [expr $PRCM_BASE_ADDR + 0x4228] set CLKSEL_WDT1_CLK [expr $PRCM_BASE_ADDR + 0x422c] set CLKSEL_SYNCTIMER_CLK [expr $PRCM_BASE_ADDR + 0x4230] set CLKSEL_MAC_CLK [expr $PRCM_BASE_ADDR + 0x4234] set CLKSEL_CPTS_RFT_CLK [expr $PRCM_BASE_ADDR + 0x4238] set CLKSEL_GFX_FCLK [expr $PRCM_BASE_ADDR + 0x423c] set CLKSEL_GPIO0_DBCLK [expr $PRCM_BASE_ADDR + 0x4240] set CLKSEL_LCDC_PIXEL_CLK [expr $PRCM_BASE_ADDR + 0x4244] set CLKSEL_ICSS_OCP_CLK [expr $PRCM_BASE_ADDR + 0x4248] set CLKSEL_DLL_AGING_CLK [expr $PRCM_BASE_ADDR + 0x4250] set CLKSEL_USBPHY32KHZ_GCLK [expr $PRCM_BASE_ADDR + 0x4260] set CM_MPU_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8300] set CM_MPU_MPU_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8320] set CM_GFX_L3_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8400] set CM_GFX_GFX_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8420] set CM_RTC_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8500] set CM_RTC_RTC_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8520] set CM_PER_L3_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8800] set CM_PER_L3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8820] set CM_PER_AES0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8828] set CM_PER_DES_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8830] set CM_PER_CRYPTODMA_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8838] set CM_PER_L3_INSTR_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8840] set CM_PER_MSTR_EXPS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8848] set CM_PER_OCMCRAM_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8850] set CM_PER_SHA0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8858] set CM_PER_SLV_EXPS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8860] set CM_PER_VPFE0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8868] set CM_PER_VPFE1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8870] set CM_PER_TPCC_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8878] set CM_PER_TPTC0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8880] set CM_PER_TPTC1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8888] set CM_PER_TPTC2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8890] set CM_PER_DLL_AGING_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8898] set CM_PER_L4HS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x88a0] set CM_PER_L4FW_CLKCTRL [expr $PRCM_BASE_ADDR + 0x88a8] set CM_PER_L3S_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8a00] set CM_PER_GPMC_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a20] set CM_PER_IEEE5000_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a28] set CM_PER_MCASP0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a38] set CM_PER_MCASP1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a40] set CM_PER_MMC2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a48] set CM_PER_QSPI_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a58] set CM_PER_USB_OTG_SS0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a60] set CM_PER_USB_OTG_SS1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8a68] set CM_PER_ICSS_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8b00] set CM_PER_ICSS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8b20] set CM_PER_L4LS_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8c00] set CM_PER_L4LS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c20] set CM_PER_DCAN0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c28] set CM_PER_DCAN1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c30] set CM_PER_EPWMSS0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c38] set CM_PER_EPWMSS1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c40] set CM_PER_EPWMSS2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c48] set CM_PER_EPWMSS3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c50] set CM_PER_EPWMSS4_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c58] set CM_PER_EPWMSS5_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c60] set CM_PER_ELM_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c68] set CM_PER_GPIO1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c78] set CM_PER_GPIO2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c80] set CM_PER_GPIO3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c88] set CM_PER_GPIO4_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c90] set CM_PER_GPIO5_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8c98] set CM_PER_HDQ1W_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8ca0] set CM_PER_I2C1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8ca8] set CM_PER_I2C2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cb0] set CM_PER_MAILBOX0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cb8] set CM_PER_MMC0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cc0] set CM_PER_MMC1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cc8] set CM_PER_PKA_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cd0] set CM_PER_RNG_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8ce0] set CM_PER_SPARE0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8ce8] set CM_PER_SPARE1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8cf0] set CM_PER_SPI0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d00] set CM_PER_SPI1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d08] set CM_PER_SPI2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d10] set CM_PER_SPI3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d18] set CM_PER_SPI4_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d20] set CM_PER_SPINLOCK_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d28] set CM_PER_TIMER2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d30] set CM_PER_TIMER3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d38] set CM_PER_TIMER4_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d40] set CM_PER_TIMER5_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d48] set CM_PER_TIMER6_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d50] set CM_PER_TIMER7_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d58] set CM_PER_TIMER8_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d60] set CM_PER_TIMER9_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d68] set CM_PER_TIMER10_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d70] set CM_PER_TIMER11_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d78] set CM_PER_UART1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d80] set CM_PER_UART2_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d88] set CM_PER_UART3_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d90] set CM_PER_UART4_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8d98] set CM_PER_UART5_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8da0] set CM_PER_USBPHYOCP2SCP0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8db8] set CM_PER_USBPHYOCP2SCP1_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8dc0] set CM_PER_EMIF_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x8f00] set CM_PER_EMIF_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8f20] set CM_PER_DLL_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8f28] set CM_PER_EMIF_FW_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8f30] set CM_PER_OTFA_EMIF_CLKCTRL [expr $PRCM_BASE_ADDR + 0x8f38] set CM_PER_DSS_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x9200] set CM_PER_DSS_CLKCTRL [expr $PRCM_BASE_ADDR + 0x9220] set CM_PER_CPSW_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x9300] set CM_PER_CPGMAC0_CLKCTRL [expr $PRCM_BASE_ADDR + 0x9320] set CM_PER_OCPWP_L3_CLKSTCTRL [expr $PRCM_BASE_ADDR + 0x9400] set CM_PER_OCPWP_CLKCTRL [expr $PRCM_BASE_ADDR + 0x9420] set CONTROL_BASE_ADDR 0x44e10000 set CONTROL_STATUS [expr $CONTROL_BASE_ADDR + 0x0040] set DEVICE_ID [expr $CONTROL_BASE_ADDR + 0x0600] set DEV_FEATURE [expr $CONTROL_BASE_ADDR + 0x0604] set DEV_ATTRIBUTE [expr $CONTROL_BASE_ADDR + 0x0610] set MAC_ID0_LO [expr $CONTROL_BASE_ADDR + 0x0630] set MAC_ID0_HI [expr $CONTROL_BASE_ADDR + 0x0634] set MAC_ID1_LO [expr $CONTROL_BASE_ADDR + 0x0638] set MAC_ID1_HI [expr $CONTROL_BASE_ADDR + 0x063c] set USB_VID_PID [expr $CONTROL_BASE_ADDR + 0x07f4] set CONTROL_CONF_ECAP0_IN_PWM0_OUT [expr $CONTROL_BASE_ADDR + 0x0964] set CONTROL_CONF_SPI4_CS0 [expr $CONTROL_BASE_ADDR + 0x0a5c] set CONTROL_CONF_SPI2_SCLK [expr $CONTROL_BASE_ADDR + 0x0a60] set CONTROL_CONF_SPI2_D0 [expr $CONTROL_BASE_ADDR + 0x0a64] set CONTROL_CONF_XDMA_EVENT_INTR0 [expr $CONTROL_BASE_ADDR + 0x0a70] set CONTROL_CONF_XDMA_EVENT_INTR1 [expr $CONTROL_BASE_ADDR + 0x0a74] set CONTROL_CONF_GPMC_A0 [expr $CONTROL_BASE_ADDR + 0x0840] set DDR_IO_CTRL [expr $CONTROL_BASE_ADDR + 0x0e04] set VTP_CTRL_REG [expr $CONTROL_BASE_ADDR + 0x0e0c] set VREF_CTRL [expr $CONTROL_BASE_ADDR + 0x0e14] set DDR_CKE_CTRL [expr $CONTROL_BASE_ADDR + 0x131c] set DDR_ADDRCTRL_IOCTRL [expr $CONTROL_BASE_ADDR + 0x1404] set DDR_ADDRCTRL_WD0_IOCTRL [expr $CONTROL_BASE_ADDR + 0x1408] set DDR_ADDRCTRL_WD1_IOCTRL [expr $CONTROL_BASE_ADDR + 0x140c] set DDR_DATA0_IOCTRL [expr $CONTROL_BASE_ADDR + 0x1440] set DDR_DATA1_IOCTRL [expr $CONTROL_BASE_ADDR + 0x1444] set DDR_DATA2_IOCTRL [expr $CONTROL_BASE_ADDR + 0x1448] set DDR_DATA3_IOCTRL [expr $CONTROL_BASE_ADDR + 0x144c] set EMIF_SDRAM_CONFIG_EXT [expr $CONTROL_BASE_ADDR + 0x1460] set EMIF_SDRAM_STATUS_EXT [expr $CONTROL_BASE_ADDR + 0x1464] set GPIO0_BASE_ADDR 0x44e07000 set GPIO0_SYSCONFIG [expr $GPIO0_BASE_ADDR + 0x0010] set GPIO0_SYSSTATUS [expr $GPIO0_BASE_ADDR + 0x0114] set GPIO0_CTRL [expr $GPIO0_BASE_ADDR + 0x0130] set GPIO0_OE [expr $GPIO0_BASE_ADDR + 0x0134] set GPIO0_CLEARDATAOUT [expr $GPIO0_BASE_ADDR + 0x0190] set GPIO0_SETDATAOUT [expr $GPIO0_BASE_ADDR + 0x0194] set GPIO5_BASE_ADDR 0x48322000 set GPIO5_SYSCONFIG [expr $GPIO5_BASE_ADDR + 0x0010] set GPIO5_SYSSTATUS [expr $GPIO5_BASE_ADDR + 0x0114] set GPIO5_CTRL [expr $GPIO5_BASE_ADDR + 0x0130] set GPIO5_OE [expr $GPIO5_BASE_ADDR + 0x0134] set GPIO5_CLEARDATAOUT [expr $GPIO5_BASE_ADDR + 0x0190] set GPIO5_SETDATAOUT [expr $GPIO5_BASE_ADDR + 0x0194] set GPIO1_BASE_ADDR 0x4804c000 set GPIO1_SYSCONFIG [expr $GPIO1_BASE_ADDR + 0x0010] set GPIO1_SYSSTATUS [expr $GPIO1_BASE_ADDR + 0x0114] set GPIO1_CTRL [expr $GPIO1_BASE_ADDR + 0x0130] set GPIO1_OE [expr $GPIO1_BASE_ADDR + 0x0134] set GPIO1_CLEARDATAOUT [expr $GPIO1_BASE_ADDR + 0x0190] set GPIO1_SETDATAOUT [expr $GPIO1_BASE_ADDR + 0x0194] set EMIF_BASE_ADDR 0x4c000000 set EMIF_STATUS [expr $EMIF_BASE_ADDR + 0x0004] set EMIF_SDRAM_CONFIG [expr $EMIF_BASE_ADDR + 0x0008] set EMIF_SDRAM_CONFIG_2 [expr $EMIF_BASE_ADDR + 0x000c] set EMIF_SDRAM_REF_CTRL [expr $EMIF_BASE_ADDR + 0x0010] set EMIF_SDRAM_REF_CTRL_SHDW [expr $EMIF_BASE_ADDR + 0x0014] set EMIF_SDRAM_TIM_1 [expr $EMIF_BASE_ADDR + 0x0018] set EMIF_SDRAM_TIM_1_SHDW [expr $EMIF_BASE_ADDR + 0x001c] set EMIF_SDRAM_TIM_2 [expr $EMIF_BASE_ADDR + 0x0020] set EMIF_SDRAM_TIM_2_SHDW [expr $EMIF_BASE_ADDR + 0x0024] set EMIF_SDRAM_TIM_3 [expr $EMIF_BASE_ADDR + 0x0028] set EMIF_SDRAM_TIM_3_SHDW [expr $EMIF_BASE_ADDR + 0x002c] set EMIF_LPDDR2_NVM_TIM [expr $EMIF_BASE_ADDR + 0x0030] set EMIF_LPDDR2_NVM_TIM_SHDW [expr $EMIF_BASE_ADDR + 0x0034] set EMIF_PWR_MGMT_CTRL [expr $EMIF_BASE_ADDR + 0x0038] set EMIF_PWR_MGMT_CTRL_SHDW [expr $EMIF_BASE_ADDR + 0x003c] set EMIF_LPDDR2_MODE_REG_DATA [expr $EMIF_BASE_ADDR + 0x0040] set EMIF_LPDDR2_MODE_REG_CFG [expr $EMIF_BASE_ADDR + 0x0050] set EMIF_OCP_CONFIG [expr $EMIF_BASE_ADDR + 0x0054] set EMIF_OCP_CFG_VAL_1 [expr $EMIF_BASE_ADDR + 0x0058] set EMIF_OCP_CFG_VAL_2 [expr $EMIF_BASE_ADDR + 0x005c] set EMIF_IODFT_TLGC [expr $EMIF_BASE_ADDR + 0x0060] set EMIF_IODFT_CTRL_MISR_RSLT [expr $EMIF_BASE_ADDR + 0x0064] set EMIF_IODFT_ADDR_MISR_RSLT [expr $EMIF_BASE_ADDR + 0x0068] set EMIF_IODFT_DATA_MISR_RSLT_1 [expr $EMIF_BASE_ADDR + 0x006c] set EMIF_IODFT_DATA_MISR_RSLT_2 [expr $EMIF_BASE_ADDR + 0x0070] set EMIF_IODFT_DATA_MISR_RSLT_3 [expr $EMIF_BASE_ADDR + 0x0074] set EMIF_PERF_CNT_1 [expr $EMIF_BASE_ADDR + 0x0080] set EMIF_PERF_CNT_2 [expr $EMIF_BASE_ADDR + 0x0084] set EMIF_PERF_CNT_CFG [expr $EMIF_BASE_ADDR + 0x0088] set EMIF_PERF_CNT_SEL [expr $EMIF_BASE_ADDR + 0x008c] set EMIF_PERF_CNT_TIM [expr $EMIF_BASE_ADDR + 0x0090] set EMIF_MISC_REG [expr $EMIF_BASE_ADDR + 0x0094] set EMIF_DLL_CALIB_CTRL [expr $EMIF_BASE_ADDR + 0x0098] set EMIF_DLL_CALIB_CTRL_SHDW [expr $EMIF_BASE_ADDR + 0x009c] set EMIF_IRQ_EOI [expr $EMIF_BASE_ADDR + 0x00a0] set EMIF_IRQSTATUS_RAW_SYS [expr $EMIF_BASE_ADDR + 0x00a4] set EMIF_IRQSTATUS_SYS [expr $EMIF_BASE_ADDR + 0x00ac] set EMIF_IRQENABLE_SET_SYS [expr $EMIF_BASE_ADDR + 0x00b4] set EMIF_IRQENABLE_CLR_SYS [expr $EMIF_BASE_ADDR + 0x00bc] set EMIF_ZQ_CONFIG [expr $EMIF_BASE_ADDR + 0x00c8] set EMIF_TEMP_ALERT_CONFIG [expr $EMIF_BASE_ADDR + 0x00cc] set EMIF_OCP_ERR_LOG [expr $EMIF_BASE_ADDR + 0x00d0] set EMIF_RDWR_LVL_RMP_WIN [expr $EMIF_BASE_ADDR + 0x00d4] set EMIF_RDWR_LVL_RMP_CTRL [expr $EMIF_BASE_ADDR + 0x00d8] set EMIF_RDWR_LVL_CTRL [expr $EMIF_BASE_ADDR + 0x00dc] set EMIF_DDR_PHY_CTRL_1 [expr $EMIF_BASE_ADDR + 0x00e4] set EMIF_DDR_PHY_CTRL_1_SHDW [expr $EMIF_BASE_ADDR + 0x00e8] set EMIF_DDR_PHY_CTRL_2 [expr $EMIF_BASE_ADDR + 0x00ec] set EMIF_PRI_COS_MAP [expr $EMIF_BASE_ADDR + 0x0100] set EMIF_CONNID_COS_1_MAP [expr $EMIF_BASE_ADDR + 0x0104] set EMIF_CONNID_COS_2_MAP [expr $EMIF_BASE_ADDR + 0x0108] set ECC_CTRL [expr $EMIF_BASE_ADDR + 0x0110] set ECC_ADDR_RNG_1 [expr $EMIF_BASE_ADDR + 0x0114] set ECC_ADDR_RNG_2 [expr $EMIF_BASE_ADDR + 0x0118] set EMIF_RD_WR_EXEC_THRSH [expr $EMIF_BASE_ADDR + 0x0120] set COS_CONFIG [expr $EMIF_BASE_ADDR + 0x0124] set PHY_STATUS_1 [expr $EMIF_BASE_ADDR + 0x0144] set PHY_STATUS_2 [expr $EMIF_BASE_ADDR + 0x0148] set PHY_STATUS_3 [expr $EMIF_BASE_ADDR + 0x014c] set PHY_STATUS_4 [expr $EMIF_BASE_ADDR + 0x0150] set PHY_STATUS_5 [expr $EMIF_BASE_ADDR + 0x0154] set PHY_STATUS_6 [expr $EMIF_BASE_ADDR + 0x0158] set PHY_STATUS_7 [expr $EMIF_BASE_ADDR + 0x015c] set PHY_STATUS_8 [expr $EMIF_BASE_ADDR + 0x0160] set PHY_STATUS_9 [expr $EMIF_BASE_ADDR + 0x0164] set PHY_STATUS_10 [expr $EMIF_BASE_ADDR + 0x0168] set PHY_STATUS_11 [expr $EMIF_BASE_ADDR + 0x016c] set PHY_STATUS_12 [expr $EMIF_BASE_ADDR + 0x0170] set PHY_STATUS_13 [expr $EMIF_BASE_ADDR + 0x0174] set PHY_STATUS_14 [expr $EMIF_BASE_ADDR + 0x0178] set PHY_STATUS_15 [expr $EMIF_BASE_ADDR + 0x017c] set PHY_STATUS_16 [expr $EMIF_BASE_ADDR + 0x0180] set PHY_STATUS_17 [expr $EMIF_BASE_ADDR + 0x0184] set PHY_STATUS_18 [expr $EMIF_BASE_ADDR + 0x0188] set PHY_STATUS_19 [expr $EMIF_BASE_ADDR + 0x018c] set PHY_STATUS_20 [expr $EMIF_BASE_ADDR + 0x0190] set PHY_STATUS_21 [expr $EMIF_BASE_ADDR + 0x0194] set PHY_STATUS_22 [expr $EMIF_BASE_ADDR + 0x0198] set PHY_STATUS_23 [expr $EMIF_BASE_ADDR + 0x019c] set PHY_STATUS_24 [expr $EMIF_BASE_ADDR + 0x01a0] set PHY_STATUS_25 [expr $EMIF_BASE_ADDR + 0x01a4] set PHY_STATUS_26 [expr $EMIF_BASE_ADDR + 0x01a8] set PHY_STATUS_27 [expr $EMIF_BASE_ADDR + 0x01ac] set PHY_STATUS_28 [expr $EMIF_BASE_ADDR + 0x01b0] set EXT_PHY_CTRL_1 [expr $EMIF_BASE_ADDR + 0x0200] set EXT_PHY_CTRL_1_SHDW [expr $EMIF_BASE_ADDR + 0x0204] set EXT_PHY_CTRL_2 [expr $EMIF_BASE_ADDR + 0x0208] set EXT_PHY_CTRL_2_SHDW [expr $EMIF_BASE_ADDR + 0x020c] set EXT_PHY_CTRL_3 [expr $EMIF_BASE_ADDR + 0x0210] set EXT_PHY_CTRL_3_SHDW [expr $EMIF_BASE_ADDR + 0x0214] set EXT_PHY_CTRL_4 [expr $EMIF_BASE_ADDR + 0x0218] set EXT_PHY_CTRL_4_SHDW [expr $EMIF_BASE_ADDR + 0x021c] set EXT_PHY_CTRL_5 [expr $EMIF_BASE_ADDR + 0x0220] set EXT_PHY_CTRL_5_SHDW [expr $EMIF_BASE_ADDR + 0x0224] set EXT_PHY_CTRL_6 [expr $EMIF_BASE_ADDR + 0x0228] set EXT_PHY_CTRL_6_SHDW [expr $EMIF_BASE_ADDR + 0x022c] set EXT_PHY_CTRL_7 [expr $EMIF_BASE_ADDR + 0x0230] set EXT_PHY_CTRL_7_SHDW [expr $EMIF_BASE_ADDR + 0x0234] set EXT_PHY_CTRL_8 [expr $EMIF_BASE_ADDR + 0x0238] set EXT_PHY_CTRL_8_SHDW [expr $EMIF_BASE_ADDR + 0x023c] set EXT_PHY_CTRL_9 [expr $EMIF_BASE_ADDR + 0x0240] set EXT_PHY_CTRL_9_SHDW [expr $EMIF_BASE_ADDR + 0x0244] set EXT_PHY_CTRL_10 [expr $EMIF_BASE_ADDR + 0x0248] set EXT_PHY_CTRL_10_SHDW [expr $EMIF_BASE_ADDR + 0x024c] set EXT_PHY_CTRL_11 [expr $EMIF_BASE_ADDR + 0x0250] set EXT_PHY_CTRL_11_SHDW [expr $EMIF_BASE_ADDR + 0x0254] set EXT_PHY_CTRL_12 [expr $EMIF_BASE_ADDR + 0x0258] set EXT_PHY_CTRL_12_SHDW [expr $EMIF_BASE_ADDR + 0x025c] set EXT_PHY_CTRL_13 [expr $EMIF_BASE_ADDR + 0x0260] set EXT_PHY_CTRL_13_SHDW [expr $EMIF_BASE_ADDR + 0x0264] set EXT_PHY_CTRL_14 [expr $EMIF_BASE_ADDR + 0x0268] set EXT_PHY_CTRL_14_SHDW [expr $EMIF_BASE_ADDR + 0x026c] set EXT_PHY_CTRL_15 [expr $EMIF_BASE_ADDR + 0x0270] set EXT_PHY_CTRL_15_SHDW [expr $EMIF_BASE_ADDR + 0x0274] set EXT_PHY_CTRL_16 [expr $EMIF_BASE_ADDR + 0x0278] set EXT_PHY_CTRL_16_SHDW [expr $EMIF_BASE_ADDR + 0x027c] set EXT_PHY_CTRL_17 [expr $EMIF_BASE_ADDR + 0x0280] set EXT_PHY_CTRL_17_SHDW [expr $EMIF_BASE_ADDR + 0x0284] set EXT_PHY_CTRL_18 [expr $EMIF_BASE_ADDR + 0x0288] set EXT_PHY_CTRL_18_SHDW [expr $EMIF_BASE_ADDR + 0x028c] set EXT_PHY_CTRL_19 [expr $EMIF_BASE_ADDR + 0x0290] set EXT_PHY_CTRL_19_SHDW [expr $EMIF_BASE_ADDR + 0x0294] set EXT_PHY_CTRL_20 [expr $EMIF_BASE_ADDR + 0x0298] set EXT_PHY_CTRL_20_SHDW [expr $EMIF_BASE_ADDR + 0x029c] set EXT_PHY_CTRL_21 [expr $EMIF_BASE_ADDR + 0x02a0] set EXT_PHY_CTRL_21_SHDW [expr $EMIF_BASE_ADDR + 0x02a4] set EXT_PHY_CTRL_22 [expr $EMIF_BASE_ADDR + 0x02a8] set EXT_PHY_CTRL_22_SHDW [expr $EMIF_BASE_ADDR + 0x02ac] set EXT_PHY_CTRL_23 [expr $EMIF_BASE_ADDR + 0x02b0] set EXT_PHY_CTRL_23_SHDW [expr $EMIF_BASE_ADDR + 0x02b4] set EXT_PHY_CTRL_24 [expr $EMIF_BASE_ADDR + 0x02b8] set EXT_PHY_CTRL_24_SHDW [expr $EMIF_BASE_ADDR + 0x02bc] set EXT_PHY_CTRL_25 [expr $EMIF_BASE_ADDR + 0x02c0] set EXT_PHY_CTRL_25_SHDW [expr $EMIF_BASE_ADDR + 0x02c4] set EXT_PHY_CTRL_26 [expr $EMIF_BASE_ADDR + 0x02c8] set EXT_PHY_CTRL_26_SHDW [expr $EMIF_BASE_ADDR + 0x02cc] set EXT_PHY_CTRL_27 [expr $EMIF_BASE_ADDR + 0x02d0] set EXT_PHY_CTRL_27_SHDW [expr $EMIF_BASE_ADDR + 0x02d4] set EXT_PHY_CTRL_28 [expr $EMIF_BASE_ADDR + 0x02d8] set EXT_PHY_CTRL_28_SHDW [expr $EMIF_BASE_ADDR + 0x02dc] set EXT_PHY_CTRL_29 [expr $EMIF_BASE_ADDR + 0x02e0] set EXT_PHY_CTRL_29_SHDW [expr $EMIF_BASE_ADDR + 0x02e4] set EXT_PHY_CTRL_30 [expr $EMIF_BASE_ADDR + 0x02e8] set EXT_PHY_CTRL_30_SHDW [expr $EMIF_BASE_ADDR + 0x02ec] set EXT_PHY_CTRL_31 [expr $EMIF_BASE_ADDR + 0x02f0] set EXT_PHY_CTRL_31_SHDW [expr $EMIF_BASE_ADDR + 0x02f4] set EXT_PHY_CTRL_32 [expr $EMIF_BASE_ADDR + 0x02f8] set EXT_PHY_CTRL_32_SHDW [expr $EMIF_BASE_ADDR + 0x02fc] set EXT_PHY_CTRL_33 [expr $EMIF_BASE_ADDR + 0x0300] set EXT_PHY_CTRL_33_SHDW [expr $EMIF_BASE_ADDR + 0x0304] set EXT_PHY_CTRL_34 [expr $EMIF_BASE_ADDR + 0x0308] set EXT_PHY_CTRL_34_SHDW [expr $EMIF_BASE_ADDR + 0x030c] set EXT_PHY_CTRL_35 [expr $EMIF_BASE_ADDR + 0x0310] set EXT_PHY_CTRL_35_SHDW [expr $EMIF_BASE_ADDR + 0x0314] set EXT_PHY_CTRL_36 [expr $EMIF_BASE_ADDR + 0x0318] set EXT_PHY_CTRL_36_SHDW [expr $EMIF_BASE_ADDR + 0x031c] set WDT1_BASE_ADDR 0x44e35000 set WDT1_W_PEND_WSPR [expr $WDT1_BASE_ADDR + 0x0034] set WDT1_WSPR [expr $WDT1_BASE_ADDR + 0x0048] set RTC_BASE_ADDR 0x44e3e000 set RTC_KICK0R [expr $RTC_BASE_ADDR + 0x6c] set RTC_KICK1R [expr $RTC_BASE_ADDR + 0x70] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME am437x } set JRC_MODULE icepick_d set DEBUGSS_MODULE debugss set M3_MODULE m3_wakeupss set JRC_NAME $_CHIPNAME.$JRC_MODULE set DEBUGSS_NAME $_CHIPNAME.$DEBUGSS_MODULE set M3_NAME $_CHIPNAME.$M3_MODULE set _TARGETNAME $_CHIPNAME.mpuss # # M3 WakeupSS DAP # if { [info exists M3_DAP_TAPID] } { set _M3_DAP_TAPID $M3_DAP_TAPID } else { set _M3_DAP_TAPID 0x4b6b902f } jtag newtap $_CHIPNAME $M3_MODULE -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_M3_DAP_TAPID -disable jtag configure $M3_NAME -event tap-enable "icepick_d_tapenable $JRC_NAME 11 0" # # DebugSS DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x46b6902f } jtag newtap $_CHIPNAME $DEBUGSS_MODULE -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $DEBUGSS_NAME -event tap-enable "icepick_d_tapenable $JRC_NAME 12 0" # # ICEpick-D (JTAG route controller) # if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b98c02f } jtag newtap $_CHIPNAME $JRC_MODULE -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version jtag configure $JRC_NAME -event setup "jtag tapenable $DEBUGSS_NAME" # some TCK tycles are required to activate the DEBUG power domain jtag configure $JRC_NAME -event post-reset "runtest 100" # # Cortex A9 target # target create $_TARGETNAME cortex_a -chain-position $DEBUGSS_NAME -coreid 0 -dbgbase 0x80000000 # SRAM: 256K at 0x4030.0000 $_TARGETNAME configure -work-area-phys 0x40300000 -work-area-size 0x40000 # Disables watchdog timer after reset otherwise board won't stay in # halted state. proc disable_watchdog { } { global WDT1_WSPR global WDT1_W_PEND_WSPR global _TARGETNAME set curstate [$_TARGETNAME curstate] if { [string compare $curstate halted] == 0 } { set WDT_DISABLE_SEQ1 0xaaaa set WDT_DISABLE_SEQ2 0x5555 mww phys $WDT1_WSPR $WDT_DISABLE_SEQ1 # Empty body to make sure this executes as fast as possible. # We don't want any delays here otherwise romcode might start # executing and end up changing state of certain IPs. while { [expr [mrw $WDT1_W_PEND_WSPR] & 0x10] } { } mww phys $WDT1_WSPR $WDT_DISABLE_SEQ2 while { [expr [mrw $WDT1_W_PEND_WSPR] & 0x10] } { } } } proc ceil { x y } { return [ expr ($x + $y - 1) / $y ] } proc device_type { } { global CONTROL_STATUS set tmp [ mrw $CONTROL_STATUS ] set tmp [ expr $tmp & 0x700 ] set tmp [ expr $tmp >> 8 ] return $tmp } proc get_input_clock_frequency { } { global CONTROL_STATUS if { [ device_type ] != 3 } { error "Unknown device type\n" return -1 } set freq [ mrw $CONTROL_STATUS ] set freq [ expr $freq & 0x00c00000 ] set freq [ expr $freq >> 22 ] switch $freq { 0 { set CLKIN 19200000 } 1 { set CLKIN 24000000 } 2 { set CLKIN 25000000 } 3 { set CLKIN 26000000 } } return $CLKIN } proc mpu_pll_config { CLKIN N M M2 } { global CM_CLKMODE_DPLL_MPU global CM_CLKSEL_DPLL_MPU global CM_DIV_M2_DPLL_MPU global CM_IDLEST_DPLL_MPU set clksel [ mrw $CM_CLKSEL_DPLL_MPU ] set div_m2 [ mrw $CM_DIV_M2_DPLL_MPU ] mww $CM_CLKMODE_DPLL_MPU 0x4 while { !([ mrw $CM_IDLEST_DPLL_MPU ] & 0x0100) } { } set clksel [ expr $clksel & (~0x7ffff) ] set clksel [ expr $clksel | ($M << 0x8) | $N ] mww $CM_CLKSEL_DPLL_MPU $clksel set div_m2 [ expr $div_m2 & (~0x1f) ] set div_m2 [ expr $div_m2 | $M2 ] mww $CM_DIV_M2_DPLL_MPU $div_m2 mww $CM_CLKMODE_DPLL_MPU 0x7 while { [ mrw $CM_IDLEST_DPLL_MPU ] != 1 } { } echo "MPU DPLL locked" } proc core_pll_config { CLKIN N M M4 M5 M6 } { global CM_CLKMODE_DPLL_CORE global CM_CLKSEL_DPLL_CORE global CM_DIV_M4_DPLL_CORE global CM_DIV_M5_DPLL_CORE global CM_DIV_M6_DPLL_CORE global CM_IDLEST_DPLL_CORE set clksel [ mrw $CM_CLKSEL_DPLL_CORE ] mww $CM_CLKMODE_DPLL_CORE 0x4 while { !([ mrw $CM_IDLEST_DPLL_CORE ] & 0x0100) } { } set clksel [ expr $clksel & (~0x7ffff) ] set clksel [ expr $clksel | ($M << 0x8) | $N ] mww $CM_CLKSEL_DPLL_CORE $clksel mww $CM_DIV_M4_DPLL_CORE $M4 mww $CM_DIV_M5_DPLL_CORE $M5 mww $CM_DIV_M6_DPLL_CORE $M6 mww $CM_CLKMODE_DPLL_CORE 0x7 while { !([ mrw $CM_IDLEST_DPLL_CORE ] & 0x01) } { } echo "CORE DPLL locked" } proc per_pll_config { CLKIN N M M2 } { global CM_CLKMODE_DPLL_PER global CM_CLKSEL_DPLL_PER global CM_DIV_M2_DPLL_PER global CM_IDLEST_DPLL_PER set x [ expr $M * $CLKIN / 1000000 ] set y [ expr ($N + 1) * 250 ] set sd [ ceil $x $y ] set clksel [ mrw $CM_CLKSEL_DPLL_PER ] set div_m2 [ mrw $CM_DIV_M2_DPLL_PER ] mww $CM_CLKMODE_DPLL_PER 0x4 while { !([ mrw $CM_IDLEST_DPLL_PER ] & 0x0100) } { } set clksel [ expr $clksel & (~0xff0fffff) ] set clksel [ expr $clksel | ($M << 0x8) | $N ] set clksel [ expr $clksel | ($sd << 24) ] mww $CM_CLKSEL_DPLL_PER $clksel set div_m2 [ expr 0xffffff80 | $M2 ] mww $CM_CLKMODE_DPLL_PER 0x7 while { !([ mrw $CM_IDLEST_DPLL_PER ] & 0x01) } { } echo "PER DPLL locked" } proc ddr_pll_config { CLKIN N M M2 M4 } { global CM_CLKMODE_DPLL_DDR global CM_CLKSEL_DPLL_DDR global CM_DIV_M2_DPLL_DDR global CM_DIV_M4_DPLL_DDR global CM_IDLEST_DPLL_DDR set clksel [ mrw $CM_CLKSEL_DPLL_DDR ] set div_m2 [ mrw $CM_DIV_M2_DPLL_DDR ] mww $CM_CLKMODE_DPLL_DDR 0x4 while { !([ mrw $CM_IDLEST_DPLL_DDR ] & 0x0100) } { } set clksel [ expr $clksel & (~0x7ffff) ] set clksel [ expr $clksel | ($M << 8) | $N ] mww $CM_CLKSEL_DPLL_DDR $clksel set div_m2 [ expr ($div_m2 & 0xffffffe0) | $M2 ] mww $CM_DIV_M2_DPLL_DDR $div_m2 mww $CM_DIV_M4_DPLL_DDR $M4 mww $CM_CLKMODE_DPLL_DDR 0x7 while { !([ mrw $CM_IDLEST_DPLL_DDR ] & 0x01) } { } echo "DDR DPLL Locked" } proc config_opp100 { } { set CLKIN [ get_input_clock_frequency ] if { $CLKIN == -1 } { return -1 } switch $CLKIN { 24000000 { mpu_pll_config $CLKIN 0 25 1 core_pll_config $CLKIN 2 125 10 8 4 per_pll_config $CLKIN 9 400 5 ddr_pll_config $CLKIN 2 50 1 2 } 25000000 { mpu_pll_config $CLKIN 0 24 1 core_pll_config $CLKIN 0 40 10 8 4 per_pll_config $CLKIN 9 384 5 ddr_pll_config $CLKIN 0 16 1 2 } 26000000 { mpu_pll_config $CLKIN 12 300 1 core_pll_config $CLKIN 12 500 10 8 4 per_pll_config $CLKIN 12 480 5 ddr_pll_config $CLKIN 12 200 1 2 } 19200000 { mpu_pll_config $CLKIN 3 125 1 core_pll_config $CLKIN 11 625 10 8 4 per_pll_config $CLKIN 7 400 5 ddr_pll_config $CLKIN 2 125 1 2 } } } proc emif_prcm_clk_enable { } { global CM_PER_EMIF_FW_CLKCTRL global CM_PER_EMIF_CLKCTRL mww $CM_PER_EMIF_FW_CLKCTRL 0x02 mww $CM_PER_EMIF_CLKCTRL 0x02 while { [ mrw $CM_PER_EMIF_CLKCTRL ] != 0x02 } { } } proc vtp_enable { } { global VTP_CTRL_REG set vtp [ expr [ mrw $VTP_CTRL_REG ] | 0x40 ] mww $VTP_CTRL_REG $vtp set vtp [ expr [ mrw $VTP_CTRL_REG ] & ~0x01 ] mww $VTP_CTRL_REG $vtp set vtp [ expr [ mrw $VTP_CTRL_REG ] | 0x01 ] mww $VTP_CTRL_REG $vtp } proc config_ddr_ioctrl { } { global DDR_ADDRCTRL_IOCTRL global DDR_ADDRCTRL_WD0_IOCTRL global DDR_ADDRCTRL_WD1_IOCTRL global DDR_CKE_CTRL global DDR_DATA0_IOCTRL global DDR_DATA1_IOCTRL global DDR_DATA2_IOCTRL global DDR_DATA3_IOCTRL global DDR_IO_CTRL mww $DDR_ADDRCTRL_IOCTRL 0x84 mww $DDR_ADDRCTRL_WD0_IOCTRL 0x00 mww $DDR_ADDRCTRL_WD1_IOCTRL 0x00 mww $DDR_DATA0_IOCTRL 0x84 mww $DDR_DATA1_IOCTRL 0x84 mww $DDR_DATA2_IOCTRL 0x84 mww $DDR_DATA3_IOCTRL 0x84 mww $DDR_IO_CTRL 0x00 mww $DDR_CKE_CTRL 0x03 } proc config_ddr_phy { } { global EMIF_DDR_PHY_CTRL_1 global EMIF_DDR_PHY_CTRL_1_SHDW global EXT_PHY_CTRL_1 global EXT_PHY_CTRL_1_SHDW global EXT_PHY_CTRL_2 global EXT_PHY_CTRL_2_SHDW global EXT_PHY_CTRL_3 global EXT_PHY_CTRL_3_SHDW global EXT_PHY_CTRL_4 global EXT_PHY_CTRL_4_SHDW global EXT_PHY_CTRL_5 global EXT_PHY_CTRL_5_SHDW global EXT_PHY_CTRL_6 global EXT_PHY_CTRL_6_SHDW global EXT_PHY_CTRL_7 global EXT_PHY_CTRL_7_SHDW global EXT_PHY_CTRL_8 global EXT_PHY_CTRL_8_SHDW global EXT_PHY_CTRL_9 global EXT_PHY_CTRL_9_SHDW global EXT_PHY_CTRL_10 global EXT_PHY_CTRL_10_SHDW global EXT_PHY_CTRL_11 global EXT_PHY_CTRL_11_SHDW global EXT_PHY_CTRL_12 global EXT_PHY_CTRL_12_SHDW global EXT_PHY_CTRL_13 global EXT_PHY_CTRL_13_SHDW global EXT_PHY_CTRL_14 global EXT_PHY_CTRL_14_SHDW global EXT_PHY_CTRL_15 global EXT_PHY_CTRL_15_SHDW global EXT_PHY_CTRL_16 global EXT_PHY_CTRL_16_SHDW global EXT_PHY_CTRL_17 global EXT_PHY_CTRL_17_SHDW global EXT_PHY_CTRL_18 global EXT_PHY_CTRL_18_SHDW global EXT_PHY_CTRL_19 global EXT_PHY_CTRL_19_SHDW global EXT_PHY_CTRL_20 global EXT_PHY_CTRL_20_SHDW global EXT_PHY_CTRL_21 global EXT_PHY_CTRL_21_SHDW global EXT_PHY_CTRL_22 global EXT_PHY_CTRL_22_SHDW global EXT_PHY_CTRL_23 global EXT_PHY_CTRL_23_SHDW global EXT_PHY_CTRL_24 global EXT_PHY_CTRL_24_SHDW global EXT_PHY_CTRL_25 global EXT_PHY_CTRL_25_SHDW global EXT_PHY_CTRL_26 global EXT_PHY_CTRL_26_SHDW global EXT_PHY_CTRL_27 global EXT_PHY_CTRL_27_SHDW global EXT_PHY_CTRL_28 global EXT_PHY_CTRL_28_SHDW global EXT_PHY_CTRL_29 global EXT_PHY_CTRL_29_SHDW global EXT_PHY_CTRL_30 global EXT_PHY_CTRL_30_SHDW global EXT_PHY_CTRL_31 global EXT_PHY_CTRL_31_SHDW global EXT_PHY_CTRL_32 global EXT_PHY_CTRL_32_SHDW global EXT_PHY_CTRL_33 global EXT_PHY_CTRL_33_SHDW global EXT_PHY_CTRL_34 global EXT_PHY_CTRL_34_SHDW global EXT_PHY_CTRL_35 global EXT_PHY_CTRL_35_SHDW global EXT_PHY_CTRL_36 global EXT_PHY_CTRL_36_SHDW mww $EMIF_DDR_PHY_CTRL_1 0x8009 mww $EMIF_DDR_PHY_CTRL_1_SHDW 0x8009 set slave_ratio 0x80 set gatelvl_init_ratio 0x20 set wr_dqs_slave_delay 0x60 set rd_dqs_slave_delay 0x60 set dq_offset 0x40 set gatelvl_init_mode 0x01 set wr_data_slave_delay 0x80 set gatelvl_num_dq0 0x0f set wrlvl_num_dq0 0x0f mww $EXT_PHY_CTRL_1 [ expr ($slave_ratio << 20) | ($slave_ratio << 10) | $slave_ratio ] mww $EXT_PHY_CTRL_1_SHDW [ expr ($slave_ratio << 20) | ($slave_ratio << 10) | $slave_ratio ] mww $EXT_PHY_CTRL_26 [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_26_SHDW [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_27 [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_27_SHDW [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_28 [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_28_SHDW [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_29 [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_29_SHDW [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_30 [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_30_SHDW [ expr ($gatelvl_init_ratio << 16) | $gatelvl_init_ratio ] mww $EXT_PHY_CTRL_31 0x00 mww $EXT_PHY_CTRL_31_SHDW 0x00 mww $EXT_PHY_CTRL_32 0x00 mww $EXT_PHY_CTRL_32_SHDW 0x00 mww $EXT_PHY_CTRL_33 0x00 mww $EXT_PHY_CTRL_33_SHDW 0x00 mww $EXT_PHY_CTRL_34 0x00 mww $EXT_PHY_CTRL_34_SHDW 0x00 mww $EXT_PHY_CTRL_35 0x00 mww $EXT_PHY_CTRL_35_SHDW 0x00 mww $EXT_PHY_CTRL_22 0x00 mww $EXT_PHY_CTRL_22_SHDW 0x00 mww $EXT_PHY_CTRL_23 [ expr ($wr_dqs_slave_delay << 16) | $rd_dqs_slave_delay ] mww $EXT_PHY_CTRL_23_SHDW [ expr ($wr_dqs_slave_delay << 16) | $rd_dqs_slave_delay ] mww $EXT_PHY_CTRL_24 [ expr ($dq_offset << 24) | ($gatelvl_init_mode << 16) | $wr_data_slave_delay ] mww $EXT_PHY_CTRL_24_SHDW [ expr ($dq_offset << 24) | ($gatelvl_init_mode << 16) | $wr_data_slave_delay << 0 ] mww $EXT_PHY_CTRL_25 [ expr ($dq_offset << 21) | ($dq_offset << 14) | ($dq_offset << 7) | $dq_offset ] mww $EXT_PHY_CTRL_25_SHDW [ expr ($dq_offset << 21) | ($dq_offset << 14) | ($dq_offset << 7) | $dq_offset ] mww $EXT_PHY_CTRL_36 [ expr ($wrlvl_num_dq0 << 4) | $gatelvl_num_dq0 ] mww $EXT_PHY_CTRL_36_SHDW [ expr ($wrlvl_num_dq0 << 4) | $gatelvl_num_dq0 ] } proc config_ddr_timing { } { global EMIF_SDRAM_TIM_1 global EMIF_SDRAM_TIM_2 global EMIF_SDRAM_TIM_3 global EMIF_SDRAM_TIM_1_SHDW global EMIF_SDRAM_TIM_2_SHDW global EMIF_SDRAM_TIM_3_SHDW global EMIF_ZQ_CONFIG mww $EMIF_SDRAM_TIM_1 0xeaaad4db mww $EMIF_SDRAM_TIM_1_SHDW 0xeaaad4db mww $EMIF_SDRAM_TIM_2 0x266b7fda mww $EMIF_SDRAM_TIM_2_SHDW 0x266b7fda mww $EMIF_SDRAM_TIM_3 0x107f8678 mww $EMIF_SDRAM_TIM_3_SHDW 0x107f8678 mww $EMIF_ZQ_CONFIG 0x50074be4 } proc config_ddr_pm { } { global EMIF_PWR_MGMT_CTRL global EMIF_PWR_MGMT_CTRL_SHDW global EMIF_DLL_CALIB_CTRL global EMIF_DLL_CALIB_CTRL_SHDW global EMIF_TEMP_ALERT_CONFIG mww $EMIF_PWR_MGMT_CTRL 0x00 mww $EMIF_PWR_MGMT_CTRL_SHDW 0x00 mww $EMIF_DLL_CALIB_CTRL 0x00050000 mww $EMIF_DLL_CALIB_CTRL_SHDW 0x00050000 mww $EMIF_TEMP_ALERT_CONFIG 0x00 } proc config_ddr_priority { } { global EMIF_PRI_COS_MAP global EMIF_CONNID_COS_1_MAP global EMIF_CONNID_COS_2_MAP global EMIF_RD_WR_EXEC_THRSH global COS_CONFIG mww $EMIF_PRI_COS_MAP 0x00 mww $EMIF_CONNID_COS_1_MAP 0x00 mww $EMIF_CONNID_COS_2_MAP 0x0 mww $EMIF_RD_WR_EXEC_THRSH 0x0405 mww $COS_CONFIG 0x00ffffff } proc config_ddr3 { SDRAM_CONFIG } { global CM_DLL_CTRL global EMIF_IODFT_TLGC global EMIF_RDWR_LVL_CTRL global EMIF_RDWR_LVL_RMP_CTRL global EMIF_SDRAM_CONFIG global EMIF_SDRAM_CONFIG_EXT global EMIF_SDRAM_REF_CTRL global EMIF_SDRAM_REF_CTRL_SHDW global EMIF_STATUS global EXT_PHY_CTRL_36 global EXT_PHY_CTRL_36_SHDW emif_prcm_clk_enable vtp_enable set dll [ expr [ mrw $CM_DLL_CTRL ] & ~0x01 ] mww $CM_DLL_CTRL $dll while { !([ mrw $CM_DLL_CTRL ] & 0x04) } { } config_ddr_ioctrl mww $EMIF_SDRAM_CONFIG_EXT 0xc163 mww $EMIF_IODFT_TLGC 0x2011 mww $EMIF_IODFT_TLGC 0x2411 mww $EMIF_IODFT_TLGC 0x2011 mww $EMIF_SDRAM_REF_CTRL 0x80003000 config_ddr_phy mww $EMIF_IODFT_TLGC 0x2011 mww $EMIF_IODFT_TLGC 0x2411 mww $EMIF_IODFT_TLGC 0x2011 config_ddr_timing config_ddr_pm config_ddr_priority mww $EMIF_SDRAM_REF_CTRL 0x3000 mww $EMIF_SDRAM_CONFIG $SDRAM_CONFIG mww $EMIF_SDRAM_REF_CTRL 0x0c30 mww $EMIF_SDRAM_REF_CTRL_SHDW 0x0c30 sleep 10 set tmp [ expr [ mrw $EXT_PHY_CTRL_36 ] | 0x0100 ] mww $EXT_PHY_CTRL_36 $tmp mww $EXT_PHY_CTRL_36_SHDW $tmp mww $EMIF_RDWR_LVL_RMP_CTRL 0x80000000 mww $EMIF_RDWR_LVL_CTRL 0x80000000 while { [ mrw $EMIF_RDWR_LVL_CTRL ] & 0x80000000 } { } if { [ mrw $EMIF_STATUS ] & 0x70 } { error "DDR3 Hardware Leveling incomplete!!!" } } proc init_platform { SDRAM_CONFIG } { config_opp100 config_ddr3 $SDRAM_CONFIG # now that PLLs are configured, we can run JTAG at full speed adapter_khz 16000 } $_TARGETNAME configure -event reset-start { adapter_khz 1000 } $_TARGETNAME configure -event reset-init { init_platform 0x61a013b2 } $_TARGETNAME configure -event reset-end { disable_watchdog } openocd-0.9.0/tcl/target/hilscher_netx10.cfg0000644000175000017500000000141112526202245015616 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ #Hilscher netX 10 CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME netx10 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x25966021 } # jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # that TAP is associated with a target set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/stellaris.cfg0000644000175000017500000001227212526202245014627 00000000000000# TI/Luminary Stellaris LM3S chip family # Some devices have errata in returning their device class. # DEVICECLASS is provided as a manual override # Manual setting of a device class of 0xff is not allowed global _DEVICECLASS if { [info exists DEVICECLASS] } { set _DEVICECLASS $DEVICECLASS } else { set _DEVICECLASS 0xff } # Luminary chips support both JTAG and SWD transports. # Adapt based on what transport is active. source [find target/swj-dp.tcl] # For now we ignore the SPI and UART options, which # are usable only for ISP style initial flash programming. if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lm3s } # CPU TAP ID 0x1ba00477 for early Sandstorm parts # CPU TAP ID 0x2ba00477 for later SandStorm parts, e.g. lm3s811 Rev C2 # CPU TAP ID 0x3ba00477 for Cortex-M3 r1p2 (on Fury, DustDevil) # CPU TAP ID 0x4ba00477 for Cortex-M3 r2p0 (on Tempest, Firestorm) # CPU TAP ID 0x4ba00477 for Cortex-M4 r0p1 (on Blizzard) # ... we'll ignore the JTAG version field, rather than list every # chip revision that turns up. if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0ba00477 } # SWD DAP, and JTAG TAP, take same params for now; # ... even though SWD ignores all except TAPID, and # JTAG shouldn't need anything more then irlen. (and TAPID). swj_newdap $_CHIPNAME cpu -irlen 4 -irmask 0xf \ -expected-id $_CPUTAPID -ignore-version if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { # default to 2K working area set _WORKAREASIZE 0x800 } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu # 8K working area at base of ram, not backed up # # NOTE: you may need or want to reconfigure the work area; # some parts have just 6K, and you may want to use other # addresses (at end of mem not beginning) or back it up. $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE # JTAG speed ... slow enough to work with a 12 MHz RC oscillator; # LM3S parts don't support RTCK # # NOTE: this may be increased by a reset-init handler, after it # configures and enables the PLL. Or you might need to decrease # this, if you're using a slower clock. adapter_khz 500 source [find mem_helper.tcl] proc reset_peripherals {family} { source [find chip/ti/lm3s/lm3s.tcl] echo "Resetting Core Peripherals" # Disable the PLL and the system clock divider (nop if disabled) mmw $SYSCTL_RCC 0 $SYSCTL_RCC_USESYSDIV mmw $SYSCTL_RCC2 $SYSCTL_RCC2_BYPASS2 0 # RCC and RCC2 to their reset values mww $SYSCTL_RCC [expr (0x078e3ad0 | ([mrw $SYSCTL_RCC] & $SYSCTL_RCC_MOSCDIS))] mww $SYSCTL_RCC2 0x07806810 mww $SYSCTL_RCC 0x078e3ad1 # Reset the deep sleep clock configuration register mww $SYSCTL_DSLPCLKCFG 0x07800000 # Reset the clock gating registers mww $SYSCTL_RCGC0 0x00000040 mww $SYSCTL_RCGC1 0 mww $SYSCTL_RCGC2 0 mww $SYSCTL_SCGC0 0x00000040 mww $SYSCTL_SCGC1 0 mww $SYSCTL_SCGC2 0 mww $SYSCTL_DCGC0 0x00000040 mww $SYSCTL_DCGC1 0 mww $SYSCTL_DCGC2 0 # Reset the remaining SysCtl registers mww $SYSCTL_PBORCTL 0 mww $SYSCTL_IMC 0 mww $SYSCTL_GPIOHBCTL 0 mww $SYSCTL_MOSCCTL 0 mww $SYSCTL_PIOSCCAL 0 mww $SYSCTL_I2SMCLKCFG 0 # Reset the peripherals mww $SYSCTL_SRCR0 0xffffffff mww $SYSCTL_SRCR1 0xffffffff mww $SYSCTL_SRCR2 0xffffffff mww $SYSCTL_SRCR0 0 mww $SYSCTL_SRCR1 0 mww $SYSCTL_SRCR2 0 # Clear any pending SysCtl interrupts mww $SYSCTL_MISC 0xffffffff # Wait for any pending flash operations to complete while {[expr [mrw $FLASH_FMC] & 0xffff] != 0} { sleep 1 } while {[expr [mrw $FLASH_FMC2] & 0xffff] != 0} { sleep 1 } # Reset the flash controller registers mww $FLASH_FMA 0 mww $FLASH_FCIM 0 mww $FLASH_FCMISC 0xffffffff mww $FLASH_FWBVAL 0 } $_TARGETNAME configure -event reset-start { adapter_khz 500 # # When nRST is asserted on most Stellaris devices, it clears some of # the debug state. The ARMv7M and Cortex-M3 TRMs say that's wrong; # and OpenOCD depends on those TRMs. So we won't use SRST on those # chips. (Only power-on reset should affect debug state, beyond a # few specified bits; not the chip's nRST input, wired to SRST.) # # REVISIT current errata specs don't seem to cover this issue. # Do we have more details than this email? # https://lists.berlios.de/pipermail # /openocd-development/2008-August/003065.html # global _DEVICECLASS if {$_DEVICECLASS != 0xff} { set device_class $_DEVICECLASS } else { set device_class [expr (([mrw 0x400fe000] >> 16) & 0xff)] } if {$device_class == 0 || $device_class == 1 || $device_class == 3 || $device_class == 5 || $device_class == 0xa} { if {![using_hla]} { # Sandstorm, Fury, DustDevil, Blizzard and Snowflake are able to use NVIC SYSRESETREQ cortex_m reset_config sysresetreq } } else { if {![using_hla]} { # Tempest and Firestorm default to using NVIC VECTRESET # peripherals will need reseting manually, see proc reset_peripherals cortex_m reset_config vectreset } # reset peripherals, based on code in # http://www.ti.com/lit/er/spmz573a/spmz573a.pdf reset_peripherals $device_class } } # flash configuration ... autodetects sizes, autoprobed flash bank $_CHIPNAME.flash stellaris 0 0 0 0 $_TARGETNAME openocd-0.9.0/tcl/target/bcm6348.cfg0000644000175000017500000000040112526202245013702 00000000000000set _CHIPNAME bcm6348 set _CPUID 0x0634817f adapter_khz 1000 jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/lpc13xx.cfg0000644000175000017500000000027512526202245014127 00000000000000# NXP LPC13xx Cortex-M3 with at least 4kB SRAM set CHIPNAME lpc13xx set CHIPSERIES lpc1300 if { ![info exists WORKAREASIZE] } { set WORKAREASIZE 0x1000 } source [find target/lpc1xxx.cfg] openocd-0.9.0/tcl/target/at91sam9260.cfg0000644000175000017500000000123012526202245014415 00000000000000###################################### # Target: Atmel AT91SAM9260 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9260 } source [find target/at91sam9.cfg] # Establish internal SRAM memory work areas that are important to pre-bootstrap loaders, etc. The # AT91SAM9260 has two SRAM areas, one starting at 0x00200000 and the other starting at 0x00300000. # Both areas are 4 kB long. #$_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x1000 -work-area-backup 1 $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x1000 -work-area-backup 1 openocd-0.9.0/tcl/target/at91sam9261.cfg0000644000175000017500000000055712526202245014431 00000000000000###################################### # Target: Atmel AT91SAM9261 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9261 } source [find target/at91sam9.cfg] # Internal sram1 memory $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x28000 -work-area-backup 1 openocd-0.9.0/tcl/target/at91sam9263.cfg0000644000175000017500000000125312526202245014425 00000000000000###################################### # Target: Atmel AT91SAM9263 ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9263 } source [find target/at91sam9.cfg] # Establish internal SRAM memory work areas that are important to pre-bootstrap loaders, etc. The # AT91SAM9263 has two SRAM areas, # one starting at 0x00300000 of 80KiB # and the other starting at 0x00500000 of 16KiB. # Internal sram1 memory $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x14000 -work-area-backup 1 #$_TARGETNAME configure -work-area-phys 0x00500000 -work-area-size 0x4000 -work-area-backup 1 openocd-0.9.0/tcl/target/at91samdXX.cfg0000644000175000017500000000275212526202245014532 00000000000000# # script for ATMEL samdXX, a CORTEX-M0 chip # # # samdXX devices only support SWD transports. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91samd } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming # By default use 2kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x800 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # JTAG speed should be <= F_CPU/6. F_CPU after reset is 4 MHz, so use F_JTAG = 0.5MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 500 adapter_nsrst_delay 100 if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91samd 0x00000000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91samg5x.cfg0000644000175000017500000000027412526202245014527 00000000000000# script for the ATMEL samg5x CORTEX-M4F chip family # source [find target/at91sam4XXX.cfg] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam4 0x00400000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/atheros_ar9331.cfg0000644000175000017500000000054112526202245015270 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $_CHIPNAME } else { set _CHIPNAME ar9331 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x00000001 } jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID set TARGETNAME $_CHIPNAME.cpu target create $TARGETNAME mips_m4k -endian big -chain-position $TARGETNAME openocd-0.9.0/tcl/target/ti_calypso.cfg0000644000175000017500000000231312526202245014766 00000000000000# # TI Calypso (lite) G2 C035 Digital Base Band chip # # ARM7TDMIE + DSP subchip (S28C128) # # 512K SRAM Calypso # 256K SRAM Calypso lite # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME calypso } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x3100e02f } # Work-area is a space in RAM used for flash programming # By default use 64kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x10000 } adapter_khz 1000 reset_config trst_and_srst jtag newtap $_CHIPNAME dsp -expected-id 0x00000000 -irlen 8 jtag newtap $_CHIPNAME arm -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # target set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm7tdmi -endian little -chain-position $_TARGETNAME # workarea $_TARGETNAME configure -work-area-phys 0x00800000 -work-area-size $_WORKAREASIZE -work-area-backup 1 arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable $_TARGETNAME configure -event examine-start { irscan calypso.arm 0x0b -endstate DRPAUSE drscan calypso.arm 2 2 -endstate RUN/IDLE } openocd-0.9.0/tcl/target/at91sam3ax_4x.cfg0000644000175000017500000000052312526202245015127 00000000000000# common stuff source [find target/at91sam3ax_xx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME # This is a 256K chip - it has the 2nd bank set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME at91sam3 0x0000A0000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91r40008.cfg0000644000175000017500000000133212526202245014154 00000000000000# AT91R40008 target configuration file # TRST is tied to SRST on the AT91X40 family. reset_config srst_only srst_pulls_trst if {[info exists CHIPNAME]} { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91r40008 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Setup the JTAG scan chain. if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x1f0f0f0f } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000 -work-area-size 0x20000 -work-area-backup 0 openocd-0.9.0/tcl/target/к1879xб1Ñ.cfg0000644000175000017500000000140512526202245015655 00000000000000# СБИС К1879ХБ1Я # http://www.module.ru/catalog/micro/mikroshema_dekodera_cifrovogo_televizionnogo_signala_sbis_k1879hb1ya/ adapter_khz 1000 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME к1879хб1Ñ } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists DSP_TAPID] } { set _DSP_TAPID $DSP_TAPID } else { set _DSP_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME dsp -irlen 4 -expected-id $_DSP_TAPID if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x07b76f0f } jtag newtap $_CHIPNAME arm -irlen 5 -expected-id $_CPU_TAPID set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm11 -chain-position $_CHIPNAME.arm openocd-0.9.0/tcl/target/at91sam9.cfg0000644000175000017500000000144312526202245014173 00000000000000###################################### # Target: Atmel AT91SAM9 ###################################### if { [info exists AT91_CHIPNAME] } { set _CHIPNAME $AT91_CHIPNAME } else { error "you must specify a chip name" } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0792603f } reset_config trst_and_srst separate trst_push_pull srst_open_drain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID adapter_nsrst_delay 300 jtag_ntrst_delay 200 adapter_khz 3 ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/imx6.cfg0000644000175000017500000000324312526202245013506 00000000000000# Freescale i.MX6 series single/dual/quad core processor if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME imx6 } # CoreSight Debug Access Port if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x4ba00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x0f \ -expected-id $_DAP_TAPID # SDMA / no IDCODE jtag newtap $_CHIPNAME sdma -irlen 4 -ircapture 0x00 -irmask 0x0f # System JTAG Controller if { [info exists SJC_TAPID] } { set _SJC_TAPID $SJC_TAPID } else { set _SJC_TAPID 0x0191c01d } set _SJC_TAPID2 0x2191c01d set _SJC_TAPID3 0x2191e01d set _SJC_TAPID4 0x1191c01d jtag newtap $_CHIPNAME sjc -irlen 5 -ircapture 0x01 -irmask 0x1f \ -expected-id $_SJC_TAPID -expected-id $_SJC_TAPID2 \ -expected-id $_SJC_TAPID3 -expected-id $_SJC_TAPID4 # GDB target: Cortex-A9, using DAP, configuring only one core # Base addresses of cores: # core 0 - 0x82150000 # core 1 - 0x82152000 # core 2 - 0x82154000 # core 3 - 0x82156000 set _TARGETNAME $_CHIPNAME.cpu.0 target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase 0x82150000 # some TCK cycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.sjc -event post-reset "runtest 100" proc imx6_dbginit {target} { # General Cortex A8/A9 debug initialisation cortex_a dbginit } # Slow speed to be sure it will work adapter_khz 1000 $_TARGETNAME configure -event reset-start { adapter_khz 1000 } $_TARGETNAME configure -event reset-assert-post "imx6_dbginit $_TARGETNAME" $_TARGETNAME configure -event gdb-attach { halt } openocd-0.9.0/tcl/target/hilscher_netx50.cfg0000644000175000017500000000231112526202245015622 00000000000000################################################################################ # Author: Michael Trensch (MTrensch@googlemail.com) ################################################################################ #Hilscher netX 50 CPU if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME netx50 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x25966021 } # jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # that TAP is associated with a target set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME # On netX50 SDRAM is not accessible at offset 0xDEAD0-0xDEADF as it is busy from # DMA controller at init. This function will setup a dummy DMA to free this ares # and must be called before using SDRAM proc sdram_fix { } { mww 0x1c005830 0x00000001 mww 0x1c005104 0xBFFFFFFC mww 0x1c00510c 0x00480001 mww 0x1c005110 0x00000001 sleep 100 mww 0x1c00510c 0 mww 0x1c005110 0 mww 0x1c005830 0x00000000 puts "SDRAM Fix executed!" } openocd-0.9.0/tcl/target/at91sam4XXX.cfg0000644000175000017500000000303412526202245014574 00000000000000# # script for ATMEL sam4, a CORTEX-M4 chip # # # sam4 devices can support both JTAG and SWD transports. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME sam4 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming # By default use 64kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x4000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME # 16K is plenty, the smallest chip has this much $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # JTAG speed should be <= F_CPU/6. F_CPU after reset is 4 MHz, so use F_JTAG = 0.5MHz # # Since we may be running of an RC oscilator, we crank down the speed a # bit more to be on the safe side. Perhaps superstition, but if are # running off a crystal, we can run closer to the limit. Note # that there can be a pretty wide band where things are more or less stable. adapter_khz 500 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/lpc1xxx.cfg0000644000175000017500000001510312526202245014230 00000000000000# Main file for NXP LPC1xxx/LPC40xx series Cortex-M0/0+/3/4F parts # # !!!!!! # # This file should not be included directly, rather by the lpc11xx.cfg, # lpc13xx.cfg, lpc17xx.cfg, etc. which set the needed variables to the # appropriate values. # # !!!!!! # LPC8xx chips support only SWD transport. # LPC11xx chips support only SWD transport. # LPC12xx chips support only SWD transport. # LPC11Uxx chips support only SWD transports. # LPC13xx chips support only SWD transports. # LPC17xx chips support both JTAG and SWD transports. # LPC40xx chips support both JTAG and SWD transports. # Adapt based on what transport is active. source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { error "CHIPNAME not set. Please do not include lpc1xxx.cfg directly, but the specific chip configuration file (lpc11xx.cfg, lpc13xx.cfg, lpc17xx.cfg, etc)." } if { [info exists CHIPSERIES] } { # Validate chip series is supported if { $CHIPSERIES != "lpc800" && $CHIPSERIES != "lpc1100" && $CHIPSERIES != "lpc1200" && $CHIPSERIES != "lpc1300" && $CHIPSERIES != "lpc1700" && $CHIPSERIES != "lpc4000" } { error "Unsupported LPC1xxx chip series specified." } set _CHIPSERIES $CHIPSERIES } else { error "CHIPSERIES not set. Please do not include lpc1xxx.cfg directly, but the specific chip configuration file (lpc11xx.cfg, lpc13xx.cfg, lpc17xx.cfg, etc)." } # After reset, the chip is clocked by an internal RC oscillator. # When board-specific code (reset-init handler or device firmware) # configures another oscillator and/or PLL0, set CCLK to match; if # you don't, then flash erase and write operations may misbehave. # (The ROM code doing those updates cares about core clock speed...) # CCLK is the core clock frequency in KHz if { [info exists CCLK] } { # Allow user override set _CCLK $CCLK } else { # LPC8xx/LPC11xx/LPC12xx/LPC13xx use a 12MHz one, LPC17xx uses a 4MHz one(except for LPC177x/8x,LPC407x/8x) if { $_CHIPSERIES == "lpc800" || $_CHIPSERIES == "lpc1100" || $_CHIPSERIES == "lpc1200" || $_CHIPSERIES == "lpc1300" } { set _CCLK 12000 } elseif { $_CHIPSERIES == "lpc1700" || $_CHIPSERIES == "lpc4000" } { set _CCLK 4000 } } if { [info exists CPUTAPID] } { # Allow user override set _CPUTAPID $CPUTAPID } else { # LPC8xx/LPC11xx/LPC12xx use a Cortex M0/M0+ core, LPC13xx/LPC17xx use a Cortex M3 core,LPC40xx use a Cortex-M4F core. if { $_CHIPSERIES == "lpc800" || $_CHIPSERIES == "lpc1100" || $_CHIPSERIES == "lpc1200" } { set _CPUTAPID 0x0bb11477 } elseif { $_CHIPSERIES == "lpc1300" || $_CHIPSERIES == "lpc1700" || $_CHIPSERIES == "lpc4000" } { if { [using_jtag] } { set _CPUTAPID 0x4ba00477 } { set _CPUTAPID 0x2ba01477 } } } if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { error "WORKAREASIZE is not set. The $CHIPNAME part is available in several Flash and RAM size configurations. Please set WORKAREASIZE." } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME # The LPC11xx devices have 2/4/8kB of SRAM in the ARMv7-M "Code" area (at 0x10000000) # The LPC12xx devices have 4/8kB of SRAM in the ARMv7-M "Code" area (at 0x10000000) # The LPC11Uxx devices have 4/6/8kB of SRAM in the ARMv7-M "Code" area (at 0x10000000) # The LPC13xx devices have 4/8kB of SRAM in the ARMv7-M "Code" area (at 0x10000000) # The LPC17xx devices have 8/16/32/64kB of SRAM in the ARMv7-M "Code" area (at 0x10000000) # The LPC40xx devices have 16/32/64kB of SRAM in the ARMv7-ME "Code" area (at 0x10000000) $_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE # The LPC11xx devies have 8/16/24/32/48/56/64kB of flash memory (at 0x00000000) # The LPC12xx devies have 32/48/64/80/96/128kB of flash memory (at 0x00000000) # The LPC11Uxx devies have 16/24/32/40/48/64/96/128kB of flash memory (at 0x00000000) # The LPC13xx devies have 8/16/32kB of flash memory (at 0x00000000) # The LPC17xx devies have 32/64/128/256/512kB of flash memory (at 0x00000000) # The LPC40xx devies have 64/128/256/512kB of flash memory (at 0x00000000) # # All are compatible with the "lpc1700" variant of the LPC2000 flash driver # (same cmd51 destination boundary alignment, and all three support 256 byte # transfers). # # flash bank lpc2000 0 0 [calc checksum] set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME lpc2000 0x0 0 0 0 $_TARGETNAME \ auto $_CCLK calc_checksum if { $_CHIPSERIES == "lpc800" || $_CHIPSERIES == "lpc1100" || $_CHIPSERIES == "lpc1200" || $_CHIPSERIES == "lpc1300" } { # Do not remap 0x0000-0x0200 to anything but the flash (i.e. select # "User Flash Mode" where interrupt vectors are _not_ remapped, # and reside in flash instead). # # Table 8. System memory remap register (SYSMEMREMAP, address 0x4004 8000) bit description # Bit Symbol Value Description # 1:0 MAP System memory remap # 0x0 Boot Loader Mode. Interrupt vectors are re-mapped to Boot ROM. # 0x1 User RAM Mode. Interrupt vectors are re-mapped to Static RAM. # 0x2 User Flash Mode. Interrupt vectors are not re-mapped and reside in Flash. # 31:2 - - Reserved. $_TARGETNAME configure -event reset-init { mww 0x40048000 0x02 } } elseif { $_CHIPSERIES == "lpc1700" || $_CHIPSERIES == "lpc4000" } { # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select # "User Flash Mode" where interrupt vectors are _not_ remapped, # and reside in flash instead). # # See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description # Bit Symbol Value Description Reset # value # 0 MAP Memory map control. 0 # 0 Boot mode. A portion of the Boot ROM is mapped to address 0. # 1 User mode. The on-chip Flash memory is mapped to address 0. # 31:1 - Reserved. The value read from a reserved bit is not defined. NA # # http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user $_TARGETNAME configure -event reset-init { mww 0x400FC040 0x01 } } # Run with *real slow* clock by default since the # boot rom could have been playing with the PLL, so # we have no idea what clock the target is running at. adapter_khz 10 # delays on reset lines adapter_nsrst_delay 200 if {[using_jtag]} { jtag_ntrst_delay 200 } # LPC8xx (Cortex M0+ core) support SYSRESETREQ # LPC11xx/LPC12xx (Cortex M0 core) support SYSRESETREQ # LPC13xx/LPC17xx (Cortex M3 core) support SYSRESETREQ # LPC40xx (Cortex M4F core) support SYSRESETREQ if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/ti_dm6446.cfg0000644000175000017500000000526312526202245014247 00000000000000# # Texas Instruments DaVinci family: TMS320DM6446 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dm6446 } # TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled* # after JTAG reset until ICEpick is used to route them in. set EMU01 "-disable" # With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without # needing any ICEpick interaction. #set EMU01 "-enable" source [find target/icepick.cfg] # Subsidiary TAP: unknown ... must enable via ICEpick jtag newtap $_CHIPNAME unknown -irlen 8 -disable jtag configure $_CHIPNAME.unknown -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 3" # Subsidiary TAP: C64x+ DSP ... must enable via ICEpick jtag newtap $_CHIPNAME dsp -irlen 38 -ircapture 0x25 -irmask 0x3f -disable jtag configure $_CHIPNAME.dsp -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 2" # Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer if { [info exists ETB_TAPID] } { set _ETB_TAPID $ETB_TAPID } else { set _ETB_TAPID 0x2b900f0f } jtag newtap $_CHIPNAME etb -irlen 4 -irmask 0xf -expected-id $_ETB_TAPID $EMU01 jtag configure $_CHIPNAME.etb -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 1" # Subsidiary TAP: ARM926ejs with scan chains for ARM Debug, EmbeddedICE-RT, ETM. if { [info exists CPU_TAPID] } { set _CPU_TAPID $CPU_TAPID } else { set _CPU_TAPID 0x07926001 } jtag newtap $_CHIPNAME arm -irlen 4 -irmask 0xf -expected-id $_CPU_TAPID $EMU01 jtag configure $_CHIPNAME.arm -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 0" # Primary TAP: ICEpick-C (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b70002f } jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID jtag configure $_CHIPNAME.jrc -event setup \ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm" ################ # GDB target: the ARM, using SRAM1 for scratch. SRAM0 (also 8K) # and the ETB memory (4K) are other options, while trace is unused. # Little-endian; use the OpenOCD default. set _TARGETNAME $_CHIPNAME.arm target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x0000a000 -work-area-size 0x2000 # be absolutely certain the JTAG clock will work with the worst-case # CLKIN = 20 MHz (best case: 30 MHz) even when no bootloader turns # on the PLL and starts using it. OK to speed up after clock setup. adapter_khz 1500 $_TARGETNAME configure -event "reset-start" { adapter_khz 1500 } arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable # trace setup etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb openocd-0.9.0/tcl/target/pxa255.cfg0000644000175000017500000000254312526202245013651 00000000000000# PXA255 chip ... originally from Intel, PXA line was sold to Marvell. # This chip is now at end-of-life. Final orders have been taken. if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME pxa255 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x69264013 } jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME xscale -endian $_ENDIAN \ -chain-position $_CHIPNAME.cpu # PXA255 comes out of reset using 3.6864 MHz oscillator. # Until the PLL kicks in, keep the JTAG clock slow enough # that we get no errors. adapter_khz 300 $_TARGETNAME configure -event "reset-start" { adapter_khz 300 } # both TRST and SRST are *required* for debug # DCSR is often accessed with SRST active reset_config trst_and_srst separate srst_nogate # reset processing that works with PXA proc init_reset {mode} { # assert both resets; equivalent to power-on reset jtag_reset 1 1 # drop TRST after at least 32 cycles sleep 1 jtag_reset 0 1 # minimum 32 TCK cycles to wake up the controller runtest 50 # now the TAP will be responsive; validate scanchain jtag arp_init # ... and take it out of reset jtag_reset 0 0 } proc jtag_init {} { init_reset startup } openocd-0.9.0/tcl/target/em357.cfg0000644000175000017500000000373312526202245013467 00000000000000# # Target configuration for the Silicon Labs EM357 chips # # # em357 family supports JTAG and SWD transports # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME em357 } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { set _CPUTAPID 0x3ba00477 } else { set _CPUTAPID 0x1ba00477 } } if { [info exists BSTAPID] } { set _BSTAPID $BSTAPID } else { set _BSTAPID 0x069a962b } if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME em358 } if { [info exists FLASHSIZE] } { set _FLASHSIZE $FLASHSIZE } else { set _FLASHSIZE 0x30000 } swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID if { [using_jtag] } { swj_newdap $_CHIPNAME bs -irlen 4 -expected-id $_BSTAPID -ircapture 0xe -irmask 0xf } set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian little -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME em357 0x08000000 $_FLASHSIZE 0 0 $_TARGETNAME if { ![using_hla]} { # according to errata, we need to use vectreset rather than sysresetreq to avoid lockup # There is a bug in the chip, which means that when using external debuggers the chip # may lock up in certain CPU clock modes. Affected modes are operating the CPU at # 24MHz derived from the 24MHz crystal, or 12MHz derived from the high frequency RC # oscillator. If an external debugger tool asserts SYSRESETREQ, the chip will lock up and # require a pin reset or power cycle. # # for details, refer to: # http://www.silabs.com/Support%20Documents/TechnicalDocs/EM35x-Errata.pdf cortex_m reset_config vectreset } openocd-0.9.0/tcl/target/em358.cfg0000644000175000017500000000047412526202245013467 00000000000000# Target configuration for the Silicon Labs EM358 chips # # em357 family supports JTAG and SWD transports # if { ![info exists CHIPNAME] } { set CHIPNAME em358 } if { ![info exists BSTAPID] } { set BSTAPID 0x069aa62b } # 512K of flash in the em358 chips set FLASHSIZE 0x80000 source [find target/em357.cfg] openocd-0.9.0/tcl/target/lpc3250.cfg0000644000175000017500000000205012526202245013706 00000000000000# lpc3250 config # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lpc3250 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x17900f0f } if { [info exists CPUTAPID_REV_A0] } { set _CPUTAPID_REV_A0 $CPUTAPID_REV_A0 } else { set _CPUTAPID_REV_A0 0x17926f0f } if { [info exists SJCTAPID] } { set _SJCTAPID $SJCTAPID } else { set _SJCTAPID 0x1b900f0f } jtag newtap $_CHIPNAME sjc -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_SJCTAPID jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID \ -expected-id $_CPUTAPID_REV_A0 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian little -chain-position $_TARGETNAME -work-area-phys 0x00000000 -work-area-size 0x7d0000 -work-area-backup 0 proc power_restore {} { echo "Sensed power restore. No action." } proc srst_deasserted {} { echo "Sensed nSRST deasserted. No action." } openocd-0.9.0/tcl/target/at91sam3ax_8x.cfg0000644000175000017500000000052512526202245015135 00000000000000# common stuff source [find target/at91sam3ax_xx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME # This is a 512K chip - it has the 2nd bank set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME at91sam3 0x0000C0000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/sharp_lh79532.cfg0000644000175000017500000000105212526202245015031 00000000000000reset_config srst_only srst_pulls_trst if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME lh79532 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # sharp changed the number! set _CPUTAPID 0x00002061 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/pxa270.cfg0000644000175000017500000000256012526202245013645 00000000000000#Marvell/Intel PXA270 Script if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME pxa270 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } #IDs for pxa270. Are there more? if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # set useful default set _CPUTAPID 0x49265013 } if { [info exists CPUTAPID2] } { set _CPUTAPID2 $CPUTAPID2 } else { # set useful default set _CPUTAPID2 0x79265013 } if { [info exists CPUTAPID3] } { set _CPUTAPID2 $CPUTAPID3 } else { # set useful default set _CPUTAPID3 0x89265013 } # set adapter_nsrst_delay to the delay introduced by your reset circuit # the rest of the needed delays are built into the openocd program adapter_nsrst_delay 260 # set the jtag_ntrst_delay to the delay introduced by a reset circuit # the rest of the needed delays are built into the openocd program jtag_ntrst_delay 250 set _TARGETNAME $_CHIPNAME.cpu jtag newtap $_CHIPNAME cpu -irlen 7 -ircapture 0x1 -irmask 0x7f -expected-id $_CPUTAPID -expected-id $_CPUTAPID2 -expected-id $_CPUTAPID3 target create $_TARGETNAME xscale -endian $_ENDIAN -chain-position $_TARGETNAME # maps to PXA internal RAM. If you are using a PXA255 # you must initialize SDRAM or leave this option off $_TARGETNAME configure -work-area-phys 0x5c000000 -work-area-size 0x10000 -work-area-backup 0 openocd-0.9.0/tcl/target/at91sam9260_ext_RAM_ext_flash.cfg0000644000175000017500000000630312526202245020037 00000000000000###################################### # Target: Atmel AT91SAM9260 ###################################### source [find target/at91sam9261.cfg] reset_config trst_and_srst adapter_khz 4 adapter_nsrst_delay 200 jtag_ntrst_delay 200 scan_chain $_TARGETNAME configure -event reset-start { # at reset chip runs at 32khz adapter_khz 8 } $_TARGETNAME configure -event reset-init {at91sam_init} # Flash configuration #flash bank cfi set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME cfi 0x10000000 0x01000000 2 2 $_TARGETNAME # Faster memory downloads. This is disabled automatically during # reset init since all reset init sequences are too short for # fast memory access arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable proc at91sam_init { } { mww 0xfffffd08 0xa5000501 ;# RSTC_MR : enable user reset mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog mww 0xfffffc20 0x00004001 ;# CKGR_MOR : enable the main oscillator sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000001 ;# PMC_MCKR : switch to main oscillator sleep 10 ;# wait 10 ms mww 0xfffffc28 0x2060bf09 ;# CKGR_PLLAR: Set PLLA Register for 198,656MHz sleep 20 ;# wait 20 ms mww 0xfffffc30 0x00000101 ;# PMC_MCKR : Select prescaler sleep 10 ;# wait 10 ms mww 0xfffffc30 0x00000102 ;# PMC_MCKR : Clock from PLLA is selected sleep 10 ;# wait 10 ms # Now run at anything fast... ie: 10mhz! adapter_khz 10000 ;# Increase JTAG Speed to 6 MHz mww 0xffffec00 0x0a0a0a0a ;# SMC_SETUP0 : Setup SMC for Intel NOR Flash JS28F128P30T85 128MBit mww 0xffffec04 0x0b0b0b0b ;# SMC_PULSE0 mww 0xffffec08 0x00160016 ;# SMC_CYCLE0 mww 0xffffec0c 0x00161003 ;# SMC_MODE0 mww 0xfffff870 0xffff0000 ;# PIO_ASR : Select peripheral function for D15..D31 mww 0xfffff804 0xffff0000 ;# PIO_PDR : Disable PIO function for D15..D31 mww 0xffffef1c 0x2 ;# EBI_CSA : Assign EBI Chip Select 1 to SDRAM mww 0xffffea08 0x85227259 ;# SDRAMC_CR : Configure SDRAM (2 x Samsung K4S561632H-UC75 : 4M x 16Bit x 4 Banks) #mww 0xffffea08 0x85227254 ;# SDRAMC_CR : Configure SDRAM (2 x Samsung K4S641632H-UC75 : 1M x 16Bit x 4 Banks) mww 0xffffea00 0x1 ;# SDRAMC_MR : issue a NOP command mww 0x20000000 0 mww 0xffffea00 0x2 ;# SDRAMC_MR : issue an 'All Banks Precharge' command mww 0x20000000 0 mww 0xffffea00 0x4 ;# SDRAMC_MR : issue 8 x 'Auto-Refresh' Command mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x4 mww 0x20000000 0 mww 0xffffea00 0x3 ;# SDRAMC_MR : issue a 'Load Mode Register' command mww 0x20000000 0 mww 0xffffea00 0x0 ;# SDRAMC_MR : normal mode mww 0x20000000 0 mww 0xffffea04 0x5d2 ;# SDRAMC_TR : Set refresh timer count to 15us } openocd-0.9.0/tcl/target/armada370.cfg0000644000175000017500000000127012526202245014300 00000000000000# # armada370 -- support for the Marvell Armada/370 CPU family # # gerg@uclinux.org, OCT-2013 # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME armada370 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x4ba00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap proc armada370_dbginit {target} { cortex_a dbginit } $_TARGETNAME configure -event reset-assert-post "armada370_dbginit $_TARGETNAME" # We need to init now, so we can run the apsel command. init dap apsel 1 openocd-0.9.0/tcl/target/bcm281xx.cfg0000644000175000017500000000133612526202245014200 00000000000000# BCM281xx if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME bcm281xx } # Main CPU DAP if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x4ba00477 } jtag newtap $_CHIPNAME dap -expected-id $_DAP_TAPID -irlen 4 # Dual Cortex A9s set _TARGETNAME0 $_CHIPNAME.cpu0 set _TARGETNAME1 $_CHIPNAME.cpu1 target create $_TARGETNAME0 cortex_a -chain-position $_CHIPNAME.dap -coreid 0 -dbgbase 0x3fe10000 target create $_TARGETNAME1 cortex_a -chain-position $_CHIPNAME.dap -coreid 1 -dbgbase 0x3fe12000 target smp $_TARGETNAME0 $_TARGETNAME1 $_TARGETNAME0 configure -event gdb-attach { cortex_a dbginit } $_TARGETNAME1 configure -event gdb-attach { cortex_a dbginit } openocd-0.9.0/tcl/target/imx.cfg0000644000175000017500000000143612526202245013422 00000000000000# utility fn's for Freescale i.MX series global TARGETNAME set TARGETNAME $_TARGETNAME # rewrite commands of the form below to arm11 mcr... # Data.Set c15:0x042f %long 0x40000015 proc setc15 {regs value} { global TARGETNAME echo [format "set p15 0x%04x, 0x%08x" $regs $value] arm mcr 15 [expr ($regs>>12)&0x7] [expr ($regs>>0)&0xf] [expr ($regs>>4)&0xf] [expr ($regs>>8)&0x7] $value } proc imx3x_reset {} { # this reset script comes from the Freescale PDK # # http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=IMX35PDK echo "Target Setup: initialize DRAM controller and peripherals" # Data.Set c15:0x01 %long 0x00050078 setc15 0x01 0x00050078 echo "configuring CP15 for enabling the peripheral bus" # Data.Set c15:0x042f %long 0x40000015 setc15 0x042f 0x40000015 } openocd-0.9.0/tcl/target/at91sam9rl.cfg0000644000175000017500000000056112526202245014531 00000000000000###################################### # Target: Atmel AT91SAM9RL ###################################### if { [info exists CHIPNAME] } { set AT91_CHIPNAME $CHIPNAME } else { set AT91_CHIPNAME at91sam9rl } source [find target/at91sam9.cfg] # Internal sram1 memory $_TARGETNAME configure -work-area-phys 0x00300000 -work-area-size 0x10000 -work-area-backup 1 openocd-0.9.0/tcl/target/dsp568013.cfg0000644000175000017500000000376212526202245014106 00000000000000# Script for freescale DSP568013 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dsp568013 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a big endian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x01f2401d } #jtag speed adapter_khz 800 reset_config srst_only #MASTER tap jtag newtap $_CHIPNAME chp -irlen 8 -ircapture 1 -irmask 0x03 -expected-id $_CPUTAPID #CORE tap jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 1 -irmask 0x03 -disable -expected-id 0x02211004 #target configuration - There is only 1 tap at a time, hence only 1 target is defined. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME dsp5680xx -endian $_ENDIAN -chain-position $_TARGETNAME # Setup the interesting tap # Disable polling to be able to get idcode from core tap. If re enabled, can be re enabled, but it should be disabled to correctly unlock flash (operations requiere certain instruction to be in the IR register during reset, and polling would change this) jtag configure $_CHIPNAME.chp -event setup " jtag tapenable $_TARGETNAME poll off " #select CORE tap by modifying the TLM register. #to be used when MASTER tap is selected. jtag configure $_TARGETNAME -event tap-enable " irscan $_CHIPNAME.chp 0x05; drscan $_CHIPNAME.chp 4 0x02; jtag tapdisable $_CHIPNAME.chp; " #select MASTER tap by modifying the TLM register. #to be used when CORE tap is selected. jtag configure $_CHIPNAME.chp -event tap-enable " irscan $_TARGETNAME 0x08; drscan $_TARGETNAME 4 0x1; jtag tapdisable $_TARGETNAME; " #disables the master tap jtag configure $_TARGETNAME -event tap-disable " " #TODO FIND SMARTER WAY. jtag configure $_CHIPNAME.chp -event tap-disable " " #TODO FIND SMARTER WAY. #working area at base of ram $_TARGETNAME configure -work-area-virt 0 #setup flash set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME dsp5680xx_flash 0 0 2 1 $_TARGETNAME openocd-0.9.0/tcl/target/ti_tms570.cfg0000644000175000017500000000356012526202245014360 00000000000000adapter_khz 1500 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME tms570 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN big } # TMS570 has an ICEpick-C on which we need the router commands. source [find target/icepick.cfg] # Main DAP # DAP_TAPID should be set before source-ing this file if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" # ICEpick-C (JTAG route controller) # JRC_TAPID should be set before source-ing this file if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } set _JRC_TAPID2 0x0B7B302F set _JRC_TAPID3 0x0B95502F set _JRC_TAPID4 0x0B97102F set _JRC_TAPID5 0x0D8A002F set _JRC_TAPID6 0x2B8A002F set _JRC_TAPID7 0x2D8A002F set _JRC_TAPID8 0x3B8A002F set _JRC_TAPID9 0x3D8A002F jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \ -expected-id $_JRC_TAPID \ -expected-id $_JRC_TAPID2 \ -expected-id $_JRC_TAPID3 \ -expected-id $_JRC_TAPID4 \ -expected-id $_JRC_TAPID5 \ -expected-id $_JRC_TAPID6 \ -expected-id $_JRC_TAPID7 \ -expected-id $_JRC_TAPID8 \ -expected-id $_JRC_TAPID9 \ -ignore-version jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" jtag configure $_CHIPNAME.jrc -event post-reset "runtest 100" # Cortex R4 target set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_r4 -endian $_ENDIAN \ -chain-position $_CHIPNAME.dap -coreid 0 -dbgbase 0x00001003 # TMS570 uses quirky BE-32 mode $_TARGETNAME dap ti_be_32_quirks 1 $_TARGETNAME configure -event gdb-attach { cortex_r4 dbginit halt } $_TARGETNAME configure -event "reset-assert" { global _CHIPNAME # assert warm system reset through ICEPick icepick_c_wreset $_CHIPNAME.jrc } openocd-0.9.0/tcl/target/at91sam4sd32x.cfg0000644000175000017500000000042512526202245015051 00000000000000# script for ATMEL sam4sd32, a CORTEX-M4 chip # source [find target/at91sam4XXX.cfg] set _FLASHNAME $_CHIPNAME.flash0 flash bank $_FLASHNAME at91sam4 0x00400000 0 1 1 $_TARGETNAME set _FLASHNAME $_CHIPNAME.flash1 flash bank $_FLASHNAME at91sam4 0x00500000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/alphascale_asm9260t.cfg0000644000175000017500000000103612526202245016263 00000000000000if { [info exists CHIPNAME] } { set _CHIPNAME $_CHIPNAME } else { set _CHIPNAME asm9260t } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x079264F3 } # And srst_pulls_trst by chip design. reset_config srst_pulls_trst jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME openocd-0.9.0/tcl/target/at91sam3uxx.cfg0000644000175000017500000000024712526202245014733 00000000000000# script for ATMEL sam3, a CORTEX-M3 chip # # at91sam3u4e # at91sam3u2e # at91sam3u1e # at91sam3u4c # at91sam3u2c # at91sam3u1c source [find target/at91sam3XXX.cfg] openocd-0.9.0/tcl/target/stm32f3x_stlink.cfg0000644000175000017500000000020112526202245015567 00000000000000echo "WARNING: target/stm32f3x_stlink.cfg is deprecated, please switch to target/stm32f3x.cfg" source [find target/stm32f3x.cfg] openocd-0.9.0/tcl/target/dsp568037.cfg0000644000175000017500000000333412526202245014107 00000000000000# Script for freescale DSP568037 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME dsp568037 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # this defaults to a big endian set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x01f2801d } #jtag speed adapter_khz 800 reset_config srst_only #MASTER tap jtag newtap $_CHIPNAME chp -irlen 8 -ircapture 1 -irmask 0x03 -expected-id $_CPUTAPID #CORE tap jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 1 -irmask 0x03 -disable -expected-id 0x02211004 #target configuration - There is only 1 tap at a time, hence only 1 target is defined. set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME dsp5680xx -endian $_ENDIAN -chain-position $_TARGETNAME # Setup the interesting tap jtag configure $_CHIPNAME.chp -event setup "jtag tapenable $_TARGETNAME" #select CORE tap by modifying the TLM register. #to be used when MASTER tap is selected. jtag configure $_TARGETNAME -event tap-enable " irscan $_CHIPNAME.chp 0x05; drscan $_CHIPNAME.chp 4 0x02; jtag tapdisable $_CHIPNAME.chp; " #select MASTER tap by modifying the TLM register. #to be used when CORE tap is selected. jtag configure $_CHIPNAME.chp -event tap-enable " irscan $_TARGETNAME 0x08; drscan $_TARGETNAME 4 0x1; jtag tapdisable $_TARGETNAME; " #disables the master tap jtag configure $_TARGETNAME -event tap-disable " " #TODO FIND SMARTER WAY. jtag configure $_CHIPNAME.chp -event tap-disable " " #TODO FIND SMARTER WAY. #working area at base of ram $_TARGETNAME configure -work-area-virt 0 #setup flash set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME dsp5680xx_flash 0 0 2 1 $_TARGETNAME openocd-0.9.0/tcl/target/kl25.cfg0000644000175000017500000000012512526202245013374 00000000000000# # Freescale Kinetis KL25 devices # set CHIPNAME kl25 source [find target/klx.cfg] openocd-0.9.0/tcl/target/omap3530.cfg0000644000175000017500000000465312526202245014100 00000000000000# TI OMAP3530 # http://focus.ti.com/docs/prod/folders/print/omap3530.html # Other OMAP3 chips remove DSP and/or the OpenGL support if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME omap3530 } # ICEpick-C ... used to route Cortex, DSP, and more not shown here source [find target/icepick.cfg] # Subsidiary TAP: C64x+ DSP ... must enable via ICEpick jtag newtap $_CHIPNAME dsp -irlen 38 -ircapture 0x25 -irmask 0x3f -disable # Subsidiary TAP: CoreSight Debug Access Port (DAP) if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x0b6d602f } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf \ -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.dap -event tap-enable \ "icepick_c_tapenable $_CHIPNAME.jrc 3" # Primary TAP: ICEpick-C (JTAG route controller) and boundary scan if { [info exists JRC_TAPID] } { set _JRC_TAPID $JRC_TAPID } else { set _JRC_TAPID 0x0b7ae02f } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \ -expected-id $_JRC_TAPID # GDB target: Cortex-A8, using DAP set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap # SRAM: 64K at 0x4020.0000; use the first 16K $_TARGETNAME configure -work-area-phys 0x40200000 -work-area-size 0x4000 ################### # the reset sequence is event-driven # and kind of finicky... # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.jrc -event post-reset "runtest 100" # have the DAP "always" be active jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" proc omap3_dbginit {target} { # General Cortex A8 debug initialisation cortex_a dbginit # Enable DBGU signal for OMAP353x $target mww phys 0x5401d030 0x00002000 } # be absolutely certain the JTAG clock will work with the worst-case # 16.8MHz/2 = 8.4MHz core clock, even before a bootloader kicks in. # OK to speed up *after* PLL and clock tree setup. adapter_khz 1000 $_TARGETNAME configure -event "reset-start" { adapter_khz 1000 } # Assume SRST is unavailable (e.g. TI-14 JTAG), so we must assert reset # ourselves using PRM_RSTCTRL. RST_GS (2) is a warm reset, like ICEpick # would issue. RST_DPLL3 (4) is a cold reset. set PRM_RSTCTRL 0x48307250 $_TARGETNAME configure -event reset-assert "$_TARGETNAME mww $PRM_RSTCTRL 2" $_TARGETNAME configure -event reset-assert-post "omap3_dbginit $_TARGETNAME" openocd-0.9.0/tcl/target/mdr32f9q2i.cfg0000644000175000017500000000310712526202245014424 00000000000000# MDR32F9Q2I (1986ВЕ92У) # http://milandr.ru/index.php?mact=Products,cntnt01,details,0&cntnt01productid=57&cntnt01returnid=68 source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME mdr32f9q2i } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # Work-area is a space in RAM used for flash programming if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x8000 } #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { if { [using_jtag] } { set _CPUTAPID 0x4ba00477 } { # SWD IDCODE set _CPUTAPID 0x2ba01477 } } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # can't handle overlapping memory regions if { [info exists IMEMORY] && [string equal $IMEMORY true] } { flash bank ${_CHIPNAME}_info.flash mdr 0x08000000 0x01000 0 0 $_TARGETNAME 1 1 4 } else { flash bank $_CHIPNAME.flash mdr 0x08000000 0x20000 0 0 $_TARGETNAME 0 32 4 } # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 adapter_nsrst_delay 100 if {[using_jtag]} { jtag_ntrst_delay 100 } if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } openocd-0.9.0/tcl/target/pxa3xx.cfg0000644000175000017500000000457212526202245014064 00000000000000# Marvell PXA3xx if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME pxa3xx } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } # IDs for all currently known PXA3xx chips if { [info exists CPUTAPID_PXA30X_A0] } { set _CPUTAPID_PXA30X_A0 $CPUTAPID_PXA30X_A0 } else { set _CPUTAPID_PXA30X_A0 0x0E648013 } if { [info exists CPUTAPID_PXA30X_A1] } { set _CPUTAPID_PXA30X_A1 $CPUTAPID_PXA30X_A1 } else { set _CPUTAPID_PXA30X_A1 0x1E648013 } if { [info exists CPUTAPID_PXA31X_A0] } { set _CPUTAPID_PXA31X_A0 $CPUTAPID_PXA31X_A0 } else { set _CPUTAPID_PXA31X_A0 0x0E649013 } if { [info exists CPUTAPID_PXA31X_A1] } { set _CPUTAPID_PXA31X_A1 $CPUTAPID_PXA31X_A1 } else { set _CPUTAPID_PXA31X_A1 0x1E649013 } if { [info exists CPUTAPID_PXA31X_A2] } { set _CPUTAPID_PXA31X_A2 $CPUTAPID_PXA31X_A2 } else { set _CPUTAPID_PXA31X_A2 0x2E649013 } if { [info exists CPUTAPID_PXA31X_B0] } { set _CPUTAPID_PXA31X_B0 $CPUTAPID_PXA31X_B0 } else { set _CPUTAPID_PXA31X_B0 0x3E649013 } if { [info exists CPUTAPID_PXA32X_B1] } { set _CPUTAPID_PXA32X_B1 $CPUTAPID_PXA32X_B1 } else { set _CPUTAPID_PXA32X_B1 0x5E642013 } if { [info exists CPUTAPID_PXA32X_B2] } { set _CPUTAPID_PXA32X_B2 $CPUTAPID_PXA32X_B2 } else { set _CPUTAPID_PXA32X_B2 0x6E642013 } if { [info exists CPUTAPID_PXA32X_C0] } { set _CPUTAPID_PXA32X_C0 $CPUTAPID_PXA32X_C0 } else { set _CPUTAPID_PXA32X_C0 0x7E642013 } # set adapter_nsrst_delay to the delay introduced by your reset circuit # the rest of the needed delays are built into the openocd program adapter_nsrst_delay 260 # set the jtag_ntrst_delay to the delay introduced by a reset circuit # the rest of the needed delays are built into the openocd program jtag_ntrst_delay 250 set _TARGETNAME $_CHIPNAME.cpu jtag newtap $_CHIPNAME cpu -irlen 11 -ircapture 0x1 -irmask 0x7f \ -expected-id $_CPUTAPID_PXA30X_A0 \ -expected-id $_CPUTAPID_PXA30X_A1 \ -expected-id $_CPUTAPID_PXA31X_A0 \ -expected-id $_CPUTAPID_PXA31X_A1 \ -expected-id $_CPUTAPID_PXA31X_A2 \ -expected-id $_CPUTAPID_PXA31X_B0 \ -expected-id $_CPUTAPID_PXA32X_B1 \ -expected-id $_CPUTAPID_PXA32X_B2 \ -expected-id $_CPUTAPID_PXA32X_C0 target create $_TARGETNAME xscale -endian $_ENDIAN \ -chain-position $_TARGETNAME # work area in internal RAM. $_TARGETNAME configure -work-area-phys 0x5c030000 -work-area-size 0x10000 openocd-0.9.0/tcl/target/at91sam3u1c.cfg0000644000175000017500000000030612526202245014573 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91sam3u1e.cfg0000644000175000017500000000030612526202245014575 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91sam3u2c.cfg0000644000175000017500000000030612526202245014574 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/at91sam3u2e.cfg0000644000175000017500000000030612526202245014576 00000000000000# common stuff source [find target/at91sam3uxx.cfg] # size is automatically "calculated" by probing set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME at91sam3 0x000080000 0 1 1 $_TARGETNAME openocd-0.9.0/tcl/target/kl46.cfg0000644000175000017500000000012512526202245013377 00000000000000# # Freescale Kinetis KL46 devices # set CHIPNAME kl46 source [find target/klx.cfg] openocd-0.9.0/tcl/target/icepick.cfg0000644000175000017500000000726712526202245014244 00000000000000# # Copyright (C) 2011 by Karl Kurbjun # Copyright (C) 2009 by David Brownell # # Utilities for TI ICEpick-C/D used in most TI SoCs # Details about the ICEPick are available in the the TRM for each SoC # and http://processors.wiki.ti.com/index.php/ICEPICK # create "constants" proc CONST { key } { array set constant { # define ICEPick instructions IR_BYPASS 0x00 IR_ROUTER 0x02 IR_CONNECT 0x07 IF_BYPASS 0x3F } return $constant($key) } # Instruction to connect to the icepick module proc icepick_c_connect {jrc} { # Send CONNECT instruction in IR state irscan $jrc [CONST IR_CONNECT] -endstate IRPAUSE # Send write and connect key drscan $jrc 8 0x89 -endstate DRPAUSE } # Instruction to disconnect to the icepick module proc icepick_c_disconnect {jrc} { # Send CONNECT instruction in IR state irscan $jrc [CONST IR_CONNECT] -endstate IRPAUSE # Send write and connect key drscan $jrc 8 0x86 -endstate DRPAUSE } # # icepick_c_router: # this function is for sending router commands # arguments are: # jrc: TAP name for the ICEpick # rw: read/write (0 for read, 1 for write) # block: icepick or DAP # register: which register to read/write # payload: value to read/write # this function is for sending router commands # proc icepick_c_router {jrc rw block register payload} { set new_dr_value \ [expr ( ($rw & 0x1) << 31) | ( ($block & 0x7) << 28) | \ ( ($register & 0xF) << 24) | ( $payload & 0xFFFFFF ) ] # echo "\tNew router value:\t0x[format %x $new_dr_value]" # select router irscan $jrc [CONST IR_ROUTER] -endstate IRPAUSE # ROUTER instructions are 32 bits wide set old_dr_value [drscan $jrc 32 $new_dr_value -endstate DRPAUSE] } # Configure the icepick control register proc icepick_c_setup {jrc} { # send a router write, block is 0, register is 1, value is 0x2100 icepick_c_router $jrc 1 0x0 0x1 0x001000 } # jrc == TAP name for the ICEpick # port == a port number, 0..15 proc icepick_c_tapenable {jrc port} { # First CONNECT to the ICEPick # echo "Connecting to ICEPick" icepick_c_connect $jrc # echo "Configuring the ICEpick" icepick_c_setup $jrc # NOTE: it's important not to enter RUN/IDLE state until # done sending these instructions and data to the ICEpick. # And never to enter RESET, which will disable the TAPs. # first enable power and clock for TAP icepick_c_router $jrc 1 0x2 $port 0x100048 # TRM states that the register should be read back here, skipped for now # enable debug "default" mode icepick_c_router $jrc 1 0x2 $port 0x102048 # TRM states that debug enable and debug mode should be read back and # confirmed - skipped for now # Finally select the tap icepick_c_router $jrc 1 0x2 $port 0x102148 # Enter the bypass state irscan $jrc [CONST IR_BYPASS] -endstate RUN/IDLE runtest 10 } # jrc == TAP name for the ICEpick # coreid== core id number 0..15 (not same as port number!) proc icepick_d_set_coreid {jrc coreid } { icepick_c_router $jrc 1 0x6 $coreid 0x2008 } # jrc == TAP name for the ICEpick # port == a port number, 0..15 # Follow the sequence described in # http://processors.wiki.ti.com/images/f/f6/Router_Scan_Sequence-ICEpick-D.pdf proc icepick_d_tapenable {jrc port coreid} { # First CONNECT to the ICEPick icepick_c_connect $jrc icepick_c_setup $jrc # Select the port icepick_c_router $jrc 1 0x2 $port 0x2108 # Set 4 bit core ID to the Cortex-A icepick_d_set_coreid $jrc $coreid # Enter the bypass state irscan $jrc [CONST IF_BYPASS] -endstate RUN/IDLE runtest 10 } # This function uses the ICEPick to send a warm system reset proc icepick_c_wreset {jrc} { # send a router write, block is 0, register is 1, value is 0x2100 icepick_c_router $jrc 1 0x0 0x1 0x002101 } openocd-0.9.0/tcl/target/samsung_s3c2410.cfg0000644000175000017500000000164412526202245015362 00000000000000# Found on the 'TinCanTools' Hammer board. if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME s3c2410 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { # This config file was defaulting to big endian.. set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { # Force an error until we get a good number. set _CPUTAPID 0xffffffff } #use combined on interfaces or targets that cannot set TRST/SRST separately reset_config trst_and_srst #jtag scan chain jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-phys 0x30800000 -work-area-size 0x20000 -work-area-backup 0 # speed up memory downloads arm7_9 fast_memory_access enable arm7_9 dcc_downloads enable openocd-0.9.0/tcl/target/tmpa900.cfg0000644000175000017500000000220312526202245014010 00000000000000###################################### # Target: Toshiba TMPA900 ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME tmpa900 } # Toshiba TMPA900 series MCUs are always little endian as per datasheet. set _ENDIAN little if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926031 } #TMPA900 has following IDs: # CP15.0 register 0x41069265 # CP15.1 register 0x1d152152 # ARM core 0x07926031 # jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst adapter_nsrst_delay 20 jtag_ntrst_delay 20 ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME # Internal RAM-0 (16kB): 0xf8004000 # Internal RAM-1 (8kB): 0xf8008000 # Use internal RAM-0 and RAM-1 as working area (24kB total). $_TARGETNAME configure -work-area-phys 0xf8004000 -work-area-size 0x6000 \ -work-area-backup 0 openocd-0.9.0/tcl/target/altera_fpgasoc.cfg0000644000175000017500000000314612526202245015577 00000000000000# # Altera cyclone V SoC family, 5Cxxx # if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME fpgasoc } # CoreSight Debug Access Port if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x4ba00477 } jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x0f \ -expected-id $_DAP_TAPID # Subsidiary TAP: fpga if { [info exists FPGA_TAPID] } { set _FPGA_TAPID $FPGA_TAPID } else { set _FPGA_TAPID 0x02d020dd } jtag newtap $_CHIPNAME.fpga tap -irlen 10 -ircapture 0x01 -irmask 0x3 -expected-id $_FPGA_TAPID # # Cortex A9 target # # GDB target: Cortex-A9, using DAP, configuring only one core # Base addresses of cores: # core 0 - 0x80110000 # core 1 - 0x80112000 # Slow speed to be sure it will work adapter_khz 1000 set _TARGETNAME1 $_CHIPNAME.cpu.0 set _TARGETNAME2 $_CHIPNAME.cpu.1 # A9 core 0 target create $_TARGETNAME1 cortex_a -chain-position $_CHIPNAME.dap \ -coreid 0 -dbgbase 0x80110000 $_TARGETNAME1 configure -event reset-start { adapter_khz 1000 } $_TARGETNAME1 configure -event reset-assert-post "cycv_dbginit $_TARGETNAME1" $_TARGETNAME1 configure -event gdb-attach { halt } # A9 core 1 #target create $_TARGETNAME2 cortex_a -chain-position $_CHIPNAME.dap \ # -coreid 1 -dbgbase 0x80112000 #$_TARGETNAME2 configure -event reset-start { adapter_khz 1000 } #$_TARGETNAME2 configure -event reset-assert-post "cycv_dbginit $_TARGETNAME2" #$_TARGETNAME2 configure -event gdb-attach { halt } proc cycv_dbginit {target} { # General Cortex A8/A9 debug initialisation cortex_a dbginit } openocd-0.9.0/tcl/bitsbytes.tcl0000644000175000017500000000310112526202245013361 00000000000000#---------------------------------------- # Purpose - Create some $BIT variables # Create $K and $M variables # and some bit field extraction variables. # Creat helper variables ... # BIT0.. BIT31 for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { set vn [format "BIT%d" $x] global $vn set $vn [expr (1 << $x)] } # Create K bytes values # __1K ... to __2048K for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { set vn [format "__%dK" $x] global $vn set $vn [expr (1024 * $x)] } # Create M bytes values # __1M ... to __2048K for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { set vn [format "__%dM" $x] global $vn set $vn [expr (1024 * 1024 * $x)] } proc create_mask { MSB LSB } { return [expr (((1 << ($MSB - $LSB + 1))-1) << $LSB)] } # Cut Bits $MSB to $LSB out of this value. # Example: % format "0x%08x" [extract_bitfield 0x12345678 27 16] # Result: 0x02340000 proc extract_bitfield { VALUE MSB LSB } { return [expr [create_mask $MSB $LSB] & $VALUE] } # Cut bits $MSB to $LSB out of this value # and shift (normalize) them down to bit 0. # # Example: % format "0x%08x" [normalize_bitfield 0x12345678 27 16] # Result: 0x00000234 # proc normalize_bitfield { VALUE MSB LSB } { return [expr [extract_bitfield $VALUE $MSB $LSB ] >> $LSB] } proc show_normalize_bitfield { VALUE MSB LSB } { set m [create_mask $MSB $LSB] set mr [expr $VALUE & $m] set sr [expr $mr >> $LSB] echo [format "((0x%08x & 0x%08x) -> 0x%08x) >> %2d => (0x%x) %5d " $VALUE $m $mr $LSB $sr $sr] return $sr } openocd-0.9.0/tcl/mem_helper.tcl0000644000175000017500000000116212526202245013473 00000000000000# Helper for common memory read/modify/write procedures # mrw: "memory read word", returns value of $reg proc mrw {reg} { set value "" mem2array value 32 $reg 1 return $value(0) } add_usage_text mrw "address" add_help_text mrw "Returns value of word in memory." # mmw: "memory modify word", updates value of $reg # $reg <== ((value & ~$clearbits) | $setbits) proc mmw {reg setbits clearbits} { set old [mrw $reg] set new [expr ($old & ~$clearbits) | $setbits] mww $reg $new } add_usage_text mmw "address setbits clearbits" add_help_text mmw "Modify word in memory. new_val = (old_val & ~clearbits) | setbits;" openocd-0.9.0/tcl/interface/0000755000175000017500000000000012526202246012673 500000000000000openocd-0.9.0/tcl/interface/ftdi/0000755000175000017500000000000012526202245013620 500000000000000openocd-0.9.0/tcl/interface/ftdi/dp_busblaster.cfg0000644000175000017500000000117412526202245017055 00000000000000# # Dangerous Prototypes - Bus Blaster # # The Bus Blaster has a configurable buffer between the FTDI FT2232H and the # JTAG header which allows it to emulate various debugger types. It comes # configured as a JTAGkey device. # # http://dangerousprototypes.com/docs/Bus_Blaster # echo "Info : If you need SWD support, flash KT-Link buffer from https://github.com/bharrisau/busblaster and use dp_busblaster_kt-link.cfg instead" interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 openocd-0.9.0/tcl/interface/ftdi/minimodule.cfg0000644000175000017500000000076512526202245016373 00000000000000# # FTDI MiniModule # # http://www.ftdichip.com/Support/Documents/DataSheets/Modules/DS_FT2232H_Mini_Module.pdf # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "FT2232H MiniModule" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0018 0x05fb ftdi_layout_signal nSRST -data 0x0020 openocd-0.9.0/tcl/interface/ftdi/tumpa-lite.cfg0000644000175000017500000000047312526202245016306 00000000000000# # TIAO USB Multi-Protocol Adapter (TUMPA) Lite # # http://www.diygadget.com/tiao-usb-multi-protocol-adapter-lite-jtag-spi-i2c-serial.html # interface ftdi ftdi_vid_pid 0x0403 0x8a99 ftdi_layout_init 0x0038 0x087b ftdi_layout_signal nTRST -data 0x0020 -oe 0x0020 ftdi_layout_signal nSRST -data 0x0010 -oe 0x0010 openocd-0.9.0/tcl/interface/ftdi/ti-icdi.cfg0000644000175000017500000000062012526202245015541 00000000000000# # This is an FTDI-based debugging solution as found on some TI boards, # e.g. CC3200 LaunchPad. # # The schematics are identical to luminary-icdi (including SWD # support) but the USB IDs are different. # interface ftdi ftdi_vid_pid 0x0451 0xc32a ftdi_layout_init 0x00a8 0x00eb ftdi_layout_signal nSRST -noe 0x0020 ftdi_layout_signal SWD_EN -ndata 0x0080 ftdi_layout_signal SWDIO_OE -data 0x0008 openocd-0.9.0/tcl/interface/ftdi/openocd-usb-hs.cfg0000644000175000017500000000052312526202245017047 00000000000000# # embedded projects openocd usb adapter v3 # # http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=14 # interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/flossjtag.cfg0000644000175000017500000000167312526202245016224 00000000000000# # FlossJTAG # # http://github.com/esden/floss-jtag # # This is the v0.3 and v1.0 Floss-JTAG compatible config file. It relies on the # existence of an EEPROM on Floss-JTAG containing a name. If you have several # Floss-JTAG adapters connected you can use the serial number to select a # specific device. # # If your Floss-JTAG does not have an EEPROM, or the EEPROM is empty, use the # flossjtag-noeeprom.cfg file. # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_vid_pid 0x0403 0x6010 ftdi_device_desc "FLOSS-JTAG" #ftdi_serial "FJ000001" ftdi_layout_init 0x0008 0x180b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0040 -oe 0x0040 ftdi_layout_signal LED -data 0x0800 ftdi_layout_signal LED2 -data 0x1000 openocd-0.9.0/tcl/interface/ftdi/hitex_lpc1768stick.cfg0000644000175000017500000000040112526202245017557 00000000000000# # Hitex LPC1768-Stick # # http://www.hitex.com/?id=1602 # interface ftdi ftdi_device_desc "LPC1768-Stick" ftdi_vid_pid 0x0640 0x0026 ftdi_layout_init 0x0388 0x038b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0080 -noe 0x200 openocd-0.9.0/tcl/interface/ftdi/hitex_str9-comstick.cfg0000644000175000017500000000040712526202245020136 00000000000000# # Hitex STR9-comStick # # http://www.hitex.com/index.php?id=383 # interface ftdi ftdi_device_desc "STR9-comStick" ftdi_vid_pid 0x0640 0x002c ftdi_layout_init 0x0108 0x010b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 -oe 0x0200 openocd-0.9.0/tcl/interface/ftdi/luminary.cfg0000644000175000017500000000237712526202245016072 00000000000000# # Luminary Micro Stellaris Evaluation Kits # # http://www.luminarymicro.com/products/evaluation_kits.html # # There are a number of evaluation kits for Stellaris Cortex-M3 chips. # Currently they all bundle ftdi based debug support. When that is # used (instead of an external adapter), use this config file in one # of these two modes: # # - Eval board debug ... debug of the Stellaris chip via port A. # # - Other board debug ... same thing, but the board acts as a debug # adapter for another board (using a standard ARM JTAG connector). # The Stellaris chip stays in reset. # # Those support both JTAG and SWD. SWD is an ARM-only two-wire debug # protocol; in 2009, OpenOCD does not support SWD. # # Port B of the ftdi chip is normally used as a serial link to the # Stellaris chip. On most boards (but not older LM3S811 eval boards), # when SWD is used Port B may instead be used to read low-bandwidth # "SWO trace" data, including so-called "printf style" output from # firmware via the ITM module as well as profile data. # interface ftdi ftdi_device_desc "Stellaris Evaluation Board" ftdi_vid_pid 0x0403 0xbcd9 ftdi_layout_init 0x00a8 0x00eb ftdi_layout_signal nSRST -noe 0x0020 ftdi_layout_signal SWD_EN -ndata 0x0080 ftdi_layout_signal SWDIO_OE -data 0x0008 openocd-0.9.0/tcl/interface/ftdi/m53evk.cfg0000644000175000017500000000042312526202245015332 00000000000000# # DENX M53EVK # # http://www.denx-cs.de/?q=M53EVK # interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_channel 0 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0020 -oe 0x0020 openocd-0.9.0/tcl/interface/ftdi/olimex-arm-usb-ocd.cfg0000644000175000017500000000046412526202245017631 00000000000000# # Olimex ARM-USB-OCD # # http://www.olimex.com/dev/arm-usb-ocd.html # interface ftdi ftdi_device_desc "Olimex OpenOCD JTAG" ftdi_vid_pid 0x15ba 0x0003 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nSRST -oe 0x0200 ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal LED -data 0x0800 openocd-0.9.0/tcl/interface/ftdi/olimex-jtag-tiny.cfg0000644000175000017500000000047212526202245017425 00000000000000# # Olimex ARM-USB-TINY # # http://www.olimex.com/dev/arm-usb-tiny.html # interface ftdi ftdi_device_desc "Olimex OpenOCD JTAG TINY" ftdi_vid_pid 0x15ba 0x0004 ftdi_layout_init 0x0808 0x0a1b ftdi_layout_signal nSRST -oe 0x0200 ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 ftdi_layout_signal LED -data 0x0800 openocd-0.9.0/tcl/interface/ftdi/kt-link.cfg0000644000175000017500000000057512526202245015601 00000000000000# # Kristech KT-Link # # http://www.kristech.eu # interface ftdi ftdi_device_desc "KT-LINK" ftdi_vid_pid 0x0403 0xbbe2 ftdi_layout_init 0x8c28 0xff3b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 ftdi_layout_signal LED -data 0x8000 ftdi_layout_signal SWD_EN -ndata 0x0020 -oe 0x2000 ftdi_layout_signal SWDIO_OE -ndata 0x1000 openocd-0.9.0/tcl/interface/ftdi/flossjtag-noeeprom.cfg0000644000175000017500000000150512526202245020040 00000000000000# # FlossJTAG # # http://github.com/esden/floss-jtag # # This is the pre v0.3 Floss-JTAG compatible config file. It can also be used # for newer versions of Floss-JTAG with empty or not populated EEPROM. If you # have several Floss-JTAG connected you have to use the USB ID to select a # specific one. # # If you have a Floss-JTAG WITH EEPROM that is programmed, use the # flossjtag.cfg file. # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0040 -oe 0x0040 openocd-0.9.0/tcl/interface/ftdi/jtag-lock-pick_tiny_2.cfg0000644000175000017500000000063512526202245020310 00000000000000# # DISTORTEC JTAG-lock-pick Tiny 2 # # http://www.distortec.com # interface ftdi ftdi_device_desc "JTAG-lock-pick Tiny 2" ftdi_vid_pid 0x0403 0x8220 ftdi_layout_init 0x8c28 0xff3b ftdi_layout_signal SWD_EN -ndata 0x0020 -oe 0x2000 ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 ftdi_layout_signal SWDIO_OE -ndata 0x1000 ftdi_layout_signal LED -ndata 0x8000 openocd-0.9.0/tcl/interface/ftdi/digilent_jtag_smt2.cfg0000644000175000017500000000073212526202245017774 00000000000000# # Digilent JTAG-SMT2 # # http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,395,1053&Prod=JTAG-SMT2 # # Config is based on data from # http://electronix.ru/forum/index.php?showtopic=114633&view=findpost&p=1215497 and ZedBoard schematics # interface ftdi ftdi_vid_pid 0x0403 0x6014 ftdi_layout_init 0x2088 0x3f8b ftdi_layout_signal nSRST -data 0x2000 ftdi_layout_signal GPIO2 -data 0x2000 ftdi_layout_signal GPIO1 -data 0x0200 ftdi_layout_signal GPIO0 -data 0x0100 openocd-0.9.0/tcl/interface/ftdi/ngxtech.cfg0000644000175000017500000000113612526202245015662 00000000000000# # NGX ARM USB JTAG # # http://shop.ngxtechnologies.com/product_info.php?cPath=26&products_id=30 # echo "WARNING!" echo "This file was not tested with real interface, but is assumed to work as this" echo "interface uses the same layout as configs that were verified. Please report your" echo "experience with this file to openocd-devel mailing list, so it could be marked" echo "as working or fixed." interface ftdi ftdi_device_desc "NGX JTAG" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/iotlab-usb.cfg0000644000175000017500000000043312526202245016262 00000000000000# # This is the integrated adapter as found on the IoT-LAB boards # https://github.com/iot-lab/iot-lab/wiki # interface ftdi ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0040 -oe 0x0040 openocd-0.9.0/tcl/interface/ftdi/redbee-usb.cfg0000644000175000017500000000112612526202245016236 00000000000000# # Redwire Redbee-USB # # http://www.redwirellc.com # # The Redbee-USB has an onboard FT2232H with: # - FT2232H channel B wired to mc13224v JTAG # - FT2232H channel A wired to mc13224v UART1 # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_vid_pid 0x0403 0x6010 ftdi_channel 1 ftdi_layout_init 0x0c08 0x0c2b ftdi_layout_signal nTRST -data 0x0800 ftdi_layout_signal nSRST -data 0x0400 openocd-0.9.0/tcl/interface/ftdi/stm32-stick.cfg0000644000175000017500000000043112526202245016302 00000000000000# # Hitex STM32-PerformanceStick # # http://www.hitex.com/index.php?id=340 # interface ftdi ftdi_device_desc "STM32-PerformanceStick" ftdi_vid_pid 0x0640 0x002d ftdi_layout_init 0x0388 0x038b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0080 -noe 0x200 openocd-0.9.0/tcl/interface/ftdi/signalyzer-lite.cfg0000644000175000017500000000100612526202245017340 00000000000000# # Xverve Signalyzer LITE (DT-USB-SLITE) # # http://www.signalyzer.com # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Signalyzer LITE" ftdi_vid_pid 0x0403 0xbca1 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0020 -oe 0x0020 openocd-0.9.0/tcl/interface/ftdi/luminary-lm3s811.cfg0000644000175000017500000000130112526202245017162 00000000000000# # Luminary Micro Stellaris LM3S811 Evaluation Kit # # http://www.luminarymicro.com/products/stellaris_811_evaluation_kits.html # # NOTE: this is only for boards *before* Rev C, which adds support # for SWO tracing with ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN signals. # The "evb_lm3s811" layout doesn't set up those signals. # # Rev C boards work more like the other Stellaris eval boards. They # need to use the "luminary_icdi" layout to work correctly. # interface ftdi ftdi_device_desc "LM3S811 Evaluation Board" ftdi_vid_pid 0x0403 0xbcd9 ftdi_layout_init 0x0088 0x008b ftdi_layout_signal nSRST -data 0x0020 -oe 0x0020 ftdi_layout_signal SWD_EN -ndata 0x0080 ftdi_layout_signal SWDIO_OE -data 0x0008 openocd-0.9.0/tcl/interface/ftdi/dp_busblaster_kt-link.cfg0000644000175000017500000000132312526202245020502 00000000000000# # Dangerous Prototypes - Bus Blaster (with KT-Link buffer) # # The Bus Blaster has a configurable buffer between the FTDI FT2232H # and the JTAG header which allows it to emulate various debugger # types. This config works with KT-Link compatible implementation from # https://github.com/bharrisau/busblaster and is SWD-enabled. # # http://dangerousprototypes.com/docs/Bus_Blaster # interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x8c28 0xff3b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 ftdi_layout_signal LED -ndata 0x8000 ftdi_layout_signal SWD_EN -ndata 0x0020 -oe 0x2000 ftdi_layout_signal SWDIO_OE -ndata 0x1000 openocd-0.9.0/tcl/interface/ftdi/sheevaplug.cfg0000644000175000017500000000052712526202245016370 00000000000000# # Marvel SheevaPlug Development Kit # # http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp # interface ftdi ftdi_device_desc "SheevaPlug JTAGKey FT2232D B" ftdi_vid_pid 0x9e88 0x9e8f ftdi_channel 1 ftdi_layout_init 0x0608 0x0f1b ftdi_layout_signal nTRST -data 0x0200 ftdi_layout_signal nSRST -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/flyswatter2.cfg0000644000175000017500000000050012526202245016502 00000000000000# # TinCanTools Flyswatter2 # # http://www.tincantools.com/product.php?productid=16153 # interface ftdi ftdi_device_desc "Flyswatter2" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0538 0x057b ftdi_layout_signal LED -ndata 0x0400 ftdi_layout_signal nTRST -data 0x0010 ftdi_layout_signal nSRST -data 0x0020 -noe 0x0100 openocd-0.9.0/tcl/interface/ftdi/xds100v2.cfg0000644000175000017500000000333712526202245015516 00000000000000# # Texas Instruments XDS100v2 # # http://processors.wiki.ti.com/index.php/XDS100#XDS100v2_Features # # Detailed documentation is available only as CPLD verilog source code # to the registered TI users. # interface ftdi ftdi_vid_pid 0x0403 0xa6d0 0x0403 0x6010 ftdi_layout_init 0x0038 0x597b # 8000 z - unused # 4000 0 > CPLD loopback (all target side pins high-Z) # 2000 z < !( cable connected ) (open drain on CPLD side for $reasons) # 1000 0 > EMU1_oe # # 800 0 > PWR_RST = clear power-loss flag on rising edge # 400 z < !( power-loss flag ) # 200 z < nSRST # 100 0 > nSRST_oe # # 80 z < RTCK # 40 0 > EMU0_oe # 20 1 > EMU_EN # 10 1 > nTRST # # 8 1 > TMS # 4 z < TDO # 2 0 > TDI # 1 0 > TCK # # As long as the power-loss flag is set, all target-side pins are # high-Z except the EMU-pins for which the opposite holds unless # EMU_EN is high. # # To use wait-in-reset, drive EMU0 low at power-on reset. If the # target normally reuses EMU0 for other purposes, clear EMU_EN to # keep the EMU pins high-Z until the target is power-cycled. # # The LED only turns off at USB suspend, which is also the only way to # set the power-loss flag manually. (Can be done in software e.g. by # changing the USB configuration to zero.) # ftdi_layout_signal nTRST -data 0x0010 ftdi_layout_signal nSRST -oe 0x0100 ftdi_layout_signal EMU_EN -data 0x0020 ftdi_layout_signal EMU0 -oe 0x0040 ftdi_layout_signal EMU1 -oe 0x1000 ftdi_layout_signal PWR_RST -data 0x0800 ftdi_layout_signal LOOPBACK -data 0x4000 echo "\nInfo : to use this adapter you MUST add ``init; ftdi_set_signal PWR_RST 1; jtag arp_init'' to the end of your config file!\n" # note: rising edge on PWR_RST is also needed after power-cycling the # target openocd-0.9.0/tcl/interface/ftdi/vpaclink.cfg0000644000175000017500000000106212526202245016027 00000000000000# # Voipac VPACLink # # http://voipac.com/27M-JTG-000 # echo "WARNING!" echo "This file was not tested with real interface, but is assumed to work as this" echo "interface uses the same layout as configs that were verified. Please report your" echo "experience with this file to openocd-devel mailing list, so it could be marked" echo "as working or fixed." interface ftdi ftdi_device_desc "VPACLink" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/jtagkey2p.cfg0000644000175000017500000000043012526202245016116 00000000000000# # Amontec JTAGkey2P # # http://www.amontec.com/jtagkey2p.shtml # interface ftdi ftdi_device_desc "Amontec JTAGkey-2P" ftdi_vid_pid 0x0403 0xcff8 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 openocd-0.9.0/tcl/interface/ftdi/cortino.cfg0000644000175000017500000000037712526202245015705 00000000000000# # Hitex Cortino # # http://www.hitex.com/index.php?id=cortino # interface ftdi ftdi_device_desc "Cortino" ftdi_vid_pid 0x0640 0x0032 ftdi_layout_init 0x0108 0x010b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 -oe 0x0200 openocd-0.9.0/tcl/interface/ftdi/hilscher_nxhx50_re.cfg0000644000175000017500000000101712526202245017721 00000000000000# # Hilscher NXHX 50-RE # # http://de.hilscher.com/products_details_hardware.html?p_id=P_483c0f582ad36&bs=20 # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "NXHX50-RE" ftdi_vid_pid 0x0640 0x0028 ftdi_layout_init 0x0308 0x030b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 openocd-0.9.0/tcl/interface/ftdi/flyswatter.cfg0000644000175000017500000000045712526202245016433 00000000000000# # TinCanTools Flyswatter # # http://www.tincantools.com/product.php?productid=16134 # interface ftdi ftdi_device_desc "Flyswatter" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0818 0x0cfb ftdi_layout_signal nTRST -data 0x0010 ftdi_layout_signal nSRST -oe 0x0020 ftdi_layout_signal LED -data 0x0c00 openocd-0.9.0/tcl/interface/ftdi/neodb.cfg0000644000175000017500000000054412526202245015313 00000000000000# # Openmoko USB JTAG/RS232 adapter # # http://wiki.openmoko.org/wiki/Debug_Board_v3 # interface ftdi ftdi_device_desc "Debug Board for Neo1973" ftdi_vid_pid 0x1457 0x5118 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 ftdi_layout_signal nNOR_WP -data 0x0010 -oe 0x0010 openocd-0.9.0/tcl/interface/ftdi/rowley-cc-arm-swd.cfg0000644000175000017500000000041612526202245017476 00000000000000# # Rowley ARM SWD Adapter # http://sites.fastspring.com/rowley/product/armswdadapter # https://drive.google.com/file/d/0Bzv7UpKpOQhnTUNNdzI5OUR4WGs/edit?usp=sharing # transport select swd ftdi_layout_signal SWD_EN -nalias nTRST ftdi_layout_signal SWDIO_OE -alias TMS openocd-0.9.0/tcl/interface/ftdi/jtagkey.cfg0000644000175000017500000000042112526202245015654 00000000000000# # Amontec JTAGkey # # http://www.amontec.com/jtagkey.shtml # interface ftdi ftdi_device_desc "Amontec JTAGkey" ftdi_vid_pid 0x0403 0xcff8 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 openocd-0.9.0/tcl/interface/ftdi/tumpa.cfg0000644000175000017500000000050612526202245015350 00000000000000# # TIAO USB Multi-Protocol Adapter (TUMPA) # # http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html # interface ftdi ftdi_vid_pid 0x0403 0x8a98 0x0403 0x6010 ftdi_layout_init 0x0038 0x087b ftdi_layout_signal nTRST -data 0x0020 ftdi_layout_signal nSRST -data 0x0010 reset_config srst_push_pull openocd-0.9.0/tcl/interface/ftdi/opendous_ftdi.cfg0000644000175000017500000000062312526202245017064 00000000000000# # Opendous # # http://code.google.com/p/opendous/wiki/JTAG # # According to the website, it is similar to jtagkey, but it uses channel B # (and it has a different pid number). # interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_channel 1 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 openocd-0.9.0/tcl/interface/ftdi/hilscher_nxhx500_re.cfg0000644000175000017500000000102212526202245017775 00000000000000# # Hilscher NXHX 500-RE # # http://de.hilscher.com/products_details_hardware.html?p_id=P_461ff2053bad1&bs=20 # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "NXHX 500-RE" ftdi_vid_pid 0x0640 0x0028 ftdi_layout_init 0x0308 0x030b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 openocd-0.9.0/tcl/interface/ftdi/hilscher_nxhx500_etm.cfg0000644000175000017500000000101612526202245020157 00000000000000# # Hilscher NXHX 500-ETM # # http://de.hilscher.com/files_design/8/NXHX500-ETM_description_Rev01_EN.pdf # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "NXHX 500-ETM" ftdi_vid_pid 0x0640 0x0028 ftdi_layout_init 0x0308 0x030b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 openocd-0.9.0/tcl/interface/ftdi/gw16042.cfg0000644000175000017500000000075312526202245015240 00000000000000# # Gateworks GW16042 JTAG Dongle # # http://www.gateworks.com/ # # Layout: FTDI FT2232H # ADBUS0 TCK # ADBUS1 TDI # ADBUS2 TDO (input) # ADBUS3 TMS # ADBUS4 nTRST # ADBUS5 nSRST # ADBUS6 OE (active high) for TRST, TDI, TMS, TCK # ADBUS7 NC # ACBUS0-7 NC # BDBUS0 RXD # BDBUS1 TXD (input) # interface ftdi ftdi_device_desc "USB-JTAG" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0058 0x007b ftdi_layout_signal nTRST -data 0x0010 ftdi_layout_signal nSRST -oe 0x0020 openocd-0.9.0/tcl/interface/ftdi/turtelizer2-revB.cfg0000644000175000017500000000105512526202245017411 00000000000000# # egnite Turtelizer 2 rev B (with SRST only) # # http://www.ethernut.de/en/hardware/turtelizer/index.html # echo "WARNING!" echo "This file was not tested with real interface, it is based on schematics and code" echo "in ft2232.c. Please report your experience with this file to openocd-devel" echo "mailing list, so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Turtelizer JTAG/RS232 Adapter" ftdi_vid_pid 0x0403 0xbdc8 ftdi_layout_init 0x0008 0x0c5b ftdi_layout_signal nSRST -oe 0x0040 ftdi_layout_signal LED -data 0x0c00 openocd-0.9.0/tcl/interface/ftdi/turtelizer2-revC.cfg0000644000175000017500000000053212526202245017411 00000000000000# # egnite Turtelizer 2 revC (with TRST and SRST) # # http://www.ethernut.de/en/hardware/turtelizer/index.html # interface ftdi ftdi_device_desc "Turtelizer JTAG/RS232 Adapter" ftdi_vid_pid 0x0403 0xbdc8 ftdi_layout_init 0x0008 0x0c7b ftdi_layout_signal nTRST -oe 0x0020 ftdi_layout_signal nSRST -oe 0x0040 ftdi_layout_signal LED -ndata 0x0c00 openocd-0.9.0/tcl/interface/ftdi/dlp-usb1232h.cfg0000644000175000017500000000125012526202245016245 00000000000000# # DLP Design DLP-USB1232H USB-to-UART/FIFO interface module # # http://www.dlpdesign.com/usb/usb1232h.shtml # # Schematics for OpenOCD usage: # http://randomprojects.org/wiki/DLP-USB1232H_and_OpenOCD_based_JTAG_adapter # echo "WARNING!" echo "This file was not tested with real interface, it is based on schematics and code" echo "in ft2232.c. Please report your experience with this file to openocd-devel" echo "mailing list, so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Dual RS232-HS" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0040 -oe 0x0040 openocd-0.9.0/tcl/interface/ftdi/oocdlink.cfg0000644000175000017500000000112612526202245016023 00000000000000# # Joern Kaipf's OOCDLink # # http://www.joernonline.de/contrexx2/cms/index.php?page=126 # echo "WARNING!" echo "This file was not tested with real interface, but is assumed to work as this" echo "interface uses the same layout as configs that were verified. Please report your" echo "experience with this file to openocd-devel mailing list, so it could be marked" echo "as working or fixed." interface ftdi ftdi_device_desc "OOCDLink" ftdi_vid_pid 0x0403 0xbaf8 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/redbee-econotag.cfg0000644000175000017500000000113612526202245017245 00000000000000# # Redwire Redbee-Econotag # # http://www.redwirellc.com/store/node/1 # # The Redbee-Econotag has an onboard FT2232H with: # - FT2232H channel A wired to mc13224v JTAG # - FT2232H channel B wired to mc13224v UART1 # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0c08 0x0c2b ftdi_layout_signal nTRST -data 0x0800 ftdi_layout_signal nSRST -data 0x0400 openocd-0.9.0/tcl/interface/ftdi/signalyzer.cfg0000644000175000017500000000077612526202245016422 00000000000000# # Xverve Signalyzer Tool (DT-USB-ST) # # http://www.signalyzer.com # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Signalyzer" ftdi_vid_pid 0x0403 0xbca0 ftdi_layout_init 0x0008 0x000b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0020 -oe 0x0020 openocd-0.9.0/tcl/interface/ftdi/olimex-arm-usb-ocd-h.cfg0000644000175000017500000000047212526202245020055 00000000000000# # Olimex ARM-USB-OCD-H # # http://www.olimex.com/dev/arm-usb-ocd-h.html # interface ftdi ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H" ftdi_vid_pid 0x15ba 0x002b ftdi_layout_init 0x0908 0x0b1b ftdi_layout_signal nSRST -oe 0x0200 ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal LED -data 0x0800 openocd-0.9.0/tcl/interface/ftdi/lisa-l.cfg0000644000175000017500000000105112526202245015377 00000000000000# # Lisa/L # # http://paparazzi.enac.fr/wiki/Lisa # echo "WARNING!" echo "This file was not tested with real interface, it is based on schematics and code" echo "in ft2232.c. Please report your experience with this file to openocd-devel" echo "mailing list, so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Lisa/L" ftdi_vid_pid 0x0403 0x6010 ftdi_channel 1 ftdi_layout_init 0x0008 0x180b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0040 -oe 0x0040 ftdi_layout_signal LED -data 0x1800 openocd-0.9.0/tcl/interface/ftdi/hilscher_nxhx50_etm.cfg0000644000175000017500000000101312526202245020074 00000000000000# # Hilscher NXHX 50-ETM # # http://de.hilscher.com/files_design/8/NXHX50-ETM_description_Rev01_EN.pdf # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "NXHX 50-ETM" ftdi_vid_pid 0x0640 0x0028 ftdi_layout_init 0x0308 0x030b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 openocd-0.9.0/tcl/interface/ftdi/luminary-icdi.cfg0000644000175000017500000000164612526202245016776 00000000000000# # Luminary Micro Stellaris LM3S9B9x Evaluation Kits # In-Circuit Debug Interface (ICDI) Board # # Essentially all Luminary debug hardware is the same, (with both # JTAG and SWD support compatible with ICDI boards. This ICDI adapter # configuration is JTAG-only, but the same hardware handles SWD too. # # This is a discrete ftdi based debug board which supports ARM's # JTAG/SWD connectors in both backwards-compatible 20-pin format and # in the new-style compact 10-pin. There's also an 8-pin connector # with serial port support. It's included with LM3S9B9x eval boards. # # http://www.luminarymicro.com/products/ek-lm3s9b90.html # http://www.luminarymicro.com/products/ek-lm3s9b92.html # interface ftdi ftdi_device_desc "Luminary Micro ICDI Board" ftdi_vid_pid 0x0403 0xbcda ftdi_layout_init 0x00a8 0x00eb ftdi_layout_signal nSRST -noe 0x0020 ftdi_layout_signal SWD_EN -ndata 0x0080 ftdi_layout_signal SWDIO_OE -data 0x0008 openocd-0.9.0/tcl/interface/ftdi/hilscher_nxhx10_etm.cfg0000644000175000017500000000101412526202245020071 00000000000000# # Hilscher NXHX 10-ETM # # http://de.hilscher.com/products_details_hardware.html?p_id=P_4ce145a5983e6 # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "NXHX 10-ETM" ftdi_vid_pid 0x0640 0x0028 ftdi_layout_init 0x0308 0x030b ftdi_layout_signal nTRST -data 0x0100 ftdi_layout_signal nSRST -data 0x0200 openocd-0.9.0/tcl/interface/ftdi/swd-resistor-hack.cfg0000644000175000017500000000152712526202245017577 00000000000000# # Connect TDI to SWDIO via a suitable series resistor (220-470 Ohm or # so depending on the drive capability of the target and adapter); # connect TDO directly to SWDIO. # # You also need to have reliable GND connection between the target and # adapter. Vref of the adapter should be supplied with a voltage equal # to the target's (preferrably connect it to Vcc). You can also # optionally connect nSRST. Leave everything else unconnected. # # FTDI Target # ---- ------ # 1 - Vref ----------------- Vcc # 3 - nTRST - # 4 - GND ----------------- GND # 5 - TDI ---/\470 Ohm/\--- SWDIO # 7 - TMS - # 9 - TCK ----------------- SWCLK # 11 - RTCK - # 13 - TDO ----------------- SWDIO # 15 - nSRST - - - - - - - - - nRESET # transport select swd ftdi_layout_signal SWD_EN -data 0 openocd-0.9.0/tcl/interface/ftdi/jtagkey2.cfg0000644000175000017500000000042512526202245015742 00000000000000# # Amontec JTAGkey2 # # http://www.amontec.com/jtagkey2.shtml # interface ftdi ftdi_device_desc "Amontec JTAGkey-2" ftdi_vid_pid 0x0403 0xcff8 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 openocd-0.9.0/tcl/interface/ftdi/olimex-arm-jtag-swd.cfg0000644000175000017500000000030112526202245020003 00000000000000# # Olimex ARM JTAG SWD adapter # https://www.olimex.com/Products/ARM/JTAG/ARM-JTAG-SWD/ # transport select swd ftdi_layout_signal SWD_EN -nalias nTRST ftdi_layout_signal SWDIO_OE -alias TMS openocd-0.9.0/tcl/interface/ftdi/axm0432.cfg0000644000175000017500000000072612526202245015324 00000000000000# # Axiom axm0432 # # http://www.axman.com # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "Symphony SoundBite" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0c08 0x0c2b ftdi_layout_signal nTRST -data 0x0800 ftdi_layout_signal nSRST -data 0x0400 openocd-0.9.0/tcl/interface/ftdi/openocd-usb.cfg0000644000175000017500000000045612526202245016444 00000000000000# # Hubert Hoegl's USB to JTAG # # http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html # interface ftdi ftdi_device_desc "Dual RS232" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0508 0x0f1b ftdi_layout_signal nTRST -data 0x0200 -noe 0x0100 ftdi_layout_signal nSRST -data 0x0800 -noe 0x0400 openocd-0.9.0/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg0000644000175000017500000000051012526202245020264 00000000000000# # Olimex ARM-USB-TINY-H # # http://www.olimex.com/dev/arm-usb-tiny-h.html # interface ftdi ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" ftdi_vid_pid 0x15ba 0x002a ftdi_layout_init 0x0808 0x0a1b ftdi_layout_signal nSRST -oe 0x0200 ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 ftdi_layout_signal LED -data 0x0800 openocd-0.9.0/tcl/interface/ftdi/icebear.cfg0000644000175000017500000000075412526202245015621 00000000000000# # Section5 ICEBear # # http://section5.ch/icebear # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "ICEbear JTAG adapter" ftdi_vid_pid 0x0403 0xc140 ftdi_layout_init 0x0028 0x002b ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010 ftdi_layout_signal nSRST -data 0x0020 openocd-0.9.0/tcl/interface/ftdi/calao-usb-a9260-c01.cfg0000644000175000017500000000121212526202245017203 00000000000000# # CALAO Systems USB-A9260-C01 # # http://www.calao-systems.com/ # echo "WARNING!" echo "This file was not tested with real interface, but is assumed to work as this" echo "interface uses the same layout as configs that were verified. Please report your" echo "experience with this file to openocd-devel mailing list, so it could be marked" echo "as working or fixed." interface ftdi ftdi_device_desc "USB-A9260" ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 script interface/calao-usb-a9260.cfg script target/at91sam9260minimal.cfg openocd-0.9.0/tcl/interface/ftdi/calao-usb-a9260-c02.cfg0000644000175000017500000000121212526202245017204 00000000000000# # CALAO Systems USB-A9260-C02 # # http://www.calao-systems.com/ # echo "WARNING!" echo "This file was not tested with real interface, but is assumed to work as this" echo "interface uses the same layout as configs that were verified. Please report your" echo "experience with this file to openocd-devel mailing list, so it could be marked" echo "as working or fixed." interface ftdi ftdi_device_desc "USB-A9260" ftdi_vid_pid 0x0403 0x6001 ftdi_layout_init 0x0c08 0x0f1b ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 script interface/calao-usb-a9260.cfg script target/at91sam9260minimal.cfg openocd-0.9.0/tcl/interface/ftdi/openrd.cfg0000644000175000017500000000104612526202245015511 00000000000000# # Marvell OpenRD # # http://www.marvell.com/products/embedded_processors/developer/kirkwood/openrd.jsp # echo "WARNING!" echo "This file was not tested with real interface, it is based on code in ft2232.c." echo "Please report your experience with this file to openocd-devel mailing list," echo "so it could be marked as working or fixed." interface ftdi ftdi_device_desc "OpenRD JTAGKey FT2232D" ftdi_vid_pid 0x0403 0x9e90 ftdi_channel 1 ftdi_layout_init 0x0608 0x0f1b ftdi_layout_signal nTRST -data 0x0200 ftdi_layout_signal nSRST -noe 0x0400 openocd-0.9.0/tcl/interface/jtag_vpi.cfg0000644000175000017500000000054212526202245015077 00000000000000interface jtag_vpi # Set the VPI JTAG server port if { [info exists VPI_PORT] } { set _VPI_PORT $VPI_PORT } else { set _VPI_PORT 5555 } # Set the VPI JTAG server address if { [info exists VPI_ADDRESS] } { set _VPI_ADDRESS $VPI_ADDRESS } else { set _VPI_ADDRESS "127.0.0.1" } jtag_vpi_set_port $_VPI_PORT jtag_vpi_set_address $_VPI_ADDRESS openocd-0.9.0/tcl/interface/usb-jtag.cfg0000644000175000017500000000024212526202245015005 00000000000000# # Kolja Waschk's USB-JTAG # # http://www.ixo.de/info/usb_jtag/ # interface usb_blaster usb_blaster_vid_pid 0x16C0 0x06AD usb_blaster_device_desc "USB-JTAG-IF" openocd-0.9.0/tcl/interface/minimodule.cfg0000644000175000017500000000034412526202245015436 00000000000000# # FTDI MiniModule # # http://www.ftdichip.com/Support/Documents/DataSheets/Modules/DS_FT2232H_Mini_Module.pdf # interface ft2232 ft2232_device_desc "FT2232H MiniModule" ft2232_layout "minimodule" ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/parport.cfg0000644000175000017500000000056312526202245014766 00000000000000# # Parallel port wiggler (many clones available) on port 0x378 # # Addresses: 0x378/LPT1 or 0x278/LPT2 ... # if { [info exists PARPORTADDR] } { set _PARPORTADDR $PARPORTADDR } else { if {$tcl_platform(platform) eq "windows"} { set _PARPORTADDR 0x378 } { set _PARPORTADDR 0 } } interface parport parport_port $_PARPORTADDR parport_cable wiggler openocd-0.9.0/tcl/interface/ti-icdi.cfg0000644000175000017500000000053512526202245014620 00000000000000# # TI Stellaris In-Circuit Debug Interface (ICDI) Board # # This is the propriety ICDI interface used on newer boards such as # LM4F232 Evaluation Kit - http://www.ti.com/tool/ek-lm4f232 # Stellaris Launchpad - http://www.ti.com/stellaris-launchpad # http://www.ti.com/tool/ek-lm4f232 # interface hla hla_layout ti-icdi hla_vid_pid 0x1cbe 0x00fd openocd-0.9.0/tcl/interface/openocd-usb-hs.cfg0000644000175000017500000000037712526202245016130 00000000000000# # embedded projects openocd usb adapter v3 # # http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=14 # interface ft2232 ft2232_vid_pid 0x0403 0x6010 ft2232_device_desc "Dual RS232-HS" ft2232_layout "oocdlink" ft2232_latency 2 openocd-0.9.0/tcl/interface/flossjtag.cfg0000644000175000017500000000106712526202245015273 00000000000000# # FlossJTAG # # http://github.com/esden/floss-jtag # # This is the v0.3 and v1.0 Floss-JTAG compatible config file. It relies on the # existence of an EEPROM on Floss-JTAG containing a name. If you have several # Floss-JTAG adapters connected you can use the serial number to select a # specific device. # # If your Floss-JTAG does not have an EEPROM, or the EEPROM is empty, use the # flossjtag-noeeprom.cfg file. # interface ft2232 ft2232_vid_pid 0x0403 0x6010 ft2232_device_desc "FLOSS-JTAG" #ft2232_serial "FJ000001" ft2232_layout "flossjtag" ft2232_latency 2 openocd-0.9.0/tcl/interface/parport_dlc5.cfg0000644000175000017500000000045012526202245015670 00000000000000# # Xilinx Parallel Cable III 'DLC 5' (and various clones) # # http://www.xilinx.com/itp/xilinx4/data/docs/pac/appendixb.html # if { [info exists PARPORTADDR] } { set _PARPORTADDR $PARPORTADDR } else { set _PARPORTADDR 0 } interface parport parport_port $_PARPORTADDR parport_cable dlc5 openocd-0.9.0/tcl/interface/hitex_str9-comstick.cfg0000644000175000017500000000025612526202245017212 00000000000000# # Hitex STR9-comStick # # http://www.hitex.com/index.php?id=383 # interface ft2232 ft2232_device_desc "STR9-comStick" ft2232_layout comstick ft2232_vid_pid 0x0640 0x002c openocd-0.9.0/tcl/interface/ulink.cfg0000644000175000017500000000024212526202246014414 00000000000000# # Keil ULINK running OpenULINK firmware. # # http://www.keil.com/ulink1/ # http://article.gmane.org/gmane.comp.debugging.openocd.devel/17362 # interface ulink openocd-0.9.0/tcl/interface/vsllink.cfg0000644000175000017500000000012212526202246014751 00000000000000# # Versaloon Link -- VSLLink # # http://www.versaloon.com/ # interface vsllink openocd-0.9.0/tcl/interface/at91rm9200.cfg0000644000175000017500000000014612526202246014725 00000000000000# # Various Atmel AT91RM9200 boards # # TODO: URL? # interface at91rm9200 at91rm9200_device rea_ecr openocd-0.9.0/tcl/interface/luminary.cfg0000644000175000017500000000222012526202246015130 00000000000000# # Luminary Micro Stellaris Evaluation Kits # # http://www.luminarymicro.com/products/evaluation_kits.html # # There are a number of evaluation kits for Stellaris Cortex-M3 chips. # Currently they all bundle FT2232 based debug support. When that is # used (instead of an external adapter), use this config file in one # of these two modes: # # - Eval board debug ... debug of the Stellaris chip via port A. # # - Other board debug ... same thing, but the board acts as a debug # adapter for another board (using a standard ARM JTAG connector). # The Stellaris chip stays in reset. # # Those support both JTAG and SWD. SWD is an ARM-only two-wire debug # protocol; in 2009, OpenOCD does not support SWD. # # Port B of the FT2232 chip is normally used as a serial link to the # Stellaris chip. On most boards (but not older LM3S811 eval boards), # when SWD is used Port B may instead be used to read low-bandwidth # "SWO trace" data, including so-called "printf style" output from # firmware via the ITM module as well as profile data. # interface ft2232 ft2232_device_desc "Stellaris Evaluation Board" ft2232_layout luminary_icdi ft2232_vid_pid 0x0403 0xbcd9 openocd-0.9.0/tcl/interface/chameleon.cfg0000644000175000017500000000016312526202246015227 00000000000000# # Amontec Chameleon POD # # http://www.amontec.com/chameleon.shtml # interface parport parport_cable chameleon openocd-0.9.0/tcl/interface/olimex-arm-usb-ocd.cfg0000644000175000017500000000027312526202246016702 00000000000000# # Olimex ARM-USB-OCD # # http://www.olimex.com/dev/arm-usb-ocd.html # interface ft2232 ft2232_device_desc "Olimex OpenOCD JTAG" ft2232_layout olimex-jtag ft2232_vid_pid 0x15ba 0x0003 openocd-0.9.0/tcl/interface/olimex-jtag-tiny.cfg0000644000175000017500000000030212526202246016470 00000000000000# # Olimex ARM-USB-TINY # # http://www.olimex.com/dev/arm-usb-tiny.html # interface ft2232 ft2232_device_desc "Olimex OpenOCD JTAG TINY" ft2232_layout olimex-jtag ft2232_vid_pid 0x15ba 0x0004 openocd-0.9.0/tcl/interface/turtelizer2.cfg0000644000175000017500000000061112526202246015565 00000000000000# # egnite Turtelizer 2 # # http://www.ethernut.de/en/hardware/turtelizer/index.html # # Deprecated, if possible use tcl/interface/ftdi/turtelizer... # To run, one of following configure option needed # --enable-legacy-ft2232_libftdi # --enable-legacy-ft2232_ftd2xx interface ft2232 ft2232_device_desc "Turtelizer JTAG/RS232 Adapter" ft2232_layout turtelizer2 ft2232_vid_pid 0x0403 0xbdc8 openocd-0.9.0/tcl/interface/flashlink.cfg0000644000175000017500000000051312526202246015246 00000000000000# # ST FlashLINK JTAG parallel cable # # http://www.st.com/internet/evalboard/product/94023.jsp # http://www.st.com/stonline/products/literature/um/7889.pdf # if { [info exists PARPORTADDR] } { set _PARPORTADDR $PARPORTADDR } else { set _PARPORTADDR 0 } interface parport parport_port $_PARPORTADDR parport_cable flashlink openocd-0.9.0/tcl/interface/kt-link.cfg0000644000175000017500000000022312526202246014642 00000000000000# # Kristech KT-Link # # http://www.kristech.eu # interface ft2232 ft2232_device_desc "KT-LINK" ft2232_layout ktlink ft2232_vid_pid 0x0403 0xBBE2 openocd-0.9.0/tcl/interface/buspirate.cfg0000644000175000017500000000100512526202246015266 00000000000000# # Buspirate with OpenOCD support # # http://dangerousprototypes.com/bus-pirate-manual/ # interface buspirate # you need to specify port on which BP lives #buspirate_port /dev/ttyUSB0 # communication speed setting buspirate_speed normal ;# or fast # voltage regulator Enabled = 1 Disabled = 0 #buspirate_vreg 0 # pin mode normal or open-drain #buspirate_mode normal # pullup state Enabled = 1 Disabled = 0 #buspirate_pullup 0 # this depends on the cable, you are safe with this option reset_config srst_only openocd-0.9.0/tcl/interface/flossjtag-noeeprom.cfg0000644000175000017500000000100612526202246017107 00000000000000# # FlossJTAG # # http://github.com/esden/floss-jtag # # This is the pre v0.3 Floss-JTAG compatible config file. It can also be used # for newer versions of Floss-JTAG with empty or not populated EEPROM. If you # have several Floss-JTAG connected you have to use the USB ID to select a # specific one. # # If you have a Floss-JTAG WITH EEPROM that is programmed, use the # flossjtag.cfg file. # interface ft2232 ft2232_vid_pid 0x0403 0x6010 ft2232_device_desc "Dual RS232-HS" ft2232_layout "usbjtag" ft2232_latency 2 openocd-0.9.0/tcl/interface/jtag-lock-pick_tiny_2.cfg0000644000175000017500000000026212526202246017357 00000000000000# # DISTORTEC JTAG-lock-pick Tiny 2 # # http://www.distortec.com # interface ft2232 ft2232_device_desc "JTAG-lock-pick Tiny 2" ft2232_layout ktlink ft2232_vid_pid 0x0403 0x8220 openocd-0.9.0/tcl/interface/busblaster.cfg0000644000175000017500000000060012526202246015436 00000000000000# # Dangerous Prototypes - Bus Blaster # # The Bus Blaster has a configurable buffer between the FTDI FT2232H and the # JTAG header which allows it to emulate various debugger types. It comes # configured as a JTAGkey device. # # http://dangerousprototypes.com/docs/Bus_Blaster # interface ft2232 ft2232_device_desc "Dual RS232-HS" ft2232_layout jtagkey ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/arm-jtag-ew.cfg0000644000175000017500000000014012526202246015402 00000000000000# # Olimex ARM-JTAG-EW # # http://www.olimex.com/dev/arm-jtag-ew.html # interface arm-jtag-ew openocd-0.9.0/tcl/interface/estick.cfg0000644000175000017500000000011312526202246014551 00000000000000# # eStick # # http://code.google.com/p/estick-jtag/ # interface opendous openocd-0.9.0/tcl/interface/stlink-v1.cfg0000644000175000017500000000023412526202246015123 00000000000000# # STMicroelectronics ST-LINK/V1 in-circuit debugger/programmer # interface hla hla_layout stlink hla_device_desc "ST-LINK/V1" hla_vid_pid 0x0483 0x3744 openocd-0.9.0/tcl/interface/stlink-v2.cfg0000644000175000017500000000074412526202246015132 00000000000000# # STMicroelectronics ST-LINK/V2 in-circuit debugger/programmer # interface hla hla_layout stlink hla_device_desc "ST-LINK/V2" hla_vid_pid 0x0483 0x3748 # Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 # devices seem to have serial numbers with unreadable characters. ST-LINK/V2 # firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial # number reset issues. # eg. #hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" openocd-0.9.0/tcl/interface/ngxtech.cfg0000644000175000017500000000031412526202246014732 00000000000000# # NGX ARM USB JTAG # # http://shop.ngxtechnologies.com/product_info.php?cPath=26&products_id=30 # interface ft2232 ft2232_device_desc "NGX JTAG A" ft2232_vid_pid 0x0403 0x6010 ft2232_layout "oocdlink" openocd-0.9.0/tcl/interface/stlink-v2-1.cfg0000644000175000017500000000075012526202246015265 00000000000000# # STMicroelectronics ST-LINK/V2-1 in-circuit debugger/programmer # interface hla hla_layout stlink hla_device_desc "ST-LINK/V2-1" hla_vid_pid 0x0483 0x374b # Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 # devices seem to have serial numbers with unreadable characters. ST-LINK/V2 # firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial # number reset issues. # eg. #hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" openocd-0.9.0/tcl/interface/rlink.cfg0000644000175000017500000000023312526202246014411 00000000000000# # Raisonance RLink # # http://www.mcu-raisonance.com/~rlink-debugger-programmer__microcontrollers__tool~tool__T018:4cn9ziz4bnx6.html # interface rlink openocd-0.9.0/tcl/interface/dummy.cfg0000644000175000017500000000007712526202246014433 00000000000000# # Dummy interface (for testing purposes) # interface dummy openocd-0.9.0/tcl/interface/redbee-usb.cfg0000644000175000017500000000041412526202246015310 00000000000000# # Redwire Redbee-USB # # http://www.redwirellc.com # # The Redbee-USB has an onboard FT2232H with: # - FT2232H channel B wired to mc13224v JTAG # - FT2232H channel A wired to mc13224v UART1 # interface ft2232 ft2232_layout redbee-usb ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/stm32-stick.cfg0000644000175000017500000000030212526202246015352 00000000000000# # Hitex STM32-PerformanceStick # # http://www.hitex.com/index.php?id=340 # interface ft2232 ft2232_device_desc "STM32-PerformanceStick" ft2232_layout stm32stick ft2232_vid_pid 0x0640 0x002d openocd-0.9.0/tcl/interface/signalyzer-lite.cfg0000644000175000017500000000027012526202246016415 00000000000000# # Xverve Signalyzer LITE (DT-USB-SLITE) # # http://www.signalyzer.com # interface ft2232 ft2232_device_desc "Signalyzer LITE" ft2232_layout signalyzer ft2232_vid_pid 0x0403 0xbca1 openocd-0.9.0/tcl/interface/signalyzer-h2.cfg0000644000175000017500000000026412526202246015774 00000000000000# # Xverve Signalyzer H2 (DT-USB-SH2) # # http://www.signalyzer.com # interface ft2232 ft2232_device_desc "Signalyzer H2" ft2232_layout signalyzer-h ft2232_vid_pid 0x0403 0xbca2 openocd-0.9.0/tcl/interface/signalyzer-h4.cfg0000644000175000017500000000026412526202246015776 00000000000000# # Xverve Signalyzer H4 (DT-USB-SH4) # # http://www.signalyzer.com # interface ft2232 ft2232_device_desc "Signalyzer H4" ft2232_layout signalyzer-h ft2232_vid_pid 0x0403 0xbca4 openocd-0.9.0/tcl/interface/luminary-lm3s811.cfg0000644000175000017500000000110012526202246016232 00000000000000# # Luminary Micro Stellaris LM3S811 Evaluation Kit # # http://www.luminarymicro.com/products/stellaris_811_evaluation_kits.html # # NOTE: this is only for boards *before* Rev C, which adds support # for SWO tracing with ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN signals. # The "evb_lm3s811" layout doesn't set up those signals. # # Rev C boards work more like the other Stellaris eval boards. They # need to use the "luminary_icdi" layout to work correctly. # interface ft2232 ft2232_device_desc "LM3S811 Evaluation Board" ft2232_layout evb_lm3s811 ft2232_vid_pid 0x0403 0xbcd9 openocd-0.9.0/tcl/interface/usbprog.cfg0000644000175000017500000000033512526202246014756 00000000000000# # Embedded Projects USBprog # # http://embedded-projects.net/index.php?page_id=135 # interface usbprog # USBprog is broken w/short TMS sequences, this is a workaround # until the C code can be fixed. tms_sequence long openocd-0.9.0/tcl/interface/sheevaplug.cfg0000644000175000017500000000041612526202246015440 00000000000000# # Marvel SheevaPlug Development Kit # # http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp # interface ft2232 ft2232_layout sheevaplug ft2232_vid_pid 0x9e88 0x9e8f ft2232_device_desc "SheevaPlug JTAGKey FT2232D B" adapter_khz 2000 openocd-0.9.0/tcl/interface/flyswatter2.cfg0000644000175000017500000000030612526202246015561 00000000000000# # TinCanTools Flyswatter 2 # # http://www.tincantools.com/product.php?productid=16153 # interface ft2232 ft2232_device_desc "Flyswatter2" ft2232_layout "flyswatter2" ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/xds100v2.cfg0000644000175000017500000000034612526202246014566 00000000000000# # Texas Instruments XDS100v2 # # http://processors.wiki.ti.com/index.php/XDS100#XDS100v2_Features # interface ft2232 ft2232_device_desc "Texas Instruments Inc.XDS100 Ver 2.0" ft2232_layout xds100v2 ft2232_vid_pid 0x0403 0xa6d0 openocd-0.9.0/tcl/interface/digilent-hs1.cfg0000644000175000017500000000071212526202246015564 00000000000000# # Digilent HS1 # # The Digilent HS1 is a high-speed FT2232H-based adapter, compliant with the # Xilinx JTAG 14-pin pinout. # It does not support ARM reset signals (SRST and TRST) but can still be used for # hardware debugging, with some limitations. # # http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,395,922&Prod=JTAG-HS1 # interface ft2232 ft2232_device_desc "Digilent Adept USB Device" ft2232_layout digilent-hs1 ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/sysfsgpio-raspberrypi.cfg0000644000175000017500000000105212526202246017660 00000000000000# # Config for using RaspberryPi's expansion header # # This is best used with a fast enough buffer but also # is suitable for direct connection if the target voltage # matches RPi's 3.3V # # Do not forget the GND connection, pin 6 of the expansion header. # interface sysfsgpio # Each of the JTAG lines need a gpio number set: tck tms tdi tdo # Header pin numbers: 23 22 19 21 sysfsgpio_jtag_nums 11 25 10 9 # At least one of srst or trst needs to be specified # Header pin numbers: TRST - 26, SRST - 18 sysfsgpio_trst_num 7 # sysfsgpio_srst_num 24 openocd-0.9.0/tcl/interface/vpaclink.cfg0000644000175000017500000000023612526202246015104 00000000000000# # Voipac VPACLink # # http://voipac.com/27M-JTG-000 # interface ft2232 ft2232_device_desc "VPACLink A" ft2232_layout oocdlink ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/jtagkey2p.cfg0000644000175000017500000000026112526202246015173 00000000000000# # Amontec JTAGkey2P # # http://www.amontec.com/jtagkey2p.shtml # interface ft2232 ft2232_device_desc "Amontec JTAGkey-2P" ft2232_layout jtagkey ft2232_vid_pid 0x0403 0xCFF8 openocd-0.9.0/tcl/interface/jtagkey-tiny.cfg0000644000175000017500000000025712526202246015717 00000000000000# # Amontec JTAGkey-tiny # # http://www.amontec.com/jtagkey-tiny.shtml # # The JTAGkey-tiny uses exactly the same config as the JTAGkey. source [find interface/jtagkey.cfg] openocd-0.9.0/tcl/interface/cortino.cfg0000644000175000017500000000024512526202246014752 00000000000000# # Hitex Cortino # # http://www.hitex.com/index.php?id=cortino # interface ft2232 ft2232_device_desc "Cortino" ft2232_layout cortino ft2232_vid_pid 0x0640 0x0032 openocd-0.9.0/tcl/interface/cmsis-dap.cfg0000644000175000017500000000033212526202246015152 00000000000000# # ARM CMSIS-DAP compliant adapter # # http://www.keil.com/support/man/docs/dapdebug/ # interface cmsis-dap # Optionally specify the serial number of CMSIS-DAP usb device. #cmsis_dap_serial 02200201E6661E601B98E3B9 openocd-0.9.0/tcl/interface/hilscher_nxhx50_re.cfg0000644000175000017500000000034512526202246016777 00000000000000# # Hilscher NXHX 50-RE # # http://de.hilscher.com/products_details_hardware.html?p_id=P_483c0f582ad36&bs=20 # interface ft2232 ft2232_device_desc "NXHX50-RE" ft2232_layout comstick ft2232_vid_pid 0x0640 0x0028 adapter_khz 6000 openocd-0.9.0/tcl/interface/flyswatter.cfg0000644000175000017500000000030212526202246015473 00000000000000# # TinCanTools Flyswatter # # http://www.tincantools.com/product.php?productid=16134 # interface ft2232 ft2232_device_desc "Flyswatter" ft2232_layout "flyswatter" ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/neodb.cfg0000644000175000017500000000031112526202246014356 00000000000000# # Openmoko USB JTAG/RS232 adapter # # http://wiki.openmoko.org/wiki/Debug_Board_v3 # interface ft2232 ft2232_device_desc "Debug Board for Neo1973" ft2232_layout jtagkey ft2232_vid_pid 0x1457 0x5118 openocd-0.9.0/tcl/interface/jtagkey.cfg0000644000175000017500000000025212526202246014731 00000000000000# # Amontec JTAGkey # # http://www.amontec.com/jtagkey.shtml # interface ft2232 ft2232_device_desc "Amontec JTAGkey" ft2232_layout jtagkey ft2232_vid_pid 0x0403 0xcff8 openocd-0.9.0/tcl/interface/opendous_ftdi.cfg0000644000175000017500000000045612526202246016143 00000000000000# # Opendous # # http://code.google.com/p/opendous/wiki/JTAG # # According to the website, it is similar to jtagkey, but it uses channel B # (and it has a different pid number). # interface ft2232 ft2232_device_desc "Dual RS232-HS" ft2232_layout jtagkey ft2232_vid_pid 0x0403 0x6010 ft2232_channel 2 openocd-0.9.0/tcl/interface/hilscher_nxhx500_re.cfg0000644000175000017500000000035012526202246017053 00000000000000# # Hilscher NXHX 500-RE # # http://de.hilscher.com/products_details_hardware.html?p_id=P_461ff2053bad1&bs=20 # interface ft2232 ft2232_device_desc "NXHX 500-RE" ft2232_layout comstick ft2232_vid_pid 0x0640 0x0028 adapter_khz 6000 openocd-0.9.0/tcl/interface/altera-usb-blaster2.cfg0000644000175000017500000000027612526202246017054 00000000000000# # Altera USB-Blaster II # interface usb_blaster usb_blaster_vid_pid 0x09fb 0x6010 0x09fb 0x6810 usb_blaster_lowlevel_driver ublast2 usb_blaster_firmware /path/to/quartus/blaster_6810.hex openocd-0.9.0/tcl/interface/hilscher_nxhx500_etm.cfg0000644000175000017500000000034412526202246017235 00000000000000# # Hilscher NXHX 500-ETM # # http://de.hilscher.com/files_design/8/NXHX500-ETM_description_Rev01_EN.pdf # interface ft2232 ft2232_device_desc "NXHX 500-ETM" ft2232_layout comstick ft2232_vid_pid 0x0640 0x0028 adapter_khz 6000 openocd-0.9.0/tcl/interface/nds32-aice.cfg0000644000175000017500000000040212526202246015120 00000000000000# # Andes AICE # # http://www.andestech.com # interface aice aice desc "Andes AICE adapter" aice serial "C001-42163" aice vid_pid 0x1CFC 0x0000 aice port aice_usb reset_config trst_and_srst adapter_khz 24000 aice retry_times 50 aice count_to_check_dbger 30 openocd-0.9.0/tcl/interface/dlp-usb1232h.cfg0000644000175000017500000000051012526202246015316 00000000000000# # DLP Design DLP-USB1232H USB-to-UART/FIFO interface module # # http://www.dlpdesign.com/usb/usb1232h.shtml # # Schematics for OpenOCD usage: # http://randomprojects.org/wiki/DLP-USB1232H_and_OpenOCD_based_JTAG_adapter # interface ft2232 ft2232_device_desc "Dual RS232-HS" ft2232_layout usbjtag ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/opendous.cfg0000644000175000017500000000012412526202246015125 00000000000000# # opendous-jtag # # http://code.google.com/p/opendous-jtag/ # interface opendous openocd-0.9.0/tcl/interface/calao-usb-a9260.cfg0000644000175000017500000000030312526202246015675 00000000000000# # CALAO Systems USB-A9260 common -C01 -C02 setup # # http://www.calao-systems.com/ # # See calao-usb-a9260-c01.cfg and calao-usb-a9260-c02.cfg. # adapter_nsrst_delay 200 jtag_ntrst_delay 200 openocd-0.9.0/tcl/interface/osbdm.cfg0000644000175000017500000000016212526202246014377 00000000000000# # P&E Micro OSBDM (aka OSJTAG) interface # # http://pemicro.com/osbdm/ # interface osbdm reset_config srst_only openocd-0.9.0/tcl/interface/oocdlink.cfg0000644000175000017500000000031712526202246015077 00000000000000# # Joern Kaipf's OOCDLink # # http://www.joernonline.de/contrexx2/cms/index.php?page=126 # interface ft2232 ft2232_device_desc "OOCDLink" ft2232_layout oocdlink ft2232_vid_pid 0x0403 0xbaf8 adapter_khz 5 openocd-0.9.0/tcl/interface/jlink.cfg0000644000175000017500000000055112526202246014404 00000000000000# # Segger J-Link # # http://www.segger.com/jlink.html # interface jlink # The serial number can be used to select a specific interface in case more than one # is connected to the host. # # Segger software omits leading zeros in serial number displays, # OpenOCD requires them. # # Example: Select J-Link with serial 123456789 # # jlink serial 000123456789 openocd-0.9.0/tcl/interface/openjtag.cfg0000644000175000017500000000014012526202246015076 00000000000000# # OpenJTAG # # www.openjtag.org # interface openjtag openjtag_device_desc "Open JTAG Project"openocd-0.9.0/tcl/interface/redbee-econotag.cfg0000644000175000017500000000045012526202246016316 00000000000000# # Redwire Redbee-Econotag # # http://www.redwirellc.com/store/node/1 # # The Redbee-Econotag has an onboard FT2232H with: # - FT2232H channel A wired to mc13224v JTAG # - FT2232H channel B wired to mc13224v UART1 # interface ft2232 ft2232_layout redbee-econotag ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/altera-usb-blaster.cfg0000644000175000017500000000032712526202246016767 00000000000000# # Altera USB-Blaster # # http://www.altera.com/literature/ug/ug_usb_blstr.pdf # interface usb_blaster # These are already the defaults. # usb_blaster_vid_pid 0x09FB 0x6001 # usb_blaster_device_desc "USB-Blaster" openocd-0.9.0/tcl/interface/signalyzer.cfg0000644000175000017500000000026012526202246015461 00000000000000# # Xverve Signalyzer Tool (DT-USB-ST) # # http://www.signalyzer.com # interface ft2232 ft2232_device_desc "Signalyzer" ft2232_layout signalyzer ft2232_vid_pid 0x0403 0xbca0 openocd-0.9.0/tcl/interface/olimex-arm-usb-ocd-h.cfg0000644000175000017500000000031312526202246017122 00000000000000# # Olimex ARM-USB-OCD-H # # http://www.olimex.com/dev/arm-usb-ocd.html # interface ft2232 ft2232_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H" ft2232_layout olimex-jtag ft2232_vid_pid 0x15ba 0x002b openocd-0.9.0/tcl/interface/lisa-l.cfg0000644000175000017500000000024712526202246014460 00000000000000# # Lisa/L # # http://paparazzi.enac.fr/wiki/Lisa # interface ft2232 ft2232_vid_pid 0x0403 0x6010 ft2232_device_desc "Lisa/L" ft2232_layout "lisa-l" ft2232_latency 2 openocd-0.9.0/tcl/interface/hilscher_nxhx50_etm.cfg0000644000175000017500000000034112526202246017152 00000000000000# # Hilscher NXHX 50-ETM # # http://de.hilscher.com/files_design/8/NXHX50-ETM_description_Rev01_EN.pdf # interface ft2232 ft2232_device_desc "NXHX 50-ETM" ft2232_layout comstick ft2232_vid_pid 0x0640 0x0028 adapter_khz 6000 openocd-0.9.0/tcl/interface/luminary-icdi.cfg0000644000175000017500000000146412526202246016047 00000000000000# # Luminary Micro Stellaris LM3S9B9x Evaluation Kits # In-Circuit Debug Interface (ICDI) Board # # Essentially all Luminary debug hardware is the same, (with both # JTAG and SWD support compatible with ICDI boards. This ICDI adapter # configuration is JTAG-only, but the same hardware handles SWD too. # # This is a discrete FT2232 based debug board which supports ARM's # JTAG/SWD connectors in both backwards-compatible 20-pin format and # in the new-style compact 10-pin. There's also an 8-pin connector # with serial port support. It's included with LM3S9B9x eval boards. # # http://www.luminarymicro.com/products/ek-lm3s9b90.html # http://www.luminarymicro.com/products/ek-lm3s9b92.html # interface ft2232 ft2232_device_desc "Luminary Micro ICDI Board" ft2232_layout luminary_icdi ft2232_vid_pid 0x0403 0xbcda openocd-0.9.0/tcl/interface/raspberrypi-native.cfg0000644000175000017500000000166712526202246017134 00000000000000# # Config for using Raspberry Pi's expansion header # # This is best used with a fast enough buffer but also # is suitable for direct connection if the target voltage # matches RPi's 3.3V and the cable is short enough. # # Do not forget the GND connection, pin 6 of the expansion header. # interface bcm2835gpio # Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET # These depend on system clock, calibrated for stock 700MHz # bcm2835gpio_speed SPEED_COEFF SPEED_OFFSET bcm2835gpio_speed_coeffs 113714 28 # Each of the JTAG lines need a gpio number set: tck tms tdi tdo # Header pin numbers: 23 22 19 21 bcm2835gpio_jtag_nums 11 25 10 9 # If you define trst or srst, use appropriate reset_config # Header pin numbers: TRST - 26, SRST - 18 # bcm2835gpio_trst_num 7 # reset_config trst_only # bcm2835gpio_srst_num 24 # reset_config srst_only srst_push_pull # or if you have both connected, # reset_config trst_and_srst srst_push_pull openocd-0.9.0/tcl/interface/hilscher_nxhx10_etm.cfg0000644000175000017500000000034212526202246017147 00000000000000# # Hilscher NXHX 10-ETM # # http://de.hilscher.com/products_details_hardware.html?p_id=P_4ce145a5983e6 # interface ft2232 ft2232_device_desc "NXHX 10-ETM" ft2232_layout comstick ft2232_vid_pid 0x0640 0x0028 adapter_khz 6000 openocd-0.9.0/tcl/interface/jtagkey2.cfg0000644000175000017500000000025612526202246015017 00000000000000# # Amontec JTAGkey2 # # http://www.amontec.com/jtagkey2.shtml # interface ft2232 ft2232_device_desc "Amontec JTAGkey-2" ft2232_layout jtagkey ft2232_vid_pid 0x0403 0xCFF8 openocd-0.9.0/tcl/interface/axm0432.cfg0000644000175000017500000000024212526202246014370 00000000000000# # Axiom axm0432 # # http://www.axman.com # interface ft2232 ft2232_device_desc "Symphony SoundBite" ft2232_layout "axm0432_jtag" ft2232_vid_pid 0x0403 0x6010 openocd-0.9.0/tcl/interface/openocd-usb.cfg0000644000175000017500000000033212526202246015510 00000000000000# # Hubert Hoegl's USB to JTAG # # http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html # interface ft2232 ft2232_vid_pid 0x0403 0x6010 ft2232_device_desc "Dual RS232" ft2232_layout "oocdlink" ft2232_latency 2 openocd-0.9.0/tcl/interface/olimex-arm-usb-tiny-h.cfg0000644000175000017500000000032012526202246017336 00000000000000# # Olimex ARM-USB-TINY-H # # http://www.olimex.com/dev/arm-usb-tiny-h.html # interface ft2232 ft2232_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" ft2232_layout olimex-jtag ft2232_vid_pid 0x15ba 0x002a openocd-0.9.0/tcl/interface/icebear.cfg0000644000175000017500000000024612526202246014670 00000000000000# # Section5 ICEBear # # http://section5.ch/icebear # interface ft2232 ft2232_device_desc "ICEbear JTAG adapter" ft2232_layout icebear ft2232_vid_pid 0x0403 0xc140 openocd-0.9.0/tcl/interface/calao-usb-a9260-c01.cfg0000644000175000017500000000036312526202246016264 00000000000000# # CALAO Systems USB-A9260-C01 # # http://www.calao-systems.com/ # interface ft2232 ft2232_layout jtagkey ft2232_device_desc "USB-A9260" ft2232_vid_pid 0x0403 0x6010 script interface/calao-usb-a9260.cfg script target/at91sam9260minimal.cfg openocd-0.9.0/tcl/interface/calao-usb-a9260-c02.cfg0000644000175000017500000000036312526202246016265 00000000000000# # CALAO Systems USB-A9260-C02 # # http://www.calao-systems.com/ # interface ft2232 ft2232_layout jtagkey ft2232_device_desc "USB-A9260" ft2232_vid_pid 0x0403 0x6001 script interface/calao-usb-a9260.cfg script target/at91sam9260minimal.cfg openocd-0.9.0/tcl/interface/openrd.cfg0000644000175000017500000000036312526202246014565 00000000000000# # Marvell OpenRD # # http://www.marvell.com/products/embedded_processors/developer/kirkwood/openrd.jsp # interface ft2232 ft2232_layout sheevaplug ft2232_vid_pid 0x0403 0x9e90 ft2232_device_desc "OpenRD JTAGKey FT2232D B" adapter_khz 3000 openocd-0.9.0/src/0000755000175000017500000000000012526202226010736 500000000000000openocd-0.9.0/src/pld/0000755000175000017500000000000012526202226011515 500000000000000openocd-0.9.0/src/pld/xilinx_bit.c0000644000175000017500000001036712315575361013772 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xilinx_bit.h" #include "pld.h" #include #include static int read_section(FILE *input_file, int length_size, char section, uint32_t *buffer_length, uint8_t **buffer) { uint8_t length_buffer[4]; int length; char section_char; int read_count; if ((length_size != 2) && (length_size != 4)) { LOG_ERROR("BUG: length_size neither 2 nor 4"); return ERROR_PLD_FILE_LOAD_FAILED; } read_count = fread(§ion_char, 1, 1, input_file); if (read_count != 1) return ERROR_PLD_FILE_LOAD_FAILED; if (section_char != section) return ERROR_PLD_FILE_LOAD_FAILED; read_count = fread(length_buffer, 1, length_size, input_file); if (read_count != length_size) return ERROR_PLD_FILE_LOAD_FAILED; if (length_size == 4) length = be_to_h_u32(length_buffer); else /* (length_size == 2) */ length = be_to_h_u16(length_buffer); if (buffer_length) *buffer_length = length; *buffer = malloc(length); read_count = fread(*buffer, 1, length, input_file); if (read_count != length) return ERROR_PLD_FILE_LOAD_FAILED; return ERROR_OK; } int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename) { FILE *input_file; struct stat input_stat; int read_count; if (!filename || !bit_file) return ERROR_COMMAND_SYNTAX_ERROR; if (stat(filename, &input_stat) == -1) { LOG_ERROR("couldn't stat() %s: %s", filename, strerror(errno)); return ERROR_PLD_FILE_LOAD_FAILED; } if (S_ISDIR(input_stat.st_mode)) { LOG_ERROR("%s is a directory", filename); return ERROR_PLD_FILE_LOAD_FAILED; } if (input_stat.st_size == 0) { LOG_ERROR("Empty file %s", filename); return ERROR_PLD_FILE_LOAD_FAILED; } input_file = fopen(filename, "rb"); if (input_file == NULL) { LOG_ERROR("couldn't open %s: %s", filename, strerror(errno)); return ERROR_PLD_FILE_LOAD_FAILED; } read_count = fread(bit_file->unknown_header, 1, 13, input_file); if (read_count != 13) { LOG_ERROR("couldn't read unknown_header from file '%s'", filename); return ERROR_PLD_FILE_LOAD_FAILED; } if (read_section(input_file, 2, 'a', NULL, &bit_file->source_file) != ERROR_OK) return ERROR_PLD_FILE_LOAD_FAILED; if (read_section(input_file, 2, 'b', NULL, &bit_file->part_name) != ERROR_OK) return ERROR_PLD_FILE_LOAD_FAILED; if (read_section(input_file, 2, 'c', NULL, &bit_file->date) != ERROR_OK) return ERROR_PLD_FILE_LOAD_FAILED; if (read_section(input_file, 2, 'd', NULL, &bit_file->time) != ERROR_OK) return ERROR_PLD_FILE_LOAD_FAILED; if (read_section(input_file, 4, 'e', &bit_file->length, &bit_file->data) != ERROR_OK) return ERROR_PLD_FILE_LOAD_FAILED; LOG_DEBUG("bit_file: %s %s %s,%s %" PRIi32 "", bit_file->source_file, bit_file->part_name, bit_file->date, bit_file->time, bit_file->length); fclose(input_file); return ERROR_OK; } openocd-0.9.0/src/pld/xilinx_bit.h0000644000175000017500000000337112315575361013774 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef XILINX_BIT_H #define XILINX_BIT_H struct xilinx_bit_file { uint8_t unknown_header[13]; uint8_t *source_file; uint8_t *part_name; uint8_t *date; uint8_t *time; uint32_t length; uint8_t *data; }; int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename); #endif /* XILINX_BIT_H */ openocd-0.9.0/src/pld/pld.c0000644000175000017500000001401712315575361012374 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pld.h" #include #include /* pld drivers */ extern struct pld_driver virtex2_pld; static struct pld_driver *pld_drivers[] = { &virtex2_pld, NULL, }; static struct pld_device *pld_devices; struct pld_device *get_pld_device_by_num(int num) { struct pld_device *p; int i = 0; for (p = pld_devices; p; p = p->next) { if (i++ == num) return p; } return NULL; } /* pld device [driver_options ...] */ COMMAND_HANDLER(handle_pld_device_command) { int i; int found = 0; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; for (i = 0; pld_drivers[i]; i++) { if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) { struct pld_device *p, *c; /* register pld specific commands */ int retval; if (pld_drivers[i]->commands) { retval = register_commands(CMD_CTX, NULL, pld_drivers[i]->commands); if (ERROR_OK != retval) { LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]); return ERROR_FAIL; } } c = malloc(sizeof(struct pld_device)); c->driver = pld_drivers[i]; c->next = NULL; retval = CALL_COMMAND_HANDLER( pld_drivers[i]->pld_device_command, c); if (ERROR_OK != retval) { LOG_ERROR("'%s' driver rejected pld device", CMD_ARGV[0]); free(c); return ERROR_OK; } /* put pld device in linked list */ if (pld_devices) { /* find last pld device */ for (p = pld_devices; p && p->next; p = p->next) ; if (p) p->next = c; } else pld_devices = c; found = 1; } } /* no matching pld driver found */ if (!found) { LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]); exit(-1); } return ERROR_OK; } COMMAND_HANDLER(handle_pld_devices_command) { struct pld_device *p; int i = 0; if (!pld_devices) { command_print(CMD_CTX, "no pld devices configured"); return ERROR_OK; } for (p = pld_devices; p; p = p->next) command_print(CMD_CTX, "#%i: %s", i++, p->driver->name); return ERROR_OK; } COMMAND_HANDLER(handle_pld_load_command) { int retval; struct timeval start, end, duration; struct pld_device *p; gettimeofday(&start, NULL); if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; unsigned dev_id; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id); p = get_pld_device_by_num(dev_id); if (!p) { command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]); return ERROR_OK; } retval = p->driver->load(p, CMD_ARGV[1]); if (retval != ERROR_OK) { command_print(CMD_CTX, "failed loading file %s to pld device %u", CMD_ARGV[1], dev_id); switch (retval) { } return retval; } else { gettimeofday(&end, NULL); timeval_subtract(&duration, &end, &start); command_print(CMD_CTX, "loaded file %s to pld device %u in %jis %jius", CMD_ARGV[1], dev_id, (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec); } return ERROR_OK; } static const struct command_registration pld_exec_command_handlers[] = { { .name = "devices", .handler = handle_pld_devices_command, .mode = COMMAND_EXEC, .help = "list configured pld devices", }, { .name = "load", .handler = handle_pld_load_command, .mode = COMMAND_EXEC, .help = "load configuration file into PLD", .usage = "pld_num filename", }, COMMAND_REGISTRATION_DONE }; static int pld_init(struct command_context *cmd_ctx) { if (!pld_devices) return ERROR_OK; struct command *parent = command_find_in_context(cmd_ctx, "pld"); return register_commands(cmd_ctx, parent, pld_exec_command_handlers); } COMMAND_HANDLER(handle_pld_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool pld_initialized; if (pld_initialized) { LOG_INFO("'pld init' has already been called"); return ERROR_OK; } pld_initialized = true; LOG_DEBUG("Initializing PLDs..."); return pld_init(CMD_CTX); } static const struct command_registration pld_config_command_handlers[] = { { .name = "device", .mode = COMMAND_CONFIG, .handler = handle_pld_device_command, .help = "configure a PLD device", .usage = "driver_name [driver_args ... ]", }, { .name = "init", .mode = COMMAND_CONFIG, .handler = handle_pld_init_command, .help = "initialize PLD devices", .usage = "" }, COMMAND_REGISTRATION_DONE }; static const struct command_registration pld_command_handler[] = { { .name = "pld", .mode = COMMAND_ANY, .help = "programmable logic device commands", .usage = "", .chain = pld_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; int pld_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, pld_command_handler); } openocd-0.9.0/src/pld/pld.h0000644000175000017500000000427312315575361012404 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef PLD_H #define PLD_H #include struct pld_device; #define __PLD_DEVICE_COMMAND(name) \ COMMAND_HELPER(name, struct pld_device *pld) struct pld_driver { const char *name; __PLD_DEVICE_COMMAND((*pld_device_command)); const struct command_registration *commands; int (*load)(struct pld_device *pld_device, const char *filename); }; #define PLD_DEVICE_COMMAND_HANDLER(name) \ static __PLD_DEVICE_COMMAND(name) struct pld_device { struct pld_driver *driver; void *driver_priv; struct pld_device *next; }; int pld_register_commands(struct command_context *cmd_ctx); struct pld_device *get_pld_device_by_num(int num); #define ERROR_PLD_DEVICE_INVALID (-1000) #define ERROR_PLD_FILE_LOAD_FAILED (-1001) #endif /* PLD_H */ openocd-0.9.0/src/pld/virtex2.c0000644000175000017500000001524012315575361013217 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "virtex2.h" #include "xilinx_bit.h" #include "pld.h" static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr) { if (tap == NULL) return ERROR_FAIL; if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { struct scan_field field; field.num_bits = tap->ir_length; void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); free(t); } return ERROR_OK; } static int virtex2_send_32(struct pld_device *pld_device, int num_words, uint32_t *words) { struct virtex2_pld_device *virtex2_info = pld_device->driver_priv; struct scan_field scan_field; uint8_t *values; int i; values = malloc(num_words * 4); scan_field.num_bits = num_words * 32; scan_field.out_value = values; scan_field.in_value = NULL; for (i = 0; i < num_words; i++) buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32)); virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */ jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE); free(values); return ERROR_OK; } static inline void virtexflip32(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32); } static int virtex2_receive_32(struct pld_device *pld_device, int num_words, uint32_t *words) { struct virtex2_pld_device *virtex2_info = pld_device->driver_priv; struct scan_field scan_field; scan_field.num_bits = 32; scan_field.out_value = NULL; scan_field.in_value = NULL; virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */ while (num_words--) { scan_field.in_value = (uint8_t *)words; jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE); jtag_add_callback(virtexflip32, (jtag_callback_data_t)words); words++; } return ERROR_OK; } static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status) { uint32_t data[5]; jtag_add_tlr(); data[0] = 0xaa995566; /* synch word */ data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */ data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */ data[3] = 0x20000000; /* NOOP */ data[4] = 0x20000000; /* NOOP */ virtex2_send_32(pld_device, 5, data); virtex2_receive_32(pld_device, 1, status); jtag_execute_queue(); LOG_DEBUG("status: 0x%8.8" PRIx32 "", *status); return ERROR_OK; } static int virtex2_load(struct pld_device *pld_device, const char *filename) { struct virtex2_pld_device *virtex2_info = pld_device->driver_priv; struct xilinx_bit_file bit_file; int retval; unsigned int i; struct scan_field field; field.in_value = NULL; retval = xilinx_read_bit_file(&bit_file, filename); if (retval != ERROR_OK) return retval; virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */ jtag_execute_queue(); jtag_add_sleep(1000); virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */ jtag_execute_queue(); for (i = 0; i < bit_file.length; i++) bit_file.data[i] = flip_u32(bit_file.data[i], 8); field.num_bits = bit_file.length * 8; field.out_value = bit_file.data; jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE); jtag_execute_queue(); jtag_add_tlr(); virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ jtag_add_runtest(13, TAP_IDLE); virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ jtag_add_runtest(13, TAP_IDLE); virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ jtag_execute_queue(); return ERROR_OK; } COMMAND_HANDLER(virtex2_handle_read_stat_command) { struct pld_device *device; uint32_t status; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; unsigned dev_id; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id); device = get_pld_device_by_num(dev_id); if (!device) { command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]); return ERROR_OK; } virtex2_read_stat(device, &status); command_print(CMD_CTX, "virtex2 status register: 0x%8.8" PRIx32 "", status); return ERROR_OK; } PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command) { struct jtag_tap *tap; struct virtex2_pld_device *virtex2_info; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; tap = jtag_tap_by_string(CMD_ARGV[1]); if (tap == NULL) { command_print(CMD_CTX, "Tap: %s does not exist", CMD_ARGV[1]); return ERROR_OK; } virtex2_info = malloc(sizeof(struct virtex2_pld_device)); virtex2_info->tap = tap; pld->driver_priv = virtex2_info; return ERROR_OK; } static const struct command_registration virtex2_exec_command_handlers[] = { { .name = "read_stat", .mode = COMMAND_EXEC, .handler = virtex2_handle_read_stat_command, .help = "read status register", .usage = "pld_num", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration virtex2_command_handler[] = { { .name = "virtex2", .mode = COMMAND_ANY, .help = "Virtex-II specific commands", .usage = "", .chain = virtex2_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct pld_driver virtex2_pld = { .name = "virtex2", .commands = virtex2_command_handler, .pld_device_command = &virtex2_pld_device_command, .load = &virtex2_load, }; openocd-0.9.0/src/pld/virtex2.h0000644000175000017500000000310412315575361013220 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef VIRTEX2_H #define VIRTEX2_H #include struct virtex2_pld_device { struct jtag_tap *tap; }; #endif /* VIRTEX2_H */ openocd-0.9.0/src/pld/Makefile.am0000644000175000017500000000034012315575361013477 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libpld.la noinst_HEADERS = pld.h xilinx_bit.h virtex2.h libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/pld/Makefile.in0000644000175000017500000004404312526201651013510 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/pld ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpld_la_LIBADD = am_libpld_la_OBJECTS = pld.lo xilinx_bit.lo virtex2.lo libpld_la_OBJECTS = $(am_libpld_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libpld_la_SOURCES) DIST_SOURCES = $(libpld_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libpld.la noinst_HEADERS = pld.h xilinx_bit.h virtex2.h libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pld/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/pld/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libpld.la: $(libpld_la_OBJECTS) $(libpld_la_DEPENDENCIES) $(EXTRA_libpld_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpld_la_OBJECTS) $(libpld_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pld.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtex2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xilinx_bit.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/svf/0000755000175000017500000000000012526202226011534 500000000000000openocd-0.9.0/src/svf/svf.c0000644000175000017500000012544412516456303012436 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * SimonQian@SimonQian.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* The specification for SVF is available here: * http://www.asset-intertech.com/support/svf.pdf * Below, this document is refered to as the "SVF spec". * * The specification for XSVF is available here: * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf * Below, this document is refered to as the "XSVF spec". */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "svf.h" #include /* SVF command */ enum svf_command { ENDDR, ENDIR, FREQUENCY, HDR, HIR, PIO, PIOMAP, RUNTEST, SDR, SIR, STATE, TDR, TIR, TRST, }; static const char *svf_command_name[14] = { "ENDDR", "ENDIR", "FREQUENCY", "HDR", "HIR", "PIO", "PIOMAP", "RUNTEST", "SDR", "SIR", "STATE", "TDR", "TIR", "TRST" }; enum trst_mode { TRST_ON, TRST_OFF, TRST_Z, TRST_ABSENT }; static const char *svf_trst_mode_name[4] = { "ON", "OFF", "Z", "ABSENT" }; struct svf_statemove { tap_state_t from; tap_state_t to; uint32_t num_of_moves; tap_state_t paths[8]; }; /* * These paths are from the SVF specification for the STATE command, to be * used when the STATE command only includes the final state. The first * element of the path is the "from" (current) state, and the last one is * the "to" (target) state. * * All specified paths are the shortest ones in the JTAG spec, and are thus * not (!!) exact matches for the paths used elsewhere in OpenOCD. Note * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE, * which has specific effects on the various registers; they are not NOPs. * * Paths to RESET are disabled here. As elsewhere in OpenOCD, and in XSVF * and many SVF implementations, we don't want to risk missing that state. * To get to RESET, always we ignore the current state. */ static const struct svf_statemove svf_statemoves[] = { /* from to num_of_moves, paths[8] */ /* {TAP_RESET, TAP_RESET, 1, {TAP_RESET}}, */ {TAP_RESET, TAP_IDLE, 2, {TAP_RESET, TAP_IDLE} }, {TAP_RESET, TAP_DRPAUSE, 6, {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE} }, {TAP_RESET, TAP_IRPAUSE, 7, {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} }, /* {TAP_IDLE, TAP_RESET, 4, {TAP_IDLE, * TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */ {TAP_IDLE, TAP_IDLE, 1, {TAP_IDLE} }, {TAP_IDLE, TAP_DRPAUSE, 5, {TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE} }, {TAP_IDLE, TAP_IRPAUSE, 6, {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} }, /* {TAP_DRPAUSE, TAP_RESET, 6, {TAP_DRPAUSE, * TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */ {TAP_DRPAUSE, TAP_IDLE, 4, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE} }, {TAP_DRPAUSE, TAP_DRPAUSE, 7, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE} }, {TAP_DRPAUSE, TAP_IRPAUSE, 8, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} }, /* {TAP_IRPAUSE, TAP_RESET, 6, {TAP_IRPAUSE, * TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */ {TAP_IRPAUSE, TAP_IDLE, 4, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_IDLE} }, {TAP_IRPAUSE, TAP_DRPAUSE, 7, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE} }, {TAP_IRPAUSE, TAP_IRPAUSE, 8, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} } }; #define XXR_TDI (1 << 0) #define XXR_TDO (1 << 1) #define XXR_MASK (1 << 2) #define XXR_SMASK (1 << 3) struct svf_xxr_para { int len; int data_mask; uint8_t *tdi; uint8_t *tdo; uint8_t *mask; uint8_t *smask; }; struct svf_para { float frequency; tap_state_t ir_end_state; tap_state_t dr_end_state; tap_state_t runtest_run_state; tap_state_t runtest_end_state; enum trst_mode trst_mode; struct svf_xxr_para hir_para; struct svf_xxr_para hdr_para; struct svf_xxr_para tir_para; struct svf_xxr_para tdr_para; struct svf_xxr_para sir_para; struct svf_xxr_para sdr_para; }; static struct svf_para svf_para; static const struct svf_para svf_para_init = { /* frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode */ 0, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TRST_Z, /* hir_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, /* hdr_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, /* tir_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, /* tdr_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, /* sir_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, /* sdr_para */ /* {len, data_mask, tdi, tdo, mask, smask}, */ {0, 0, NULL, NULL, NULL, NULL}, }; struct svf_check_tdo_para { int line_num; /* used to record line number of the check operation */ /* so more information could be printed */ int enabled; /* check is enabled or not */ int buffer_offset; /* buffer_offset to buffers */ int bit_len; /* bit length to check */ }; #define SVF_CHECK_TDO_PARA_SIZE 1024 static struct svf_check_tdo_para *svf_check_tdo_para; static int svf_check_tdo_para_index; static int svf_read_command_from_file(FILE *fd); static int svf_check_tdo(void); static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len); static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str); static FILE *svf_fd; static char *svf_read_line; static size_t svf_read_line_size; static char *svf_command_buffer; static size_t svf_command_buffer_size; static int svf_line_number = 1; static int svf_getline(char **lineptr, size_t *n, FILE *stream); #define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024) static uint8_t *svf_tdi_buffer, *svf_tdo_buffer, *svf_mask_buffer; static int svf_buffer_index, svf_buffer_size ; static int svf_quiet; static int svf_nil; static int svf_ignore_error; /* Targetting particular tap */ static int svf_tap_is_specified; static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi); /* Progress Indicator */ static int svf_progress_enabled; static long svf_total_lines; static int svf_percentage; static int svf_last_printed_percentage = -1; /* * macro is used to print the svf hex buffer at desired debug level * DEBUG, INFO, ERROR, USER */ #define SVF_BUF_LOG(_lvl, _buf, _nbits, _desc) \ svf_hexbuf_print(LOG_LVL_##_lvl , __FILE__, __LINE__, __func__, _buf, _nbits, _desc) static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned line, const char *function, const uint8_t *buf, int bit_len, const char *desc) { int j, len = 0; int byte_len = DIV_ROUND_UP(bit_len, 8); int msbits = bit_len % 8; /* allocate 2 bytes per hex digit */ char *prbuf = malloc((byte_len * 2) + 1); if (!prbuf) return; /* print correct number of bytes, mask excess bits where applicable */ uint8_t msb = buf[byte_len - 1] & (msbits ? (1 << msbits) - 1 : 0xff); len = sprintf(prbuf, msbits <= 4 ? "0x%01"PRIx8 : "0x%02"PRIx8, msb); for (j = byte_len - 2; j >= 0; j--) len += sprintf(prbuf + len, "%02"PRIx8, buf[j]); log_printf_lf(dbg_lvl, file, line, function, "%8s = %s", desc ? desc : " ", prbuf); free(prbuf); } static int svf_realloc_buffers(size_t len) { void *ptr; ptr = realloc(svf_tdi_buffer, len); if (!ptr) return ERROR_FAIL; svf_tdi_buffer = ptr; ptr = realloc(svf_tdo_buffer, len); if (!ptr) return ERROR_FAIL; svf_tdo_buffer = ptr; ptr = realloc(svf_mask_buffer, len); if (!ptr) return ERROR_FAIL; svf_mask_buffer = ptr; svf_buffer_size = len; return ERROR_OK; } static void svf_free_xxd_para(struct svf_xxr_para *para) { if (NULL != para) { if (para->tdi != NULL) { free(para->tdi); para->tdi = NULL; } if (para->tdo != NULL) { free(para->tdo); para->tdo = NULL; } if (para->mask != NULL) { free(para->mask); para->mask = NULL; } if (para->smask != NULL) { free(para->smask); para->smask = NULL; } } } int svf_add_statemove(tap_state_t state_to) { tap_state_t state_from = cmd_queue_cur_state; unsigned index_var; /* when resetting, be paranoid and ignore current state */ if (state_to == TAP_RESET) { if (svf_nil) return ERROR_OK; jtag_add_tlr(); return ERROR_OK; } for (index_var = 0; index_var < ARRAY_SIZE(svf_statemoves); index_var++) { if ((svf_statemoves[index_var].from == state_from) && (svf_statemoves[index_var].to == state_to)) { if (svf_nil) continue; /* recorded path includes current state ... avoid *extra TCKs! */ if (svf_statemoves[index_var].num_of_moves > 1) jtag_add_pathmove(svf_statemoves[index_var].num_of_moves - 1, svf_statemoves[index_var].paths + 1); else jtag_add_pathmove(svf_statemoves[index_var].num_of_moves, svf_statemoves[index_var].paths); return ERROR_OK; } } LOG_ERROR("SVF: can not move to %s", tap_state_name(state_to)); return ERROR_FAIL; } COMMAND_HANDLER(handle_svf_command) { #define SVF_MIN_NUM_OF_OPTIONS 1 #define SVF_MAX_NUM_OF_OPTIONS 5 int command_num = 0; int ret = ERROR_OK; long long time_measure_ms; int time_measure_s, time_measure_m; /* use NULL to indicate a "plain" svf file which accounts for * any additional devices in the scan chain, otherwise the device * that should be affected */ struct jtag_tap *tap = NULL; if ((CMD_ARGC < SVF_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > SVF_MAX_NUM_OF_OPTIONS)) return ERROR_COMMAND_SYNTAX_ERROR; /* parse command line */ svf_quiet = 0; svf_nil = 0; svf_ignore_error = 0; for (unsigned int i = 0; i < CMD_ARGC; i++) { if (strcmp(CMD_ARGV[i], "-tap") == 0) { tap = jtag_tap_by_string(CMD_ARGV[i+1]); if (!tap) { command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i+1]); return ERROR_FAIL; } i++; } else if ((strcmp(CMD_ARGV[i], "quiet") == 0) || (strcmp(CMD_ARGV[i], "-quiet") == 0)) svf_quiet = 1; else if ((strcmp(CMD_ARGV[i], "nil") == 0) || (strcmp(CMD_ARGV[i], "-nil") == 0)) svf_nil = 1; else if ((strcmp(CMD_ARGV[i], "progress") == 0) || (strcmp(CMD_ARGV[i], "-progress") == 0)) svf_progress_enabled = 1; else if ((strcmp(CMD_ARGV[i], "ignore_error") == 0) || (strcmp(CMD_ARGV[i], "-ignore_error") == 0)) svf_ignore_error = 1; else { svf_fd = fopen(CMD_ARGV[i], "r"); if (svf_fd == NULL) { int err = errno; command_print(CMD_CTX, "open(\"%s\"): %s", CMD_ARGV[i], strerror(err)); /* no need to free anything now */ return ERROR_COMMAND_SYNTAX_ERROR; } else LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]); } } if (svf_fd == NULL) return ERROR_COMMAND_SYNTAX_ERROR; /* get time */ time_measure_ms = timeval_ms(); /* init */ svf_line_number = 1; svf_command_buffer_size = 0; svf_check_tdo_para_index = 0; svf_check_tdo_para = malloc(sizeof(struct svf_check_tdo_para) * SVF_CHECK_TDO_PARA_SIZE); if (NULL == svf_check_tdo_para) { LOG_ERROR("not enough memory"); ret = ERROR_FAIL; goto free_all; } svf_buffer_index = 0; /* double the buffer size */ /* in case current command cannot be committed, and next command is a bit scan command */ /* here is 32K bits for this big scan command, it should be enough */ /* buffer will be reallocated if buffer size is not enough */ if (svf_realloc_buffers(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT) != ERROR_OK) { ret = ERROR_FAIL; goto free_all; } memcpy(&svf_para, &svf_para_init, sizeof(svf_para)); if (!svf_nil) { /* TAP_RESET */ jtag_add_tlr(); } if (tap) { /* Tap is specified, set header/trailer paddings */ int header_ir_len = 0, header_dr_len = 0, trailer_ir_len = 0, trailer_dr_len = 0; struct jtag_tap *check_tap; svf_tap_is_specified = 1; for (check_tap = jtag_all_taps(); check_tap; check_tap = check_tap->next_tap) { if (check_tap->abs_chain_position < tap->abs_chain_position) { /* Header */ header_ir_len += check_tap->ir_length; header_dr_len++; } else if (check_tap->abs_chain_position > tap->abs_chain_position) { /* Trailer */ trailer_ir_len += check_tap->ir_length; trailer_dr_len++; } } /* HDR %d TDI (0) */ if (ERROR_OK != svf_set_padding(&svf_para.hdr_para, header_dr_len, 0)) { LOG_ERROR("failed to set data header"); return ERROR_FAIL; } /* HIR %d TDI (0xFF) */ if (ERROR_OK != svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF)) { LOG_ERROR("failed to set instruction header"); return ERROR_FAIL; } /* TDR %d TDI (0) */ if (ERROR_OK != svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0)) { LOG_ERROR("failed to set data trailer"); return ERROR_FAIL; } /* TIR %d TDI (0xFF) */ if (ERROR_OK != svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF)) { LOG_ERROR("failed to set instruction trailer"); return ERROR_FAIL; } } if (svf_progress_enabled) { /* Count total lines in file. */ while (!feof(svf_fd)) { svf_getline(&svf_command_buffer, &svf_command_buffer_size, svf_fd); svf_total_lines++; } rewind(svf_fd); } while (ERROR_OK == svf_read_command_from_file(svf_fd)) { /* Log Output */ if (svf_quiet) { if (svf_progress_enabled) { svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5; if (svf_last_printed_percentage != svf_percentage) { LOG_USER_N("\r%d%% ", svf_percentage); svf_last_printed_percentage = svf_percentage; } } } else { if (svf_progress_enabled) { svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5; LOG_USER_N("%3d%% %s", svf_percentage, svf_read_line); } else LOG_USER_N("%s", svf_read_line); } /* Run Command */ if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer)) { LOG_ERROR("fail to run command at line %d", svf_line_number); ret = ERROR_FAIL; break; } command_num++; } if ((!svf_nil) && (ERROR_OK != jtag_execute_queue())) ret = ERROR_FAIL; else if (ERROR_OK != svf_check_tdo()) ret = ERROR_FAIL; /* print time */ time_measure_ms = timeval_ms() - time_measure_ms; time_measure_s = time_measure_ms / 1000; time_measure_ms %= 1000; time_measure_m = time_measure_s / 60; time_measure_s %= 60; if (time_measure_ms < 1000) command_print(CMD_CTX, "\r\nTime used: %dm%ds%lldms ", time_measure_m, time_measure_s, time_measure_ms); free_all: fclose(svf_fd); svf_fd = 0; /* free buffers */ if (svf_command_buffer) { free(svf_command_buffer); svf_command_buffer = NULL; svf_command_buffer_size = 0; } if (svf_check_tdo_para) { free(svf_check_tdo_para); svf_check_tdo_para = NULL; svf_check_tdo_para_index = 0; } if (svf_tdi_buffer) { free(svf_tdi_buffer); svf_tdi_buffer = NULL; } if (svf_tdo_buffer) { free(svf_tdo_buffer); svf_tdo_buffer = NULL; } if (svf_mask_buffer) { free(svf_mask_buffer); svf_mask_buffer = NULL; } svf_buffer_index = 0; svf_buffer_size = 0; svf_free_xxd_para(&svf_para.hdr_para); svf_free_xxd_para(&svf_para.hir_para); svf_free_xxd_para(&svf_para.tdr_para); svf_free_xxd_para(&svf_para.tir_para); svf_free_xxd_para(&svf_para.sdr_para); svf_free_xxd_para(&svf_para.sir_para); if (ERROR_OK == ret) command_print(CMD_CTX, "svf file programmed %s for %d commands with %d errors", (svf_ignore_error > 1) ? "unsuccessfully" : "successfully", command_num, (svf_ignore_error > 1) ? (svf_ignore_error - 1) : 0); else command_print(CMD_CTX, "svf file programmed failed"); svf_ignore_error = 0; return ret; } static int svf_getline(char **lineptr, size_t *n, FILE *stream) { #define MIN_CHUNK 16 /* Buffer is increased by this size each time as required */ size_t i = 0; if (*lineptr == NULL) { *n = MIN_CHUNK; *lineptr = malloc(*n); if (!*lineptr) return -1; } (*lineptr)[0] = fgetc(stream); while ((*lineptr)[i] != '\n') { (*lineptr)[++i] = fgetc(stream); if (feof(stream)) { (*lineptr)[0] = 0; return -1; } if ((i + 2) > *n) { *n += MIN_CHUNK; *lineptr = realloc(*lineptr, *n); } } (*lineptr)[++i] = 0; return sizeof(*lineptr); } #define SVFP_CMD_INC_CNT 1024 static int svf_read_command_from_file(FILE *fd) { unsigned char ch; int i = 0; size_t cmd_pos = 0; int cmd_ok = 0, slash = 0; if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0) return ERROR_FAIL; svf_line_number++; ch = svf_read_line[0]; while (!cmd_ok && (ch != 0)) { switch (ch) { case '!': slash = 0; if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0) return ERROR_FAIL; svf_line_number++; i = -1; break; case '/': if (++slash == 2) { slash = 0; if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0) return ERROR_FAIL; svf_line_number++; i = -1; } break; case ';': slash = 0; cmd_ok = 1; break; case '\n': svf_line_number++; if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0) return ERROR_FAIL; i = -1; case '\r': slash = 0; /* Don't save '\r' and '\n' if no data is parsed */ if (!cmd_pos) break; default: /* The parsing code currently expects a space * before parentheses -- "TDI (123)". Also a * space afterwards -- "TDI (123) TDO(456)". * But such spaces are optional... instead of * parser updates, cope with that by adding the * spaces as needed. * * Ensure there are 3 bytes available, for: * - current character * - added space. * - terminating NUL ('\0') */ if (cmd_pos + 3 > svf_command_buffer_size) { svf_command_buffer = realloc(svf_command_buffer, cmd_pos + 3); svf_command_buffer_size = cmd_pos + 3; if (svf_command_buffer == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } } /* insert a space before '(' */ if ('(' == ch) svf_command_buffer[cmd_pos++] = ' '; svf_command_buffer[cmd_pos++] = (char)toupper(ch); /* insert a space after ')' */ if (')' == ch) svf_command_buffer[cmd_pos++] = ' '; break; } ch = svf_read_line[++i]; } if (cmd_ok) { svf_command_buffer[cmd_pos] = '\0'; return ERROR_OK; } else return ERROR_FAIL; } static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu) { int pos = 0, num = 0, space_found = 1, in_bracket = 0; while (pos < len) { switch (str[pos]) { case '!': case '/': LOG_ERROR("fail to parse svf command"); return ERROR_FAIL; case '(': in_bracket = 1; goto parse_char; case ')': in_bracket = 0; goto parse_char; default: parse_char: if (!in_bracket && isspace((int) str[pos])) { space_found = 1; str[pos] = '\0'; } else if (space_found) { argus[num++] = &str[pos]; space_found = 0; } break; } pos++; } *num_of_argu = num; return ERROR_OK; } bool svf_tap_state_is_stable(tap_state_t state) { return (TAP_RESET == state) || (TAP_IDLE == state) || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state); } static int svf_find_string_in_array(char *str, char **strs, int num_of_element) { int i; for (i = 0; i < num_of_element; i++) { if (!strcmp(str, strs[i])) return i; } return 0xFF; } static int svf_adjust_array_length(uint8_t **arr, int orig_bit_len, int new_bit_len) { int new_byte_len = (new_bit_len + 7) >> 3; if ((NULL == *arr) || (((orig_bit_len + 7) >> 3) < ((new_bit_len + 7) >> 3))) { if (*arr != NULL) { free(*arr); *arr = NULL; } *arr = malloc(new_byte_len); if (NULL == *arr) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } memset(*arr, 0, new_byte_len); } return ERROR_OK; } static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi) { int error = ERROR_OK; error |= svf_adjust_array_length(¶->tdi, para->len, len); memset(para->tdi, tdi, (len + 7) >> 3); error |= svf_adjust_array_length(¶->tdo, para->len, len); error |= svf_adjust_array_length(¶->mask, para->len, len); para->len = len; para->data_mask = XXR_TDI; return error; } static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_len, int bit_len) { int i, str_len = strlen(str), str_hbyte_len = (bit_len + 3) >> 2; uint8_t ch = 0; if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len)) { LOG_ERROR("fail to adjust length of array"); return ERROR_FAIL; } /* fill from LSB (end of str) to MSB (beginning of str) */ for (i = 0; i < str_hbyte_len; i++) { ch = 0; while (str_len > 0) { ch = str[--str_len]; /* Skip whitespace. The SVF specification (rev E) is * deficient in terms of basic lexical issues like * where whitespace is allowed. Long bitstrings may * require line ends for correctness, since there is * a hard limit on line length. */ if (!isspace(ch)) { if ((ch >= '0') && (ch <= '9')) { ch = ch - '0'; break; } else if ((ch >= 'A') && (ch <= 'F')) { ch = ch - 'A' + 10; break; } else { LOG_ERROR("invalid hex string"); return ERROR_FAIL; } } ch = 0; } /* write bin */ if (i % 2) { /* MSB */ (*bin)[i / 2] |= ch << 4; } else { /* LSB */ (*bin)[i / 2] = 0; (*bin)[i / 2] |= ch; } } /* consume optional leading '0' MSBs or whitespace */ while (str_len > 0 && ((str[str_len - 1] == '0') || isspace((int) str[str_len - 1]))) str_len--; /* check validity: we must have consumed everything */ if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0) { LOG_ERROR("value execeeds length"); return ERROR_FAIL; } return ERROR_OK; } static int svf_check_tdo(void) { int i, len, index_var; for (i = 0; i < svf_check_tdo_para_index; i++) { index_var = svf_check_tdo_para[i].buffer_offset; len = svf_check_tdo_para[i].bit_len; if ((svf_check_tdo_para[i].enabled) && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len)) { LOG_ERROR("tdo check error at line %d", svf_check_tdo_para[i].line_num); SVF_BUF_LOG(ERROR, &svf_tdi_buffer[index_var], len, "READ"); SVF_BUF_LOG(ERROR, &svf_tdo_buffer[index_var], len, "WANT"); SVF_BUF_LOG(ERROR, &svf_mask_buffer[index_var], len, "MASK"); if (svf_ignore_error == 0) return ERROR_FAIL; else svf_ignore_error++; } } svf_check_tdo_para_index = 0; return ERROR_OK; } static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len) { if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE) { LOG_ERROR("toooooo many operation undone"); return ERROR_FAIL; } svf_check_tdo_para[svf_check_tdo_para_index].line_num = svf_line_number; svf_check_tdo_para[svf_check_tdo_para_index].bit_len = bit_len; svf_check_tdo_para[svf_check_tdo_para_index].enabled = enabled; svf_check_tdo_para[svf_check_tdo_para_index].buffer_offset = buffer_offset; svf_check_tdo_para_index++; return ERROR_OK; } static int svf_execute_tap(void) { if ((!svf_nil) && (ERROR_OK != jtag_execute_queue())) return ERROR_FAIL; else if (ERROR_OK != svf_check_tdo()) return ERROR_FAIL; svf_buffer_index = 0; return ERROR_OK; } static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) { char *argus[256], command; int num_of_argu = 0, i; /* tmp variable */ int i_tmp; /* for RUNTEST */ int run_count; float min_time; /* for XXR */ struct svf_xxr_para *xxr_para_tmp; uint8_t **pbuffer_tmp; struct scan_field field; /* for STATE */ tap_state_t *path = NULL, state; /* flag padding commands skipped due to -tap command */ int padding_command_skipped = 0; if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu)) return ERROR_FAIL; /* NOTE: we're a bit loose here, because we ignore case in * TAP state names (instead of insisting on uppercase). */ command = svf_find_string_in_array(argus[0], (char **)svf_command_name, ARRAY_SIZE(svf_command_name)); switch (command) { case ENDDR: case ENDIR: if (num_of_argu != 2) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } i_tmp = tap_state_by_name(argus[1]); if (svf_tap_state_is_stable(i_tmp)) { if (command == ENDIR) { svf_para.ir_end_state = i_tmp; LOG_DEBUG("\tIR end_state = %s", tap_state_name(i_tmp)); } else { svf_para.dr_end_state = i_tmp; LOG_DEBUG("\tDR end_state = %s", tap_state_name(i_tmp)); } } else { LOG_ERROR("%s: %s is not a stable state", argus[0], argus[1]); return ERROR_FAIL; } break; case FREQUENCY: if ((num_of_argu != 1) && (num_of_argu != 3)) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } if (1 == num_of_argu) { /* TODO: set jtag speed to full speed */ svf_para.frequency = 0; } else { if (strcmp(argus[2], "HZ")) { LOG_ERROR("HZ not found in FREQUENCY command"); return ERROR_FAIL; } if (ERROR_OK != svf_execute_tap()) return ERROR_FAIL; svf_para.frequency = atof(argus[1]); /* TODO: set jtag speed to */ if (svf_para.frequency > 0) { command_run_linef(cmd_ctx, "adapter_khz %d", (int)svf_para.frequency / 1000); LOG_DEBUG("\tfrequency = %f", svf_para.frequency); } } break; case HDR: if (svf_tap_is_specified) { padding_command_skipped = 1; break; } xxr_para_tmp = &svf_para.hdr_para; goto XXR_common; case HIR: if (svf_tap_is_specified) { padding_command_skipped = 1; break; } xxr_para_tmp = &svf_para.hir_para; goto XXR_common; case TDR: if (svf_tap_is_specified) { padding_command_skipped = 1; break; } xxr_para_tmp = &svf_para.tdr_para; goto XXR_common; case TIR: if (svf_tap_is_specified) { padding_command_skipped = 1; break; } xxr_para_tmp = &svf_para.tir_para; goto XXR_common; case SDR: xxr_para_tmp = &svf_para.sdr_para; goto XXR_common; case SIR: xxr_para_tmp = &svf_para.sir_para; goto XXR_common; XXR_common: /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */ if ((num_of_argu > 10) || (num_of_argu % 2)) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } i_tmp = xxr_para_tmp->len; xxr_para_tmp->len = atoi(argus[1]); LOG_DEBUG("\tlength = %d", xxr_para_tmp->len); xxr_para_tmp->data_mask = 0; for (i = 2; i < num_of_argu; i += 2) { if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) { LOG_ERROR("data section error"); return ERROR_FAIL; } argus[i + 1][strlen(argus[i + 1]) - 1] = '\0'; /* TDI, TDO, MASK, SMASK */ if (!strcmp(argus[i], "TDI")) { /* TDI */ pbuffer_tmp = &xxr_para_tmp->tdi; xxr_para_tmp->data_mask |= XXR_TDI; } else if (!strcmp(argus[i], "TDO")) { /* TDO */ pbuffer_tmp = &xxr_para_tmp->tdo; xxr_para_tmp->data_mask |= XXR_TDO; } else if (!strcmp(argus[i], "MASK")) { /* MASK */ pbuffer_tmp = &xxr_para_tmp->mask; xxr_para_tmp->data_mask |= XXR_MASK; } else if (!strcmp(argus[i], "SMASK")) { /* SMASK */ pbuffer_tmp = &xxr_para_tmp->smask; xxr_para_tmp->data_mask |= XXR_SMASK; } else { LOG_ERROR("unknow parameter: %s", argus[i]); return ERROR_FAIL; } if (ERROR_OK != svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp, xxr_para_tmp->len)) { LOG_ERROR("fail to parse hex value"); return ERROR_FAIL; } SVF_BUF_LOG(DEBUG, *pbuffer_tmp, xxr_para_tmp->len, argus[i]); } /* If a command changes the length of the last scan of the same type and the * MASK parameter is absent, */ /* the mask pattern used is all cares */ if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len)) { /* MASK not defined and length changed */ if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)) { LOG_ERROR("fail to adjust length of array"); return ERROR_FAIL; } buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len); } /* If TDO is absent, no comparison is needed, set the mask to 0 */ if (!(xxr_para_tmp->data_mask & XXR_TDO)) { if (NULL == xxr_para_tmp->tdo) { if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp, xxr_para_tmp->len)) { LOG_ERROR("fail to adjust length of array"); return ERROR_FAIL; } } if (NULL == xxr_para_tmp->mask) { if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)) { LOG_ERROR("fail to adjust length of array"); return ERROR_FAIL; } } memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3); } /* do scan if necessary */ if (SDR == command) { /* check buffer size first, reallocate if necessary */ i = svf_para.hdr_para.len + svf_para.sdr_para.len + svf_para.tdr_para.len; if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) { /* reallocate buffer */ if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } } /* assemble dr data */ i = 0; buf_set_buf(svf_para.hdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hdr_para.len); i += svf_para.hdr_para.len; buf_set_buf(svf_para.sdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sdr_para.len); i += svf_para.sdr_para.len; buf_set_buf(svf_para.tdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tdr_para.len); i += svf_para.tdr_para.len; /* add check data */ if (svf_para.sdr_para.data_mask & XXR_TDO) { /* assemble dr mask data */ i = 0; buf_set_buf(svf_para.hdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hdr_para.len); i += svf_para.hdr_para.len; buf_set_buf(svf_para.sdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sdr_para.len); i += svf_para.sdr_para.len; buf_set_buf(svf_para.tdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tdr_para.len); /* assemble dr check data */ i = 0; buf_set_buf(svf_para.hdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hdr_para.len); i += svf_para.hdr_para.len; buf_set_buf(svf_para.sdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sdr_para.len); i += svf_para.sdr_para.len; buf_set_buf(svf_para.tdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tdr_para.len); i += svf_para.tdr_para.len; svf_add_check_para(1, svf_buffer_index, i); } else svf_add_check_para(0, svf_buffer_index, i); field.num_bits = i; field.out_value = &svf_tdi_buffer[svf_buffer_index]; field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL; if (!svf_nil) { /* NOTE: doesn't use SVF-specified state paths */ jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, svf_para.dr_end_state); } svf_buffer_index += (i + 7) >> 3; } else if (SIR == command) { /* check buffer size first, reallocate if necessary */ i = svf_para.hir_para.len + svf_para.sir_para.len + svf_para.tir_para.len; if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) { if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } } /* assemble ir data */ i = 0; buf_set_buf(svf_para.hir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hir_para.len); i += svf_para.hir_para.len; buf_set_buf(svf_para.sir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sir_para.len); i += svf_para.sir_para.len; buf_set_buf(svf_para.tir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tir_para.len); i += svf_para.tir_para.len; /* add check data */ if (svf_para.sir_para.data_mask & XXR_TDO) { /* assemble dr mask data */ i = 0; buf_set_buf(svf_para.hir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hir_para.len); i += svf_para.hir_para.len; buf_set_buf(svf_para.sir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sir_para.len); i += svf_para.sir_para.len; buf_set_buf(svf_para.tir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tir_para.len); /* assemble dr check data */ i = 0; buf_set_buf(svf_para.hir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hir_para.len); i += svf_para.hir_para.len; buf_set_buf(svf_para.sir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sir_para.len); i += svf_para.sir_para.len; buf_set_buf(svf_para.tir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tir_para.len); i += svf_para.tir_para.len; svf_add_check_para(1, svf_buffer_index, i); } else svf_add_check_para(0, svf_buffer_index, i); field.num_bits = i; field.out_value = &svf_tdi_buffer[svf_buffer_index]; field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL; if (!svf_nil) { /* NOTE: doesn't use SVF-specified state paths */ jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, svf_para.ir_end_state); } svf_buffer_index += (i + 7) >> 3; } break; case PIO: case PIOMAP: LOG_ERROR("PIO and PIOMAP are not supported"); return ERROR_FAIL; break; case RUNTEST: /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time * SEC]] [ENDSTATE end_state] */ /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE * end_state] */ if ((num_of_argu < 3) && (num_of_argu > 11)) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } /* init */ run_count = 0; min_time = 0; i = 1; /* run_state */ i_tmp = tap_state_by_name(argus[i]); if (i_tmp != TAP_INVALID) { if (svf_tap_state_is_stable(i_tmp)) { svf_para.runtest_run_state = i_tmp; /* When a run_state is specified, the new * run_state becomes the default end_state. */ svf_para.runtest_end_state = i_tmp; LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp)); i++; } else { LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp)); return ERROR_FAIL; } } /* run_count run_clk */ if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) { if (!strcmp(argus[i + 1], "TCK")) { /* clock source is TCK */ run_count = atoi(argus[i]); LOG_DEBUG("\trun_count@TCK = %d", run_count); } else { LOG_ERROR("%s not supported for clock", argus[i + 1]); return ERROR_FAIL; } i += 2; } /* min_time SEC */ if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) { min_time = atof(argus[i]); LOG_DEBUG("\tmin_time = %fs", min_time); i += 2; } /* MAXIMUM max_time SEC */ if (((i + 3) <= num_of_argu) && !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) { float max_time = 0; max_time = atof(argus[i + 1]); LOG_DEBUG("\tmax_time = %fs", max_time); i += 3; } /* ENDSTATE end_state */ if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) { i_tmp = tap_state_by_name(argus[i + 1]); if (svf_tap_state_is_stable(i_tmp)) { svf_para.runtest_end_state = i_tmp; LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp)); } else { LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp)); return ERROR_FAIL; } i += 2; } /* all parameter should be parsed */ if (i == num_of_argu) { #if 1 /* FIXME handle statemove failures */ uint32_t min_usec = 1000000 * min_time; /* enter into run_state if necessary */ if (cmd_queue_cur_state != svf_para.runtest_run_state) svf_add_statemove(svf_para.runtest_run_state); /* add clocks and/or min wait */ if (run_count > 0) { if (!svf_nil) jtag_add_clocks(run_count); } if (min_usec > 0) { if (!svf_nil) jtag_add_sleep(min_usec); } /* move to end_state if necessary */ if (svf_para.runtest_end_state != svf_para.runtest_run_state) svf_add_statemove(svf_para.runtest_end_state); #else if (svf_para.runtest_run_state != TAP_IDLE) { LOG_ERROR("cannot runtest in %s state", tap_state_name(svf_para.runtest_run_state)); return ERROR_FAIL; } if (!svf_nil) jtag_add_runtest(run_count, svf_para.runtest_end_state); #endif } else { LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed", i, num_of_argu); return ERROR_FAIL; } break; case STATE: /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */ if (num_of_argu < 2) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } if (num_of_argu > 2) { /* STATE pathstate1 ... stable_state */ path = malloc((num_of_argu - 1) * sizeof(tap_state_t)); if (NULL == path) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } num_of_argu--; /* num of path */ i_tmp = 1; /* path is from parameter 1 */ for (i = 0; i < num_of_argu; i++, i_tmp++) { path[i] = tap_state_by_name(argus[i_tmp]); if (path[i] == TAP_INVALID) { LOG_ERROR("%s: %s is not a valid state", argus[0], argus[i_tmp]); free(path); return ERROR_FAIL; } /* OpenOCD refuses paths containing TAP_RESET */ if (TAP_RESET == path[i]) { /* FIXME last state MUST be stable! */ if (i > 0) { if (!svf_nil) jtag_add_pathmove(i, path); } if (!svf_nil) jtag_add_tlr(); num_of_argu -= i + 1; i = -1; } } if (num_of_argu > 0) { /* execute last path if necessary */ if (svf_tap_state_is_stable(path[num_of_argu - 1])) { /* last state MUST be stable state */ if (!svf_nil) jtag_add_pathmove(num_of_argu, path); LOG_DEBUG("\tmove to %s by path_move", tap_state_name(path[num_of_argu - 1])); } else { LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(path[num_of_argu - 1])); free(path); return ERROR_FAIL; } } free(path); path = NULL; } else { /* STATE stable_state */ state = tap_state_by_name(argus[1]); if (svf_tap_state_is_stable(state)) { LOG_DEBUG("\tmove to %s by svf_add_statemove", tap_state_name(state)); /* FIXME handle statemove failures */ svf_add_statemove(state); } else { LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(state)); return ERROR_FAIL; } } break; case TRST: /* TRST trst_mode */ if (num_of_argu != 2) { LOG_ERROR("invalid parameter of %s", argus[0]); return ERROR_FAIL; } if (svf_para.trst_mode != TRST_ABSENT) { if (ERROR_OK != svf_execute_tap()) return ERROR_FAIL; i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, ARRAY_SIZE(svf_trst_mode_name)); switch (i_tmp) { case TRST_ON: if (!svf_nil) jtag_add_reset(1, 0); break; case TRST_Z: case TRST_OFF: if (!svf_nil) jtag_add_reset(0, 0); break; case TRST_ABSENT: break; default: LOG_ERROR("unknown TRST mode: %s", argus[1]); return ERROR_FAIL; } svf_para.trst_mode = i_tmp; LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]); } else { LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT"); return ERROR_FAIL; } break; default: LOG_ERROR("invalid svf command: %s", argus[0]); return ERROR_FAIL; break; } if (!svf_quiet) { if (padding_command_skipped) LOG_USER("(Above Padding command skipped, as per -tap argument)"); } if (debug_level >= LOG_LVL_DEBUG) { /* for convenient debugging, execute tap if possible */ if ((svf_buffer_index > 0) && \ (((command != STATE) && (command != RUNTEST)) || \ ((command == STATE) && (num_of_argu == 2)))) { if (ERROR_OK != svf_execute_tap()) return ERROR_FAIL; /* output debug info */ if ((SIR == command) || (SDR == command)) { SVF_BUF_LOG(DEBUG, svf_tdi_buffer, svf_check_tdo_para[0].bit_len, "TDO read"); } } } else { /* for fast executing, execute tap if necessary */ /* half of the buffer is for the next command */ if (((svf_buffer_index >= SVF_MAX_BUFFER_SIZE_TO_COMMIT) || (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE / 2)) && \ (((command != STATE) && (command != RUNTEST)) || \ ((command == STATE) && (num_of_argu == 2)))) return svf_execute_tap(); } return ERROR_OK; } static const struct command_registration svf_command_handlers[] = { { .name = "svf", .handler = handle_svf_command, .mode = COMMAND_EXEC, .help = "Runs a SVF file.", .usage = "svf [-tap device.tap] [quiet] [nil] [progress] [ignore_error]", }, COMMAND_REGISTRATION_DONE }; int svf_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, svf_command_handlers); } openocd-0.9.0/src/svf/svf.h0000644000175000017500000000442212315575361012436 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * SimonQian@SimonQian.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef SVF_H #define SVF_H #include int svf_register_commands(struct command_context *cmd_ctx); /** * svf_add_statemove() moves from the current state to @a goal_state. * * @param goal_state The final TAP state. * @return ERROR_OK on success, or an error code on failure. * * The current and goal states must satisfy svf_tap_state_is_stable(). * State transition paths used by this routine are those given in the * SVF specification for single-argument STATE commands (and also used * for various other state transitions). */ int svf_add_statemove(tap_state_t goal_state); /** * svf_tap_state_is_stable() returns true for stable non-SHIFT states * * @param state The TAP state in question * @return true iff the state is stable and not a SHIFT state. */ bool svf_tap_state_is_stable(tap_state_t state); #endif /* SVF_H */ openocd-0.9.0/src/svf/Makefile.am0000644000175000017500000000026212315575361013521 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libsvf.la noinst_HEADERS = svf.h libsvf_la_SOURCES = svf.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/svf/Makefile.in0000644000175000017500000004351112526201651013526 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/svf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsvf_la_LIBADD = am_libsvf_la_OBJECTS = svf.lo libsvf_la_OBJECTS = $(am_libsvf_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libsvf_la_SOURCES) DIST_SOURCES = $(libsvf_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libsvf.la noinst_HEADERS = svf.h libsvf_la_SOURCES = svf.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/svf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/svf/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libsvf.la: $(libsvf_la_OBJECTS) $(libsvf_la_DEPENDENCIES) $(EXTRA_libsvf_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsvf_la_OBJECTS) $(libsvf_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svf.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/0000755000175000017500000000000012526202224011661 500000000000000openocd-0.9.0/src/jtag/hla/0000755000175000017500000000000012526202224012425 500000000000000openocd-0.9.0/src/jtag/hla/hla_tcl.c0000644000175000017500000001176112516456303014135 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, struct jtag_tap *pTap) { jim_wide w; int e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) { Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name); return e; } unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt; uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t)); if (new_expected_ids == NULL) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } memcpy(new_expected_ids, pTap->expected_ids, expected_len); new_expected_ids[pTap->expected_ids_cnt] = w; free(pTap->expected_ids); pTap->expected_ids = new_expected_ids; pTap->expected_ids_cnt++; return JIM_OK; } #define NTAP_OPT_IRLEN 0 #define NTAP_OPT_IRMASK 1 #define NTAP_OPT_IRCAPTURE 2 #define NTAP_OPT_ENABLED 3 #define NTAP_OPT_DISABLED 4 #define NTAP_OPT_EXPECTED_ID 5 #define NTAP_OPT_VERSION 6 static int jim_hl_newtap_cmd(Jim_GetOptInfo *goi) { struct jtag_tap *pTap; int x; int e; Jim_Nvp *n; char *cp; const Jim_Nvp opts[] = { { .name = "-irlen", .value = NTAP_OPT_IRLEN }, { .name = "-irmask", .value = NTAP_OPT_IRMASK }, { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE }, { .name = "-enable", .value = NTAP_OPT_ENABLED }, { .name = "-disable", .value = NTAP_OPT_DISABLED }, { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID }, { .name = "-ignore-version", .value = NTAP_OPT_VERSION }, { .name = NULL, .value = -1}, }; pTap = calloc(1, sizeof(struct jtag_tap)); if (!pTap) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } /* * we expect CHIP + TAP + OPTIONS * */ if (goi->argc < 3) { Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ...."); free(pTap); return JIM_ERR; } Jim_GetOpt_String(goi, &cp, NULL); pTap->chip = strdup(cp); Jim_GetOpt_String(goi, &cp, NULL); pTap->tapname = strdup(cp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; cp = malloc(x); sprintf(cp, "%s.%s", pTap->chip, pTap->tapname); pTap->dotted_name = cp; LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); while (goi->argc) { e = Jim_GetOpt_Nvp(goi, opts, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, opts, 0); free(cp); free(pTap); return e; } LOG_DEBUG("Processing option: %s", n->name); switch (n->value) { case NTAP_OPT_EXPECTED_ID: e = jim_newtap_expected_id(n, goi, pTap); if (JIM_OK != e) { free(cp); free(pTap); return e; } break; case NTAP_OPT_IRLEN: case NTAP_OPT_IRMASK: case NTAP_OPT_IRCAPTURE: /* dummy read to ignore the next argument */ Jim_GetOpt_Wide(goi, NULL); break; } /* switch (n->value) */ } /* while (goi->argc) */ /* default is enabled-after-reset */ pTap->enabled = !pTap->disabled_after_reset; jtag_tap_init(pTap); return JIM_OK; } int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); return jim_hl_newtap_cmd(&goi); } openocd-0.9.0/src/jtag/hla/hla_tcl.h0000644000175000017500000000345112315575360014141 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _HL_TCL_ #define _HL_TCL_ /** */ int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv); #endif /* _HL_TCL_ */ openocd-0.9.0/src/jtag/hla/hla_layout.c0000644000175000017500000000563112315575360014671 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include #include static int hl_layout_open(struct hl_interface_s *adapter) { int res; LOG_DEBUG("hl_layout_open"); adapter->handle = NULL; res = adapter->layout->api->open(&adapter->param, &adapter->handle); if (res != ERROR_OK) { LOG_DEBUG("failed"); return res; } return ERROR_OK; } static int hl_layout_close(struct hl_interface_s *adapter) { return ERROR_OK; } static const struct hl_layout hl_layouts[] = { { .name = "stlink", .open = hl_layout_open, .close = hl_layout_close, .api = &stlink_usb_layout_api, }, { .name = "ti-icdi", .open = hl_layout_open, .close = hl_layout_close, .api = &icdi_usb_layout_api, }, {.name = NULL, /* END OF TABLE */ }, }; /** */ const struct hl_layout *hl_layout_get_list(void) { return hl_layouts; } int hl_layout_init(struct hl_interface_s *adapter) { LOG_DEBUG("hl_layout_init"); if (adapter->layout == NULL) { LOG_ERROR("no layout specified"); return ERROR_FAIL; } return ERROR_OK; } openocd-0.9.0/src/jtag/hla/hla_layout.h0000644000175000017500000001115512516456303014672 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _HL_LAYOUT_H #define _HL_LAYOUT_H #include /** */ struct hl_interface_s; struct hl_interface_param_s; /** */ extern struct hl_layout_api_s stlink_usb_layout_api; extern struct hl_layout_api_s icdi_usb_layout_api; /** */ struct hl_layout_api_s { /** */ int (*open) (struct hl_interface_param_s *param, void **handle); /** */ int (*close) (void *handle); /** */ int (*reset) (void *handle); /** */ int (*assert_srst) (void *handle, int srst); /** */ int (*run) (void *handle); /** */ int (*halt) (void *handle); /** */ int (*step) (void *handle); /** */ int (*read_regs) (void *handle); /** */ int (*read_reg) (void *handle, int num, uint32_t *val); /** */ int (*write_reg) (void *handle, int num, uint32_t val); /** */ int (*read_mem) (void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer); /** */ int (*write_mem) (void *handle, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer); /** */ int (*write_debug_reg) (void *handle, uint32_t addr, uint32_t val); /** * Read the idcode of the target connected to the adapter * * If the adapter doesn't support idcode retrieval, this callback should * store 0 to indicate a wildcard match. * * @param handle A pointer to the device-specific handle * @param idcode Storage for the detected idcode * @returns ERROR_OK on success, or an error code on failure. */ int (*idcode) (void *handle, uint32_t *idcode); /** */ int (*override_target) (const char *targetname); /** */ int (*custom_command) (void *handle, const char *command); /** */ int (*speed)(void *handle, int khz, bool query); /** * Configure trace parameters for the adapter * * @param handle A handle to adapter * @param enabled Whether to enable trace * @param pin_protocol Configured pin protocol * @param port_size Trace port width for sync mode * @param trace_freq A pointer to the configured trace * frequency; if it points to 0, the adapter driver must write * its maximum supported rate there * @returns ERROR_OK on success, an error code on failure. */ int (*config_trace)(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); /** * Poll for new trace data * * @param handle A handle to adapter * @param buf A pointer to buffer to store received data * @param size A pointer to buffer size; must be filled with * the actual amount of bytes written * * @returns ERROR_OK on success, an error code on failure. */ int (*poll_trace)(void *handle, uint8_t *buf, size_t *size); /** */ enum target_state (*state) (void *fd); }; /** */ struct hl_layout { /** */ char *name; /** */ int (*open) (struct hl_interface_s *adapter); /** */ int (*close) (struct hl_interface_s *adapter); /** */ struct hl_layout_api_s *api; }; /** */ const struct hl_layout *hl_layout_get_list(void); /** */ int hl_layout_init(struct hl_interface_s *adapter); #endif /* _HL_LAYOUT_H */ openocd-0.9.0/src/jtag/hla/hla_transport.c0000644000175000017500000001425512516456303015410 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include #include #include COMMAND_HANDLER(hl_transport_jtag_command) { LOG_DEBUG("hl_transport_jtag_command"); return ERROR_OK; } COMMAND_HANDLER(hl_transport_reset_command) { return hl_interface_init_reset(); } static const struct command_registration hl_transport_stlink_subcommand_handlers[] = { { .name = "newtap", .mode = COMMAND_CONFIG, .jim_handler = jim_hl_newtap, .help = "Create a new TAP instance named basename.tap_type, " "and appends it to the scan chain.", .usage = "basename tap_type '-irlen' count " "['-expected_id' number] ", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration hl_transport_jtag_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_ANY, .handler = hl_transport_jtag_command, .usage = "" }, { .name = "arp_init", .mode = COMMAND_ANY, .handler = hl_transport_jtag_command, .usage = "" }, { .name = "arp_init-reset", .mode = COMMAND_ANY, .handler = hl_transport_reset_command, .usage = "" }, { .name = "tapisenabled", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, }, { .name = "tapenable", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, }, { .name = "tapdisable", .mode = COMMAND_EXEC, .handler = hl_transport_jtag_command, .usage = "", }, { .name = "configure", .mode = COMMAND_EXEC, .handler = hl_transport_jtag_command, .usage = "", }, { .name = "cget", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_configure, }, { .name = "names", .mode = COMMAND_ANY, .handler = hl_transport_jtag_command, .usage = "", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration stlink_transport_command_handlers[] = { { .name = "hla", .mode = COMMAND_ANY, .help = "perform hl adapter actions", .usage = "", .chain = hl_transport_stlink_subcommand_handlers, }, { .name = "jtag", .mode = COMMAND_ANY, .usage = "", .chain = hl_transport_jtag_subcommand_handlers, }, { .name = "jtag_ntrst_delay", .mode = COMMAND_ANY, .handler = hl_transport_jtag_command, .usage = "", }, COMMAND_REGISTRATION_DONE }; static int hl_transport_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, stlink_transport_command_handlers); } static int hl_transport_init(struct command_context *cmd_ctx) { LOG_DEBUG("hl_transport_init"); struct target *t = get_current_target(cmd_ctx); struct transport *transport; enum hl_transports tr; if (!t) { LOG_ERROR("no current target"); return ERROR_FAIL; } transport = get_current_transport(); if (!transport) { LOG_ERROR("no transport selected"); return ERROR_FAIL; } LOG_DEBUG("current transport %s", transport->name); /* get selected transport as enum */ tr = HL_TRANSPORT_UNKNOWN; if (strcmp(transport->name, "hla_swd") == 0) tr = HL_TRANSPORT_SWD; else if (strcmp(transport->name, "hla_jtag") == 0) tr = HL_TRANSPORT_JTAG; else if (strcmp(transport->name, "stlink_swim") == 0) tr = HL_TRANSPORT_SWIM; int retval = hl_interface_open(tr); if (retval != ERROR_OK) return retval; return hl_interface_init_target(t); } static int hl_transport_select(struct command_context *ctx) { LOG_DEBUG("hl_transport_select"); int retval; /* NOTE: interface init must already have been done. * That works with only C code ... no Tcl glue required. */ retval = hl_transport_register_commands(ctx); if (retval != ERROR_OK) return retval; return ERROR_OK; } static struct transport hl_swd_transport = { .name = "hla_swd", .select = hl_transport_select, .init = hl_transport_init, .override_target = hl_interface_override_target, }; static struct transport hl_jtag_transport = { .name = "hla_jtag", .select = hl_transport_select, .init = hl_transport_init, .override_target = hl_interface_override_target, }; static struct transport stlink_swim_transport = { .name = "stlink_swim", .select = hl_transport_select, .init = hl_transport_init, }; const char *hl_transports[] = { "hla_swd", "hla_jtag", "stlink_swim", NULL }; static void hl_constructor(void) __attribute__ ((constructor)); static void hl_constructor(void) { transport_register(&hl_swd_transport); transport_register(&hl_jtag_transport); transport_register(&stlink_swim_transport); } openocd-0.9.0/src/jtag/hla/hla_transport.h0000644000175000017500000000352612315575360015416 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _HL_TRANSPORT #define _HL_TRANSPORT enum hl_transports { HL_TRANSPORT_UNKNOWN = 0, HL_TRANSPORT_SWD, HL_TRANSPORT_JTAG, HL_TRANSPORT_SWIM }; #endif /* _HL_TRANSPORT */ openocd-0.9.0/src/jtag/hla/Makefile.am0000644000175000017500000000055612315575360014421 00000000000000include $(top_srcdir)/common.mk noinst_LTLIBRARIES = libocdhla.la libocdhla_la_SOURCES = \ $(HLFILES) HLFILES = if HLADAPTER HLFILES += hla_transport.c HLFILES += hla_tcl.c HLFILES += hla_interface.c HLFILES += hla_layout.c endif noinst_HEADERS = \ hla_interface.h \ hla_layout.h \ hla_tcl.h \ hla_transport.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/jtag/hla/Makefile.in0000644000175000017500000004504012526201651014420 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @HLADAPTER_TRUE@am__append_2 = hla_transport.c hla_tcl.c \ @HLADAPTER_TRUE@ hla_interface.c hla_layout.c subdir = src/jtag/hla ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdhla_la_LIBADD = am__libocdhla_la_SOURCES_DIST = hla_transport.c hla_tcl.c \ hla_interface.c hla_layout.c @HLADAPTER_TRUE@am__objects_1 = hla_transport.lo hla_tcl.lo \ @HLADAPTER_TRUE@ hla_interface.lo hla_layout.lo am__objects_2 = $(am__objects_1) am_libocdhla_la_OBJECTS = $(am__objects_2) libocdhla_la_OBJECTS = $(am_libocdhla_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdhla_la_SOURCES) DIST_SOURCES = $(am__libocdhla_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) noinst_LTLIBRARIES = libocdhla.la libocdhla_la_SOURCES = \ $(HLFILES) HLFILES = $(am__append_2) noinst_HEADERS = \ hla_interface.h \ hla_layout.h \ hla_tcl.h \ hla_transport.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/jtag/hla/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/jtag/hla/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libocdhla.la: $(libocdhla_la_OBJECTS) $(libocdhla_la_DEPENDENCIES) $(EXTRA_libocdhla_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdhla_la_OBJECTS) $(libocdhla_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hla_interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hla_layout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hla_tcl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hla_transport.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/hla/hla_interface.c0000644000175000017500000002220412516456303015305 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include #include #include static struct hl_interface_s hl_if = { {0, 0, 0, 0, 0, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 }; int hl_interface_open(enum hl_transports tr) { LOG_DEBUG("hl_interface_open"); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { if (jtag_reset_config & RESET_SRST_NO_GATING) hl_if.param.connect_under_reset = true; else LOG_WARNING("\'srst_nogate\' reset_config option is required"); } /* set transport mode */ hl_if.param.transport = tr; int result = hl_if.layout->open(&hl_if); if (result != ERROR_OK) return result; return hl_interface_init_reset(); } int hl_interface_init_target(struct target *t) { int res; LOG_DEBUG("hl_interface_init_target"); /* this is the interface for the current target and we * can setup the private pointer in the tap structure * if the interface match the tap idcode */ res = hl_if.layout->api->idcode(hl_if.handle, &t->tap->idcode); if (res != ERROR_OK) return res; unsigned ii, limit = t->tap->expected_ids_cnt; int found = 0; for (ii = 0; ii < limit; ii++) { uint32_t expected = t->tap->expected_ids[ii]; /* treat "-expected-id 0" as a "don't-warn" wildcard */ if (!expected || !t->tap->idcode || (t->tap->idcode == expected)) { found = 1; break; } } if (found == 0) { LOG_WARNING("UNEXPECTED idcode: 0x%08" PRIx32, t->tap->idcode); for (ii = 0; ii < limit; ii++) LOG_ERROR("expected %u of %u: 0x%08" PRIx32, ii + 1, limit, t->tap->expected_ids[ii]); return ERROR_FAIL; } t->tap->priv = &hl_if; t->tap->hasidcode = 1; return ERROR_OK; } static int hl_interface_init(void) { LOG_DEBUG("hl_interface_init"); /* here we can initialize the layout */ return hl_layout_init(&hl_if); } static int hl_interface_quit(void) { LOG_DEBUG("hl_interface_quit"); if (hl_if.layout->api->close) hl_if.layout->api->close(hl_if.handle); return ERROR_OK; } static int hl_interface_execute_queue(void) { LOG_DEBUG("hl_interface_execute_queue: ignored"); return ERROR_OK; } int hl_interface_init_reset(void) { /* incase the adapter has not already handled asserting srst * we will attempt it again */ if (hl_if.param.connect_under_reset) { jtag_add_reset(0, 1); hl_if.layout->api->assert_srst(hl_if.handle, 0); } else { jtag_add_reset(0, 0); } return ERROR_OK; } static int hl_interface_khz(int khz, int *jtag_speed) { if (hl_if.layout->api->speed == NULL) return ERROR_OK; *jtag_speed = hl_if.layout->api->speed(hl_if.handle, khz, true); return ERROR_OK; } static int hl_interface_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } static int hl_interface_speed(int speed) { if (hl_if.layout->api->speed == NULL) return ERROR_OK; if (hl_if.handle == NULL) { /* pass speed as initial param as interface not open yet */ hl_if.param.initial_interface_speed = speed; return ERROR_OK; } hl_if.layout->api->speed(hl_if.handle, speed, false); return ERROR_OK; } int hl_interface_override_target(const char **targetname) { if (hl_if.layout->api->override_target) { if (hl_if.layout->api->override_target(*targetname)) { *targetname = "hla_target"; return ERROR_OK; } else return ERROR_FAIL; } return ERROR_FAIL; } int hl_interface_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { if (hl_if.layout->api->config_trace) return hl_if.layout->api->config_trace(hl_if.handle, enabled, pin_protocol, port_size, trace_freq); else if (enabled) { LOG_ERROR("The selected interface does not support tracing"); return ERROR_FAIL; } return ERROR_OK; } int hl_interface_poll_trace(uint8_t *buf, size_t *size) { if (hl_if.layout->api->poll_trace) return hl_if.layout->api->poll_trace(hl_if.handle, buf, size); return ERROR_FAIL; } COMMAND_HANDLER(hl_interface_handle_device_desc_command) { LOG_DEBUG("hl_interface_handle_device_desc_command"); if (CMD_ARGC == 1) { hl_if.param.device_desc = strdup(CMD_ARGV[0]); } else { LOG_ERROR("expected exactly one argument to hl_device_desc "); } return ERROR_OK; } COMMAND_HANDLER(hl_interface_handle_serial_command) { LOG_DEBUG("hl_interface_handle_serial_command"); if (CMD_ARGC == 1) { hl_if.param.serial = strdup(CMD_ARGV[0]); } else { LOG_ERROR("expected exactly one argument to hl_serial "); } return ERROR_OK; } COMMAND_HANDLER(hl_interface_handle_layout_command) { LOG_DEBUG("hl_interface_handle_layout_command"); if (CMD_ARGC != 1) { LOG_ERROR("Need exactly one argument to stlink_layout"); return ERROR_COMMAND_SYNTAX_ERROR; } if (hl_if.layout) { LOG_ERROR("already specified hl_layout %s", hl_if.layout->name); return (strcmp(hl_if.layout->name, CMD_ARGV[0]) != 0) ? ERROR_FAIL : ERROR_OK; } for (const struct hl_layout *l = hl_layout_get_list(); l->name; l++) { if (strcmp(l->name, CMD_ARGV[0]) == 0) { hl_if.layout = l; return ERROR_OK; } } LOG_ERROR("No adapter layout '%s' found", CMD_ARGV[0]); return ERROR_FAIL; } COMMAND_HANDLER(hl_interface_handle_vid_pid_command) { LOG_DEBUG("hl_interface_handle_vid_pid_command"); if (CMD_ARGC != 2) { LOG_WARNING("ignoring extra IDs in hl_vid_pid (maximum is 1 pair)"); return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], hl_if.param.vid); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], hl_if.param.pid); return ERROR_OK; } COMMAND_HANDLER(interface_handle_hla_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; if (!hl_if.layout->api->custom_command) { LOG_ERROR("The selected adapter doesn't support custom commands"); return ERROR_FAIL; } hl_if.layout->api->custom_command(hl_if.handle, CMD_ARGV[0]); return ERROR_OK; } static const struct command_registration hl_interface_command_handlers[] = { { .name = "hla_device_desc", .handler = &hl_interface_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the a device description of the adapter", .usage = "description_string", }, { .name = "hla_serial", .handler = &hl_interface_handle_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the adapter", .usage = "serial_string", }, { .name = "hla_layout", .handler = &hl_interface_handle_layout_command, .mode = COMMAND_CONFIG, .help = "set the layout of the adapter", .usage = "layout_name", }, { .name = "hla_vid_pid", .handler = &hl_interface_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor and product ID of the adapter", .usage = "(vid pid)* ", }, { .name = "hla_command", .handler = &interface_handle_hla_command, .mode = COMMAND_EXEC, .help = "execute a custom adapter-specific command", .usage = "hla_command ", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface hl_interface = { .name = "hla", .supported = 0, .commands = hl_interface_command_handlers, .transports = hl_transports, .init = hl_interface_init, .quit = hl_interface_quit, .execute_queue = hl_interface_execute_queue, .speed = &hl_interface_speed, .khz = &hl_interface_khz, .speed_div = &hl_interface_speed_div, .config_trace = &hl_interface_config_trace, .poll_trace = &hl_interface_poll_trace, }; openocd-0.9.0/src/jtag/hla/hla_interface.h0000644000175000017500000000472512516456303015322 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _HL_INTERFACE #define _HL_INTERFACE /** */ struct target; /** */ enum e_hl_transports; /** */ extern const char *hl_transports[]; struct hl_interface_param_s { /** */ const char *device_desc; /** */ const char *serial; /** */ uint16_t vid; /** */ uint16_t pid; /** */ unsigned api; /** */ enum hl_transports transport; /** */ bool connect_under_reset; /** Initial interface clock clock speed */ int initial_interface_speed; }; struct hl_interface_s { /** */ struct hl_interface_param_s param; /** */ const struct hl_layout *layout; /** */ void *handle; }; /** */ int hl_interface_open(enum hl_transports tr); /** */ int hl_interface_init_target(struct target *t); int hl_interface_init_reset(void); int hl_interface_override_target(const char **targetname); #endif /* _HL_INTERFACE */ openocd-0.9.0/src/jtag/aice/0000755000175000017500000000000012526202224012562 500000000000000openocd-0.9.0/src/jtag/aice/aice_transport.c0000644000175000017500000002333312315575360015701 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include /* */ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, struct jtag_tap *pTap) { jim_wide w; int e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) { Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name); return e; } unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt; uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t)); if (new_expected_ids == NULL) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } memcpy(new_expected_ids, pTap->expected_ids, expected_len); new_expected_ids[pTap->expected_ids_cnt] = w; free(pTap->expected_ids); pTap->expected_ids = new_expected_ids; pTap->expected_ids_cnt++; return JIM_OK; } #define NTAP_OPT_EXPECTED_ID 0 /* */ static int jim_aice_newtap_cmd(Jim_GetOptInfo *goi) { struct jtag_tap *pTap; int x; int e; Jim_Nvp *n; char *cp; const Jim_Nvp opts[] = { {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID}, {.name = NULL, .value = -1}, }; pTap = calloc(1, sizeof(struct jtag_tap)); if (!pTap) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } /* * we expect CHIP + TAP + OPTIONS * */ if (goi->argc < 3) { Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ...."); free(pTap); return JIM_ERR; } Jim_GetOpt_String(goi, &cp, NULL); pTap->chip = strdup(cp); Jim_GetOpt_String(goi, &cp, NULL); pTap->tapname = strdup(cp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; cp = malloc(x); sprintf(cp, "%s.%s", pTap->chip, pTap->tapname); pTap->dotted_name = cp; LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); while (goi->argc) { e = Jim_GetOpt_Nvp(goi, opts, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, opts, 0); free(cp); free(pTap); return e; } LOG_DEBUG("Processing option: %s", n->name); switch (n->value) { case NTAP_OPT_EXPECTED_ID: e = jim_newtap_expected_id(n, goi, pTap); if (JIM_OK != e) { free(cp); free(pTap); return e; } break; } /* switch (n->value) */ } /* while (goi->argc) */ /* default is enabled-after-reset */ pTap->enabled = !pTap->disabled_after_reset; jtag_tap_init(pTap); return JIM_OK; } /* */ static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); return jim_aice_newtap_cmd(&goi); } /* */ COMMAND_HANDLER(handle_aice_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool jtag_initialized; if (jtag_initialized) { LOG_INFO("'jtag init' has already been called"); return ERROR_OK; } jtag_initialized = true; LOG_DEBUG("Initializing jtag devices..."); return jtag_init(CMD_CTX); } static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { LOG_DEBUG("No implement: jim_aice_arp_init"); return JIM_OK; } /* */ static int aice_init_reset(struct command_context *cmd_ctx) { LOG_DEBUG("Initializing with hard TRST+SRST reset"); int retval; enum reset_types jtag_reset_config = jtag_get_reset_config(); jtag_add_reset(1, 0); /* TAP_RESET */ if (jtag_reset_config & RESET_HAS_SRST) { jtag_add_reset(1, 1); if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) jtag_add_reset(0, 1); } jtag_add_reset(0, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; return ERROR_OK; } /* */ static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { int e = ERROR_OK; Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)"); return JIM_ERR; } struct command_context *context = current_command_context(interp); e = aice_init_reset(context); if (e != ERROR_OK) { Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); Jim_FreeNewObj(goi.interp, eObj); return JIM_ERR; } return JIM_OK; } static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters"); return JIM_ERR; } Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0)); struct jtag_tap *tap; for (tap = jtag_all_taps(); tap; tap = tap->next_tap) Jim_ListAppendElement(goi.interp, Jim_GetResult(goi.interp), Jim_NewStringObj(goi.interp, tap->dotted_name, -1)); return JIM_OK; } /* */ static const struct command_registration aice_transport_jtag_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_ANY, .handler = handle_aice_init_command, .help = "initialize jtag scan chain", .usage = "" }, { .name = "arp_init", .mode = COMMAND_ANY, .jim_handler = jim_aice_arp_init, .help = "Validates JTAG scan chain against the list of " "declared TAPs.", }, { .name = "arp_init-reset", .mode = COMMAND_ANY, .jim_handler = jim_aice_arp_init_reset, .help = "Uses TRST and SRST to try resetting everything on " "the JTAG scan chain, then performs 'jtag arp_init'." }, { .name = "newtap", .mode = COMMAND_CONFIG, .jim_handler = jim_aice_newtap, .help = "Create a new TAP instance named basename.tap_type, " "and appends it to the scan chain.", .usage = "basename tap_type ['-expected_id' number]" }, { .name = "tapisenabled", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Returns a Tcl boolean (0/1) indicating whether " "the TAP is enabled (1) or not (0).", .usage = "tap_name", }, { .name = "tapenable", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Try to enable the specified TAP using the " "'tap-enable' TAP event.", .usage = "tap_name", }, { .name = "tapdisable", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Try to disable the specified TAP using the " "'tap-disable' TAP event.", .usage = "tap_name", }, { .name = "configure", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_configure, .help = "Provide a Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name handler", }, { .name = "cget", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_configure, .help = "Return any Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name", }, { .name = "names", .mode = COMMAND_ANY, .jim_handler = jim_aice_names, .help = "Returns list of all JTAG tap names.", }, COMMAND_REGISTRATION_DONE }; /* */ static const struct command_registration aice_transport_command_handlers[] = { { .name = "jtag", .mode = COMMAND_ANY, .usage = "", .chain = aice_transport_jtag_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; /* */ static int aice_transport_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, aice_transport_command_handlers); } /* */ static int aice_transport_init(struct command_context *cmd_ctx) { LOG_DEBUG("aice_transport_init"); struct target *t = get_current_target(cmd_ctx); struct transport *transport; if (!t) { LOG_ERROR("no current target"); return ERROR_FAIL; } transport = get_current_transport(); if (!transport) { LOG_ERROR("no transport selected"); return ERROR_FAIL; } LOG_DEBUG("current transport %s", transport->name); return aice_init_targets(); } /* */ static int aice_transport_select(struct command_context *ctx) { LOG_DEBUG("aice_transport_select"); int retval; retval = aice_transport_register_commands(ctx); if (retval != ERROR_OK) return retval; return ERROR_OK; } static struct transport aice_jtag_transport = { .name = "aice_jtag", .select = aice_transport_select, .init = aice_transport_init, }; const char *aice_transports[] = { "aice_jtag", NULL }; static void aice_constructor(void) __attribute__((constructor)); static void aice_constructor(void) { transport_register(&aice_jtag_transport); } openocd-0.9.0/src/jtag/aice/aice_transport.h0000644000175000017500000000303212315575360015700 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _AICE_TRANSPORT_ #define _AICE_TRANSPORT_ extern const char *aice_transports[]; #endif openocd-0.9.0/src/jtag/aice/aice_pipe.c0000644000175000017500000004662612315575360014614 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef _WIN32 #include #else #include #endif #include #include #include "aice_port.h" #include "aice_pipe.h" #define AICE_PIPE_MAXLINE 8192 #ifdef _WIN32 PROCESS_INFORMATION proc_info; HANDLE aice_pipe_output[2]; HANDLE aice_pipe_input[2]; static int aice_pipe_write(const void *buffer, int count) { BOOL success; DWORD written; success = WriteFile(aice_pipe_output[1], buffer, count, &written, NULL); if (!success) { LOG_ERROR("(WIN32) write to pipe failed, error code: 0x%08l" PRIx32, GetLastError()); return -1; } return written; } static int aice_pipe_read(void *buffer, int count) { BOOL success; DWORD has_read; success = ReadFile(aice_pipe_input[0], buffer, count, &has_read, NULL); if (!success || (has_read == 0)) { LOG_ERROR("(WIN32) read from pipe failed, error code: 0x%08l" PRIx32, GetLastError()); return -1; } return has_read; } static int aice_pipe_child_init(struct aice_port_param_s *param) { STARTUPINFO start_info; BOOL success; ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION)); ZeroMemory(&start_info, sizeof(STARTUPINFO)); start_info.cb = sizeof(STARTUPINFO); start_info.hStdError = aice_pipe_input[1]; start_info.hStdOutput = aice_pipe_input[1]; start_info.hStdInput = aice_pipe_output[0]; start_info.dwFlags |= STARTF_USESTDHANDLES; success = CreateProcess(NULL, param->adapter_name, NULL, NULL, TRUE, 0, NULL, NULL, &start_info, &proc_info); if (!success) { LOG_ERROR("Create new process failed"); return ERROR_FAIL; } return ERROR_OK; } static int aice_pipe_parent_init(struct aice_port_param_s *param) { /* send open to adapter */ char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_OPEN; set_u16(command + 1, param->vid); set_u16(command + 3, param->pid); if (aice_pipe_write(command, 5) != 5) { LOG_ERROR("write failed\n"); return ERROR_FAIL; } if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) { LOG_ERROR("read failed\n"); return ERROR_FAIL; } if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_open(struct aice_port_param_s *param) { SECURITY_ATTRIBUTES attribute; attribute.nLength = sizeof(SECURITY_ATTRIBUTES); attribute.bInheritHandle = TRUE; attribute.lpSecurityDescriptor = NULL; if (!CreatePipe(&aice_pipe_output[0], &aice_pipe_output[1], &attribute, AICE_PIPE_MAXLINE)) { LOG_ERROR("Create pipes failed"); return ERROR_FAIL; } if (!CreatePipe(&aice_pipe_input[0], &aice_pipe_input[1], &attribute, AICE_PIPE_MAXLINE)) { LOG_ERROR("Create pipes failed"); return ERROR_FAIL; } /* do not inherit aice_pipe_output[1] & aice_pipe_input[0] to child process */ if (!SetHandleInformation(aice_pipe_output[1], HANDLE_FLAG_INHERIT, 0)) return ERROR_FAIL; if (!SetHandleInformation(aice_pipe_input[0], HANDLE_FLAG_INHERIT, 0)) return ERROR_FAIL; aice_pipe_child_init(param); aice_pipe_parent_init(param); return ERROR_OK; } #else int aice_pipe_output[2]; int aice_pipe_input[2]; static int aice_pipe_write(const void *buffer, int count) { if (write(aice_pipe_output[1], buffer, count) != count) { LOG_ERROR("write to pipe failed"); return -1; } return count; } static int aice_pipe_read(void *buffer, int count) { int n; long long then, cur; then = timeval_ms(); while (1) { n = read(aice_pipe_input[0], buffer, count); if ((n == -1) && (errno == EAGAIN)) { cur = timeval_ms(); if (cur - then > 500) keep_alive(); continue; } else if (n > 0) break; else { LOG_ERROR("read from pipe failed"); break; } } return n; } static int aice_pipe_child_init(struct aice_port_param_s *param) { close(aice_pipe_output[1]); close(aice_pipe_input[0]); if (aice_pipe_output[0] != STDIN_FILENO) { if (dup2(aice_pipe_output[0], STDIN_FILENO) != STDIN_FILENO) { LOG_ERROR("Map aice_pipe to STDIN failed"); return ERROR_FAIL; } close(aice_pipe_output[0]); } if (aice_pipe_input[1] != STDOUT_FILENO) { if (dup2(aice_pipe_input[1], STDOUT_FILENO) != STDOUT_FILENO) { LOG_ERROR("Map aice_pipe to STDOUT failed"); return ERROR_FAIL; } close(aice_pipe_input[1]); } if (execl(param->adapter_name, param->adapter_name, (char *)0) < 0) { LOG_ERROR("Execute aice_pipe failed"); return ERROR_FAIL; } return ERROR_OK; } static int aice_pipe_parent_init(struct aice_port_param_s *param) { close(aice_pipe_output[0]); close(aice_pipe_input[1]); /* set read end of pipe as non-blocking */ if (fcntl(aice_pipe_input[0], F_SETFL, O_NONBLOCK)) return ERROR_FAIL; /* send open to adapter */ char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_OPEN; set_u16(command + 1, param->vid); set_u16(command + 3, param->pid); if (aice_pipe_write(command, 5) != 5) { LOG_ERROR("write failed\n"); return ERROR_FAIL; } if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) { LOG_ERROR("read failed\n"); return ERROR_FAIL; } if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static void sig_pipe(int signo) { exit(1); } static int aice_pipe_open(struct aice_port_param_s *param) { pid_t pid; if (signal(SIGPIPE, sig_pipe) == SIG_ERR) { LOG_ERROR("Register SIGPIPE handler failed"); return ERROR_FAIL; } if (pipe(aice_pipe_output) < 0 || pipe(aice_pipe_input) < 0) { LOG_ERROR("Create pipes failed"); return ERROR_FAIL; } pid = fork(); if (pid < 0) { LOG_ERROR("Fork new process failed"); return ERROR_FAIL; } else if (pid == 0) { if (aice_pipe_child_init(param) != ERROR_OK) { LOG_ERROR("AICE_PIPE child process initial error"); return ERROR_FAIL; } else { if (aice_pipe_parent_init(param) != ERROR_OK) { LOG_ERROR("AICE_PIPE parent process initial error"); return ERROR_FAIL; } } } return ERROR_OK; } #endif static int aice_pipe_close(void) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_CLOSE; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) { #ifdef _WIN32 WaitForSingleObject(proc_info.hProcess, INFINITE); CloseHandle(proc_info.hProcess); CloseHandle(proc_info.hThread); #endif return ERROR_OK; } else return ERROR_FAIL; } static int aice_pipe_idcode(uint32_t *idcode, uint8_t *num_of_idcode) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_IDCODE; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; *num_of_idcode = line[0]; if ((*num_of_idcode == 0) || (*num_of_idcode >= 16)) return ERROR_FAIL; for (int i = 0 ; i < *num_of_idcode ; i++) idcode[i] = get_u32(line + i * 4 + 1); return ERROR_OK; } static int aice_pipe_state(uint32_t coreid, enum aice_target_state_s *state) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_STATE; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; *state = (enum aice_target_state_s)line[0]; return ERROR_OK; } static int aice_pipe_reset(void) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_RESET; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_assert_srst(uint32_t coreid, enum aice_srst_type_s srst) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_ASSERT_SRST; command[1] = srst; if (aice_pipe_write(command, 2) != 2) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_run(uint32_t coreid) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_RUN; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_halt(uint32_t coreid) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_HALT; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_read_reg(uint32_t coreid, uint32_t num, uint32_t *val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_READ_REG; set_u32(command + 1, num); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; *val = get_u32(line); return ERROR_OK; } static int aice_pipe_write_reg(uint32_t coreid, uint32_t num, uint32_t val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_WRITE_REG; set_u32(command + 1, num); set_u32(command + 5, val); if (aice_pipe_write(command, 9) != 9) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_READ_REG_64; set_u32(command + 1, num); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; *val = (((uint64_t)get_u32(line + 4)) << 32) | get_u32(line); return ERROR_OK; } static int aice_pipe_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_WRITE_REG_64; set_u32(command + 1, num); set_u32(command + 5, val & 0xFFFFFFFF); set_u32(command + 9, (val >> 32) & 0xFFFFFFFF); if (aice_pipe_write(command, 13) != 9) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_step(uint32_t coreid) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_STEP; if (aice_pipe_write(command, 1) != 1) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_read_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { char command[AICE_PIPE_MAXLINE]; command[0] = AICE_READ_MEM_UNIT; set_u32(command + 1, addr); set_u32(command + 5, size); set_u32(command + 9, count); if (aice_pipe_write(command, 13) != 13) return ERROR_FAIL; if (aice_pipe_read(buffer, size * count) < 0) return ERROR_FAIL; return ERROR_OK; } static int aice_pipe_write_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_WRITE_MEM_UNIT; set_u32(command + 1, addr); set_u32(command + 5, size); set_u32(command + 9, count); /* WRITE_MEM_UNIT|addr|size|count|data */ memcpy(command + 13, buffer, size * count); if (aice_pipe_write(command, 13 + size * count) < 0) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; return ERROR_OK; } static int aice_pipe_read_mem_bulk(uint32_t coreid, uint32_t addr, uint32_t length, uint8_t *buffer) { char line[AICE_PIPE_MAXLINE + 1]; char command[AICE_PIPE_MAXLINE]; uint32_t remain_len = length; uint32_t prepare_len; char *received_line; uint32_t received_len; int read_len; command[0] = AICE_READ_MEM_BULK; set_u32(command + 1, addr); set_u32(command + 5, length); if (aice_pipe_write(command, 9) < 0) return ERROR_FAIL; while (remain_len > 0) { if (remain_len > AICE_PIPE_MAXLINE) prepare_len = AICE_PIPE_MAXLINE; else prepare_len = remain_len; prepare_len++; received_len = 0; received_line = line; do { read_len = aice_pipe_read(received_line, prepare_len - received_len); if (read_len < 0) return ERROR_FAIL; received_line += read_len; received_len += read_len; } while (received_len < prepare_len); if (line[0] != AICE_OK) return ERROR_FAIL; prepare_len--; memcpy(buffer, line + 1, prepare_len); remain_len -= prepare_len; buffer += prepare_len; } return ERROR_OK; } static int aice_pipe_write_mem_bulk(uint32_t coreid, uint32_t addr, uint32_t length, const uint8_t *buffer) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE + 4]; uint32_t remain_len = length; uint32_t written_len = 0; uint32_t write_len; command[0] = AICE_WRITE_MEM_BULK; set_u32(command + 1, addr); set_u32(command + 5, length); /* Send command first */ if (aice_pipe_write(command, 9) < 0) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_ERROR) return ERROR_FAIL; while (remain_len > 0) { if (remain_len > AICE_PIPE_MAXLINE) write_len = AICE_PIPE_MAXLINE; else write_len = remain_len; set_u32(command, write_len); memcpy(command + 4, buffer + written_len, write_len); /* data only */ if (aice_pipe_write(command, write_len + 4) < 0) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_ERROR) return ERROR_FAIL; remain_len -= write_len; written_len += write_len; } if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_READ_DEBUG_REG; set_u32(command + 1, addr); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; *val = get_u32(line); return ERROR_OK; } static int aice_pipe_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_WRITE_DEBUG_REG; set_u32(command + 1, addr); set_u32(command + 5, val); if (aice_pipe_write(command, 9) != 9) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_set_jtag_clock(uint32_t a_clock) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_SET_JTAG_CLOCK; set_u32(command + 1, a_clock); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_memory_access(uint32_t coreid, enum nds_memory_access access_channel) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_MEMORY_ACCESS; set_u32(command + 1, access_channel); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_select) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_MEMORY_MODE; set_u32(command + 1, mem_select); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_READ_TLB; set_u32(command + 1, virtual_address); if (aice_pipe_write(command, 5) != 5) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) { *physical_address = get_u32(line + 1); return ERROR_OK; } else return ERROR_FAIL; } static int aice_pipe_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; command[0] = AICE_CACHE_CTL; set_u32(command + 1, subtype); set_u32(command + 5, address); if (aice_pipe_write(command, 9) != 9) return ERROR_FAIL; if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) return ERROR_FAIL; if (line[0] == AICE_OK) return ERROR_OK; else return ERROR_FAIL; } static int aice_pipe_set_retry_times(uint32_t a_retry_times) { return ERROR_OK; } /** */ struct aice_port_api_s aice_pipe = { /** */ .open = aice_pipe_open, /** */ .close = aice_pipe_close, /** */ .idcode = aice_pipe_idcode, /** */ .set_jtag_clock = aice_pipe_set_jtag_clock, /** */ .state = aice_pipe_state, /** */ .reset = aice_pipe_reset, /** */ .assert_srst = aice_pipe_assert_srst, /** */ .run = aice_pipe_run, /** */ .halt = aice_pipe_halt, /** */ .step = aice_pipe_step, /** */ .read_reg = aice_pipe_read_reg, /** */ .write_reg = aice_pipe_write_reg, /** */ .read_reg_64 = aice_pipe_read_reg_64, /** */ .write_reg_64 = aice_pipe_write_reg_64, /** */ .read_mem_unit = aice_pipe_read_mem_unit, /** */ .write_mem_unit = aice_pipe_write_mem_unit, /** */ .read_mem_bulk = aice_pipe_read_mem_bulk, /** */ .write_mem_bulk = aice_pipe_write_mem_bulk, /** */ .read_debug_reg = aice_pipe_read_debug_reg, /** */ .write_debug_reg = aice_pipe_write_debug_reg, /** */ .memory_access = aice_pipe_memory_access, /** */ .memory_mode = aice_pipe_memory_mode, /** */ .read_tlb = aice_pipe_read_tlb, /** */ .cache_ctl = aice_pipe_cache_ctl, /** */ .set_retry_times = aice_pipe_set_retry_times, }; openocd-0.9.0/src/jtag/aice/aice_pipe.h0000644000175000017500000000346612315575360014614 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _AICE_PIPE_H_ #define _AICE_PIPE_H_ #include #define set_u32(buffer, value) h_u32_to_le((uint8_t *)buffer, value) #define set_u16(buffer, value) h_u16_to_le((uint8_t *)buffer, value) #define get_u32(buffer) le_to_h_u32((const uint8_t *)buffer) #define get_u16(buffer) le_to_h_u16((const uint8_t *)buffer) extern struct aice_port_api_s aice_pipe; #endif openocd-0.9.0/src/jtag/aice/aice_port.c0000644000175000017500000000362412315575360014632 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "aice_usb.h" #include "aice_pipe.h" #include "aice_port.h" static const struct aice_port aice_ports[] = { { .name = "aice_usb", .type = AICE_PORT_AICE_USB, .api = &aice_usb_api, }, { .name = "aice_pipe", .type = AICE_PORT_AICE_PIPE, .api = &aice_pipe, }, {.name = NULL, /* END OF TABLE */ }, }; /** */ const struct aice_port *aice_port_get_list(void) { return aice_ports; } openocd-0.9.0/src/jtag/aice/aice_port.h0000644000175000017500000001405012516456302014627 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _AICE_PORT_H_ #define _AICE_PORT_H_ #include #define AICE_MAX_NUM_CORE (0x10) #define ERROR_AICE_DISCONNECT (-200) #define ERROR_AICE_TIMEOUT (-201) enum aice_target_state_s { AICE_DISCONNECT = 0, AICE_TARGET_DETACH, AICE_TARGET_UNKNOWN, AICE_TARGET_RUNNING, AICE_TARGET_HALTED, AICE_TARGET_RESET, AICE_TARGET_DEBUG_RUNNING, }; enum aice_srst_type_s { AICE_SRST = 0x1, AICE_RESET_HOLD = 0x8, }; enum aice_target_endian { AICE_LITTLE_ENDIAN = 0, AICE_BIG_ENDIAN, }; enum aice_api_s { AICE_OPEN = 0x0, AICE_CLOSE, AICE_RESET, AICE_IDCODE, AICE_SET_JTAG_CLOCK, AICE_ASSERT_SRST, AICE_RUN, AICE_HALT, AICE_STEP, AICE_READ_REG, AICE_WRITE_REG, AICE_READ_REG_64, AICE_WRITE_REG_64, AICE_READ_MEM_UNIT, AICE_WRITE_MEM_UNIT, AICE_READ_MEM_BULK, AICE_WRITE_MEM_BULK, AICE_READ_DEBUG_REG, AICE_WRITE_DEBUG_REG, AICE_STATE, AICE_MEMORY_ACCESS, AICE_MEMORY_MODE, AICE_READ_TLB, AICE_CACHE_CTL, AICE_SET_RETRY_TIMES, AICE_PROGRAM_EDM, AICE_SET_COMMAND_MODE, AICE_EXECUTE, AICE_SET_CUSTOM_SRST_SCRIPT, AICE_SET_CUSTOM_TRST_SCRIPT, AICE_SET_CUSTOM_RESTART_SCRIPT, AICE_SET_COUNT_TO_CHECK_DBGER, AICE_SET_DATA_ENDIAN, }; enum aice_error_s { AICE_OK, AICE_ACK, AICE_ERROR, }; enum aice_cache_ctl_type { AICE_CACHE_CTL_L1D_INVALALL = 0, AICE_CACHE_CTL_L1D_VA_INVAL, AICE_CACHE_CTL_L1D_WBALL, AICE_CACHE_CTL_L1D_VA_WB, AICE_CACHE_CTL_L1I_INVALALL, AICE_CACHE_CTL_L1I_VA_INVAL, }; enum aice_command_mode { AICE_COMMAND_MODE_NORMAL, AICE_COMMAND_MODE_PACK, AICE_COMMAND_MODE_BATCH, }; struct aice_port_param_s { /** */ const char *device_desc; /** */ const char *serial; /** */ uint16_t vid; /** */ uint16_t pid; /** */ char *adapter_name; }; struct aice_port_s { /** */ uint32_t coreid; /** */ const struct aice_port *port; }; /** */ extern struct aice_port_api_s aice_usb_layout_api; /** */ struct aice_port_api_s { /** */ int (*open)(struct aice_port_param_s *param); /** */ int (*close)(void); /** */ int (*reset)(void); /** */ int (*idcode)(uint32_t *idcode, uint8_t *num_of_idcode); /** */ int (*set_jtag_clock)(uint32_t a_clock); /** */ int (*assert_srst)(uint32_t coreid, enum aice_srst_type_s srst); /** */ int (*run)(uint32_t coreid); /** */ int (*halt)(uint32_t coreid); /** */ int (*step)(uint32_t coreid); /** */ int (*read_reg)(uint32_t coreid, uint32_t num, uint32_t *val); /** */ int (*write_reg)(uint32_t coreid, uint32_t num, uint32_t val); /** */ int (*read_reg_64)(uint32_t coreid, uint32_t num, uint64_t *val); /** */ int (*write_reg_64)(uint32_t coreid, uint32_t num, uint64_t val); /** */ int (*read_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer); /** */ int (*write_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer); /** */ int (*read_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length, uint8_t *buffer); /** */ int (*write_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length, const uint8_t *buffer); /** */ int (*read_debug_reg)(uint32_t coreid, uint32_t addr, uint32_t *val); /** */ int (*write_debug_reg)(uint32_t coreid, uint32_t addr, const uint32_t val); /** */ int (*state)(uint32_t coreid, enum aice_target_state_s *state); /** */ int (*memory_access)(uint32_t coreid, enum nds_memory_access a_access); /** */ int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select); /** */ int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address); /** */ int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address); /** */ int (*set_retry_times)(uint32_t a_retry_times); /** */ int (*program_edm)(uint32_t coreid, char *command_sequence); /** */ int (*set_command_mode)(enum aice_command_mode command_mode); /** */ int (*execute)(uint32_t coreid, uint32_t *instructions, uint32_t instruction_num); /** */ int (*set_custom_srst_script)(const char *script); /** */ int (*set_custom_trst_script)(const char *script); /** */ int (*set_custom_restart_script)(const char *script); /** */ int (*set_count_to_check_dbger)(uint32_t count_to_check); /** */ int (*set_data_endian)(uint32_t coreid, enum aice_target_endian target_data_endian); /** */ int (*profiling)(uint32_t coreid, uint32_t interval, uint32_t iteration, uint32_t reg_no, uint32_t *samples, uint32_t *num_samples); }; #define AICE_PORT_UNKNOWN 0 #define AICE_PORT_AICE_USB 1 #define AICE_PORT_AICE_PIPE 2 /** */ struct aice_port { /** */ const char *name; /** */ int type; /** */ struct aice_port_api_s *const api; }; /** */ const struct aice_port *aice_port_get_list(void); #endif openocd-0.9.0/src/jtag/aice/Makefile.am0000644000175000017500000000077012315575360014554 00000000000000include $(top_srcdir)/common.mk AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) noinst_LTLIBRARIES = libocdaice.la libocdaice_la_SOURCES = \ $(AICEFILES) AICEFILES = if AICE AICEFILES += aice_transport.c AICEFILES += aice_interface.c AICEFILES += aice_port.c AICEFILES += aice_usb.c AICEFILES += aice_pipe.c endif noinst_HEADERS = \ aice_transport.h \ aice_interface.h \ aice_port.h \ aice_usb.h \ aice_pipe.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/jtag/aice/Makefile.in0000644000175000017500000004536512526201650014566 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @AICE_TRUE@am__append_2 = aice_transport.c aice_interface.c \ @AICE_TRUE@ aice_port.c aice_usb.c aice_pipe.c subdir = src/jtag/aice ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdaice_la_LIBADD = am__libocdaice_la_SOURCES_DIST = aice_transport.c aice_interface.c \ aice_port.c aice_usb.c aice_pipe.c @AICE_TRUE@am__objects_1 = aice_transport.lo aice_interface.lo \ @AICE_TRUE@ aice_port.lo aice_usb.lo aice_pipe.lo am__objects_2 = $(am__objects_1) am_libocdaice_la_OBJECTS = $(am__objects_2) libocdaice_la_OBJECTS = $(am_libocdaice_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdaice_la_SOURCES) DIST_SOURCES = $(am__libocdaice_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) \ -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) \ $(LIBUSB0_CFLAGS) noinst_LTLIBRARIES = libocdaice.la libocdaice_la_SOURCES = \ $(AICEFILES) AICEFILES = $(am__append_2) noinst_HEADERS = \ aice_transport.h \ aice_interface.h \ aice_port.h \ aice_usb.h \ aice_pipe.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/jtag/aice/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/jtag/aice/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libocdaice.la: $(libocdaice_la_OBJECTS) $(libocdaice_la_DEPENDENCIES) $(EXTRA_libocdaice_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdaice_la_OBJECTS) $(libocdaice_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aice_interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aice_pipe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aice_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aice_transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aice_usb.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/aice/aice_interface.c0000644000175000017500000003140412516456302015600 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "aice_usb.h" #define AICE_KHZ_TO_SPEED_MAP_SIZE 16 static const int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = { 30000, 15000, 7500, 3750, 1875, 937, 468, 234, 48000, 24000, 12000, 6000, 3000, 1500, 750, 375, }; static const struct aice_port *aice_port; static struct aice_port_param_s param; static uint32_t retry_times; static uint32_t count_to_check_dbger; /***************************************************************************/ /* External interface implementation */ static uint32_t aice_target_id_codes[AICE_MAX_NUM_CORE]; static uint8_t aice_num_of_target_id_codes; /***************************************************************************/ /* AICE operations */ int aice_init_targets(void) { int res; struct target *target; struct aice_port_s *aice; LOG_DEBUG("aice_init_targets"); if (aice_num_of_target_id_codes == 0) { res = aice_port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes); if (res != ERROR_OK) { LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore " "JTAG Manufacture ID in the JTAG scan chain. " "Failed to access EDM registers. -->"); return res; } } for (target = all_targets; target; target = target->next) { target->tap->idcode = aice_target_id_codes[target->tap->abs_chain_position]; unsigned ii, limit = target->tap->expected_ids_cnt; int found = 0; for (ii = 0; ii < limit; ii++) { uint32_t expected = target->tap->expected_ids[ii]; /* treat "-expected-id 0" as a "don't-warn" wildcard */ if (!expected || (target->tap->idcode == expected)) { found = 1; break; } } if (found == 0) { LOG_ERROR ("aice_init_targets: target not found: idcode: %" PRIx32, target->tap->idcode); return ERROR_FAIL; } aice = calloc(1, sizeof(struct aice_port_s)); aice->port = aice_port; aice->coreid = target->tap->abs_chain_position; target->tap->priv = aice; target->tap->hasidcode = 1; } return ERROR_OK; } /***************************************************************************/ /* End of External interface implementation */ /* initial aice * 1. open usb * 2. get/show version number * 3. reset */ static int aice_init(void) { if (ERROR_OK != aice_port->api->open(¶m)) { LOG_ERROR("Cannot find AICE Interface! Please check " "connection and permissions."); return ERROR_JTAG_INIT_FAILED; } aice_port->api->set_retry_times(retry_times); aice_port->api->set_count_to_check_dbger(count_to_check_dbger); LOG_INFO("AICE JTAG Interface ready"); return ERROR_OK; } /* cleanup aice resource * close usb */ static int aice_quit(void) { aice_port->api->close(); return ERROR_OK; } static int aice_execute_reset(struct jtag_command *cmd) { static int last_trst; int retval = ERROR_OK; DEBUG_JTAG_IO("reset trst: %d", cmd->cmd.reset->trst); if (cmd->cmd.reset->trst != last_trst) { if (cmd->cmd.reset->trst) retval = aice_port->api->reset(); last_trst = cmd->cmd.reset->trst; } return retval; } static int aice_execute_command(struct jtag_command *cmd) { int retval; switch (cmd->type) { case JTAG_RESET: retval = aice_execute_reset(cmd); break; default: retval = ERROR_OK; break; } return retval; } /* aice has no need to implement jtag execution model */ static int aice_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int retval; retval = ERROR_OK; while (cmd) { if (aice_execute_command(cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; cmd = cmd->next; } return retval; } /* set jtag frequency(base frequency/frequency divider) to your jtag adapter */ static int aice_speed(int speed) { return aice_port->api->set_jtag_clock(speed); } /* convert jtag adapter frequency(base frequency/frequency divider) to * human readable KHz value */ static int aice_speed_div(int speed, int *khz) { *khz = aice_khz_to_speed_map[speed]; return ERROR_OK; } /* convert human readable KHz value to jtag adapter frequency * (base frequency/frequency divider) */ static int aice_khz(int khz, int *jtag_speed) { int i; for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) { if (khz == aice_khz_to_speed_map[i]) { if (8 <= i) *jtag_speed = i | AICE_TCK_CONTROL_TCK3048; else *jtag_speed = i; break; } } if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) { LOG_INFO("No support the jtag clock: %d", khz); LOG_INFO("Supported jtag clocks are:"); for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) LOG_INFO("* %d", aice_khz_to_speed_map[i]); return ERROR_FAIL; } return ERROR_OK; } /***************************************************************************/ /* Command handlers */ COMMAND_HANDLER(aice_handle_aice_info_command) { LOG_DEBUG("aice_handle_aice_info_command"); command_print(CMD_CTX, "Description: %s", param.device_desc); command_print(CMD_CTX, "Serial number: %s", param.serial); if (strncmp(aice_port->name, "aice_pipe", 9) == 0) command_print(CMD_CTX, "Adapter: %s", param.adapter_name); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_port_command) { LOG_DEBUG("aice_handle_aice_port_command"); if (CMD_ARGC != 1) { LOG_ERROR("Need exactly one argument to 'aice port'"); return ERROR_COMMAND_SYNTAX_ERROR; } for (const struct aice_port *l = aice_port_get_list(); l->name; l++) { if (strcmp(l->name, CMD_ARGV[0]) == 0) { aice_port = l; return ERROR_OK; } } LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]); return ERROR_FAIL; } COMMAND_HANDLER(aice_handle_aice_desc_command) { LOG_DEBUG("aice_handle_aice_desc_command"); if (CMD_ARGC == 1) param.device_desc = strdup(CMD_ARGV[0]); else LOG_ERROR("expected exactly one argument to aice desc "); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_serial_command) { LOG_DEBUG("aice_handle_aice_serial_command"); if (CMD_ARGC == 1) param.serial = strdup(CMD_ARGV[0]); else LOG_ERROR("expected exactly one argument to aice serial "); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_vid_pid_command) { LOG_DEBUG("aice_handle_aice_vid_pid_command"); if (CMD_ARGC != 2) { LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)"); return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], param.vid); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], param.pid); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_adapter_command) { LOG_DEBUG("aice_handle_aice_adapter_command"); if (CMD_ARGC == 1) param.adapter_name = strdup(CMD_ARGV[0]); else LOG_ERROR("expected exactly one argument to aice adapter "); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_retry_times_command) { LOG_DEBUG("aice_handle_aice_retry_times_command"); if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], retry_times); else LOG_ERROR("expected exactly one argument to aice retry_times "); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command) { LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command"); if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count_to_check_dbger); else LOG_ERROR("expected exactly one argument to aice count_to_check_dbger " ""); return ERROR_OK; } COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command) { LOG_DEBUG("aice_handle_aice_custom_srst_script_command"); if (CMD_ARGC > 0) { aice_port->api->set_custom_srst_script(CMD_ARGV[0]); return ERROR_OK; } return ERROR_FAIL; } COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command) { LOG_DEBUG("aice_handle_aice_custom_trst_script_command"); if (CMD_ARGC > 0) { aice_port->api->set_custom_trst_script(CMD_ARGV[0]); return ERROR_OK; } return ERROR_FAIL; } COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command) { LOG_DEBUG("aice_handle_aice_custom_restart_script_command"); if (CMD_ARGC > 0) { aice_port->api->set_custom_restart_script(CMD_ARGV[0]); return ERROR_OK; } return ERROR_FAIL; } COMMAND_HANDLER(aice_handle_aice_reset_command) { LOG_DEBUG("aice_handle_aice_reset_command"); return aice_port->api->reset(); } static const struct command_registration aice_subcommand_handlers[] = { { .name = "info", .handler = &aice_handle_aice_info_command, .mode = COMMAND_EXEC, .help = "show aice info", .usage = "aice info", }, { .name = "port", .handler = &aice_handle_aice_port_command, .mode = COMMAND_CONFIG, .help = "set the port of the AICE", .usage = "aice port ['aice_pipe'|'aice_usb']", }, { .name = "desc", .handler = &aice_handle_aice_desc_command, .mode = COMMAND_CONFIG, .help = "set the aice device description", .usage = "aice desc [desciption string]", }, { .name = "serial", .handler = &aice_handle_aice_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the AICE device", .usage = "aice serial [serial string]", }, { .name = "vid_pid", .handler = &aice_handle_aice_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor and product ID of the AICE device", .usage = "aice vid_pid (vid pid)*", }, { .name = "adapter", .handler = &aice_handle_aice_adapter_command, .mode = COMMAND_CONFIG, .help = "set the file name of adapter", .usage = "aice adapter [adapter name]", }, { .name = "retry_times", .handler = &aice_handle_aice_retry_times_command, .mode = COMMAND_CONFIG, .help = "set retry times as AICE timeout", .usage = "aice retry_times num_of_retry", }, { .name = "count_to_check_dbger", .handler = &aice_handle_aice_count_to_check_dbger_command, .mode = COMMAND_CONFIG, .help = "set retry times as checking $DBGER status", .usage = "aice count_to_check_dbger count_of_checking", }, { .name = "custom_srst_script", .handler = &aice_handle_aice_custom_srst_script_command, .mode = COMMAND_CONFIG, .usage = "custom_srst_script script_file_name", .help = "set custom srst script", }, { .name = "custom_trst_script", .handler = &aice_handle_aice_custom_trst_script_command, .mode = COMMAND_CONFIG, .usage = "custom_trst_script script_file_name", .help = "set custom trst script", }, { .name = "custom_restart_script", .handler = &aice_handle_aice_custom_restart_script_command, .mode = COMMAND_CONFIG, .usage = "custom_restart_script script_file_name", .help = "set custom restart script", }, { .name = "reset", .handler = &aice_handle_aice_reset_command, .mode = COMMAND_EXEC, .usage = "aice reset", .help = "reset AICE", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration aice_command_handlers[] = { { .name = "aice", .mode = COMMAND_ANY, .help = "perform aice management", .usage = "aice [subcommand]", .chain = aice_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; /***************************************************************************/ /* End of Command handlers */ struct jtag_interface aice_interface = { .name = "aice", .commands = aice_command_handlers, .transports = aice_transports, .init = aice_init, .quit = aice_quit, .execute_queue = aice_execute_queue, .speed = aice_speed, /* set interface speed */ .speed_div = aice_speed_div, /* return readable value */ .khz = aice_khz, /* convert khz to interface speed value */ }; openocd-0.9.0/src/jtag/aice/aice_interface.h0000644000175000017500000000325112516456302015604 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __AICE_INTERFACE_H__ #define __AICE_INTERFACE_H__ struct aice_interface_param_s { /** */ const char *device_desc; /** */ const char *serial; /** */ uint16_t vid; /** */ uint16_t pid; }; int aice_init_targets(void); #endif openocd-0.9.0/src/jtag/aice/aice_usb.c0000644000175000017500000033717612516456302014450 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "aice_usb.h" /* Global USB buffers */ static uint8_t usb_in_buffer[AICE_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[AICE_OUT_BUFFER_SIZE]; static uint32_t jtag_clock; static struct aice_usb_handler_s aice_handler; /* AICE max retry times. If AICE command timeout, retry it. */ static int aice_max_retry_times = 50; /* Default endian is little endian. */ static enum aice_target_endian data_endian; /* Constants for AICE command format length */ static const int32_t AICE_FORMAT_HTDA = 3; static const int32_t AICE_FORMAT_HTDC = 7; static const int32_t AICE_FORMAT_HTDMA = 4; static const int32_t AICE_FORMAT_HTDMB = 8; static const int32_t AICE_FORMAT_HTDMC = 8; static const int32_t AICE_FORMAT_HTDMD = 12; static const int32_t AICE_FORMAT_DTHA = 6; static const int32_t AICE_FORMAT_DTHB = 2; static const int32_t AICE_FORMAT_DTHMA = 8; static const int32_t AICE_FORMAT_DTHMB = 4; /* Constants for AICE command */ static const uint8_t AICE_CMD_SCAN_CHAIN = 0x00; static const uint8_t AICE_CMD_T_READ_MISC = 0x20; static const uint8_t AICE_CMD_T_READ_EDMSR = 0x21; static const uint8_t AICE_CMD_T_READ_DTR = 0x22; static const uint8_t AICE_CMD_T_READ_MEM_B = 0x24; static const uint8_t AICE_CMD_T_READ_MEM_H = 0x25; static const uint8_t AICE_CMD_T_READ_MEM = 0x26; static const uint8_t AICE_CMD_T_FASTREAD_MEM = 0x27; static const uint8_t AICE_CMD_T_WRITE_MISC = 0x28; static const uint8_t AICE_CMD_T_WRITE_EDMSR = 0x29; static const uint8_t AICE_CMD_T_WRITE_DTR = 0x2A; static const uint8_t AICE_CMD_T_WRITE_DIM = 0x2B; static const uint8_t AICE_CMD_T_WRITE_MEM_B = 0x2C; static const uint8_t AICE_CMD_T_WRITE_MEM_H = 0x2D; static const uint8_t AICE_CMD_T_WRITE_MEM = 0x2E; static const uint8_t AICE_CMD_T_FASTWRITE_MEM = 0x2F; static const uint8_t AICE_CMD_T_EXECUTE = 0x3E; static const uint8_t AICE_CMD_READ_CTRL = 0x50; static const uint8_t AICE_CMD_WRITE_CTRL = 0x51; static const uint8_t AICE_CMD_BATCH_BUFFER_READ = 0x60; static const uint8_t AICE_CMD_READ_DTR_TO_BUFFER = 0x61; static const uint8_t AICE_CMD_BATCH_BUFFER_WRITE = 0x68; static const uint8_t AICE_CMD_WRITE_DTR_FROM_BUFFER = 0x69; /***************************************************************************/ /* AICE commands' pack/unpack functions */ static void aice_pack_htda(uint8_t cmd_code, uint8_t extra_word_length, uint32_t address) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = extra_word_length; usb_out_buffer[2] = (uint8_t)(address & 0xFF); } static void aice_pack_htdc(uint8_t cmd_code, uint8_t extra_word_length, uint32_t address, uint32_t word, enum aice_target_endian access_endian) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = extra_word_length; usb_out_buffer[2] = (uint8_t)(address & 0xFF); if (access_endian == AICE_BIG_ENDIAN) { usb_out_buffer[6] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[4] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[3] = (uint8_t)(word & 0xFF); } else { usb_out_buffer[3] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[4] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[6] = (uint8_t)(word & 0xFF); } } static void aice_pack_htdma(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = (uint8_t)(address & 0xFF); } static void aice_pack_htdmb(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = 0; usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF); usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF); usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF); usb_out_buffer[7] = (uint8_t)(address & 0xFF); } static void aice_pack_htdmc(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address, uint32_t word, enum aice_target_endian access_endian) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = (uint8_t)(address & 0xFF); if (access_endian == AICE_BIG_ENDIAN) { usb_out_buffer[7] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[6] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[4] = (uint8_t)(word & 0xFF); } else { usb_out_buffer[4] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[6] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[7] = (uint8_t)(word & 0xFF); } } static void aice_pack_htdmc_multiple_data(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address, uint32_t *word, uint8_t num_of_words, enum aice_target_endian access_endian) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = (uint8_t)(address & 0xFF); uint8_t i; for (i = 0 ; i < num_of_words ; i++, word++) { if (access_endian == AICE_BIG_ENDIAN) { usb_out_buffer[7 + i * 4] = (uint8_t)((*word >> 24) & 0xFF); usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 16) & 0xFF); usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 8) & 0xFF); usb_out_buffer[4 + i * 4] = (uint8_t)(*word & 0xFF); } else { usb_out_buffer[4 + i * 4] = (uint8_t)((*word >> 24) & 0xFF); usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 16) & 0xFF); usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 8) & 0xFF); usb_out_buffer[7 + i * 4] = (uint8_t)(*word & 0xFF); } } } static void aice_pack_htdmd(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address, uint32_t word, enum aice_target_endian access_endian) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = 0; usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF); usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF); usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF); usb_out_buffer[7] = (uint8_t)(address & 0xFF); if (access_endian == AICE_BIG_ENDIAN) { usb_out_buffer[11] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[10] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[9] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[8] = (uint8_t)(word & 0xFF); } else { usb_out_buffer[8] = (uint8_t)((word >> 24) & 0xFF); usb_out_buffer[9] = (uint8_t)((word >> 16) & 0xFF); usb_out_buffer[10] = (uint8_t)((word >> 8) & 0xFF); usb_out_buffer[11] = (uint8_t)(word & 0xFF); } } static void aice_pack_htdmd_multiple_data(uint8_t cmd_code, uint8_t target_id, uint8_t extra_word_length, uint32_t address, const uint8_t *word, enum aice_target_endian access_endian) { usb_out_buffer[0] = cmd_code; usb_out_buffer[1] = target_id; usb_out_buffer[2] = extra_word_length; usb_out_buffer[3] = 0; usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF); usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF); usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF); usb_out_buffer[7] = (uint8_t)(address & 0xFF); uint32_t i; /* num_of_words may be over 0xFF, so use uint32_t */ uint32_t num_of_words = extra_word_length + 1; for (i = 0 ; i < num_of_words ; i++, word += 4) { if (access_endian == AICE_BIG_ENDIAN) { usb_out_buffer[11 + i * 4] = word[3]; usb_out_buffer[10 + i * 4] = word[2]; usb_out_buffer[9 + i * 4] = word[1]; usb_out_buffer[8 + i * 4] = word[0]; } else { usb_out_buffer[8 + i * 4] = word[3]; usb_out_buffer[9 + i * 4] = word[2]; usb_out_buffer[10 + i * 4] = word[1]; usb_out_buffer[11 + i * 4] = word[0]; } } } static void aice_unpack_dtha(uint8_t *cmd_ack_code, uint8_t *extra_word_length, uint32_t *word, enum aice_target_endian access_endian) { *cmd_ack_code = usb_in_buffer[0]; *extra_word_length = usb_in_buffer[1]; if (access_endian == AICE_BIG_ENDIAN) { *word = (usb_in_buffer[5] << 24) | (usb_in_buffer[4] << 16) | (usb_in_buffer[3] << 8) | (usb_in_buffer[2]); } else { *word = (usb_in_buffer[2] << 24) | (usb_in_buffer[3] << 16) | (usb_in_buffer[4] << 8) | (usb_in_buffer[5]); } } static void aice_unpack_dtha_multiple_data(uint8_t *cmd_ack_code, uint8_t *extra_word_length, uint32_t *word, uint8_t num_of_words, enum aice_target_endian access_endian) { *cmd_ack_code = usb_in_buffer[0]; *extra_word_length = usb_in_buffer[1]; uint8_t i; for (i = 0 ; i < num_of_words ; i++, word++) { if (access_endian == AICE_BIG_ENDIAN) { *word = (usb_in_buffer[5 + i * 4] << 24) | (usb_in_buffer[4 + i * 4] << 16) | (usb_in_buffer[3 + i * 4] << 8) | (usb_in_buffer[2 + i * 4]); } else { *word = (usb_in_buffer[2 + i * 4] << 24) | (usb_in_buffer[3 + i * 4] << 16) | (usb_in_buffer[4 + i * 4] << 8) | (usb_in_buffer[5 + i * 4]); } } } static void aice_unpack_dthb(uint8_t *cmd_ack_code, uint8_t *extra_word_length) { *cmd_ack_code = usb_in_buffer[0]; *extra_word_length = usb_in_buffer[1]; } static void aice_unpack_dthma(uint8_t *cmd_ack_code, uint8_t *target_id, uint8_t *extra_word_length, uint32_t *word, enum aice_target_endian access_endian) { *cmd_ack_code = usb_in_buffer[0]; *target_id = usb_in_buffer[1]; *extra_word_length = usb_in_buffer[2]; if (access_endian == AICE_BIG_ENDIAN) { *word = (usb_in_buffer[7] << 24) | (usb_in_buffer[6] << 16) | (usb_in_buffer[5] << 8) | (usb_in_buffer[4]); } else { *word = (usb_in_buffer[4] << 24) | (usb_in_buffer[5] << 16) | (usb_in_buffer[6] << 8) | (usb_in_buffer[7]); } } static void aice_unpack_dthma_multiple_data(uint8_t *cmd_ack_code, uint8_t *target_id, uint8_t *extra_word_length, uint8_t *word, enum aice_target_endian access_endian) { *cmd_ack_code = usb_in_buffer[0]; *target_id = usb_in_buffer[1]; *extra_word_length = usb_in_buffer[2]; if (access_endian == AICE_BIG_ENDIAN) { word[0] = usb_in_buffer[4]; word[1] = usb_in_buffer[5]; word[2] = usb_in_buffer[6]; word[3] = usb_in_buffer[7]; } else { word[0] = usb_in_buffer[7]; word[1] = usb_in_buffer[6]; word[2] = usb_in_buffer[5]; word[3] = usb_in_buffer[4]; } word += 4; uint8_t i; for (i = 0; i < *extra_word_length; i++) { if (access_endian == AICE_BIG_ENDIAN) { word[0] = usb_in_buffer[8 + i * 4]; word[1] = usb_in_buffer[9 + i * 4]; word[2] = usb_in_buffer[10 + i * 4]; word[3] = usb_in_buffer[11 + i * 4]; } else { word[0] = usb_in_buffer[11 + i * 4]; word[1] = usb_in_buffer[10 + i * 4]; word[2] = usb_in_buffer[9 + i * 4]; word[3] = usb_in_buffer[8 + i * 4]; } word += 4; } } static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id, uint8_t *extra_word_length) { *cmd_ack_code = usb_in_buffer[0]; *target_id = usb_in_buffer[1]; *extra_word_length = usb_in_buffer[2]; } /***************************************************************************/ /* End of AICE commands' pack/unpack functions */ /* calls the given usb_bulk_* function, allowing for the data to * trickle in with some timeouts */ static int usb_bulk_with_retries( int (*f)(jtag_libusb_device_handle *, int, char *, int, int), jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { int tries = 3, count = 0; while (tries && (count < size)) { int result = f(dev, ep, bytes + count, size - count, timeout); if (result > 0) count += result; else if ((-ETIMEDOUT != result) || !--tries) return result; } return count; } static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *buff, int size, int timeout) { /* usb_bulk_write() takes const char *buff */ return jtag_libusb_bulk_write(dev, ep, buff, size, timeout); } static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_with_retries(&wrap_usb_bulk_write, dev, ep, bytes, size, timeout); } static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_with_retries(&jtag_libusb_bulk_read, dev, ep, bytes, size, timeout); } /* Write data from out_buffer to USB. */ static int aice_usb_write(uint8_t *out_buffer, int out_length) { int result; if (out_length > AICE_OUT_BUFFER_SIZE) { LOG_ERROR("aice_write illegal out_length=%i (max=%i)", out_length, AICE_OUT_BUFFER_SIZE); return -1; } result = usb_bulk_write_ex(aice_handler.usb_handle, aice_handler.usb_write_ep, (char *)out_buffer, out_length, AICE_USB_TIMEOUT); DEBUG_JTAG_IO("aice_usb_write, out_length = %i, result = %i", out_length, result); return result; } /* Read data from USB into in_buffer. */ static int aice_usb_read(uint8_t *in_buffer, int expected_size) { int32_t result = usb_bulk_read_ex(aice_handler.usb_handle, aice_handler.usb_read_ep, (char *)in_buffer, expected_size, AICE_USB_TIMEOUT); DEBUG_JTAG_IO("aice_usb_read, result = %" PRId32, result); return result; } static uint8_t usb_out_packets_buffer[AICE_OUT_PACKETS_BUFFER_SIZE]; static uint8_t usb_in_packets_buffer[AICE_IN_PACKETS_BUFFER_SIZE]; static uint32_t usb_out_packets_buffer_length; static uint32_t usb_in_packets_buffer_length; static enum aice_command_mode aice_command_mode; static int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word, uint32_t num_of_words); static int aice_usb_packet_flush(void) { if (usb_out_packets_buffer_length == 0) return 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_PACK)"); if (aice_usb_write(usb_out_packets_buffer, usb_out_packets_buffer_length) < 0) return ERROR_FAIL; if (aice_usb_read(usb_in_packets_buffer, usb_in_packets_buffer_length) < 0) return ERROR_FAIL; usb_out_packets_buffer_length = 0; usb_in_packets_buffer_length = 0; } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_BATCH)"); /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */ if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0, usb_out_packets_buffer, (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK) return ERROR_FAIL; usb_out_packets_buffer_length = 0; usb_in_packets_buffer_length = 0; /* enable BATCH command */ aice_command_mode = AICE_COMMAND_MODE_NORMAL; if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL, 0x80000000) != ERROR_OK) return ERROR_FAIL; aice_command_mode = AICE_COMMAND_MODE_BATCH; /* wait 1 second (AICE bug, workaround) */ alive_sleep(1000); /* check status */ uint32_t i; uint32_t batch_status; i = 0; while (1) { aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status); if (batch_status & 0x1) return ERROR_OK; else if (batch_status & 0xE) return ERROR_FAIL; if ((i % 30) == 0) keep_alive(); i++; } } return ERROR_OK; } static int aice_usb_packet_append(uint8_t *out_buffer, int out_length, int in_length) { uint32_t max_packet_size = AICE_OUT_PACKETS_BUFFER_SIZE; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { max_packet_size = AICE_OUT_PACK_COMMAND_SIZE; } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { max_packet_size = AICE_OUT_BATCH_COMMAND_SIZE; } else { /* AICE_COMMAND_MODE_NORMAL */ if (aice_usb_packet_flush() != ERROR_OK) return ERROR_FAIL; } if (usb_out_packets_buffer_length + out_length > max_packet_size) if (aice_usb_packet_flush() != ERROR_OK) { LOG_DEBUG("Flush usb packets failed"); return ERROR_FAIL; } LOG_DEBUG("Append usb packets 0x%02x", out_buffer[0]); memcpy(usb_out_packets_buffer + usb_out_packets_buffer_length, out_buffer, out_length); usb_out_packets_buffer_length += out_length; usb_in_packets_buffer_length += in_length; return ERROR_OK; } /***************************************************************************/ /* AICE commands */ static int aice_reset_box(void) { if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK) return ERROR_FAIL; /* turn off FASTMODE */ uint32_t pin_status; if (aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status) != ERROR_OK) return ERROR_FAIL; if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x2)) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htda(AICE_CMD_SCAN_CHAIN, 0x0F, 0x0); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA); LOG_DEBUG("SCAN_CHAIN, length: 0x0F"); /** TODO: modify receive length */ result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA); if (AICE_FORMAT_DTHA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")", AICE_FORMAT_DTHA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; aice_unpack_dtha_multiple_data(&cmd_ack_code, num_of_ids, id_codes, 0x10, AICE_LITTLE_ENDIAN); if (cmd_ack_code != AICE_CMD_SCAN_CHAIN) { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_SCAN_CHAIN, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; continue; } LOG_DEBUG("SCAN_CHAIN response, # of IDs: %" PRIu8, *num_of_ids); if (*num_of_ids == 0xFF) { LOG_ERROR("No target connected"); return ERROR_FAIL; } else if (*num_of_ids == AICE_MAX_NUM_CORE) { LOG_INFO("The ice chain over 16 targets"); } else { (*num_of_ids)++; } break; } while (1); return ERROR_OK; } int aice_read_ctrl(uint32_t address, uint32_t *data) { int32_t result; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); aice_pack_htda(AICE_CMD_READ_CTRL, 0, address); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA); LOG_DEBUG("READ_CTRL, address: 0x%" PRIx32, address); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA); if (AICE_FORMAT_DTHA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")", AICE_FORMAT_DTHA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; aice_unpack_dtha(&cmd_ack_code, &extra_length, data, AICE_LITTLE_ENDIAN); LOG_DEBUG("READ_CTRL response, data: 0x%" PRIx32, *data); if (cmd_ack_code != AICE_CMD_READ_CTRL) { LOG_ERROR("aice command error (command=0x%" PRIx32 ", response=0x%" PRIx8 ")", (uint32_t)AICE_CMD_READ_CTRL, cmd_ack_code); return ERROR_FAIL; } return ERROR_OK; } int aice_write_ctrl(uint32_t address, uint32_t data) { int32_t result; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDC, AICE_FORMAT_DTHB); } aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDC); LOG_DEBUG("WRITE_CTRL, address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, data); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHB); if (AICE_FORMAT_DTHB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")", AICE_FORMAT_DTHB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; aice_unpack_dthb(&cmd_ack_code, &extra_length); LOG_DEBUG("WRITE_CTRL response"); if (cmd_ack_code != AICE_CMD_WRITE_CTRL) { LOG_ERROR("aice command error (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_WRITE_CTRL, cmd_ack_code); return ERROR_FAIL; } return ERROR_OK; } int aice_read_dtr(uint8_t target_id, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdma(AICE_CMD_T_READ_DTR, target_id, 0, 0); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("READ_DTR, COREID: %" PRIu8, target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, AICE_LITTLE_ENDIAN); if (cmd_ack_code == AICE_CMD_T_READ_DTR) { LOG_DEBUG("READ_DTR response, data: 0x%" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_DTR, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_dtr_to_buffer(uint8_t target_id, uint32_t buffer_idx) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA, AICE_FORMAT_DTHMB); } do { aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("READ_DTR_TO_BUFFER, COREID: %" PRIu8, target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_READ_DTR_TO_BUFFER) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_READ_DTR_TO_BUFFER, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_write_dtr(uint8_t target_id, uint32_t data) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC, AICE_FORMAT_DTHMB); } do { aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC); LOG_DEBUG("WRITE_DTR, COREID: %" PRIu8 ", data: 0x%" PRIx32, target_id, data); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_DTR) { LOG_DEBUG("WRITE_DTR response"); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_DTR, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_write_dtr_from_buffer(uint8_t target_id, uint32_t buffer_idx) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA, AICE_FORMAT_DTHMB); } do { aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("WRITE_DTR_FROM_BUFFER, COREID: %" PRIu8 "", target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_WRITE_DTR_FROM_BUFFER) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_WRITE_DTR_FROM_BUFFER, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdma(AICE_CMD_T_READ_MISC, target_id, 0, address); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("READ_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_AICE_DISCONNECT; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, AICE_LITTLE_ENDIAN); if (cmd_ack_code == AICE_CMD_T_READ_MISC) { LOG_DEBUG("READ_MISC response, data: 0x%" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_MISC, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address, data, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC, AICE_FORMAT_DTHMB); } do { aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address, data, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC); LOG_DEBUG("WRITE_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32, target_id, address, data); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_MISC) { LOG_DEBUG("WRITE_MISC response"); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_MISC, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdma(AICE_CMD_T_READ_EDMSR, target_id, 0, address); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("READ_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, AICE_LITTLE_ENDIAN); if (cmd_ack_code == AICE_CMD_T_READ_EDMSR) { LOG_DEBUG("READ_EDMSR response, data: 0x%" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_EDMSR, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address, data, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC, AICE_FORMAT_DTHMB); } do { aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address, data, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC); LOG_DEBUG("WRITE_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32, target_id, address, data); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_EDMSR) { LOG_DEBUG("WRITE_EDMSR response"); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_EDMSR, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } static int aice_switch_to_big_endian(uint32_t *word, uint8_t num_of_words) { uint32_t tmp; for (uint8_t i = 0 ; i < num_of_words ; i++) { tmp = ((word[i] >> 24) & 0x000000FF) | ((word[i] >> 8) & 0x0000FF00) | ((word[i] << 8) & 0x00FF0000) | ((word[i] << 24) & 0xFF000000); word[i] = tmp; } return ERROR_OK; } static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_words) { int32_t result; uint32_t big_endian_word[4]; int retry_times = 0; /** instruction is big-endian */ memcpy(big_endian_word, word, sizeof(big_endian_word)); aice_switch_to_big_endian(big_endian_word, num_of_words); if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id, num_of_words - 1, 0, big_endian_word, num_of_words, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4, AICE_FORMAT_DTHMB); } do { aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id, num_of_words - 1, 0, big_endian_word, num_of_words, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4); LOG_DEBUG("WRITE_DIM, COREID: %" PRIu8 ", data: 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32, target_id, big_endian_word[0], big_endian_word[1], big_endian_word[2], big_endian_word[3]); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_DIM) { LOG_DEBUG("WRITE_DIM response"); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_DIM, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } static int aice_do_execute(uint8_t target_id) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC, AICE_FORMAT_DTHMB); } do { aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC); LOG_DEBUG("EXECUTE, COREID: %" PRIu8 "", target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_EXECUTE) { LOG_DEBUG("EXECUTE response"); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_EXECUTE, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data) { int32_t result; int retry_times = 0; LOG_DEBUG("WRITE_MEM_B, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32, target_id, address, data); if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0, address, data & 0x000000FF, data_endian); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB); } else { do { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0, address, data & 0x000000FF, data_endian); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_B) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_MEM_B, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); } return ERROR_OK; } int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data) { int32_t result; int retry_times = 0; LOG_DEBUG("WRITE_MEM_H, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32, target_id, address, data); if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0, (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB); } else { do { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0, (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_H) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_MEM_H, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); } return ERROR_OK; } int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data) { int32_t result; int retry_times = 0; LOG_DEBUG("WRITE_MEM, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32, target_id, address, data); if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0, (address >> 2) & 0x3FFFFFFF, data, data_endian); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB); } else { do { aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0, (address >> 2) & 0x3FFFFFFF, data, data_endian); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_WRITE_MEM) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_WRITE_MEM, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); } return ERROR_OK; } int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdmb(AICE_CMD_T_FASTREAD_MEM, target_id, num_of_words - 1, 0); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB); LOG_DEBUG("FASTREAD_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32, target_id, num_of_words); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4); if (result < 0) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id, &extra_length, word, data_endian); if (cmd_ack_code == AICE_CMD_T_FASTREAD_MEM) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_FASTREAD_MEM, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_words) { int32_t result; int retry_times = 0; if (AICE_COMMAND_MODE_PACK == aice_command_mode) { aice_usb_packet_flush(); } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) { aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id, num_of_words - 1, 0, word, data_endian); return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD + (num_of_words - 1) * 4, AICE_FORMAT_DTHMB); } do { aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id, num_of_words - 1, 0, word, data_endian); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD + (num_of_words - 1) * 4); LOG_DEBUG("FASTWRITE_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32, target_id, num_of_words); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_T_FASTWRITE_MEM) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_FASTWRITE_MEM, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdmb(AICE_CMD_T_READ_MEM_B, target_id, 0, address); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB); LOG_DEBUG("READ_MEM_B, COREID: %" PRIu8 "", target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, data_endian); if (cmd_ack_code == AICE_CMD_T_READ_MEM_B) { LOG_DEBUG("READ_MEM_B response, data: 0x%02" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_MEM_B, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdmb(AICE_CMD_T_READ_MEM_H, target_id, 0, (address >> 1) & 0x7FFFFFFF); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB); LOG_DEBUG("READ_MEM_H, CORE_ID: %" PRIu8 "", target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, data_endian); if (cmd_ack_code == AICE_CMD_T_READ_MEM_H) { LOG_DEBUG("READ_MEM_H response, data: 0x%" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_MEM_H, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data) { int32_t result; int retry_times = 0; if ((AICE_COMMAND_MODE_PACK == aice_command_mode) || (AICE_COMMAND_MODE_BATCH == aice_command_mode)) aice_usb_packet_flush(); do { aice_pack_htdmb(AICE_CMD_T_READ_MEM, target_id, 0, (address >> 2) & 0x3FFFFFFF); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB); LOG_DEBUG("READ_MEM, COREID: %" PRIu8 "", target_id); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA); if (AICE_FORMAT_DTHMA != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length, data, data_endian); if (cmd_ack_code == AICE_CMD_T_READ_MEM) { LOG_DEBUG("READ_MEM response, data: 0x%" PRIx32, *data); break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_T_READ_MEM, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_batch_buffer_read(uint8_t buf_index, uint32_t *word, uint32_t num_of_words) { int32_t result; int retry_times = 0; do { aice_pack_htdma(AICE_CMD_BATCH_BUFFER_READ, 0, num_of_words - 1, buf_index); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA); LOG_DEBUG("BATCH_BUFFER_READ, # of DATA %08" PRIx32, num_of_words); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4); if (result < 0) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id, &extra_length, (uint8_t *)word, data_endian); if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_READ) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_BATCH_BUFFER_READ, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word, uint32_t num_of_words) { int32_t result; int retry_times = 0; if (num_of_words == 0) return ERROR_OK; do { /* only pack AICE_CMD_BATCH_BUFFER_WRITE command header */ aice_pack_htdmc(AICE_CMD_BATCH_BUFFER_WRITE, 0, num_of_words - 1, buf_index, 0, data_endian); /* use append instead of pack */ memcpy(usb_out_buffer + 4, word, num_of_words * 4); aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4); LOG_DEBUG("BATCH_BUFFER_WRITE, # of DATA %08" PRIx32, num_of_words); result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB); if (AICE_FORMAT_DTHMB != result) { LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result); return ERROR_FAIL; } uint8_t cmd_ack_code; uint8_t extra_length; uint8_t res_target_id; aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length); if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_WRITE) { break; } else { if (retry_times > aice_max_retry_times) { LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")", AICE_CMD_BATCH_BUFFER_WRITE, cmd_ack_code); return ERROR_FAIL; } /* clear timeout and retry */ if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; retry_times++; } } while (1); return ERROR_OK; } /***************************************************************************/ /* End of AICE commands */ typedef int (*read_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t *data); typedef int (*write_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t data); struct aice_nds32_info core_info[AICE_MAX_NUM_CORE]; static uint8_t total_num_of_core; static char *custom_srst_script; static char *custom_trst_script; static char *custom_restart_script; static uint32_t aice_count_to_check_dbger = 30; static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val); static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val); static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value) { uint32_t ir4_value; uint32_t ir6_value; /* the default value of handling_suppressed_exception is false */ static bool handling_suppressed_exception; if (handling_suppressed_exception) return ERROR_OK; if ((dbger_value & NDS_DBGER_ALL_SUPRS_EX) == NDS_DBGER_ALL_SUPRS_EX) { LOG_ERROR("<-- TARGET WARNING! Exception is detected and suppressed. -->"); handling_suppressed_exception = true; aice_read_reg(coreid, IR4, &ir4_value); /* Clear IR6.SUPRS_EXC, IR6.IMP_EXC */ aice_read_reg(coreid, IR6, &ir6_value); /* * For MCU version(MSC_CFG.MCU == 1) like V3m * | SWID[30:16] | Reserved[15:10] | SUPRS_EXC[9] | IMP_EXC[8] * |VECTOR[7:5] | INST[4] | Exc Type[3:0] | * * For non-MCU version(MSC_CFG.MCU == 0) like V3 * | SWID[30:16] | Reserved[15:14] | SUPRS_EXC[13] | IMP_EXC[12] * | VECTOR[11:5] | INST[4] | Exc Type[3:0] | */ LOG_INFO("EVA: 0x%08" PRIx32, ir4_value); LOG_INFO("ITYPE: 0x%08" PRIx32, ir6_value); ir6_value = ir6_value & (~0x300); /* for MCU */ ir6_value = ir6_value & (~0x3000); /* for non-MCU */ aice_write_reg(coreid, IR6, ir6_value); handling_suppressed_exception = false; } return ERROR_OK; } static int check_privilege(uint32_t coreid, uint32_t dbger_value) { if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) { LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege " "to execute the debug operations. -->"); /* Clear DBGER.ILL_SEC_ACC */ if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC) != ERROR_OK) return ERROR_FAIL; } return ERROR_OK; } static int aice_check_dbger(uint32_t coreid, uint32_t expect_status) { uint32_t i = 0; uint32_t value_dbger; while (1) { aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger); if ((value_dbger & expect_status) == expect_status) { if (ERROR_OK != check_suppressed_exception(coreid, value_dbger)) return ERROR_FAIL; if (ERROR_OK != check_privilege(coreid, value_dbger)) return ERROR_FAIL; return ERROR_OK; } if ((i % 30) == 0) keep_alive(); long long then = 0; if (i == aice_count_to_check_dbger) then = timeval_ms(); if (i >= aice_count_to_check_dbger) { if ((timeval_ms() - then) > 1000) { LOG_ERROR("Timeout (1000ms) waiting for $DBGER status " "being 0x%08" PRIx32, expect_status); return ERROR_FAIL; } } i++; } return ERROR_FAIL; } static int aice_execute_dim(uint32_t coreid, uint32_t *insts, uint8_t n_inst) { /** fill DIM */ if (aice_write_dim(coreid, insts, n_inst) != ERROR_OK) return ERROR_FAIL; /** clear DBGER.DPED */ if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK) return ERROR_FAIL; /** execute DIM */ if (aice_do_execute(coreid) != ERROR_OK) return ERROR_FAIL; /** read DBGER.DPED */ if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) { LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly: " "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 ". -->", insts[0], insts[1], insts[2], insts[3]); return ERROR_FAIL; } return ERROR_OK; } static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val) { LOG_DEBUG("aice_read_reg, reg_no: 0x%08" PRIx32, num); uint32_t instructions[4]; /** execute instructions in DIM */ if (NDS32_REG_TYPE_GPR == nds32_reg_type(num)) { /* general registers */ instructions[0] = MTSR_DTR(num); instructions[1] = DSB; instructions[2] = NOP; instructions[3] = BEQ_MINUS_12; } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(num)) { /* user special registers */ instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (NDS32_REG_TYPE_AUMR == nds32_reg_type(num)) { /* audio registers */ if ((CB_CTL <= num) && (num <= CBE3)) { instructions[0] = AMFAR2(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else { instructions[0] = AMFAR(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } } else if (NDS32_REG_TYPE_FPU == nds32_reg_type(num)) { /* fpu registers */ if (FPCSR == num) { instructions[0] = FMFCSR; instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (FPCFG == num) { instructions[0] = FMFCFG; instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else { if (FS0 <= num && num <= FS31) { /* single precision */ instructions[0] = FMFSR(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (FD0 <= num && num <= FD31) { /* double precision */ instructions[0] = FMFDR(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } } } else { /* system registers */ instructions[0] = MFSR(0, nds32_reg_sr_index(num)); instructions[1] = MTSR_DTR(0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } aice_execute_dim(coreid, instructions, 4); uint32_t value_edmsw; aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw); if (value_edmsw & NDS_EDMSW_WDV) aice_read_dtr(coreid, val); else { LOG_ERROR("<-- TARGET ERROR! The debug target failed to update " "the DTR register. -->"); return ERROR_FAIL; } return ERROR_OK; } static int aice_usb_read_reg(uint32_t coreid, uint32_t num, uint32_t *val) { LOG_DEBUG("aice_usb_read_reg"); if (num == R0) { *val = core_info[coreid].r0_backup; } else if (num == R1) { *val = core_info[coreid].r1_backup; } else if (num == DR41) { /* As target is halted, OpenOCD will backup DR41/DR42/DR43. * As user wants to read these registers, OpenOCD should return * the backup values, instead of reading the real values. * As user wants to write these registers, OpenOCD should write * to the backup values, instead of writing to real registers. */ *val = core_info[coreid].edmsw_backup; } else if (num == DR42) { *val = core_info[coreid].edm_ctl_backup; } else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43)) { *val = core_info[coreid].target_dtr_backup; } else { if (ERROR_OK != aice_read_reg(coreid, num, val)) *val = 0xBBADBEEF; } return ERROR_OK; } static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val) { LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val); uint32_t instructions[4]; /** execute instructions in DIM */ uint32_t value_edmsw; aice_write_dtr(coreid, val); aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw); if (0 == (value_edmsw & NDS_EDMSW_RDV)) { LOG_ERROR("<-- TARGET ERROR! AICE failed to write to the DTR register. -->"); return ERROR_FAIL; } if (NDS32_REG_TYPE_GPR == nds32_reg_type(num)) { /* general registers */ instructions[0] = MFSR_DTR(num); instructions[1] = DSB; instructions[2] = NOP; instructions[3] = BEQ_MINUS_12; } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(num)) { /* user special registers */ instructions[0] = MFSR_DTR(0); instructions[1] = MTUSR_G0(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (NDS32_REG_TYPE_AUMR == nds32_reg_type(num)) { /* audio registers */ if ((CB_CTL <= num) && (num <= CBE3)) { instructions[0] = MFSR_DTR(0); instructions[1] = AMTAR2(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else { instructions[0] = MFSR_DTR(0); instructions[1] = AMTAR(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } } else if (NDS32_REG_TYPE_FPU == nds32_reg_type(num)) { /* fpu registers */ if (FPCSR == num) { instructions[0] = MFSR_DTR(0); instructions[1] = FMTCSR; instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (FPCFG == num) { /* FPCFG is readonly */ } else { if (FS0 <= num && num <= FS31) { /* single precision */ instructions[0] = MFSR_DTR(0); instructions[1] = FMTSR(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } else if (FD0 <= num && num <= FD31) { /* double precision */ instructions[0] = MFSR_DTR(0); instructions[1] = FMTDR(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } } } else { instructions[0] = MFSR_DTR(0); instructions[1] = MTSR(0, nds32_reg_sr_index(num)); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; } return aice_execute_dim(coreid, instructions, 4); } static int aice_usb_write_reg(uint32_t coreid, uint32_t num, uint32_t val) { LOG_DEBUG("aice_usb_write_reg"); if (num == R0) core_info[coreid].r0_backup = val; else if (num == R1) core_info[coreid].r1_backup = val; else if (num == DR42) /* As target is halted, OpenOCD will backup DR41/DR42/DR43. * As user wants to read these registers, OpenOCD should return * the backup values, instead of reading the real values. * As user wants to write these registers, OpenOCD should write * to the backup values, instead of writing to real registers. */ core_info[coreid].edm_ctl_backup = val; else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43)) core_info[coreid].target_dtr_backup = val; else return aice_write_reg(coreid, num, val); return ERROR_OK; } static int aice_usb_open(struct aice_port_param_s *param) { const uint16_t vids[] = { param->vid, 0 }; const uint16_t pids[] = { param->pid, 0 }; struct jtag_libusb_device_handle *devh; if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK) return ERROR_FAIL; /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS * AREA!!!!!!!!!!! The behavior of libusb is not completely * consistent across Windows, Linux, and Mac OS X platforms. * The actions taken in the following compiler conditionals may * not agree with published documentation for libusb, but were * found to be necessary through trials and tribulations. Even * little tweaks can break one or more platforms, so if you do * make changes test them carefully on all platforms before * committing them! */ #if IS_WIN32 == 0 jtag_libusb_reset_device(devh); #if IS_DARWIN == 0 int timeout = 5; /* reopen jlink after usb_reset * on win32 this may take a second or two to re-enumerate */ int retval; while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) { usleep(1000); timeout--; if (!timeout) break; } if (ERROR_OK != retval) return ERROR_FAIL; #endif #endif /* usb_set_configuration required under win32 */ jtag_libusb_set_configuration(devh, 0); unsigned int aice_read_ep; unsigned int aice_write_ep; jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_write_ep = aice_write_ep; aice_handler.usb_handle = devh; return ERROR_OK; } static int aice_usb_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val) { LOG_DEBUG("aice_usb_read_reg_64, %s", nds32_reg_simple_name(num)); uint32_t value; uint32_t high_value; if (ERROR_OK != aice_read_reg(coreid, num, &value)) value = 0xBBADBEEF; aice_read_reg(coreid, R1, &high_value); LOG_DEBUG("low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n", value, high_value); if (data_endian == AICE_BIG_ENDIAN) *val = (((uint64_t)high_value) << 32) | value; else *val = (((uint64_t)value) << 32) | high_value; return ERROR_OK; } static int aice_usb_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val) { uint32_t value; uint32_t high_value; if (data_endian == AICE_BIG_ENDIAN) { value = val & 0xFFFFFFFF; high_value = (val >> 32) & 0xFFFFFFFF; } else { high_value = val & 0xFFFFFFFF; value = (val >> 32) & 0xFFFFFFFF; } LOG_DEBUG("aice_usb_write_reg_64, %s, low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n", nds32_reg_simple_name(num), value, high_value); aice_write_reg(coreid, R1, high_value); return aice_write_reg(coreid, num, value); } static int aice_get_version_info(void) { uint32_t hardware_version; uint32_t firmware_version; uint32_t fpga_version; if (aice_read_ctrl(AICE_READ_CTRL_GET_HARDWARE_VERSION, &hardware_version) != ERROR_OK) return ERROR_FAIL; if (aice_read_ctrl(AICE_READ_CTRL_GET_FIRMWARE_VERSION, &firmware_version) != ERROR_OK) return ERROR_FAIL; if (aice_read_ctrl(AICE_READ_CTRL_GET_FPGA_VERSION, &fpga_version) != ERROR_OK) return ERROR_FAIL; LOG_INFO("AICE version: hw_ver = 0x%" PRIx32 ", fw_ver = 0x%" PRIx32 ", fpga_ver = 0x%" PRIx32, hardware_version, firmware_version, fpga_version); return ERROR_OK; } #define LINE_BUFFER_SIZE 1024 static int aice_execute_custom_script(const char *script) { FILE *script_fd; char line_buffer[LINE_BUFFER_SIZE]; char *op_str; char *reset_str; uint32_t delay; uint32_t write_ctrl_value; bool set_op; script_fd = fopen(script, "r"); if (script_fd == NULL) { return ERROR_FAIL; } else { while (fgets(line_buffer, LINE_BUFFER_SIZE, script_fd) != NULL) { /* execute operations */ set_op = false; op_str = strstr(line_buffer, "set"); if (op_str != NULL) { set_op = true; goto get_reset_type; } op_str = strstr(line_buffer, "clear"); if (op_str == NULL) continue; get_reset_type: reset_str = strstr(op_str, "srst"); if (reset_str != NULL) { if (set_op) write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST; else write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST; goto get_delay; } reset_str = strstr(op_str, "dbgi"); if (reset_str != NULL) { if (set_op) write_ctrl_value = AICE_CUSTOM_DELAY_SET_DBGI; else write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_DBGI; goto get_delay; } reset_str = strstr(op_str, "trst"); if (reset_str != NULL) { if (set_op) write_ctrl_value = AICE_CUSTOM_DELAY_SET_TRST; else write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_TRST; goto get_delay; } continue; get_delay: /* get delay */ delay = strtoul(reset_str + 4, NULL, 0); write_ctrl_value |= (delay << 16); if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY, write_ctrl_value) != ERROR_OK) { fclose(script_fd); return ERROR_FAIL; } } fclose(script_fd); } return ERROR_OK; } static int aice_usb_set_clock(int set_clock) { if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK) return ERROR_FAIL; /* Read out TCK_SCAN clock value */ uint32_t scan_clock; if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK) return ERROR_FAIL; scan_clock &= 0x0F; uint32_t scan_base_freq; if (scan_clock & 0x8) scan_base_freq = 48000; /* 48 MHz */ else scan_base_freq = 30000; /* 30 MHz */ uint32_t set_base_freq; if (set_clock & 0x8) set_base_freq = 48000; else set_base_freq = 30000; uint32_t set_freq; uint32_t scan_freq; set_freq = set_base_freq >> (set_clock & 0x7); scan_freq = scan_base_freq >> (scan_clock & 0x7); if (scan_freq < set_freq) { LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock"); return ERROR_FAIL; } if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, set_clock) != ERROR_OK) return ERROR_FAIL; uint32_t check_speed; if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &check_speed) != ERROR_OK) return ERROR_FAIL; if (((int)check_speed & 0x0F) != set_clock) { LOG_ERROR("Set jtag clock failed"); return ERROR_FAIL; } return ERROR_OK; } static int aice_edm_init(uint32_t coreid) { aice_write_edmsr(coreid, NDS_EDM_SR_DIMBR, 0xFFFF0000); aice_write_misc(coreid, NDS_EDM_MISC_DIMIR, 0); /* unconditionally try to turn on V3_EDM_MODE */ uint32_t edm_ctl_value; aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value); aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value | 0x00000040); /* clear DBGER */ aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED | NDS_DBGER_CRST | NDS_DBGER_AT_MAX); /* get EDM version */ uint32_t value_edmcfg; aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CFG, &value_edmcfg); core_info[coreid].edm_version = (value_edmcfg >> 16) & 0xFFFF; return ERROR_OK; } static bool is_v2_edm(uint32_t coreid) { if ((core_info[coreid].edm_version & 0x1000) == 0) return true; else return false; } static int aice_init_edm_registers(uint32_t coreid, bool clear_dex_use_psw) { /* enable DEH_SEL & MAX_STOP & V3_EDM_MODE & DBGI_MASK */ uint32_t host_edm_ctl = core_info[coreid].edm_ctl_backup | 0xA000004F; if (clear_dex_use_psw) /* After entering debug mode, OpenOCD may set * DEX_USE_PSW accidentally through backup value * of target EDM_CTL. * So, clear DEX_USE_PSW by force. */ host_edm_ctl &= ~(0x40000000); LOG_DEBUG("aice_init_edm_registers - EDM_CTL: 0x%08" PRIx32, host_edm_ctl); int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, host_edm_ctl); return result; } /** * EDM_CTL will be modified by OpenOCD as debugging. OpenOCD has the * responsibility to keep EDM_CTL untouched after debugging. * * There are two scenarios to consider: * 1. single step/running as debugging (running under debug session) * 2. detached from gdb (exit debug session) * * So, we need to bakcup EDM_CTL before halted and restore it after * running. The difference of these two scenarios is EDM_CTL.DEH_SEL * is on for scenario 1, and off for scenario 2. */ static int aice_backup_edm_registers(uint32_t coreid) { int result = aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &core_info[coreid].edm_ctl_backup); /* To call aice_backup_edm_registers() after DEX on, DEX_USE_PSW * may be not correct. (For example, hit breakpoint, then backup * EDM_CTL. EDM_CTL.DEX_USE_PSW will be cleared.) Because debug * interrupt will clear DEX_USE_PSW, DEX_USE_PSW is always off after * DEX is on. It only backups correct value before OpenOCD issues DBGI. * (Backup EDM_CTL, then issue DBGI actively (refer aice_usb_halt())) */ if (core_info[coreid].edm_ctl_backup & 0x40000000) core_info[coreid].dex_use_psw_on = true; else core_info[coreid].dex_use_psw_on = false; LOG_DEBUG("aice_backup_edm_registers - EDM_CTL: 0x%08" PRIx32 ", DEX_USE_PSW: %s", core_info[coreid].edm_ctl_backup, core_info[coreid].dex_use_psw_on ? "on" : "off"); return result; } static int aice_restore_edm_registers(uint32_t coreid) { LOG_DEBUG("aice_restore_edm_registers -"); /* set DEH_SEL, because target still under EDM control */ int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, core_info[coreid].edm_ctl_backup | 0x80000000); return result; } static int aice_backup_tmp_registers(uint32_t coreid) { LOG_DEBUG("backup_tmp_registers -"); /* backup target DTR first(if the target DTR is valid) */ uint32_t value_edmsw; aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw); core_info[coreid].edmsw_backup = value_edmsw; if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */ aice_read_dtr(coreid, &core_info[coreid].target_dtr_backup); core_info[coreid].target_dtr_valid = true; LOG_DEBUG("Backup target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup); } else { core_info[coreid].target_dtr_valid = false; } /* Target DTR has been backup, then backup $R0 and $R1 */ aice_read_reg(coreid, R0, &core_info[coreid].r0_backup); aice_read_reg(coreid, R1, &core_info[coreid].r1_backup); /* backup host DTR(if the host DTR is valid) */ if (value_edmsw & 0x2) { /* EDMSW.RDV == 1*/ /* read out host DTR and write into target DTR, then use aice_read_edmsr to * read out */ uint32_t instructions[4] = { MFSR_DTR(R0), /* R0 has already been backup */ DSB, MTSR_DTR(R0), BEQ_MINUS_12 }; aice_execute_dim(coreid, instructions, 4); aice_read_dtr(coreid, &core_info[coreid].host_dtr_backup); core_info[coreid].host_dtr_valid = true; LOG_DEBUG("Backup host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup); } else { core_info[coreid].host_dtr_valid = false; } LOG_DEBUG("r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32, core_info[coreid].r0_backup, core_info[coreid].r1_backup); return ERROR_OK; } static int aice_restore_tmp_registers(uint32_t coreid) { LOG_DEBUG("restore_tmp_registers - r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32, core_info[coreid].r0_backup, core_info[coreid].r1_backup); if (core_info[coreid].target_dtr_valid) { uint32_t instructions[4] = { SETHI(R0, core_info[coreid].target_dtr_backup >> 12), ORI(R0, R0, core_info[coreid].target_dtr_backup & 0x00000FFF), NOP, BEQ_MINUS_12 }; aice_execute_dim(coreid, instructions, 4); instructions[0] = MTSR_DTR(R0); instructions[1] = DSB; instructions[2] = NOP; instructions[3] = BEQ_MINUS_12; aice_execute_dim(coreid, instructions, 4); LOG_DEBUG("Restore target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup); } aice_write_reg(coreid, R0, core_info[coreid].r0_backup); aice_write_reg(coreid, R1, core_info[coreid].r1_backup); if (core_info[coreid].host_dtr_valid) { aice_write_dtr(coreid, core_info[coreid].host_dtr_backup); LOG_DEBUG("Restore host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup); } return ERROR_OK; } static int aice_open_device(struct aice_port_param_s *param) { if (ERROR_OK != aice_usb_open(param)) return ERROR_FAIL; if (ERROR_FAIL == aice_get_version_info()) { LOG_ERROR("Cannot get AICE version!"); return ERROR_FAIL; } LOG_INFO("AICE initialization started"); /* attempt to reset Andes EDM */ if (ERROR_FAIL == aice_reset_box()) { LOG_ERROR("Cannot initial AICE box!"); return ERROR_FAIL; } return ERROR_OK; } static int aice_usb_set_jtag_clock(uint32_t a_clock) { jtag_clock = a_clock; if (ERROR_OK != aice_usb_set_clock(a_clock)) { LOG_ERROR("Cannot set AICE JTAG clock!"); return ERROR_FAIL; } return ERROR_OK; } static int aice_usb_close(void) { jtag_libusb_close(aice_handler.usb_handle); if (custom_srst_script) free(custom_srst_script); if (custom_trst_script) free(custom_trst_script); if (custom_restart_script) free(custom_restart_script); return ERROR_OK; } static int aice_core_init(uint32_t coreid) { core_info[coreid].access_channel = NDS_MEMORY_ACC_CPU; core_info[coreid].memory_select = NDS_MEMORY_SELECT_AUTO; core_info[coreid].core_state = AICE_TARGET_UNKNOWN; return ERROR_OK; } static int aice_usb_idcode(uint32_t *idcode, uint8_t *num_of_idcode) { int retval; retval = aice_scan_chain(idcode, num_of_idcode); if (ERROR_OK == retval) { for (int i = 0; i < *num_of_idcode; i++) { aice_core_init(i); aice_edm_init(i); } total_num_of_core = *num_of_idcode; } return retval; } static int aice_usb_halt(uint32_t coreid) { if (core_info[coreid].core_state == AICE_TARGET_HALTED) { LOG_DEBUG("aice_usb_halt check halted"); return ERROR_OK; } LOG_DEBUG("aice_usb_halt"); /** backup EDM registers */ aice_backup_edm_registers(coreid); /** init EDM for host debugging */ /** no need to clear dex_use_psw, because dbgi will clear it */ aice_init_edm_registers(coreid, false); /** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */ uint32_t edm_ctl_value; aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value); if (edm_ctl_value & 0x3) aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3)); uint32_t dbger; uint32_t acc_ctl_value; core_info[coreid].debug_under_dex_on = false; aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger); if (dbger & NDS_DBGER_AT_MAX) LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level. -->"); if (dbger & NDS_DBGER_DEX) { if (is_v2_edm(coreid) == false) { /** debug 'debug mode'. use force_debug to issue dbgi */ aice_read_misc(coreid, NDS_EDM_MISC_ACC_CTL, &acc_ctl_value); acc_ctl_value |= 0x8; aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, acc_ctl_value); core_info[coreid].debug_under_dex_on = true; aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0); /* If CPU stalled due to AT_MAX, clear AT_MAX status. */ if (dbger & NDS_DBGER_AT_MAX) aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX); } } else { /** Issue DBGI normally */ aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0); /* If CPU stalled due to AT_MAX, clear AT_MAX status. */ if (dbger & NDS_DBGER_AT_MAX) aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX); } if (aice_check_dbger(coreid, NDS_DBGER_DEX) != ERROR_OK) { LOG_ERROR("<-- TARGET ERROR! Unable to stop the debug target through DBGI. -->"); return ERROR_FAIL; } if (core_info[coreid].debug_under_dex_on) { if (core_info[coreid].dex_use_psw_on == false) { /* under debug 'debug mode', force $psw to 'debug mode' bahavior */ /* !!!NOTICE!!! this is workaround for debug 'debug mode'. * it is only for debugging 'debug exception handler' purpose. * after openocd detaches from target, target behavior is * undefined. */ uint32_t ir0_value; uint32_t debug_mode_ir0_value; aice_read_reg(coreid, IR0, &ir0_value); debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */ debug_mode_ir0_value &= ~(0x000000C1); /* turn off DT/IT/GIE */ aice_write_reg(coreid, IR0, debug_mode_ir0_value); } } /** set EDM_CTL.DBGIM & EDM_CTL.DBGACKM after halt */ if (edm_ctl_value & 0x3) aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value); /* backup r0 & r1 */ aice_backup_tmp_registers(coreid); core_info[coreid].core_state = AICE_TARGET_HALTED; return ERROR_OK; } static int aice_usb_state(uint32_t coreid, enum aice_target_state_s *state) { uint32_t dbger_value; uint32_t ice_state; int result = aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value); if (ERROR_AICE_TIMEOUT == result) { if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &ice_state) != ERROR_OK) { LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->"); return ERROR_FAIL; } if ((ice_state & 0x20) == 0) { LOG_ERROR("<-- TARGET ERROR! Target is disconnected with AICE. -->"); return ERROR_FAIL; } else { return ERROR_FAIL; } } else if (ERROR_AICE_DISCONNECT == result) { LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->"); return ERROR_FAIL; } if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) { LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege. -->"); /* Clear ILL_SEC_ACC */ aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC); *state = AICE_TARGET_RUNNING; core_info[coreid].core_state = AICE_TARGET_RUNNING; } else if ((dbger_value & NDS_DBGER_AT_MAX) == NDS_DBGER_AT_MAX) { /* Issue DBGI to exit cpu stall */ aice_usb_halt(coreid); /* Read OIPC to find out the trigger point */ uint32_t ir11_value; aice_read_reg(coreid, IR11, &ir11_value); LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level; " "CPU is stalled at 0x%08" PRIx32 " for debugging. -->", ir11_value); *state = AICE_TARGET_HALTED; } else if ((dbger_value & NDS_DBGER_CRST) == NDS_DBGER_CRST) { LOG_DEBUG("DBGER.CRST is on."); *state = AICE_TARGET_RESET; core_info[coreid].core_state = AICE_TARGET_RUNNING; /* Clear CRST */ aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST); } else if ((dbger_value & NDS_DBGER_DEX) == NDS_DBGER_DEX) { if (AICE_TARGET_RUNNING == core_info[coreid].core_state) { /* enter debug mode, init EDM registers */ /* backup EDM registers */ aice_backup_edm_registers(coreid); /* init EDM for host debugging */ aice_init_edm_registers(coreid, true); aice_backup_tmp_registers(coreid); core_info[coreid].core_state = AICE_TARGET_HALTED; } else if (AICE_TARGET_UNKNOWN == core_info[coreid].core_state) { /* debug 'debug mode', use force debug to halt core */ aice_usb_halt(coreid); } *state = AICE_TARGET_HALTED; } else { *state = AICE_TARGET_RUNNING; core_info[coreid].core_state = AICE_TARGET_RUNNING; } return ERROR_OK; } static int aice_usb_reset(void) { if (aice_reset_box() != ERROR_OK) return ERROR_FAIL; /* issue TRST */ if (custom_trst_script == NULL) { if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL, AICE_JTAG_PIN_CONTROL_TRST) != ERROR_OK) return ERROR_FAIL; } else { /* custom trst operations */ if (aice_execute_custom_script(custom_trst_script) != ERROR_OK) return ERROR_FAIL; } if (aice_usb_set_clock(jtag_clock) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int aice_issue_srst(uint32_t coreid) { LOG_DEBUG("aice_issue_srst"); /* After issuing srst, target will be running. So we need to restore EDM_CTL. */ aice_restore_edm_registers(coreid); if (custom_srst_script == NULL) { if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL, AICE_JTAG_PIN_CONTROL_SRST) != ERROR_OK) return ERROR_FAIL; } else { /* custom srst operations */ if (aice_execute_custom_script(custom_srst_script) != ERROR_OK) return ERROR_FAIL; } /* wait CRST infinitely */ uint32_t dbger_value; int i = 0; while (1) { if (aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK) return ERROR_FAIL; if (dbger_value & NDS_DBGER_CRST) break; if ((i % 30) == 0) keep_alive(); i++; } core_info[coreid].host_dtr_valid = false; core_info[coreid].target_dtr_valid = false; core_info[coreid].core_state = AICE_TARGET_RUNNING; return ERROR_OK; } static int aice_issue_reset_hold(uint32_t coreid) { LOG_DEBUG("aice_issue_reset_hold"); /* set no_dbgi_pin to 0 */ uint32_t pin_status; aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status); if (pin_status | 0x4) aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x4)); /* issue restart */ if (custom_restart_script == NULL) { if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL, AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK) return ERROR_FAIL; } else { /* custom restart operations */ if (aice_execute_custom_script(custom_restart_script) != ERROR_OK) return ERROR_FAIL; } if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) { aice_backup_tmp_registers(coreid); core_info[coreid].core_state = AICE_TARGET_HALTED; return ERROR_OK; } else { /* set no_dbgi_pin to 1 */ aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status | 0x4); /* issue restart again */ if (custom_restart_script == NULL) { if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL, AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK) return ERROR_FAIL; } else { /* custom restart operations */ if (aice_execute_custom_script(custom_restart_script) != ERROR_OK) return ERROR_FAIL; } if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) { aice_backup_tmp_registers(coreid); core_info[coreid].core_state = AICE_TARGET_HALTED; return ERROR_OK; } /* do software reset-and-hold */ aice_issue_srst(coreid); aice_usb_halt(coreid); uint32_t value_ir3; aice_read_reg(coreid, IR3, &value_ir3); aice_write_reg(coreid, PC, value_ir3 & 0xFFFF0000); } return ERROR_FAIL; } static int aice_issue_reset_hold_multi(void) { uint32_t write_ctrl_value = 0; /* set SRST */ write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST; write_ctrl_value |= (0x200 << 16); if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY, write_ctrl_value) != ERROR_OK) return ERROR_FAIL; for (uint8_t i = 0 ; i < total_num_of_core ; i++) aice_write_misc(i, NDS_EDM_MISC_EDM_CMDR, 0); /* clear SRST */ write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST; write_ctrl_value |= (0x200 << 16); if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY, write_ctrl_value) != ERROR_OK) return ERROR_FAIL; for (uint8_t i = 0; i < total_num_of_core; i++) aice_edm_init(i); return ERROR_FAIL; } static int aice_usb_assert_srst(uint32_t coreid, enum aice_srst_type_s srst) { if ((AICE_SRST != srst) && (AICE_RESET_HOLD != srst)) return ERROR_FAIL; /* clear DBGER */ if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CLEAR_ALL) != ERROR_OK) return ERROR_FAIL; int result = ERROR_OK; if (AICE_SRST == srst) result = aice_issue_srst(coreid); else { if (1 == total_num_of_core) result = aice_issue_reset_hold(coreid); else result = aice_issue_reset_hold_multi(); } /* Clear DBGER.CRST after reset to avoid 'core-reset checking' errors. * assert_srst is user-intentional reset behavior, so we could * clear DBGER.CRST safely. */ if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST) != ERROR_OK) return ERROR_FAIL; return result; } static int aice_usb_run(uint32_t coreid) { LOG_DEBUG("aice_usb_run"); uint32_t dbger_value; if (aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK) return ERROR_FAIL; if ((dbger_value & NDS_DBGER_DEX) != NDS_DBGER_DEX) { LOG_WARNING("<-- TARGET WARNING! The debug target exited " "the debug mode unexpectedly. -->"); return ERROR_FAIL; } /* restore r0 & r1 before free run */ aice_restore_tmp_registers(coreid); core_info[coreid].core_state = AICE_TARGET_RUNNING; /* clear DBGER */ aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CLEAR_ALL); /** restore EDM registers */ /** OpenOCD should restore EDM_CTL **before** to exit debug state. * Otherwise, following instruction will read wrong EDM_CTL value. * * pc -> mfsr $p0, EDM_CTL (single step) * slli $p0, $p0, 1 * slri $p0, $p0, 31 */ aice_restore_edm_registers(coreid); /** execute instructions in DIM */ uint32_t instructions[4] = { NOP, NOP, NOP, IRET }; int result = aice_execute_dim(coreid, instructions, 4); return result; } static int aice_usb_step(uint32_t coreid) { LOG_DEBUG("aice_usb_step"); uint32_t ir0_value; uint32_t ir0_reg_num; if (is_v2_edm(coreid) == true) /* V2 EDM will push interrupt stack as debug exception */ ir0_reg_num = IR1; else ir0_reg_num = IR0; /** enable HSS */ aice_read_reg(coreid, ir0_reg_num, &ir0_value); if ((ir0_value & 0x800) == 0) { /** set PSW.HSS */ ir0_value |= (0x01 << 11); aice_write_reg(coreid, ir0_reg_num, ir0_value); } if (ERROR_FAIL == aice_usb_run(coreid)) return ERROR_FAIL; int i = 0; enum aice_target_state_s state; while (1) { /* read DBGER */ if (aice_usb_state(coreid, &state) != ERROR_OK) return ERROR_FAIL; if (AICE_TARGET_HALTED == state) break; long long then = 0; if (i == 30) then = timeval_ms(); if (i >= 30) { if ((timeval_ms() - then) > 1000) LOG_WARNING("Timeout (1000ms) waiting for halt to complete"); return ERROR_FAIL; } i++; } /** disable HSS */ aice_read_reg(coreid, ir0_reg_num, &ir0_value); ir0_value &= ~(0x01 << 11); aice_write_reg(coreid, ir0_reg_num, ir0_value); return ERROR_OK; } static int aice_usb_read_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t *data) { return aice_read_mem_b(coreid, address, data); } static int aice_usb_read_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t *data) { return aice_read_mem_h(coreid, address, data); } static int aice_usb_read_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t *data) { return aice_read_mem(coreid, address, data); } static int aice_usb_read_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t *data) { uint32_t value; uint32_t instructions[4] = { LBI_BI(R1, R0), MTSR_DTR(R1), DSB, BEQ_MINUS_12 }; aice_execute_dim(coreid, instructions, 4); aice_read_dtr(coreid, &value); *data = value & 0xFF; return ERROR_OK; } static int aice_usb_read_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t *data) { uint32_t value; uint32_t instructions[4] = { LHI_BI(R1, R0), MTSR_DTR(R1), DSB, BEQ_MINUS_12 }; aice_execute_dim(coreid, instructions, 4); aice_read_dtr(coreid, &value); *data = value & 0xFFFF; return ERROR_OK; } static int aice_usb_read_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t *data) { uint32_t instructions[4] = { LWI_BI(R1, R0), MTSR_DTR(R1), DSB, BEQ_MINUS_12 }; aice_execute_dim(coreid, instructions, 4); aice_read_dtr(coreid, data); return ERROR_OK; } static int aice_usb_set_address_dim(uint32_t coreid, uint32_t address) { uint32_t instructions[4] = { SETHI(R0, address >> 12), ORI(R0, R0, address & 0x00000FFF), NOP, BEQ_MINUS_12 }; return aice_execute_dim(coreid, instructions, 4); } static int aice_usb_read_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { LOG_DEBUG("aice_usb_read_memory_unit, addr: 0x%08" PRIx32 ", size: %" PRIu32 ", count: %" PRIu32 "", addr, size, count); if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) aice_usb_set_address_dim(coreid, addr); uint32_t value; size_t i; read_mem_func_t read_mem_func; switch (size) { case 1: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) read_mem_func = aice_usb_read_mem_b_bus; else read_mem_func = aice_usb_read_mem_b_dim; for (i = 0; i < count; i++) { read_mem_func(coreid, addr, &value); *buffer++ = (uint8_t)value; addr++; } break; case 2: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) read_mem_func = aice_usb_read_mem_h_bus; else read_mem_func = aice_usb_read_mem_h_dim; for (i = 0; i < count; i++) { read_mem_func(coreid, addr, &value); uint16_t svalue = value; memcpy(buffer, &svalue, sizeof(uint16_t)); buffer += 2; addr += 2; } break; case 4: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) read_mem_func = aice_usb_read_mem_w_bus; else read_mem_func = aice_usb_read_mem_w_dim; for (i = 0; i < count; i++) { read_mem_func(coreid, addr, &value); memcpy(buffer, &value, sizeof(uint32_t)); buffer += 4; addr += 4; } break; } return ERROR_OK; } static int aice_usb_write_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t data) { return aice_write_mem_b(coreid, address, data); } static int aice_usb_write_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t data) { return aice_write_mem_h(coreid, address, data); } static int aice_usb_write_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t data) { return aice_write_mem(coreid, address, data); } static int aice_usb_write_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t data) { uint32_t instructions[4] = { MFSR_DTR(R1), SBI_BI(R1, R0), DSB, BEQ_MINUS_12 }; aice_write_dtr(coreid, data & 0xFF); aice_execute_dim(coreid, instructions, 4); return ERROR_OK; } static int aice_usb_write_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t data) { uint32_t instructions[4] = { MFSR_DTR(R1), SHI_BI(R1, R0), DSB, BEQ_MINUS_12 }; aice_write_dtr(coreid, data & 0xFFFF); aice_execute_dim(coreid, instructions, 4); return ERROR_OK; } static int aice_usb_write_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t data) { uint32_t instructions[4] = { MFSR_DTR(R1), SWI_BI(R1, R0), DSB, BEQ_MINUS_12 }; aice_write_dtr(coreid, data); aice_execute_dim(coreid, instructions, 4); return ERROR_OK; } static int aice_usb_write_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { LOG_DEBUG("aice_usb_write_memory_unit, addr: 0x%08" PRIx32 ", size: %" PRIu32 ", count: %" PRIu32 "", addr, size, count); if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) aice_usb_set_address_dim(coreid, addr); size_t i; write_mem_func_t write_mem_func; switch (size) { case 1: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) write_mem_func = aice_usb_write_mem_b_bus; else write_mem_func = aice_usb_write_mem_b_dim; for (i = 0; i < count; i++) { write_mem_func(coreid, addr, *buffer); buffer++; addr++; } break; case 2: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) write_mem_func = aice_usb_write_mem_h_bus; else write_mem_func = aice_usb_write_mem_h_dim; for (i = 0; i < count; i++) { uint16_t value; memcpy(&value, buffer, sizeof(uint16_t)); write_mem_func(coreid, addr, value); buffer += 2; addr += 2; } break; case 4: if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel) write_mem_func = aice_usb_write_mem_w_bus; else write_mem_func = aice_usb_write_mem_w_dim; for (i = 0; i < count; i++) { uint32_t value; memcpy(&value, buffer, sizeof(uint32_t)); write_mem_func(coreid, addr, value); buffer += 4; addr += 4; } break; } return ERROR_OK; } static int aice_bulk_read_mem(uint32_t coreid, uint32_t addr, uint32_t count, uint8_t *buffer) { uint32_t packet_size; while (count > 0) { packet_size = (count >= 0x100) ? 0x100 : count; /** set address */ addr &= 0xFFFFFFFC; if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr) != ERROR_OK) return ERROR_FAIL; if (aice_fastread_mem(coreid, buffer, packet_size) != ERROR_OK) return ERROR_FAIL; buffer += (packet_size * 4); addr += (packet_size * 4); count -= packet_size; } return ERROR_OK; } static int aice_bulk_write_mem(uint32_t coreid, uint32_t addr, uint32_t count, const uint8_t *buffer) { uint32_t packet_size; while (count > 0) { packet_size = (count >= 0x100) ? 0x100 : count; /** set address */ addr &= 0xFFFFFFFC; if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr | 1) != ERROR_OK) return ERROR_FAIL; if (aice_fastwrite_mem(coreid, buffer, packet_size) != ERROR_OK) return ERROR_FAIL; buffer += (packet_size * 4); addr += (packet_size * 4); count -= packet_size; } return ERROR_OK; } static int aice_usb_bulk_read_mem(uint32_t coreid, uint32_t addr, uint32_t length, uint8_t *buffer) { LOG_DEBUG("aice_usb_bulk_read_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length); int retval; if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) aice_usb_set_address_dim(coreid, addr); if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) retval = aice_usb_read_memory_unit(coreid, addr, 4, length / 4, buffer); else retval = aice_bulk_read_mem(coreid, addr, length / 4, buffer); return retval; } static int aice_usb_bulk_write_mem(uint32_t coreid, uint32_t addr, uint32_t length, const uint8_t *buffer) { LOG_DEBUG("aice_usb_bulk_write_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length); int retval; if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) aice_usb_set_address_dim(coreid, addr); if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel) retval = aice_usb_write_memory_unit(coreid, addr, 4, length / 4, buffer); else retval = aice_bulk_write_mem(coreid, addr, length / 4, buffer); return retval; } static int aice_usb_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val) { if (AICE_TARGET_HALTED == core_info[coreid].core_state) { if (NDS_EDM_SR_EDMSW == addr) { *val = core_info[coreid].edmsw_backup; } else if (NDS_EDM_SR_EDM_DTR == addr) { if (core_info[coreid].target_dtr_valid) { /* if EDM_DTR has read out, clear it. */ *val = core_info[coreid].target_dtr_backup; core_info[coreid].edmsw_backup &= (~0x1); core_info[coreid].target_dtr_valid = false; } else { *val = 0; } } } return aice_read_edmsr(coreid, addr, val); } static int aice_usb_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val) { if (AICE_TARGET_HALTED == core_info[coreid].core_state) { if (NDS_EDM_SR_EDM_DTR == addr) { core_info[coreid].host_dtr_backup = val; core_info[coreid].edmsw_backup |= 0x2; core_info[coreid].host_dtr_valid = true; } } return aice_write_edmsr(coreid, addr, val); } static int aice_usb_memory_access(uint32_t coreid, enum nds_memory_access channel) { LOG_DEBUG("aice_usb_memory_access, access channel: %u", channel); core_info[coreid].access_channel = channel; return ERROR_OK; } static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_select) { if (core_info[coreid].memory_select == mem_select) return ERROR_OK; LOG_DEBUG("aice_usb_memory_mode, memory select: %u", mem_select); core_info[coreid].memory_select = mem_select; if (NDS_MEMORY_SELECT_AUTO != core_info[coreid].memory_select) aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, core_info[coreid].memory_select - 1); else aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, NDS_MEMORY_SELECT_MEM - 1); return ERROR_OK; } static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address) { LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address); uint32_t instructions[4]; uint32_t probe_result; uint32_t value_mr3; uint32_t value_mr4; uint32_t access_page_size; uint32_t virtual_offset; uint32_t physical_page_number; aice_write_dtr(coreid, virtual_address); /* probe TLB first */ instructions[0] = MFSR_DTR(R0); instructions[1] = TLBOP_TARGET_PROBE(R1, R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; aice_execute_dim(coreid, instructions, 4); aice_read_reg(coreid, R1, &probe_result); if (probe_result & 0x80000000) return ERROR_FAIL; /* read TLB entry */ aice_write_dtr(coreid, probe_result & 0x7FF); /* probe TLB first */ instructions[0] = MFSR_DTR(R0); instructions[1] = TLBOP_TARGET_READ(R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; aice_execute_dim(coreid, instructions, 4); /* TODO: it should backup mr3, mr4 */ aice_read_reg(coreid, MR3, &value_mr3); aice_read_reg(coreid, MR4, &value_mr4); access_page_size = value_mr4 & 0xF; if (0 == access_page_size) { /* 4K page */ virtual_offset = virtual_address & 0x00000FFF; physical_page_number = value_mr3 & 0xFFFFF000; } else if (1 == access_page_size) { /* 8K page */ virtual_offset = virtual_address & 0x00001FFF; physical_page_number = value_mr3 & 0xFFFFE000; } else if (5 == access_page_size) { /* 1M page */ virtual_offset = virtual_address & 0x000FFFFF; physical_page_number = value_mr3 & 0xFFF00000; } else { return ERROR_FAIL; } *physical_address = physical_page_number | virtual_offset; return ERROR_OK; } static int aice_usb_init_cache(uint32_t coreid) { LOG_DEBUG("aice_usb_init_cache"); uint32_t value_cr1; uint32_t value_cr2; aice_read_reg(coreid, CR1, &value_cr1); aice_read_reg(coreid, CR2, &value_cr2); struct cache_info *icache = &core_info[coreid].icache; icache->set = value_cr1 & 0x7; icache->log2_set = icache->set + 6; icache->set = 64 << icache->set; icache->way = ((value_cr1 >> 3) & 0x7) + 1; icache->line_size = (value_cr1 >> 6) & 0x7; if (icache->line_size != 0) { icache->log2_line_size = icache->line_size + 2; icache->line_size = 8 << (icache->line_size - 1); } else { icache->log2_line_size = 0; } LOG_DEBUG("\ticache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", " "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "", icache->set, icache->way, icache->line_size, icache->log2_set, icache->log2_line_size); struct cache_info *dcache = &core_info[coreid].dcache; dcache->set = value_cr2 & 0x7; dcache->log2_set = dcache->set + 6; dcache->set = 64 << dcache->set; dcache->way = ((value_cr2 >> 3) & 0x7) + 1; dcache->line_size = (value_cr2 >> 6) & 0x7; if (dcache->line_size != 0) { dcache->log2_line_size = dcache->line_size + 2; dcache->line_size = 8 << (dcache->line_size - 1); } else { dcache->log2_line_size = 0; } LOG_DEBUG("\tdcache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", " "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "", dcache->set, dcache->way, dcache->line_size, dcache->log2_set, dcache->log2_line_size); core_info[coreid].cache_init = true; return ERROR_OK; } static int aice_usb_dcache_inval_all(uint32_t coreid) { LOG_DEBUG("aice_usb_dcache_inval_all"); uint32_t set_index; uint32_t way_index; uint32_t cache_index; uint32_t instructions[4]; instructions[0] = MFSR_DTR(R0); instructions[1] = L1D_IX_INVAL(R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; struct cache_info *dcache = &core_info[coreid].dcache; for (set_index = 0; set_index < dcache->set; set_index++) { for (way_index = 0; way_index < dcache->way; way_index++) { cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) | (set_index << dcache->log2_line_size); if (ERROR_OK != aice_write_dtr(coreid, cache_index)) return ERROR_FAIL; if (ERROR_OK != aice_execute_dim(coreid, instructions, 4)) return ERROR_FAIL; } } return ERROR_OK; } static int aice_usb_dcache_va_inval(uint32_t coreid, uint32_t address) { LOG_DEBUG("aice_usb_dcache_va_inval"); uint32_t instructions[4]; aice_write_dtr(coreid, address); instructions[0] = MFSR_DTR(R0); instructions[1] = L1D_VA_INVAL(R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; return aice_execute_dim(coreid, instructions, 4); } static int aice_usb_dcache_wb_all(uint32_t coreid) { LOG_DEBUG("aice_usb_dcache_wb_all"); uint32_t set_index; uint32_t way_index; uint32_t cache_index; uint32_t instructions[4]; instructions[0] = MFSR_DTR(R0); instructions[1] = L1D_IX_WB(R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; struct cache_info *dcache = &core_info[coreid].dcache; for (set_index = 0; set_index < dcache->set; set_index++) { for (way_index = 0; way_index < dcache->way; way_index++) { cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) | (set_index << dcache->log2_line_size); if (ERROR_OK != aice_write_dtr(coreid, cache_index)) return ERROR_FAIL; if (ERROR_OK != aice_execute_dim(coreid, instructions, 4)) return ERROR_FAIL; } } return ERROR_OK; } static int aice_usb_dcache_va_wb(uint32_t coreid, uint32_t address) { LOG_DEBUG("aice_usb_dcache_va_wb"); uint32_t instructions[4]; aice_write_dtr(coreid, address); instructions[0] = MFSR_DTR(R0); instructions[1] = L1D_VA_WB(R0); instructions[2] = DSB; instructions[3] = BEQ_MINUS_12; return aice_execute_dim(coreid, instructions, 4); } static int aice_usb_icache_inval_all(uint32_t coreid) { LOG_DEBUG("aice_usb_icache_inval_all"); uint32_t set_index; uint32_t way_index; uint32_t cache_index; uint32_t instructions[4]; instructions[0] = MFSR_DTR(R0); instructions[1] = L1I_IX_INVAL(R0); instructions[2] = ISB; instructions[3] = BEQ_MINUS_12; struct cache_info *icache = &core_info[coreid].icache; for (set_index = 0; set_index < icache->set; set_index++) { for (way_index = 0; way_index < icache->way; way_index++) { cache_index = (way_index << (icache->log2_set + icache->log2_line_size)) | (set_index << icache->log2_line_size); if (ERROR_OK != aice_write_dtr(coreid, cache_index)) return ERROR_FAIL; if (ERROR_OK != aice_execute_dim(coreid, instructions, 4)) return ERROR_FAIL; } } return ERROR_OK; } static int aice_usb_icache_va_inval(uint32_t coreid, uint32_t address) { LOG_DEBUG("aice_usb_icache_va_inval"); uint32_t instructions[4]; aice_write_dtr(coreid, address); instructions[0] = MFSR_DTR(R0); instructions[1] = L1I_VA_INVAL(R0); instructions[2] = ISB; instructions[3] = BEQ_MINUS_12; return aice_execute_dim(coreid, instructions, 4); } static int aice_usb_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address) { LOG_DEBUG("aice_usb_cache_ctl"); int result; if (core_info[coreid].cache_init == false) aice_usb_init_cache(coreid); switch (subtype) { case AICE_CACHE_CTL_L1D_INVALALL: result = aice_usb_dcache_inval_all(coreid); break; case AICE_CACHE_CTL_L1D_VA_INVAL: result = aice_usb_dcache_va_inval(coreid, address); break; case AICE_CACHE_CTL_L1D_WBALL: result = aice_usb_dcache_wb_all(coreid); break; case AICE_CACHE_CTL_L1D_VA_WB: result = aice_usb_dcache_va_wb(coreid, address); break; case AICE_CACHE_CTL_L1I_INVALALL: result = aice_usb_icache_inval_all(coreid); break; case AICE_CACHE_CTL_L1I_VA_INVAL: result = aice_usb_icache_va_inval(coreid, address); break; default: result = ERROR_FAIL; break; } return result; } static int aice_usb_set_retry_times(uint32_t a_retry_times) { aice_max_retry_times = a_retry_times; return ERROR_OK; } static int aice_usb_program_edm(uint32_t coreid, char *command_sequence) { char *command_str; char *reg_name_0; char *reg_name_1; uint32_t data_value; int i; /* init strtok() */ command_str = strtok(command_sequence, ";"); if (command_str == NULL) return ERROR_OK; do { i = 0; /* process one command */ while (command_str[i] == ' ' || command_str[i] == '\n' || command_str[i] == '\r' || command_str[i] == '\t') i++; /* skip ' ', '\r', '\n', '\t' */ command_str = command_str + i; if (strncmp(command_str, "write_misc", 10) == 0) { reg_name_0 = strstr(command_str, "gen_port0"); reg_name_1 = strstr(command_str, "gen_port1"); if (reg_name_0 != NULL) { data_value = strtoul(reg_name_0 + 9, NULL, 0); if (aice_write_misc(coreid, NDS_EDM_MISC_GEN_PORT0, data_value) != ERROR_OK) return ERROR_FAIL; } else if (reg_name_1 != NULL) { data_value = strtoul(reg_name_1 + 9, NULL, 0); if (aice_write_misc(coreid, NDS_EDM_MISC_GEN_PORT1, data_value) != ERROR_OK) return ERROR_FAIL; } else { LOG_ERROR("program EDM, unsupported misc register: %s", command_str); } } else { LOG_ERROR("program EDM, unsupported command: %s", command_str); } /* update command_str */ command_str = strtok(NULL, ";"); } while (command_str != NULL); return ERROR_OK; } static int aice_usb_set_command_mode(enum aice_command_mode command_mode) { int retval = ERROR_OK; /* flush usb_packets_buffer as users change mode */ retval = aice_usb_packet_flush(); if (AICE_COMMAND_MODE_BATCH == command_mode) { /* reset batch buffer */ aice_command_mode = AICE_COMMAND_MODE_NORMAL; retval = aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL, 0x40000); } aice_command_mode = command_mode; return retval; } static int aice_usb_execute(uint32_t coreid, uint32_t *instructions, uint32_t instruction_num) { uint32_t i, j; uint8_t current_instruction_num; uint32_t dim_instructions[4] = {NOP, NOP, NOP, BEQ_MINUS_12}; /* To execute 4 instructions as a special case */ if (instruction_num == 4) return aice_execute_dim(coreid, instructions, 4); for (i = 0 ; i < instruction_num ; i += 3) { if (instruction_num - i < 3) { current_instruction_num = instruction_num - i; for (j = current_instruction_num ; j < 3 ; j++) dim_instructions[j] = NOP; } else { current_instruction_num = 3; } memcpy(dim_instructions, instructions + i, current_instruction_num * sizeof(uint32_t)); /** fill DIM */ if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK) return ERROR_FAIL; /** clear DBGER.DPED */ if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK) return ERROR_FAIL; /** execute DIM */ if (aice_do_execute(coreid) != ERROR_OK) return ERROR_FAIL; /** check DBGER.DPED */ if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) { LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly:" "0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 ". -->", dim_instructions[0], dim_instructions[1], dim_instructions[2], dim_instructions[3]); return ERROR_FAIL; } } return ERROR_OK; } static int aice_usb_set_custom_srst_script(const char *script) { custom_srst_script = strdup(script); return ERROR_OK; } static int aice_usb_set_custom_trst_script(const char *script) { custom_trst_script = strdup(script); return ERROR_OK; } static int aice_usb_set_custom_restart_script(const char *script) { custom_restart_script = strdup(script); return ERROR_OK; } static int aice_usb_set_count_to_check_dbger(uint32_t count_to_check) { aice_count_to_check_dbger = count_to_check; return ERROR_OK; } static int aice_usb_set_data_endian(uint32_t coreid, enum aice_target_endian target_data_endian) { data_endian = target_data_endian; return ERROR_OK; } static int fill_profiling_batch_commands(uint32_t coreid, uint32_t reg_no) { uint32_t dim_instructions[4]; aice_usb_set_command_mode(AICE_COMMAND_MODE_BATCH); /* halt */ if (aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0) != ERROR_OK) return ERROR_FAIL; /* backup $r0 */ dim_instructions[0] = MTSR_DTR(0); dim_instructions[1] = DSB; dim_instructions[2] = NOP; dim_instructions[3] = BEQ_MINUS_12; if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK) return ERROR_FAIL; aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_0); /* get samples */ if (NDS32_REG_TYPE_GPR == nds32_reg_type(reg_no)) { /* general registers */ dim_instructions[0] = MTSR_DTR(reg_no); dim_instructions[1] = DSB; dim_instructions[2] = NOP; dim_instructions[3] = BEQ_MINUS_12; } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(reg_no)) { /* user special registers */ dim_instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(reg_no)); dim_instructions[1] = MTSR_DTR(0); dim_instructions[2] = DSB; dim_instructions[3] = BEQ_MINUS_12; } else { /* system registers */ dim_instructions[0] = MFSR(0, nds32_reg_sr_index(reg_no)); dim_instructions[1] = MTSR_DTR(0); dim_instructions[2] = DSB; dim_instructions[3] = BEQ_MINUS_12; } if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK) return ERROR_FAIL; aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_1); /* restore $r0 */ aice_write_dtr_from_buffer(coreid, AICE_BATCH_DATA_BUFFER_0); dim_instructions[0] = MFSR_DTR(0); dim_instructions[1] = DSB; dim_instructions[2] = NOP; dim_instructions[3] = IRET; /* free run */ if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK) return ERROR_FAIL; aice_command_mode = AICE_COMMAND_MODE_NORMAL; /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */ if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0, usb_out_packets_buffer, (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK) return ERROR_FAIL; usb_out_packets_buffer_length = 0; usb_in_packets_buffer_length = 0; return ERROR_OK; } static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t iteration, uint32_t reg_no, uint32_t *samples, uint32_t *num_samples) { uint32_t iteration_count; uint32_t this_iteration; int retval = ERROR_OK; const uint32_t MAX_ITERATION = 250; *num_samples = 0; /* init DIM size */ if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DIM_SIZE, 4) != ERROR_OK) return ERROR_FAIL; /* Use AICE_BATCH_DATA_BUFFER_0 to read/write $DTR. * Set it to circular buffer */ if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL, 0xC0000) != ERROR_OK) return ERROR_FAIL; fill_profiling_batch_commands(coreid, reg_no); iteration_count = 0; while (iteration_count < iteration) { if (iteration - iteration_count < MAX_ITERATION) this_iteration = iteration - iteration_count; else this_iteration = MAX_ITERATION; /* set number of iterations */ uint32_t val_iteration; val_iteration = interval << 16 | this_iteration; if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_ITERATION, val_iteration) != ERROR_OK) { retval = ERROR_FAIL; goto end_profiling; } /* init AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL to store $PC */ if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL, 0x40000) != ERROR_OK) { retval = ERROR_FAIL; goto end_profiling; } aice_usb_run(coreid); /* enable BATCH command */ if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL, 0x80000000) != ERROR_OK) { aice_usb_halt(coreid); retval = ERROR_FAIL; goto end_profiling; } /* wait a while (AICE bug, workaround) */ alive_sleep(this_iteration); /* check status */ uint32_t i; uint32_t batch_status; i = 0; while (1) { aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status); if (batch_status & 0x1) { break; } else if (batch_status & 0xE) { aice_usb_halt(coreid); retval = ERROR_FAIL; goto end_profiling; } if ((i % 30) == 0) keep_alive(); i++; } aice_usb_halt(coreid); /* get samples from batch data buffer */ if (aice_batch_buffer_read(AICE_BATCH_DATA_BUFFER_1, samples + iteration_count, this_iteration) != ERROR_OK) { retval = ERROR_FAIL; goto end_profiling; } iteration_count += this_iteration; } end_profiling: *num_samples = iteration_count; return retval; } /** */ struct aice_port_api_s aice_usb_api = { /** */ .open = aice_open_device, /** */ .close = aice_usb_close, /** */ .idcode = aice_usb_idcode, /** */ .state = aice_usb_state, /** */ .reset = aice_usb_reset, /** */ .assert_srst = aice_usb_assert_srst, /** */ .run = aice_usb_run, /** */ .halt = aice_usb_halt, /** */ .step = aice_usb_step, /** */ .read_reg = aice_usb_read_reg, /** */ .write_reg = aice_usb_write_reg, /** */ .read_reg_64 = aice_usb_read_reg_64, /** */ .write_reg_64 = aice_usb_write_reg_64, /** */ .read_mem_unit = aice_usb_read_memory_unit, /** */ .write_mem_unit = aice_usb_write_memory_unit, /** */ .read_mem_bulk = aice_usb_bulk_read_mem, /** */ .write_mem_bulk = aice_usb_bulk_write_mem, /** */ .read_debug_reg = aice_usb_read_debug_reg, /** */ .write_debug_reg = aice_usb_write_debug_reg, /** */ .set_jtag_clock = aice_usb_set_jtag_clock, /** */ .memory_access = aice_usb_memory_access, /** */ .memory_mode = aice_usb_memory_mode, /** */ .read_tlb = aice_usb_read_tlb, /** */ .cache_ctl = aice_usb_cache_ctl, /** */ .set_retry_times = aice_usb_set_retry_times, /** */ .program_edm = aice_usb_program_edm, /** */ .set_command_mode = aice_usb_set_command_mode, /** */ .execute = aice_usb_execute, /** */ .set_custom_srst_script = aice_usb_set_custom_srst_script, /** */ .set_custom_trst_script = aice_usb_set_custom_trst_script, /** */ .set_custom_restart_script = aice_usb_set_custom_restart_script, /** */ .set_count_to_check_dbger = aice_usb_set_count_to_check_dbger, /** */ .set_data_endian = aice_usb_set_data_endian, /** */ .profiling = aice_usb_profiling, }; openocd-0.9.0/src/jtag/aice/aice_usb.h0000644000175000017500000001156012315575360014442 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __AICE_USB_H__ #define __AICE_USB_H__ #include "aice_port.h" /* AICE USB timeout value */ #define AICE_USB_TIMEOUT 5000 /* AICE USB buffer size */ #define AICE_IN_BUFFER_SIZE 2048 #define AICE_OUT_BUFFER_SIZE 2048 #define AICE_IN_PACKETS_BUFFER_SIZE 2048 #define AICE_OUT_PACKETS_BUFFER_SIZE 2048 #define AICE_IN_BATCH_COMMAND_SIZE 512 #define AICE_OUT_BATCH_COMMAND_SIZE 512 #define AICE_IN_PACK_COMMAND_SIZE 2048 #define AICE_OUT_PACK_COMMAND_SIZE 2048 /* Constants for AICE command READ_CTRL */ #define AICE_READ_CTRL_GET_ICE_STATE 0x00 #define AICE_READ_CTRL_GET_HARDWARE_VERSION 0x01 #define AICE_READ_CTRL_GET_FPGA_VERSION 0x02 #define AICE_READ_CTRL_GET_FIRMWARE_VERSION 0x03 #define AICE_READ_CTRL_GET_JTAG_PIN_STATUS 0x04 #define AICE_READ_CTRL_BATCH_BUF_INFO 0x22 #define AICE_READ_CTRL_BATCH_STATUS 0x23 #define AICE_READ_CTRL_BATCH_BUF0_STATE 0x31 #define AICE_READ_CTRL_BATCH_BUF4_STATE 0x39 #define AICE_READ_CTRL_BATCH_BUF5_STATE 0x3b /* Constants for AICE command WRITE_CTRL */ #define AICE_WRITE_CTRL_TCK_CONTROL 0x00 #define AICE_WRITE_CTRL_JTAG_PIN_CONTROL 0x01 #define AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS 0x02 #define AICE_WRITE_CTRL_RESERVED 0x03 #define AICE_WRITE_CTRL_JTAG_PIN_STATUS 0x04 #define AICE_WRITE_CTRL_CUSTOM_DELAY 0x0d #define AICE_WRITE_CTRL_BATCH_CTRL 0x20 #define AICE_WRITE_CTRL_BATCH_ITERATION 0x21 #define AICE_WRITE_CTRL_BATCH_DIM_SIZE 0x22 #define AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL 0x30 #define AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL 0x38 #define AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL 0x3a #define AICE_BATCH_COMMAND_BUFFER_0 0x0 #define AICE_BATCH_COMMAND_BUFFER_1 0x1 #define AICE_BATCH_COMMAND_BUFFER_2 0x2 #define AICE_BATCH_COMMAND_BUFFER_3 0x3 #define AICE_BATCH_DATA_BUFFER_0 0x4 #define AICE_BATCH_DATA_BUFFER_1 0x5 #define AICE_BATCH_DATA_BUFFER_2 0x6 #define AICE_BATCH_DATA_BUFFER_3 0x7 /* Constants for AICE command WRITE_CTRL:TCK_CONTROL */ #define AICE_TCK_CONTROL_TCK3048 0x08 /* Constants for AICE command WRITE_CTRL:JTAG_PIN_CONTROL */ #define AICE_JTAG_PIN_CONTROL_SRST 0x01 #define AICE_JTAG_PIN_CONTROL_TRST 0x02 #define AICE_JTAG_PIN_CONTROL_STOP 0x04 #define AICE_JTAG_PIN_CONTROL_RESTART 0x08 /* Constants for AICE command WRITE_CTRL:TCK_CONTROL */ #define AICE_TCK_CONTROL_TCK_SCAN 0x10 /* Custom SRST/DBGI/TRST */ #define AICE_CUSTOM_DELAY_SET_SRST 0x01 #define AICE_CUSTOM_DELAY_CLEAN_SRST 0x02 #define AICE_CUSTOM_DELAY_SET_DBGI 0x04 #define AICE_CUSTOM_DELAY_CLEAN_DBGI 0x08 #define AICE_CUSTOM_DELAY_SET_TRST 0x10 #define AICE_CUSTOM_DELAY_CLEAN_TRST 0x20 struct aice_usb_handler_s { unsigned int usb_read_ep; unsigned int usb_write_ep; struct jtag_libusb_device_handle *usb_handle; }; struct cache_info { uint32_t set; uint32_t way; uint32_t line_size; uint32_t log2_set; uint32_t log2_line_size; }; struct aice_nds32_info { uint32_t edm_version; uint32_t r0_backup; uint32_t r1_backup; uint32_t host_dtr_backup; uint32_t target_dtr_backup; uint32_t edmsw_backup; uint32_t edm_ctl_backup; bool debug_under_dex_on; bool dex_use_psw_on; bool host_dtr_valid; bool target_dtr_valid; enum nds_memory_access access_channel; enum nds_memory_select memory_select; enum aice_target_state_s core_state; bool cache_init; struct cache_info icache; struct cache_info dcache; }; extern struct aice_port_api_s aice_usb_api; int aice_read_ctrl(uint32_t address, uint32_t *data); int aice_write_ctrl(uint32_t address, uint32_t data); #endif openocd-0.9.0/src/jtag/interface.c0000644000175000017500000003430512315575360013724 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag.h" #include "interface.h" /** * @see tap_set_state() and tap_get_state() accessors. * Actual name is not important since accessors hide it. */ static tap_state_t state_follower = TAP_RESET; void tap_set_state_impl(tap_state_t new_state) { /* this is the state we think the TAPs are in now, was cur_state */ state_follower = new_state; } tap_state_t tap_get_state() { return state_follower; } /** * @see tap_set_end_state() and tap_get_end_state() accessors. * Actual name is not important because accessors hide it. */ static tap_state_t end_state_follower = TAP_RESET; void tap_set_end_state(tap_state_t new_end_state) { /* this is the state we think the TAPs will be in at completion of the * current TAP operation, was end_state */ end_state_follower = new_end_state; } tap_state_t tap_get_end_state() { return end_state_follower; } int tap_move_ndx(tap_state_t astate) { /* given a stable state, return the index into the tms_seqs[] * array within tap_get_tms_path() */ int ndx; switch (astate) { case TAP_RESET: ndx = 0; break; case TAP_IDLE: ndx = 1; break; case TAP_DRSHIFT: ndx = 2; break; case TAP_DRPAUSE: ndx = 3; break; case TAP_IRSHIFT: ndx = 4; break; case TAP_IRPAUSE: ndx = 5; break; default: LOG_ERROR("FATAL: unstable state \"%s\" in tap_move_ndx()", tap_state_name(astate)); exit(1); } return ndx; } /* tap_move[i][j]: tap movement command to go from state i to state j * encodings of i and j are what tap_move_ndx() reports. * * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code */ struct tms_sequences { uint8_t bits; uint8_t bit_count; }; /* * These macros allow us to specify TMS state transitions by bits rather than hex bytes. * Read the bits from LSBit first to MSBit last (right-to-left). */ #define HEX__(n) 0x##n##LU #define B8__(x) \ ((((x) & 0x0000000FLU) ? (1 << 0) : 0) \ +(((x) & 0x000000F0LU) ? (1 << 1) : 0) \ +(((x) & 0x00000F00LU) ? (1 << 2) : 0) \ +(((x) & 0x0000F000LU) ? (1 << 3) : 0) \ +(((x) & 0x000F0000LU) ? (1 << 4) : 0) \ +(((x) & 0x00F00000LU) ? (1 << 5) : 0) \ +(((x) & 0x0F000000LU) ? (1 << 6) : 0) \ +(((x) & 0xF0000000LU) ? (1 << 7) : 0)) #define B8(bits, count) {((uint8_t)B8__(HEX__(bits))), (count)} static const struct tms_sequences old_tms_seqs[6][6] = { /* [from_state_ndx][to_state_ndx] */ /* value clocked to TMS to move from one of six stable states to another. * N.B. OOCD clocks TMS from LSB first, so read these right-to-left. * N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable. * These extra ones cause no TAP state problem, because we go into reset and stay in reset. */ /* to state: */ /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ {B8(1111111, 7), B8(0000000, 7), B8(0010111, 7), B8(0001010, 7), B8(0011011, 7), B8(0010110, 7)},/* RESET */ {B8(1111111, 7), B8(0000000, 7), B8(0100101, 7), B8(0000101, 7), B8(0101011, 7), B8(0001011, 7)},/* IDLE */ {B8(1111111, 7), B8(0110001, 7), B8(0000000, 7), B8(0000001, 7), B8(0001111, 7), B8(0101111, 7)},/* DRSHIFT */ {B8(1111111, 7), B8(0110000, 7), B8(0100000, 7), B8(0010111, 7), B8(0011110, 7), B8(0101111, 7)},/* DRPAUSE */ {B8(1111111, 7), B8(0110001, 7), B8(0000111, 7), B8(0010111, 7), B8(0000000, 7), B8(0000001, 7)},/* IRSHIFT */ {B8(1111111, 7), B8(0110000, 7), B8(0011100, 7), B8(0010111, 7), B8(0011110, 7), B8(0101111, 7)},/* IRPAUSE */ }; static const struct tms_sequences short_tms_seqs[6][6] = { /* [from_state_ndx][to_state_ndx] */ /* this is the table submitted by Jeff Williams on 3/30/2009 with this comment: OK, I added Peter's version of the state table, and it works OK for me on MC1322x. I've recreated the jlink portion of patch with this new state table. His changes to my state table are pretty minor in terms of total transitions, but Peter feels that his version fixes some long-standing problems. Jeff I added the bit count into the table, reduced RESET column to 7 bits from 8. Dick state specific comments: ------------------------ *->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to work better on ARM9 with ft2232 driver. (Dick) RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing. needed on ARM9 with ft2232 driver. (Dick) (For a total of *THREE* extra clocks in RESET; NOP.) RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing. needed on ARM9 with ft2232 driver. (Dick) (For a total of *TWO* extra clocks in RESET; NOP.) RESET->* always adds one or more clocks in the target state, which should be NOPS; except shift states which (as noted above) add those clocks in RESET. The X-to-X transitions always add clocks; from *SHIFT, they go via IDLE and thus *DO HAVE SIDE EFFECTS* (capture and update). */ /* to state: */ /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ {B8(1111111, 7), B8(0000000, 7), B8(0010111, 7), B8(0001010, 7), B8(0011011, 7), B8(0010110, 7)}, /* RESET */ {B8(1111111, 7), B8(0000000, 7), B8(001, 3), B8(0101, 4), B8(0011, 4), B8(01011, 5)}, /* IDLE */ {B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(01, 2), B8(001111, 6), B8(0101111, 7)}, /* DRSHIFT */ {B8(1111111, 7), B8(011, 3), B8(01, 2), B8(0, 1), B8(001111, 6), B8(0101111, 7)}, /* DRPAUSE */ {B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(010111, 6), B8(001111, 6), B8(01, 2)}, /* IRSHIFT */ {B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(010111, 6), B8(01, 2), B8(0, 1)} /* IRPAUSE */ }; typedef const struct tms_sequences tms_table[6][6]; static tms_table *tms_seqs = &short_tms_seqs; int tap_get_tms_path(tap_state_t from, tap_state_t to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits; } int tap_get_tms_path_len(tap_state_t from, tap_state_t to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count; } bool tap_is_state_stable(tap_state_t astate) { bool is_stable; /* A switch () is used because it is symbol dependent * (not value dependent like an array), and can also check bounds. */ switch (astate) { case TAP_RESET: case TAP_IDLE: case TAP_DRSHIFT: case TAP_DRPAUSE: case TAP_IRSHIFT: case TAP_IRPAUSE: is_stable = true; break; default: is_stable = false; } return is_stable; } tap_state_t tap_state_transition(tap_state_t cur_state, bool tms) { tap_state_t new_state; /* A switch is used because it is symbol dependent and not value dependent * like an array. Also it can check for out of range conditions. */ if (tms) { switch (cur_state) { case TAP_RESET: new_state = cur_state; break; case TAP_IDLE: case TAP_DRUPDATE: case TAP_IRUPDATE: new_state = TAP_DRSELECT; break; case TAP_DRSELECT: new_state = TAP_IRSELECT; break; case TAP_DRCAPTURE: case TAP_DRSHIFT: new_state = TAP_DREXIT1; break; case TAP_DREXIT1: case TAP_DREXIT2: new_state = TAP_DRUPDATE; break; case TAP_DRPAUSE: new_state = TAP_DREXIT2; break; case TAP_IRSELECT: new_state = TAP_RESET; break; case TAP_IRCAPTURE: case TAP_IRSHIFT: new_state = TAP_IREXIT1; break; case TAP_IREXIT1: case TAP_IREXIT2: new_state = TAP_IRUPDATE; break; case TAP_IRPAUSE: new_state = TAP_IREXIT2; break; default: LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state); exit(1); break; } } else { switch (cur_state) { case TAP_RESET: case TAP_IDLE: case TAP_DRUPDATE: case TAP_IRUPDATE: new_state = TAP_IDLE; break; case TAP_DRSELECT: new_state = TAP_DRCAPTURE; break; case TAP_DRCAPTURE: case TAP_DRSHIFT: case TAP_DREXIT2: new_state = TAP_DRSHIFT; break; case TAP_DREXIT1: case TAP_DRPAUSE: new_state = TAP_DRPAUSE; break; case TAP_IRSELECT: new_state = TAP_IRCAPTURE; break; case TAP_IRCAPTURE: case TAP_IRSHIFT: case TAP_IREXIT2: new_state = TAP_IRSHIFT; break; case TAP_IREXIT1: case TAP_IRPAUSE: new_state = TAP_IRPAUSE; break; default: LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state); exit(1); break; } } return new_state; } /* NOTE: do not change these state names. They're documented, * and we rely on them to match SVF input (except for "RUN/IDLE"). */ static const struct name_mapping { enum tap_state symbol; const char *name; } tap_name_mapping[] = { { TAP_RESET, "RESET", }, { TAP_IDLE, "RUN/IDLE", }, { TAP_DRSELECT, "DRSELECT", }, { TAP_DRCAPTURE, "DRCAPTURE", }, { TAP_DRSHIFT, "DRSHIFT", }, { TAP_DREXIT1, "DREXIT1", }, { TAP_DRPAUSE, "DRPAUSE", }, { TAP_DREXIT2, "DREXIT2", }, { TAP_DRUPDATE, "DRUPDATE", }, { TAP_IRSELECT, "IRSELECT", }, { TAP_IRCAPTURE, "IRCAPTURE", }, { TAP_IRSHIFT, "IRSHIFT", }, { TAP_IREXIT1, "IREXIT1", }, { TAP_IRPAUSE, "IRPAUSE", }, { TAP_IREXIT2, "IREXIT2", }, { TAP_IRUPDATE, "IRUPDATE", }, /* only for input: accept standard SVF name */ { TAP_IDLE, "IDLE", }, }; const char *tap_state_name(tap_state_t state) { unsigned i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { if (tap_name_mapping[i].symbol == state) return tap_name_mapping[i].name; } return "???"; } tap_state_t tap_state_by_name(const char *name) { unsigned i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { /* be nice to the human */ if (strcasecmp(name, tap_name_mapping[i].name) == 0) return tap_name_mapping[i].symbol; } /* not found */ return TAP_INVALID; } #ifdef _DEBUG_JTAG_IO_ #define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \ do { buf[len] = bit ? '1' : '0'; } while (0) #define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \ DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \ tap_state_name(a), tap_state_name(b), astr, bstr) tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf, unsigned tap_bits, tap_state_t next_state) { const uint8_t *tms_buffer; const uint8_t *tdi_buffer; unsigned tap_bytes; unsigned cur_byte; unsigned cur_bit; unsigned tap_out_bits; char tms_str[33]; char tdi_str[33]; tap_state_t last_state; /* set startstate (and possibly last, if tap_bits == 0) */ last_state = next_state; DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state)); tms_buffer = (const uint8_t *)tms_buf; tdi_buffer = (const uint8_t *)tdi_buf; tap_bytes = DIV_ROUND_UP(tap_bits, 8); DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes); tap_out_bits = 0; for (cur_byte = 0; cur_byte < tap_bytes; cur_byte++) { for (cur_bit = 0; cur_bit < 8; cur_bit++) { /* make sure we do not run off the end of the buffers */ unsigned tap_bit = cur_byte * 8 + cur_bit; if (tap_bit == tap_bits) break; /* check and save TMS bit */ tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit)); JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit); /* use TMS bit to find the next TAP state */ next_state = tap_state_transition(last_state, tap_bit); /* check and store TDI bit */ tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit)); JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit); /* increment TAP bits */ tap_out_bits++; /* Only show TDO bits on state transitions, or */ /* after some number of bits in the same state. */ if ((next_state == last_state) && (tap_out_bits < 32)) continue; /* terminate strings and display state transition */ tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0; JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str); /* reset state */ last_state = next_state; tap_out_bits = 0; } } if (tap_out_bits) { /* terminate strings and display state transition */ tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0; JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str); } DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state)); return next_state; } #endif /* _DEBUG_JTAG_IO_ */ void tap_use_new_tms_table(bool use_new) { tms_seqs = use_new ? &short_tms_seqs : &old_tms_seqs; } bool tap_uses_new_tms_table(void) { return tms_seqs == &short_tms_seqs; } openocd-0.9.0/src/jtag/interface.h0000644000175000017500000003073512516456303013732 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OPENOCD_JTAG_INTERFACE_H #define OPENOCD_JTAG_INTERFACE_H #include #include /* @file * The "Cable Helper API" is what the cable drivers can use to help * implement their "Cable API". So a Cable Helper API is a set of * helper functions used by cable drivers, and this is different from a * Cable API. A "Cable API" is what higher level code used to talk to a * cable. */ /** implementation of wrapper function tap_set_state() */ void tap_set_state_impl(tap_state_t new_state); /** * This function sets the state of a "state follower" which tracks the * state of the TAPs connected to the cable. The state follower is * hopefully always in the same state as the actual TAPs in the jtag * chain, and will be so if there are no bugs in the tracking logic * within that cable driver. * * All the cable drivers call this function to indicate the state they * think the TAPs attached to their cables are in. Because this * function can also log transitions, it will be helpful to call this * function with every transition that the TAPs being manipulated are * expected to traverse, not just end points of a multi-step state path. * * @param new_state The state we think the TAPs are currently in (or * are about to enter). */ #if defined(_DEBUG_JTAG_IO_) #define tap_set_state(new_state) \ do { \ LOG_DEBUG("tap_set_state(%s)", tap_state_name(new_state)); \ tap_set_state_impl(new_state); \ } while (0) #else static inline void tap_set_state(tap_state_t new_state) { tap_set_state_impl(new_state); } #endif /** * This function gets the state of the "state follower" which tracks the * state of the TAPs connected to the cable. @see tap_set_state @return * tap_state_t The state the TAPs are in now. */ tap_state_t tap_get_state(void); /** * This function sets the state of an "end state follower" which tracks * the state that any cable driver thinks will be the end (resultant) * state of the current TAP SIR or SDR operation. * * At completion of that TAP operation this value is copied into the * state follower via tap_set_state(). * * @param new_end_state The state the TAPs should enter at completion of * a pending TAP operation. */ void tap_set_end_state(tap_state_t new_end_state); /** * For more information, @see tap_set_end_state * @return tap_state_t - The state the TAPs should be in at completion of the current TAP operation. */ tap_state_t tap_get_end_state(void); /** * This function provides a "bit sequence" indicating what has to be * done with TMS during a sequence of seven TAP clock cycles in order to * get from state \a "from" to state \a "to". * * The length of the sequence must be determined with a parallel call to * tap_get_tms_path_len(). * * @param from The starting state. * @param to The desired final state. * @return int The required TMS bit sequence, with the first bit in the * sequence at bit 0. */ int tap_get_tms_path(tap_state_t from, tap_state_t to); /** * Function int tap_get_tms_path_len * returns the total number of bits that represents a TMS path * transition as given by the function tap_get_tms_path(). * * For at least one interface (JLink) it's not OK to simply "pad" TMS * sequences to fit a whole byte. (I suspect this is a general TAP * problem within OOCD.) Padding TMS causes all manner of instability * that's not easily discovered. Using this routine we can apply * EXACTLY the state transitions required to make something work - no * more - no less. * * @param from is the starting state * @param to is the resultant or final state * @return int - the total number of bits in a transition. */ int tap_get_tms_path_len(tap_state_t from, tap_state_t to); /** * Function tap_move_ndx * when given a stable state, returns an index from 0-5. The index corresponds to a * sequence of stable states which are given in this order:

* { TAP_RESET, TAP_IDLE, TAP_DRSHIFT, TAP_DRPAUSE, TAP_IRSHIFT, TAP_IRPAUSE } *

* This sequence corresponds to look up tables which are used in some of the * cable drivers. * @param astate is the stable state to find in the sequence. If a non stable * state is passed, this may cause the program to output an error message * and terminate. * @return int - the array (or sequence) index as described above */ int tap_move_ndx(tap_state_t astate); /** * Function tap_is_state_stable * returns true if the \a astate is stable. */ bool tap_is_state_stable(tap_state_t astate); /** * Function tap_state_transition * takes a current TAP state and returns the next state according to the tms value. * @param current_state is the state of a TAP currently. * @param tms is either zero or non-zero, just like a real TMS line in a jtag interface. * @return tap_state_t - the next state a TAP would enter. */ tap_state_t tap_state_transition(tap_state_t current_state, bool tms); /** Allow switching between old and new TMS tables. @see tap_get_tms_path */ void tap_use_new_tms_table(bool use_new); /** @returns True if new TMS table is active; false otherwise. */ bool tap_uses_new_tms_table(void); #ifdef _DEBUG_JTAG_IO_ /** * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers. * @param tms_buf must points to a buffer containing the TMS bitstream. * @param tdi_buf must points to a buffer containing the TDI bitstream. * @param tap_len must specify the length of the TMS/TDI bitstreams. * @param start_tap_state must specify the current TAP state. * @returns the final TAP state; pass as @a start_tap_state in following call. */ tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state); #else static inline tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state) { return start_tap_state; } #endif /* _DEBUG_JTAG_IO_ */ /** * Represents a driver for a debugging interface. * * @todo Rename; perhaps "debug_driver". This isn't an interface, * it's a driver! Also, not all drivers support JTAG. * * @todo We need a per-instance structure too, and changes to pass * that structure to the driver. Instances can for example be in * either SWD or JTAG modes. This will help remove globals, and * eventually to cope with systems which have more than one such * debugging interface. */ struct jtag_interface { /** The name of the JTAG interface driver. */ const char * const name; /** * Bit vector listing capabilities exposed by this driver. */ unsigned supported; #define DEBUG_CAP_TMS_SEQ (1 << 0) /** transports supported in C code (NULL terminated vector) */ const char * const *transports; const struct swd_driver *swd; /** * Execute queued commands. * @returns ERROR_OK on success, or an error code on failure. */ int (*execute_queue)(void); /** * Set the interface speed. * @param speed The new interface speed setting. * @returns ERROR_OK on success, or an error code on failure. */ int (*speed)(int speed); /** * The interface driver may register additional commands to expose * additional features not covered by the standard command set. */ const struct command_registration *commands; /** * Interface driver must initialize any resources and connect to a * JTAG device. * * quit() is invoked if and only if init() succeeds. quit() is always * invoked if init() succeeds. Same as malloc() + free(). Always * invoke free() if malloc() succeeds and do not invoke free() * otherwise. * * @returns ERROR_OK on success, or an error code on failure. */ int (*init)(void); /** * Interface driver must tear down all resources and disconnect from * the JTAG device. * * @returns ERROR_OK on success, or an error code on failure. */ int (*quit)(void); /** * Returns JTAG maxium speed for KHz. 0 = RTCK. The function returns * a failure if it can't support the KHz/RTCK. * * WARNING!!!! if RTCK is *slow* then think carefully about * whether you actually want to support this in the driver. * Many target scripts are written to handle the absence of RTCK * and use a fallback kHz TCK. * @returns ERROR_OK on success, or an error code on failure. */ int (*khz)(int khz, int *jtag_speed); /** * Calculate the clock frequency (in KHz) for the given @a speed. * @param speed The desired interface speed setting. * @param khz On return, contains the speed in KHz (0 for RTCK). * @returns ERROR_OK on success, or an error code if the * interface cannot support the specified speed (KHz or RTCK). */ int (*speed_div)(int speed, int *khz); /** * Read and clear the power dropout flag. Note that a power dropout * can be transitionary, easily much less than a ms. * * To find out if the power is *currently* on, one must invoke this * method twice. Once to clear the power dropout flag and a second * time to read the current state. The default implementation * never reports power dropouts. * * @returns ERROR_OK on success, or an error code on failure. */ int (*power_dropout)(int *power_dropout); /** * Read and clear the srst asserted detection flag. * * Like power_dropout this does *not* read the current * state. SRST assertion is transitionary and may be much * less than 1ms, so the interface driver must watch for these * events until this routine is called. * * @param srst_asserted On return, indicates whether SRST has * been asserted. * @returns ERROR_OK on success, or an error code on failure. */ int (*srst_asserted)(int *srst_asserted); /** * Configure trace parameters for the adapter * * @param enabled Whether to enable trace * @param pin_protocol Configured pin protocol * @param port_size Trace port width for sync mode * @param trace_freq A pointer to the configured trace * frequency; if it points to 0, the adapter driver must write * its maximum supported rate there * @returns ERROR_OK on success, an error code on failure. */ int (*config_trace)(bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); /** * Poll for new trace data * * @param buf A pointer to buffer to store received data * @param size A pointer to buffer size; must be filled with * the actual amount of bytes written * * @returns ERROR_OK on success, an error code on failure. */ int (*poll_trace)(uint8_t *buf, size_t *size); }; extern const char * const jtag_only[]; void adapter_assert_reset(void); void adapter_deassert_reset(void); int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); int adapter_poll_trace(uint8_t *buf, size_t *size); #endif /* OPENOCD_JTAG_INTERFACE_H */ openocd-0.9.0/src/jtag/tcl.c0000644000175000017500000010613712516456303012547 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag.h" #include "swd.h" #include "minidriver.h" #include "interface.h" #include "interfaces.h" #include "tcl.h" #ifdef HAVE_STRINGS_H #include #endif #include /** * @file * Holds support for accessing JTAG-specific mechanisms from TCl scripts. */ static const Jim_Nvp nvp_jtag_tap_event[] = { { .value = JTAG_TRST_ASSERTED, .name = "post-reset" }, { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" }, { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" }, { .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" }, { .name = NULL, .value = -1 } }; struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) { const char *cp = Jim_GetString(o, NULL); struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL; if (NULL == cp) cp = "(unknown)"; if (NULL == t) Jim_SetResultFormatted(interp, "Tap '%s' could not be found", cp); return t; } static bool scan_is_safe(tap_state_t state) { switch (state) { case TAP_RESET: case TAP_IDLE: case TAP_DRPAUSE: case TAP_IRPAUSE: return true; default: return false; } } static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args) { int retval; struct scan_field *fields; int num_fields; int field_count = 0; int i, e; struct jtag_tap *tap; tap_state_t endstate; /* args[1] = device * args[2] = num_bits * args[3] = hex string * ... repeat num bits and hex string ... * * .. optionally: * args[N-2] = "-endstate" * args[N-1] = statename */ if ((argc < 4) || ((argc % 2) != 0)) { Jim_WrongNumArgs(interp, 1, args, "wrong arguments"); return JIM_ERR; } endstate = TAP_IDLE; script_debug(interp, "drscan", argc, args); /* validate arguments as numbers */ e = JIM_OK; for (i = 2; i < argc; i += 2) { long bits; const char *cp; e = Jim_GetLong(interp, args[i], &bits); /* If valid - try next arg */ if (e == JIM_OK) continue; /* Not valid.. are we at the end? */ if (((i + 2) != argc)) { /* nope, then error */ return e; } /* it could be: "-endstate FOO" * e.g. DRPAUSE so we can issue more instructions * before entering RUN/IDLE and executing them. */ /* get arg as a string. */ cp = Jim_GetString(args[i], NULL); /* is it the magic? */ if (0 == strcmp("-endstate", cp)) { /* is the statename valid? */ cp = Jim_GetString(args[i + 1], NULL); /* see if it is a valid state name */ endstate = tap_state_by_name(cp); if (endstate < 0) { /* update the error message */ Jim_SetResultFormatted(interp, "endstate: %s invalid", cp); } else { if (!scan_is_safe(endstate)) LOG_WARNING("drscan with unsafe " "endstate \"%s\"", cp); /* valid - so clear the error */ e = JIM_OK; /* and remove the last 2 args */ argc -= 2; } } /* Still an error? */ if (e != JIM_OK) return e; /* too bad */ } /* validate args */ assert(e == JIM_OK); tap = jtag_tap_by_jim_obj(interp, args[1]); if (tap == NULL) return JIM_ERR; num_fields = (argc-2)/2; if (num_fields <= 0) { Jim_SetResultString(interp, "drscan: no scan fields supplied", -1); return JIM_ERR; } fields = malloc(sizeof(struct scan_field) * num_fields); for (i = 2; i < argc; i += 2) { long bits; int len; const char *str; Jim_GetLong(interp, args[i], &bits); str = Jim_GetString(args[i + 1], &len); fields[field_count].num_bits = bits; void *t = malloc(DIV_ROUND_UP(bits, 8)); fields[field_count].out_value = t; str_to_buf(str, len, t, bits, 0); fields[field_count].in_value = t; field_count++; } jtag_add_dr_scan(tap, num_fields, fields, endstate); retval = jtag_execute_queue(); if (retval != ERROR_OK) { Jim_SetResultString(interp, "drscan: jtag execute failed", -1); return JIM_ERR; } field_count = 0; Jim_Obj *list = Jim_NewListObj(interp, NULL, 0); for (i = 2; i < argc; i += 2) { long bits; char *str; Jim_GetLong(interp, args[i], &bits); str = buf_to_str(fields[field_count].in_value, bits, 16); free(fields[field_count].in_value); Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str))); free(str); field_count++; } Jim_SetResult(interp, list); free(fields); return JIM_OK; } static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *args) { tap_state_t states[8]; if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1))) { Jim_WrongNumArgs(interp, 1, args, "wrong arguments"); return JIM_ERR; } script_debug(interp, "pathmove", argc, args); int i; for (i = 0; i < argc-1; i++) { const char *cp; cp = Jim_GetString(args[i + 1], NULL); states[i] = tap_state_by_name(cp); if (states[i] < 0) { /* update the error message */ Jim_SetResultFormatted(interp, "endstate: %s invalid", cp); return JIM_ERR; } } if ((jtag_add_statemove(states[0]) != ERROR_OK) || (jtag_execute_queue() != ERROR_OK)) { Jim_SetResultString(interp, "pathmove: jtag execute failed", -1); return JIM_ERR; } jtag_add_pathmove(argc - 2, states + 1); if (jtag_execute_queue() != ERROR_OK) { Jim_SetResultString(interp, "pathmove: failed", -1); return JIM_ERR; } return JIM_OK; } static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args) { script_debug(interp, "flush_count", argc, args); Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count())); return JIM_OK; } /* REVISIT Just what about these should "move" ... ? * These registrations, into the main JTAG table? * * There's a minor compatibility issue, these all show up twice; * that's not desirable: * - jtag drscan ... NOT DOCUMENTED! * - drscan ... * * The "irscan" command (for example) doesn't show twice. */ static const struct command_registration jtag_command_handlers_to_move[] = { { .name = "drscan", .mode = COMMAND_EXEC, .jim_handler = Jim_Command_drscan, .help = "Execute Data Register (DR) scan for one TAP. " "Other TAPs must be in BYPASS mode.", .usage = "tap_name [num_bits value]* ['-endstate' state_name]", }, { .name = "flush_count", .mode = COMMAND_EXEC, .jim_handler = Jim_Command_flush_count, .help = "Returns the number of times the JTAG queue " "has been flushed.", }, { .name = "pathmove", .mode = COMMAND_EXEC, .jim_handler = Jim_Command_pathmove, .usage = "start_state state1 [state2 [state3 ...]]", .help = "Move JTAG state machine from current state " "(start_state) to state1, then state2, state3, etc.", }, COMMAND_REGISTRATION_DONE }; enum jtag_tap_cfg_param { JCFG_EVENT }; static Jim_Nvp nvp_config_opts[] = { { .name = "-event", .value = JCFG_EVENT }, { .name = NULL, .value = -1 } }; static int jtag_tap_configure_event(Jim_GetOptInfo *goi, struct jtag_tap *tap) { if (goi->argc == 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ..."); return JIM_ERR; } Jim_Nvp *n; int e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1); return e; } if (goi->isconfigure) { if (goi->argc != 1) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event "); return JIM_ERR; } } else { if (goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event "); return JIM_ERR; } } struct jtag_tap_event_action *jteap = tap->event_action; /* replace existing event body */ bool found = false; while (jteap) { if (jteap->event == (enum jtag_event)n->value) { found = true; break; } jteap = jteap->next; } Jim_SetEmptyResult(goi->interp); if (goi->isconfigure) { if (!found) jteap = calloc(1, sizeof(*jteap)); else if (NULL != jteap->body) Jim_DecrRefCount(goi->interp, jteap->body); jteap->interp = goi->interp; jteap->event = n->value; Jim_Obj *o; Jim_GetOpt_Obj(goi, &o); jteap->body = Jim_DuplicateObj(goi->interp, o); Jim_IncrRefCount(jteap->body); if (!found) { /* add to head of event list */ jteap->next = tap->event_action; tap->event_action = jteap; } } else if (found) { jteap->interp = goi->interp; Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body)); } return JIM_OK; } static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, struct jtag_tap *tap) { /* parse config or cget options */ while (goi->argc > 0) { Jim_SetEmptyResult(goi->interp); Jim_Nvp *n; int e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); return e; } switch (n->value) { case JCFG_EVENT: e = jtag_tap_configure_event(goi, tap); if (e != JIM_OK) return e; break; default: Jim_SetResultFormatted(goi->interp, "unknown event: %s", n->name); return JIM_ERR; } } return JIM_OK; } static int is_bad_irval(int ir_length, jim_wide w) { jim_wide v = 1; v <<= ir_length; v -= 1; v = ~v; return (w & v) != 0; } static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, struct jtag_tap *pTap) { jim_wide w; int e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) { Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name); return e; } uint32_t *p = realloc(pTap->expected_ids, (pTap->expected_ids_cnt + 1) * sizeof(uint32_t)); if (!p) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } pTap->expected_ids = p; pTap->expected_ids[pTap->expected_ids_cnt++] = w; return JIM_OK; } #define NTAP_OPT_IRLEN 0 #define NTAP_OPT_IRMASK 1 #define NTAP_OPT_IRCAPTURE 2 #define NTAP_OPT_ENABLED 3 #define NTAP_OPT_DISABLED 4 #define NTAP_OPT_EXPECTED_ID 5 #define NTAP_OPT_VERSION 6 static int jim_newtap_ir_param(Jim_Nvp *n, Jim_GetOptInfo *goi, struct jtag_tap *pTap) { jim_wide w; int e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) { Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name); return e; } switch (n->value) { case NTAP_OPT_IRLEN: if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value))) { LOG_WARNING("%s: huge IR length %d", pTap->dotted_name, (int) w); } pTap->ir_length = w; break; case NTAP_OPT_IRMASK: if (is_bad_irval(pTap->ir_length, w)) { LOG_ERROR("%s: IR mask %x too big", pTap->dotted_name, (int) w); return JIM_ERR; } if ((w & 3) != 3) LOG_WARNING("%s: nonstandard IR mask", pTap->dotted_name); pTap->ir_capture_mask = w; break; case NTAP_OPT_IRCAPTURE: if (is_bad_irval(pTap->ir_length, w)) { LOG_ERROR("%s: IR capture %x too big", pTap->dotted_name, (int) w); return JIM_ERR; } if ((w & 3) != 1) LOG_WARNING("%s: nonstandard IR value", pTap->dotted_name); pTap->ir_capture_value = w; break; default: return JIM_ERR; } return JIM_OK; } static int jim_newtap_cmd(Jim_GetOptInfo *goi) { struct jtag_tap *pTap; int x; int e; Jim_Nvp *n; char *cp; const Jim_Nvp opts[] = { { .name = "-irlen", .value = NTAP_OPT_IRLEN }, { .name = "-irmask", .value = NTAP_OPT_IRMASK }, { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE }, { .name = "-enable", .value = NTAP_OPT_ENABLED }, { .name = "-disable", .value = NTAP_OPT_DISABLED }, { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID }, { .name = "-ignore-version", .value = NTAP_OPT_VERSION }, { .name = NULL, .value = -1 }, }; pTap = calloc(1, sizeof(struct jtag_tap)); if (!pTap) { Jim_SetResultFormatted(goi->interp, "no memory"); return JIM_ERR; } /* * we expect CHIP + TAP + OPTIONS * */ if (goi->argc < 3) { Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ...."); free(pTap); return JIM_ERR; } Jim_GetOpt_String(goi, &cp, NULL); pTap->chip = strdup(cp); Jim_GetOpt_String(goi, &cp, NULL); pTap->tapname = strdup(cp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; cp = malloc(x); sprintf(cp, "%s.%s", pTap->chip, pTap->tapname); pTap->dotted_name = cp; LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); if (!transport_is_jtag()) { /* SWD doesn't require any JTAG tap parameters */ pTap->enabled = true; jtag_tap_init(pTap); return JIM_OK; } /* IEEE specifies that the two LSBs of an IR scan are 01, so make * that the default. The "-ircapture" and "-irmask" options are only * needed to cope with nonstandard TAPs, or to specify more bits. */ pTap->ir_capture_mask = 0x03; pTap->ir_capture_value = 0x01; while (goi->argc) { e = Jim_GetOpt_Nvp(goi, opts, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, opts, 0); free(cp); free(pTap); return e; } LOG_DEBUG("Processing option: %s", n->name); switch (n->value) { case NTAP_OPT_ENABLED: pTap->disabled_after_reset = false; break; case NTAP_OPT_DISABLED: pTap->disabled_after_reset = true; break; case NTAP_OPT_EXPECTED_ID: e = jim_newtap_expected_id(n, goi, pTap); if (JIM_OK != e) { free(cp); free(pTap); return e; } break; case NTAP_OPT_IRLEN: case NTAP_OPT_IRMASK: case NTAP_OPT_IRCAPTURE: e = jim_newtap_ir_param(n, goi, pTap); if (JIM_OK != e) { free(cp); free(pTap); return e; } break; case NTAP_OPT_VERSION: pTap->ignore_version = true; break; } /* switch (n->value) */ } /* while (goi->argc) */ /* default is enabled-after-reset */ pTap->enabled = !pTap->disabled_after_reset; /* Did all the required option bits get cleared? */ if (pTap->ir_length != 0) { jtag_tap_init(pTap); return JIM_OK; } Jim_SetResultFormatted(goi->interp, "newtap: %s missing IR length", pTap->dotted_name); jtag_tap_free(pTap); return JIM_ERR; } static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e) { struct jtag_tap_event_action *jteap; for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) { if (jteap->event != e) continue; Jim_Nvp *nvp = Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e); LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s", tap->dotted_name, e, nvp->name, Jim_GetString(jteap->body, NULL)); if (Jim_EvalObj(jteap->interp, jteap->body) != JIM_OK) { Jim_MakeErrorMessage(jteap->interp); LOG_USER("%s", Jim_GetString(Jim_GetResult(jteap->interp), NULL)); continue; } switch (e) { case JTAG_TAP_EVENT_ENABLE: case JTAG_TAP_EVENT_DISABLE: /* NOTE: we currently assume the handlers * can't fail. Right here is where we should * really be verifying the scan chains ... */ tap->enabled = (e == JTAG_TAP_EVENT_ENABLE); LOG_INFO("JTAG tap: %s %s", tap->dotted_name, tap->enabled ? "enabled" : "disabled"); break; default: break; } } } static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)"); return JIM_ERR; } struct command_context *context = current_command_context(interp); int e = jtag_init_inner(context); if (e != ERROR_OK) { Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); Jim_FreeNewObj(goi.interp, eObj); return JIM_ERR; } return JIM_OK; } static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int e = ERROR_OK; Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)"); return JIM_ERR; } struct command_context *context = current_command_context(interp); if (transport_is_jtag()) e = jtag_init_reset(context); else if (transport_is_swd()) e = swd_init_reset(context); if (e != ERROR_OK) { Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); Jim_FreeNewObj(goi.interp, eObj); return JIM_ERR; } return JIM_OK; } int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); return jim_newtap_cmd(&goi); } static bool jtag_tap_enable(struct jtag_tap *t) { if (t->enabled) return false; jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE); if (!t->enabled) return false; /* FIXME add JTAG sanity checks, w/o TLR * - scan chain length grew by one (this) * - IDs and IR lengths are as expected */ jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE); return true; } static bool jtag_tap_disable(struct jtag_tap *t) { if (!t->enabled) return false; jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE); if (t->enabled) return false; /* FIXME add JTAG sanity checks, w/o TLR * - scan chain length shrank by one (this) * - IDs and IR lengths are as expected */ jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE); return true; } int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); if (goi.argc != 1) { Jim_SetResultFormatted(goi.interp, "usage: %s ", cmd_name); return JIM_ERR; } struct jtag_tap *t; t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]); if (t == NULL) return JIM_ERR; if (strcasecmp(cmd_name, "tapisenabled") == 0) { /* do nothing, just return the value */ } else if (strcasecmp(cmd_name, "tapenable") == 0) { if (!jtag_tap_enable(t)) { LOG_WARNING("failed to enable tap %s", t->dotted_name); return JIM_ERR; } } else if (strcasecmp(cmd_name, "tapdisable") == 0) { if (!jtag_tap_disable(t)) { LOG_WARNING("failed to disable tap %s", t->dotted_name); return JIM_ERR; } } else { LOG_ERROR("command '%s' unknown", cmd_name); return JIM_ERR; } bool e = t->enabled; Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e)); return JIM_OK; } int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); goi.isconfigure = !strcmp(cmd_name, "configure"); if (goi.argc < 2 + goi.isconfigure) { Jim_WrongNumArgs(goi.interp, 0, NULL, " ..."); return JIM_ERR; } struct jtag_tap *t; Jim_Obj *o; Jim_GetOpt_Obj(&goi, &o); t = jtag_tap_by_jim_obj(goi.interp, o); if (t == NULL) return JIM_ERR; return jtag_tap_configure_cmd(&goi, t); } static int jim_jtag_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters"); return JIM_ERR; } Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0)); struct jtag_tap *tap; for (tap = jtag_all_taps(); tap; tap = tap->next_tap) { Jim_ListAppendElement(goi.interp, Jim_GetResult(goi.interp), Jim_NewStringObj(goi.interp, tap->dotted_name, -1)); } return JIM_OK; } COMMAND_HANDLER(handle_jtag_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool jtag_initialized; if (jtag_initialized) { LOG_INFO("'jtag init' has already been called"); return ERROR_OK; } jtag_initialized = true; LOG_DEBUG("Initializing jtag devices..."); return jtag_init(CMD_CTX); } static const struct command_registration jtag_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_ANY, .handler = handle_jtag_init_command, .help = "initialize jtag scan chain", .usage = "" }, { .name = "arp_init", .mode = COMMAND_ANY, .jim_handler = jim_jtag_arp_init, .help = "Validates JTAG scan chain against the list of " "declared TAPs using just the four standard JTAG " "signals.", }, { .name = "arp_init-reset", .mode = COMMAND_ANY, .jim_handler = jim_jtag_arp_init_reset, .help = "Uses TRST and SRST to try resetting everything on " "the JTAG scan chain, then performs 'jtag arp_init'." }, { .name = "newtap", .mode = COMMAND_CONFIG, .jim_handler = jim_jtag_newtap, .help = "Create a new TAP instance named basename.tap_type, " "and appends it to the scan chain.", .usage = "basename tap_type '-irlen' count " "['-enable'|'-disable'] " "['-expected_id' number] " "['-ignore-version'] " "['-ircapture' number] " "['-mask' number] ", }, { .name = "tapisenabled", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Returns a Tcl boolean (0/1) indicating whether " "the TAP is enabled (1) or not (0).", .usage = "tap_name", }, { .name = "tapenable", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Try to enable the specified TAP using the " "'tap-enable' TAP event.", .usage = "tap_name", }, { .name = "tapdisable", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_tap_enabler, .help = "Try to disable the specified TAP using the " "'tap-disable' TAP event.", .usage = "tap_name", }, { .name = "configure", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_configure, .help = "Provide a Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name handler", }, { .name = "cget", .mode = COMMAND_EXEC, .jim_handler = jim_jtag_configure, .help = "Return any Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name", }, { .name = "names", .mode = COMMAND_ANY, .jim_handler = jim_jtag_names, .help = "Returns list of all JTAG tap names.", }, { .chain = jtag_command_handlers_to_move, }, COMMAND_REGISTRATION_DONE }; void jtag_notify_event(enum jtag_event event) { struct jtag_tap *tap; for (tap = jtag_all_taps(); tap; tap = tap->next_tap) jtag_tap_handle_event(tap, event); } COMMAND_HANDLER(handle_scan_chain_command) { struct jtag_tap *tap; char expected_id[12]; tap = jtag_all_taps(); command_print(CMD_CTX, " TapName Enabled IdCode Expected IrLen IrCap IrMask"); command_print(CMD_CTX, "-- ------------------- -------- ---------- ---------- ----- ----- ------"); while (tap) { uint32_t expected, expected_mask, ii; snprintf(expected_id, sizeof expected_id, "0x%08x", (unsigned)((tap->expected_ids_cnt > 0) ? tap->expected_ids[0] : 0)); if (tap->ignore_version) expected_id[2] = '*'; expected = buf_get_u32(tap->expected, 0, tap->ir_length); expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length); command_print(CMD_CTX, "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", tap->abs_chain_position, tap->dotted_name, tap->enabled ? 'Y' : 'n', (unsigned int)(tap->idcode), expected_id, (unsigned int)(tap->ir_length), (unsigned int)(expected), (unsigned int)(expected_mask)); for (ii = 1; ii < tap->expected_ids_cnt; ii++) { snprintf(expected_id, sizeof expected_id, "0x%08x", (unsigned) tap->expected_ids[ii]); if (tap->ignore_version) expected_id[2] = '*'; command_print(CMD_CTX, " %s", expected_id); } tap = tap->next_tap; } return ERROR_OK; } COMMAND_HANDLER(handle_jtag_ntrst_delay_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { unsigned delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_delay(delay); } command_print(CMD_CTX, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay()); return ERROR_OK; } COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { unsigned delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_assert_width(delay); } command_print(CMD_CTX, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width()); return ERROR_OK; } COMMAND_HANDLER(handle_jtag_rclk_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; int retval = ERROR_OK; if (CMD_ARGC == 1) { unsigned khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = jtag_config_rclk(khz); if (ERROR_OK != retval) return retval; } int cur_khz = jtag_get_speed_khz(); retval = jtag_get_speed_readable(&cur_khz); if (ERROR_OK != retval) return retval; if (cur_khz) command_print(CMD_CTX, "RCLK not supported - fallback to %d kHz", cur_khz); else command_print(CMD_CTX, "RCLK - adaptive"); return retval; } COMMAND_HANDLER(handle_jtag_reset_command) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; int trst = -1; if (CMD_ARGV[0][0] == '1') trst = 1; else if (CMD_ARGV[0][0] == '0') trst = 0; else return ERROR_COMMAND_SYNTAX_ERROR; int srst = -1; if (CMD_ARGV[1][0] == '1') srst = 1; else if (CMD_ARGV[1][0] == '0') srst = 0; else return ERROR_COMMAND_SYNTAX_ERROR; if (adapter_init(CMD_CTX) != ERROR_OK) return ERROR_JTAG_INIT_FAILED; jtag_add_reset(trst, srst); return jtag_execute_queue(); } COMMAND_HANDLER(handle_runtest_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; unsigned num_clocks; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks); jtag_add_runtest(num_clocks, TAP_IDLE); return jtag_execute_queue(); } /* * For "irscan" or "drscan" commands, the "end" (really, "next") state * should be stable ... and *NOT* a shift state, otherwise free-running * jtag clocks could change the values latched by the update state. * Not surprisingly, this is the same constraint as SVF; the "irscan" * and "drscan" commands are a write-only subset of what SVF provides. */ COMMAND_HANDLER(handle_irscan_command) { int i; struct scan_field *fields; struct jtag_tap *tap = NULL; tap_state_t endstate; if ((CMD_ARGC < 2) || (CMD_ARGC % 2)) return ERROR_COMMAND_SYNTAX_ERROR; /* optional "-endstate" "statename" at the end of the arguments, * so that e.g. IRPAUSE can let us load the data register before * entering RUN/IDLE to execute the instruction we load here. */ endstate = TAP_IDLE; if (CMD_ARGC >= 4) { /* have at least one pair of numbers. * is last pair the magic text? */ if (strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2]) == 0) { endstate = tap_state_by_name(CMD_ARGV[CMD_ARGC - 1]); if (endstate == TAP_INVALID) return ERROR_COMMAND_SYNTAX_ERROR; if (!scan_is_safe(endstate)) LOG_WARNING("unstable irscan endstate \"%s\"", CMD_ARGV[CMD_ARGC - 1]); CMD_ARGC -= 2; } } int num_fields = CMD_ARGC / 2; if (num_fields > 1) { /* we really should be looking at plain_ir_scan if we want * anything more fancy. */ LOG_ERROR("Specify a single value for tap"); return ERROR_COMMAND_SYNTAX_ERROR; } fields = calloc(num_fields, sizeof(*fields)); int retval; for (i = 0; i < num_fields; i++) { tap = jtag_tap_by_string(CMD_ARGV[i*2]); if (tap == NULL) { free(fields); command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i*2]); return ERROR_FAIL; } int field_size = tap->ir_length; fields[i].num_bits = field_size; uint8_t *v = malloc(DIV_ROUND_UP(field_size, 8)); uint64_t value; retval = parse_u64(CMD_ARGV[i * 2 + 1], &value); if (ERROR_OK != retval) goto error_return; buf_set_u64(v, 0, field_size, value); fields[i].out_value = v; fields[i].in_value = NULL; } /* did we have an endstate? */ jtag_add_ir_scan(tap, fields, endstate); retval = jtag_execute_queue(); error_return: for (i = 0; i < num_fields; i++) { if (NULL != fields[i].out_value) free((void *)fields[i].out_value); } free(fields); return retval; } COMMAND_HANDLER(handle_verify_ircapture_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { bool enable; COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable); jtag_set_verify_capture_ir(enable); } const char *status = jtag_will_verify_capture_ir() ? "enabled" : "disabled"; command_print(CMD_CTX, "verify Capture-IR is %s", status); return ERROR_OK; } COMMAND_HANDLER(handle_verify_jtag_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { bool enable; COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable); jtag_set_verify(enable); } const char *status = jtag_will_verify() ? "enabled" : "disabled"; command_print(CMD_CTX, "verify jtag capture is %s", status); return ERROR_OK; } COMMAND_HANDLER(handle_tms_sequence_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { bool use_new_table; if (strcmp(CMD_ARGV[0], "short") == 0) use_new_table = true; else if (strcmp(CMD_ARGV[0], "long") == 0) use_new_table = false; else return ERROR_COMMAND_SYNTAX_ERROR; tap_use_new_tms_table(use_new_table); } command_print(CMD_CTX, "tms sequence is %s", tap_uses_new_tms_table() ? "short" : "long"); return ERROR_OK; } COMMAND_HANDLER(handle_jtag_flush_queue_sleep) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; int sleep_ms; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], sleep_ms); jtag_set_flush_queue_sleep(sleep_ms); return ERROR_OK; } COMMAND_HANDLER(handle_wait_srst_deassert) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; int timeout_ms; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], timeout_ms); if ((timeout_ms <= 0) || (timeout_ms > 100000)) { LOG_ERROR("Timeout must be an integer between 0 and 100000"); return ERROR_FAIL; } LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms); int asserted_yet; long long then = timeval_ms(); while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) { if ((timeval_ms() - then) > timeout_ms) { LOG_ERROR("Timed out"); return ERROR_FAIL; } if (asserted_yet) break; } while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) { if ((timeval_ms() - then) > timeout_ms) { LOG_ERROR("Timed out"); return ERROR_FAIL; } if (!asserted_yet) break; } return ERROR_OK; } static const struct command_registration jtag_command_handlers[] = { { .name = "jtag_flush_queue_sleep", .handler = handle_jtag_flush_queue_sleep, .mode = COMMAND_ANY, .help = "For debug purposes(simulate long delays of interface) " "to test performance or change in behavior. Default 0ms.", .usage = "[sleep in ms]", }, { .name = "jtag_rclk", .handler = handle_jtag_rclk_command, .mode = COMMAND_ANY, .help = "With an argument, change to to use adaptive clocking " "if possible; else to use the fallback speed. " "With or without argument, display current setting.", .usage = "[fallback_speed_khz]", }, { .name = "jtag_ntrst_delay", .handler = handle_jtag_ntrst_delay_command, .mode = COMMAND_ANY, .help = "delay after deasserting trst in ms", .usage = "[milliseconds]", }, { .name = "jtag_ntrst_assert_width", .handler = handle_jtag_ntrst_assert_width_command, .mode = COMMAND_ANY, .help = "delay after asserting trst in ms", .usage = "[milliseconds]", }, { .name = "scan_chain", .handler = handle_scan_chain_command, .mode = COMMAND_ANY, .help = "print current scan chain configuration", .usage = "" }, { .name = "jtag_reset", .handler = handle_jtag_reset_command, .mode = COMMAND_EXEC, .help = "Set reset line values. Value '1' is active, " "value '0' is inactive.", .usage = "trst_active srst_active", }, { .name = "runtest", .handler = handle_runtest_command, .mode = COMMAND_EXEC, .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.", .usage = "num_cycles" }, { .name = "irscan", .handler = handle_irscan_command, .mode = COMMAND_EXEC, .help = "Execute Instruction Register (DR) scan. The " "specified opcodes are put into each TAP's IR, " "and other TAPs are put in BYPASS.", .usage = "[tap_name instruction]* ['-endstate' state_name]", }, { .name = "verify_ircapture", .handler = handle_verify_ircapture_command, .mode = COMMAND_ANY, .help = "Display or assign flag controlling whether to " "verify values captured during Capture-IR.", .usage = "['enable'|'disable']", }, { .name = "verify_jtag", .handler = handle_verify_jtag_command, .mode = COMMAND_ANY, .help = "Display or assign flag controlling whether to " "verify values captured during IR and DR scans.", .usage = "['enable'|'disable']", }, { .name = "tms_sequence", .handler = handle_tms_sequence_command, .mode = COMMAND_ANY, .help = "Display or change what style TMS sequences to use " "for JTAG state transitions: short (default) or " "long. Only for working around JTAG bugs.", /* Specifically for working around DRIVER bugs... */ .usage = "['short'|'long']", }, { .name = "wait_srst_deassert", .handler = handle_wait_srst_deassert, .mode = COMMAND_ANY, .help = "Wait for an SRST deassert. " "Useful for cases where you need something to happen within ms " "of an srst deassert. Timeout in ms ", .usage = "ms", }, { .name = "jtag", .mode = COMMAND_ANY, .help = "perform jtag tap actions", .usage = "", .chain = jtag_subcommand_handlers, }, { .chain = jtag_command_handlers_to_move, }, COMMAND_REGISTRATION_DONE }; int jtag_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, jtag_command_handlers); } openocd-0.9.0/src/jtag/tcl.h0000644000175000017500000000461712315575361012557 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _JTAG_TCL_H_ #define _JTAG_TCL_H_ int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv); int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj * const *argv); #endif openocd-0.9.0/src/jtag/swd.h0000644000175000017500000001677212516456303012574 00000000000000/*************************************************************************** * Copyright (C) 2009-2010 by David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef SWD_H #define SWD_H #include /* Bits in SWD command packets, written from host to target * first bit on the wire is START */ #define SWD_CMD_START (1 << 0) /* always set */ #define SWD_CMD_APnDP (1 << 1) /* set only for AP access */ #define SWD_CMD_RnW (1 << 2) /* set only for read access */ #define SWD_CMD_A32 (3 << 3) /* bits A[3:2] of register addr */ #define SWD_CMD_PARITY (1 << 5) /* parity of APnDP|RnW|A32 */ #define SWD_CMD_STOP (0 << 6) /* always clear for synch SWD */ #define SWD_CMD_PARK (1 << 7) /* driven high by host */ /* followed by TRN, 3-bits of ACK, TRN */ /** * Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg() * and swd_driver.write_reg() methods will use directly. */ static inline uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum) { uint8_t cmd = (is_ap ? SWD_CMD_APnDP : 0) | (is_read ? SWD_CMD_RnW : 0) | ((regnum & 0xc) << 1); /* 8 cmd bits 4:1 may be set */ if (parity_u32(cmd)) cmd |= SWD_CMD_PARITY; /* driver handles START, STOP, and TRN */ return cmd; } /* SWD_ACK_* bits are defined in */ /** * Line reset. * * Line reset is at least 50 SWCLK cycles with SWDIO driven high, followed * by at least one idle (low) cycle. */ static const uint8_t swd_seq_line_reset[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03 }; static const unsigned swd_seq_line_reset_len = 51; /** * JTAG-to-SWD sequence. * * The JTAG-to-SWD sequence is at least 50 TCK/SWCLK cycles with TMS/SWDIO * high, putting either interface logic into reset state, followed by a * specific 16-bit sequence and finally a line reset in case the SWJ-DP was * already in SWD mode. */ static const uint8_t swd_seq_jtag_to_swd[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, }; static const unsigned swd_seq_jtag_to_swd_len = 118; /** * SWD-to-JTAG sequence. * * The SWD-to-JTAG sequence is at least 50 TCK/SWCLK cycles with TMS/SWDIO * high, putting either interface logic into reset state, followed by a * specific 16-bit sequence and finally at least 5 TCK cycles to put the * JTAG TAP in TLR. */ static const uint8_t swd_seq_swd_to_jtag[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xff }; static const unsigned swd_seq_swd_to_jtag_len = 71; /** * SWD-to-dormant sequence. * * This is at least 50 SWCLK cycles with SWDIO high to put the interface * in reset state, followed by a specific 16-bit sequence. */ static const uint8_t swd_seq_swd_to_dormant[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x8e, 0x03 }; static const unsigned swd_seq_swd_to_dormant_len = 66; /** * Dormant-to-SWD sequence. * * This is at least 8 TCK/SWCLK cycles with TMS/SWDIO high to abort any ongoing * selection alert sequence, followed by a specific 128-bit selection alert * sequence, followed by 4 TCK/SWCLK cycles with TMS/SWDIO low, followed by * a specific protocol-dependent activation code. For SWD the activation code * is an 8-bit sequence. The sequence ends with a line reset. */ static const uint8_t swd_seq_dormant_to_swd[] = { 0xff, 0x92, 0xf3, 0x09, 0x62, 0x95, 0x2d, 0x85, 0x86, 0xe9, 0xaf, 0xdd, 0xe3, 0xa2, 0x0e, 0xbc, 0x19, 0x10, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f }; static const unsigned swd_seq_dormant_to_swd_len = 199; enum swd_special_seq { LINE_RESET, JTAG_TO_SWD, SWD_TO_JTAG, SWD_TO_DORMANT, DORMANT_TO_SWD, }; struct swd_driver { /** * Initialize the debug link so it can perform SWD operations. * * As an example, this would switch a dual-mode debug adapter * into SWD mode and out of JTAG mode. * * @return ERROR_OK on success, else a negative fault code. */ int (*init)(void); /** * Set the SWCLK frequency of the SWD link. * * The driver should round the desired value, downwards if possible, to * the nearest supported frequency. A negative value should be ignored * and can be used to query the current setting. If the driver does not * support a variable frequency a fixed, nominal, value should be * returned. * * If the frequency is increased, it must not apply before the currently * queued transactions are executed. If the frequency is lowered, it may * apply immediately. * * @param dap The DAP controlled by the SWD link. * @param hz The desired frequency in Hz. * @return The actual resulting frequency after rounding. */ int_least32_t (*frequency)(struct adiv5_dap *dap, int_least32_t hz); /** * Queue a special SWDIO sequence. * * @param dap The DAP controlled by the SWD link. * @param seq The special sequence to generate. * @return ERROR_OK if the sequence was queued, negative error if the * sequence is unsupported. */ int (*switch_seq)(struct adiv5_dap *dap, enum swd_special_seq seq); /** * Queued read of an AP or DP register. * * @param dap The DAP controlled by the SWD link. * @param Command byte with APnDP/RnW/addr/parity bits * @param Where to store value to read from register */ void (*read_reg)(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value); /** * Queued write of an AP or DP register. * * @param dap The DAP controlled by the SWD link. * @param Command byte with APnDP/RnW/addr/parity bits * @param Value to be written to the register */ void (*write_reg)(struct adiv5_dap *dap, uint8_t cmd, uint32_t value); /** * Execute any queued transactions and collect the result. * * @param dap The DAP controlled by the SWD link. * @return ERROR_OK on success, Ack response code on WAIT/FAULT * or negative error code on other kinds of failure. */ int (*run)(struct adiv5_dap *dap); /** * Configures data collection from the Single-wire * trace (SWO) signal. * @param swo true if SWO data collection should be routed. * * For example, some debug adapters include a UART which * is normally connected to a microcontroller's UART TX, * but which may instead be connected to SWO for use in * collecting ITM (and possibly ETM) trace data. * * @return ERROR_OK on success, else a negative fault code. */ int *(*trace)(struct adiv5_dap *dap, bool swo); }; int swd_init_reset(struct command_context *cmd_ctx); void swd_add_reset(int req_srst); bool transport_is_swd(void); #endif /* SWD_H */ openocd-0.9.0/src/jtag/minidriver.h0000644000175000017500000001020112315575361014127 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MINIDRIVER_H #define MINIDRIVER_H /** * @page jtagminidriver JTAG Mini-Driver * * The JTAG minidriver interface allows the definition of alternate * interface functions, instead of the built-in asynchronous driver * module that is used by the standard JTAG interface drivers. * * In addtion to the functions defined in the @c minidriver.h file, the * @c jtag_minidriver.h file must declare the following functions (or * define static inline versions of them): * - jtag_add_callback * - jtag_add_callback4 * * The following core functions are declared in this file for use by * the minidriver and do @b not need to be defined by an implementation: * - default_interface_jtag_execute_queue() */ /* this header will be provided by the minidriver implementation, */ /* and it may provide additional declarations that must be defined. */ #include int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields, tap_state_t endstate); int interface_jtag_add_plain_ir_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields, const struct scan_field *fields, tap_state_t endstate); int interface_jtag_add_plain_dr_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); int interface_jtag_add_tlr(void); int interface_jtag_add_pathmove(int num_states, const tap_state_t *path); int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate); int interface_add_tms_seq(unsigned num_bits, const uint8_t *bits, enum tap_state state); /** * This drives the actual srst and trst pins. srst will always be 0 * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for * trst. * * the higher level jtag_add_reset will invoke jtag_add_tlr() if * approperiate */ int interface_jtag_add_reset(int trst, int srst); int interface_jtag_add_sleep(uint32_t us); int interface_jtag_add_clocks(int num_cycles); int interface_jtag_execute_queue(void); /** * Calls the interface callback to execute the queue. This routine * is used by the JTAG driver layer and should not be called directly. */ int default_interface_jtag_execute_queue(void); #endif /* MINIDRIVER_H */ openocd-0.9.0/src/jtag/drivers/0000755000175000017500000000000012526202225013340 500000000000000openocd-0.9.0/src/jtag/drivers/bcm2835gpio.c0000644000175000017500000002530512315575360015404 00000000000000/*************************************************************************** * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com * * * * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au * * Based on at91rm9200.c (c) Anders Larsen * * and RPi GPIO examples by Gert van Loo & Dom * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" #include #define BCM2835_PERI_BASE 0x20000000 #define BCM2835_GPIO_BASE (BCM2835_PERI_BASE + 0x200000) /* GPIO controller */ #define BCM2835_PADS_GPIO_0_27 (BCM2835_PERI_BASE + 0x100000) #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4) /* GPIO setup macros */ #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7) #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0) #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \ INP_GPIO(g); \ *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0) #define OUT_GPIO(g) SET_MODE_GPIO(g, 1) #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */ #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */ #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */ static int dev_mem_fd; static volatile uint32_t *pio_base; static int bcm2835gpio_read(void); static void bcm2835gpio_write(int tck, int tms, int tdi); static void bcm2835gpio_reset(int trst, int srst); static int bcm2835gpio_init(void); static int bcm2835gpio_quit(void); static struct bitbang_interface bcm2835gpio_bitbang = { .read = bcm2835gpio_read, .write = bcm2835gpio_write, .reset = bcm2835gpio_reset, .blink = NULL }; /* GPIO numbers for each signal. Negative values are invalid */ static int tck_gpio = -1; static int tck_gpio_mode; static int tms_gpio = -1; static int tms_gpio_mode; static int tdi_gpio = -1; static int tdi_gpio_mode; static int tdo_gpio = -1; static int tdo_gpio_mode; static int trst_gpio = -1; static int trst_gpio_mode; static int srst_gpio = -1; static int srst_gpio_mode; /* Transition delay coefficients */ static int speed_coeff = 113714; static int speed_offset = 28; static unsigned int jtag_delay; static int bcm2835gpio_read(void) { return !!(GPIO_LEV & 1< 0) { set |= !trst< 0) { set |= !srst<= 0 && gpio <= 53; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums) { if (CMD_ARGC == 4) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdi = %d", tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: tck = %d", tck_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: tms = %d", tms_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: tdo = %d", tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: tdi = %d", tdi_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: srst = %d", srst_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); command_print(CMD_CTX, "BCM2835 GPIO config: trst = %d", trst_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs) { if (CMD_ARGC == 2) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset); } return ERROR_OK; } static const struct command_registration bcm2835gpio_command_handlers[] = { { .name = "bcm2835gpio_jtag_nums", .handler = &bcm2835gpio_handle_jtag_gpionums, .mode = COMMAND_CONFIG, .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", .usage = "(tck tms tdi tdo)* ", }, { .name = "bcm2835gpio_tck_num", .handler = &bcm2835gpio_handle_jtag_gpionum_tck, .mode = COMMAND_CONFIG, .help = "gpio number for tck.", }, { .name = "bcm2835gpio_tms_num", .handler = &bcm2835gpio_handle_jtag_gpionum_tms, .mode = COMMAND_CONFIG, .help = "gpio number for tms.", }, { .name = "bcm2835gpio_tdo_num", .handler = &bcm2835gpio_handle_jtag_gpionum_tdo, .mode = COMMAND_CONFIG, .help = "gpio number for tdo.", }, { .name = "bcm2835gpio_tdi_num", .handler = &bcm2835gpio_handle_jtag_gpionum_tdi, .mode = COMMAND_CONFIG, .help = "gpio number for tdi.", }, { .name = "bcm2835gpio_srst_num", .handler = &bcm2835gpio_handle_jtag_gpionum_srst, .mode = COMMAND_CONFIG, .help = "gpio number for srst.", }, { .name = "bcm2835gpio_trst_num", .handler = &bcm2835gpio_handle_jtag_gpionum_trst, .mode = COMMAND_CONFIG, .help = "gpio number for trst.", }, { .name = "bcm2835gpio_speed_coeffs", .handler = &bcm2835gpio_handle_speed_coeffs, .mode = COMMAND_CONFIG, .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface bcm2835gpio_interface = { .name = "bcm2835gpio", .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, .transports = jtag_only, .speed = bcm2835gpio_speed, .khz = bcm2835gpio_khz, .speed_div = bcm2835gpio_speed_div, .commands = bcm2835gpio_command_handlers, .init = bcm2835gpio_init, .quit = bcm2835gpio_quit, }; static int bcm2835gpio_init(void) { bitbang_interface = &bcm2835gpio_bitbang; if (!is_gpio_valid(tdo_gpio) || !is_gpio_valid(tdi_gpio) || !is_gpio_valid(tck_gpio) || !is_gpio_valid(tms_gpio) || (trst_gpio != -1 && !is_gpio_valid(trst_gpio)) || (srst_gpio != -1 && !is_gpio_valid(srst_gpio))) return ERROR_JTAG_INIT_FAILED; dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if (dev_mem_fd < 0) { perror("open"); return ERROR_JTAG_INIT_FAILED; } pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE); if (pio_base == MAP_FAILED) { perror("mmap"); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } static volatile uint32_t *pads_base; pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27); if (pads_base == MAP_FAILED) { perror("mmap"); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } /* set 16mA drive strength */ pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7; tdo_gpio_mode = MODE_GPIO(tdo_gpio); tdi_gpio_mode = MODE_GPIO(tdi_gpio); tck_gpio_mode = MODE_GPIO(tck_gpio); tms_gpio_mode = MODE_GPIO(tms_gpio); /* * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. */ INP_GPIO(tdo_gpio); GPIO_CLR = 1< * * based on Dominic Rath's and Benedikt Sauter's usbprog.c * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD * * plagnioj@jcrosoft.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "libusb_common.h" /* See Segger's public documentation: * Reference manual for J-Link USB Protocol * Document RM08001-R6 Date: June 16, 2009 * (Or newer, with some SWD information). * http://www.segger.com/cms/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf */ /* * The default pid of the segger is 0x0101 * But when you change the USB Address it will also * * pid = ( usb_address > 0x4) ? 0x0101 : (0x101 + usb_address) */ #define JLINK_USB_INTERFACE_CLASS 0xff #define JLINK_USB_INTERFACE_SUBCLASS 0xff #define JLINK_USB_INTERFACE_PROTOCOL 0xff static unsigned int jlink_write_ep; static unsigned int jlink_read_ep; static unsigned int jlink_hw_jtag_version = 2; #define JLINK_USB_TIMEOUT 1000 /* See Section 3.3.2 of the Segger JLink USB protocol manual */ /* 2048 is the max value we can use here */ #define JLINK_TAP_BUFFER_SIZE 2048 /*#define JLINK_TAP_BUFFER_SIZE 256*/ /*#define JLINK_TAP_BUFFER_SIZE 384*/ #define JLINK_IN_BUFFER_SIZE (2048 + 1) #define JLINK_OUT_BUFFER_SIZE (2*2048 + 4) /* Global USB buffers */ static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; /* Constants for JLink command */ #define EMU_CMD_VERSION 0x01 #define EMU_CMD_RESET_TRST 0x02 #define EMU_CMD_RESET_TARGET 0x03 #define EMU_CMD_SET_SPEED 0x05 #define EMU_CMD_GET_STATE 0x07 #define EMU_CMD_SET_KS_POWER 0x08 #define EMU_CMD_REGISTER 0x09 #define EMU_CMD_GET_SPEEDS 0xc0 #define EMU_CMD_GET_HW_INFO 0xc1 #define EMU_CMD_GET_COUNTERS 0xc2 #define EMU_CMD_SELECT_IF 0xc7 #define EMU_CMD_HW_CLOCK 0xc8 #define EMU_CMD_HW_TMS0 0xc9 #define EMU_CMD_HW_TMS1 0xca #define EMU_CMD_HW_DATA0 0xcb #define EMU_CMD_HW_DATA1 0xcc #define EMU_CMD_HW_JTAG 0xcd #define EMU_CMD_HW_JTAG2 0xce #define EMU_CMD_HW_JTAG3 0xcf #define EMU_CMD_HW_RELEASE_RESET_STOP_EX 0xd0 #define EMU_CMD_HW_RELEASE_RESET_STOP_TIMED 0xd1 #define EMU_CMD_GET_MAX_MEM_BLOCK 0xd4 #define EMU_CMD_HW_JTAG_WRITE 0xd5 #define EMU_CMD_HW_JTAG_GET_RESULT 0xd6 #define EMU_CMD_HW_RESET0 0xdc #define EMU_CMD_HW_RESET1 0xdd #define EMU_CMD_HW_TRST0 0xde #define EMU_CMD_HW_TRST1 0xdf #define EMU_CMD_GET_CAPS 0xe8 #define EMU_CMD_GET_CPU_CAPS 0xe9 #define EMU_CMD_EXEC_CPU_CMD 0xea #define EMU_CMD_GET_CAPS_EX 0xed #define EMU_CMD_GET_HW_VERSION 0xf0 #define EMU_CMD_WRITE_DCC 0xf1 #define EMU_CMD_READ_CONFIG 0xf2 #define EMU_CMD_WRITE_CONFIG 0xf3 #define EMU_CMD_WRITE_MEM 0xf4 #define EMU_CMD_READ_MEM 0xf5 #define EMU_CMD_MEASURE_RTCK_REACT 0xf6 #define EMU_CMD_WRITE_MEM_ARM79 0xf7 #define EMU_CMD_READ_MEM_ARM79 0xf8 /* Register subcommands */ #define REG_CMD_REGISTER 100 #define REG_CMD_UNREGISTER 101 /* bits return from EMU_CMD_GET_CAPS */ #define EMU_CAP_RESERVED_1 0 #define EMU_CAP_GET_HW_VERSION 1 #define EMU_CAP_WRITE_DCC 2 #define EMU_CAP_ADAPTIVE_CLOCKING 3 #define EMU_CAP_READ_CONFIG 4 #define EMU_CAP_WRITE_CONFIG 5 #define EMU_CAP_TRACE 6 #define EMU_CAP_WRITE_MEM 7 #define EMU_CAP_READ_MEM 8 #define EMU_CAP_SPEED_INFO 9 #define EMU_CAP_EXEC_CODE 10 #define EMU_CAP_GET_MAX_BLOCK_SIZE 11 #define EMU_CAP_GET_HW_INFO 12 #define EMU_CAP_SET_KS_POWER 13 #define EMU_CAP_RESET_STOP_TIMED 14 #define EMU_CAP_RESERVED_2 15 #define EMU_CAP_MEASURE_RTCK_REACT 16 #define EMU_CAP_SELECT_IF 17 #define EMU_CAP_RW_MEM_ARM79 18 #define EMU_CAP_GET_COUNTERS 19 #define EMU_CAP_READ_DCC 20 #define EMU_CAP_GET_CPU_CAPS 21 #define EMU_CAP_EXEC_CPU_CMD 22 #define EMU_CAP_SWO 23 #define EMU_CAP_WRITE_DCC_EX 24 #define EMU_CAP_UPDATE_FIRMWARE_EX 25 #define EMU_CAP_FILE_IO 26 #define EMU_CAP_REGISTER 27 #define EMU_CAP_INDICATORS 28 #define EMU_CAP_TEST_NET_SPEED 29 #define EMU_CAP_RAWTRACE 30 #define EMU_CAP_RESERVED_3 31 static const char * const jlink_cap_str[] = { "Always 1.", "Supports command EMU_CMD_GET_HARDWARE_VERSION", "Supports command EMU_CMD_WRITE_DCC", "Supports adaptive clocking", "Supports command EMU_CMD_READ_CONFIG", "Supports command EMU_CMD_WRITE_CONFIG", "Supports trace commands", "Supports command EMU_CMD_WRITE_MEM", "Supports command EMU_CMD_READ_MEM", "Supports command EMU_CMD_GET_SPEED", "Supports command EMU_CMD_CODE_...", "Supports command EMU_CMD_GET_MAX_BLOCK_SIZE", "Supports command EMU_CMD_GET_HW_INFO", "Supports command EMU_CMD_SET_KS_POWER", "Supports command EMU_CMD_HW_RELEASE_RESET_STOP_TIMED", "Reserved", "Supports command EMU_CMD_MEASURE_RTCK_REACT", "Supports command EMU_CMD_HW_SELECT_IF", "Supports command EMU_CMD_READ/WRITE_MEM_ARM79", "Supports command EMU_CMD_GET_COUNTERS", "Supports command EMU_CMD_READ_DCC", "Supports command EMU_CMD_GET_CPU_CAPS", "Supports command EMU_CMD_EXEC_CPU_CMD", "Supports command EMU_CMD_SWO", "Supports command EMU_CMD_WRITE_DCC_EX", "Supports command EMU_CMD_UPDATE_FIRMWARE_EX", "Supports command EMU_CMD_FILE_IO", "Supports command EMU_CMD_REGISTER", "Supports command EMU_CMD_INDICATORS", "Supports command EMU_CMD_TEST_NET_SPEED", "Supports command EMU_CMD_RAWTRACE", "Reserved", }; /* max speed 12MHz v5.0 jlink */ #define JLINK_MAX_SPEED 12000 /* J-Link hardware versions */ #define JLINK_HW_TYPE_JLINK 0 #define JLINK_HW_TYPE_JTRACE 1 #define JLINK_HW_TYPE_FLASHER 2 #define JLINK_HW_TYPE_JLINK_PRO 3 #define JLINK_HW_TYPE_JLINK_LITE_ADI 5 #define JLINK_HW_TYPE_JLINK_LITE_XMC4000 16 #define JLINK_HW_TYPE_JLINK_LITE_XMC4200 17 #define JLINK_HW_TYPE_LPCLINK2 18 /* Interface selection */ #define JLINK_TIF_JTAG 0 #define JLINK_TIF_SWD 1 #define JLINK_SWD_DIR_IN 0 #define JLINK_SWD_DIR_OUT 1 /* Queue command functions */ static void jlink_end_state(tap_state_t state); static void jlink_state_move(void); static void jlink_path_move(int num_states, tap_state_t *path); static void jlink_runtest(int num_cycles); static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void jlink_reset(int trst, int srst); static void jlink_simple_command(uint8_t command); static int jlink_get_status(void); static int jlink_swd_run_queue(struct adiv5_dap *dap); static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data); static int jlink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq); /* J-Link tap buffer functions */ static void jlink_tap_init(void); static int jlink_tap_execute(void); static void jlink_tap_ensure_space(int scans, int bits); static void jlink_tap_append_step(int tms, int tdi); static void jlink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); /* Jlink lowlevel functions */ struct jlink { struct jtag_libusb_device_handle *usb_handle; }; static struct jlink *jlink_usb_open(void); static void jlink_usb_close(struct jlink *jlink); static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length); static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length); static int jlink_usb_write(struct jlink *jlink, int out_length); static int jlink_usb_read(struct jlink *jlink, int expected_size); /* helper functions */ static int jlink_get_version_info(void); #ifdef _DEBUG_USB_COMMS_ static void jlink_debug_buffer(uint8_t *buffer, int length); #else static inline void jlink_debug_buffer(uint8_t *buffer, int length) { } #endif static enum tap_state jlink_last_state = TAP_RESET; static struct jlink *jlink_handle; /* pid could be specified at runtime */ static uint16_t vids[] = { 0x1366, 0x1366, 0x1366, 0x1366, 0x1366, 0 }; static uint16_t pids[] = { 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0 }; static char *jlink_serial; static uint32_t jlink_caps; static uint32_t jlink_hw_type; static int queued_retval; static bool swd_mode; /* 256 byte non-volatile memory */ struct jlink_config { uint8_t usb_address; /* 0ffset 0x01 to 0x03 */ uint8_t reserved_1[3]; uint32_t kickstart_power_on_jtag_pin_19; /* 0ffset 0x08 to 0x1f */ uint8_t reserved_2[24]; /* IP only for J-Link Pro */ uint8_t ip_address[4]; uint8_t subnet_mask[4]; /* 0ffset 0x28 to 0x2f */ uint8_t reserved_3[8]; uint8_t mac_address[6]; /* 0ffset 0x36 to 0xff */ uint8_t reserved_4[202]; } __attribute__ ((packed)); struct jlink_config jlink_cfg; /***************************************************************************/ /* External interface implementation */ static void jlink_execute_runtest(struct jtag_command *cmd) { DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); jlink_end_state(cmd->cmd.runtest->end_state); jlink_runtest(cmd->cmd.runtest->num_cycles); } static void jlink_execute_statemove(struct jtag_command *cmd) { DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); jlink_end_state(cmd->cmd.statemove->end_state); jlink_state_move(); } static void jlink_execute_pathmove(struct jtag_command *cmd) { DEBUG_JTAG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); } static void jlink_execute_scan(struct jtag_command *cmd) { int scan_size; enum scan_type type; uint8_t *buffer; DEBUG_JTAG_IO("scan end in %s", tap_state_name(cmd->cmd.scan->end_state)); jlink_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); DEBUG_JTAG_IO("scan input, length = %d", scan_size); jlink_debug_buffer(buffer, (scan_size + 7) / 8); type = jtag_scan_type(cmd->cmd.scan); jlink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); } static void jlink_execute_reset(struct jtag_command *cmd) { DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); jlink_tap_execute(); jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); jlink_tap_execute(); } static void jlink_execute_sleep(struct jtag_command *cmd) { DEBUG_JTAG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us); jlink_tap_execute(); jtag_sleep(cmd->cmd.sleep->us); } static void jlink_execute_command(struct jtag_command *cmd) { switch (cmd->type) { case JTAG_RUNTEST: jlink_execute_runtest(cmd); break; case JTAG_TLR_RESET: jlink_execute_statemove(cmd); break; case JTAG_PATHMOVE: jlink_execute_pathmove(cmd); break; case JTAG_SCAN: jlink_execute_scan(cmd); break; case JTAG_RESET: jlink_execute_reset(cmd); break; case JTAG_SLEEP: jlink_execute_sleep(cmd); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } } static int jlink_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; while (cmd != NULL) { jlink_execute_command(cmd); cmd = cmd->next; } return jlink_tap_execute(); } /* Sets speed in kHz. */ static int jlink_speed(int speed) { int result; if (speed > JLINK_MAX_SPEED) { LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, JLINK_MAX_SPEED); speed = JLINK_MAX_SPEED; } /* check for RTCK setting */ if (speed == 0) speed = -1; usb_out_buffer[0] = EMU_CMD_SET_SPEED; usb_out_buffer[1] = (speed >> 0) & 0xff; usb_out_buffer[2] = (speed >> 8) & 0xff; result = jlink_usb_write(jlink_handle, 3); if (result != 3) { LOG_ERROR("J-Link setting speed failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int jlink_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } static int jlink_khz(int khz, int *jtag_speed) { *jtag_speed = khz; return ERROR_OK; } static int jlink_register(void) { int result; usb_out_buffer[0] = EMU_CMD_REGISTER; usb_out_buffer[1] = REG_CMD_REGISTER; /* 2 - 11 is "additional parameter", * 12 - 13 is connection handle, zero initially */ memset(&usb_out_buffer[2], 0, 10 + 2); result = jlink_usb_write(jlink_handle, 14); if (result != 14) { LOG_ERROR("J-Link register write failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } /* Returns: * 0 - 1 connection handle, * 2 - 3 number of information entities, * 4 - 5 size of a single information struct, * 6 - 7 number of additional bytes, * 8 - ... reply data * * Try to read the whole USB bulk packet */ result = jtag_libusb_bulk_read(jlink_handle->usb_handle, jlink_read_ep, (char *)usb_in_buffer, sizeof(usb_in_buffer), JLINK_USB_TIMEOUT); if (!result) { LOG_ERROR("J-Link register read failed (0 bytes received)"); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } /* * select transport interface * * @param iface [0..31] currently: 0=JTAG, 1=SWD * @returns ERROR_OK or ERROR_ code * * @pre jlink_handle must be opened * @pre function may be called only for devices, that have * EMU_CAP_SELECT_IF capability enabled */ static int jlink_select_interface(int iface) { /* According to Segger's document RM08001-R7 Date: October 8, 2010, * http://www.segger.com/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf * section 5.5.3 EMU_CMD_SELECT_IF * > SubCmd 1..31 to select interface (0..31) * * The table below states: * 0 TIF_JTAG * 1 TIF_SWD * * This obviosly means that to select TIF_JTAG one should write SubCmd = 1. * * In fact, JTAG interface operates when SubCmd=0 * * It looks like a typo in documentation, because interfaces 0..31 could not * be selected by 1..31 range command. */ assert(iface >= 0 && iface < 32); int result; /* get available interfaces */ usb_out_buffer[0] = EMU_CMD_SELECT_IF; usb_out_buffer[1] = 0xff; result = jlink_usb_io(jlink_handle, 2, 4); if (result != ERROR_OK) { LOG_ERROR("J-Link query interface failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } uint32_t iface_mask = buf_get_u32(usb_in_buffer, 0, 32); if (!(iface_mask & (1<> i) & 1; jlink_tap_append_step(tms, 0); } tap_set_state(tap_get_end_state()); } static void jlink_path_move(int num_states, tap_state_t *path) { int i; for (i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) jlink_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) jlink_tap_append_step(1, 0); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); exit(-1); } tap_set_state(path[i]); } tap_set_end_state(tap_get_state()); } static void jlink_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); jlink_tap_ensure_space(1, num_cycles + 16); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { jlink_end_state(TAP_IDLE); jlink_state_move(); /* num_cycles--; */ } /* execute num_cycles */ for (i = 0; i < num_cycles; i++) jlink_tap_append_step(0, 0); /* finish in end_state */ jlink_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) jlink_state_move(); } static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { tap_state_t saved_end_state; jlink_tap_ensure_space(1, scan_size + 16); saved_end_state = tap_get_end_state(); /* Move to appropriate scan state */ jlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); /* Only move if we're not already there */ if (tap_get_state() != tap_get_end_state()) jlink_state_move(); jlink_end_state(saved_end_state); /* Scan */ jlink_tap_append_scan(scan_size, buffer, command); /* We are in Exit1, go to Pause */ jlink_tap_append_step(0, 0); tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) jlink_state_move(); } static void jlink_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); /* Signals are active low */ if (srst == 0) jlink_simple_command(EMU_CMD_HW_RESET1); if (srst == 1) jlink_simple_command(EMU_CMD_HW_RESET0); if (trst == 1) jlink_simple_command(EMU_CMD_HW_TRST0); if (trst == 0) jlink_simple_command(EMU_CMD_HW_TRST1); } static void jlink_simple_command(uint8_t command) { int result; DEBUG_JTAG_IO("0x%02x", command); usb_out_buffer[0] = command; result = jlink_usb_write(jlink_handle, 1); if (result != 1) LOG_ERROR("J-Link command 0x%02x failed (%d)", command, result); } static int jlink_get_status(void) { int result; jlink_simple_command(EMU_CMD_GET_STATE); result = jlink_usb_read(jlink_handle, 8); if (result != 8) { LOG_ERROR("J-Link command EMU_CMD_GET_STATE failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } int vref = usb_in_buffer[0] + (usb_in_buffer[1] << 8); LOG_INFO("Vref = %d.%d TCK = %d TDI = %d TDO = %d TMS = %d SRST = %d TRST = %d", \ vref / 1000, vref % 1000, \ usb_in_buffer[2], usb_in_buffer[3], usb_in_buffer[4], \ usb_in_buffer[5], usb_in_buffer[6], usb_in_buffer[7]); if (vref < 1500) LOG_ERROR("Vref too low. Check Target Power"); return ERROR_OK; } #define jlink_dump_printf(context, expr ...) \ do { \ if (context) \ command_print(context, expr); \ else \ LOG_INFO(expr); \ } while (0); static void jlink_caps_dump(struct command_context *ctx) { int i; jlink_dump_printf(ctx, "J-Link Capabilities"); for (i = 1; i < 31; i++) if (jlink_caps & (1 << i)) jlink_dump_printf(ctx, "%s", jlink_cap_str[i]); } static void jlink_config_usb_address_dump(struct command_context *ctx, struct jlink_config *cfg) { if (!cfg) return; jlink_dump_printf(ctx, "USB-Address: 0x%x", cfg->usb_address); } static void jlink_config_kickstart_dump(struct command_context *ctx, struct jlink_config *cfg) { if (!cfg) return; jlink_dump_printf(ctx, "Kickstart power on JTAG-pin 19: 0x%" PRIx32, cfg->kickstart_power_on_jtag_pin_19); } static void jlink_config_mac_address_dump(struct command_context *ctx, struct jlink_config *cfg) { if (!cfg) return; jlink_dump_printf(ctx, "MAC Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x", cfg->mac_address[5], cfg->mac_address[4], cfg->mac_address[3], cfg->mac_address[2], cfg->mac_address[1], cfg->mac_address[0]); } static void jlink_config_ip_dump(struct command_context *ctx, struct jlink_config *cfg) { if (!cfg) return; jlink_dump_printf(ctx, "IP Address: %d.%d.%d.%d", cfg->ip_address[3], cfg->ip_address[2], cfg->ip_address[1], cfg->ip_address[0]); jlink_dump_printf(ctx, "Subnet Mask: %d.%d.%d.%d", cfg->subnet_mask[3], cfg->subnet_mask[2], cfg->subnet_mask[1], cfg->subnet_mask[0]); } static void jlink_config_dump(struct command_context *ctx, struct jlink_config *cfg) { if (!cfg) return; jlink_dump_printf(ctx, "J-Link configuration"); jlink_config_usb_address_dump(ctx, cfg); jlink_config_kickstart_dump(ctx, cfg); if (jlink_hw_type == JLINK_HW_TYPE_JLINK_PRO) { jlink_config_ip_dump(ctx, cfg); jlink_config_mac_address_dump(ctx, cfg); } } static int jlink_get_config(struct jlink_config *cfg) { int result; int size = sizeof(struct jlink_config); usb_out_buffer[0] = EMU_CMD_READ_CONFIG; result = jlink_usb_io(jlink_handle, 1, size); if (result != ERROR_OK) { LOG_ERROR("jlink_usb_read failed (requested=%d, result=%d)", size, result); return ERROR_FAIL; } memcpy(cfg, usb_in_buffer, size); return ERROR_OK; } static int jlink_set_config(struct jlink_config *cfg) { int result; int size = sizeof(struct jlink_config); jlink_simple_command(EMU_CMD_WRITE_CONFIG); memcpy(usb_out_buffer, cfg, size); result = jlink_usb_write(jlink_handle, size); if (result != size) { LOG_ERROR("jlink_usb_write failed (requested=%d, result=%d)", 256, result); return ERROR_FAIL; } return ERROR_OK; } /* * List of unsupported version string markers. * * The firmware versions does not correspond directly with * "Software and documentation pack for Windows", it may be * distinguished by the "compile" date in the information string. * * For example, version string is: * "J-Link ARM V8 compiled May 3 2012 18:36:22" * Marker sould be: * "May 3 2012" * * The list must be terminated by NULL string. */ static const char * const unsupported_versions[] = { "Jan 31 2011", "JAN 31 2011", NULL /* End of list */ }; static void jlink_check_supported(const char *str) { const char * const *p = unsupported_versions; while (*p) { if (NULL != strstr(str, *p)) { LOG_WARNING( "Unsupported J-Link firmware version.\n" " Please check http://www.segger.com/j-link-older-versions.html for updates"); return; } p++; } } static int jlink_get_version_info(void) { int result; int len; uint32_t jlink_max_size; /* query hardware version */ jlink_simple_command(EMU_CMD_VERSION); result = jlink_usb_read(jlink_handle, 2); if (2 != result) { LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } len = buf_get_u32(usb_in_buffer, 0, 16); if (len > JLINK_IN_BUFFER_SIZE) { LOG_ERROR("J-Link command EMU_CMD_VERSION impossible return length 0x%0x", len); len = JLINK_IN_BUFFER_SIZE; } result = jlink_usb_read(jlink_handle, len); if (result != len) { LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } usb_in_buffer[result] = 0; LOG_INFO("%s", (char *)usb_in_buffer); jlink_check_supported((char *)usb_in_buffer); /* query hardware capabilities */ jlink_simple_command(EMU_CMD_GET_CAPS); result = jlink_usb_read(jlink_handle, 4); if (4 != result) { LOG_ERROR("J-Link command EMU_CMD_GET_CAPS failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } jlink_caps = buf_get_u32(usb_in_buffer, 0, 32); LOG_INFO("J-Link caps 0x%x", (unsigned)jlink_caps); if (jlink_caps & (1 << EMU_CAP_GET_HW_VERSION)) { /* query hardware version */ jlink_simple_command(EMU_CMD_GET_HW_VERSION); result = jlink_usb_read(jlink_handle, 4); if (4 != result) { LOG_ERROR("J-Link command EMU_CMD_GET_HW_VERSION failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } uint32_t jlink_hw_version = buf_get_u32(usb_in_buffer, 0, 32); uint32_t major_revision = (jlink_hw_version / 10000) % 100; jlink_hw_type = (jlink_hw_version / 1000000) % 100; if (major_revision >= 5) jlink_hw_jtag_version = 3; LOG_INFO("J-Link hw version %i", (int)jlink_hw_version); switch (jlink_hw_type) { case JLINK_HW_TYPE_JLINK: LOG_INFO("J-Link hw type J-Link"); break; case JLINK_HW_TYPE_JTRACE: LOG_INFO("J-Link hw type J-Trace"); break; case JLINK_HW_TYPE_FLASHER: LOG_INFO("J-Link hw type Flasher"); break; case JLINK_HW_TYPE_JLINK_PRO: LOG_INFO("J-Link hw type J-Link Pro"); break; case JLINK_HW_TYPE_JLINK_LITE_ADI: LOG_INFO("J-Link hw type J-Link Lite-ADI"); break; case JLINK_HW_TYPE_JLINK_LITE_XMC4000: LOG_INFO("J-Link hw type J-Link Lite-XMC4000"); break; case JLINK_HW_TYPE_JLINK_LITE_XMC4200: LOG_INFO("J-Link hw type J-Link Lite-XMC4200"); break; case JLINK_HW_TYPE_LPCLINK2: LOG_INFO("J-Link hw type J-Link on LPC-Link2"); break; default: LOG_INFO("J-Link hw type unknown 0x%" PRIx32, jlink_hw_type); break; } } if (jlink_caps & (1 << EMU_CAP_GET_MAX_BLOCK_SIZE)) { /* query hardware maximum memory block */ jlink_simple_command(EMU_CMD_GET_MAX_MEM_BLOCK); result = jlink_usb_read(jlink_handle, 4); if (4 != result) { LOG_ERROR("J-Link command EMU_CMD_GET_MAX_MEM_BLOCK failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } jlink_max_size = buf_get_u32(usb_in_buffer, 0, 32); LOG_INFO("J-Link max mem block %i", (int)jlink_max_size); } if (jlink_caps & (1 << EMU_CAP_READ_CONFIG)) { if (jlink_get_config(&jlink_cfg) != ERROR_OK) return ERROR_JTAG_DEVICE_ERROR; jlink_config_dump(NULL, &jlink_cfg); } return ERROR_OK; } COMMAND_HANDLER(jlink_pid_command) { if (CMD_ARGC != 1) { LOG_ERROR("Need exactly one argument to jlink_pid"); return ERROR_FAIL; } pids[0] = strtoul(CMD_ARGV[0], NULL, 16); pids[1] = 0; vids[1] = 0; return ERROR_OK; } COMMAND_HANDLER(jlink_serial_command) { if (CMD_ARGC != 1) { LOG_ERROR("Need exactly one argument to jlink_serial"); return ERROR_FAIL; } if (jlink_serial) free(jlink_serial); jlink_serial = strdup(CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_info_command) { if (jlink_get_version_info() == ERROR_OK) { /* attempt to get status */ jlink_get_status(); } return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_caps_command) { jlink_caps_dump(CMD_CTX); return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_hw_jtag_command) { switch (CMD_ARGC) { case 0: command_print(CMD_CTX, "J-Link hw jtag %i", jlink_hw_jtag_version); break; case 1: { int request_version = atoi(CMD_ARGV[0]); switch (request_version) { case 2: case 3: jlink_hw_jtag_version = request_version; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } break; } default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_kickstart_command) { uint32_t kickstart; if (CMD_ARGC < 1) { jlink_config_kickstart_dump(CMD_CTX, &jlink_cfg); return ERROR_OK; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], kickstart); jlink_cfg.kickstart_power_on_jtag_pin_19 = kickstart; return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_mac_address_command) { uint8_t addr[6]; int i; char *e; const char *str; if (CMD_ARGC < 1) { jlink_config_mac_address_dump(CMD_CTX, &jlink_cfg); return ERROR_OK; } str = CMD_ARGV[0]; if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || str[8] != ':' || str[11] != ':' || str[14] != ':')) { command_print(CMD_CTX, "ethaddr miss format ff:ff:ff:ff:ff:ff"); return ERROR_COMMAND_SYNTAX_ERROR; } for (i = 5; i >= 0; i--) { addr[i] = strtoul(str, &e, 16); str = e + 1; } if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) { command_print(CMD_CTX, "invalid it's zero mac_address"); return ERROR_COMMAND_SYNTAX_ERROR; } if (!(0x01 & addr[0])) { command_print(CMD_CTX, "invalid it's a multicat mac_address"); return ERROR_COMMAND_SYNTAX_ERROR; } memcpy(jlink_cfg.mac_address, addr, sizeof(addr)); return ERROR_OK; } static int string_to_ip(const char *s, uint8_t *ip, int *pos) { uint8_t lip[4]; char *e; const char *s_save = s; int i; if (!s) return -EINVAL; for (i = 0; i < 4; i++) { lip[i] = strtoul(s, &e, 10); if (*e != '.' && i != 3) return -EINVAL; s = e + 1; } *pos = e - s_save; memcpy(ip, lip, sizeof(lip)); return ERROR_OK; } static void cpy_ip(uint8_t *dst, uint8_t *src) { int i, j; for (i = 0, j = 3; i < 4; i++, j--) dst[i] = src[j]; } COMMAND_HANDLER(jlink_handle_jlink_ip_command) { uint32_t ip_address; uint32_t subnet_mask = 0; int i, len; int ret; uint8_t subnet_bits = 24; if (CMD_ARGC < 1) { jlink_config_ip_dump(CMD_CTX, &jlink_cfg); return ERROR_OK; } ret = string_to_ip(CMD_ARGV[0], (uint8_t *)&ip_address, &i); if (ret != ERROR_OK) return ret; len = strlen(CMD_ARGV[0]); /* check for this format A.B.C.D/E */ if (i < len) { if (CMD_ARGV[0][i] != '/') return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0] + i + 1, subnet_bits); } else { if (CMD_ARGC > 1) { ret = string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i); if (ret != ERROR_OK) return ret; } } if (!subnet_mask) subnet_mask = (uint32_t)(subnet_bits < 32 ? ((1ULL << subnet_bits) - 1) : 0xffffffff); cpy_ip(jlink_cfg.ip_address, (uint8_t *)&ip_address); cpy_ip(jlink_cfg.subnet_mask, (uint8_t *)&subnet_mask); return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_reset_command) { memset(&jlink_cfg, 0xff, sizeof(jlink_cfg)); return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_save_command) { if (!(jlink_caps & (1 << EMU_CAP_WRITE_CONFIG))) { command_print(CMD_CTX, "J-Link write emulator configuration not supported"); return ERROR_OK; } command_print(CMD_CTX, "The J-Link need to be unpluged and repluged ta have the config effective"); return jlink_set_config(&jlink_cfg); } COMMAND_HANDLER(jlink_handle_jlink_usb_address_command) { uint32_t address; if (CMD_ARGC < 1) { jlink_config_usb_address_dump(CMD_CTX, &jlink_cfg); return ERROR_OK; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); if (address > 0x3 && address != 0xff) { command_print(CMD_CTX, "USB Address must be between 0x00 and 0x03 or 0xff"); return ERROR_COMMAND_SYNTAX_ERROR; } jlink_cfg.usb_address = address; return ERROR_OK; } COMMAND_HANDLER(jlink_handle_jlink_config_command) { struct jlink_config cfg; int ret = ERROR_OK; if (CMD_ARGC == 0) { if (!(jlink_caps & (1 << EMU_CAP_READ_CONFIG))) { command_print(CMD_CTX, "J-Link read emulator configuration not supported"); goto exit; } ret = jlink_get_config(&cfg); if (ret != ERROR_OK) command_print(CMD_CTX, "J-Link read emulator configuration failled"); else jlink_config_dump(CMD_CTX, &jlink_cfg); } exit: return ret; } static const struct command_registration jlink_config_subcommand_handlers[] = { { .name = "kickstart", .handler = &jlink_handle_jlink_kickstart_command, .mode = COMMAND_EXEC, .help = "set Kickstart power on JTAG-pin 19.", .usage = "[val]", }, { .name = "mac_address", .handler = &jlink_handle_jlink_mac_address_command, .mode = COMMAND_EXEC, .help = "set the MAC Address", .usage = "[ff:ff:ff:ff:ff:ff]", }, { .name = "ip", .handler = &jlink_handle_jlink_ip_command, .mode = COMMAND_EXEC, .help = "set the ip address of the J-Link Pro, " "where A.B.C.D is the ip, " "E the bit of the subnet mask, " "F.G.H.I the subnet mask", .usage = "[A.B.C.D[/E] [F.G.H.I]]", }, { .name = "reset", .handler = &jlink_handle_jlink_reset_command, .mode = COMMAND_EXEC, .help = "reset the current config", }, { .name = "save", .handler = &jlink_handle_jlink_save_command, .mode = COMMAND_EXEC, .help = "save the current config", }, { .name = "usb_address", .handler = &jlink_handle_jlink_usb_address_command, .mode = COMMAND_EXEC, .help = "set the USB-Address, " "This will change the product id", .usage = "[0x00 to 0x03 or 0xff]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration jlink_subcommand_handlers[] = { { .name = "caps", .handler = &jlink_handle_jlink_caps_command, .mode = COMMAND_EXEC, .help = "show jlink capabilities", }, { .name = "info", .handler = &jlink_handle_jlink_info_command, .mode = COMMAND_EXEC, .help = "show jlink info", }, { .name = "hw_jtag", .handler = &jlink_handle_jlink_hw_jtag_command, .mode = COMMAND_EXEC, .help = "access J-Link HW JTAG command version", .usage = "[2|3]", }, { .name = "config", .handler = &jlink_handle_jlink_config_command, .mode = COMMAND_EXEC, .help = "access J-Link configuration, " "if no argument this will dump the config", .chain = jlink_config_subcommand_handlers, }, { .name = "pid", .handler = &jlink_pid_command, .mode = COMMAND_CONFIG, .help = "set the pid of the interface we want to use", }, { .name = "serial", .handler = &jlink_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the J-Link adapter we want to use" }, COMMAND_REGISTRATION_DONE }; static const struct command_registration jlink_command_handlers[] = { { .name = "jlink", .mode = COMMAND_ANY, .help = "perform jlink management", .chain = jlink_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; static int jlink_swd_init(void) { LOG_INFO("JLink SWD mode enabled"); swd_mode = true; return ERROR_OK; } static void jlink_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value) { assert(!(cmd & SWD_CMD_RnW)); jlink_swd_queue_cmd(dap, cmd, NULL, value); } static void jlink_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value) { assert(cmd & SWD_CMD_RnW); jlink_swd_queue_cmd(dap, cmd, value, 0); } static int_least32_t jlink_swd_frequency(struct adiv5_dap *dap, int_least32_t hz) { if (hz > 0) jlink_speed(hz / 1000); return hz; } static const struct swd_driver jlink_swd = { .init = jlink_swd_init, .frequency = jlink_swd_frequency, .switch_seq = jlink_swd_switch_seq, .read_reg = jlink_swd_read_reg, .write_reg = jlink_swd_write_reg, .run = jlink_swd_run_queue, }; static const char * const jlink_transports[] = { "jtag", "swd", NULL }; struct jtag_interface jlink_interface = { .name = "jlink", .commands = jlink_command_handlers, .transports = jlink_transports, .swd = &jlink_swd, .execute_queue = jlink_execute_queue, .speed = jlink_speed, .speed_div = jlink_speed_div, .khz = jlink_khz, .init = jlink_init, .quit = jlink_quit, }; /***************************************************************************/ /* J-Link tap functions */ static unsigned tap_length; /* In SWD mode use tms buffer for direction control */ static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE]; static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE]; struct pending_scan_result { int first; /* First bit position in tdo_buffer to read */ int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ void *buffer; }; #define MAX_PENDING_SCAN_RESULTS 256 static int pending_scan_results_length; static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; static void jlink_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; } static void jlink_tap_ensure_space(int scans, int bits) { int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length - 32; if (scans > available_scans || bits > available_bits) jlink_tap_execute(); } static void jlink_tap_append_step(int tms, int tdi) { int index_var = tap_length / 8; assert(index_var < JLINK_TAP_BUFFER_SIZE); int bit_index = tap_length % 8; uint8_t bit = 1 << bit_index; /* we do not pad TMS, so be sure to initialize all bits */ if (0 == bit_index) tms_buffer[index_var] = tdi_buffer[index_var] = 0; if (tms) tms_buffer[index_var] |= bit; else tms_buffer[index_var] &= ~bit; if (tdi) tdi_buffer[index_var] |= bit; else tdi_buffer[index_var] &= ~bit; tap_length++; } static void jlink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length]; int i; pending_scan_result->first = tap_length; pending_scan_result->length = length; pending_scan_result->command = command; pending_scan_result->buffer = buffer; for (i = 0; i < length; i++) { int tms = (i < (length - 1)) ? 0 : 1; int tdi = (buffer[i / 8] & (1 << (i % 8))) != 0; jlink_tap_append_step(tms, tdi); } pending_scan_results_length++; } /* Pad and send a tap sequence to the device, and receive the answer. * For the purpose of padding we assume that we are in idle or pause state. */ static int jlink_tap_execute(void) { int byte_length; int i; int result; if (!tap_length) return ERROR_OK; /* JLink returns an extra NULL in packet when size of incoming * message is a multiple of 64, creates problems with USB comms. * WARNING: This will interfere with tap state counting. */ while ((DIV_ROUND_UP(tap_length, 8) % 64) == 0) jlink_tap_append_step((tap_get_state() == TAP_RESET) ? 1 : 0, 0); /* number of full bytes (plus one if some would be left over) */ byte_length = DIV_ROUND_UP(tap_length, 8); bool use_jtag3 = jlink_hw_jtag_version >= 3; usb_out_buffer[0] = use_jtag3 ? EMU_CMD_HW_JTAG3 : EMU_CMD_HW_JTAG2; usb_out_buffer[1] = 0; usb_out_buffer[2] = (tap_length >> 0) & 0xff; usb_out_buffer[3] = (tap_length >> 8) & 0xff; memcpy(usb_out_buffer + 4, tms_buffer, byte_length); memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length); jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer, tap_length, jlink_last_state); result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, use_jtag3 ? byte_length + 1 : byte_length); if (result != ERROR_OK) { LOG_ERROR("jlink_tap_execute failed USB io (%d)", result); jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } result = use_jtag3 ? usb_in_buffer[byte_length] : 0; if (result != 0) { LOG_ERROR("jlink_tap_execute failed, result %d (%s)", result, result == 1 ? "adaptive clocking timeout" : "unknown"); jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } memcpy(tdo_buffer, usb_in_buffer, byte_length); for (i = 0; i < pending_scan_results_length; i++) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; uint8_t *buffer = pending_scan_result->buffer; int length = pending_scan_result->length; int first = pending_scan_result->first; struct scan_command *command = pending_scan_result->command; /* Copy to buffer */ buf_set_buf(tdo_buffer, first, buffer, 0, length); DEBUG_JTAG_IO("pending scan result, length = %d", length); jlink_debug_buffer(buffer, DIV_ROUND_UP(length, 8)); if (jtag_read_buffer(buffer, command) != ERROR_OK) { jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } if (pending_scan_result->buffer != NULL) free(pending_scan_result->buffer); } jlink_tap_init(); return ERROR_OK; } static void fill_buffer(uint8_t *buf, uint32_t val, uint32_t len) { unsigned int tap_pos = tap_length; while (len > 32) { buf_set_u32(buf, tap_pos, 32, val); len -= 32; tap_pos += 32; } if (len) buf_set_u32(buf, tap_pos, len, val); } static void jlink_queue_data_out(const uint8_t *data, uint32_t len) { const uint32_t dir_out = 0xffffffff; if (data) bit_copy(tdi_buffer, tap_length, data, 0, len); else fill_buffer(tdi_buffer, 0, len); fill_buffer(tms_buffer, dir_out, len); tap_length += len; } static void jlink_queue_data_in(uint32_t len) { const uint32_t dir_in = 0; fill_buffer(tms_buffer, dir_in, len); tap_length += len; } static int jlink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq) { const uint8_t *s; unsigned int s_len; switch (seq) { case LINE_RESET: LOG_DEBUG("SWD line reset"); s = swd_seq_line_reset; s_len = swd_seq_line_reset_len; break; case JTAG_TO_SWD: LOG_DEBUG("JTAG-to-SWD"); s = swd_seq_jtag_to_swd; s_len = swd_seq_jtag_to_swd_len; break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); s = swd_seq_swd_to_jtag; s_len = swd_seq_swd_to_jtag_len; break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; } jlink_queue_data_out(s, s_len); return ERROR_OK; } static int jlink_swd_run_queue(struct adiv5_dap *dap) { LOG_DEBUG("Executing %d queued transactions", pending_scan_results_length); int retval; if (queued_retval != ERROR_OK) { LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); goto skip; } /* A transaction must be followed by another transaction or at least 8 idle cycles to * ensure that data is clocked through the AP. */ jlink_queue_data_out(NULL, 8); size_t byte_length = DIV_ROUND_UP(tap_length, 8); /* There's a comment in jlink_tap_execute saying JLink returns * an extra NULL in packet when size of incoming message is a * multiple of 64. Someone should verify if that's still the * case with the current jlink firmware */ usb_out_buffer[0] = EMU_CMD_HW_JTAG3; usb_out_buffer[1] = 0; usb_out_buffer[2] = (tap_length >> 0) & 0xff; usb_out_buffer[3] = (tap_length >> 8) & 0xff; memcpy(usb_out_buffer + 4, tms_buffer, byte_length); memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length); retval = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, byte_length + 1); if (retval != ERROR_OK) { LOG_ERROR("jlink_swd_run_queue failed USB io (%d)", retval); goto skip; } retval = usb_in_buffer[byte_length]; if (retval) { LOG_ERROR("jlink_swd_run_queue failed, result %d", retval); goto skip; } for (int i = 0; i < pending_scan_results_length; i++) { int ack = buf_get_u32(usb_in_buffer, pending_scan_results_buffer[i].first, 3); if (ack != SWD_ACK_OK) { LOG_DEBUG("SWD ack not OK: %d %s", ack, ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; goto skip; } else if (pending_scan_results_buffer[i].length) { uint32_t data = buf_get_u32(usb_in_buffer, 3 + pending_scan_results_buffer[i].first, 32); int parity = buf_get_u32(usb_in_buffer, 3 + 32 + pending_scan_results_buffer[i].first, 1); if (parity != parity_u32(data)) { LOG_ERROR("SWD Read data parity mismatch"); queued_retval = ERROR_FAIL; goto skip; } if (pending_scan_results_buffer[i].buffer) *(uint32_t *)pending_scan_results_buffer[i].buffer = data; } } skip: jlink_tap_init(); retval = queued_retval; queued_retval = ERROR_OK; return retval; } static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data) { uint8_t data_parity_trn[DIV_ROUND_UP(32 + 1, 8)]; if (tap_length + 46 + 8 + dap->memaccess_tck >= sizeof(tdi_buffer) * 8 || pending_scan_results_length == MAX_PENDING_SCAN_RESULTS) { /* Not enough room in the queue. Run the queue. */ queued_retval = jlink_swd_run_queue(dap); } if (queued_retval != ERROR_OK) return; cmd |= SWD_CMD_START | SWD_CMD_PARK; jlink_queue_data_out(&cmd, 8); pending_scan_results_buffer[pending_scan_results_length].first = tap_length; if (cmd & SWD_CMD_RnW) { /* Queue a read transaction */ pending_scan_results_buffer[pending_scan_results_length].length = 32; pending_scan_results_buffer[pending_scan_results_length].buffer = dst; jlink_queue_data_in(1 + 3 + 32 + 1 + 1); } else { /* Queue a write transaction */ pending_scan_results_buffer[pending_scan_results_length].length = 0; jlink_queue_data_in(1 + 3 + 1); buf_set_u32(data_parity_trn, 0, 32, data); buf_set_u32(data_parity_trn, 32, 1, parity_u32(data)); jlink_queue_data_out(data_parity_trn, 32 + 1); } pending_scan_results_length++; /* Insert idle cycles after AP accesses to avoid WAIT */ if (cmd & SWD_CMD_APnDP) jlink_queue_data_out(NULL, dap->memaccess_tck); } /*****************************************************************************/ /* JLink USB low-level functions */ static struct jlink *jlink_usb_open() { struct jtag_libusb_device_handle *devh; if (jtag_libusb_open(vids, pids, jlink_serial, &devh) != ERROR_OK) return NULL; /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS * AREA!!!!!!!!!!! The behavior of libusb is not completely * consistent across Windows, Linux, and Mac OS X platforms. * The actions taken in the following compiler conditionals may * not agree with published documentation for libusb, but were * found to be necessary through trials and tribulations. Even * little tweaks can break one or more platforms, so if you do * make changes test them carefully on all platforms before * committing them! */ /* This entire block can probably be removed. It was a workaround for * libusb0.1 and old JLink firmware. It has already be removed for * windows and causing problems (LPC Link-2 with JLink firmware) on * Linux with libusb1.0. * * However, for now the behavior will be left unchanged for non-windows * platforms using libusb0.1 due to lack of testing. */ #if IS_WIN32 == 0 && HAVE_LIBUSB1 == 0 jtag_libusb_reset_device(devh); #if IS_DARWIN == 0 int timeout = 5; /* reopen jlink after usb_reset * on win32 this may take a second or two to re-enumerate */ int retval; while ((retval = jtag_libusb_open(vids, pids, jlink_serial, &devh)) != ERROR_OK) { usleep(1000); timeout--; if (!timeout) break; } if (ERROR_OK != retval) return NULL; #endif #endif /* usb_set_configuration is only required under win32 * with libusb 0.1 and libusb0.sys. For libusb 1.0 it is a no-op * since the configuration is already set. */ jtag_libusb_set_configuration(devh, 0); jtag_libusb_choose_interface(devh, &jlink_read_ep, &jlink_write_ep, JLINK_USB_INTERFACE_CLASS, JLINK_USB_INTERFACE_SUBCLASS, JLINK_USB_INTERFACE_PROTOCOL); struct jlink *result = malloc(sizeof(struct jlink)); result->usb_handle = devh; return result; } static void jlink_usb_close(struct jlink *jlink) { jtag_libusb_close(jlink->usb_handle); free(jlink); } /* Send a message and receive the reply. */ static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length) { int result; result = jlink_usb_write(jlink, out_length); if (result != out_length) { LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result); return ERROR_JTAG_DEVICE_ERROR; } result = jlink_usb_read(jlink, in_length); if (result != in_length) { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } /* calls the given usb_bulk_* function, allowing for the data to * trickle in with some timeouts */ static int usb_bulk_with_retries( int (*f)(jtag_libusb_device_handle *, int, char *, int, int), jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { int tries = 3, count = 0; while (tries && (count < size)) { int result = f(dev, ep, bytes + count, size - count, timeout); if (result > 0) count += result; else if ((-ETIMEDOUT != result) || !--tries) return result; } return count; } static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *buff, int size, int timeout) { /* usb_bulk_write() takes const char *buff */ return jtag_libusb_bulk_write(dev, ep, buff, size, timeout); } static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_with_retries(&wrap_usb_bulk_write, dev, ep, bytes, size, timeout); } static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_with_retries(&jtag_libusb_bulk_read, dev, ep, bytes, size, timeout); } /* Write data from out_buffer to USB. */ static int jlink_usb_write(struct jlink *jlink, int out_length) { int result; if (out_length > JLINK_OUT_BUFFER_SIZE) { LOG_ERROR("jlink_write illegal out_length=%d (max=%d)", out_length, JLINK_OUT_BUFFER_SIZE); return -1; } result = usb_bulk_write_ex(jlink->usb_handle, jlink_write_ep, (char *)usb_out_buffer, out_length, JLINK_USB_TIMEOUT); DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d", out_length, result); jlink_debug_buffer(usb_out_buffer, out_length); return result; } /* Read data from USB into in_buffer. */ static int jlink_usb_read(struct jlink *jlink, int expected_size) { int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep, (char *)usb_in_buffer, expected_size, JLINK_USB_TIMEOUT); DEBUG_JTAG_IO("jlink_usb_read, result = %d", result); jlink_debug_buffer(usb_in_buffer, result); return result; } /* * Send a message and receive the reply - simple messages. * * @param jlink pointer to driver data * @param out_length data length in @c usb_out_buffer * @param in_length data length to be read to @c usb_in_buffer */ static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length) { int result; result = jlink_usb_write(jlink, out_length); if (result != out_length) { LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result); return ERROR_JTAG_DEVICE_ERROR; } result = jlink_usb_read(jlink, in_length); if (result != in_length) { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); return ERROR_JTAG_DEVICE_ERROR; } /* * Section 4.2.4 IN-transaction: * read dummy 0-byte packet if transaction size is * multiple of 64 bytes but not max. size of 0x8000 */ if ((in_length % 64) == 0 && in_length != 0x8000) { char dummy_buffer; result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep, &dummy_buffer, 1, JLINK_USB_TIMEOUT); if (result != 0) { LOG_ERROR("dummy byte read failed"); return ERROR_JTAG_DEVICE_ERROR; } } return ERROR_OK; } #ifdef _DEBUG_USB_COMMS_ #define BYTES_PER_LINE 16 static void jlink_debug_buffer(uint8_t *buffer, int length) { char line[81]; char s[4]; int i; int j; for (i = 0; i < length; i += BYTES_PER_LINE) { snprintf(line, 5, "%04x", i); for (j = i; j < i + BYTES_PER_LINE && j < length; j++) { snprintf(s, 4, " %02x", buffer[j]); strcat(line, s); } LOG_DEBUG("%s", line); } } #endif openocd-0.9.0/src/jtag/drivers/usb_common.c0000644000175000017500000000424012315575360015576 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "usb_common.h" static bool jtag_usb_match(struct usb_device *dev, const uint16_t vids[], const uint16_t pids[]) { for (unsigned i = 0; vids[i] && pids[i]; i++) { if (dev->descriptor.idVendor == vids[i] && dev->descriptor.idProduct == pids[i]) return true; } return false; } int jtag_usb_open(const uint16_t vids[], const uint16_t pids[], struct usb_dev_handle **out) { usb_find_busses(); usb_find_devices(); struct usb_bus *busses = usb_get_busses(); for (struct usb_bus *bus = busses; bus; bus = bus->next) { for (struct usb_device *dev = bus->devices; dev; dev = dev->next) { if (!jtag_usb_match(dev, vids, pids)) continue; *out = usb_open(dev); if (NULL == *out) return -errno; return 0; } } return -ENODEV; } openocd-0.9.0/src/jtag/drivers/usb_common.h0000644000175000017500000000306312315575360015605 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_USB_COMMON_H #define JTAG_USB_COMMON_H #include int jtag_usb_open(const uint16_t vids[], const uint16_t pids[], struct usb_dev_handle **out); #endif /* JTAG_USB_COMMON_H */ openocd-0.9.0/src/jtag/drivers/ep93xx.c0000644000175000017500000001302012315575360014571 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" #define TDO_BIT 1 #define TDI_BIT 2 #define TCK_BIT 4 #define TMS_BIT 8 #define TRST_BIT 16 #define SRST_BIT 32 #define VCC_BIT 64 #include static uint8_t output_value; static int dev_mem_fd; static void *gpio_controller; static volatile uint8_t *gpio_data_register; static volatile uint8_t *gpio_data_direction_register; /* low level command set */ static int ep93xx_read(void); static void ep93xx_write(int tck, int tms, int tdi); static void ep93xx_reset(int trst, int srst); static int ep93xx_init(void); static int ep93xx_quit(void); struct timespec ep93xx_zzzz; struct jtag_interface ep93xx_interface = { .name = "ep93xx", .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, .init = ep93xx_init, .quit = ep93xx_quit, }; static struct bitbang_interface ep93xx_bitbang = { .read = ep93xx_read, .write = ep93xx_write, .reset = ep93xx_reset, .blink = 0, }; static int ep93xx_read(void) { return !!(*gpio_data_register & TDO_BIT); } static void ep93xx_write(int tck, int tms, int tdi) { if (tck) output_value |= TCK_BIT; else output_value &= ~TCK_BIT; if (tms) output_value |= TMS_BIT; else output_value &= ~TMS_BIT; if (tdi) output_value |= TDI_BIT; else output_value &= ~TDI_BIT; *gpio_data_register = output_value; nanosleep(&ep93xx_zzzz, NULL); } /* (1) assert or (0) deassert reset lines */ static void ep93xx_reset(int trst, int srst) { if (trst == 0) output_value |= TRST_BIT; else if (trst == 1) output_value &= ~TRST_BIT; if (srst == 0) output_value |= SRST_BIT; else if (srst == 1) output_value &= ~SRST_BIT; *gpio_data_register = output_value; nanosleep(&ep93xx_zzzz, NULL); } static int set_gonk_mode(void) { void *syscon; uint32_t devicecfg; syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, 0x80930000); if (syscon == MAP_FAILED) { perror("mmap"); return ERROR_JTAG_INIT_FAILED; } devicecfg = *((volatile int *)(syscon + 0x80)); *((volatile int *)(syscon + 0xc0)) = 0xaa; *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000; munmap(syscon, 4096); return ERROR_OK; } static int ep93xx_init(void) { int ret; bitbang_interface = &ep93xx_bitbang; ep93xx_zzzz.tv_sec = 0; ep93xx_zzzz.tv_nsec = 10000000; dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if (dev_mem_fd < 0) { perror("open"); return ERROR_JTAG_INIT_FAILED; } gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, 0x80840000); if (gpio_controller == MAP_FAILED) { perror("mmap"); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } ret = set_gonk_mode(); if (ret != ERROR_OK) { munmap(gpio_controller, 4096); close(dev_mem_fd); return ret; } #if 0 /* Use GPIO port A. */ gpio_data_register = gpio_controller + 0x00; gpio_data_direction_register = gpio_controller + 0x10; /* Use GPIO port B. */ gpio_data_register = gpio_controller + 0x04; gpio_data_direction_register = gpio_controller + 0x14; /* Use GPIO port C. */ gpio_data_register = gpio_controller + 0x08; gpio_data_direction_register = gpio_controller + 0x18; /* Use GPIO port D. */ gpio_data_register = gpio_controller + 0x0c; gpio_data_direction_register = gpio_controller + 0x1c; #endif /* Use GPIO port C. */ gpio_data_register = gpio_controller + 0x08; gpio_data_direction_register = gpio_controller + 0x18; LOG_INFO("gpio_data_register = %p", gpio_data_register); LOG_INFO("gpio_data_direction_reg = %p", gpio_data_direction_register); /* * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK * TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and * TMS/TRST/SRST high. */ output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; *gpio_data_register = output_value; nanosleep(&ep93xx_zzzz, NULL); /* * Configure the direction register. 1 = output, 0 = input. */ *gpio_data_direction_register = TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; nanosleep(&ep93xx_zzzz, NULL); return ERROR_OK; } static int ep93xx_quit(void) { return ERROR_OK; } openocd-0.9.0/src/jtag/drivers/minidriver_imp.h0000644000175000017500000000433112315575360016460 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007-2009 Øyvind Harboe * * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MINIDRIVER_IMP_H #define MINIDRIVER_IMP_H #include static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field) { unsigned num_bytes = DIV_ROUND_UP(field->num_bits, 8); field->in_value = cmd_queue_alloc(num_bytes); } void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0); void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); #endif /* MINIDRIVER_IMP_H */ openocd-0.9.0/src/jtag/drivers/parport.c0000644000175000017500000003362112516456302015126 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" /* -ino: 060521-1036 */ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define ioperm(startport, length, enable)\ i386_set_ioperm((startport), (length), (enable)) #endif /* __FreeBSD__ */ #if PARPORT_USE_PPDEV == 1 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define PPRSTATUS PPIGSTATUS #define PPWDATA PPISDATA #else #include #include #endif #include #else /* not PARPORT_USE_PPDEV */ #ifndef _WIN32 #include #endif #endif #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1 #include #endif /* parallel port cable description */ struct cable { const char *name; uint8_t TDO_MASK; /* status port bit containing current TDO value */ uint8_t TRST_MASK; /* data port bit for TRST */ uint8_t TMS_MASK; /* data port bit for TMS */ uint8_t TCK_MASK; /* data port bit for TCK */ uint8_t TDI_MASK; /* data port bit for TDI */ uint8_t SRST_MASK; /* data port bit for SRST */ uint8_t OUTPUT_INVERT; /* data port bits that should be inverted */ uint8_t INPUT_INVERT; /* status port that should be inverted */ uint8_t PORT_INIT; /* initialize data port with this value */ uint8_t PORT_EXIT; /* de-initialize data port with this value */ uint8_t LED_MASK; /* data port bit for LED */ }; static const struct cable cables[] = { /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */ { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 }, { "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 }, { "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 }, { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 }, { "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 }, { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }, { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 }, { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }, { "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 }, { "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 }, /* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows: HARD TCK - Target TCK HARD TMS - Target TMS HARD TDI - Target TDI HARD TDO - Target TDO SOFT TCK - Target TRST SOFT TDI - Target SRST */ { "altium", 0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 }, { "aspo", 0x10, 0x01, 0x04, 0x08, 0x02, 0x10, 0x17, 0x00, 0x17, 0x17, 0x00 }, { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; /* configuration */ static char *parport_cable; static uint16_t parport_port; static bool parport_exit; static uint32_t parport_toggling_time_ns = 1000; static int wait_states; /* interface variables */ static const struct cable *cable; static uint8_t dataport_value; #if PARPORT_USE_PPDEV == 1 static int device_handle; #else static unsigned long dataport; static unsigned long statusport; #endif static int parport_read(void) { int data = 0; #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPRSTATUS, &data); #else data = inb(statusport); #endif if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK) return 1; else return 0; } static inline void parport_write_data(void) { uint8_t output; output = dataport_value ^ cable->OUTPUT_INVERT; #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &output); #else #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(dataport, output); #else outb(output, dataport); #endif #endif } static void parport_write(int tck, int tms, int tdi) { int i = wait_states + 1; if (tck) dataport_value |= cable->TCK_MASK; else dataport_value &= ~cable->TCK_MASK; if (tms) dataport_value |= cable->TMS_MASK; else dataport_value &= ~cable->TMS_MASK; if (tdi) dataport_value |= cable->TDI_MASK; else dataport_value &= ~cable->TDI_MASK; while (i-- > 0) parport_write_data(); } /* (1) assert or (0) deassert reset lines */ static void parport_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst == 0) dataport_value |= cable->TRST_MASK; else if (trst == 1) dataport_value &= ~cable->TRST_MASK; if (srst == 0) dataport_value |= cable->SRST_MASK; else if (srst == 1) dataport_value &= ~cable->SRST_MASK; parport_write_data(); } /* turn LED on parport adapter on (1) or off (0) */ static void parport_led(int on) { if (on) dataport_value |= cable->LED_MASK; else dataport_value &= ~cable->LED_MASK; parport_write_data(); } static int parport_speed(int speed) { wait_states = speed; return ERROR_OK; } static int parport_khz(int khz, int *jtag_speed) { if (khz == 0) { LOG_DEBUG("RCLK not supported"); return ERROR_FAIL; } *jtag_speed = 499999 / (khz * parport_toggling_time_ns); return ERROR_OK; } static int parport_speed_div(int speed, int *khz) { uint32_t denominator = (speed + 1) * parport_toggling_time_ns; *khz = (499999 + denominator) / denominator; return ERROR_OK; } #if PARPORT_USE_GIVEIO == 1 static int parport_get_giveio_access(void) { HANDLE h; OSVERSIONINFO version; version.dwOSVersionInfoSize = sizeof version; if (!GetVersionEx(&version)) { errno = EINVAL; return -1; } if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0; h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { errno = ENODEV; return -1; } CloseHandle(h); return 0; } #endif static struct bitbang_interface parport_bitbang = { .read = &parport_read, .write = &parport_write, .reset = &parport_reset, .blink = &parport_led, }; static int parport_init(void) { const struct cable *cur_cable; #if PARPORT_USE_PPDEV == 1 char buffer[256]; #endif cur_cable = cables; if (parport_cable == NULL) { parport_cable = strdup("wiggler"); LOG_WARNING("No parport cable specified, using default 'wiggler'"); } while (cur_cable->name) { if (strcmp(cur_cable->name, parport_cable) == 0) { cable = cur_cable; break; } cur_cable++; } if (!cable) { LOG_ERROR("No matching cable found for %s", parport_cable); return ERROR_JTAG_INIT_FAILED; } dataport_value = cable->PORT_INIT; #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { LOG_ERROR("device is already opened"); return ERROR_JTAG_INIT_FAILED; } #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) LOG_DEBUG("opening /dev/ppi%d...", parport_port); snprintf(buffer, 256, "/dev/ppi%d", parport_port); device_handle = open(buffer, O_WRONLY); #else /* not __FreeBSD__, __FreeBSD_kernel__ */ LOG_DEBUG("opening /dev/parport%d...", parport_port); snprintf(buffer, 256, "/dev/parport%d", parport_port); device_handle = open(buffer, O_WRONLY); #endif /* __FreeBSD__, __FreeBSD_kernel__ */ if (device_handle < 0) { int err = errno; LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...open"); #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) int i = ioctl(device_handle, PPCLAIM); if (i < 0) { LOG_ERROR("cannot claim device"); return ERROR_JTAG_INIT_FAILED; } i = PARPORT_MODE_COMPAT; i = ioctl(device_handle, PPSETMODE, &i); if (i < 0) { LOG_ERROR(" cannot set compatible mode to device"); return ERROR_JTAG_INIT_FAILED; } i = IEEE1284_MODE_COMPAT; i = ioctl(device_handle, PPNEGOT, &i); if (i < 0) { LOG_ERROR("cannot set compatible 1284 mode to device"); return ERROR_JTAG_INIT_FAILED; } #endif /* not __FreeBSD__, __FreeBSD_kernel__ */ #else /* not PARPORT_USE_PPDEV */ if (parport_port == 0) { parport_port = 0x378; LOG_WARNING("No parport port specified, using default '0x378' (LPT1)"); } dataport = parport_port; statusport = parport_port + 1; LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport); #if PARPORT_USE_GIVEIO == 1 if (parport_get_giveio_access() != 0) { #else /* PARPORT_USE_GIVEIO */ if (ioperm(dataport, 3, 1) != 0) { #endif /* PARPORT_USE_GIVEIO */ LOG_ERROR("missing privileges for direct i/o"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...privileges granted"); /* make sure parallel port is in right mode (clear tristate and interrupt */ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(parport_port + 2, 0x0); #else outb(0x0, parport_port + 2); #endif #endif /* PARPORT_USE_PPDEV */ parport_reset(0, 0); parport_write(0, 0, 0); parport_led(1); bitbang_interface = &parport_bitbang; return ERROR_OK; } static int parport_quit(void) { parport_led(0); if (parport_exit) { dataport_value = cable->PORT_EXIT; parport_write_data(); } if (parport_cable) { free(parport_cable); parport_cable = NULL; } return ERROR_OK; } COMMAND_HANDLER(parport_handle_parport_port_command) { if (CMD_ARGC == 1) { /* only if the port wasn't overwritten by cmdline */ if (parport_port == 0) COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port); else { LOG_ERROR("The parport port was already configured!"); return ERROR_FAIL; } } command_print(CMD_CTX, "parport port = 0x%" PRIx16 "", parport_port); return ERROR_OK; } COMMAND_HANDLER(parport_handle_parport_cable_command) { if (CMD_ARGC == 0) return ERROR_OK; /* only if the cable name wasn't overwritten by cmdline */ if (parport_cable == 0) { /* REVISIT first verify that it's listed in cables[] ... */ parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); strcpy(parport_cable, CMD_ARGV[0]); } /* REVISIT it's probably worth returning the current value ... */ return ERROR_OK; } COMMAND_HANDLER(parport_handle_write_on_exit_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], parport_exit); return ERROR_OK; } COMMAND_HANDLER(parport_handle_parport_toggling_time_command) { if (CMD_ARGC == 1) { uint32_t ns; int retval = parse_u32(CMD_ARGV[0], &ns); if (ERROR_OK != retval) return retval; if (ns == 0) { LOG_ERROR("0 ns is not a valid parport toggling time"); return ERROR_FAIL; } parport_toggling_time_ns = ns; retval = jtag_get_speed(&wait_states); if (retval != ERROR_OK) { /* if jtag_get_speed fails then the clock_mode * has not been configured, this happens if parport_toggling_time is * called before the adapter speed is set */ LOG_INFO("no parport speed set - defaulting to zero wait states"); wait_states = 0; } } command_print(CMD_CTX, "parport toggling time = %" PRIu32 " ns", parport_toggling_time_ns); return ERROR_OK; } static const struct command_registration parport_command_handlers[] = { { .name = "parport_port", .handler = parport_handle_parport_port_command, .mode = COMMAND_CONFIG, .help = "Display the address of the I/O port (e.g. 0x378) " "or the number of the '/dev/parport' device used. " "If a parameter is provided, first change that port.", .usage = "[port_number]", }, { .name = "parport_cable", .handler = parport_handle_parport_cable_command, .mode = COMMAND_CONFIG, .help = "Set the layout of the parallel port cable " "used to connect to the target.", /* REVISIT there's no way to list layouts we know ... */ .usage = "[layout]", }, { .name = "parport_write_on_exit", .handler = parport_handle_write_on_exit_command, .mode = COMMAND_CONFIG, .help = "Configure the parallel driver to write " "a known value to the parallel interface on exit.", .usage = "('on'|'off')", }, { .name = "parport_toggling_time", .handler = parport_handle_parport_toggling_time_command, .mode = COMMAND_CONFIG, .help = "Displays or assigns how many nanoseconds it " "takes for the hardware to toggle TCK.", .usage = "[nanoseconds]", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface parport_interface = { .name = "parport", .supported = DEBUG_CAP_TMS_SEQ, .commands = parport_command_handlers, .init = parport_init, .quit = parport_quit, .khz = parport_khz, .speed_div = parport_speed_div, .speed = parport_speed, .execute_queue = bitbang_execute_queue, }; openocd-0.9.0/src/jtag/drivers/OpenULINK/0000755000175000017500000000000012315575360015055 500000000000000openocd-0.9.0/src/jtag/drivers/OpenULINK/src/0000755000175000017500000000000012315575360015644 500000000000000openocd-0.9.0/src/jtag/drivers/OpenULINK/src/delay.c0000644000175000017500000000342212315575360017027 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "delay.h" void delay_5us(void) { NOP; } void delay_1ms(void) { uint16_t i; for (i = 0; i < 598; i++) ; } void delay_us(uint16_t delay) { uint16_t i; uint16_t maxcount = (delay / 5); for (i = 0; i < maxcount; i++) delay_5us(); } void delay_ms(uint16_t delay) { uint16_t i; for (i = 0; i < delay; i++) delay_1ms(); } openocd-0.9.0/src/jtag/drivers/OpenULINK/src/usb.c0000644000175000017500000003377312315575360016536 00000000000000/*************************************************************************** * Copyright (C) 2011-2013 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * Defines USB descriptors, interrupt routines and helper functions. * To minimize code size, we make the following assumptions: * - The OpenULINK has exactly one configuration * - and exactly one alternate setting * * Therefore, we do not have to support the Set Configuration USB request. */ #include "usb.h" #include "delay.h" #include "io.h" /* Also update external declarations in "include/usb.h" if making changes to * these variables! */ volatile bool EP2_out; volatile bool EP2_in; volatile __xdata __at 0x7FE8 struct setup_data setup_data; /* Define number of endpoints (except Control Endpoint 0) in a central place. * Be sure to include the neccessary endpoint descriptors! */ #define NUM_ENDPOINTS 2 __code struct usb_device_descriptor device_descriptor = { .bLength = sizeof(struct usb_device_descriptor), .bDescriptorType = DESCRIPTOR_TYPE_DEVICE, .bcdUSB = 0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */ .bDeviceClass = 0xFF, /* 0xFF = vendor-specific */ .bDeviceSubClass = 0xFF, .bDeviceProtocol = 0xFF, .bMaxPacketSize0 = 64, .idVendor = 0xC251, .idProduct = 0x2710, .bcdDevice = 0x0100, .iManufacturer = 1, .iProduct = 2, .iSerialNumber = 3, .bNumConfigurations = 1 }; /* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */ __code struct usb_config_descriptor config_descriptor = { .bLength = sizeof(struct usb_config_descriptor), .bDescriptorType = DESCRIPTOR_TYPE_CONFIGURATION, .wTotalLength = sizeof(struct usb_config_descriptor) + sizeof(struct usb_interface_descriptor) + (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)), .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = 4, /* String describing this configuration */ .bmAttributes = 0x80, /* Only MSB set according to USB spec */ .MaxPower = 50 /* 100 mA */ }; __code struct usb_interface_descriptor interface_descriptor00 = { .bLength = sizeof(struct usb_interface_descriptor), .bDescriptorType = DESCRIPTOR_TYPE_INTERFACE, .bInterfaceNumber = 0, .bAlternateSetting = 0, .bNumEndpoints = NUM_ENDPOINTS, .bInterfaceClass = 0xFF, .bInterfaceSubclass = 0xFF, .bInterfaceProtocol = 0xFF, .iInterface = 0 }; __code struct usb_endpoint_descriptor Bulk_EP2_IN_Endpoint_Descriptor = { .bLength = sizeof(struct usb_endpoint_descriptor), .bDescriptorType = 0x05, .bEndpointAddress = (2 | USB_DIR_IN), .bmAttributes = 0x02, .wMaxPacketSize = 64, .bInterval = 0 }; __code struct usb_endpoint_descriptor Bulk_EP2_OUT_Endpoint_Descriptor = { .bLength = sizeof(struct usb_endpoint_descriptor), .bDescriptorType = 0x05, .bEndpointAddress = (2 | USB_DIR_OUT), .bmAttributes = 0x02, .wMaxPacketSize = 64, .bInterval = 0 }; __code struct usb_language_descriptor language_descriptor = { .bLength = 4, .bDescriptorType = DESCRIPTOR_TYPE_STRING, .wLANGID = {0x0409 /* US English */} }; __code struct usb_string_descriptor strManufacturer = STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K'); __code struct usb_string_descriptor strProduct = STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K'); __code struct usb_string_descriptor strSerialNumber = STR_DESCR(6, '0', '0', '0', '0', '0', '1'); __code struct usb_string_descriptor strConfigDescr = STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r'); /* Table containing pointers to string descriptors */ __code struct usb_string_descriptor *__code en_string_descriptors[4] = { &strManufacturer, &strProduct, &strSerialNumber, &strConfigDescr }; void sudav_isr(void) __interrupt SUDAV_ISR { CLEAR_IRQ(); usb_handle_setup_data(); USBIRQ = SUDAVIR; EP0CS |= HSNAK; } void sof_isr(void) __interrupt SOF_ISR { } void sutok_isr(void) __interrupt SUTOK_ISR { } void suspend_isr(void) __interrupt SUSPEND_ISR { } void usbreset_isr(void) __interrupt USBRESET_ISR { } void ibn_isr(void) __interrupt IBN_ISR { } void ep0in_isr(void) __interrupt EP0IN_ISR { } void ep0out_isr(void) __interrupt EP0OUT_ISR { } void ep1in_isr(void) __interrupt EP1IN_ISR { } void ep1out_isr(void) __interrupt EP1OUT_ISR { } /** * EP2 IN: called after the transfer from uC->Host has finished: we sent data */ void ep2in_isr(void) __interrupt EP2IN_ISR { EP2_in = 1; CLEAR_IRQ(); IN07IRQ = IN2IR;/* Clear OUT2 IRQ */ } /** * EP2 OUT: called after the transfer from Host->uC has finished: we got data */ void ep2out_isr(void) __interrupt EP2OUT_ISR { EP2_out = 1; CLEAR_IRQ(); OUT07IRQ = OUT2IR; /* Clear OUT2 IRQ */ } void ep3in_isr(void) __interrupt EP3IN_ISR { } void ep3out_isr(void) __interrupt EP3OUT_ISR { } void ep4in_isr(void) __interrupt EP4IN_ISR { } void ep4out_isr(void) __interrupt EP4OUT_ISR { } void ep5in_isr(void) __interrupt EP5IN_ISR { } void ep5out_isr(void) __interrupt EP5OUT_ISR { } void ep6in_isr(void) __interrupt EP6IN_ISR { } void ep6out_isr(void) __interrupt EP6OUT_ISR { } void ep7in_isr(void) __interrupt EP7IN_ISR { } void ep7out_isr(void) __interrupt EP7OUT_ISR { } /** * Return the control/status register for an endpoint * * @param ep endpoint address * @return on success: pointer to Control & Status register for endpoint * specified in \a ep * @return on failure: NULL */ __xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep) { /* Mask direction bit */ uint8_t ep_num = ep & 0x7F; switch (ep_num) { case 0: return &EP0CS; break; case 1: return ep & 0x80 ? &IN1CS : &OUT1CS; break; case 2: return ep & 0x80 ? &IN2CS : &OUT2CS; break; case 3: return ep & 0x80 ? &IN3CS : &OUT3CS; break; case 4: return ep & 0x80 ? &IN4CS : &OUT4CS; break; case 5: return ep & 0x80 ? &IN5CS : &OUT5CS; break; case 6: return ep & 0x80 ? &IN6CS : &OUT6CS; break; case 7: return ep & 0x80 ? &IN7CS : &OUT7CS; break; } return NULL; } void usb_reset_data_toggle(uint8_t ep) { /* TOGCTL register: +----+-----+-----+------+-----+-------+-------+-------+ | Q | S | R | IO | 0 | EP2 | EP1 | EP0 | +----+-----+-----+------+-----+-------+-------+-------+ To reset data toggle bits, we have to write the endpoint direction (IN/OUT) to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a separate write cycle, the R bit needs to be set. */ uint8_t togctl_value = (ep & 0x80 >> 3) | (ep & 0x7); /* First step: Write EP number and direction bit */ TOGCTL = togctl_value; /* Second step: Set R bit */ togctl_value |= TOG_R; TOGCTL = togctl_value; } /** * Handle GET_STATUS request. * * @return on success: true * @return on failure: false */ bool usb_handle_get_status(void) { uint8_t *ep_cs; switch (setup_data.bmRequestType) { case GS_DEVICE: /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup. * Byte 1: reserved, reset to zero */ IN0BUF[0] = 0; IN0BUF[1] = 0; /* Send response */ IN0BC = 2; break; case GS_INTERFACE: /* Always return two zero bytes according to USB 1.1 spec, p. 191 */ IN0BUF[0] = 0; IN0BUF[1] = 0; /* Send response */ IN0BC = 2; break; case GS_ENDPOINT: /* Get stall bit for endpoint specified in low byte of wIndex */ ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff); if (*ep_cs & EPSTALL) IN0BUF[0] = 0x01; else IN0BUF[0] = 0x00; /* Second byte sent has to be always zero */ IN0BUF[1] = 0; /* Send response */ IN0BC = 2; break; default: return false; break; } return true; } /** * Handle CLEAR_FEATURE request. * * @return on success: true * @return on failure: false */ bool usb_handle_clear_feature(void) { __xdata uint8_t *ep_cs; switch (setup_data.bmRequestType) { case CF_DEVICE: /* Clear remote wakeup not supported: stall EP0 */ STALL_EP0(); break; case CF_ENDPOINT: if (setup_data.wValue == 0) { /* Unstall the endpoint specified in wIndex */ ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex); if (!ep_cs) return false; *ep_cs &= ~EPSTALL; } else { /* Unsupported feature, stall EP0 */ STALL_EP0(); } break; default: /* Vendor commands... */ } return true; } /** * Handle SET_FEATURE request. * * @return on success: true * @return on failure: false */ bool usb_handle_set_feature(void) { __xdata uint8_t *ep_cs; switch (setup_data.bmRequestType) { case SF_DEVICE: if (setup_data.wValue == 2) return true; break; case SF_ENDPOINT: if (setup_data.wValue == 0) { /* Stall the endpoint specified in wIndex */ ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex); if (!ep_cs) return false; *ep_cs |= EPSTALL; } else { /* Unsupported endpoint feature */ return false; } break; default: /* Vendor commands... */ break; } return true; } /** * Handle GET_DESCRIPTOR request. * * @return on success: true * @return on failure: false */ bool usb_handle_get_descriptor(void) { __xdata uint8_t descriptor_type; __xdata uint8_t descriptor_index; descriptor_type = (setup_data.wValue & 0xff00) >> 8; descriptor_index = setup_data.wValue & 0x00ff; switch (descriptor_type) { case DESCRIPTOR_TYPE_DEVICE: SUDPTRH = HI8(&device_descriptor); SUDPTRL = LO8(&device_descriptor); break; case DESCRIPTOR_TYPE_CONFIGURATION: SUDPTRH = HI8(&config_descriptor); SUDPTRL = LO8(&config_descriptor); break; case DESCRIPTOR_TYPE_STRING: if (setup_data.wIndex == 0) { /* Supply language descriptor */ SUDPTRH = HI8(&language_descriptor); SUDPTRL = LO8(&language_descriptor); } else if (setup_data.wIndex == 0x0409 /* US English */) { /* Supply string descriptor */ SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]); SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]); } else return false; break; default: /* Unsupported descriptor type */ return false; break; } return true; } /** * Handle SET_INTERFACE request. */ void usb_handle_set_interface(void) { /* Reset Data Toggle */ usb_reset_data_toggle(USB_DIR_IN | 2); usb_reset_data_toggle(USB_DIR_OUT | 2); /* Unstall & clear busy flag of all valid IN endpoints */ IN2CS = 0 | EPBSY; /* Unstall all valid OUT endpoints, reset bytecounts */ OUT2CS = 0; OUT2BC = 0; } /** * Handle the arrival of a USB Control Setup Packet. */ void usb_handle_setup_data(void) { switch (setup_data.bRequest) { case GET_STATUS: if (!usb_handle_get_status()) STALL_EP0(); break; case CLEAR_FEATURE: if (!usb_handle_clear_feature()) STALL_EP0(); break; case 2: case 4: /* Reserved values */ STALL_EP0(); break; case SET_FEATURE: if (!usb_handle_set_feature()) STALL_EP0(); break; case SET_ADDRESS: /* Handled by USB core */ break; case SET_DESCRIPTOR: /* Set Descriptor not supported. */ STALL_EP0(); break; case GET_DESCRIPTOR: if (!usb_handle_get_descriptor()) STALL_EP0(); break; case GET_CONFIGURATION: /* OpenULINK has only one configuration, return its index */ IN0BUF[0] = config_descriptor.bConfigurationValue; IN0BC = 1; break; case SET_CONFIGURATION: /* OpenULINK has only one configuration -> nothing to do */ break; case GET_INTERFACE: /* OpenULINK only has one interface, return its number */ IN0BUF[0] = interface_descriptor00.bInterfaceNumber; IN0BC = 1; break; case SET_INTERFACE: usb_handle_set_interface(); break; case SYNCH_FRAME: /* Isochronous endpoints not used -> nothing to do */ break; default: /* Any other requests: do nothing */ break; } } /** * USB initialization. Configures USB interrupts, endpoints and performs * ReNumeration. */ void usb_init(void) { /* Mark endpoint 2 IN & OUT as valid */ IN07VAL = IN2VAL; OUT07VAL = OUT2VAL; /* Make sure no isochronous endpoints are marked valid */ INISOVAL = 0; OUTISOVAL = 0; /* Disable isochronous endpoints. This makes the isochronous data buffers * available as 8051 XDATA memory at address 0x2000 - 0x27FF */ ISOCTL = ISODISAB; /* Enable USB Autovectoring */ USBBAV |= AVEN; /* Enable SUDAV interrupt */ USBIEN |= SUDAVIE; /* Enable EP2 OUT & IN interrupts */ OUT07IEN = OUT2IEN; IN07IEN = IN2IEN; /* Enable USB interrupt (EIE register) */ EUSB = 1; /* Perform ReNumeration */ USBCS = DISCON | RENUM; delay_ms(200); USBCS = DISCOE | RENUM; } openocd-0.9.0/src/jtag/drivers/OpenULINK/src/protocol.c0000644000175000017500000001667312315575360017606 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "protocol.h" #include "jtag.h" #include "delay.h" #include "usb.h" #include "io.h" #include "msgtypes.h" #include "reg_ezusb.h" /** * @file * Implementation of the OpenULINK communication protocol. * * The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints * are configured to use the maximum packet size for full-speed transfers, * 64 bytes. Commands always start with a command ID (see msgtypes.h for * command ID definitions) and contain zero or more payload data bytes in both * transfer directions (IN and OUT). The payload * * Almost all commands contain a fixed number of payload data bytes. The number * of payload data bytes for the IN and OUT direction does not need to be the * same. * * Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the * OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets, * the host MUST ensure that the commands sent in the OUT packet require a * maximum of 64 bytes of IN data. */ /** Index in EP2 Bulk-OUT data buffer that contains the current command ID */ volatile uint8_t cmd_id_index; /** Number of data bytes already in EP2 Bulk-IN buffer */ volatile uint8_t payload_index_in; /** * Execute a SET_LEDS command. */ void execute_set_led_command(void) { uint8_t led_state = OUT2BUF[cmd_id_index + 1]; if (led_state & RUN_LED_ON) SET_RUN_LED(); if (led_state & COM_LED_ON) SET_COM_LED(); if (led_state & RUN_LED_OFF) CLEAR_RUN_LED(); if (led_state & COM_LED_OFF) CLEAR_COM_LED(); } /** * Executes one command and updates global command indexes. * * @return true if this command was the last command. * @return false if there are more commands within the current contents of the * Bulk EP2-OUT data buffer. */ bool execute_command(void) { uint8_t usb_out_bytecount, usb_in_bytecount; uint16_t signal_state; uint16_t count; /* Most commands do not transfer IN data. To save code space, we write 0 to * usb_in_bytecount here, then modify it in the switch statement below where * neccessary */ usb_in_bytecount = 0; switch (OUT2BUF[cmd_id_index] /* Command ID */) { case CMD_SCAN_IN: usb_out_bytecount = 5; usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; jtag_scan_in(cmd_id_index + 1, payload_index_in); break; case CMD_SCAN_OUT: usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5; jtag_scan_out(cmd_id_index + 1); break; case CMD_SCAN_IO: usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; usb_out_bytecount = usb_in_bytecount + 5; jtag_scan_io(cmd_id_index + 1, payload_index_in); break; case CMD_CLOCK_TMS: usb_out_bytecount = 2; jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]); break; case CMD_CLOCK_TCK: usb_out_bytecount = 2; count = (uint16_t)OUT2BUF[cmd_id_index + 1]; count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8; jtag_clock_tck(count); break; case CMD_SLOW_SCAN_IN: usb_out_bytecount = 5; usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; jtag_slow_scan_in(cmd_id_index + 1, payload_index_in); break; case CMD_SLOW_SCAN_OUT: usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5; jtag_slow_scan_out(cmd_id_index + 1); break; case CMD_SLOW_SCAN_IO: usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; usb_out_bytecount = usb_in_bytecount + 5; jtag_slow_scan_io(cmd_id_index + 1, payload_index_in); break; case CMD_SLOW_CLOCK_TMS: usb_out_bytecount = 2; jtag_slow_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]); break; case CMD_SLOW_CLOCK_TCK: usb_out_bytecount = 2; count = (uint16_t)OUT2BUF[cmd_id_index + 1]; count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8; jtag_slow_clock_tck(count); break; case CMD_SLEEP_US: usb_out_bytecount = 2; count = (uint16_t)OUT2BUF[cmd_id_index + 1]; count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8; delay_us(count); break; case CMD_SLEEP_MS: usb_out_bytecount = 2; count = (uint16_t)OUT2BUF[cmd_id_index + 1]; count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8; delay_ms(count); break; case CMD_GET_SIGNALS: usb_out_bytecount = 0; usb_in_bytecount = 2; signal_state = jtag_get_signals(); IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF; IN2BUF[payload_index_in + 1] = signal_state & 0x00FF; break; case CMD_SET_SIGNALS: usb_out_bytecount = 2; jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]); break; case CMD_CONFIGURE_TCK_FREQ: usb_out_bytecount = 5; jtag_configure_tck_delay( OUT2BUF[cmd_id_index + 1], /* scan_in */ OUT2BUF[cmd_id_index + 2], /* scan_out */ OUT2BUF[cmd_id_index + 3], /* scan_io */ OUT2BUF[cmd_id_index + 4], /* clock_tck */ OUT2BUF[cmd_id_index + 5]); /* clock_tms */ break; case CMD_SET_LEDS: usb_out_bytecount = 1; execute_set_led_command(); break; case CMD_TEST: usb_out_bytecount = 1; /* Do nothing... This command is only used to test if the device is ready * to accept new commands */ break; default: /* Should never be reached */ usb_out_bytecount = 0; break; } /* Update EP2 Bulk-IN data byte count */ payload_index_in += usb_in_bytecount; /* Determine if this was the last command */ if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC) return true; else { /* Not the last command, update cmd_id_index */ cmd_id_index += (usb_out_bytecount + 1); return false; } } /** * Forever wait for commands and execute them as they arrive. */ void command_loop(void) { bool last_command; while (1) { cmd_id_index = 0; payload_index_in = 0; /* Wait until host sends EP2 Bulk-OUT packet */ while (!EP2_out) ; EP2_out = 0; /* Turn on COM LED to indicate command execution */ SET_COM_LED(); /* Execute the commands */ last_command = false; while (last_command == false) last_command = execute_command(); CLEAR_COM_LED(); /* Send back EP2 Bulk-IN packet if required */ if (payload_index_in > 0) { IN2BC = payload_index_in; while (!EP2_in) ; EP2_in = 0; } /* Re-arm EP2-OUT after command execution */ OUT2BC = 0; } } openocd-0.9.0/src/jtag/drivers/OpenULINK/src/jtag.c0000644000175000017500000004704712315575360016671 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "jtag.h" #include "io.h" #include "msgtypes.h" #include "common.h" #include /** Delay value for SCAN_IN operations with less than maximum TCK frequency */ uint8_t delay_scan_in; /** Delay value for SCAN_OUT operations with less than maximum TCK frequency */ uint8_t delay_scan_out; /** Delay value for SCAN_IO operations with less than maximum TCK frequency */ uint8_t delay_scan_io; /** Delay value for CLOCK_TCK operations with less than maximum frequency */ uint8_t delay_tck; /** Delay value for CLOCK_TMS operations with less than maximum frequency */ uint8_t delay_tms; /** * Perform JTAG SCAN-IN operation at maximum TCK frequency. * * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and * stored in the EP2 IN buffer. * * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_in(uint8_t out_offset, uint8_t in_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdo_data, i, j; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdo_data = 0; for (j = 0; j < 8; j++) { OUTB = outb_buffer; /* TCK changes here */ tdo_data = tdo_data >> 1; OUTB = (outb_buffer | PIN_TCK); if (GET_TDO()) tdo_data |= 0x80; } /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; } tdo_data = 0; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TCK changes here */ tdo_data = tdo_data >> 1; OUTB = (outb_buffer | PIN_TCK); if (GET_TDO()) tdo_data |= 0x80; } tdo_data = tdo_data >> (8 - bits_last_byte); /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; /* Move to correct end state */ if (tms_count_end > 0) jtag_clock_tms(tms_count_end, tms_sequence_end); } /** * Perform JTAG SCAN-IN operation at variable TCK frequency. * * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and * stored in the EP2 IN buffer. * * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdo_data, i, j, k; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_slow_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdo_data = 0; for (j = 0; j < 8; j++) { OUTB = outb_buffer; /* TCK changes here */ for (k = 0; k < delay_scan_in; k++) ; tdo_data = tdo_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_in; k++) ; if (GET_TDO()) tdo_data |= 0x80; } /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; } tdo_data = 0; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TCK changes here */ for (k = 0; k < delay_scan_in; k++) ; tdo_data = tdo_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_in; k++) ; if (GET_TDO()) tdo_data |= 0x80; } tdo_data = tdo_data >> (8 - bits_last_byte); /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; /* Move to correct end state */ if (tms_count_end > 0) jtag_slow_clock_tms(tms_count_end, tms_sequence_end); } /** * Perform JTAG SCAN-OUT operation at maximum TCK frequency. * * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO * data is not sampled. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_out(uint8_t out_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdi_data, i, j; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdi_data = OUT2BUF[i + out_offset + 5]; for (j = 0; j < 8; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; OUTB = outb_buffer; /* TDI and TCK change here */ tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); } } tdi_data = OUT2BUF[i + out_offset + 5]; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TDI and TCK change here */ tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); } /* Move to correct end state */ if (tms_count_end > 0) jtag_clock_tms(tms_count_end, tms_sequence_end); } /** * Perform JTAG SCAN-OUT operation at maximum TCK frequency. * * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO * data is not sampled. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_slow_scan_out(uint8_t out_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdi_data, i, j, k; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_slow_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdi_data = OUT2BUF[i + out_offset + 5]; for (j = 0; j < 8; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; OUTB = outb_buffer; /* TDI and TCK change here */ for (k = 0; k < delay_scan_out; k++) ; tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_out; k++) ; } } tdi_data = OUT2BUF[i + out_offset + 5]; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TDI and TCK change here */ for (k = 0; k < delay_scan_out; k++) ; tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_out; k++) ; } /* Move to correct end state */ if (tms_count_end > 0) jtag_slow_clock_tms(tms_count_end, tms_sequence_end); } /** * Perform bidirectional JTAG SCAN operation at maximum TCK frequency. * * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO * data is sampled and stored in the EP2 IN buffer. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_io(uint8_t out_offset, uint8_t in_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdi_data, tdo_data, i, j; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdi_data = OUT2BUF[i + out_offset + 5]; tdo_data = 0; for (j = 0; j < 8; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; OUTB = outb_buffer; /* TDI and TCK change here */ tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); tdo_data = tdo_data >> 1; if (GET_TDO()) tdo_data |= 0x80; } /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; } tdi_data = OUT2BUF[i + out_offset + 5]; tdo_data = 0; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TDI and TCK change here */ tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); tdo_data = tdo_data >> 1; if (GET_TDO()) tdo_data |= 0x80; } tdo_data = tdo_data >> (8 - bits_last_byte); /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; /* Move to correct end state */ if (tms_count_end > 0) jtag_clock_tms(tms_count_end, tms_sequence_end); } /** * Perform bidirectional JTAG SCAN operation at maximum TCK frequency. * * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO * data is sampled and stored in the EP2 IN buffer. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz. * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset) { uint8_t scan_size_bytes, bits_last_byte; uint8_t tms_count_start, tms_count_end; uint8_t tms_sequence_start, tms_sequence_end; uint8_t tdi_data, tdo_data, i, j, k; uint8_t outb_buffer; /* Get parameters from OUT2BUF */ scan_size_bytes = OUT2BUF[out_offset]; bits_last_byte = OUT2BUF[out_offset + 1]; tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; tms_sequence_start = OUT2BUF[out_offset + 3]; tms_sequence_end = OUT2BUF[out_offset + 4]; if (tms_count_start > 0) jtag_slow_clock_tms(tms_count_start, tms_sequence_start); outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); /* Shift all bytes except the last byte */ for (i = 0; i < scan_size_bytes - 1; i++) { tdi_data = OUT2BUF[i + out_offset + 5]; tdo_data = 0; for (j = 0; j < 8; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; OUTB = outb_buffer; /* TDI and TCK change here */ for (k = 0; k < delay_scan_io; k++) ; tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_io; k++) ; tdo_data = tdo_data >> 1; if (GET_TDO()) tdo_data |= 0x80; } /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; } tdi_data = OUT2BUF[i + out_offset + 5]; tdo_data = 0; /* Shift the last byte */ for (j = 0; j < bits_last_byte; j++) { if (tdi_data & 0x01) outb_buffer |= PIN_TDI; else outb_buffer &= ~PIN_TDI; /* Assert TMS signal if requested and this is the last bit */ if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { outb_buffer |= PIN_TMS; tms_count_end--; tms_sequence_end = tms_sequence_end >> 1; } OUTB = outb_buffer; /* TDI and TCK change here */ for (k = 0; k < delay_scan_io; k++) ; tdi_data = tdi_data >> 1; OUTB = (outb_buffer | PIN_TCK); for (k = 0; k < delay_scan_io; k++) ; tdo_data = tdo_data >> 1; if (GET_TDO()) tdo_data |= 0x80; } tdo_data = tdo_data >> (8 - bits_last_byte); /* Copy TDO data to IN2BUF */ IN2BUF[i + in_offset] = tdo_data; /* Move to correct end state */ if (tms_count_end > 0) jtag_slow_clock_tms(tms_count_end, tms_sequence_end); } /** * Generate TCK clock cycles. * * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz. * * @param count number of TCK clock cyclces to generate. */ void jtag_clock_tck(uint16_t count) { uint16_t i; uint8_t outb_buffer = OUTB & ~(PIN_TCK); for (i = 0; i < count; i++) { OUTB = outb_buffer; OUTB = outb_buffer | PIN_TCK; } } /** * Generate TCK clock cycles at variable frequency. * * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz. * * @param count number of TCK clock cyclces to generate. */ void jtag_slow_clock_tck(uint16_t count) { uint16_t i; uint8_t j; uint8_t outb_buffer = OUTB & ~(PIN_TCK); for (i = 0; i < count; i++) { OUTB = outb_buffer; for (j = 0; j < delay_tck; j++) ; OUTB = outb_buffer | PIN_TCK; for (j = 0; j < delay_tck; j++) ; } } /** * Perform TAP FSM state transitions at maximum TCK frequency. * * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz. * * @param count the number of state transitions to perform. * @param sequence the TMS pin levels for each state transition, starting with * the least-significant bit. */ void jtag_clock_tms(uint8_t count, uint8_t sequence) { uint8_t outb_buffer = OUTB & ~(PIN_TCK); uint8_t i; for (i = 0; i < count; i++) { /* Set TMS pin according to sequence parameter */ if (sequence & 0x1) outb_buffer |= PIN_TMS; else outb_buffer &= ~PIN_TMS; OUTB = outb_buffer; sequence = sequence >> 1; OUTB = outb_buffer | PIN_TCK; } } /** * Perform TAP-FSM state transitions at less than maximum TCK frequency. * * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz. * * @param count the number of state transitions to perform. * @param sequence the TMS pin levels for each state transition, starting with * the least-significant bit. */ void jtag_slow_clock_tms(uint8_t count, uint8_t sequence) { uint8_t outb_buffer = OUTB & ~(PIN_TCK); uint8_t i, j; for (i = 0; i < count; i++) { /* Set TMS pin according to sequence parameter */ if (sequence & 0x1) outb_buffer |= PIN_TMS; else outb_buffer &= ~PIN_TMS; OUTB = outb_buffer; for (j = 0; j < delay_tms; j++) ; sequence = sequence >> 1; OUTB = outb_buffer | PIN_TCK; for (j = 0; j < delay_tms; j++) ; } } /** * Get current JTAG signal states. * * @return a 16-bit integer where the most-significant byte contains the state * of the JTAG input signals and the least-significant byte contains the state * of the JTAG output signals. */ uint16_t jtag_get_signals(void) { uint8_t input_signal_state, output_signal_state; input_signal_state = 0; output_signal_state = 0; /* Get states of input pins */ if (GET_TDO()) input_signal_state |= SIGNAL_TDO; if (GET_BRKOUT()) input_signal_state |= SIGNAL_BRKOUT; if (GET_TRAP()) input_signal_state |= SIGNAL_TRAP; if (GET_RTCK()) { /* Using RTCK this way would be extremely slow, * implemented only for the sake of completeness */ input_signal_state |= SIGNAL_RTCK; } /* Get states of output pins */ output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT; return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state); } /** * Set state of JTAG output signals. * * @param low signals which should be de-asserted. * @param high signals which should be asserted. */ void jtag_set_signals(uint8_t low, uint8_t high) { OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT); OUTB |= (high & MASK_PORTB_DIRECTION_OUT); } /** * Configure TCK delay parameters. * * @param scan_in number of delay cycles in scan_in operations. * @param scan_out number of delay cycles in scan_out operations. * @param scan_io number of delay cycles in scan_io operations. * @param tck number of delay cycles in clock_tck operations. * @param tms number of delay cycles in clock_tms operations. */ void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out, uint8_t scan_io, uint8_t tck, uint8_t tms) { delay_scan_in = scan_in; delay_scan_out = scan_out; delay_scan_io = scan_io; delay_tck = tck; delay_tms = tms; } openocd-0.9.0/src/jtag/drivers/OpenULINK/src/main.c0000644000175000017500000000676612315575360016673 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "main.h" #include "io.h" #include "usb.h" #include "protocol.h" extern void sudav_isr(void) __interrupt SUDAV_ISR; extern void sof_isr(void) __interrupt; extern void sutok_isr(void) __interrupt; extern void suspend_isr(void) __interrupt; extern void usbreset_isr(void) __interrupt; extern void ibn_isr(void) __interrupt; extern void ep0in_isr(void) __interrupt; extern void ep0out_isr(void) __interrupt; extern void ep1in_isr(void) __interrupt; extern void ep1out_isr(void) __interrupt; extern void ep2in_isr(void) __interrupt; extern void ep2out_isr(void) __interrupt; extern void ep3in_isr(void) __interrupt; extern void ep3out_isr(void) __interrupt; extern void ep4in_isr(void) __interrupt; extern void ep4out_isr(void) __interrupt; extern void ep5in_isr(void) __interrupt; extern void ep5out_isr(void) __interrupt; extern void ep6in_isr(void) __interrupt; extern void ep6out_isr(void) __interrupt; extern void ep7in_isr(void) __interrupt; extern void ep7out_isr(void) __interrupt; void io_init(void) { /* PORTxCFG register bits select alternate functions (1 == alternate function, * 0 == standard I/O) * OEx register bits turn on/off output buffer (1 == output, 0 == input) * OUTx register bits determine pin state of output * PINx register bits reflect pin state (high == 1, low == 0) */ /* PORT A */ PORTACFG = PIN_OE; OEA = PIN_U_OE | PIN_OE | PIN_RUN_LED | PIN_COM_LED; OUTA = PIN_RUN_LED | PIN_COM_LED; /* PORT B */ PORTBCFG = 0x00; OEB = PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE; /* TRST and RESET signals are low-active but inverted by hardware, so we clear * these signals here! */ OUTB = 0x00; /* PORT C */ PORTCCFG = PIN_WR; OEC = PIN_TXD0 | PIN_WR; OUTC = 0x00; } int main(void) { io_init(); usb_init(); /* Enable Interrupts */ EA = 1; /* Begin executing command(s). This function never returns. */ command_loop(); /* Never reached, but SDCC complains about missing return statement */ return 0; } openocd-0.9.0/src/jtag/drivers/OpenULINK/src/USBJmpTb.a510000644000175000017500000000664712315575360017477 00000000000000;--------------------------------------------------------------------------; ; Copyright (C) 2011-2013 by Martin Schmoelzer ; ; ; ; ; ; This program 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 2 of the License, or ; ; (at your option) any later version. ; ; ; ; This program 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, write to the ; ; Free Software Foundation, Inc., ; ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ; ;--------------------------------------------------------------------------; .module JUMPTABLE .globl USB_AutoVector .globl USB_Jump_Table ;--------------------------------------------------------------------------; ; Interrupt Vectors ; ;--------------------------------------------------------------------------; .area USB_JV (ABS,OVR) ; Absolute, Overlay .org 0x43 ; USB interrupt (INT2) jumps here USB_AutoVector = #. + 2 ljmp USB_Jump_Table ;--------------------------------------------------------------------------; ; USB Jump Table ; ;--------------------------------------------------------------------------; .area USB_JT (ABS) ; Absolute placement .org 0x1B00 ; Place jump table at 0x1B00 USB_Jump_Table: ; autovector jump table ljmp _sudav_isr ; Setup Data Available .db 0 ljmp _sof_isr ; Start of Frame .db 0 ljmp _sutok_isr ; Setup Data Loading .db 0 ljmp _suspend_isr ; Global Suspend .db 0 ljmp _usbreset_isr ; USB Reset .db 0 ljmp _ibn_isr ; IN Bulk NAK interrupt .db 0 ljmp _ep0in_isr ; Endpoint 0 IN .db 0 ljmp _ep0out_isr ; Endpoint 0 OUT .db 0 ljmp _ep1in_isr ; Endpoint 1 IN .db 0 ljmp _ep1out_isr ; Endpoint 1 OUT .db 0 ljmp _ep2in_isr ; Endpoint 2 IN .db 0 ljmp _ep2out_isr ; Endpoint 2 OUT .db 0 ljmp _ep3in_isr ; Endpoint 3 IN .db 0 ljmp _ep3out_isr ; Endpoint 3 OUT .db 0 ljmp _ep4in_isr ; Endpoint 4 IN .db 0 ljmp _ep4out_isr ; Endpoint 4 OUT .db 0 ljmp _ep5in_isr ; Endpoint 5 IN .db 0 ljmp _ep5out_isr ; Endpoint 5 OUT .db 0 ljmp _ep6in_isr ; Endpoint 6 IN .db 0 ljmp _ep6out_isr ; Endpoint 6 OUT .db 0 ljmp _ep7in_isr ; Endpoint 7 IN .db 0 ljmp _ep7out_isr ; Endpoint 7 OUT .db 0 openocd-0.9.0/src/jtag/drivers/OpenULINK/ulink_firmware.hex0000644000175000017500000003440612315575360020530 00000000000000:040000000200713257 :01000B0032C2 :0100130032BA :01001B0032B2 :0100230032AA :01002B0032A2 :01003300329A :01003B003292 :01004300328A :01004B003282 :01005300327A :01005B003272 :01006300326A :03006B000201107F :0300CA0002006EC3 :03006E000201018B :1000CD00907F937404F0907F9C7495F0907F96745C :1000DD0090F0907F94E4F0907F9D747FF0907F97E7 :1000ED00E4F0907F957440F0907F9E7442F0907F85 :1000FD0098E4F0221200CD1204ADD2AF1208E090B8 :10010D00000022C021C0E0C0F0C082C083C007C083 :10011D0006C005C004C003C002C001C000C0D07538 :10012D00D000AF9174EF5FF59112040C907FAB741A :10013D0001F0907FB4E04402F0D0D0D000D001D0D7 :10014D0002D003D004D005D006D007D083D082D002 :10015D00F0D0E0D02132323232323232323232C04D :10016D00E0C082C083C007C0D075D000D201AF916E :10017D0074EF5FF591907FA97404F0D0D0D007D0C3 :10018D0083D082D0E032C0E0C082C083C007C0D02F :10019D0075D000D200AF9174EF5FF591907FAA7486 :1001AD0004F0D0D0D007D083D082D0E032323232BA :1001BD0032323232323232AF82747F5FFE24F850E7 :1001CD0003020278EE240A83F582EE240C83F58374 :1001DD00E473EFF306192C3F52650101020202028E :1001ED000202907FB422EF30E7067DB67E7F800459 :1001FD007DC67E7F8D828E8322EF30E7067DB87EB1 :10020D007F80047DC87E7F8D828E8322EF30E7064E :10021D007DBA7E7F80047DCA7E7F8D828E8322EFA4 :10022D0030E7067DBC7E7F80047DCC7E7F8D828E07 :10023D008322EF30E7067DBE7E7F80047DCE7E7FFC :10024D008D828E8322EF30E7067DC07E7F80047D18 :10025D00D07E7F8D828E8322EF30E7067EC27F7F38 :10026D0080047ED27F7F8E828F832290000022AF0A :10027D008274105FFE74075F4206907FD7EEF074B4 :10028D00204EF022907FE8E0C322907FE8E0FF60EF :10029D0005BF0246800A907FB4E0FF4401F0803A2A :1002AD00907FEAE0FEA3E0FF4E7027907FECE0FE2A :1002BD00A3E08E821201C4AE82AF83EE4F7002C3F3 :1002CD00228E828F83E0FD5305FE8E828F83EDF0AB :1002DD008008907FB4E0FF4401F0D322907FE8E0E6 :1002ED00FF6005BF02468010907FEAE0FEA3E0FFAD :1002FD00BE0239BF0036D322907FEAE0FEA3E0FFB5 :10030D004E7027907FECE0FEA3E08E821201C4AE0A :10031D0082AF83EE4F7002C3228E828F83E0FD4346 :10032D0005018E828F83EDF08002C322D322907F50 :10033D00EAE0A3E0FF907FEAE0FDA3E07E00BF01CD :10034D0002800DBF02028021BF030280340203EC44 :10035D007ED37F138F06907FD4EEF07ED37F137FF5 :10036D0000907FD5EEF00203EE7EE57F138F0690B1 :10037D007FD4EEF07EE57F137F00907FD5EEF08089 :10038D0060907FECE0FEA3E0FF4E70187E057F14B9 :10039D008F06907FD4EEF07E057F147F00907FD581 :1003AD00EEF0803D907FECE0FEA3E0FFBE092EBF96 :1003BD00042BED1475F002A42459F582741435F054 :1003CD00F583E493FEA3E493FF8E048F058D0490D3 :1003DD007FD4ECF07F00907FD5EEF08004C322C374 :1003ED0022D32275828212027C75820212027C90C7 :1003FD007FB87402F0907FC8E4F0907FC9F022902E :10040D007FE9E0FF24F3500122EFF5F0240B83F593 :10041D0082E5F0241183F583E473414F5D655D72D0 :10042D007B73889899A9AC0404040404040404049F :10043D0004040404120291500122907FB4E044019F :10044D00F022120297500122907FB4E04401F02275 :10045D00907FB4E04401F0221202E94042907FB453 :10046D00E04401F02222907FB4E04401F022120317 :10047D003B402C907FB4E04401F0229013EAE493CA :10048D00907F00F0907FB57401F022229013F0E47C :10049D0093907F00F0907FB57401F0221203F0224B :1004AD00907FDE7404F0907FDF7404F0907FE0E4C1 :1004BD00F0907FE1F0907FA17401F0907FAFE04468 :1004CD0001F0907FAEE04401F0907FAD7404F090A8 :1004DD007FAC7404F0D2E8907FD6740AF09000C817 :0A04ED0012137C907FD67406F022F3 :1013D30012011001FFFFFF4051C21027000101025B :1013E3000301090220000101048032090400000204 :1013F300FFFFFF00070582024000000705020240CD :1014030000000403090414034F00700065006E001C :1014130055004C0049004E004B0014034F00700070 :1014230065006E0055004C0049004E004B000E0352 :101433003000300030003000300031001A034A0021 :101443005400410047002000410064006100700027 :0E14530074006500720009141D1431143F145A :1004F700E5080424C0F582E4347DF583E0FF30E1AC :1005070008907F96E0FE54EFF08F06EE30E00890FB :100517007F96E0FE547FF0EF30E308907F96E0FE91 :100527004410F0EF30E208907F96E0FF4480F0221D :100537007F00E50824C0F582E4347DF583E0FE24DE :10054700D550030208A6EE240A83F582EE242F83F2 :10055700F583E473B18AD7B0FAD3A6A6A6A6A6A652 :10056700A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A624 :10057700A6A6A6A621FA512A639CD5053493A205FF :1005870006050605060808080808080808080808F0 :1005970008080808080808080808080808080806D6 :1005A700060607070707080808087E05E508042464 :1005B700C0F582E4347DF583E0FFE50804F5828524 :1005C7000927C007C00612091DD006D0070208A8D0 :1005D700E5080424C0F582E4347DF583E02405FEB4 :1005E700E50804F582C007C006120BDED006D00767 :1005F7000208A8E5080424C0F582E4347DF583E009 :10060700FF2405FEE50804F58285093CC007C006FE :10061700120E79D006D0070208A87E02E508042446 :10062700C0F582E4347DF583E0FD7402250824C01B :10063700F582E4347DF583E0F50A8D82C007C006B4 :1006470012124AD006D0070208A87E02E508042441 :10065700C0F582E4347DF583E0FC7D007402250853 :1006670024C0F582E4347DF583E0FAE44204EA42EB :10067700058C828D83C007C0061211DDD006D00716 :100687000208A87E05E5080424C0F582E4347DF558 :1006970083E0FFE50804F58285092DC007C006122F :1006A7000A67D006D0070208A8E5080424C0F58227 :1006B700E4347DF583E02405FEE50804F582C007F0 :1006C700C006120D14D006D0070208A8E5080424B6 :1006D700C0F582E4347DF583E0FF2405FEE50804D8 :1006E700F582850943C007C006121013D006D0074C :1006F7000208A87E02E5080424C0F582E4347DF5EB :1007070083E0FB7402250824C0F582E4347DF58379 :10071700E0F50A8B82C007C006121281D006D00707 :100727000208A87E02E5080424C0F582E4347DF5BA :1007370083E0FC7D007402250824C0F582E4347D43 :10074700F583E0FAE44204EA42058C828D83C00710 :10075700C006121207D006D0070208A87E02E508D5 :100767000424C0F582E4347DF583E0FC7D00740247 :10077700250824C0F582E4347DF583E0FAE44204D9 :10078700EA42058C828D83C007C006121349D00642 :10079700D0070208A87E02E5080424C0F582E434E5 :1007A7007DF583E0FC7D007402250824C0F582E412 :1007B700347DF583E0FAE44204EA42058C828D83B6 :1007C700C007C00612137CD006D0070208A87E0017 :1007D7007F02C007C0061212CEAC82AD83D006D00E :1007E7000785098275837E8D03EBF0E509042400F4 :1007F700F582E4347EF5837D00ECF00208A87E02E2 :10080700E5080424C0F582E4347DF583E0FD740235 :10081700250824C0F582E4347DF583E0F50A8D824E :10082700C007C006121311D006D00780747E05E5F5 :10083700080424C0F582E4347DF583E0FD740225C5 :100847000824C0F582E4347DF583E0F50A740325B6 :100857000824C0F582E4347DF583E0F50B740425A4 :100867000824C0F582E4347DF583E0F50C74052592 :100877000824C0F582E4347DF583E0F50D8D82C050 :1008870007C006121329D006D00780157E01C007BE :10089700C0061204F7D006D00780067E0180027ECC :1008A70000EF2509F509AD087F008E037C00EB2DCD :1008B700FDEC3FFF0DBD00010F907FC9E0FC7B0001 :1008C700C3ED9CEF64808BF063F08095F04002D31A :1008D70022EE042508F508C32275080075090010E3 :1008E700000280FB907F96E0FF547FF0C202200257 :1008F70007120537920280F6907F96E0FF4480F05A :10090700E509600B907FB9E509F010010280FB90C3 :100917007FC9E4F080C3E582FF24C0F582E4347D1B :10092700F583E0F528EF0424C0F582E4347DF583F0 :10093700E0F52974022FFC24C0F582E4347DF583A9 :10094700E0C4540FFB53030FEC24C0F582E4347D5D :10095700F583E0FC740F5CF52A74032F24C0F5823D :10096700E4347DF583E0FA74042F24C0F582E4347F :100977007DF583E0F52BEB60078A0A8B8212124A1A :10098700907F97E0FB5303F874044BFA7900A8288B :100997007C0018B8FF011C89067F00C3EE98EF643E :1009A700808CF063F08095F050347F007E00907F5C :1009B70097EBF0EFC313FF907F97EAF0907F99E0F2 :1009C700FC30E5034307800EBE080040E1E5272918 :1009D7002400F582E4347EF583EFF00980B0892C9A :1009E7007F00AC2A7A00C3EA95295040A8297900EC :1009F70018B8FF01198A057E00EDB50011EEB501A3 :100A07000DEC600A4303021CE52BC313F52B907F03 :100A170097EBF0EFC313FF907F9774044BF0907F31 :100A270099E0FE30E5034307800A80BAAD297E00CE :100A37007408C39DFDE49EFE8DF005F0EF8002C3B0 :100A470013D5F0FBFFE527252C2400F582E4347E3F :100A5700F583EFF0EC6008852B0A8C8202124A229C :100A6700E582FF24C0F582E4347DF583E0F52EEFBF :100A77000424C0F582E4347DF583E0F52F74022F5A :100A8700FC24C0F582E4347DF583E0C4540FFB53A6 :100A9700030FEC24C0F582E4347DF583E0FC740F8A :100AA7005CF53074032F24C0F582E4347DF583E0D0 :100AB700FA74042F24C0F582E4347DF583E0F53120 :100AC700EB60078A0A8B82121281907F97E0FB53B3 :100AD70003F874044BFA753200A82E7C0018B8FF8F :100AE700011CA9327E00C3E998EE64808CF063F0A4 :100AF7008095F0504C7E007C00907F97EBF079005A :100B0700C3E9952250030980F7EEC313FE907F9740 :100B1700EAF07900C3E9952250030980F7907F999D :100B2700E0F930E5034306800CBC080040CBE52D17 :100B370025322400F582E4347EF583EEF005328019 :100B4700987E00AA307900C3E9952F5056A82F7CCC :100B57000018B8FF011C89057F00EDB50011EFB53E :100B6700040DEA600A4303021AE531C313F5319015 :100B77007F97EBF07F00C3EF952250030F80F7EECE :100B8700C313FE907F9774044BF07F00C3EF952249 :100B970050030F80F7907F99E0FF30E5034306800D :100BA7000980A4AD2F7F007408C39DFDE49FFF8DCE :100BB700F005F0EE8002C313D5F0FBFEE52D2532DC :100BC7002400F582E4347EF583EEF0EA600885318F :100BD7000A8A8202128122E582FF24C0F582E43468 :100BE7007DF583E0F533EF0424C0F582E4347DF529 :100BF70083E0F53474022FFC24C0F582E4347DF5DC :100C070083E0C4540FFB53030FEC24C0F582E43494 :100C17007DF583E0FC740F5CF53574032F24C0F574 :100C270082E4347DF583E0FA74042F24C0F582E46E :100C3700347DF583E0F536EB600B8A0A8B82C007BB :100C470012124AD007907F97E0FB5303F97A00A866 :100C5700337C0018B8FF011C8A017E00C3E998EEB7 :100C670064808CF063F08095F05039EF2A240524D6 :100C7700C0F582E4347DF583E0FE7C00EE30E005CC :100C870043030180068B0174FE59FB907F97EBF0BD :100C9700EEC313FE907F9774044BF00CBC08004022 :100CA700DB0A80ABEF2A240524C0F582E4347DF506 :100CB70083E0FEAF357C00C3EC95345044EE30E062 :100CC7000543030180068B0274FE5AFBA9347A00A0 :100CD70019B9FF011A8C007D00E8B50111EDB502C5 :100CE7000DEF600A4303021FE536C313F536907F05 :100CF70097EBF0EEC313FE907F9774044BF00C80D4 :100D0700B6EF600885360A8F8202124A22E582F51D :100D17003724C0F582E4347DF583E0F538E5370400 :100D270024C0F582E4347DF583E0F5397402253774 :100D3700FC24C0F582E4347DF583E0C4540FFB53F3 :100D4700030FEC24C0F582E4347DF583E0FC740FD7 :100D57005CF53A7403253724C0F582E4347DF583C6 :100D6700E0FA7404253724C0F582E4347DF583E086 :100D7700F53BEB60078A0A8B82121281907F97E01E :100D8700FB5303F97A00A8387C0018B8FF011C8AC6 :100D9700067F00C3EE98EF64808CF063F08095F0D7 :100DA7005050E5372A240524C0F582E4347DF583C5 :100DB700E0FF7E00EF30E00543030180068B0474FB :100DC700FE5CFB907F97EBF07C00C3EC9523500310 :100DD7000C80F7EFC313FF907F9774044BF07C00F0 :100DE700C3EC952350030C80F70EBE080040C50ADC :100DF7008094E5372A240524C0F582E4347DF58301 :100E0700E0FFAE3A7C00C3EC9539505AEF30E0056D :100E170043030180068B0274FE5AFBA8397A001837 :100E2700B8FF011A8C017D00E9B50011EDB5020D7F :100E3700EE600A4303021EE53BC313F53B907F9721 :100E4700EBF07D00C3ED952350030D80F7EFC3133F :100E5700FF907F9774044BF07D00C3ED95235003FB :100E67000D80F70C80A0EE6008853B0A8E82021287 :100E77008122E582FF24C0F582E4347DF583E0F525 :100E87003DEF0424C0F582E4347DF583E0F53E743C :100E9700022FFC24C0F582E4347DF583E0C4540FAF :100EA700FB53030FEC24C0F582E4347DF583E0FCAB :100EB700740F5CF53F74032F24C0F582E4347DF58D :100EC70083E0FA74042F24C0F582E4347DF583E0CF :100ED700F540EB600B8A0A8B82C00712124AD007D3 :100EE700907F97E0FB5303F97A00A83D7C0018B880 :100EF700FF011C8A017E00C3E998EE64808CF063D1 :100F0700F08095F0505CEF2A240524C0F582E43484 :100F17007DF583E0F5417C007900E54130E005434C :100F2700030180068B0074FE58FB907F97EBF0E57A :100F370041C313F541907F9774044BF0ECC313FC46 :100F4700907F99E0F830E50343048009B908004031 :100F5700C9E53C2A2400F582E4347EF583ECF00AE7 :100F670080888A01EF2A240524C0F582E4347DF5C0 :100F770083E0F5417C00AF3F754200C3E542953EF3 :100F87005057E54130E00543030180068B0074FEAE :100F970058FBA83E7D0018B8FF011DAA427E00EA53 :100FA700B50011EEB5050DEF600A4303021FE540DA :100FB700C313F540907F97EBF0E541C313F54190DC :100FC7007F9774044BF0ECC313FC907F99E0FE30DD :100FD700E503430480054280A2AD3E7E007408C34A :100FE7009DFDE49EFE8DF005F0EC8002C313D5F065 :100FF700FBFCE53C292400F582E4347EF583ECF024 :10100700EF600885400A8F8202124A22E582F54482 :1010170024C0F582E4347DF583E0F545E5440424F6 :10102700C0F582E4347DF583E0F54674022544FC7F :1010370024C0F582E4347DF583E0C4540FFB5303E9 :101047000FEC24C0F582E4347DF583E0FC740F5C7B :10105700F5477403254424C0F582E4347DF583E025 :10106700FA7404254424C0F582E4347DF583E0F561 :1010770048EB60078A0A8B82121281907F97E0FB08 :101087005303F97A00A8457C0018B8FF011C8A06AB :101097007F00C3EE98EF64808CF063F08095F0508A :1010A70074E5442A240524C0F582E4347DF583E001 :1010B700F5497E007C00E54930E0054303018006E1 :1010C7008B0074FE58FB907F97EBF07800C3E89590 :1010D7002450030880F7E549C313F549907F9774B7 :1010E700044BF07800C3E8952450030880F7EEC35B :1010F70013FE907F99E0F830E5034306800CBC08A7 :101107000040B3E5432A2400F582E4347EF583EEFC :10111700F00A02108C8A04E5442A240524C0F582CB :10112700E4347DF583E0F5497E00AA47754A00C39C :10113700E54A9546506DE54930E0054303018006D1 :101147008B0174FE59FBA9467D0019B9FF011DA843 :101157004A7F00E8B50111EFB5050DEA600A4303C0 :10116700021AE548C313F548907F97EBF07F00C359 :10117700EF952450030F80F7E549C313F549907F96 :101187009774044BF07F00C3EF952450030F80F74B :10119700EEC313FE907F99E0FF30E5034306800519 :1011A7004A808CAD467F007408C39DFDE49FFF8D88 :1011B700F005F0EE8002C313D5F0FBFEE5432C24C7 :1011C70000F582E4347EF583EEF0EA600885480A8C :1011D7008A8202128122AE82AF83907F97E0FD530D :1011E70005FB74044DFC7A007B00C3EA9EEB9F501D :1011F7000E907F97EDF0ECF00ABA00EE0B80EB2231 :10120700AE82AF83907F97E0FD5305FB74044DFCDE :101217007A007B00C3EA9EEB9F5027907F97EDF003 :101227007900C3E9952550030980F7907F97ECF083 :101237007900C3E9952550030980F70ABA00D50B51 :1012470080D222AF82907F97E0FE5306FB7D00C3DA :10125700ED9F5025E50A30E00543060280068E041F :1012670074FD5CFE907F97EEF0E50AC313F50A90D4 :101277007F9774044EF00D80D622AF82907F97E05F :10128700FE5306FB7D00C3ED9F503BE50A30E005AA :1012970043060280068E0474FD5CFE907F97EEF095 :1012A7007C00C3EC952650030C80F7E50AC313F5C1 :1012B7000A907F9774044EF07C00C3EC9526500388 :1012C7000C80F70D80C0227F00907F99E0FE30E50B :1012D700027F01907F99E0FE30E603430702907F8B :1012E7009AE0FE30E703430704907F9BE0FE30E57A :1012F70003430708907F9AE0FE53067F8F05E4FFBC :10130700FCEE4FF582EC4DF58322E582547FF4FF26 :10131700907F97E05FF0747F550AFF907F97E04FCB :10132700F022858222850A23850B24850C25850DCD :10133700262200227E567F021EBEFF011FEE4F703F :10134700F722750A05750B001213A6AE82AF837CD0 :10135700007D00C3EC9EED9F501AC007C006C00574 :10136700C004121339D004D005D006D0070CBC0036 :10137700E20D80DF22AE82AF837C007D00C3EC9E4E :10138700ED9F501AC007C006C005C00412133BD01A :0F13970004D005D006D0070CBC00E20D80DF2289 :03004300021B009D :101B0000020110000201630002016400020165008D :101B1000020166000201670002016800020169001B :101B200002016A0002016B0002016C0002019300D5 :101B30000201BA000201BB000201BC000201BD00AB :101B40000201BE000201BF000201C0000201C1008B :081B50000201C2000201C30002 :1013A6007A10E4FBFCE58225E0F582E58333F583DC :1013B600EB33FBEC33FCEB950AF5F0EC950B4006B2 :0913C600FCABF0438201DADD22E8 :0600A000E478FFF6D8FD34 :10007E007900E94400601B7A009014617800759253 :10008E0020E493F2A308B800020592D9F4DAF275CF :02009E0092FFCF :1000A6007800E84400600A7900759220E4F309D8E4 :1000B600FC7800E84400600C7900902000E4F0A38E :0400C600D8FCD9FA8F :0D00710075814A1213CFE582600302006E14 :0413CF007582002201 :00000001FF openocd-0.9.0/src/jtag/drivers/OpenULINK/Makefile0000644000175000017500000000706012315575360016440 00000000000000############################################################################ # Copyright (C) 2011 by Martin Schmoelzer # # # # # # This program 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 2 of the License, or # # (at your option) any later version. # # # # This program 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, write to the # # Free Software Foundation, Inc., # # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # ############################################################################ # Define the name of our tools. Some distributions (e. g. Fedora) prefix # the SDCC executables, change this accordingly! PREFIX = # Small Device C Compiler: http://sdcc.sourceforge.net/ CC = $(PREFIX)-sdcc # 8051 assembler, part of the SDCC software package. AS = $(PREFIX)-sdas8051 # SDCC produces quite messy Intel HEX files. This tool is be used to re-format # those files. It is not required for the firmware download functionality in # the OpenOCD driver, but the resulting file is smaller. PACKIHX = $(PREFIX)-packihx # GNU binutils size. Used to print the size of the IHX file generated by SDCC. SIZE = size # Source and header directories. SRC_DIR = src INCLUDE_DIR = include CODE_SIZE = 0x1B00 # Starting address of __xdata variables. Since the OpenULINK firmware does not # use any of the isochronous interrupts, we can use the isochronous buffer space # as XDATA memory. XRAM_LOC = 0x2000 XRAM_SIZE = 0x0800 CFLAGS = --std-sdcc99 --opt-code-size --model-small LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \ --xram-size $(XRAM_SIZE) --iram-size 256 --model-small # list of base object files OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel HEADERS = $(INCLUDE_DIR)/main.h \ $(INCLUDE_DIR)/usb.h \ $(INCLUDE_DIR)/protocol.h \ $(INCLUDE_DIR)/jtag.h \ $(INCLUDE_DIR)/delay.h \ $(INCLUDE_DIR)/reg_ezusb.h \ $(INCLUDE_DIR)/io.h \ $(INCLUDE_DIR)/msgtypes.h # Disable all built-in rules. .SUFFIXES: # Targets which are executed even when identically named file is present. .PHONY: all, clean all: ulink_firmware.ihx $(SIZE) ulink_firmware.ihx ulink_firmware.ihx: $(OBJECTS) $(CC) -mmcs51 $(LDFLAGS) -o $@ $^ # Rebuild every C module (there are only 5 of them) if any header changes. %.rel: $(SRC_DIR)/%.c $(HEADERS) $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $< %.rel: $(SRC_DIR)/%.a51 $(AS) -lsgo $@ $< clean: rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lk *.map *.mem hex: ulink_firmware.ihx $(PACKIHX) ulink_firmware.ihx > ulink_firmware.hex openocd-0.9.0/src/jtag/drivers/OpenULINK/README0000644000175000017500000000361012315575360015655 00000000000000This is the OpenULINK firmware for the Keil ULINK JTAG adapter. The main components of the Keil ULINK adapter are: - Cypress EZ-USB microcontroller: enhanced 8051 CPU + USB core (1.1 Full-Speed) - SRAM memory chip - Level shifters to support different JTAG signal voltage levels - Pin headers for various JTAG pin assignments This firmware can only be run on the ORIGINAL Keil ULINK adapter, not on the newer ULINK2, ULINK-ME or ULINK-PRO, as these adapters are based on different hardware. To compile the firmware, the SDCC compiler package is required. Most Linux distributions include SDCC in their official package repositories. The SDCC source code can be found at http://sdcc.sourceforge.net/ Simply type "make hex" in the OpenULINK directory to compile the firmware. "make clean" will remove all generated files except the Intel HEX file required for downloading the firmware to the ULINK adapter. Note that the EZ-USB microcontroller does not have on-chip flash, nor does the Keil ULINK include on-board memory to store the firmware program of the EZ-USB. Instead, upon initial connection of the ULINK adapter to the host PC via USB, the EZ-USB core has enough intelligence to act as a stand-alone USB device, responding to USB control requests and allowing firmware download via a special VENDOR-type control request. Then, the EZ-USB microcontroller simulates a disconnect and re-connect to the USB bus. It may take up to two seconds for the host to recognize the newly connected device before OpenOCD can proceed to execute JTAG commands. This delay is only visible when OpenOCD first uses a blank (unconfigured) ULINK device. Once the user disconnects the ULINK adapter, all its memory contents are lost and the firmware download process has to be executed again. This also maintains compatibility with the original Keil uVision IDE, which will happily download its own firmware image to a blank ULINK adapter. openocd-0.9.0/src/jtag/drivers/OpenULINK/include/0000755000175000017500000000000012315575360016500 500000000000000openocd-0.9.0/src/jtag/drivers/OpenULINK/include/io.h0000644000175000017500000001277212315575360017211 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __IO_H #define __IO_H #include "reg_ezusb.h" /*************************************************************************** * JTAG Signals: * *************************************************************************** * TMS ....... Test Mode Select * * TCK ....... Test Clock * * TDI ....... Test Data Input (from device point of view, not JTAG * * adapter point of view!) * * TDO ....... Test Data Output (from device point of view, not JTAG * * adapter point of view!) * * TRST ...... Test Reset: Used to reset the TAP Finite State Machine * * into the Test Logic Reset state * * RTCK ...... Return Test Clock * * OCDSE ..... Enable/Disable OCDS interface (Infineon specific) - shared * * with /JEN * * TRAP ...... Trap Condition (Infineon specific) - shared with TSTAT * * BRKIN ..... Hardware Break-In (Infineon specific) * * BRKOUT .... Hardware Break-Out (Infineon specific) * * /JEN ...... JTAG-Enable (STMicroelectronics specific) - shared * * with OCDSE * * TSTAT ..... JTAG ISP Status (STMicroelectronics specific) - shared * * with TRAP * * RESET ..... Chip Reset (STMicroelectronics specific) * * /TERR ..... JTAG ISP Error (STMicroelectronics specific) - shared * * with BRKOUT * ***************************************************************************/ /* PORT A */ #define PIN_U_OE OUTA0 /* PA1 Not Connected */ #define PIN_OE OUTA2 /* PA3 Not Connected */ #define PIN_RUN_LED OUTA4 #define PIN_TDO PINA5 #define PIN_BRKOUT PINA6 #define PIN_COM_LED OUTA7 /* PORT B */ #define PIN_TDI OUTB0 #define PIN_TMS OUTB1 #define PIN_TCK OUTB2 #define PIN_TRST OUTB3 #define PIN_BRKIN OUTB4 #define PIN_RESET OUTB5 #define PIN_OCDSE OUTB6 #define PIN_TRAP PINB7 /* JTAG Signals with direction 'OUT' on port B */ #define MASK_PORTB_DIRECTION_OUT (PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE) /* PORT C */ #define PIN_RXD0 PINC0 #define PIN_TXD0 OUTC1 #define PIN_RESET_2 PINC2 /* PC3 Not Connecte */ /* PC4 Not Connected */ #define PIN_RTCK PINC5 #define PIN_WR OUTC6 /* PC7 Not Connected */ /* LED Macros */ #define SET_RUN_LED() (OUTA &= ~PIN_RUN_LED) #define CLEAR_RUN_LED() (OUTA |= PIN_RUN_LED) #define SET_COM_LED() (OUTA &= ~PIN_COM_LED) #define CLEAR_COM_LED() (OUTA |= PIN_COM_LED) /* JTAG Pin Macros */ #define GET_TMS() (PINSB & PIN_TMS) #define GET_TCK() (PINSB & PIN_TCK) #define GET_TDO() (PINSA & PIN_TDO) #define GET_BRKOUT() (PINSA & PIN_BRKOUT) #define GET_TRAP() (PINSB & PIN_TRAP) #define GET_RTCK() (PINSC & PIN_RTCK) #define SET_TMS_HIGH() (OUTB |= PIN_TMS) #define SET_TMS_LOW() (OUTB &= ~PIN_TMS) #define SET_TCK_HIGH() (OUTB |= PIN_TCK) #define SET_TCK_LOW() (OUTB &= ~PIN_TCK) #define SET_TDI_HIGH() (OUTB |= PIN_TDI) #define SET_TDI_LOW() (OUTB &= ~PIN_TDI) /* TRST and RESET are low-active and inverted by hardware. SET_HIGH de-asserts * the signal (enabling reset), SET_LOW asserts the signal (disabling reset) */ #define SET_TRST_HIGH() (OUTB |= PIN_TRST) #define SET_TRST_LOW() (OUTB &= ~PIN_TRST) #define SET_RESET_HIGH() (OUTB |= PIN_RESET) #define SET_RESET_LOW() (OUTB &= ~PIN_RESET) #define SET_OCDSE_HIGH() (OUTB |= PIN_OCDSE) #define SET_OCDSE_LOW() (OUTB &= ~PIN_OCDSE) #define SET_BRKIN_HIGH() (OUTB |= PIN_BRKIN) #define SET_BRKIN_LOW() (OUTB &= ~PIN_BRKIN) #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/delay.h0000644000175000017500000000321312315575360017666 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __DELAY_H #define __DELAY_H #include #define NOP { __asm nop __endasm; } void delay_5us(void); void delay_1ms(void); void delay_us(uint16_t delay); void delay_ms(uint16_t delay); #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/usb.h0000644000175000017500000002416212315575360017367 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __USB_H #define __USB_H #include "reg_ezusb.h" #include #include #define NULL (void *)0; /* High and Low byte of a word (uint16_t) */ #define HI8(word) (uint8_t)(((uint16_t)word >> 8) & 0xff) #define LO8(word) (uint8_t)((uint16_t)word & 0xff) /* Convenience functions */ #define STALL_EP0() (EP0CS |= EP0STALL) #define CLEAR_IRQ() (EXIF &= ~USBINT) /*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/ /* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */ #define DESCRIPTOR_TYPE_DEVICE 0x01 #define DESCRIPTOR_TYPE_CONFIGURATION 0x02 #define DESCRIPTOR_TYPE_STRING 0x03 #define DESCRIPTOR_TYPE_INTERFACE 0x04 #define DESCRIPTOR_TYPE_ENDPOINT 0x05 #define STR_DESCR(len, ...) { len * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } } /** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */ struct usb_device_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< DEVICE Descriptor Type. */ uint16_t bcdUSB; /**< USB specification release number (BCD). */ uint8_t bDeviceClass; /**< Class code. */ uint8_t bDeviceSubClass; /**< Subclass code. */ uint8_t bDeviceProtocol; /**< Protocol code. */ uint8_t bMaxPacketSize0; /**< Maximum packet size for EP0 (8, 16, 32, 64). */ uint16_t idVendor; /**< USB Vendor ID. */ uint16_t idProduct; /**< USB Product ID. */ uint16_t bcdDevice; /**< Device Release Number (BCD). */ uint8_t iManufacturer; /**< Index of manufacturer string descriptor. */ uint8_t iProduct; /**< Index of product string descriptor. */ uint8_t iSerialNumber; /**< Index of string descriptor containing serial #. */ uint8_t bNumConfigurations; /**< Number of possible configurations. */ }; /** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */ struct usb_config_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< CONFIGURATION descriptor type. */ uint16_t wTotalLength; /**< Combined total length of all descriptors. */ uint8_t bNumInterfaces; /**< Number of interfaces in this configuration. */ uint8_t bConfigurationValue; /**< Value used to select this configuration. */ uint8_t iConfiguration; /**< Index of configuration string descriptor. */ uint8_t bmAttributes; /**< Configuration characteristics. */ uint8_t MaxPower; /**< Maximum power consumption in 2 mA units. */ }; /** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */ struct usb_interface_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< INTERFACE descriptor type. */ uint8_t bInterfaceNumber; /**< Interface number. */ uint8_t bAlternateSetting; /**< Value used to select alternate setting. */ uint8_t bNumEndpoints; /**< Number of endpoints used by this interface. */ uint8_t bInterfaceClass; /**< Class code. */ uint8_t bInterfaceSubclass; /**< Subclass code. */ uint8_t bInterfaceProtocol; /**< Protocol code. */ uint8_t iInterface; /**< Index of interface string descriptor. */ }; /** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */ struct usb_endpoint_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< ENDPOINT descriptor type. */ uint8_t bEndpointAddress; /**< Endpoint Address: USB 1.1 spec, table 9-10. */ uint8_t bmAttributes; /**< Endpoint Attributes: USB 1.1 spec, table 9-10. */ uint16_t wMaxPacketSize; /**< Maximum packet size for this endpoint. */ uint8_t bInterval; /**< Polling interval (in ms) for this endpoint. */ }; /** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */ struct usb_language_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< STRING descriptor type. */ uint16_t wLANGID[]; /**< LANGID codes. */ }; /** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */ struct usb_string_descriptor { uint8_t bLength; /**< Size of this descriptor in bytes. */ uint8_t bDescriptorType; /**< STRING descriptor type. */ uint16_t bString[]; /**< UNICODE encoded string. */ }; /********************** USB Control Endpoint 0 related *********************/ /** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */ struct setup_data { uint8_t bmRequestType; /**< Characteristics of a request. */ uint8_t bRequest; /**< Specific request. */ uint16_t wValue; /**< Field that varies according to request. */ uint16_t wIndex; /**< Field that varies according to request. */ uint16_t wLength; /**< Number of bytes to transfer in data stage. */ }; /* External declarations for variables that need to be accessed outside of * the USB module */ extern volatile bool EP2_out; extern volatile bool EP2_in; extern volatile __xdata __at 0x7FE8 struct setup_data setup_data; /* * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2 * * Bit 7: Data transfer direction * 0 = Host-to-device * 1 = Device-to-host * Bit 6...5: Type * 0 = Standard * 1 = Class * 2 = Vendor * 3 = Reserved * Bit 4...0: Recipient * 0 = Device * 1 = Interface * 2 = Endpoint * 3 = Other * 4...31 = Reserved */ #define USB_DIR_OUT 0x00 #define USB_DIR_IN 0x80 #define USB_REQ_TYPE_STANDARD (0x00 << 5) #define USB_REQ_TYPE_CLASS (0x01 << 5) #define USB_REQ_TYPE_VENDOR (0x02 << 5) #define USB_REQ_TYPE_RESERVED (0x03 << 5) #define USB_RECIP_DEVICE 0x00 #define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_OTHER 0x03 /* bmRequestType for USB Standard Requests */ /* Clear Interface Request */ #define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Get Configuration Request */ #define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Descriptor Request */ #define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Interface Request */ #define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) /* Get Status Request: See USB 1.1 spec, page 190 */ #define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Set Address Request is handled by EZ-USB core */ /* Set Configuration Request */ #define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Descriptor Request */ #define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Feature Request */ #define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Set Interface Request */ #define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) /* Synch Frame Request */ #define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */ #define GET_STATUS 0 #define CLEAR_FEATURE 1 /* Value '2' is reserved for future use */ #define SET_FEATURE 3 /* Value '4' is reserved for future use */ #define SET_ADDRESS 5 #define GET_DESCRIPTOR 6 #define SET_DESCRIPTOR 7 #define GET_CONFIGURATION 8 #define SET_CONFIGURATION 9 #define GET_INTERFACE 10 #define SET_INTERFACE 11 #define SYNCH_FRAME 12 /* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */ #define DEVICE_REMOTE_WAKEUP 1 #define ENDPOINT_HALT 0 /************************** EZ-USB specific stuff **************************/ /** USB Interrupts. See AN2131-TRM, page 9-4 for details */ enum usb_isr { SUDAV_ISR = 13, SOF_ISR, SUTOK_ISR, SUSPEND_ISR, USBRESET_ISR, IBN_ISR, EP0IN_ISR, EP0OUT_ISR, EP1IN_ISR, EP1OUT_ISR, EP2IN_ISR, EP2OUT_ISR, EP3IN_ISR, EP3OUT_ISR, EP4IN_ISR, EP4OUT_ISR, EP5IN_ISR, EP5OUT_ISR, EP6IN_ISR, EP6OUT_ISR, EP7IN_ISR, EP7OUT_ISR }; /*************************** Function Prototypes ***************************/ __xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep); void usb_reset_data_toggle(uint8_t ep); bool usb_handle_get_status(void); bool usb_handle_clear_feature(void); bool usb_handle_set_feature(void); bool usb_handle_get_descriptor(void); void usb_handle_set_interface(void); void usb_handle_setup_data(void); void usb_init(void); #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/protocol.h0000644000175000017500000000316012315575360020432 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __PROTOCOL_H #define __PROTOCOL_H #include "common.h" #include void execute_set_led_command(void); bool execute_command(void); void command_loop(void); #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/msgtypes.h0000644000175000017500000002601112315575360020444 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * Definition of the commands supported by the OpenULINK firmware. * * Basically, two types of commands can be distinguished: * - Commands with fixed payload size * - Commands with variable payload size * * SCAN commands (in all variations) carry payloads of variable size, all * other commands carry payloads of fixed size. * * In the case of SCAN commands, the payload size (n) is calculated by * dividing the scan_size_bits variable by 8, rounding up the result. * * Offset zero always contains the command ID. * **************************************************************************** * CMD_SCAN_IN, CMD_SLOW_SCAN_IN: * * * * OUT: * * offset 1: scan_size_bytes * * offset 2: bits_last_byte * * offset 3: tms_count_start + tms_count_end * * offset 4: tms_sequence_start * * offset 5: tms_sequence_end * * * * IN: * * offset 0..n: TDO data * **************************************************************************** * CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: * * * * OUT: * * offset 1: scan_size_bytes * * offset 2: bits_last_byte * * offset 3: tms_count_start + tms_count_end * * offset 4: tms_sequence_start * * offset 5: tms_sequence_end * * offset 6..x: TDI data * **************************************************************************** * CMD_SCAN_IO, CMD_SLOW_SCAN_IO: * * * * OUT: * * offset 1: scan_size_bytes * * offset 2: bits_last_byte * * offset 3: tms_count_start + tms_count_end * * offset 4: tms_sequence_start * * offset 5: tms_sequence_end * * offset 6..x: TDI data * * * * IN: * * offset 0..n: TDO data * **************************************************************************** * CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: * * * * OUT: * * offset 1: tms_count * * offset 2: tms_sequence * **************************************************************************** * CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: * * * * OUT: * * offset 1: low byte of tck_count * * offset 2: high byte of tck_count * **************************************************************************** * CMD_CLOCK_SLEEP_US: * * * * OUT: * * offset 1: low byte of sleep_us * * offset 2: high byte of sleep_us * **************************************************************************** * CMD_CLOCK_SLEEP_MS: * * * * OUT: * * offset 1: low byte of sleep_ms * * offset 2: high byte of sleep_ms * **************************************************************************** * CMD_GET_SIGNALS: * * * * IN: * * offset 0: current state of input signals * * offset 1: current state of output signals * **************************************************************************** * CMD_SET_SIGNALS: * * * * OUT: * * offset 1: signals that should be de-asserted * * offset 2: signals that should be asserted * **************************************************************************** * CMD_CONFIGURE_TCK_FREQ: * * * * OUT: * * offset 1: delay value for scan_in function * * offset 2: delay value for scan_out function * * offset 3: delay value for scan_io function * * offset 4: delay value for clock_tck function * * offset 5: delay value for clock_tms function * **************************************************************************** * CMD_SET_LEDS: * * * * OUT: * * offset 1: LED states: * * Bit 0: turn COM LED on * * Bit 1: turn RUN LED on * * Bit 2: turn COM LED off * * Bit 3: turn RUN LED off * * Bits 7..4: Reserved * **************************************************************************** * CMD_TEST: * * * * OUT: * * offset 1: unused dummy value * **************************************************************************** */ #ifndef __MSGTYPES_H #define __MSGTYPES_H /* * Command IDs: * * Bits 7..6: Reserved, should always be zero * Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs, * the IDs 0x00..0x1F are commands with variable payload size, * the IDs 0x20..0x3F are commands with fixed payload size. */ #define CMD_ID_MASK 0x3F /* Commands with variable payload size */ #define CMD_SCAN_IN 0x00 #define CMD_SLOW_SCAN_IN 0x01 #define CMD_SCAN_OUT 0x02 #define CMD_SLOW_SCAN_OUT 0x03 #define CMD_SCAN_IO 0x04 #define CMD_SLOW_SCAN_IO 0x05 /* Commands with fixed payload size */ #define CMD_CLOCK_TMS 0x20 #define CMD_SLOW_CLOCK_TMS 0x21 #define CMD_CLOCK_TCK 0x22 #define CMD_SLOW_CLOCK_TCK 0x23 #define CMD_SLEEP_US 0x24 #define CMD_SLEEP_MS 0x25 #define CMD_GET_SIGNALS 0x26 #define CMD_SET_SIGNALS 0x27 #define CMD_CONFIGURE_TCK_FREQ 0x28 #define CMD_SET_LEDS 0x29 #define CMD_TEST 0x2A /* JTAG signal definition for jtag_get_signals() -- Input signals! */ #define SIGNAL_TDO (1<<0) #define SIGNAL_BRKOUT (1<<1) #define SIGNAL_TRAP (1<<2) #define SIGNAL_RTCK (1<<3) /* JTAG signal definition for jtag_get_signals() -- Output signals! */ #define SIGNAL_TDI (1<<0) #define SIGNAL_TMS (1<<1) #define SIGNAL_TCK (1<<2) #define SIGNAL_TRST (1<<3) #define SIGNAL_BRKIN (1<<4) #define SIGNAL_RESET (1<<5) #define SIGNAL_OCDSE (1<<6) /* LED definitions for CMD_SET_LEDS and CMD_CLEAR_LEDS commands */ #define COM_LED_ON (1<<0) #define RUN_LED_ON (1<<1) #define COM_LED_OFF (1<<2) #define RUN_LED_OFF (1<<3) #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/common.h0000644000175000017500000000303412315575360020061 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __COMMON_H #define __COMMON_H #define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n)) #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/reg_ezusb.h0000644000175000017500000005120512315575360020561 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef REG_EZUSB_H #define REG_EZUSB_H /** * @file * All information in this file was taken from the EZ-USB Technical * Reference Manual, Cypress Semiconductor, 3901 North First Street * San Jose, CA 95134 (www.cypress.com). * * The EZ-USB Technical Reference Manual is called "EZ-USB TRM" hereafter. * * The following bit name definitions differ from those in the EZ-USB TRM: * - All lowercase characters in the EZ-USB TRM bit names have been converted * to capitals (e. g. "WakeSRC" converted to "WAKESRC"). * - CPUCS: 8051RES is named "RES8051". * - ISOCTL: Two MBZ ("Must Be Zero") bits are named "MBZ0" and "MBZ1". * - I2CS: STOP and START bits are preceded by "I2C_" * - INxCS, OUTxCS: the busy and stall bits are named "EPBSY" and "EPSTALL". * - TOGCTL: EZ-USB TRM bit names are preceded by "TOG_". */ /* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */ #include /* Bit vectors */ #define bmBit0 0x01 #define bmBit1 0x02 #define bmBit2 0x04 #define bmBit3 0x08 #define bmBit4 0x10 #define bmBit5 0x20 #define bmBit6 0x40 #define bmBit7 0x80 /************************************************************************** ************************ Special Function Registers ********************** ***************************************************************************/ /* See EZ-USB TRM, pp. A-9 - A-10 */ SFR(SP, 0x81); SFR(DPL0, 0x82); SFR(DPH0, 0x83); SFR(DPL1, 0x84); SFR(DPL2, 0x85); SFR(DPS, 0x86); #define SEL bmBit0 /* Bit 1 read-only, always reads '0' */ /* Bit 2 read-only, always reads '0' */ /* Bit 3 read-only, always reads '0' */ /* Bit 4 read-only, always reads '0' */ /* Bit 5 read-only, always reads '0' */ /* Bit 6 read-only, always reads '0' */ /* Bit 7 read-only, always reads '0' */ SFR(PCON, 0x87); #define IDLE bmBit0 #define STOP bmBit1 #define GF0 bmBit2 #define GF1 bmBit3 /* Bit 4 read-only, always reads '1' */ /* Bit 5 read-only, always reads '1' */ /* Bit 6 unused */ #define SMOD0 bmBit7 SFR(TCON, 0x88); SBIT(IT0, 0x88, 0); SBIT(IE0, 0x88, 1); SBIT(IT1, 0x88, 2); SBIT(IE1, 0x88, 3); SBIT(TR0, 0x88, 4); SBIT(TF0, 0x88, 5); SBIT(TR1, 0x88, 6); SBIT(TF1, 0x88, 7); SFR(TMOD, 0x89); /* Some bits in this register share the same name in the EZ-USB TRM. Therefore, * we add a '0'/'1' to distinguish them */ #define M00 bmBit0 #define M01 bmBit1 #define CT0 bmBit2 #define GATE0 bmBit3 #define M10 bmBit4 #define M11 bmBit5 #define CT1 bmBit6 #define GATE1 bmBit7 SFR(TL0, 0x8A); SFR(TL1, 0x8B); SFR(TH0, 0x8C); SFR(TH1, 0x8D); SFR(CKCON, 0x8E); #define MD0 bmBit0 #define MD1 bmBit1 #define MD2 bmBit2 #define T0M bmBit3 #define T1M bmBit4 #define T2M bmBit5 /* Bit 6 unused */ /* Bit 7 unused */ SFR(SPC_FNC, 0x8D); #define bmWRS bmBit0 /* Bit 1 read-only, always reads '0' */ /* Bit 2 read-only, always reads '0' */ /* Bit 3 read-only, always reads '0' */ /* Bit 4 read-only, always reads '0' */ /* Bit 5 read-only, always reads '0' */ /* Bit 6 read-only, always reads '0' */ /* Bit 7 read-only, always reads '0' */ SFR(EXIF, 0x91); /* Bit 0 read-only, always reads '0' */ /* Bit 1 read-only, always reads '0' */ /* Bit 2 read-only, always reads '0' */ /* Bit 3 read-only, always reads '1' */ #define USBINT bmBit4 #define I2CINT bmBit5 #define IE4 bmBit6 #define IE5 bmBit7 /* Definition of the _XPAGE register, according to SDCC Compiler User Guide, * Version 3.0.1, Chapter 4, p. 61. Also see EZ-USB TRM, p. 2-4. */ SFR(MPAGE, 0x92); SFR(_XPAGE, 0x92); SFR(SCON0, 0x98); SBIT(RI_0, 0x98, 0); SBIT(TI_0, 0x98, 1); SBIT(RB8_0, 0x98, 2); SBIT(TB8_0, 0x98, 3); SBIT(REN_0, 0x98, 4); SBIT(SM2_0, 0x98, 5); SBIT(SM1_0, 0x98, 6); SBIT(SM0_0, 0x98, 7); SFR(SBUF0, 0x99); SFR(IE, 0xA8); SBIT(EX0, 0xA8, 0); SBIT(ET0, 0xA8, 1); SBIT(EX1, 0xA8, 2); SBIT(ET1, 0xA8, 3); SBIT(ES0, 0xA8, 4); SBIT(ET2, 0xA8, 5); SBIT(ES1, 0xA8, 6); SBIT(EA, 0xA8, 7); SFR(IP, 0xB8); SBIT(PX0, 0xB8, 0); SBIT(PT0, 0xB8, 1); SBIT(PX1, 0xB8, 2); SBIT(PT1, 0xB8, 3); SBIT(PS0, 0xB8, 4); SBIT(PT2, 0xB8, 5); SBIT(PS1, 0xB8, 6); /* Bit 7 read-only, always reads '1' */ SFR(SCON1, 0xC0); SBIT(RI_1, 0xC0, 0); SBIT(TI_1, 0xC0, 1); SBIT(RB8_1, 0xC0, 2); SBIT(TB8_1, 0xC0, 3); SBIT(REN_1, 0xC0, 4); SBIT(SM2_1, 0xC0, 5); SBIT(SM1_1, 0xC0, 6); SBIT(SM0_1, 0xC0, 7); SFR(SBUF1, 0xC1); SFR(T2CON, 0xC8); SBIT(CPRL2, 0xC8, 0); SBIT(CT2, 0xC8, 1); SBIT(TR2, 0xC8, 2); SBIT(EXEN2, 0xC8, 3); SBIT(TCLK, 0xC8, 4); SBIT(RCLK, 0xC8, 5); SBIT(EXF2, 0xC8, 6); SBIT(TF2, 0xC8, 7); SFR(RCAP2L, 0xCA); SFR(RCAP2H, 0xCB); SFR(TL2, 0xCC); SFR(TH2, 0xCD); SFR(PSW, 0xD0); SBIT(P, 0xD0, 0); SBIT(F1, 0xD0, 1); SBIT(OV, 0xD0, 2); SBIT(RS0, 0xD0, 3); SBIT(RS1, 0xD0, 4); SBIT(F0, 0xD0, 5); SBIT(AC, 0xD0, 6); SBIT(CY, 0xD0, 7); SFR(EICON, 0xD8); /* Bit 0 read-only, always reads '0' */ /* Bit 1 read-only, always reads '0' */ /* Bit 2 read-only, always reads '0' */ SBIT(INT6, 0xD8, 3); SBIT(RESI, 0xD8, 4); SBIT(ERESI, 0xD8, 5); /* Bit 6 read-only, always reads '1' */ SBIT(SMOD1, 0xD8, 7); SFR(ACC, 0xE0); SFR(EIE, 0xE8); SBIT(EUSB, 0xE8, 0); SBIT(EI2C, 0xE8, 1); SBIT(EX4, 0xE8, 2); SBIT(EX5, 0xE8, 3); SBIT(EWDI, 0xE8, 4); /* Bit 5 read-only, always reads '1' */ /* Bit 6 read-only, always reads '1' */ /* Bit 7 read-only, always reads '1' */ SFR(B, 0xF0); SFR(EIP, 0xF8); SBIT(PUSB, 0xF8, 0); SBIT(PI2C, 0xF8, 1); SBIT(PX4, 0xF8, 2); SBIT(PX5, 0xF8, 3); SBIT(PX6, 0xF8, 4); /* Bit 5 read-only, always reads '1' */ /* Bit 6 read-only, always reads '1' */ /* Bit 7 read-only, always reads '1' */ /************************************************************************** ***************************** XDATA Registers **************************** ***************************************************************************/ /************************ Endpoint 0-7 Data Buffers ************************/ SFRX(OUT7BUF[64], 0x7B40); SFRX(IN7BUF[64], 0x7B80); SFRX(OUT6BUF[64], 0x7BC0); SFRX(IN6BUF[64], 0x7C00); SFRX(OUT5BUF[64], 0x7C40); SFRX(IN5BUF[64], 0x7C80); SFRX(OUT4BUF[64], 0x7CC0); SFRX(IN4BUF[64], 0x7D00); SFRX(OUT3BUF[64], 0x7D40); SFRX(IN3BUF[64], 0x7D80); SFRX(OUT2BUF[64], 0x7DC0); SFRX(IN2BUF[64], 0x7E00); SFRX(OUT1BUF[64], 0x7E40); SFRX(IN1BUF[64], 0x7E80); SFRX(OUT0BUF[64], 0x7EC0); SFRX(IN0BUF[64], 0x7F00); /* 0x7F40 - 0x7F5F reserved */ /**************************** Isochronous Data *****************************/ SFRX(OUT8DATA, 0x7F60); SFRX(OUT9DATA, 0x7F61); SFRX(OUT10DATA, 0x7F62); SFRX(OUT11DATA, 0x7F63); SFRX(OUT12DATA, 0x7F64); SFRX(OUT13DATA, 0x7F65); SFRX(OUT14DATA, 0x7F66); SFRX(OUT15DATA, 0x7F67); SFRX(IN8DATA, 0x7F68); SFRX(IN9DATA, 0x7F69); SFRX(IN10DATA, 0x7F6A); SFRX(IN11DATA, 0x7F6B); SFRX(IN12DATA, 0x7F6C); SFRX(IN13DATA, 0x7F6D); SFRX(IN14DATA, 0x7F6E); SFRX(IN15DATA, 0x7F6F); /************************* Isochronous Byte Counts *************************/ SFRX(OUT8BCH, 0x7F70); SFRX(OUT8BCL, 0x7F71); SFRX(OUT9BCH, 0x7F72); SFRX(OUT9BCL, 0x7F73); SFRX(OUT10BCH, 0x7F74); SFRX(OUT10BCL, 0x7F75); SFRX(OUT11BCH, 0x7F76); SFRX(OUT11BCL, 0x7F77); SFRX(OUT12BCH, 0x7F78); SFRX(OUT12BCL, 0x7F79); SFRX(OUT13BCH, 0x7F7A); SFRX(OUT13BCL, 0x7F7B); SFRX(OUT14BCH, 0x7F7C); SFRX(OUT14BCL, 0x7F7D); SFRX(OUT15BCH, 0x7F7E); SFRX(OUT16BCL, 0x7F7F); /****************************** CPU Registers ******************************/ SFRX(CPUCS, 0x7F92); #define RES8051 bmBit0 #define CLK24OE bmBit1 /* Bit 2 read-only, always reads '0' */ /* Bit 3 read-only, always reads '0' */ /* Bits 4...7: Chip Revision */ SFRX(PORTACFG, 0x7F93); #define T0OUT bmBit0 #define T1OUT bmBit1 #define OE bmBit2 #define CS bmBit3 #define FWR bmBit4 #define FRD bmBit5 #define RXD0OUT bmBit6 #define RXD1OUT bmBit7 SFRX(PORTBCFG, 0x7F94); #define T2 bmBit0 #define T2EX bmBit1 #define RXD1 bmBit2 #define TXD1 bmBit3 #define INT4 bmBit4 #define INT5 bmBit5 #define INT6 bmBit6 #define T2OUT bmBit7 SFRX(PORTCCFG, 0x7F95); #define RXD0 bmBit0 #define TXD0 bmBit1 #define INT0 bmBit2 #define INT1 bmBit3 #define T0 bmBit4 #define T1 bmBit5 #define WR bmBit6 #define RD bmBit7 /*********************** Input-Output Port Registers ***********************/ SFRX(OUTA, 0x7F96); #define OUTA0 bmBit0 #define OUTA1 bmBit1 #define OUTA2 bmBit2 #define OUTA3 bmBit3 #define OUTA4 bmBit4 #define OUTA5 bmBit5 #define OUTA6 bmBit6 #define OUTA7 bmBit7 SFRX(OUTB, 0x7F97); #define OUTB0 bmBit0 #define OUTB1 bmBit1 #define OUTB2 bmBit2 #define OUTB3 bmBit3 #define OUTB4 bmBit4 #define OUTB5 bmBit5 #define OUTB6 bmBit6 #define OUTB7 bmBit7 SFRX(OUTC, 0x7F98); #define OUTC0 bmBit0 #define OUTC1 bmBit1 #define OUTC2 bmBit2 #define OUTC3 bmBit3 #define OUTC4 bmBit4 #define OUTC5 bmBit5 #define OUTC6 bmBit6 #define OUTC7 bmBit7 SFRX(PINSA, 0x7F99); #define PINA0 bmBit0 #define PINA1 bmBit1 #define PINA2 bmBit2 #define PINA3 bmBit3 #define PINA4 bmBit4 #define PINA5 bmBit5 #define PINA6 bmBit6 #define PINA7 bmBit7 SFRX(PINSB, 0x7F9A); #define PINB0 bmBit0 #define PINB1 bmBit1 #define PINB2 bmBit2 #define PINB3 bmBit3 #define PINB4 bmBit4 #define PINB5 bmBit5 #define PINB6 bmBit6 #define PINB7 bmBit7 SFRX(PINSC, 0x7F9B); #define PINC0 bmBit0 #define PINC1 bmBit1 #define PINC2 bmBit2 #define PINC3 bmBit3 #define PINC4 bmBit4 #define PINC5 bmBit5 #define PINC6 bmBit6 #define PINC7 bmBit7 SFRX(OEA, 0x7F9C); #define OEA0 bmBit0 #define OEA1 bmBit1 #define OEA2 bmBit2 #define OEA3 bmBit3 #define OEA4 bmBit4 #define OEA5 bmBit5 #define OEA6 bmBit6 #define OEA7 bmBit7 SFRX(OEB, 0x7F9D); #define OEB0 bmBit0 #define OEB1 bmBit1 #define OEB2 bmBit2 #define OEB3 bmBit3 #define OEB4 bmBit4 #define OEB5 bmBit5 #define OEB6 bmBit6 #define OEB7 bmBit7 SFRX(OEC, 0x7F9E); #define OEC0 bmBit0 #define OEC1 bmBit1 #define OEC2 bmBit2 #define OEC3 bmBit3 #define OEC4 bmBit4 #define OEC5 bmBit5 #define OEC6 bmBit6 #define OEC7 bmBit7 /* 0x7F9F reserved */ /****************** Isochronous Control/Status Registers *******************/ SFRX(ISOERR, 0x7FA0); #define ISO8ERR bmBit0 #define ISO9ERR bmBit1 #define ISO10ERR bmBit2 #define ISO11ERR bmBit3 #define ISO12ERR bmBit4 #define ISO13ERR bmBit5 #define ISO14ERR bmBit6 #define ISO15ERR bmBit7 SFRX(ISOCTL, 0x7FA1); #define ISODISAB bmBit0 #define MBZ0 bmBit1 #define MBZ1 bmBit2 #define PPSTAT bmBit3 /* Bit 4 unused */ /* Bit 5 unused */ /* Bit 6 unused */ /* Bit 7 unused */ SFRX(ZBCOUT, 0x7FA2); #define EP8 bmBit0 #define EP9 bmBit1 #define EP10 bmBit2 #define EP11 bmBit3 #define EP12 bmBit4 #define EP13 bmBit5 #define EP14 bmBit6 #define EP15 bmBit7 /* 0x7FA3 reserved */ /* 0x7FA4 reserved */ /****************************** I2C Registers ******************************/ SFRX(I2CS, 0x7FA5); #define DONE bmBit0 #define ACK bmBit1 #define BERR bmBit2 #define ID0 bmBit3 #define ID1 bmBit4 #define LASTRD bmBit5 #define I2C_STOP bmBit6 #define I2C_START bmBit7 SFRX(I2DAT, 0x7FA6); /* 0x7FA7 reserved */ /******************************* Interrupts ********************************/ SFRX(IVEC, 0x7FA8); /* Bit 0 read-only, always reads '0' */ /* Bit 1 read-only, always reads '0' */ #define IV0 bmBit2 #define IV1 bmBit3 #define IV2 bmBit4 #define IV3 bmBit5 #define IV4 bmBit6 /* Bit 7 read-only, always reads '0' */ SFRX(IN07IRQ, 0x7FA9); #define IN0IR bmBit0 #define IN1IR bmBit1 #define IN2IR bmBit2 #define IN3IR bmBit3 #define IN4IR bmBit4 #define IN5IR bmBit5 #define IN6IR bmBit6 #define IN7IR bmBit7 SFRX(OUT07IRQ, 0x7FAA); #define OUT0IR bmBit0 #define OUT1IR bmBit1 #define OUT2IR bmBit2 #define OUT3IR bmBit3 #define OUT4IR bmBit4 #define OUT5IR bmBit5 #define OUT6IR bmBit6 #define OUT7IR bmBit7 SFRX(USBIRQ, 0x7FAB); #define SUDAVIR bmBit0 #define SOFIR bmBit1 #define SUTOKIR bmBit2 #define SUSPIR bmBit3 #define URESIR bmBit4 /* Bit 5 unused */ /* Bit 6 unused */ /* Bit 7 unused */ SFRX(IN07IEN, 0x7FAC); #define IN0IEN bmBit0 #define IN1IEN bmBit1 #define IN2IEN bmBit2 #define IN3IEN bmBit3 #define IN4IEN bmBit4 #define IN5IEN bmBit5 #define IN6IEN bmBit6 #define IN7IEN bmBit7 SFRX(OUT07IEN, 0x7FAD); #define OUT0IEN bmBit0 #define OUT1IEN bmBit1 #define OUT2IEN bmBit2 #define OUT3IEN bmBit3 #define OUT4IEN bmBit4 #define OUT5IEN bmBit5 #define OUT6IEN bmBit6 #define OUT7IEN bmBit7 SFRX(USBIEN, 0x7FAE); #define SUDAVIE bmBit0 #define SOFIE bmBit1 #define SUTOKIE bmBit2 #define SUSPIE bmBit3 #define URESIE bmBit4 /* Bit 5 unused */ /* Bit 6 unused */ /* Bit 7 unused */ SFRX(USBBAV, 0x7FAF); #define AVEN bmBit0 #define BPEN bmBit1 #define BPPULSE bmBit2 #define BREAK bmBit3 /* Bit 4 unused */ /* Bit 5 unused */ /* Bit 6 unused */ /* Bit 7 unused */ /* 0x7FB0 reserved */ /* 0x7FB1 reserved */ SFRX(BPADDRH, 0x7FB2); SFRX(BPADDRL, 0x7FB3); /****************************** Endpoints 0-7 ******************************/ SFRX(EP0CS, 0x7FB4); #define EP0STALL bmBit0 #define HSNAK bmBit1 #define IN0BSY bmBit2 #define OUT0BSY bmBit3 /* Bit 4 unused */ /* Bit 5 unused */ /* Bit 6 unused */ /* Bit 7 unused */ SFRX(IN0BC, 0x7FB5); SFRX(IN1CS, 0x7FB6); SFRX(IN1BC, 0x7FB7); SFRX(IN2CS, 0x7FB8); SFRX(IN2BC, 0x7FB9); SFRX(IN3CS, 0x7FBA); SFRX(IN3BC, 0x7FBB); SFRX(IN4CS, 0x7FBC); SFRX(IN4BC, 0x7FBD); SFRX(IN5CS, 0x7FBE); SFRX(IN5BC, 0x7FBF); SFRX(IN6CS, 0x7FC0); SFRX(IN6BC, 0x7FC1); SFRX(IN7CS, 0x7FC2); SFRX(IN7BC, 0x7FC3); /* 0x7FC4 reserved */ SFRX(OUT0BC, 0x7FC5); SFRX(OUT1CS, 0x7FC6); SFRX(OUT1BC, 0x7FC7); SFRX(OUT2CS, 0x7FC8); SFRX(OUT2BC, 0x7FC9); SFRX(OUT3CS, 0x7FCA); SFRX(OUT3BC, 0x7FCB); SFRX(OUT4CS, 0x7FCC); SFRX(OUT4BC, 0x7FCD); SFRX(OUT5CS, 0x7FCE); SFRX(OUT5BC, 0x7FCF); SFRX(OUT6CS, 0x7FD0); SFRX(OUT6BC, 0x7FD1); SFRX(OUT7CS, 0x7FD2); SFRX(OUT7BC, 0x7FD3); /* The INxSTALL, OUTxSTALL, INxBSY and OUTxBSY bits are the same for all * INxCS/OUTxCS registers. For better readability, we define them only once */ #define EPSTALL bmBit0 #define EPBSY bmBit1 /************************** Global USB Registers ***************************/ SFRX(SUDPTRH, 0x7FD4); SFRX(SUDPTRL, 0x7FD5); SFRX(USBCS, 0x7FD6); #define SIGRSUME bmBit0 #define RENUM bmBit1 #define DISCOE bmBit2 #define DISCON bmBit3 /* Bit 4 unused */ /* Bit 5 unused */ /* Bit 6 unused */ #define WAKESRC bmBit7 SFRX(TOGCTL, 0x7FD7); #define TOG_EP0 bmBit0 #define TOG_EP1 bmBit1 #define TOG_EP2 bmBit2 /* Bit 3 is read-only, always reads '0' */ #define TOG_IO bmBit4 #define TOG_R bmBit5 #define TOG_S bmBit6 #define TOG_Q bmBit7 SFRX(USBFRAMEL, 0x7FD8); SFRX(USBFRAMEH, 0x7FD9); /* 0x7FDA reserved */ SFRX(FNADDR, 0x7FDB); /* 0x7FDC reserved */ SFRX(USBPAIR, 0x7FDD); #define PR2IN bmBit0 #define PR4IN bmBit1 #define PR6IN bmBit2 #define PR2OUT bmBit3 #define PR4OUT bmBit4 #define PR6OUT bmBit5 /* Bit 6 unused */ #define ISOSEND0 bmBit7 SFRX(IN07VAL, 0x7FDE); /* Bit 0 is read-only, always reads '1' */ #define IN1VAL bmBit1 #define IN2VAL bmBit2 #define IN3VAL bmBit3 #define IN4VAL bmBit4 #define IN5VAL bmBit5 #define IN6VAL bmBit6 #define IN7VAL bmBit7 SFRX(OUT07VAL, 0x7FDF); /* Bit 0 is read-only, always reads '1' */ #define OUT1VAL bmBit1 #define OUT2VAL bmBit2 #define OUT3VAL bmBit3 #define OUT4VAL bmBit4 #define OUT5VAL bmBit5 #define OUT6VAL bmBit6 #define OUT7VAL bmBit7 SFRX(INISOVAL, 0x7FE0); #define IN8VAL bmBit0 #define IN9VAL bmBit1 #define IN10VAL bmBit2 #define IN11VAL bmBit3 #define IN12VAL bmBit4 #define IN13VAL bmBit5 #define IN14VAL bmBit6 #define IN15VAL bmBit7 SFRX(OUTISOVAL, 0x7FE1); #define OUT8VAL bmBit0 #define OUT9VAL bmBit1 #define OUT10VAL bmBit2 #define OUT11VAL bmBit3 #define OUT12VAL bmBit4 #define OUT13VAL bmBit5 #define OUT14VAL bmBit6 #define OUT15VAL bmBit7 SFRX(FASTXFR, 0x7FE2); #define WMOD0 bmBit0 #define WMOD1 bmBit1 #define WPOL bmBit2 #define RMOD0 bmBit3 #define RMOD1 bmBit4 #define RPOL bmBit5 #define FBLK bmBit6 #define FISO bmBit7 SFRX(AUTOPTRH, 0x7FE3); SFRX(AUTOPTRL, 0x7FE4); SFRX(AUTODATA, 0x7FE5); /* 0x7FE6 reserved */ /* 0x7FE7 reserved */ /******************************* Setup Data ********************************/ SFRX(SETUPDAT[8], 0x7FE8); /************************* Isochronous FIFO sizes **************************/ SFRX(OUT8ADDR, 0x7FF0); SFRX(OUT9ADDR, 0x7FF1); SFRX(OUT10ADDR, 0x7FF2); SFRX(OUT11ADDR, 0x7FF3); SFRX(OUT12ADDR, 0x7FF4); SFRX(OUT13ADDR, 0x7FF5); SFRX(OUT14ADDR, 0x7FF6); SFRX(OUT15ADDR, 0x7FF7); SFRX(IN8ADDR, 0x7FF8); SFRX(IN9ADDR, 0x7FF9); SFRX(IN10ADDR, 0x7FFA); SFRX(IN11ADDR, 0x7FFB); SFRX(IN12ADDR, 0x7FFC); SFRX(IN13ADDR, 0x7FFD); SFRX(IN14ADDR, 0x7FFE); SFRX(IN15ADDR, 0x7FFF); #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/jtag.h0000644000175000017500000000435512315575360017525 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __JTAG_H #define __JTAG_H #include #define NOP { __asm nop __endasm; } void jtag_scan_in(uint8_t out_offset, uint8_t in_offset); void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset); void jtag_scan_out(uint8_t out_offset); void jtag_slow_scan_out(uint8_t out_offset); void jtag_scan_io(uint8_t out_offset, uint8_t in_offset); void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset); void jtag_clock_tck(uint16_t count); void jtag_slow_clock_tck(uint16_t count); void jtag_clock_tms(uint8_t count, uint8_t sequence); void jtag_slow_clock_tms(uint8_t count, uint8_t sequence); uint16_t jtag_get_signals(void); void jtag_set_signals(uint8_t low, uint8_t high); void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out, uint8_t scan_io, uint8_t tck, uint8_t tms); #endif openocd-0.9.0/src/jtag/drivers/OpenULINK/include/main.h0000644000175000017500000000277012315575360017523 00000000000000/*************************************************************************** * Copyright (C) 2011 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __MAIN_H #define __MAIN_H void io_init(void); #endif openocd-0.9.0/src/jtag/drivers/ft2232.c0000644000175000017500000034645512516456302014375 00000000000000/*************************************************************************** * Copyright (C) 2009 by Øyvind Harboe * * Øyvind Harboe * * * * Copyright (C) 2009 by SoftPLC Corporation. http://softplc.com * * Dick Hollenbeck * * * * Copyright (C) 2004, 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * JTAG adapters based on the FT2232 full and high speed USB parts are * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters * are discrete, but development boards may integrate them as alternatives * to more capable (and expensive) third party JTAG pods. * * JTAG uses only one of the two communications channels ("MPSSE engines") * on these devices. Adapters based on FT4232 parts have four ports/channels * (A/B/C/D), instead of just two (A/B). * * Especially on development boards integrating one of these chips (as * opposed to discrete pods/dongles), the additional channels can be used * for a variety of purposes, but OpenOCD only uses one channel at a time. * * - As a USB-to-serial adapter for the target's console UART ... * which may be able to support ROM boot loaders that load initial * firmware images to flash (or SRAM). * * - On systems which support ARM's SWD in addition to JTAG, or instead * of it, that second port can be used for reading SWV/SWO trace data. * * - Additional JTAG links, e.g. to a CPLD or * FPGA. * * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG * request/response interactions involve round trips over the USB link. * A "smart" JTAG adapter has intelligence close to the scan chain, so it * can for example poll quickly for a status change (usually taking on the * order of microseconds not milliseconds) before beginning a queued * transaction which require the previous one to have completed. * * There are dozens of adapters of this type, differing in details which * this driver needs to understand. Those "layout" details are required * as part of FT2232 driver configuration. * * This code uses information contained in the MPSSE specification which was * found here: * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf * Hereafter this is called the "MPSSE Spec". * * The datasheet for the ftdichip.com's FT2232D part is here: * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf * * Also note the issue with code 0x4b (clock data to TMS) noted in * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html * which can affect longer JTAG state paths. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #if IS_CYGWIN == 1 #include #endif #include #if (BUILD_FT2232_FTD2XX == 1 && BUILD_FT2232_LIBFTDI == 1) #error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive" #elif (BUILD_FT2232_FTD2XX != 1 && BUILD_FT2232_LIBFTDI != 1) #error "BUILD_FT2232_FTD2XX || BUILD_FT2232_LIBFTDI must be chosen" #endif /* FT2232 access library includes */ #if BUILD_FT2232_FTD2XX == 1 #include #include "ftd2xx_common.h" enum ftdi_interface { INTERFACE_ANY = 0, INTERFACE_A = 1, INTERFACE_B = 2, INTERFACE_C = 3, INTERFACE_D = 4 }; #elif BUILD_FT2232_LIBFTDI == 1 #include #endif /* max TCK for the high speed devices 30000 kHz */ #define FTDI_x232H_MAX_TCK 30000 /* max TCK for the full speed devices 6000 kHz */ #define FTDI_2232C_MAX_TCK 6000 /* this speed value tells that RTCK is requested */ #define RTCK_SPEED -1 /* * On my Athlon XP 1900+ EHCI host with FT2232H JTAG dongle I get read timeout * errors with a retry count of 100. Increasing it solves the problem for me. * - Dimitar * * FIXME There's likely an issue with the usb_read_timeout from libftdi. * Fix that (libusb? kernel? libftdi? here?) and restore the retry count * to something sane. */ #define LIBFTDI_READ_RETRY_COUNT 2000 #ifndef BUILD_FT2232_HIGHSPEED #if BUILD_FT2232_FTD2XX == 1 enum { FT_DEVICE_2232H = 6, FT_DEVICE_4232H, FT_DEVICE_232H }; #elif BUILD_FT2232_LIBFTDI == 1 enum ftdi_chip_type { TYPE_2232H = 4, TYPE_4232H = 5, TYPE_232H = 6 }; #endif #endif /** * Send out \a num_cycles on the TCK line while the TAP(s) are in a * stable state. Calling code must ensure that current state is stable, * that verification is not done in here. * * @param num_cycles The number of clocks cycles to send. * @param cmd The command to send. * * @returns ERROR_OK on success, or ERROR_JTAG_QUEUE_FAILED on failure. */ static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd); static char *ft2232_device_desc_A; static char *ft2232_device_desc; static char *ft2232_serial; static uint8_t ft2232_latency = 2; static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK; static int ft2232_channel = INTERFACE_ANY; #define MAX_USB_IDS 8 /* vid = pid = 0 marks the end of the list */ static uint16_t ft2232_vid[MAX_USB_IDS + 1] = { 0x0403, 0 }; static uint16_t ft2232_pid[MAX_USB_IDS + 1] = { 0x6010, 0 }; struct ft2232_layout { const char *name; int (*init)(void); void (*reset)(int trst, int srst); void (*blink)(void); int channel; }; /* init procedures for supported layouts */ static int usbjtag_init(void); static int jtagkey_init(void); static int lm3s811_jtag_init(void); static int icdi_jtag_init(void); static int olimex_jtag_init(void); static int flyswatter1_init(void); static int flyswatter2_init(void); static int minimodule_init(void); static int turtle_init(void); static int comstick_init(void); static int stm32stick_init(void); static int axm0432_jtag_init(void); static int sheevaplug_init(void); static int icebear_jtag_init(void); static int cortino_jtag_init(void); static int signalyzer_init(void); static int signalyzer_h_init(void); static int ktlink_init(void); static int redbee_init(void); static int lisa_l_init(void); static int flossjtag_init(void); static int xds100v2_init(void); static int digilent_hs1_init(void); /* reset procedures for supported layouts */ static void ftx23_reset(int trst, int srst); static void jtagkey_reset(int trst, int srst); static void olimex_jtag_reset(int trst, int srst); static void flyswatter1_reset(int trst, int srst); static void flyswatter2_reset(int trst, int srst); static void minimodule_reset(int trst, int srst); static void turtle_reset(int trst, int srst); static void comstick_reset(int trst, int srst); static void stm32stick_reset(int trst, int srst); static void axm0432_jtag_reset(int trst, int srst); static void sheevaplug_reset(int trst, int srst); static void icebear_jtag_reset(int trst, int srst); static void signalyzer_h_reset(int trst, int srst); static void ktlink_reset(int trst, int srst); static void redbee_reset(int trst, int srst); static void xds100v2_reset(int trst, int srst); static void digilent_hs1_reset(int trst, int srst); /* blink procedures for layouts that support a blinking led */ static void olimex_jtag_blink(void); static void flyswatter1_jtag_blink(void); static void flyswatter2_jtag_blink(void); static void turtle_jtag_blink(void); static void signalyzer_h_blink(void); static void ktlink_blink(void); static void lisa_l_blink(void); static void flossjtag_blink(void); /* common transport support options */ /* static const char *jtag_and_swd[] = { "jtag", "swd", NULL }; */ static const struct ft2232_layout ft2232_layouts[] = { { .name = "usbjtag", .init = usbjtag_init, .reset = ftx23_reset, }, { .name = "jtagkey", .init = jtagkey_init, .reset = jtagkey_reset, }, { .name = "jtagkey_prototype_v1", .init = jtagkey_init, .reset = jtagkey_reset, }, { .name = "oocdlink", .init = jtagkey_init, .reset = jtagkey_reset, }, { .name = "signalyzer", .init = signalyzer_init, .reset = ftx23_reset, }, { .name = "evb_lm3s811", .init = lm3s811_jtag_init, .reset = ftx23_reset, }, { .name = "luminary_icdi", .init = icdi_jtag_init, .reset = ftx23_reset, }, { .name = "olimex-jtag", .init = olimex_jtag_init, .reset = olimex_jtag_reset, .blink = olimex_jtag_blink }, { .name = "flyswatter", .init = flyswatter1_init, .reset = flyswatter1_reset, .blink = flyswatter1_jtag_blink }, { .name = "flyswatter2", .init = flyswatter2_init, .reset = flyswatter2_reset, .blink = flyswatter2_jtag_blink }, { .name = "minimodule", .init = minimodule_init, .reset = minimodule_reset, }, { .name = "turtelizer2", .init = turtle_init, .reset = turtle_reset, .blink = turtle_jtag_blink }, { .name = "comstick", .init = comstick_init, .reset = comstick_reset, }, { .name = "stm32stick", .init = stm32stick_init, .reset = stm32stick_reset, }, { .name = "axm0432_jtag", .init = axm0432_jtag_init, .reset = axm0432_jtag_reset, }, { .name = "sheevaplug", .init = sheevaplug_init, .reset = sheevaplug_reset, }, { .name = "icebear", .init = icebear_jtag_init, .reset = icebear_jtag_reset, }, { .name = "cortino", .init = cortino_jtag_init, .reset = comstick_reset, }, { .name = "signalyzer-h", .init = signalyzer_h_init, .reset = signalyzer_h_reset, .blink = signalyzer_h_blink }, { .name = "ktlink", .init = ktlink_init, .reset = ktlink_reset, .blink = ktlink_blink }, { .name = "redbee-econotag", .init = redbee_init, .reset = redbee_reset, }, { .name = "redbee-usb", .init = redbee_init, .reset = redbee_reset, .channel = INTERFACE_B, }, { .name = "lisa-l", .init = lisa_l_init, .reset = ftx23_reset, .blink = lisa_l_blink, .channel = INTERFACE_B, }, { .name = "flossjtag", .init = flossjtag_init, .reset = ftx23_reset, .blink = flossjtag_blink, }, { .name = "xds100v2", .init = xds100v2_init, .reset = xds100v2_reset, }, { .name = "digilent-hs1", .init = digilent_hs1_init, .reset = digilent_hs1_reset, .channel = INTERFACE_A, }, { .name = NULL, /* END OF TABLE */ }, }; /* bitmask used to drive nTRST; usually a GPIOLx signal */ static uint8_t nTRST; static uint8_t nTRSTnOE; /* bitmask used to drive nSRST; usually a GPIOLx signal */ static uint8_t nSRST; static uint8_t nSRSTnOE; /** the layout being used with this debug session */ static const struct ft2232_layout *layout; /** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ static uint8_t low_output; /* note that direction bit == 1 means that signal is an output */ /** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ static uint8_t low_direction; /** default value bitmask for CBUS GPIOH(0..4) */ static uint8_t high_output; /** default direction bitmask for CBUS GPIOH(0..4) */ static uint8_t high_direction; #if BUILD_FT2232_FTD2XX == 1 static FT_HANDLE ftdih; static FT_DEVICE ftdi_device; #elif BUILD_FT2232_LIBFTDI == 1 static struct ftdi_context ftdic; static enum ftdi_chip_type ftdi_device; #endif static struct jtag_command *first_unsent; /* next command that has to be sent */ static int require_send; /* http://urjtag.wiki.sourceforge.net/Cable + FT2232 says: "There is a significant difference between libftdi and libftd2xx. The latter one allows to schedule up to 64*64 bytes of result data while libftdi fails with more than 4*64. As a consequence, the FT2232 driver is forced to perform around 16x more USB transactions for long command streams with TDO capture when running with libftdi." No idea how we get #define FT2232_BUFFER_SIZE 131072 a comment would have been nice. */ #if BUILD_FT2232_FTD2XX == 1 #define FT2232_BUFFER_READ_QUEUE_SIZE (64*64) #else #define FT2232_BUFFER_READ_QUEUE_SIZE (64*4) #endif #define FT2232_BUFFER_SIZE 131072 static uint8_t *ft2232_buffer; static int ft2232_buffer_size; static int ft2232_read_pointer; static int ft2232_expect_read; /** * Function buffer_write * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later. * @param val is the byte to send. */ static inline void buffer_write(uint8_t val) { assert(ft2232_buffer); assert((unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE); ft2232_buffer[ft2232_buffer_size++] = val; } /** * Function buffer_read * returns a byte from the byte buffer. */ static inline uint8_t buffer_read(void) { assert(ft2232_buffer); assert(ft2232_read_pointer < ft2232_buffer_size); return ft2232_buffer[ft2232_read_pointer++]; } /** * Clocks out \a bit_count bits on the TMS line, starting with the least * significant bit of tms_bits and progressing to more significant bits. * Rigorous state transition logging is done here via tap_set_state(). * * @param mpsse_cmd One of the MPSSE TMS oriented commands such as * 0x4b or 0x6b. See the MPSSE spec referenced above for their * functionality. The MPSSE command "Clock Data to TMS/CS Pin (no Read)" * is often used for this, 0x4b. * * @param tms_bits Holds the sequence of bits to send. * @param tms_count Tells how many bits in the sequence. * @param tdi_bit A single bit to pass on to TDI before the first TCK * cycle and held static for the duration of TMS clocking. * * See the MPSSE spec referenced above. */ static void clock_tms(uint8_t mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit) { uint8_t tms_byte; int i; int tms_ndx; /* bit index into tms_byte */ assert(tms_count > 0); DEBUG_JTAG_IO("mpsse cmd=%02x, tms_bits = 0x%08x, bit_count=%d", mpsse_cmd, tms_bits, tms_count); for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits >>= 1) { bool bit = tms_bits & 1; if (bit) tms_byte |= (1 << tms_ndx); /* always do state transitions in public view */ tap_set_state(tap_state_transition(tap_get_state(), bit)); /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero * also increment. */ ++tms_ndx; if (tms_ndx == 7 || i == tms_count-1) { buffer_write(mpsse_cmd); buffer_write(tms_ndx - 1); /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of * TMS/CS and is held static for the duration of TMS/CS clocking. */ buffer_write(tms_byte | (tdi_bit << 7)); } } } /** * Function get_tms_buffer_requirements * returns what clock_tms() will consume if called with * same \a bit_count. */ static inline int get_tms_buffer_requirements(int bit_count) { return ((bit_count + 6)/7) * 3; } /** * Function move_to_state * moves the TAP controller from the current state to a * \a goal_state through a path given by tap_get_tms_path(). State transition * logging is performed by delegation to clock_tms(). * * @param goal_state is the destination state for the move. */ static void move_to_state(tap_state_t goal_state) { tap_state_t start_state = tap_get_state(); /* goal_state is 1/2 of a tuple/pair of states which allow convenient * lookup of the required TMS pattern to move to this state from the start state. */ /* do the 2 lookups */ int tms_bits = tap_get_tms_path(start_state, goal_state); int tms_count = tap_get_tms_path_len(start_state, goal_state); DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state)); clock_tms(0x4b, tms_bits, tms_count, 0); } static int ft2232_write(uint8_t *buf, int size, uint32_t *bytes_written) { #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; DWORD dw_bytes_written = 0; status = FT_Write(ftdih, buf, size, &dw_bytes_written); if (status != FT_OK) { *bytes_written = dw_bytes_written; LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } else *bytes_written = dw_bytes_written; #elif BUILD_FT2232_LIBFTDI == 1 int retval = ftdi_write_data(&ftdic, buf, size); if (retval < 0) { *bytes_written = 0; LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } else *bytes_written = retval; #endif if (*bytes_written != (uint32_t)size) return ERROR_JTAG_DEVICE_ERROR; return ERROR_OK; } static int ft2232_read(uint8_t *buf, uint32_t size, uint32_t *bytes_read) { #if BUILD_FT2232_FTD2XX == 1 DWORD dw_bytes_read; FT_STATUS status; int timeout = 5; *bytes_read = 0; while ((*bytes_read < size) && timeout--) { status = FT_Read(ftdih, buf + *bytes_read, size - *bytes_read, &dw_bytes_read); if (status != FT_OK) { *bytes_read = 0; LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += dw_bytes_read; } #elif BUILD_FT2232_LIBFTDI == 1 int retval; int timeout = LIBFTDI_READ_RETRY_COUNT; *bytes_read = 0; while ((*bytes_read < size) && timeout--) { retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read); if (retval < 0) { *bytes_read = 0; LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += retval; } #endif if (*bytes_read < size) { LOG_ERROR("couldn't read enough bytes from " "FT2232 device (%i < %i)", (unsigned)*bytes_read, (unsigned)size); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static bool ft2232_device_is_highspeed(void) { #if BUILD_FT2232_FTD2XX == 1 return (ftdi_device == FT_DEVICE_2232H) || (ftdi_device == FT_DEVICE_4232H) #ifdef HAS_ENUM_FT232H || (ftdi_device == FT_DEVICE_232H) #endif ; #elif BUILD_FT2232_LIBFTDI == 1 return (ftdi_device == TYPE_2232H || ftdi_device == TYPE_4232H #ifdef HAS_ENUM_FT232H || ftdi_device == TYPE_232H #endif ); #endif } /* * Commands that only apply to the highspeed FTx232H devices (FT2232H, FT4232H, FT232H). * See chapter 6 in http://www.ftdichip.com/Documents/AppNotes/ * AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf */ static int ftx232h_adaptive_clocking(bool enable) { uint8_t buf = enable ? 0x96 : 0x97; LOG_DEBUG("%2.2x", buf); uint32_t bytes_written; int retval; retval = ft2232_write(&buf, sizeof(buf), &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write command to %s adaptive clocking" , enable ? "enable" : "disable"); return retval; } return ERROR_OK; } /** * Enable/disable the clk divide by 5 of the 60MHz master clock. * This result in a JTAG clock speed range of 91.553Hz-6MHz * respective 457.763Hz-30MHz. */ static int ftx232h_clk_divide_by_5(bool enable) { uint32_t bytes_written; uint8_t buf = enable ? 0x8b : 0x8a; if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't write command to %s clk divide by 5" , enable ? "enable" : "disable"); return ERROR_JTAG_INIT_FAILED; } ft2232_max_tck = enable ? FTDI_2232C_MAX_TCK : FTDI_x232H_MAX_TCK; LOG_INFO("max TCK change to: %u kHz", ft2232_max_tck); return ERROR_OK; } static int ft2232_speed(int speed) { uint8_t buf[3]; int retval; uint32_t bytes_written; retval = ERROR_OK; bool enable_adaptive_clocking = (RTCK_SPEED == speed); if (ft2232_device_is_highspeed()) retval = ftx232h_adaptive_clocking(enable_adaptive_clocking); else if (enable_adaptive_clocking) { LOG_ERROR("ft2232 device %lu does not support RTCK" , (long unsigned int)ftdi_device); return ERROR_FAIL; } if ((enable_adaptive_clocking) || (ERROR_OK != retval)) return retval; buf[0] = 0x86; /* command "set divisor" */ buf[1] = speed & 0xff; /* valueL (0 = 6MHz, 1 = 3MHz, 2 = 2.0MHz, ...*/ buf[2] = (speed >> 8) & 0xff; /* valueH */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); retval = ft2232_write(buf, sizeof(buf), &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't set FT2232 TCK speed"); return retval; } return ERROR_OK; } static int ft2232_speed_div(int speed, int *khz) { /* Take a look in the FT2232 manual, * AN2232C-01 Command Processor for * MPSSE and MCU Host Bus. Chapter 3.8 */ *khz = (RTCK_SPEED == speed) ? 0 : ft2232_max_tck / (1 + speed); return ERROR_OK; } static int ft2232_khz(int khz, int *jtag_speed) { if (khz == 0) { if (ft2232_device_is_highspeed()) { *jtag_speed = RTCK_SPEED; return ERROR_OK; } else { LOG_DEBUG("RCLK not supported"); return ERROR_FAIL; } } /* Take a look in the FT2232 manual, * AN2232C-01 Command Processor for * MPSSE and MCU Host Bus. Chapter 3.8 * * We will calc here with a multiplier * of 10 for better rounding later. */ /* Calc speed, (ft2232_max_tck / khz) - 1 * Use 65000 for better rounding */ *jtag_speed = ((ft2232_max_tck*10) / khz) - 10; /* Add 0.9 for rounding */ *jtag_speed += 9; /* Calc real speed */ *jtag_speed = *jtag_speed / 10; /* Check if speed is greater than 0 */ if (*jtag_speed < 0) *jtag_speed = 0; /* Check max value */ if (*jtag_speed > 0xFFFF) *jtag_speed = 0xFFFF; return ERROR_OK; } static void ft2232_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state)); exit(-1); } } static void ft2232_read_scan(enum scan_type type, uint8_t *buffer, int scan_size) { int num_bytes = (scan_size + 7) / 8; int bits_left = scan_size; int cur_byte = 0; while (num_bytes-- > 1) { buffer[cur_byte++] = buffer_read(); bits_left -= 8; } buffer[cur_byte] = 0x0; /* There is one more partial byte left from the clock data in/out instructions */ if (bits_left > 1) buffer[cur_byte] = buffer_read() >> 1; /* This shift depends on the length of the *clock data to tms instruction, insterted *at end of the scan, now fixed to a two *step transition in ft2232_add_scan */ buffer[cur_byte] = (buffer[cur_byte] | (((buffer_read()) << 1) & 0x80)) >> (8 - bits_left); } static void ft2232_debug_dump_buffer(void) { int i; char line[256]; char *line_p = line; for (i = 0; i < ft2232_buffer_size; i++) { line_p += snprintf(line_p, sizeof(line) - (line_p - line), "%2.2x ", ft2232_buffer[i]); if (i % 16 == 15) { LOG_DEBUG("%s", line); line_p = line; } } if (line_p != line) LOG_DEBUG("%s", line); } static int ft2232_send_and_recv(struct jtag_command *first, struct jtag_command *last) { struct jtag_command *cmd; uint8_t *buffer; int scan_size; enum scan_type type; int retval; uint32_t bytes_written = 0; uint32_t bytes_read = 0; #ifdef _DEBUG_USB_IO_ struct timeval start, inter, inter2, end; struct timeval d_inter, d_inter2, d_end; #endif #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("write buffer (size %i):", ft2232_buffer_size); ft2232_debug_dump_buffer(); #endif #ifdef _DEBUG_USB_IO_ gettimeofday(&start, NULL); #endif retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write MPSSE commands to FT2232"); return retval; } #ifdef _DEBUG_USB_IO_ gettimeofday(&inter, NULL); #endif if (ft2232_expect_read) { /* FIXME this "timeout" is never changed ... */ int timeout = LIBFTDI_READ_RETRY_COUNT; ft2232_buffer_size = 0; #ifdef _DEBUG_USB_IO_ gettimeofday(&inter2, NULL); #endif retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read); if (retval != ERROR_OK) { LOG_ERROR("couldn't read from FT2232"); return retval; } #ifdef _DEBUG_USB_IO_ gettimeofday(&end, NULL); timeval_subtract(&d_inter, &inter, &start); timeval_subtract(&d_inter2, &inter2, &start); timeval_subtract(&d_end, &end, &start); LOG_INFO("inter: %u.%06u, inter2: %u.%06u end: %u.%06u", (unsigned)d_inter.tv_sec, (unsigned)d_inter.tv_usec, (unsigned)d_inter2.tv_sec, (unsigned)d_inter2.tv_usec, (unsigned)d_end.tv_sec, (unsigned)d_end.tv_usec); #endif ft2232_buffer_size = bytes_read; if (ft2232_expect_read != ft2232_buffer_size) { LOG_ERROR("ft2232_expect_read (%i) != " "ft2232_buffer_size (%i) " "(%i retries)", ft2232_expect_read, ft2232_buffer_size, LIBFTDI_READ_RETRY_COUNT - timeout); ft2232_debug_dump_buffer(); exit(-1); } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("read buffer (%i retries): %i bytes", LIBFTDI_READ_RETRY_COUNT - timeout, ft2232_buffer_size); ft2232_debug_dump_buffer(); #endif } ft2232_expect_read = 0; ft2232_read_pointer = 0; /* return ERROR_OK, unless a jtag_read_buffer returns a failed check * that wasn't handled by a caller-provided error handler */ retval = ERROR_OK; cmd = first; while (cmd != last) { switch (cmd->type) { case JTAG_SCAN: type = jtag_scan_type(cmd->cmd.scan); if (type != SCAN_OUT) { scan_size = jtag_scan_size(cmd->cmd.scan); buffer = calloc(DIV_ROUND_UP(scan_size, 8), 1); ft2232_read_scan(type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; free(buffer); } break; default: break; } cmd = cmd->next; } ft2232_buffer_size = 0; return retval; } /** * Function ft2232_add_pathmove * moves the TAP controller from the current state to a new state through the * given path, where path is an array of tap_state_t's. * * @param path is an array of tap_stat_t which gives the states to traverse through * ending with the last state at path[num_states-1] * @param num_states is the count of state steps to move through */ static void ft2232_add_pathmove(tap_state_t *path, int num_states) { int state_count = 0; assert((unsigned) num_states <= 32u); /* tms_bits only holds 32 bits */ DEBUG_JTAG_IO("-"); /* this loop verifies that the path is legal and logs each state in the path */ while (num_states) { unsigned char tms_byte = 0; /* zero this on each MPSSE batch */ int bit_count = 0; int num_states_batch = num_states > 7 ? 7 : num_states; /* command "Clock Data to TMS/CS Pin (no Read)" */ buffer_write(0x4b); /* number of states remaining */ buffer_write(num_states_batch - 1); while (num_states_batch--) { /* either TMS=0 or TMS=1 must work ... */ if (tap_state_transition(tap_get_state(), false) == path[state_count]) buf_set_u32(&tms_byte, bit_count++, 1, 0x0); else if (tap_state_transition(tap_get_state(), true) == path[state_count]) buf_set_u32(&tms_byte, bit_count++, 1, 0x1); /* ... or else the caller goofed BADLY */ else { LOG_ERROR("BUG: %s -> %s isn't a valid " "TAP state transition", tap_state_name(tap_get_state()), tap_state_name(path[state_count])); exit(-1); } tap_set_state(path[state_count]); state_count++; num_states--; } buffer_write(tms_byte); } tap_set_end_state(tap_get_state()); } static void ft2232_add_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { int num_bytes = (scan_size + 7) / 8; int bits_left = scan_size; int cur_byte = 0; int last_bit; if (!ir_scan) { if (tap_get_state() != TAP_DRSHIFT) move_to_state(TAP_DRSHIFT); } else { if (tap_get_state() != TAP_IRSHIFT) move_to_state(TAP_IRSHIFT); } /* add command for complete bytes */ while (num_bytes > 1) { int thisrun_bytes; if (type == SCAN_IO) { /* Clock Data Bytes In and Out LSB First */ buffer_write(0x39); /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ } else if (type == SCAN_OUT) { /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x19); /* LOG_DEBUG("added TDI bytes (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x28); /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ } thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); num_bytes -= thisrun_bytes; buffer_write((uint8_t) (thisrun_bytes - 1)); buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); if (type != SCAN_IN) { /* add complete bytes */ while (thisrun_bytes-- > 0) { buffer_write(buffer[cur_byte++]); bits_left -= 8; } } else /* (type == SCAN_IN) */ bits_left -= 8 * (thisrun_bytes); } /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; else last_bit = 0; /* process remaining bits but the last one */ if (bits_left > 1) { if (type == SCAN_IO) { /* Clock Data Bits In and Out LSB First */ buffer_write(0x3b); /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ } else if (type == SCAN_OUT) { /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x1b); /* LOG_DEBUG("added TDI bits (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x2a); /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ } buffer_write(bits_left - 2); if (type != SCAN_IN) buffer_write(buffer[cur_byte]); } if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))) { if (type == SCAN_IO) { /* Clock Data Bits In and Out LSB First */ buffer_write(0x3b); /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ } else if (type == SCAN_OUT) { /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x1b); /* LOG_DEBUG("added TDI bits (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x2a); /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ } buffer_write(0x0); if (type != SCAN_IN) buffer_write(last_bit); } else { int tms_bits; int tms_count; uint8_t mpsse_cmd; /* move from Shift-IR/DR to end state */ if (type != SCAN_OUT) { /* We always go to the PAUSE state in two step at the end of an IN or IO *scan * This must be coordinated with the bit shifts in ft2232_read_scan */ tms_bits = 0x01; tms_count = 2; /* Clock Data to TMS/CS Pin with Read */ mpsse_cmd = 0x6b; } else { tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); /* Clock Data to TMS/CS Pin (no Read) */ mpsse_cmd = 0x4b; } DEBUG_JTAG_IO("finish %s", (type == SCAN_OUT) ? "without read" : "via PAUSE"); clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); } if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); } static int ft2232_large_scan(struct scan_command *cmd, enum scan_type type, uint8_t *buffer, int scan_size) { int num_bytes = (scan_size + 7) / 8; int bits_left = scan_size; int cur_byte = 0; int last_bit; uint8_t *receive_buffer = malloc(DIV_ROUND_UP(scan_size, 8)); uint8_t *receive_pointer = receive_buffer; uint32_t bytes_written; uint32_t bytes_read; int retval; int thisrun_read = 0; if (!receive_buffer) { LOG_ERROR("failed to allocate memory"); exit(-1); } if (cmd->ir_scan) { LOG_ERROR("BUG: large IR scans are not supported"); exit(-1); } if (tap_get_state() != TAP_DRSHIFT) move_to_state(TAP_DRSHIFT); retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write MPSSE commands to FT2232"); exit(-1); } LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, (int)bytes_written); ft2232_buffer_size = 0; /* add command for complete bytes */ while (num_bytes > 1) { int thisrun_bytes; if (type == SCAN_IO) { /* Clock Data Bytes In and Out LSB First */ buffer_write(0x39); /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ } else if (type == SCAN_OUT) { /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x19); /* LOG_DEBUG("added TDI bytes (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x28); /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ } thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); thisrun_read = thisrun_bytes; num_bytes -= thisrun_bytes; buffer_write((uint8_t) (thisrun_bytes - 1)); buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); if (type != SCAN_IN) { /* add complete bytes */ while (thisrun_bytes-- > 0) { buffer_write(buffer[cur_byte]); cur_byte++; bits_left -= 8; } } else /* (type == SCAN_IN) */ bits_left -= 8 * (thisrun_bytes); retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write MPSSE commands to FT2232"); exit(-1); } LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, (int)bytes_written); ft2232_buffer_size = 0; if (type != SCAN_OUT) { retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); if (retval != ERROR_OK) { LOG_ERROR("couldn't read from FT2232"); exit(-1); } LOG_DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, (int)bytes_read); receive_pointer += bytes_read; } } thisrun_read = 0; /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; else last_bit = 0; /* process remaining bits but the last one */ if (bits_left > 1) { if (type == SCAN_IO) { /* Clock Data Bits In and Out LSB First */ buffer_write(0x3b); /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ } else if (type == SCAN_OUT) { /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x1b); /* LOG_DEBUG("added TDI bits (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x2a); /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ } buffer_write(bits_left - 2); if (type != SCAN_IN) buffer_write(buffer[cur_byte]); if (type != SCAN_OUT) thisrun_read += 2; } if (tap_get_end_state() == TAP_DRSHIFT) { if (type == SCAN_IO) { /* Clock Data Bits In and Out LSB First */ buffer_write(0x3b); /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ } else if (type == SCAN_OUT) { /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ buffer_write(0x1b); /* LOG_DEBUG("added TDI bits (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ buffer_write(0x2a); /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ } buffer_write(0x0); buffer_write(last_bit); } else { int tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); uint8_t mpsse_cmd; /* move from Shift-IR/DR to end state */ if (type != SCAN_OUT) { /* Clock Data to TMS/CS Pin with Read */ mpsse_cmd = 0x6b; /* LOG_DEBUG("added TMS scan (read)"); */ } else { /* Clock Data to TMS/CS Pin (no Read) */ mpsse_cmd = 0x4b; /* LOG_DEBUG("added TMS scan (no read)"); */ } DEBUG_JTAG_IO("finish, %s", (type == SCAN_OUT) ? "no read" : "read"); clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); } if (type != SCAN_OUT) thisrun_read += 1; retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write MPSSE commands to FT2232"); exit(-1); } LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, (int)bytes_written); ft2232_buffer_size = 0; if (type != SCAN_OUT) { retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); if (retval != ERROR_OK) { LOG_ERROR("couldn't read from FT2232"); exit(-1); } LOG_DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, (int)bytes_read); } free(receive_buffer); return ERROR_OK; } static int ft2232_predict_scan_out(int scan_size, enum scan_type type) { int predicted_size = 3; int num_bytes = (scan_size - 1) / 8; if (tap_get_state() != TAP_DRSHIFT) predicted_size += get_tms_buffer_requirements( tap_get_tms_path_len(tap_get_state(), TAP_DRSHIFT)); if (type == SCAN_IN) { /* only from device to host */ /* complete bytes */ predicted_size += DIV_ROUND_UP(num_bytes, 65536) * 3; /* remaining bits - 1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 2 : 0; } else {/* host to device, or bidirectional * complete bytes */ predicted_size += num_bytes + DIV_ROUND_UP(num_bytes, 65536) * 3; /* remaining bits -1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 3 : 0; } return predicted_size; } static int ft2232_predict_scan_in(int scan_size, enum scan_type type) { int predicted_size = 0; if (type != SCAN_OUT) { /* complete bytes */ predicted_size += (DIV_ROUND_UP(scan_size, 8) > 1) ? (DIV_ROUND_UP(scan_size, 8) - 1) : 0; /* remaining bits - 1 */ predicted_size += ((scan_size - 1) % 8) ? 1 : 0; /* last bit (from TMS scan) */ predicted_size += 1; } /* LOG_DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */ return predicted_size; } /* semi-generic FT2232/FT4232 reset code */ static void ftx23_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) low_direction |= nTRSTnOE; /* switch to output pin (output is low) */ else low_output &= ~nTRST; /* switch output low */ } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal *and external pullup) */ else low_output |= nTRST; /* switch output high */ } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) low_output &= ~nSRST; /* switch output low */ else low_direction |= nSRSTnOE; /* switch to output pin (output is low) */ } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) low_output |= nSRST; /* switch output high */ else low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */ } /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); } static void jtagkey_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output &= ~nTRSTnOE; else high_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output |= nTRSTnOE; else high_output |= nTRST; } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output &= ~nSRST; else high_output &= ~nSRSTnOE; } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output |= nSRST; else high_output |= nSRSTnOE; } /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void olimex_jtag_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output &= ~nTRSTnOE; else high_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output |= nTRSTnOE; else high_output |= nTRST; } if (srst == 1) high_output |= nSRST; else if (srst == 0) high_output &= ~nSRST; /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void axm0432_jtag_reset(int trst, int srst) { if (trst == 1) { tap_set_state(TAP_RESET); high_output &= ~nTRST; } else if (trst == 0) high_output |= nTRST; if (srst == 1) high_output &= ~nSRST; else if (srst == 0) high_output |= nSRST; /* command "set data bits low byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void flyswatter_reset(int trst, int srst) { if (trst == 1) low_output &= ~nTRST; else if (trst == 0) low_output |= nTRST; if (srst == 1) low_output |= nSRST; else if (srst == 0) low_output &= ~nSRST; /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } static void flyswatter1_reset(int trst, int srst) { flyswatter_reset(trst, srst); } static void flyswatter2_reset(int trst, int srst) { flyswatter_reset(trst, !srst); } static void minimodule_reset(int trst, int srst) { if (srst == 1) low_output &= ~nSRST; else if (srst == 0) low_output |= nSRST; /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } static void turtle_reset(int trst, int srst) { if (trst == 1) LOG_ERROR("Can't assert TRST: the adapter lacks this signal"); if (srst == 1) low_output |= nSRST; else if (srst == 0) low_output &= ~nSRST; /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction); } static void comstick_reset(int trst, int srst) { if (trst == 1) high_output &= ~nTRST; else if (trst == 0) high_output |= nTRST; if (srst == 1) high_output &= ~nSRST; else if (srst == 0) high_output |= nSRST; /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void stm32stick_reset(int trst, int srst) { if (trst == 1) high_output &= ~nTRST; else if (trst == 0) high_output |= nTRST; if (srst == 1) low_output &= ~nSRST; else if (srst == 0) low_output |= nSRST; /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void sheevaplug_reset(int trst, int srst) { if (trst == 1) high_output &= ~nTRST; else if (trst == 0) high_output |= nTRST; if (srst == 1) high_output &= ~nSRSTnOE; else if (srst == 0) high_output |= nSRSTnOE; /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void redbee_reset(int trst, int srst) { if (trst == 1) { tap_set_state(TAP_RESET); high_output &= ~nTRST; } else if (trst == 0) high_output |= nTRST; if (srst == 1) high_output &= ~nSRST; else if (srst == 0) high_output |= nSRST; /* command "set data bits low byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " "high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void xds100v2_reset(int trst, int srst) { if (trst == 1) { tap_set_state(TAP_RESET); high_output &= ~nTRST; } else if (trst == 0) high_output |= nTRST; if (srst == 1) high_output |= nSRST; else if (srst == 0) high_output &= ~nSRST; /* command "set data bits low byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " "high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static int ft2232_execute_runtest(struct jtag_command *cmd) { int retval; int i; int predicted_size = 0; retval = ERROR_OK; DEBUG_JTAG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 0; if (tap_get_state() != TAP_IDLE) predicted_size += 3; predicted_size += 3 * DIV_ROUND_UP(cmd->cmd.runtest->num_cycles, 7); if (cmd->cmd.runtest->end_state != TAP_IDLE) predicted_size += 3; if (tap_get_end_state() != TAP_IDLE) predicted_size += 3; if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } if (tap_get_state() != TAP_IDLE) { move_to_state(TAP_IDLE); require_send = 1; } i = cmd->cmd.runtest->num_cycles; while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ /* command "Clock Data to TMS/CS Pin (no Read)" */ buffer_write(0x4b); /* scan 7 bits */ buffer_write((i > 7) ? 6 : (i - 1)); /* TMS data bits */ buffer_write(0x0); i -= (i > 7) ? 7 : i; /* LOG_DEBUG("added TMS scan (no read)"); */ } ft2232_end_state(cmd->cmd.runtest->end_state); if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); require_send = 1; DEBUG_JTAG_IO("runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(tap_get_end_state())); return retval; } static int ft2232_execute_statemove(struct jtag_command *cmd) { int predicted_size = 0; int retval = ERROR_OK; DEBUG_JTAG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state)); /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3; if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } ft2232_end_state(cmd->cmd.statemove->end_state); /* For TAP_RESET, ignore the current recorded state. It's often * wrong at server startup, and this transation is critical whenever * it's requested. */ if (tap_get_end_state() == TAP_RESET) { clock_tms(0x4b, 0xff, 5, 0); require_send = 1; /* shortest-path move to desired end state */ } else if (tap_get_state() != tap_get_end_state()) { move_to_state(tap_get_end_state()); require_send = 1; } return retval; } /** * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG * (or SWD) state machine. */ static int ft2232_execute_tms(struct jtag_command *cmd) { int retval = ERROR_OK; unsigned num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; unsigned count; DEBUG_JTAG_IO("TMS: %d bits", num_bits); /* only send the maximum buffer size that FT2232C can handle */ count = 3 * DIV_ROUND_UP(num_bits, 4); if (ft2232_buffer_size + 3*count + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } /* Shift out in batches of at most 6 bits; there's a report of an * FT2232 bug in this area, where shifting exactly 7 bits can make * problems with TMS signaling for the last clock cycle: * * http://developer.intra2net.com/mailarchive/html/ * libftdi/2009/msg00292.html * * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)" * * Note that pathmoves in JTAG are not often seven bits, so that * isn't a particularly likely situation outside of "special" * signaling such as switching between JTAG and SWD modes. */ while (num_bits) { if (num_bits <= 6) { buffer_write(0x4b); buffer_write(num_bits - 1); buffer_write(*bits & 0x3f); break; } /* Yes, this is lazy ... we COULD shift out more data * bits per operation, but doing it in nybbles is easy */ buffer_write(0x4b); buffer_write(3); buffer_write(*bits & 0xf); num_bits -= 4; count = (num_bits > 4) ? 4 : num_bits; buffer_write(0x4b); buffer_write(count - 1); buffer_write((*bits >> 4) & 0xf); num_bits -= count; bits++; } require_send = 1; return retval; } static int ft2232_execute_pathmove(struct jtag_command *cmd) { int predicted_size = 0; int retval = ERROR_OK; tap_state_t *path = cmd->cmd.pathmove->path; int num_states = cmd->cmd.pathmove->num_states; DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states, tap_state_name(tap_get_state()), tap_state_name(path[num_states-1])); /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3 * DIV_ROUND_UP(num_states, 7); if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } ft2232_add_pathmove(path, num_states); require_send = 1; return retval; } static int ft2232_execute_scan(struct jtag_command *cmd) { uint8_t *buffer; int scan_size; /* size of IR or DR scan */ int predicted_size = 0; int retval = ERROR_OK; enum scan_type type = jtag_scan_type(cmd->cmd.scan); DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", type); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); predicted_size = ft2232_predict_scan_out(scan_size, type); if ((predicted_size + 1) > FT2232_BUFFER_SIZE) { LOG_DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); /* unsent commands before this */ if (first_unsent != cmd) if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; /* current command */ ft2232_end_state(cmd->cmd.scan->end_state); ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size); require_send = 0; first_unsent = cmd->next; if (buffer) free(buffer); return retval; } else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { LOG_DEBUG( "ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd); if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */ ft2232_end_state(cmd->cmd.scan->end_state); ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); require_send = 1; if (buffer) free(buffer); DEBUG_JTAG_IO("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, tap_state_name(tap_get_end_state())); return retval; } static int ft2232_execute_reset(struct jtag_command *cmd) { int retval; int predicted_size = 0; retval = ERROR_OK; DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3; if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) tap_set_state(TAP_RESET); layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); require_send = 1; DEBUG_JTAG_IO("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); return retval; } static int ft2232_execute_sleep(struct jtag_command *cmd) { int retval; retval = ERROR_OK; DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us); if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd->next; jtag_sleep(cmd->cmd.sleep->us); DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s", cmd->cmd.sleep->us, tap_state_name(tap_get_state())); return retval; } static int ft2232_execute_stableclocks(struct jtag_command *cmd) { int retval; retval = ERROR_OK; /* this is only allowed while in a stable state. A check for a stable * state was done in jtag_add_clocks() */ if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; DEBUG_JTAG_IO("clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name(tap_get_state())); return retval; } static int ft2232_execute_command(struct jtag_command *cmd) { int retval; switch (cmd->type) { case JTAG_RESET: retval = ft2232_execute_reset(cmd); break; case JTAG_RUNTEST: retval = ft2232_execute_runtest(cmd); break; case JTAG_TLR_RESET: retval = ft2232_execute_statemove(cmd); break; case JTAG_PATHMOVE: retval = ft2232_execute_pathmove(cmd); break; case JTAG_SCAN: retval = ft2232_execute_scan(cmd); break; case JTAG_SLEEP: retval = ft2232_execute_sleep(cmd); break; case JTAG_STABLECLOCKS: retval = ft2232_execute_stableclocks(cmd); break; case JTAG_TMS: retval = ft2232_execute_tms(cmd); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); retval = ERROR_JTAG_QUEUE_FAILED; break; } return retval; } static int ft2232_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int retval; first_unsent = cmd; /* next command that has to be sent */ require_send = 0; /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check * that wasn't handled by a caller-provided error handler */ retval = ERROR_OK; ft2232_buffer_size = 0; ft2232_expect_read = 0; /* blink, if the current layout has that feature */ if (layout->blink) layout->blink(); while (cmd) { /* fill the write buffer with the desired command */ if (ft2232_execute_command(cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; /* Start reading input before FT2232 TX buffer fills up. * Sometimes this happens because we don't know the * length of the last command before we execute it. So * we simple inform the user. */ cmd = cmd->next; if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE) { if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1)) LOG_DEBUG("read buffer size looks too high %d/%d", ft2232_expect_read, (FT2232_BUFFER_READ_QUEUE_SIZE+1)); if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd; } } if (require_send > 0) if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; return retval; } #if BUILD_FT2232_FTD2XX == 1 static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int *try_more) { FT_STATUS status; DWORD deviceID; char SerialNumber[16]; char Description[64]; DWORD openex_flags = 0; char *openex_string = NULL; uint8_t latency_timer; if (layout == NULL) { LOG_WARNING("No ft2232 layout specified'"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", layout->name, vid, pid); #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ status = FT_SetVIDPID(vid, pid); if (status != FT_OK) LOG_WARNING("couldn't add %4.4x:%4.4x", vid, pid); #endif if (ft2232_device_desc && ft2232_serial) { LOG_WARNING( "can't open by device description and serial number, giving precedence to serial"); ft2232_device_desc = NULL; } if (ft2232_device_desc) { openex_string = ft2232_device_desc; openex_flags = FT_OPEN_BY_DESCRIPTION; } else if (ft2232_serial) { openex_string = ft2232_serial; openex_flags = FT_OPEN_BY_SERIAL_NUMBER; } else { LOG_ERROR("neither device description nor serial number specified"); LOG_ERROR( "please add \"ft2232_device_desc \" or \"ft2232_serial \" to your .cfg file"); return ERROR_JTAG_INIT_FAILED; } status = FT_OpenEx(openex_string, openex_flags, &ftdih); if (status != FT_OK) { /* under Win32, the FTD2XX driver appends an "A" to the end * of the description, if we tried by the desc, then * try by the alternate "A" description. */ if (openex_string == ft2232_device_desc) { /* Try the alternate method. */ openex_string = ft2232_device_desc_A; status = FT_OpenEx(openex_string, openex_flags, &ftdih); if (status == FT_OK) { /* yea, the "alternate" method worked! */ } else { /* drat, give the user a meaningfull message. * telling the use we tried *BOTH* methods. */ LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'", ft2232_device_desc, ft2232_device_desc_A); } } } if (status != FT_OK) { DWORD num_devices; if (more) { LOG_WARNING("unable to open ftdi device (trying more): %s", ftd2xx_status_string(status)); *try_more = 1; return ERROR_JTAG_INIT_FAILED; } LOG_ERROR("unable to open ftdi device: %s", ftd2xx_status_string(status)); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); uint32_t i; for (i = 0; i < num_devices; i++) desc_array[i] = malloc(64); desc_array[num_devices] = NULL; status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); if (status == FT_OK) { LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]); } for (i = 0; i < num_devices; i++) free(desc_array[i]); free(desc_array); } else LOG_ERROR("ListDevices: NONE"); return ERROR_JTAG_INIT_FAILED; } status = FT_SetLatencyTimer(ftdih, ft2232_latency); if (status != FT_OK) { LOG_ERROR("unable to set latency timer: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } status = FT_GetLatencyTimer(ftdih, &latency_timer); if (status != FT_OK) { /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer * so ignore errors if using this driver version */ DWORD dw_version; status = FT_GetDriverVersion(ftdih, &dw_version); LOG_ERROR("unable to get latency timer: %s", ftd2xx_status_string(status)); if ((status == FT_OK) && (dw_version == 0x10004)) { LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \ "with FT_GetLatencyTimer, upgrade to a newer version"); } else return ERROR_JTAG_INIT_FAILED; } else LOG_DEBUG("current latency timer: %i", latency_timer); status = FT_SetTimeouts(ftdih, 5000, 5000); if (status != FT_OK) { LOG_ERROR("unable to set timeouts: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } status = FT_SetBitMode(ftdih, 0x0b, 2); if (status != FT_OK) { LOG_ERROR("unable to enable bit i/o mode: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, SerialNumber, Description, NULL); if (status != FT_OK) { LOG_ERROR("unable to get FT_GetDeviceInfo: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } else { static const char *type_str[] = { "BM", "AM", "100AX", "UNKNOWN", "2232C", "232R", "2232H", "4232H", "232H" }; unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types) ? ftdi_device : FT_DEVICE_UNKNOWN; LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]); LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID); LOG_INFO("SerialNumber: %s", SerialNumber); LOG_INFO("Description: %s", Description); } return ERROR_OK; } static int ft2232_purge_ftd2xx(void) { FT_STATUS status; status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); if (status != FT_OK) { LOG_ERROR("error purging ftd2xx device: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } #endif /* BUILD_FT2232_FTD2XX == 1 */ #if BUILD_FT2232_LIBFTDI == 1 static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int *try_more, int channel) { uint8_t latency_timer; if (layout == NULL) { LOG_WARNING("No ft2232 layout specified'"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", layout->name, vid, pid); if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; /* default to INTERFACE_A */ if (channel == INTERFACE_ANY) channel = INTERFACE_A; if (ftdi_set_interface(&ftdic, channel) < 0) { LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } /* context, vendor id, product id */ if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, ft2232_serial) < 0) { if (more) LOG_WARNING("unable to open ftdi device (trying more): %s", ftdic.error_str); else LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str); *try_more = 1; return ERROR_JTAG_INIT_FAILED; } /* There is already a reset in ftdi_usb_open_desc, this should be redundant */ if (ftdi_usb_reset(&ftdic) < 0) { LOG_ERROR("unable to reset ftdi device"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) { LOG_ERROR("unable to set latency timer"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) { LOG_ERROR("unable to get latency timer"); return ERROR_JTAG_INIT_FAILED; } else LOG_DEBUG("current latency timer: %i", latency_timer); ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ ftdi_device = ftdic.type; static const char *type_str[] = { "AM", "BM", "2232C", "R", "2232H", "4232H", "232H", "Unknown" }; unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; unsigned type_index = ((unsigned)ftdi_device < no_of_known_types) ? ftdi_device : no_of_known_types; LOG_DEBUG("FTDI chip type: %i \"%s\"", (int)ftdi_device, type_str[type_index]); return ERROR_OK; } static int ft2232_purge_libftdi(void) { if (ftdi_usb_purge_buffers(&ftdic) < 0) { LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } #endif /* BUILD_FT2232_LIBFTDI == 1 */ static int ft2232_set_data_bits_low_byte(uint8_t value, uint8_t direction) { uint8_t buf[3]; uint32_t bytes_written; buf[0] = 0x80; /* command "set data bits low byte" */ buf[1] = value; /* value */ buf[2] = direction; /* direction */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize data bits low byte"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int ft2232_set_data_bits_high_byte(uint8_t value, uint8_t direction) { uint8_t buf[3]; uint32_t bytes_written; buf[0] = 0x82; /* command "set data bits high byte" */ buf[1] = value; /* value */ buf[2] = direction; /* direction */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize data bits high byte"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int ft2232_init(void) { uint8_t buf[1]; int retval; uint32_t bytes_written; LOG_WARNING("Using DEPRECATED interface driver 'ft2232'"); #if BUILD_FTDI LOG_INFO("Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/..."); #endif if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7) LOG_DEBUG("ft2232 interface using 7 step jtag state transitions"); else LOG_DEBUG("ft2232 interface using shortest path jtag state transitions"); if (layout == NULL) { LOG_WARNING("No ft2232 layout specified'"); return ERROR_JTAG_INIT_FAILED; } for (int i = 0; 1; i++) { /* * "more indicates that there are more IDs to try, so we should * not print an error for an ID mismatch (but for anything * else, we should). * * try_more indicates that the error code returned indicates an * ID mismatch (and nothing else) and that we should proceeed * with the next ID pair. */ int more = ft2232_vid[i + 1] || ft2232_pid[i + 1]; int try_more = 0; #if BUILD_FT2232_FTD2XX == 1 retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], more, &try_more); #elif BUILD_FT2232_LIBFTDI == 1 retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], more, &try_more, ft2232_channel); #endif if (retval >= 0) break; if (!more || !try_more) return retval; } ft2232_buffer_size = 0; ft2232_buffer = malloc(FT2232_BUFFER_SIZE); if (layout->init() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; if (ft2232_device_is_highspeed()) { #ifndef BUILD_FT2232_HIGHSPEED #if BUILD_FT2232_FTD2XX == 1 LOG_WARNING( "High Speed device found - You need a newer FTD2XX driver (version 2.04.16 or later)"); #elif BUILD_FT2232_LIBFTDI == 1 LOG_WARNING( "High Speed device found - You need a newer libftdi version (0.16 or later)"); #endif #endif /* make sure the legacy mode is disabled */ if (ftx232h_clk_divide_by_5(false) != ERROR_OK) return ERROR_JTAG_INIT_FAILED; } buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ retval = ft2232_write(buf, 1, &bytes_written); if (retval != ERROR_OK) { LOG_ERROR("couldn't write to FT2232 to disable loopback"); return ERROR_JTAG_INIT_FAILED; } #if BUILD_FT2232_FTD2XX == 1 return ft2232_purge_ftd2xx(); #elif BUILD_FT2232_LIBFTDI == 1 return ft2232_purge_libftdi(); #endif return ERROR_OK; } /** Updates defaults for DBUS signals: the four JTAG signals * (TCK, TDI, TDO, TMS) and * the four GPIOL signals. */ static inline void ftx232_dbus_init(void) { low_output = 0x08; low_direction = 0x0b; } /** Initializes DBUS signals: the four JTAG signals (TCK, TDI, TDO, TMS), * the four GPIOL signals. Initialization covers value and direction, * as customized for each layout. */ static int ftx232_dbus_write(void) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { low_direction &= ~nTRSTnOE; /* nTRST input */ low_output &= ~nTRST; /* nTRST = 0 */ } else { low_direction |= nTRSTnOE; /* nTRST output */ low_output |= nTRST; /* nTRST = 1 */ } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { low_direction |= nSRSTnOE; /* nSRST output */ low_output |= nSRST; /* nSRST = 1 */ } else { low_direction &= ~nSRSTnOE; /* nSRST input */ low_output &= ~nSRST; /* nSRST = 0 */ } /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 DBUS"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int usbjtag_init(void) { /* * NOTE: This is now _specific_ to the "usbjtag" layout. * Don't try cram any more layouts into this. */ ftx232_dbus_init(); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x40; nSRSTnOE = 0x40; return ftx232_dbus_write(); } static int lm3s811_jtag_init(void) { ftx232_dbus_init(); /* There are multiple revisions of LM3S811 eval boards: * - Rev B (and older?) boards have no SWO trace support. * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN; * they should use the "luminary_icdi" layout instead. */ nTRST = 0x0; nTRSTnOE = 0x00; nSRST = 0x20; nSRSTnOE = 0x20; low_output = 0x88; low_direction = 0x8b; return ftx232_dbus_write(); } static int icdi_jtag_init(void) { ftx232_dbus_init(); /* Most Luminary eval boards support SWO trace output, * and should use this "luminary_icdi" layout. * * ADBUS 0..3 are used for JTAG as usual. GPIOs are used * to switch between JTAG and SWD, or switch the ft2232 UART * on the second MPSSE channel/interface (BDBUS) * between (i) the stellaris UART (on Luminary boards) * or (ii) SWO trace data (generic). * * We come up in JTAG mode and may switch to SWD later (with * SWO/trace option if SWD is active). * * DBUS == GPIO-Lx * CBUS == GPIO-Hx */ #define ICDI_JTAG_EN (1 << 7) /* ADBUS 7 (a.k.a. DBGMOD) */ #define ICDI_DBG_ENn (1 << 6) /* ADBUS 6 */ #define ICDI_SRST (1 << 5) /* ADBUS 5 */ /* GPIOs on second channel/interface (UART) ... */ #define ICDI_SWO_EN (1 << 4) /* BDBUS 4 */ #define ICDI_TX_SWO (1 << 1) /* BDBUS 1 */ #define ICDI_VCP_RX (1 << 0) /* BDBUS 0 (to stellaris UART) */ nTRST = 0x0; nTRSTnOE = 0x00; nSRST = ICDI_SRST; nSRSTnOE = ICDI_SRST; low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn; low_output |= ICDI_JTAG_EN; low_output &= ~ICDI_DBG_ENn; return ftx232_dbus_write(); } static int signalyzer_init(void) { ftx232_dbus_init(); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x20; nSRSTnOE = 0x20; return ftx232_dbus_write(); } static int axm0432_jtag_init(void) { low_output = 0x08; low_direction = 0x2b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; } if (strcmp(layout->name, "axm0432_jtag") == 0) { nTRST = 0x08; nTRSTnOE = 0x0; /* No output enable for TRST*/ nSRST = 0x04; nSRSTnOE = 0x0; /* No output enable for SRST*/ } else { LOG_ERROR("BUG: axm0432_jtag_init called for non axm0432 layout"); exit(-1); } high_output = 0x0; high_direction = 0x0c; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) LOG_ERROR("can't set nTRSTOE to push-pull on the Dicarlo jtag"); else high_output |= nTRST; if (jtag_reset_config & RESET_SRST_PUSH_PULL) LOG_ERROR("can't set nSRST to push-pull on the Dicarlo jtag"); else high_output |= nSRST; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int redbee_init(void) { low_output = 0x08; low_direction = 0x2b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x08; nTRSTnOE = 0x0; /* No output enable for TRST*/ nSRST = 0x04; nSRSTnOE = 0x0; /* No output enable for SRST*/ high_output = 0x0; high_direction = 0x0c; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) LOG_ERROR("can't set nTRSTOE to push-pull on redbee"); else high_output |= nTRST; if (jtag_reset_config & RESET_SRST_PUSH_PULL) LOG_ERROR("can't set nSRST to push-pull on redbee"); else high_output |= nSRST; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int jtagkey_init(void) { low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; } if (strcmp(layout->name, "jtagkey") == 0) { nTRST = 0x01; nTRSTnOE = 0x4; nSRST = 0x02; nSRSTnOE = 0x08; } else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) || (strcmp(layout->name, "oocdlink") == 0)) { nTRST = 0x02; nTRSTnOE = 0x1; nSRST = 0x08; nSRSTnOE = 0x04; } else { LOG_ERROR("BUG: jtagkey_init called for non jtagkey layout"); exit(-1); } high_output = 0x0; high_direction = 0x0f; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { high_output |= nTRSTnOE; high_output &= ~nTRST; } else { high_output &= ~nTRSTnOE; high_output |= nTRST; } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { high_output &= ~nSRSTnOE; high_output |= nSRST; } else { high_output |= nSRSTnOE; high_output &= ~nSRST; } /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int olimex_jtag_init(void) { low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x01; nTRSTnOE = 0x4; nSRST = 0x02; nSRSTnOE = 0x00;/* no output enable for nSRST */ high_output = 0x0; high_direction = 0x0f; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { high_output |= nTRSTnOE; high_output &= ~nTRST; } else { high_output &= ~nTRSTnOE; high_output |= nTRST; } if (jtag_reset_config & RESET_SRST_PUSH_PULL) LOG_ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); else high_output &= ~nSRST; /* turn red LED on */ high_output |= 0x08; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int flyswatter_init(int rev) { low_output = 0x18; low_direction = 0x7b; if ((rev < 0) || (rev > 3)) { LOG_ERROR("bogus 'flyswatter' revision supplied (%i)", rev); return ERROR_JTAG_INIT_FAILED; } if (rev == 1) low_direction |= 1 << 7; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x10; nTRSTnOE = 0x0; /* not output enable for nTRST */ nSRST = 0x20; nSRSTnOE = 0x00; /* no output enable for nSRST */ high_output = 0x00; if (rev == 1) high_direction = 0x0c; else high_direction = 0x01; /* turn red LED3 on, LED2 off */ high_output |= 0x08; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int flyswatter1_init(void) { return flyswatter_init(1); } static int flyswatter2_init(void) { return flyswatter_init(2); } static int minimodule_init(void) { low_output = 0x18; /* check if srst should be 1 or 0 initially. (0x08) (flyswatter was * 0x18) */ low_direction = 0xfb; /* 0xfb; */ /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); return ERROR_JTAG_INIT_FAILED; } nSRST = 0x20; high_output = 0x00; high_direction = 0x05; /* turn red LED3 on, LED2 off */ /* high_output |= 0x08; */ /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int turtle_init(void) { low_output = 0x08; low_direction = 0x5b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; } nSRST = 0x40; high_output = 0x00; high_direction = 0x0C; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int comstick_init(void) { low_output = 0x08; low_direction = 0x0b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x01; nTRSTnOE = 0x00; /* no output enable for nTRST */ nSRST = 0x02; nSRSTnOE = 0x00; /* no output enable for nSRST */ high_output = 0x03; high_direction = 0x03; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int stm32stick_init(void) { low_output = 0x88; low_direction = 0x8b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x01; nTRSTnOE = 0x00; /* no output enable for nTRST */ nSRST = 0x80; nSRSTnOE = 0x00; /* no output enable for nSRST */ high_output = 0x01; high_direction = 0x03; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int sheevaplug_init(void) { low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; } nTRSTnOE = 0x1; nTRST = 0x02; nSRSTnOE = 0x4; nSRST = 0x08; high_output = 0x0; high_direction = 0x0f; /* nTRST is always push-pull */ high_output &= ~nTRSTnOE; high_output |= nTRST; /* nSRST is always open-drain */ high_output |= nSRSTnOE; high_output &= ~nSRST; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int cortino_jtag_init(void) { low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x01; nTRSTnOE = 0x00; /* no output enable for nTRST */ nSRST = 0x02; nSRSTnOE = 0x00; /* no output enable for nSRST */ high_output = 0x03; high_direction = 0x03; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int lisa_l_init(void) { ftx232_dbus_init(); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x40; nSRSTnOE = 0x40; high_output = 0x00; high_direction = 0x18; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout"); return ERROR_JTAG_INIT_FAILED; } return ftx232_dbus_write(); } static int flossjtag_init(void) { ftx232_dbus_init(); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x40; nSRSTnOE = 0x40; high_output = 0x00; high_direction = 0x18; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout"); return ERROR_JTAG_INIT_FAILED; } return ftx232_dbus_write(); } /* * The reference schematic from TI for the XDS100v2 has a CPLD on which opens * the door for a number of different configurations * * Known Implementations: * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf * * http://processors.wiki.ti.com/index.php/XDS100 (rev2) * * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST) * * ACBUS3 to transition 0->1 (OE rising edge) * * CPLD logic: Put the EMU0/1 pins in Hi-Z: * * ADBUS5/GPIOL1 = EMU_EN = 1 * * ADBUS6/GPIOL2 = EMU0 = 0 * * ACBUS4/SPARE0 = EMU1 = 0 * * CPLD logic: Disable loopback * * ACBUS6/SPARE2 = LOOPBACK = 0 */ #define XDS100_nEMU_EN (1<<5) #define XDS100_nEMU0 (1<<6) #define XDS100_PWR_RST (1<<3) #define XDS100_nEMU1 (1<<4) #define XDS100_LOOPBACK (1<<6) static int xds100v2_init(void) { /* These are in the lower byte */ nTRST = 0x10; nTRSTnOE = 0x10; /* These aren't actually used on 14 pin connectors * These are in the upper byte */ nSRST = 0x01; nSRSTnOE = 0x01; low_output = 0x08 | nTRST | XDS100_nEMU_EN; low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0; if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout"); return ERROR_JTAG_INIT_FAILED; } high_output = 0; high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout"); return ERROR_JTAG_INIT_FAILED; } high_output |= XDS100_PWR_RST; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static void olimex_jtag_blink(void) { /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 * ACBUS3 is bit 3 of the GPIOH port */ high_output ^= 0x08; buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); } static void flyswatter_jtag_blink(unsigned char led) { buffer_write(0x82); buffer_write(high_output ^ led); buffer_write(high_direction); } static void flyswatter1_jtag_blink(void) { /* * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3 */ flyswatter_jtag_blink(0xc); } static void flyswatter2_jtag_blink(void) { /* * Flyswatter2 only has one LED connected to ACBUS2 */ flyswatter_jtag_blink(0x4); } static void turtle_jtag_blink(void) { /* * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 */ if (high_output & 0x08) high_output = 0x04; else high_output = 0x08; buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); } static void lisa_l_blink(void) { /* * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4 */ if (high_output & 0x10) high_output = 0x08; else high_output = 0x10; buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); } static void flossjtag_blink(void) { /* * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4 */ if (high_output & 0x10) high_output = 0x08; else high_output = 0x10; buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); } static int ft2232_quit(void) { #if BUILD_FT2232_FTD2XX == 1 FT_Close(ftdih); #elif BUILD_FT2232_LIBFTDI == 1 ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); #endif free(ft2232_buffer); ft2232_buffer = NULL; return ERROR_OK; } COMMAND_HANDLER(ft2232_handle_device_desc_command) { char *cp; char buf[200]; if (CMD_ARGC == 1) { ft2232_device_desc = strdup(CMD_ARGV[0]); cp = strchr(ft2232_device_desc, 0); /* under Win32, the FTD2XX driver appends an "A" to the end * of the description, this examines the given desc * and creates the 'missing' _A or non_A variable. */ if ((cp[-1] == 'A') && (cp[-2] == ' ')) { /* it was, so make this the "A" version. */ ft2232_device_desc_A = ft2232_device_desc; /* and *CREATE* the non-A version. */ strcpy(buf, ft2232_device_desc); cp = strchr(buf, 0); cp[-2] = 0; ft2232_device_desc = strdup(buf); } else { /* A not defined * so create it */ sprintf(buf, "%s A", ft2232_device_desc); ft2232_device_desc_A = strdup(buf); } } else LOG_ERROR("expected exactly one argument to ft2232_device_desc "); return ERROR_OK; } COMMAND_HANDLER(ft2232_handle_serial_command) { if (CMD_ARGC == 1) ft2232_serial = strdup(CMD_ARGV[0]); else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(ft2232_handle_layout_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; if (layout) { LOG_ERROR("already specified ft2232_layout %s", layout->name); return (strcmp(layout->name, CMD_ARGV[0]) != 0) ? ERROR_FAIL : ERROR_OK; } for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) { if (strcmp(l->name, CMD_ARGV[0]) == 0) { layout = l; ft2232_channel = l->channel; return ERROR_OK; } } LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]); return ERROR_FAIL; } COMMAND_HANDLER(ft2232_handle_vid_pid_command) { if (CMD_ARGC > MAX_USB_IDS * 2) { LOG_WARNING("ignoring extra IDs in ft2232_vid_pid " "(maximum is %d pairs)", MAX_USB_IDS); CMD_ARGC = MAX_USB_IDS * 2; } if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { LOG_WARNING("incomplete ft2232_vid_pid configuration directive"); if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* remove the incomplete trailing id */ CMD_ARGC -= 1; } unsigned i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ft2232_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ft2232_pid[i >> 1]); } /* * Explicitly terminate, in case there are multiples instances of * ft2232_vid_pid. */ ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; return ERROR_OK; } COMMAND_HANDLER(ft2232_handle_latency_command) { if (CMD_ARGC == 1) ft2232_latency = atoi(CMD_ARGV[0]); else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(ft2232_handle_channel_command) { if (CMD_ARGC == 1) { ft2232_channel = atoi(CMD_ARGV[0]); if (ft2232_channel < 0 || ft2232_channel > 4) LOG_ERROR("ft2232_channel must be in the 0 to 4 range"); } else LOG_ERROR("expected exactly one argument to ft2232_channel "); return ERROR_OK; } static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd) { int retval = 0; /* 7 bits of either ones or zeros. */ uint8_t tms = (tap_get_state() == TAP_RESET ? 0x7F : 0x00); while (num_cycles > 0) { /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles * at most 7 bits per invocation. Here we invoke it potentially * several times. */ int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd; } /* there are no state transitions in this code, so omit state tracking */ /* command "Clock Data to TMS/CS Pin (no Read)" */ buffer_write(0x4b); /* scan 7 bit */ buffer_write(bitcount_per_command - 1); /* TMS data bits are either all zeros or ones to stay in the current stable state */ buffer_write(tms); require_send = 1; num_cycles -= bitcount_per_command; } return retval; } /* --------------------------------------------------------------------- * Support for IceBear JTAG adapter from Section5: * http://section5.ch/icebear * * Author: Sten, debian@sansys-electronic.com */ /* Icebear pin layout * * ADBUS5 (nEMU) nSRST | 2 1| GND (10k->VCC) * GND GND | 4 3| n.c. * ADBUS3 TMS | 6 5| ADBUS6 VCC * ADBUS0 TCK | 8 7| ADBUS7 (GND) * ADBUS4 nTRST |10 9| ACBUS0 (GND) * ADBUS1 TDI |12 11| ACBUS1 (GND) * ADBUS2 TDO |14 13| GND GND * * ADBUS0 O L TCK ACBUS0 GND * ADBUS1 O L TDI ACBUS1 GND * ADBUS2 I TDO ACBUS2 n.c. * ADBUS3 O H TMS ACBUS3 n.c. * ADBUS4 O H nTRST * ADBUS5 O H nSRST * ADBUS6 - VCC * ADBUS7 - GND */ static int icebear_jtag_init(void) { low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */ low_output = 0x08; /* high: TMS; low: TCK TDI */ nTRST = 0x10; nSRST = 0x20; enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) low_direction &= ~nTRST; /* nTRST high impedance */ else { low_direction |= nTRST; low_output |= nTRST; } low_direction |= nSRST; low_output |= nSRST; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); return ERROR_JTAG_INIT_FAILED; } high_output = 0x0; high_direction = 0x00; /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static void icebear_jtag_reset(int trst, int srst) { if (trst == 1) { low_direction |= nTRST; low_output &= ~nTRST; } else if (trst == 0) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) low_direction &= ~nTRST; else low_output |= nTRST; } if (srst == 1) low_output &= ~nSRST; else if (srst == 0) low_output |= nSRST; /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } /* --------------------------------------------------------------------- * Support for Signalyzer H2 and Signalyzer H4 * JTAG adapter from Xverve Technologies Inc. * http://www.signalyzer.com or http://www.xverve.com * * Author: Oleg Seiljus, oleg@signalyzer.com */ static unsigned char signalyzer_h_side; static unsigned int signalyzer_h_adapter_type; static int signalyzer_h_ctrl_write(int address, unsigned short value); #if BUILD_FT2232_FTD2XX == 1 static int signalyzer_h_ctrl_read(int address, unsigned short *value); #endif #define SIGNALYZER_COMMAND_ADDR 128 #define SIGNALYZER_DATA_BUFFER_ADDR 129 #define SIGNALYZER_COMMAND_VERSION 0x41 #define SIGNALYZER_COMMAND_RESET 0x42 #define SIGNALYZER_COMMAND_POWERCONTROL_GET 0x50 #define SIGNALYZER_COMMAND_POWERCONTROL_SET 0x51 #define SIGNALYZER_COMMAND_PWM_SET 0x52 #define SIGNALYZER_COMMAND_LED_SET 0x53 #define SIGNALYZER_COMMAND_ADC 0x54 #define SIGNALYZER_COMMAND_GPIO_STATE 0x55 #define SIGNALYZER_COMMAND_GPIO_MODE 0x56 #define SIGNALYZER_COMMAND_GPIO_PORT 0x57 #define SIGNALYZER_COMMAND_I2C 0x58 #define SIGNALYZER_CHAN_A 1 #define SIGNALYZER_CHAN_B 2 /* LEDS use channel C */ #define SIGNALYZER_CHAN_C 4 #define SIGNALYZER_LED_GREEN 1 #define SIGNALYZER_LED_RED 2 #define SIGNALYZER_MODULE_TYPE_EM_LT16_A 0x0301 #define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG 0x0302 #define SIGNALYZER_MODULE_TYPE_EM_JTAG 0x0303 #define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P 0x0304 #define SIGNALYZER_MODULE_TYPE_EM_JTAG_P 0x0305 static int signalyzer_h_ctrl_write(int address, unsigned short value) { #if BUILD_FT2232_FTD2XX == 1 return FT_WriteEE(ftdih, address, value); #elif BUILD_FT2232_LIBFTDI == 1 return 0; #endif } #if BUILD_FT2232_FTD2XX == 1 static int signalyzer_h_ctrl_read(int address, unsigned short *value) { return FT_ReadEE(ftdih, address, value); } #endif static int signalyzer_h_led_set(unsigned char channel, unsigned char led, int on_time_ms, int off_time_ms, unsigned char cycles) { unsigned char on_time; unsigned char off_time; if (on_time_ms < 0xFFFF) on_time = (unsigned char)(on_time_ms / 62); else on_time = 0xFF; off_time = (unsigned char)(off_time_ms / 62); #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(channel << 8) | led)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), ((uint32_t)(on_time << 8) | off_time)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), ((uint32_t)cycles)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_LED_SET); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; #elif BUILD_FT2232_LIBFTDI == 1 int retval; retval = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(channel << 8) | led)); if (retval < 0) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), ((uint32_t)(on_time << 8) | off_time)); if (retval < 0) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), (uint32_t)cycles); if (retval < 0) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } retval = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_LED_SET); if (retval < 0) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; #endif } static int signalyzer_h_init(void) { #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; int i; #endif char *end_of_desc; uint16_t read_buf[12] = { 0 }; /* turn on center green led */ signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN, 0xFFFF, 0x00, 0x00); /* determine what channel config wants to open * TODO: change me... current implementation is made to work * with openocd description parsing. */ end_of_desc = strrchr(ft2232_device_desc, 0x00); if (end_of_desc) { signalyzer_h_side = *(end_of_desc - 1); if (signalyzer_h_side == 'B') signalyzer_h_side = SIGNALYZER_CHAN_B; else signalyzer_h_side = SIGNALYZER_CHAN_A; } else { LOG_ERROR("No Channel was specified"); return ERROR_FAIL; } signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_GREEN, 1000, 1000, 0xFF); #if BUILD_FT2232_FTD2XX == 1 /* read signalyzer versionining information */ status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_VERSION); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } for (i = 0; i < 10; i++) { status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i]); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } } LOG_INFO("Signalyzer: ID info: { %.4x %.4x %.4x %.4x %.4x %.4x %.4x }", read_buf[0], read_buf[1], read_buf[2], read_buf[3], read_buf[4], read_buf[5], read_buf[6]); /* set gpio register */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0404); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } /* read adapter type information */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(signalyzer_h_side << 8) | 0x01)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write( (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write( (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_I2C); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } usleep(100000); status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR, &read_buf[0]); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if (read_buf[0] != 0x0498) signalyzer_h_adapter_type = 0x0000; else { for (i = 0; i < 4; i++) { status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i]); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } } signalyzer_h_adapter_type = read_buf[0]; } #elif BUILD_FT2232_LIBFTDI == 1 /* currently libftdi does not allow reading individual eeprom * locations, therefore adapter type cannot be detected. * override with most common type */ signalyzer_h_adapter_type = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG; #endif enum reset_types jtag_reset_config = jtag_get_reset_config(); /* ADAPTOR: EM_LT16_A */ if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { LOG_INFO("Signalyzer: EM-LT (16-channel level translator) " "detected. (HW: %2x).", (read_buf[1] >> 8)); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x20; nSRSTnOE = 0x20; low_output = 0x08; low_direction = 0x1b; high_output = 0x0; high_direction = 0x0; if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { low_direction &= ~nTRSTnOE; /* nTRST input */ low_output &= ~nTRST; /* nTRST = 0 */ } else { low_direction |= nTRSTnOE; /* nTRST output */ low_output |= nTRST; /* nTRST = 1 */ } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { low_direction |= nSRSTnOE; /* nSRST output */ low_output |= nSRST; /* nSRST = 1 */ } else { low_direction &= ~nSRSTnOE; /* nSRST input */ low_output &= ~nSRST; /* nSRST = 0 */ } #if BUILD_FT2232_FTD2XX == 1 /* enable power to the module */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(signalyzer_h_side << 8) | 0x01)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_POWERCONTROL_SET); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } /* set gpio mode register */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } /* set gpio register */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } #endif } /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) LOG_INFO("Signalyzer: EM-ARM-JTAG (ARM JTAG) " "detected. (HW: %2x).", (read_buf[1] >> 8)); else if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) LOG_INFO("Signalyzer: EM-ARM-JTAG_P " "(ARM JTAG with PSU) detected. (HW: %2x).", (read_buf[1] >> 8)); else if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) LOG_INFO("Signalyzer: EM-JTAG (Generic JTAG) " "detected. (HW: %2x).", (read_buf[1] >> 8)); else if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P) LOG_INFO("Signalyzer: EM-JTAG-P " "(Generic JTAG with PSU) detected. (HW: %2x).", (read_buf[1] >> 8)); nTRST = 0x02; nTRSTnOE = 0x04; nSRST = 0x08; nSRSTnOE = 0x10; low_output = 0x08; low_direction = 0x1b; high_output = 0x0; high_direction = 0x1f; if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { high_output |= nTRSTnOE; high_output &= ~nTRST; } else { high_output &= ~nTRSTnOE; high_output |= nTRST; } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { high_output &= ~nSRSTnOE; high_output |= nSRST; } else { high_output |= nSRSTnOE; high_output &= ~nSRST; } #if BUILD_FT2232_FTD2XX == 1 /* enable power to the module */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(signalyzer_h_side << 8) | 0x01)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_POWERCONTROL_SET); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } /* set gpio mode register (IO_16 and IO_17 set as analog * inputs, other is gpio) */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } /* set gpio register (all inputs, for -P modules, * PSU will be turned off) */ status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8)); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE); if (status != FT_OK) { LOG_ERROR("signalyzer_h_ctrl_write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } #endif } else if (signalyzer_h_adapter_type == 0x0000) { LOG_INFO("Signalyzer: No external modules were detected."); nTRST = 0x10; nTRSTnOE = 0x10; nSRST = 0x20; nSRSTnOE = 0x20; low_output = 0x08; low_direction = 0x1b; high_output = 0x0; high_direction = 0x0; if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { low_direction &= ~nTRSTnOE; /* nTRST input */ low_output &= ~nTRST; /* nTRST = 0 */ } else { low_direction |= nTRSTnOE; /* nTRST output */ low_output |= nTRST; /* nTRST = 1 */ } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { low_direction |= nSRSTnOE; /* nSRST output */ low_output |= nSRST; /* nSRST = 1 */ } else { low_direction &= ~nSRSTnOE; /* nSRST input */ low_output &= ~nSRST; /* nSRST = 0 */ } } else { LOG_ERROR("Unknown module type is detected: %.4x", signalyzer_h_adapter_type); return ERROR_JTAG_DEVICE_ERROR; } /* initialize low byte of controller for jtag operation */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; } #if BUILD_FT2232_FTD2XX == 1 if (ftdi_device == FT_DEVICE_2232H) { /* initialize high byte of controller for jtag operation */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; } } #elif BUILD_FT2232_LIBFTDI == 1 if (ftdi_device == TYPE_2232H) { /* initialize high byte of controller for jtag operation */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; } } #endif return ERROR_OK; } static void signalyzer_h_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); /* ADAPTOR: EM_LT16_A */ if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) /* switch to output pin (output is low) */ low_direction |= nTRSTnOE; else /* switch output low */ low_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) /* switch to input pin (high-Z + internal * and external pullup) */ low_direction &= ~nTRSTnOE; else /* switch output high */ low_output |= nTRST; } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) /* switch output low */ low_output &= ~nSRST; else /* switch to output pin (output is low) */ low_direction |= nSRSTnOE; } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) /* switch output high */ low_output |= nSRST; else /* switch to input pin (high-Z) */ low_direction &= ~nSRSTnOE; } /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " "low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output &= ~nTRSTnOE; else high_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output |= nTRSTnOE; else high_output |= nTRST; } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output &= ~nSRST; else high_output &= ~nSRSTnOE; } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output |= nSRST; else high_output |= nSRSTnOE; } /* command "set data bits high byte" */ buffer_write(0x82); buffer_write(high_output); buffer_write(high_direction); LOG_INFO("trst: %i, srst: %i, high_output: 0x%2.2x, " "high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } else if (signalyzer_h_adapter_type == 0x0000) { if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) /* switch to output pin (output is low) */ low_direction |= nTRSTnOE; else /* switch output low */ low_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) /* switch to input pin (high-Z + internal * and external pullup) */ low_direction &= ~nTRSTnOE; else /* switch output high */ low_output |= nTRST; } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) /* switch output low */ low_output &= ~nSRST; else /* switch to output pin (output is low) */ low_direction |= nSRSTnOE; } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) /* switch output high */ low_output |= nSRST; else /* switch to input pin (high-Z) */ low_direction &= ~nSRSTnOE; } /* command "set data bits low byte" */ buffer_write(0x80); buffer_write(low_output); buffer_write(low_direction); LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " "low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } } static void signalyzer_h_blink(void) { signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_RED, 100, 0, 1); } /******************************************************************** * Support for KT-LINK * JTAG adapter from KRISTECH * http://www.kristech.eu *******************************************************************/ static int ktlink_init(void) { uint8_t swd_en = 0x20; /* 0x20 SWD disable, 0x00 SWD enable (ADBUS5) */ low_output = 0x08 | swd_en; /* value; TMS=1,TCK=0,TDI=0,SWD=swd_en */ low_direction = 0x3B; /* out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in */ /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; } nTRST = 0x01; nSRST = 0x02; nTRSTnOE = 0x04; nSRSTnOE = 0x08; high_output = 0x80; /* turn LED on */ high_direction = 0xFF; /* all outputs */ enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { high_output |= nTRSTnOE; high_output &= ~nTRST; } else { high_output &= ~nTRSTnOE; high_output |= nTRST; } if (jtag_reset_config & RESET_SRST_PUSH_PULL) { high_output &= ~nSRSTnOE; high_output |= nSRST; } else { high_output |= nSRSTnOE; high_output &= ~nSRST; } /* initialize high byte for jtag */ if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static void ktlink_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (trst == 1) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output &= ~nTRSTnOE; else high_output &= ~nTRST; } else if (trst == 0) { if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) high_output |= nTRSTnOE; else high_output |= nTRST; } if (srst == 1) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output &= ~nSRST; else high_output &= ~nSRSTnOE; } else if (srst == 0) { if (jtag_reset_config & RESET_SRST_PUSH_PULL) high_output |= nSRST; else high_output |= nSRSTnOE; } buffer_write(0x82); /* command "set data bits high byte" */ buffer_write(high_output); buffer_write(high_direction); LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } static void ktlink_blink(void) { /* LED connected to ACBUS7 */ high_output ^= 0x80; buffer_write(0x82); /* command "set data bits high byte" */ buffer_write(high_output); buffer_write(high_direction); } /******************************************************************** * Support for Digilent HS-1 * JTAG adapter from Digilent * http://www.digilent.com * Author: Stephane Bonnet bonnetst@hds.utc.fr *******************************************************************/ static int digilent_hs1_init(void) { /* the adapter only supports the base JTAG signals, no nTRST nor nSRST */ low_output = 0x88; low_direction = 0x8b; /* initialize low byte for jtag */ if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'digilent_hs1' layout"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static void digilent_hs1_reset(int trst, int srst) { /* Dummy function, no reset signals supported. */ } static const struct command_registration ft2232_command_handlers[] = { { .name = "ft2232_device_desc", .handler = &ft2232_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the FTDI FT2232 device", .usage = "description_string", }, { .name = "ft2232_serial", .handler = &ft2232_handle_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the FTDI FT2232 device", .usage = "serial_string", }, { .name = "ft2232_layout", .handler = &ft2232_handle_layout_command, .mode = COMMAND_CONFIG, .help = "set the layout of the FT2232 GPIO signals used " "to control output-enables and reset signals", .usage = "layout_name", }, { .name = "ft2232_vid_pid", .handler = &ft2232_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the FTDI FT2232 device", .usage = "(vid pid)* ", }, { .name = "ft2232_latency", .handler = &ft2232_handle_latency_command, .mode = COMMAND_CONFIG, .help = "set the FT2232 latency timer to a new value", .usage = "value", }, { .name = "ft2232_channel", .handler = &ft2232_handle_channel_command, .mode = COMMAND_CONFIG, .help = "set the FT2232 channel to a new value", .usage = "value", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface ft2232_interface = { .name = "ft2232", .supported = DEBUG_CAP_TMS_SEQ, .commands = ft2232_command_handlers, .transports = jtag_only, .init = ft2232_init, .quit = ft2232_quit, .speed = ft2232_speed, .speed_div = ft2232_speed_div, .khz = ft2232_khz, .execute_queue = ft2232_execute_queue, }; openocd-0.9.0/src/jtag/drivers/rlink.c0000644000175000017500000011400712315575360014557 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 Rob Brown, Lou Deluxe * * rob@cobbleware.com, lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include "rlink.h" #include "rlink_st7.h" #include "rlink_ep1_cmd.h" #include "rlink_dtc_cmd.h" #include "usb_common.h" /* This feature is made useless by running the DTC all the time. When automatic, the LED is on *whenever the DTC is running. Otherwise, USB messages are sent to turn it on and off. */ #undef AUTOMATIC_BUSY_LED /* This feature may require derating the speed due to reduced hold time. */ #undef USE_HARDWARE_SHIFTER_FOR_TMS #define INTERFACE_NAME "RLink" #define USB_IDVENDOR (0x138e) #define USB_IDPRODUCT (0x9000) #define USB_EP1OUT_ADDR (0x01) #define USB_EP1OUT_SIZE (16) #define USB_EP1IN_ADDR (USB_EP1OUT_ADDR | 0x80) #define USB_EP1IN_SIZE (USB_EP1OUT_SIZE) #define USB_EP2OUT_ADDR (0x02) #define USB_EP2OUT_SIZE (64) #define USB_EP2IN_ADDR (USB_EP2OUT_ADDR | 0x80) #define USB_EP2IN_SIZE (USB_EP2OUT_SIZE) #define USB_EP2BANK_SIZE (512) #define USB_TIMEOUT_MS (3 * 1000) #define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff) #define ST7_PD_NBUSY_LED ST7_PD0 #define ST7_PD_NRUN_LED ST7_PD1 /* low enables VPP at adapter header, high connects it to GND instead */ #define ST7_PD_VPP_SEL ST7_PD6 /* low: VPP = 12v, high: VPP <= 5v */ #define ST7_PD_VPP_SHDN ST7_PD7 /* These pins are connected together */ #define ST7_PE_ADAPTER_SENSE_IN ST7_PE3 #define ST7_PE_ADAPTER_SENSE_OUT ST7_PE4 /* Symbolic mapping between port pins and numbered IO lines */ #define ST7_PA_IO1 ST7_PA1 #define ST7_PA_IO2 ST7_PA2 #define ST7_PA_IO4 ST7_PA4 #define ST7_PA_IO8 ST7_PA6 #define ST7_PA_IO10 ST7_PA7 #define ST7_PB_IO5 ST7_PB5 #define ST7_PC_IO9 ST7_PC1 #define ST7_PC_IO3 ST7_PC2 #define ST7_PC_IO7 ST7_PC3 #define ST7_PE_IO6 ST7_PE5 /* Symbolic mapping between numbered IO lines and adapter signals */ #define ST7_PA_RTCK ST7_PA_IO0 #define ST7_PA_NTRST ST7_PA_IO1 #define ST7_PC_TDI ST7_PC_IO3 #define ST7_PA_DBGRQ ST7_PA_IO4 #define ST7_PB_NSRST ST7_PB_IO5 #define ST7_PE_TMS ST7_PE_IO6 #define ST7_PC_TCK ST7_PC_IO7 #define ST7_PC_TDO ST7_PC_IO9 #define ST7_PA_DBGACK ST7_PA_IO10 static usb_dev_handle *pHDev; /* * ep1 commands are up to USB_EP1OUT_SIZE bytes in length. * This function takes care of zeroing the unused bytes before sending the packet. * Any reply packet is not handled by this function. */ static int ep1_generic_commandl(usb_dev_handle *pHDev_param, size_t length, ...) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t *usb_buffer_p; va_list ap; int usb_ret; if (length > sizeof(usb_buffer)) length = sizeof(usb_buffer); usb_buffer_p = usb_buffer; va_start(ap, length); while (length > 0) { *usb_buffer_p++ = va_arg(ap, int); length--; } memset( usb_buffer_p, 0, sizeof(usb_buffer) - (usb_buffer_p - usb_buffer) ); usb_ret = usb_bulk_write( pHDev_param, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), USB_TIMEOUT_MS ); return usb_ret; } #if 0 static ssize_t ep1_memory_read( usb_dev_handle *pHDev, uint16_t addr, size_t length, uint8_t *buffer) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; int usb_ret; size_t remain; ssize_t count; usb_buffer[0] = EP1_CMD_MEMORY_READ; memset( usb_buffer + 4, 0, sizeof(usb_buffer) - 4 ); remain = length; count = 0; while (remain) { if (remain > sizeof(usb_buffer)) length = sizeof(usb_buffer); else length = remain; usb_buffer[1] = addr >> 8; usb_buffer[2] = addr; usb_buffer[3] = length; usb_ret = usb_bulk_write( pHDev, USB_EP1OUT_ADDR, usb_buffer, sizeof(usb_buffer), USB_TIMEOUT_MS ); if (usb_ret < sizeof(usb_buffer)) break; usb_ret = usb_bulk_read( pHDev, USB_EP1IN_ADDR, buffer, length, USB_TIMEOUT_MS ); if (usb_ret < length) break; addr += length; buffer += length; count += length; remain -= length; } return count; } #endif static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr, size_t length, uint8_t const *buffer) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; int usb_ret; size_t remain; ssize_t count; usb_buffer[0] = EP1_CMD_MEMORY_WRITE; remain = length; count = 0; while (remain) { if (remain > (sizeof(usb_buffer) - 4)) length = (sizeof(usb_buffer) - 4); else length = remain; usb_buffer[1] = addr >> 8; usb_buffer[2] = addr; usb_buffer[3] = length; memcpy( usb_buffer + 4, buffer, length ); memset( usb_buffer + 4 + length, 0, sizeof(usb_buffer) - 4 - length ); usb_ret = usb_bulk_write( pHDev_param, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), USB_TIMEOUT_MS ); if ((size_t)usb_ret < sizeof(usb_buffer)) break; addr += length; buffer += length; count += length; remain -= length; } return count; } #if 0 static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr, size_t length, ...) { uint8_t buffer[USB_EP1OUT_SIZE - 4]; uint8_t *buffer_p; va_list ap; size_t remain; if (length > sizeof(buffer)) length = sizeof(buffer); remain = length; buffer_p = buffer; va_start(ap, length); while (remain > 0) { *buffer_p++ = va_arg(ap, int); remain--; } return ep1_memory_write(pHDev, addr, length, buffer); } #endif #define DTCLOAD_COMMENT (0) #define DTCLOAD_ENTRY (1) #define DTCLOAD_LOAD (2) #define DTCLOAD_RUN (3) #define DTCLOAD_LUT_START (4) #define DTCLOAD_LUT (5) #define DTC_LOAD_BUFFER ST7_USB_BUF_EP2UIDO /* This gets set by the DTC loader */ static uint8_t dtc_entry_download; /* The buffer is specially formatted to represent a valid image to load into the DTC. */ static int dtc_load_from_buffer(usb_dev_handle *pHDev_param, const uint8_t *buffer, size_t length) { struct header_s { uint8_t type; uint8_t length; }; int usb_err; struct header_s *header; uint8_t lut_start = 0xc0; dtc_entry_download = 0; /* Stop the DTC before loading anything. */ usb_err = ep1_generic_commandl( pHDev_param, 1, EP1_CMD_DTC_STOP ); if (usb_err < 0) return usb_err; while (length) { if (length < sizeof(*header)) { LOG_ERROR("Malformed DTC image"); exit(1); } header = (struct header_s *)buffer; buffer += sizeof(*header); length -= sizeof(*header); if (length < (size_t)header->length + 1) { LOG_ERROR("Malformed DTC image"); exit(1); } switch (header->type) { case DTCLOAD_COMMENT: break; case DTCLOAD_ENTRY: /* store entry addresses somewhere */ if (!strncmp("download", (char *)buffer + 1, 8)) dtc_entry_download = buffer[0]; break; case DTCLOAD_LOAD: /* Send the DTC program to ST7 RAM. */ usb_err = ep1_memory_write( pHDev_param, DTC_LOAD_BUFFER, header->length + 1, buffer ); if (usb_err < 0) return usb_err; /* Load it into the DTC. */ usb_err = ep1_generic_commandl( pHDev_param, 3, EP1_CMD_DTC_LOAD, (DTC_LOAD_BUFFER >> 8), DTC_LOAD_BUFFER ); if (usb_err < 0) return usb_err; break; case DTCLOAD_RUN: usb_err = ep1_generic_commandl( pHDev_param, 3, EP1_CMD_DTC_CALL, buffer[0], EP1_CMD_DTC_WAIT ); if (usb_err < 0) return usb_err; break; case DTCLOAD_LUT_START: lut_start = buffer[0]; break; case DTCLOAD_LUT: usb_err = ep1_memory_write( pHDev_param, ST7_USB_BUF_EP0OUT + lut_start, header->length + 1, buffer ); if (usb_err < 0) return usb_err; break; default: LOG_ERROR("Invalid DTC image record type: 0x%02x", header->type); exit(1); break; } buffer += (header->length + 1); length -= (header->length + 1); } return 0; } /* * Start the DTC running in download mode (waiting for 512 byte command packets on ep2). */ static int dtc_start_download(void) { int usb_err; uint8_t ep2txr; /* set up for download mode and make sure EP2 is set up to transmit */ usb_err = ep1_generic_commandl( pHDev, 7, EP1_CMD_DTC_STOP, EP1_CMD_SET_UPLOAD, EP1_CMD_SET_DOWNLOAD, EP1_CMD_MEMORY_READ, /* read EP2TXR for its data toggle */ ST7_EP2TXR >> 8, ST7_EP2TXR, 1 ); if (usb_err < 0) return usb_err; /* read back ep2txr */ usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)&ep2txr, 1, USB_TIMEOUT_MS ); if (usb_err < 0) return usb_err; usb_err = ep1_generic_commandl( pHDev, 13, EP1_CMD_MEMORY_WRITE, /* preinitialize poll byte */ DTC_STATUS_POLL_BYTE >> 8, DTC_STATUS_POLL_BYTE, 1, 0x00, EP1_CMD_MEMORY_WRITE, /* set EP2IN to return data */ ST7_EP2TXR >> 8, ST7_EP2TXR, 1, (ep2txr & ST7_EP2TXR_DTOG_TX) | ST7_EP2TXR_STAT_VALID, EP1_CMD_DTC_CALL, /* start running the DTC */ dtc_entry_download, EP1_CMD_DTC_GET_CACHED_STATUS ); if (usb_err < 0) return usb_err; /* wait for completion */ usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)&ep2txr, 1, USB_TIMEOUT_MS ); return usb_err; } static int dtc_run_download( usb_dev_handle *pHDev_param, uint8_t *command_buffer, int command_buffer_size, uint8_t *reply_buffer, int reply_buffer_size ) { char dtc_status; int usb_err; int i; LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size); usb_err = usb_bulk_write( pHDev_param, USB_EP2OUT_ADDR, (char *)command_buffer, USB_EP2BANK_SIZE, USB_TIMEOUT_MS ); if (usb_err < 0) return usb_err; /* Wait for DTC to finish running command buffer */ for (i = 50;; ) { usb_err = ep1_generic_commandl( pHDev_param, 4, EP1_CMD_MEMORY_READ, DTC_STATUS_POLL_BYTE >> 8, DTC_STATUS_POLL_BYTE, 1 ); if (usb_err < 0) return usb_err; usb_err = usb_bulk_read( pHDev_param, USB_EP1IN_ADDR, &dtc_status, 1, USB_TIMEOUT_MS ); if (usb_err < 0) return usb_err; if (dtc_status & 0x01) break; if (!--i) { LOG_ERROR("too many retries waiting for DTC status"); return -ETIMEDOUT; } } if (reply_buffer && reply_buffer_size) { usb_err = usb_bulk_read( pHDev_param, USB_EP2IN_ADDR, (char *)reply_buffer, reply_buffer_size, USB_TIMEOUT_MS ); if (usb_err < reply_buffer_size) { LOG_ERROR("Read of endpoint 2 returned %d, expected %d", usb_err, reply_buffer_size ); return usb_err; } } return usb_err; } /* * The dtc reply queue is a singly linked list that describes what to do * with the reply packet that comes from the DTC. Only SCAN_IN and SCAN_IO generate * these entries. */ struct dtc_reply_queue_entry { struct dtc_reply_queue_entry *next; struct jtag_command *cmd; /* the command that resulted in this entry */ struct { uint8_t *buffer; /* the scan buffer */ int size; /* size of the scan buffer in bits */ int offset; /* how many bits were already done before this? */ int length; /* how many bits are processed in this operation? */ enum scan_type type; /* SCAN_IN/SCAN_OUT/SCAN_IO */ } scan; }; /* * The dtc_queue consists of a buffer of pending commands and a reply queue. * rlink_scan and tap_state_run add to the command buffer and maybe to the reply queue. */ static struct { struct dtc_reply_queue_entry *rq_head; struct dtc_reply_queue_entry *rq_tail; uint32_t cmd_index; uint32_t reply_index; uint8_t cmd_buffer[USB_EP2BANK_SIZE]; } dtc_queue; /* * The tap state queue is for accumulating TAP state changes wiithout needlessly * flushing the dtc_queue. When it fills or is run, it adds the accumulated bytes to * the dtc_queue. */ static struct { uint32_t length; uint32_t buffer; } tap_state_queue; static int dtc_queue_init(void) { dtc_queue.rq_head = NULL; dtc_queue.rq_tail = NULL; dtc_queue.cmd_index = 0; dtc_queue.reply_index = 0; return 0; } static inline struct dtc_reply_queue_entry *dtc_queue_enqueue_reply( enum scan_type type, uint8_t *buffer, int size, int offset, int length, struct jtag_command *cmd) { struct dtc_reply_queue_entry *rq_entry; rq_entry = malloc(sizeof(struct dtc_reply_queue_entry)); if (rq_entry != NULL) { rq_entry->scan.type = type; rq_entry->scan.buffer = buffer; rq_entry->scan.size = size; rq_entry->scan.offset = offset; rq_entry->scan.length = length; rq_entry->cmd = cmd; rq_entry->next = NULL; if (dtc_queue.rq_head == NULL) dtc_queue.rq_head = rq_entry; else dtc_queue.rq_tail->next = rq_entry; dtc_queue.rq_tail = rq_entry; } return rq_entry; } /* * Running the queue means that any pending command buffer is run * and any reply data dealt with. The command buffer is then cleared for subsequent processing. * The queue is automatically run by append when it is necessary to get space for the append. */ static int dtc_queue_run(void) { struct dtc_reply_queue_entry *rq_p, *rq_next; int retval; int usb_err; int bit_cnt; int x; uint8_t *dtc_p, *tdo_p; uint8_t dtc_mask, tdo_mask; uint8_t reply_buffer[USB_EP2IN_SIZE]; assert((dtc_queue.rq_head != 0) == (dtc_queue.reply_index > 0)); assert(dtc_queue.cmd_index < USB_EP2BANK_SIZE); assert(dtc_queue.reply_index <= USB_EP2IN_SIZE); retval = ERROR_OK; if (dtc_queue.cmd_index < 1) return retval; dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_STOP; usb_err = dtc_run_download(pHDev, dtc_queue.cmd_buffer, dtc_queue.cmd_index, reply_buffer, sizeof(reply_buffer) ); if (usb_err < 0) { LOG_ERROR("dtc_run_download: %s", usb_strerror()); exit(1); } if (dtc_queue.rq_head != NULL) { /* process the reply, which empties the reply queue and frees its entries */ dtc_p = reply_buffer; /* The rigamarole with the masks and doing it bit-by-bit is due to the fact that the *scan buffer is LSb-first and the DTC code is MSb-first for hardware reasons. It *was that or craft a function to do the reversal, and that wouldn't work with *bit-stuffing (supplying extra bits to use mostly byte operations), or any other *scheme which would throw the byte alignment off. */ for ( rq_p = dtc_queue.rq_head; rq_p != NULL; rq_p = rq_next ) { tdo_p = rq_p->scan.buffer + (rq_p->scan.offset / 8); tdo_mask = 1 << (rq_p->scan.offset % 8); bit_cnt = rq_p->scan.length; if (bit_cnt >= 8) { /* bytes */ dtc_mask = 1 << (8 - 1); for ( ; bit_cnt; bit_cnt-- ) { if (*dtc_p & dtc_mask) *tdo_p |= tdo_mask; else *tdo_p &= ~tdo_mask; dtc_mask >>= 1; if (dtc_mask == 0) { dtc_p++; dtc_mask = 1 << (8 - 1); } tdo_mask <<= 1; if (tdo_mask == 0) { tdo_p++; tdo_mask = 1; } } } else { /* extra bits or last bit */ x = *dtc_p++; if ((rq_p->scan.type == SCAN_IN) && ( rq_p->scan.offset != rq_p->scan.size - 1 )) { /* extra bits were sent as a full byte with padding on the *end */ dtc_mask = 1 << (8 - 1); } else dtc_mask = 1 << (bit_cnt - 1); for ( ; bit_cnt; bit_cnt-- ) { if (x & dtc_mask) *tdo_p |= tdo_mask; else *tdo_p &= ~tdo_mask; dtc_mask >>= 1; tdo_mask <<= 1; if (tdo_mask == 0) { tdo_p++; tdo_mask = 1; } } } if ((rq_p->scan.offset + rq_p->scan.length) >= rq_p->scan.size) { /* feed scan buffer back into openocd and free it */ if (jtag_read_buffer(rq_p->scan.buffer, rq_p->cmd->cmd.scan) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; free(rq_p->scan.buffer); } rq_next = rq_p->next; free(rq_p); } dtc_queue.rq_head = NULL; dtc_queue.rq_tail = NULL; } /* reset state for new appends */ dtc_queue.cmd_index = 0; dtc_queue.reply_index = 0; return retval; } /* runs the queue if it cannot take reserved_cmd bytes of command data * or reserved_reply bytes of reply data */ static int dtc_queue_run_if_full(int reserved_cmd, int reserved_reply) { /* reserve one additional byte for the STOP cmd appended during run */ if (dtc_queue.cmd_index + reserved_cmd + 1 > USB_EP2BANK_SIZE) return dtc_queue_run(); if (dtc_queue.reply_index + reserved_reply > USB_EP2IN_SIZE) return dtc_queue_run(); return ERROR_OK; } static int tap_state_queue_init(void) { tap_state_queue.length = 0; tap_state_queue.buffer = 0; return 0; } static int tap_state_queue_run(void) { int i; int bits; uint8_t byte_param; int retval; retval = 0; if (!tap_state_queue.length) return retval; bits = 1; byte_param = 0; for (i = tap_state_queue.length; i--; ) { byte_param <<= 1; if (tap_state_queue.buffer & 1) byte_param |= 1; if ((bits >= 8) || !i) { byte_param <<= (8 - bits); /* make sure there's room for two cmd bytes */ dtc_queue_run_if_full(2, 0); #ifdef USE_HARDWARE_SHIFTER_FOR_TMS if (bits == 8) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_BYTES(1); } else { #endif dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_BITS(bits); #ifdef USE_HARDWARE_SHIFTER_FOR_TMS } #endif dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = byte_param; byte_param = 0; bits = 1; } else bits++; tap_state_queue.buffer >>= 1; } retval = tap_state_queue_init(); return retval; } static int tap_state_queue_append(uint8_t tms) { int retval; if (tap_state_queue.length >= sizeof(tap_state_queue.buffer) * 8) { retval = tap_state_queue_run(); if (retval != 0) return retval; } if (tms) tap_state_queue.buffer |= (1 << tap_state_queue.length); tap_state_queue.length++; return 0; } static void rlink_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void rlink_state_move(void) { int i = 0, tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_count; i++) { tms = (tms_scan >> i) & 1; tap_state_queue_append(tms); } tap_set_state(tap_get_end_state()); } static void rlink_path_move(struct pathmove_command *cmd) { int num_states = cmd->num_states; int state_count; int tms = 0; state_count = 0; while (num_states) { if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) tms = 0; else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) tms = 1; else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); exit(-1); } tap_state_queue_append(tms); tap_set_state(cmd->path[state_count]); state_count++; num_states--; } tap_set_end_state(tap_get_state()); } static void rlink_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in RTI */ if (tap_get_state() != TAP_IDLE) { rlink_end_state(TAP_IDLE); rlink_state_move(); } /* execute num_cycles */ for (i = 0; i < num_cycles; i++) tap_state_queue_append(0); /* finish in end_state */ rlink_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) rlink_state_move(); } /* (1) assert or (0) deassert reset lines */ static void rlink_reset(int trst, int srst) { uint8_t bitmap; int usb_err; /* Read port A for bit op */ usb_err = ep1_generic_commandl( pHDev, 4, EP1_CMD_MEMORY_READ, ST7_PADR >> 8, ST7_PADR, 1 ); if (usb_err < 0) { LOG_ERROR("%s", usb_strerror()); exit(1); } usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)&bitmap, 1, USB_TIMEOUT_MS ); if (usb_err < 1) { LOG_ERROR("%s", usb_strerror()); exit(1); } if (trst) bitmap &= ~ST7_PA_NTRST; else bitmap |= ST7_PA_NTRST; /* Write port A and read port B for bit op * port B has no OR, and we want to emulate open drain on NSRST, so we initialize DR to 0 *and assert NSRST by setting DDR to 1. */ usb_err = ep1_generic_commandl( pHDev, 9, EP1_CMD_MEMORY_WRITE, ST7_PADR >> 8, ST7_PADR, 1, bitmap, EP1_CMD_MEMORY_READ, ST7_PBDDR >> 8, ST7_PBDDR, 1 ); if (usb_err < 0) { LOG_ERROR("%s", usb_strerror()); exit(1); } usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)&bitmap, 1, USB_TIMEOUT_MS ); if (usb_err < 1) { LOG_ERROR("%s", usb_strerror()); exit(1); } if (srst) bitmap |= ST7_PB_NSRST; else bitmap &= ~ST7_PB_NSRST; /* write port B and read dummy to ensure completion before returning */ usb_err = ep1_generic_commandl( pHDev, 6, EP1_CMD_MEMORY_WRITE, ST7_PBDDR >> 8, ST7_PBDDR, 1, bitmap, EP1_CMD_DTC_GET_CACHED_STATUS ); if (usb_err < 0) { LOG_ERROR("%s", usb_strerror()); exit(1); } usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)&bitmap, 1, USB_TIMEOUT_MS ); if (usb_err < 1) { LOG_ERROR("%s", usb_strerror()); exit(1); } } static int rlink_scan(struct jtag_command *cmd, enum scan_type type, uint8_t *buffer, int scan_size) { bool ir_scan; tap_state_t saved_end_state; int byte_bits; int extra_bits; int chunk_bits; int chunk_bytes; int x; int tdi_bit_offset; uint8_t tdi_mask, *tdi_p; uint8_t dtc_mask; if (scan_size < 1) { LOG_ERROR("scan_size cannot be less than 1 bit"); exit(1); } ir_scan = cmd->cmd.scan->ir_scan; /* Move to the proper state before starting to shift TDI/TDO. */ if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { saved_end_state = tap_get_end_state(); rlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); rlink_state_move(); rlink_end_state(saved_end_state); } tap_state_queue_run(); #if 0 printf("scan_size = %d, type = 0x%x\n", scan_size, type); { int i; /* clear unused bits in scan buffer for ease of debugging * (it makes diffing output easier) */ buffer[scan_size / 8] &= ((1 << ((scan_size - 1) % 8) + 1) - 1); printf("before scan:"); for (i = 0; i < (scan_size + 7) / 8; i++) printf(" %02x", buffer[i]); printf("\n"); } #endif /* The number of bits that can be shifted as complete bytes */ byte_bits = (int)(scan_size - 1) / 8 * 8; /* The number of bits left over, not counting the last bit */ extra_bits = (scan_size - 1) - byte_bits; tdi_bit_offset = 0; tdi_p = buffer; tdi_mask = 1; if (extra_bits && (type == SCAN_OUT)) { /* Schedule any extra bits into the DTC command buffer, padding as needed * For SCAN_OUT, this comes before the full bytes so the (leading) padding bits will *fall off the end */ /* make sure there's room for two cmd bytes */ dtc_queue_run_if_full(2, 0); x = 0; dtc_mask = 1 << (extra_bits - 1); while (extra_bits--) { if (*tdi_p & tdi_mask) x |= dtc_mask; dtc_mask >>= 1; tdi_mask <<= 1; if (tdi_mask == 0) { tdi_p++; tdi_mask = 1; } } dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TDI_BYTES(1); dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; } /* Loop scheduling full bytes into the DTC command buffer */ while (byte_bits) { /* make sure there's room for one (for in scans) or two cmd bytes and * at least one reply byte for in or inout scans*/ dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, type != SCAN_OUT ? 1 : 0); chunk_bits = byte_bits; /* we can only use up to 16 bytes at a time */ if (chunk_bits > (16 * 8)) chunk_bits = (16 * 8); if (type != SCAN_IN) { /* how much is there room for, considering stop and byte op? */ x = (sizeof(dtc_queue.cmd_buffer) - (dtc_queue.cmd_index + 1 + 1)) * 8; if (chunk_bits > x) chunk_bits = x; } if (type != SCAN_OUT) { /* how much is there room for in the reply buffer? */ x = (USB_EP2IN_SIZE - dtc_queue.reply_index) * 8; if (chunk_bits > x) chunk_bits = x; } /* so the loop will end */ byte_bits -= chunk_bits; if (type != SCAN_OUT) { if (dtc_queue_enqueue_reply( type, buffer, scan_size, tdi_bit_offset, chunk_bits, cmd ) == NULL) { LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno)); exit(1); } dtc_queue.reply_index += (chunk_bits + 7) / 8; tdi_bit_offset += chunk_bits; } /* chunk_bits is a multiple of 8, so there are no rounding issues. */ chunk_bytes = chunk_bits / 8; switch (type) { case SCAN_IN: x = DTC_CMD_SHIFT_TDO_BYTES(chunk_bytes); break; case SCAN_OUT: x = DTC_CMD_SHIFT_TDI_BYTES(chunk_bytes); break; default: x = DTC_CMD_SHIFT_TDIO_BYTES(chunk_bytes); break; } dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; if (type != SCAN_IN) { x = 0; dtc_mask = 1 << (8 - 1); while (chunk_bits--) { if (*tdi_p & tdi_mask) x |= dtc_mask; dtc_mask >>= 1; if (dtc_mask == 0) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; x = 0; dtc_mask = 1 << (8 - 1); } tdi_mask <<= 1; if (tdi_mask == 0) { tdi_p++; tdi_mask = 1; } } } } if (extra_bits && (type != SCAN_OUT)) { /* Schedule any extra bits into the DTC command buffer */ /* make sure there's room for one (for in scans) or two cmd bytes * and one reply byte */ dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, 1); if (dtc_queue_enqueue_reply( type, buffer, scan_size, tdi_bit_offset, extra_bits, cmd ) == NULL) { LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno)); exit(1); } dtc_queue.reply_index++; tdi_bit_offset += extra_bits; if (type == SCAN_IN) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TDO_BYTES(1); } else { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TDIO_BITS(extra_bits); x = 0; dtc_mask = 1 << (8 - 1); while (extra_bits--) { if (*tdi_p & tdi_mask) x |= dtc_mask; dtc_mask >>= 1; tdi_mask <<= 1; if (tdi_mask == 0) { tdi_p++; tdi_mask = 1; } } dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; } } /* Schedule the last bit into the DTC command buffer */ /* make sure there's room for one cmd byte and one reply byte * for in or inout scans*/ dtc_queue_run_if_full(1, type == SCAN_OUT ? 0 : 1); if (type == SCAN_OUT) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 0); } else { if (dtc_queue_enqueue_reply( type, buffer, scan_size, tdi_bit_offset, 1, cmd ) == NULL) { LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno)); exit(1); } dtc_queue.reply_index++; dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1); } /* Move to pause state */ tap_state_queue_append(0); tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) rlink_state_move(); return 0; } static int rlink_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; int retval, tmp_retval; /* return ERROR_OK, unless something goes wrong */ retval = ERROR_OK; #ifndef AUTOMATIC_BUSY_LED /* turn LED on */ ep1_generic_commandl(pHDev, 2, EP1_CMD_SET_PORTD_LEDS, ~(ST7_PD_NBUSY_LED) ); #endif while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: case JTAG_TLR_RESET: case JTAG_PATHMOVE: case JTAG_SCAN: break; default: /* some events, such as resets, need a queue flush to ensure *consistency */ tap_state_queue_run(); dtc_queue_run(); break; } switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) tap_set_state(TAP_RESET); rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif if (cmd->cmd.runtest->end_state != -1) rlink_end_state(cmd->cmd.runtest->end_state); rlink_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif if (cmd->cmd.statemove->end_state != -1) rlink_end_state(cmd->cmd.statemove->end_state); rlink_state_move(); break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif rlink_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("%s scan end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", cmd->cmd.scan->end_state); #endif if (cmd->cmd.scan->end_state != -1) rlink_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); if (rlink_scan(cmd, type, buffer, scan_size) != ERROR_OK) retval = ERROR_FAIL; break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); #endif jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } /* Flush the DTC queue to make sure any pending reads have been done before exiting this *function */ tap_state_queue_run(); tmp_retval = dtc_queue_run(); if (tmp_retval != ERROR_OK) retval = tmp_retval; #ifndef AUTOMATIC_BUSY_LED /* turn LED onff */ ep1_generic_commandl(pHDev, 2, EP1_CMD_SET_PORTD_LEDS, ~0 ); #endif return retval; } /* Using an unindexed table because it is infrequently accessed and it is short. The table must be *in order of ascending speed (and descending prescaler), as it is scanned in reverse. */ static int rlink_speed(int speed) { int i; if (speed == 0) { /* fastest speed */ speed = rlink_speed_table[rlink_speed_table_size - 1].prescaler; } for (i = rlink_speed_table_size; i--; ) { if (rlink_speed_table[i].prescaler == speed) { if (dtc_load_from_buffer(pHDev, rlink_speed_table[i].dtc, rlink_speed_table[i].dtc_size) != 0) { LOG_ERROR( "An error occurred while trying to load DTC code for speed \"%d\".", speed); exit(1); } if (dtc_start_download() < 0) { LOG_ERROR("starting DTC: %s", usb_strerror()); exit(1); } return ERROR_OK; } } LOG_ERROR("%d is not a supported speed", speed); return ERROR_FAIL; } static int rlink_speed_div(int speed, int *khz) { int i; for (i = rlink_speed_table_size; i--; ) { if (rlink_speed_table[i].prescaler == speed) { *khz = rlink_speed_table[i].khz; return ERROR_OK; } } LOG_ERROR("%d is not a supported speed", speed); return ERROR_FAIL; } static int rlink_khz(int khz, int *speed) { int i; if (khz == 0) { LOG_ERROR("RCLK not supported"); return ERROR_FAIL; } for (i = rlink_speed_table_size; i--; ) { if (rlink_speed_table[i].khz <= khz) { *speed = rlink_speed_table[i].prescaler; return ERROR_OK; } } LOG_WARNING("The lowest supported JTAG speed is %d KHz", rlink_speed_table[0].khz); *speed = rlink_speed_table[0].prescaler; return ERROR_OK; } static int rlink_init(void) { int i, j, retries; uint8_t reply_buffer[USB_EP1IN_SIZE]; usb_init(); const uint16_t vids[] = { USB_IDVENDOR, 0 }; const uint16_t pids[] = { USB_IDPRODUCT, 0 }; if (jtag_usb_open(vids, pids, &pHDev) != ERROR_OK) return ERROR_FAIL; struct usb_device *dev = usb_device(pHDev); if (dev->descriptor.bNumConfigurations > 1) { LOG_ERROR("Whoops! NumConfigurations is not 1, don't know what to do..."); return ERROR_FAIL; } if (dev->config->bNumInterfaces > 1) { LOG_ERROR("Whoops! NumInterfaces is not 1, don't know what to do..."); return ERROR_FAIL; } LOG_DEBUG("Opened device, pHDev = %p", pHDev); /* usb_set_configuration required under win32 */ usb_set_configuration(pHDev, dev->config[0].bConfigurationValue); retries = 3; do { i = usb_claim_interface(pHDev, 0); if (i) { LOG_ERROR("usb_claim_interface: %s", usb_strerror()); #ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP j = usb_detach_kernel_driver_np(pHDev, 0); if (j) LOG_ERROR("detach kernel driver: %s", usb_strerror()); #endif } else { LOG_DEBUG("interface claimed!"); break; } } while (--retries); if (i) { LOG_ERROR("Initialisation failed."); return ERROR_FAIL; } if (usb_set_altinterface(pHDev, 0) != 0) { LOG_ERROR("Failed to set interface."); return ERROR_FAIL; } /* The device starts out in an unknown state on open. As such, * result reads time out, and it's not even known whether the * command was accepted. So, for this first command, we issue * it repeatedly until its response doesn't time out. Also, if * sending a command is going to time out, we find that out here. * * It must be possible to open the device in such a way that * this special magic isn't needed, but, so far, it escapes us. */ for (i = 0; i < 5; i++) { j = ep1_generic_commandl( pHDev, 1, EP1_CMD_GET_FWREV ); if (j < USB_EP1OUT_SIZE) { LOG_ERROR("USB write error: %s", usb_strerror()); return ERROR_FAIL; } j = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, sizeof(reply_buffer), 200 ); if (j != -ETIMEDOUT) break; } if (j < (int)sizeof(reply_buffer)) { LOG_ERROR("USB read error: %s", usb_strerror()); return ERROR_FAIL; } LOG_DEBUG(INTERFACE_NAME " firmware version: %d.%d.%d", reply_buffer[0], reply_buffer[1], reply_buffer[2]); if ((reply_buffer[0] != 0) || (reply_buffer[1] != 0) || (reply_buffer[2] != 3)) LOG_WARNING( "The rlink device is not of the version that the developers have played with. It may or may not work."); /* Probe port E for adapter presence */ ep1_generic_commandl( pHDev, 16, EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 0 */ ST7_PEDR >> 8, ST7_PEDR, 3, 0x00, /* DR */ ST7_PE_ADAPTER_SENSE_OUT, /* DDR */ ST7_PE_ADAPTER_SENSE_OUT, /* OR */ EP1_CMD_MEMORY_READ, /* Read back */ ST7_PEDR >> 8, ST7_PEDR, 1, EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 1 */ ST7_PEDR >> 8, ST7_PEDR, 1, ST7_PE_ADAPTER_SENSE_OUT ); usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, USB_TIMEOUT_MS ); if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0) LOG_WARNING("target detection problem"); ep1_generic_commandl( pHDev, 11, EP1_CMD_MEMORY_READ, /* Read back */ ST7_PEDR >> 8, ST7_PEDR, 1, EP1_CMD_MEMORY_WRITE, /* float port E */ ST7_PEDR >> 8, ST7_PEDR, 3, 0x00, /* DR */ 0x00, /* DDR */ 0x00 /* OR */ ); usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, USB_TIMEOUT_MS ); if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) == 0) LOG_WARNING("target not plugged in"); /* float ports A and B */ ep1_generic_commandl( pHDev, 11, EP1_CMD_MEMORY_WRITE, ST7_PADDR >> 8, ST7_PADDR, 2, 0x00, 0x00, EP1_CMD_MEMORY_WRITE, ST7_PBDDR >> 8, ST7_PBDDR, 1, 0x00 ); /* make sure DTC is stopped, set VPP control, set up ports A and B */ ep1_generic_commandl( pHDev, 14, EP1_CMD_DTC_STOP, EP1_CMD_SET_PORTD_VPP, ~(ST7_PD_VPP_SHDN), EP1_CMD_MEMORY_WRITE, ST7_PADR >> 8, ST7_PADR, 2, ((~(0)) & (ST7_PA_NTRST)), (ST7_PA_NTRST), /* port B has no OR, and we want to emulate open drain on NSRST, so we set DR to 0 *here and later assert NSRST by setting DDR bit to 1. */ EP1_CMD_MEMORY_WRITE, ST7_PBDR >> 8, ST7_PBDR, 1, 0x00 ); /* set LED updating mode and make sure they're unlit */ ep1_generic_commandl( pHDev, 3, #ifdef AUTOMATIC_BUSY_LED EP1_CMD_LEDUE_BUSY, #else EP1_CMD_LEDUE_NONE, #endif EP1_CMD_SET_PORTD_LEDS, ~0 ); tap_state_queue_init(); dtc_queue_init(); rlink_reset(0, 0); return ERROR_OK; } static int rlink_quit(void) { /* stop DTC and make sure LEDs are off */ ep1_generic_commandl( pHDev, 6, EP1_CMD_DTC_STOP, EP1_CMD_LEDUE_NONE, EP1_CMD_SET_PORTD_LEDS, ~0, EP1_CMD_SET_PORTD_VPP, ~0 ); usb_release_interface(pHDev, 0); usb_close(pHDev); return ERROR_OK; } struct jtag_interface rlink_interface = { .name = "rlink", .init = rlink_init, .quit = rlink_quit, .speed = rlink_speed, .speed_div = rlink_speed_div, .khz = rlink_khz, .execute_queue = rlink_execute_queue, }; openocd-0.9.0/src/jtag/drivers/rlink.h0000644000175000017500000000321312315575360014560 00000000000000/*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ struct rlink_speed_table { uint8_t const *dtc; uint16_t dtc_size; uint16_t khz; uint8_t prescaler; }; extern const struct rlink_speed_table rlink_speed_table[]; extern const size_t rlink_speed_table_size; openocd-0.9.0/src/jtag/drivers/rlink_speed_table.c0000644000175000017500000001311212315575360017101 00000000000000/* This file was created automatically by ../../../tools/rlink_make_speed_table/rlink_make_speed_table.pl. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rlink.h" #include "rlink_st7.h" static const uint8_t dtc_64[] = { 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148, 191, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42, 42, 73, 0, 88, 0, 160, 189, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119, 110, 108, 111, 97, 100, 2, 226, 7, 219, 39, 137, 51, 172, 130, 192, 96, 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133, 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177, 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39, 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193, 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96, 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105, 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219, 39, 131, 161, 176, 130, 195, 53, 131, 178, 10, 66, 176, 151, 60, 97, 58, 151, 215, 2, 40, 66, 1, 0, 160, 185, 130, 60, 97, 203, 130, 60, 194, 139, 127, 195, 53, 156, 47, 200, 96, 201, 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 171, 182, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219, 39, 131, 160, 191, 130, 195, 53, 131, 177, 10, 66, 176, 147, 151, 0, 60, 97, 58, 151, 0, 160, 185, 130, 60, 97, 203, 8, 2, 36, 139, 124, 193, 151, 96 }; static const uint8_t dtc_11[] = { 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148, 188, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42, 42, 73, 0, 88, 0, 154, 183, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119, 110, 108, 111, 97, 100, 2, 213, 7, 219, 39, 137, 51, 172, 130, 192, 96, 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133, 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177, 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39, 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193, 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96, 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105, 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219, 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 0, 0, 0, 0, 0, 58, 151, 215, 2, 40, 66, 1, 203, 130, 60, 194, 139, 121, 195, 53, 156, 47, 200, 96, 201, 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 171, 176, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219, 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 0, 0, 0, 0, 0, 58, 151, 203, 8, 2, 36, 139, 117, 193, 151, 96 }; static const uint8_t dtc_8[] = { 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148, 187, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42, 42, 73, 0, 88, 0, 152, 181, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119, 110, 108, 111, 97, 100, 2, 209, 7, 219, 39, 137, 51, 172, 130, 192, 96, 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133, 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177, 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39, 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193, 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96, 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105, 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219, 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 0, 0, 0, 58, 151, 215, 2, 40, 66, 1, 203, 130, 60, 194, 139, 119, 195, 53, 156, 47, 200, 96, 201, 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 170, 190, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219, 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 0, 0, 0, 58, 151, 203, 8, 2, 36, 139, 115, 193, 151, 96 }; static const uint8_t dtc_2[] = { 0, 2, 68, 84, 67, 2, 14, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148, 186, 143, 185, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42, 42, 73, 0, 88, 0, 149, 178, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119, 110, 108, 111, 97, 100, 2, 203, 7, 219, 39, 137, 51, 172, 130, 192, 96, 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133, 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177, 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39, 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193, 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96, 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105, 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219, 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 58, 151, 215, 2, 40, 66, 1, 203, 130, 60, 194, 139, 116, 195, 53, 156, 47, 200, 96, 201, 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 170, 187, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219, 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 58, 151, 203, 8, 2, 36, 139, 112, 193, 151, 96 }; const struct rlink_speed_table rlink_speed_table[] = {{ dtc_64, sizeof(dtc_64), (ST7_FOSC * 2) / (1000 * 64), 64 }, { dtc_11, sizeof(dtc_11), (ST7_FOSC * 2) / (1000 * 11), 11 }, { dtc_8, sizeof(dtc_8), (ST7_FOSC * 2) / (1000 * 8), 8 }, { dtc_2, sizeof(dtc_2), (ST7_FOSC * 2) / (1000 * 2), 2 } }; const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table); openocd-0.9.0/src/jtag/drivers/libusb_common.h0000644000175000017500000000270512315575360016276 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mauro Gamba * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_LIBUSB1 #include #else #include #endif openocd-0.9.0/src/jtag/drivers/rlink_ep1_cmd.h0000644000175000017500000000554112315575360016156 00000000000000/*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Command opcodes that can be sent over endpoint 1. * This codifies information provided by Rob Brown . * The buffer can contain several of these, but only one which returns data. * Some of these opcodes have arguments, which follow immediately. * If shorter than the packet size, trailing positions should be zero-filled. */ /* LED update enables: * When enabled, each LED is updated automatically. * When not enabled, each LED can be controlled manually with EP1_CMD_SET_PORTD_LEDS. */ #define EP1_CMD_LEDUE_BOTH (0x05) /* EP1_CMD_LEDUE_NONE has the side effect of turning the LEDs on */ #define EP1_CMD_LEDUE_NONE (0x06) #define EP1_CMD_LEDUE_ERROR (0x17) #define EP1_CMD_LEDUE_BUSY (0x18) #define EP1_CMD_DTC_STOP (0x0b) #define EP1_CMD_DTC_LOAD (0x0c) #define EP1_CMD_DTC_CALL (0x0d) #define EP1_CMD_SET_UPLOAD (0x0f) #define EP1_CMD_SET_DOWNLOAD (0x10) #define EP1_CMD_DTC_WAIT (0x12) #define EP1_CMD_DTC_GET_STATUS (0x15) /* a quick way to just read back one byte */ #define EP1_CMD_DTC_GET_CACHED_STATUS (0x16) /* Writes upper 2 bits (SHDN and SEL) of port D with argument */ #define EP1_CMD_SET_PORTD_VPP (0x19) /* Writes lower 2 bits (BUSY and ERROR) of port D with argument */ #define EP1_CMD_SET_PORTD_LEDS (0x1a) #define EP1_CMD_MEMORY_READ (0x28) #define EP1_CMD_MEMORY_WRITE (0x29) #define EP1_CMD_GET_FWREV (0xfe) #define EP1_CMD_GET_SERIAL (0xff) openocd-0.9.0/src/jtag/drivers/dummy.c0000644000175000017500000001030312315575360014565 00000000000000/*************************************************************************** * Copyright (C) 2008 by Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" #include "hello.h" /* my private tap controller state, which tracks state for calling code */ static tap_state_t dummy_state = TAP_RESET; static int dummy_clock; /* edge detector */ static int clock_count; /* count clocks in any stable state, only stable states */ static uint32_t dummy_data; static int dummy_read(void) { int data = 1 & dummy_data; dummy_data = (dummy_data >> 1) | (1 << 31); return data; } static void dummy_write(int tck, int tms, int tdi) { /* TAP standard: "state transitions occur on rising edge of clock" */ if (tck != dummy_clock) { if (tck) { tap_state_t old_state = dummy_state; dummy_state = tap_state_transition(old_state, tms); if (old_state != dummy_state) { if (clock_count) { LOG_DEBUG("dummy_tap: %d stable clocks", clock_count); clock_count = 0; } LOG_DEBUG("dummy_tap: %s", tap_state_name(dummy_state)); #if defined(DEBUG) if (dummy_state == TAP_DRCAPTURE) dummy_data = 0x01255043; #endif } else { /* this is a stable state clock edge, no change of state here, * simply increment clock_count for subsequent logging */ ++clock_count; } } dummy_clock = tck; } } static void dummy_reset(int trst, int srst) { dummy_clock = 0; if (trst || (srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) dummy_state = TAP_RESET; LOG_DEBUG("reset to: %s", tap_state_name(dummy_state)); } static void dummy_led(int on) { } static struct bitbang_interface dummy_bitbang = { .read = &dummy_read, .write = &dummy_write, .reset = &dummy_reset, .blink = &dummy_led, }; static int dummy_khz(int khz, int *jtag_speed) { if (khz == 0) *jtag_speed = 0; else *jtag_speed = 64000/khz; return ERROR_OK; } static int dummy_speed_div(int speed, int *khz) { if (speed == 0) *khz = 0; else *khz = 64000/speed; return ERROR_OK; } static int dummy_speed(int speed) { return ERROR_OK; } static int dummy_init(void) { bitbang_interface = &dummy_bitbang; return ERROR_OK; } static int dummy_quit(void) { return ERROR_OK; } static const struct command_registration dummy_command_handlers[] = { { .name = "dummy", .mode = COMMAND_ANY, .help = "dummy interface driver commands", .chain = hello_command_handlers, }, COMMAND_REGISTRATION_DONE, }; /* The dummy driver is used to easily check the code path * where the target is unresponsive. */ struct jtag_interface dummy_interface = { .name = "dummy", .supported = DEBUG_CAP_TMS_SEQ, .commands = dummy_command_handlers, .transports = jtag_only, .execute_queue = &bitbang_execute_queue, .speed = &dummy_speed, .khz = &dummy_khz, .speed_div = &dummy_speed_div, .init = &dummy_init, .quit = &dummy_quit, }; openocd-0.9.0/src/jtag/drivers/at91rm9200.c0000644000175000017500000001753212516456302015072 00000000000000/*************************************************************************** * Copyright (C) 2006 by Anders Larsen * * al@alarsen.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" #include /* AT91RM9200 */ #define AT91C_BASE_SYS (0xfffff000) /* GPIO assignment */ #define PIOA (0 << 7) #define PIOB (1 << 7) #define PIOC (2 << 7) #define PIOD (3 << 7) #define PIO_PER (0) /* PIO enable */ #define PIO_OER (4) /* output enable */ #define PIO_ODR (5) /* output disable */ #define PIO_SODR (12) /* set output data */ #define PIO_CODR (13) /* clear output data */ #define PIO_PDSR (15) /* pin data status */ #define PIO_PPUER (25) /* pull-up enable */ #define NC (0) /* not connected */ #define P0 (1 << 0) #define P1 (1 << 1) #define P2 (1 << 2) #define P3 (1 << 3) #define P4 (1 << 4) #define P5 (1 << 5) #define P6 (1 << 6) #define P7 (1 << 7) #define P8 (1 << 8) #define P9 (1 << 9) #define P10 (1 << 10) #define P11 (1 << 11) #define P12 (1 << 12) #define P13 (1 << 13) #define P14 (1 << 14) #define P15 (1 << 15) #define P16 (1 << 16) #define P17 (1 << 17) #define P18 (1 << 18) #define P19 (1 << 19) #define P20 (1 << 20) #define P21 (1 << 21) #define P22 (1 << 22) #define P23 (1 << 23) #define P24 (1 << 24) #define P25 (1 << 25) #define P26 (1 << 26) #define P27 (1 << 27) #define P28 (1 << 28) #define P29 (1 << 29) #define P30 (1 << 30) #define P31 (1 << 31) struct device_t { const char *name; int TDO_PIO; /* PIO holding TDO */ uint32_t TDO_MASK; /* TDO bitmask */ int TRST_PIO; /* PIO holding TRST */ uint32_t TRST_MASK; /* TRST bitmask */ int TMS_PIO; /* PIO holding TMS */ uint32_t TMS_MASK; /* TMS bitmask */ int TCK_PIO; /* PIO holding TCK */ uint32_t TCK_MASK; /* TCK bitmask */ int TDI_PIO; /* PIO holding TDI */ uint32_t TDI_MASK; /* TDI bitmask */ int SRST_PIO; /* PIO holding SRST */ uint32_t SRST_MASK; /* SRST bitmask */ }; static const struct device_t devices[] = { { "rea_ecr", PIOD, P27, PIOA, NC, PIOD, P23, PIOD, P24, PIOD, P26, PIOC, P5 }, { .name = NULL }, }; /* configuration */ static char *at91rm9200_device; /* interface variables */ static const struct device_t *device; static int dev_mem_fd; static void *sys_controller; static uint32_t *pio_base; /* low level command set */ static int at91rm9200_read(void); static void at91rm9200_write(int tck, int tms, int tdi); static void at91rm9200_reset(int trst, int srst); static int at91rm9200_init(void); static int at91rm9200_quit(void); static struct bitbang_interface at91rm9200_bitbang = { .read = at91rm9200_read, .write = at91rm9200_write, .reset = at91rm9200_reset, .blink = 0 }; static int at91rm9200_read(void) { return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) != 0; } static void at91rm9200_write(int tck, int tms, int tdi) { if (tck) pio_base[device->TCK_PIO + PIO_SODR] = device->TCK_MASK; else pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK; if (tms) pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK; else pio_base[device->TMS_PIO + PIO_CODR] = device->TMS_MASK; if (tdi) pio_base[device->TDI_PIO + PIO_SODR] = device->TDI_MASK; else pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK; } /* (1) assert or (0) deassert reset lines */ static void at91rm9200_reset(int trst, int srst) { if (trst == 0) pio_base[device->TRST_PIO + PIO_SODR] = device->TRST_MASK; else if (trst == 1) pio_base[device->TRST_PIO + PIO_CODR] = device->TRST_MASK; if (srst == 0) pio_base[device->SRST_PIO + PIO_SODR] = device->SRST_MASK; else if (srst == 1) pio_base[device->SRST_PIO + PIO_CODR] = device->SRST_MASK; } COMMAND_HANDLER(at91rm9200_handle_device_command) { if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; /* only if the device name wasn't overwritten by cmdline */ if (at91rm9200_device == 0) { at91rm9200_device = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); strcpy(at91rm9200_device, CMD_ARGV[0]); } return ERROR_OK; } static const struct command_registration at91rm9200_command_handlers[] = { { .name = "at91rm9200_device", .handler = &at91rm9200_handle_device_command, .mode = COMMAND_CONFIG, .help = "query armjtagew info", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface at91rm9200_interface = { .name = "at91rm9200", .execute_queue = bitbang_execute_queue, .commands = at91rm9200_command_handlers, .init = at91rm9200_init, .quit = at91rm9200_quit, }; static int at91rm9200_init(void) { const struct device_t *cur_device; cur_device = devices; if (at91rm9200_device == NULL || at91rm9200_device[0] == 0) { at91rm9200_device = "rea_ecr"; LOG_WARNING("No at91rm9200 device specified, using default 'rea_ecr'"); } while (cur_device->name) { if (strcmp(cur_device->name, at91rm9200_device) == 0) { device = cur_device; break; } cur_device++; } if (!device) { LOG_ERROR("No matching device found for %s", at91rm9200_device); return ERROR_JTAG_INIT_FAILED; } bitbang_interface = &at91rm9200_bitbang; dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if (dev_mem_fd < 0) { perror("open"); return ERROR_JTAG_INIT_FAILED; } sys_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, AT91C_BASE_SYS); if (sys_controller == MAP_FAILED) { perror("mmap"); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } pio_base = (uint32_t *)sys_controller + 0x100; /* * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. */ pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK; pio_base[device->TDI_PIO + PIO_OER] = device->TDI_MASK; pio_base[device->TDI_PIO + PIO_PER] = device->TDI_MASK; pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK; pio_base[device->TCK_PIO + PIO_OER] = device->TCK_MASK; pio_base[device->TCK_PIO + PIO_PER] = device->TCK_MASK; pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK; pio_base[device->TMS_PIO + PIO_OER] = device->TMS_MASK; pio_base[device->TMS_PIO + PIO_PER] = device->TMS_MASK; pio_base[device->TRST_PIO + PIO_SODR] = device->TRST_MASK; pio_base[device->TRST_PIO + PIO_OER] = device->TRST_MASK; pio_base[device->TRST_PIO + PIO_PER] = device->TRST_MASK; pio_base[device->SRST_PIO + PIO_SODR] = device->SRST_MASK; pio_base[device->SRST_PIO + PIO_OER] = device->SRST_MASK; pio_base[device->SRST_PIO + PIO_PER] = device->SRST_MASK; pio_base[device->TDO_PIO + PIO_ODR] = device->TDO_MASK; pio_base[device->TDO_PIO + PIO_PPUER] = device->TDO_MASK; pio_base[device->TDO_PIO + PIO_PER] = device->TDO_MASK; return ERROR_OK; } static int at91rm9200_quit(void) { return ERROR_OK; } openocd-0.9.0/src/jtag/drivers/sysfsgpio.c0000644000175000017500000004171612516456302015471 00000000000000/*************************************************************************** * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* 2014-12: Addition of the SWD protocol support is based on the initial work * on bcm2835gpio.c by Paul Fertser and modifications by Jean-Christian de Rivaz. */ /** * @file * This driver implements a bitbang jtag interface using gpio lines via * sysfs. * The aim of this driver implementation is use system GPIOs but avoid the * need for a additional kernel driver. * (Note memory mapped IO is another option, however it doesn't mix well with * the kernel gpiolib driver - which makes sense I guess.) * * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst * must be also be specified. The required jtag gpios are specified via the * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang. * The srst and trst gpios are set via the sysfsgpio_srst_num and * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel * convention of starting from 0. * * The gpios should not be in use by another entity, and must not be requested * by a kernel driver without also being exported by it (otherwise they can't * be exported by sysfs). * * The sysfs gpio interface can only manipulate one gpio at a time, so the * bitbang write handler remembers the last state for tck, tms, tdi to avoid * superfluous writes. * For speed the sysfs "value" entry is opened at init and held open. * This results in considerable gains over open-write-close (45s vs 900s) * * Further work could address: * -srst and trst open drain/ push pull * -configurable active high/low for srst & trst */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitbang.h" /* * Helper func to determine if gpio number valid * * Assume here that there will be less than 1000 gpios on a system */ static int is_gpio_valid(int gpio) { return gpio >= 0 && gpio < 1000; } /* * Helper func to open, write to and close a file * name and valstr must be null terminated. * * Returns negative on failure. */ static int open_write_close(const char *name, const char *valstr) { int ret; int fd = open(name, O_WRONLY); if (fd < 0) return fd; ret = write(fd, valstr, strlen(valstr)); close(fd); return ret; } /* * Helper func to unexport gpio from sysfs */ static void unexport_sysfs_gpio(int gpio) { char gpiostr[4]; if (!is_gpio_valid(gpio)) return; snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0) LOG_ERROR("Couldn't unexport gpio %d", gpio); return; } /* * Exports and sets up direction for gpio. * If the gpio is an output, it is initialized according to init_high, * otherwise it is ignored. * * If the gpio is already exported we just show a warning and continue; if * openocd happened to crash (or was killed by user) then the gpios will not * have been cleaned up. */ static int setup_sysfs_gpio(int gpio, int is_output, int init_high) { char buf[40]; char gpiostr[4]; int ret; if (!is_gpio_valid(gpio)) return ERROR_OK; snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); ret = open_write_close("/sys/class/gpio/export", gpiostr); if (ret < 0) { if (errno == EBUSY) { LOG_WARNING("gpio %d is already exported", gpio); } else { LOG_ERROR("Couldn't export gpio %d", gpio); perror("sysfsgpio: "); return ERROR_FAIL; } } snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio); ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in"); if (ret < 0) { LOG_ERROR("Couldn't set direction for gpio %d", gpio); perror("sysfsgpio: "); unexport_sysfs_gpio(gpio); return ERROR_FAIL; } snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio); ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC); if (ret < 0) { LOG_ERROR("Couldn't open value for gpio %d", gpio); perror("sysfsgpio: "); unexport_sysfs_gpio(gpio); } return ret; } /* gpio numbers for each gpio. Negative values are invalid */ static int tck_gpio = -1; static int tms_gpio = -1; static int tdi_gpio = -1; static int tdo_gpio = -1; static int trst_gpio = -1; static int srst_gpio = -1; static int swclk_gpio = -1; static int swdio_gpio = -1; /* * file descriptors for /sys/class/gpio/gpioXX/value * Set up during init. */ static int tck_fd = -1; static int tms_fd = -1; static int tdi_fd = -1; static int tdo_fd = -1; static int trst_fd = -1; static int srst_fd = -1; static int swclk_fd = -1; static int swdio_fd = -1; static int last_swclk; static int last_swdio; static bool last_stored; static bool swdio_input; static void sysfsgpio_swdio_drive(bool is_output) { char buf[40]; int ret; snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", swdio_gpio); ret = open_write_close(buf, is_output ? "high" : "in"); if (ret < 0) { LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio); perror("sysfsgpio: "); } last_stored = false; swdio_input = !is_output; } static int sysfsgpio_swdio_read(void) { char buf[1]; /* important to seek to signal sysfs of new read */ lseek(swdio_fd, 0, SEEK_SET); int ret = read(swdio_fd, &buf, sizeof(buf)); if (ret < 0) { LOG_WARNING("reading swdio failed"); return 0; } return buf[0] == '1'; } static void sysfsgpio_swdio_write(int swclk, int swdio) { const char one[] = "1"; const char zero[] = "0"; size_t bytes_written; if (!swdio_input) { if (!last_stored || (swdio != last_swdio)) { bytes_written = write(swdio_fd, swdio ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing swdio failed"); } } /* write swclk last */ if (!last_stored || (swclk != last_swclk)) { bytes_written = write(swclk_fd, swclk ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing swclk failed"); } last_swdio = swdio; last_swclk = swclk; last_stored = true; } /* * Bitbang interface read of TDO * * The sysfs value will read back either '0' or '1'. The trick here is to call * lseek to bypass buffering in the sysfs kernel driver. */ static int sysfsgpio_read(void) { char buf[1]; /* important to seek to signal sysfs of new read */ lseek(tdo_fd, 0, SEEK_SET); int ret = read(tdo_fd, &buf, sizeof(buf)); if (ret < 0) { LOG_WARNING("reading tdo failed"); return 0; } return buf[0] == '1'; } /* * Bitbang interface write of TCK, TMS, TDI * * Seeing as this is the only function where the outputs are changed, * we can cache the old value to avoid needlessly writing it. */ static void sysfsgpio_write(int tck, int tms, int tdi) { if (swd_mode) { sysfsgpio_swdio_write(tck, tdi); return; } const char one[] = "1"; const char zero[] = "0"; static int last_tck; static int last_tms; static int last_tdi; static int first_time; size_t bytes_written; if (!first_time) { last_tck = !tck; last_tms = !tms; last_tdi = !tdi; first_time = 1; } if (tdi != last_tdi) { bytes_written = write(tdi_fd, tdi ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tdi failed"); } if (tms != last_tms) { bytes_written = write(tms_fd, tms ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tms failed"); } /* write clk last */ if (tck != last_tck) { bytes_written = write(tck_fd, tck ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tck failed"); } last_tdi = tdi; last_tms = tms; last_tck = tck; } /* * Bitbang interface to manipulate reset lines SRST and TRST * * (1) assert or (0) deassert reset lines */ static void sysfsgpio_reset(int trst, int srst) { LOG_DEBUG("sysfsgpio_reset"); const char one[] = "1"; const char zero[] = "0"; size_t bytes_written; /* assume active low */ if (srst_fd >= 0) { bytes_written = write(srst_fd, srst ? &zero : &one, 1); if (bytes_written != 1) LOG_WARNING("writing srst failed"); } /* assume active low */ if (trst_fd >= 0) { bytes_written = write(trst_fd, trst ? &zero : &one, 1); if (bytes_written != 1) LOG_WARNING("writing trst failed"); } } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums) { if (CMD_ARGC == 4) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d", tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); command_print(CMD_CTX, "SysfsGPIO num: tck = %d", tck_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); command_print(CMD_CTX, "SysfsGPIO num: tms = %d", tms_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); command_print(CMD_CTX, "SysfsGPIO num: tdo = %d", tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); command_print(CMD_CTX, "SysfsGPIO num: tdi = %d", tdi_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); command_print(CMD_CTX, "SysfsGPIO num: srst = %d", srst_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); command_print(CMD_CTX, "SysfsGPIO num: trst = %d", trst_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums) { if (CMD_ARGC == 2) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "SysfsGPIO nums: swclk = %d, swdio = %d", swclk_gpio, swdio_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); command_print(CMD_CTX, "SysfsGPIO num: swclk = %d", swclk_gpio); return ERROR_OK; } COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio); command_print(CMD_CTX, "SysfsGPIO num: swdio = %d", swdio_gpio); return ERROR_OK; } static const struct command_registration sysfsgpio_command_handlers[] = { { .name = "sysfsgpio_jtag_nums", .handler = &sysfsgpio_handle_jtag_gpionums, .mode = COMMAND_CONFIG, .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", .usage = "(tck tms tdi tdo)* ", }, { .name = "sysfsgpio_tck_num", .handler = &sysfsgpio_handle_jtag_gpionum_tck, .mode = COMMAND_CONFIG, .help = "gpio number for tck.", }, { .name = "sysfsgpio_tms_num", .handler = &sysfsgpio_handle_jtag_gpionum_tms, .mode = COMMAND_CONFIG, .help = "gpio number for tms.", }, { .name = "sysfsgpio_tdo_num", .handler = &sysfsgpio_handle_jtag_gpionum_tdo, .mode = COMMAND_CONFIG, .help = "gpio number for tdo.", }, { .name = "sysfsgpio_tdi_num", .handler = &sysfsgpio_handle_jtag_gpionum_tdi, .mode = COMMAND_CONFIG, .help = "gpio number for tdi.", }, { .name = "sysfsgpio_srst_num", .handler = &sysfsgpio_handle_jtag_gpionum_srst, .mode = COMMAND_CONFIG, .help = "gpio number for srst.", }, { .name = "sysfsgpio_trst_num", .handler = &sysfsgpio_handle_jtag_gpionum_trst, .mode = COMMAND_CONFIG, .help = "gpio number for trst.", }, { .name = "sysfsgpio_swd_nums", .handler = &sysfsgpio_handle_swd_gpionums, .mode = COMMAND_CONFIG, .help = "gpio numbers for swclk, swdio. (in that order)", .usage = "(swclk swdio)* ", }, { .name = "sysfsgpio_swclk_num", .handler = &sysfsgpio_handle_swd_gpionum_swclk, .mode = COMMAND_CONFIG, .help = "gpio number for swclk.", }, { .name = "sysfsgpio_swdio_num", .handler = &sysfsgpio_handle_swd_gpionum_swdio, .mode = COMMAND_CONFIG, .help = "gpio number for swdio.", }, COMMAND_REGISTRATION_DONE }; static int sysfsgpio_init(void); static int sysfsgpio_quit(void); static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL }; struct jtag_interface sysfsgpio_interface = { .name = "sysfsgpio", .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, .transports = sysfsgpio_transports, .swd = &bitbang_swd, .commands = sysfsgpio_command_handlers, .init = sysfsgpio_init, .quit = sysfsgpio_quit, }; static struct bitbang_interface sysfsgpio_bitbang = { .read = sysfsgpio_read, .write = sysfsgpio_write, .reset = sysfsgpio_reset, .swdio_read = sysfsgpio_swdio_read, .swdio_drive = sysfsgpio_swdio_drive, .blink = 0 }; /* helper func to close and cleanup files only if they were valid/ used */ static void cleanup_fd(int fd, int gpio) { if (gpio >= 0) { if (fd >= 0) close(fd); unexport_sysfs_gpio(gpio); } } static void cleanup_all_fds(void) { cleanup_fd(tck_fd, tck_gpio); cleanup_fd(tms_fd, tms_gpio); cleanup_fd(tdi_fd, tdi_gpio); cleanup_fd(tdo_fd, tdo_gpio); cleanup_fd(trst_fd, trst_gpio); cleanup_fd(srst_fd, srst_gpio); } static bool sysfsgpio_jtag_mode_possible(void) { if (!is_gpio_valid(tck_gpio)) return 0; if (!is_gpio_valid(tms_gpio)) return 0; if (!is_gpio_valid(tdi_gpio)) return 0; if (!is_gpio_valid(tdo_gpio)) return 0; return 1; } static bool sysfsgpio_swd_mode_possible(void) { if (!is_gpio_valid(swclk_gpio)) return 0; if (!is_gpio_valid(swdio_gpio)) return 0; return 1; } static int sysfsgpio_init(void) { bitbang_interface = &sysfsgpio_bitbang; LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver"); if (sysfsgpio_jtag_mode_possible()) { if (sysfsgpio_swd_mode_possible()) LOG_INFO("JTAG and SWD modes enabled"); else LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)"); if (!is_gpio_valid(trst_gpio) && !is_gpio_valid(srst_gpio)) { LOG_ERROR("Require at least one of trst or srst gpios to be specified"); return ERROR_JTAG_INIT_FAILED; } } else if (sysfsgpio_swd_mode_possible()) { LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)"); } else { LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode"); return ERROR_JTAG_INIT_FAILED; } /* * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. * For SWD, SWCLK and SWDIO are configures as output high. */ if (tck_gpio >= 0) { tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0); if (tck_fd < 0) goto out_error; } if (tms_gpio >= 0) { tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1); if (tms_fd < 0) goto out_error; } if (tdi_gpio >= 0) { tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0); if (tdi_fd < 0) goto out_error; } if (tdo_gpio >= 0) { tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0); if (tdo_fd < 0) goto out_error; } /* assume active low*/ if (trst_gpio >= 0) { trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1); if (trst_fd < 0) goto out_error; } /* assume active low*/ if (srst_gpio >= 0) { srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1); if (srst_fd < 0) goto out_error; } if (swclk_gpio >= 0) { swclk_fd = setup_sysfs_gpio(swclk_gpio, 1, 0); if (swclk_fd < 0) goto out_error; } if (swdio_gpio >= 0) { swdio_fd = setup_sysfs_gpio(swdio_gpio, 1, 0); if (swdio_fd < 0) goto out_error; } if (sysfsgpio_swd_mode_possible()) { if (swd_mode) bitbang_swd_switch_seq(NULL, JTAG_TO_SWD); else bitbang_swd_switch_seq(NULL, SWD_TO_JTAG); } return ERROR_OK; out_error: cleanup_all_fds(); return ERROR_JTAG_INIT_FAILED; } static int sysfsgpio_quit(void) { cleanup_all_fds(); return ERROR_OK; } openocd-0.9.0/src/jtag/drivers/rlink_dtc_cmd.h0000644000175000017500000000751712315575360016250 00000000000000/*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* A command position with the high nybble of 0x0 is reserved for an error condition. * If executed, it stops the DTC and raises the ERROR flag */ #define DTC_CMD_SHIFT_TMS_BYTES(bytes) ((0x1 << 4) | ((bytes) - 1)) /* Shift 1-16 bytes out TMS. TDI is 0. */ /* Bytes to shift follow. */ #define DTC_CMD_SHIFT_TDI_BYTES(bytes) ((0x2 << 4) | ((bytes) - 1)) /* Shift 1-16 bytes out TDI. TMS is 0. */ /* Bytes to shift follow. */ #define DTC_CMD_SHIFT_TDI_AND_TMS_BYTES(bytes) ((0x3 << 4) | ((bytes) - 1)) /* Shift 1-16 byte pairs out TDI and TMS. */ /* Byte pairs to shift follow in TDI, TMS order. */ #define DTC_CMD_SHIFT_TDO_BYTES(bytes) ((0x4 << 4) | ((bytes) - 1)) /* Shift 1-16 bytes in TDO. TMS is unaffected. */ /* Reply buffer contains bytes shifted in. */ #define DTC_CMD_SHIFT_TDIO_BYTES(bytes) ((0x6 << 4) | ((bytes) - 1)) /* Shift 1-16 bytes out TDI and in TDO. TMS is unaffected. */ #define DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(tms, tdi, tdo) ((0x8 << 4) | (\ (tms) ? (1 << 0) : 0 \ ) | (\ (tdi) ? (1 << 1) : 0 \ ) | (\ (tdo) ? (1 << 3) : 0 \ )) /* Single bit shift. * tms and tdi are the levels shifted out on TMS and TDI, respectively. * tdo indicates whether a byte will be returned in the reply buffer with its * least significant bit set to reflect TDO * Care should be taken when tdo is zero, as the underlying code actually does put * that byte in the reply buffer. Setting tdo to zero just moves the pointer back. * The result is that if this command is executed when the reply buffer is already full, * a byte will be written erroneously to memory not belonging to the reply buffer. * This could be worked around at the expense of DTC code space and speed. */ #define DTC_CMD_SHIFT_TMS_BITS(bits) ((0x9 << 4) | ((bits) - 1)) /* Shift 1-8 bits out TMS. */ /* Bits to be shifted out are left justified in the following byte. */ #define DTC_CMD_SHIFT_TDIO_BITS(bits) ((0xe << 4) | ((bits) - 1)) /* Shift 1-8 bits out TDI and in TDO, TMS is unaffected. */ /* Bits to be shifted out are left justified in the following byte. */ /* Bits shifted in are right justified in the byte placed in the reply buffer. */ #define DTC_CMD_STOP (0xf << 4) /* Stop processing the command buffer and wait for the next one. */ /* A shared status byte is updated with bit 0 set when this has happened, * and it is cleared when a new command buffer becomes ready. * The host can poll that byte to see when it is safe to read a reply. */ openocd-0.9.0/src/jtag/drivers/jtag_vpi.c0000644000175000017500000002467012315575360015251 00000000000000/* * JTAG to VPI driver * * Copyright (C) 2013 Franck Jullien, * * See file CREDITS for list of people who contributed to this * project. * * This program 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 2 of * the License, or (at your option) any later version. * * This program 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. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifdef HAVE_ARPA_INET_H #include #endif #define NO_TAP_SHIFT 0 #define TAP_SHIFT 1 #define SERVER_ADDRESS "127.0.0.1" #define SERVER_PORT 5555 #define XFERT_MAX_SIZE 512 #define CMD_RESET 0 #define CMD_TMS_SEQ 1 #define CMD_SCAN_CHAIN 2 #define CMD_SCAN_CHAIN_FLIP_TMS 3 #define CMD_STOP_SIMU 4 int server_port = SERVER_PORT; char *server_address; int sockfd; struct sockaddr_in serv_addr; struct vpi_cmd { int cmd; unsigned char buffer_out[XFERT_MAX_SIZE]; unsigned char buffer_in[XFERT_MAX_SIZE]; int length; int nb_bits; }; static int jtag_vpi_send_cmd(struct vpi_cmd *vpi) { int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd)); if (retval <= 0) return ERROR_FAIL; return ERROR_OK; } static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi) { int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd)); if (retval < (int)sizeof(struct vpi_cmd)) return ERROR_FAIL; return ERROR_OK; } /** * jtag_vpi_reset - ask to reset the JTAG device * @trst: 1 if TRST is to be asserted * @srst: 1 if SRST is to be asserted */ static int jtag_vpi_reset(int trst, int srst) { struct vpi_cmd vpi; vpi.cmd = CMD_RESET; vpi.length = 0; return jtag_vpi_send_cmd(&vpi); } /** * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG * @bits: TMS bits to be written (bit0, bit1 .. bitN) * @nb_bits: number of TMS bits (between 1 and 8) * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=, TDI= * - writing out TCK=1, TMS=, TDI= which triggers the transition * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits) { struct vpi_cmd vpi; int nb_bytes; nb_bytes = DIV_ROUND_UP(nb_bits, 8); vpi.cmd = CMD_TMS_SEQ; memcpy(vpi.buffer_out, bits, nb_bytes); vpi.length = nb_bytes; vpi.nb_bits = nb_bits; return jtag_vpi_send_cmd(&vpi); } /** * jtag_vpi_path_move - ask a TMS sequence transition to JTAG * @cmd: path transition * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=, TDI= * - writing out TCK=1, TMS=, TDI= which triggers the transition * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ static int jtag_vpi_path_move(struct pathmove_command *cmd) { uint8_t trans[DIV_ROUND_UP(cmd->num_states, 8)]; memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8)); for (int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) buf_set_u32(trans, i, 1, 1); tap_set_state(cmd->path[i]); } return jtag_vpi_tms_seq(trans, cmd->num_states); } /** * jtag_vpi_tms - ask a tms command * @cmd: tms command */ static int jtag_vpi_tms(struct tms_command *cmd) { return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits); } static int jtag_vpi_state_move(tap_state_t state) { if (tap_get_state() == state) return ERROR_OK; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), state); int tms_len = tap_get_tms_path_len(tap_get_state(), state); int retval = jtag_vpi_tms_seq(&tms_scan, tms_len); if (retval != ERROR_OK) return retval; tap_set_state(state); return ERROR_OK; } static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift) { struct vpi_cmd vpi; int nb_bytes = DIV_ROUND_UP(nb_bits, 8); vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN; if (bits) memcpy(vpi.buffer_out, bits, nb_bytes); else memset(vpi.buffer_out, 0xff, nb_bytes); vpi.length = nb_bytes; vpi.nb_bits = nb_bits; int retval = jtag_vpi_send_cmd(&vpi); if (retval != ERROR_OK) return retval; retval = jtag_vpi_receive_cmd(&vpi); if (retval != ERROR_OK) return retval; if (bits) memcpy(bits, vpi.buffer_in, nb_bytes); return ERROR_OK; } /** * jtag_vpi_queue_tdi - short description * @bits: bits to be queued on TDI (or NULL if 0 are to be queued) * @nb_bits: number of bits */ static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift) { int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8); uint8_t *xmit_buffer = bits; int xmit_nb_bits = nb_bits; int i = 0; int retval; while (nb_xfer) { if (nb_xfer == 1) { retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], xmit_nb_bits, tap_shift); if (retval != ERROR_OK) return retval; } else { retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], XFERT_MAX_SIZE * 8, NO_TAP_SHIFT); if (retval != ERROR_OK) return retval; xmit_nb_bits -= XFERT_MAX_SIZE * 8; i += XFERT_MAX_SIZE; } nb_xfer--; } return ERROR_OK; } /** * jtag_vpi_clock_tms - clock a TMS transition * @tms: the TMS to be sent * * Triggers a TMS transition (ie. one JTAG TAP state move). */ static int jtag_vpi_clock_tms(int tms) { const uint8_t tms_0 = 0; const uint8_t tms_1 = 1; return jtag_vpi_tms_seq(tms ? &tms_1 : &tms_0, 1); } /** * jtag_vpi_scan - launches a DR-scan or IR-scan * @cmd: the command to launch * * Launch a JTAG IR-scan or DR-scan * * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured. */ static int jtag_vpi_scan(struct scan_command *cmd) { int scan_bits; uint8_t *buf = NULL; int retval = ERROR_OK; scan_bits = jtag_build_buffer(cmd, &buf); if (cmd->ir_scan) { retval = jtag_vpi_state_move(TAP_IRSHIFT); if (retval != ERROR_OK) return retval; } else { retval = jtag_vpi_state_move(TAP_DRSHIFT); if (retval != ERROR_OK) return retval; } if (cmd->end_state == TAP_DRSHIFT) { retval = jtag_vpi_queue_tdi(buf, scan_bits, NO_TAP_SHIFT); if (retval != ERROR_OK) return retval; } else { retval = jtag_vpi_queue_tdi(buf, scan_bits, TAP_SHIFT); if (retval != ERROR_OK) return retval; } if (cmd->end_state != TAP_DRSHIFT) { /* * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it * forward to a stable IRPAUSE or DRPAUSE. */ retval = jtag_vpi_clock_tms(0); if (retval != ERROR_OK) return retval; if (cmd->ir_scan) tap_set_state(TAP_IRPAUSE); else tap_set_state(TAP_DRPAUSE); } retval = jtag_read_buffer(buf, cmd); if (retval != ERROR_OK) return retval; if (buf) free(buf); if (cmd->end_state != TAP_DRSHIFT) { retval = jtag_vpi_state_move(cmd->end_state); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int jtag_vpi_runtest(int cycles, tap_state_t state) { int retval; retval = jtag_vpi_state_move(TAP_IDLE); if (retval != ERROR_OK) return retval; retval = jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT); if (retval != ERROR_OK) return retval; return jtag_vpi_state_move(state); } static int jtag_vpi_stableclocks(int cycles) { return jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT); } static int jtag_vpi_execute_queue(void) { struct jtag_command *cmd; int retval = ERROR_OK; for (cmd = jtag_command_queue; retval == ERROR_OK && cmd != NULL; cmd = cmd->next) { switch (cmd->type) { case JTAG_RESET: retval = jtag_vpi_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: retval = jtag_vpi_runtest(cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); break; case JTAG_STABLECLOCKS: retval = jtag_vpi_stableclocks(cmd->cmd.stableclocks->num_cycles); break; case JTAG_TLR_RESET: retval = jtag_vpi_state_move(cmd->cmd.statemove->end_state); break; case JTAG_PATHMOVE: retval = jtag_vpi_path_move(cmd->cmd.pathmove); break; case JTAG_TMS: retval = jtag_vpi_tms(cmd->cmd.tms); break; case JTAG_SLEEP: jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_SCAN: retval = jtag_vpi_scan(cmd->cmd.scan); break; } } return retval; } static int jtag_vpi_init(void) { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { LOG_ERROR("Could not create socket"); return ERROR_FAIL; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(server_port); if (!server_address) server_address = strdup(SERVER_ADDRESS); serv_addr.sin_addr.s_addr = inet_addr(server_address); if (serv_addr.sin_addr.s_addr == INADDR_NONE) { LOG_ERROR("inet_addr error occured"); return ERROR_FAIL; } if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { close(sockfd); LOG_ERROR("Can't connect to %s : %u", server_address, server_port); return ERROR_COMMAND_CLOSE_CONNECTION; } LOG_INFO("Connection to %s : %u succeed", server_address, server_port); return ERROR_OK; } static int jtag_vpi_quit(void) { free(server_address); return close(sockfd); } COMMAND_HANDLER(jtag_vpi_set_port) { if (CMD_ARGC == 0) LOG_WARNING("You need to set a port number"); else COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); LOG_INFO("Set server port to %u", server_port); return ERROR_OK; } COMMAND_HANDLER(jtag_vpi_set_address) { free(server_address); if (CMD_ARGC == 0) { LOG_WARNING("You need to set an address"); server_address = strdup(SERVER_ADDRESS); } else server_address = strdup(CMD_ARGV[0]); LOG_INFO("Set server address to %s", server_address); return ERROR_OK; } static const struct command_registration jtag_vpi_command_handlers[] = { { .name = "jtag_vpi_set_port", .handler = &jtag_vpi_set_port, .mode = COMMAND_CONFIG, .help = "set the port of the VPI server", .usage = "description_string", }, { .name = "jtag_vpi_set_address", .handler = &jtag_vpi_set_address, .mode = COMMAND_CONFIG, .help = "set the address of the VPI server", .usage = "description_string", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface jtag_vpi_interface = { .name = "jtag_vpi", .supported = DEBUG_CAP_TMS_SEQ, .commands = jtag_vpi_command_handlers, .transports = jtag_only, .init = jtag_vpi_init, .quit = jtag_vpi_quit, .execute_queue = jtag_vpi_execute_queue, }; openocd-0.9.0/src/jtag/drivers/vsllink.c0000644000175000017500000006047412516456303015130 00000000000000/*************************************************************************** * Copyright (C) 2009-2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* Versaloon is a programming tool for multiple MCUs. * It's distributed under GPLv3. * You can find it at http://www.Versaloon.com/. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "versaloon/versaloon_include.h" #include "versaloon/versaloon.h" static int vsllink_tms_offset; struct pending_scan_result { int src_offset; int dest_offset; int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ uint8_t *ack; uint8_t *buffer; bool last; /* indicate the last scan pending */ }; #define MAX_PENDING_SCAN_RESULTS 256 static int pending_scan_results_length; static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; /* Queue command functions */ static void vsllink_end_state(tap_state_t state); static void vsllink_state_move(void); static void vsllink_path_move(int num_states, tap_state_t *path); static void vsllink_tms(int num_bits, const uint8_t *bits); static void vsllink_runtest(int num_cycles); static void vsllink_stableclocks(int num_cycles, int tms); static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void vsllink_reset(int trst, int srst); /* VSLLink tap buffer functions */ static void vsllink_tap_append_step(int tms, int tdi); static void vsllink_tap_init(void); static int vsllink_tap_execute(void); static void vsllink_tap_ensure_pending(int scans); static void vsllink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); /* VSLLink SWD functions */ static int_least32_t vsllink_swd_frequency(struct adiv5_dap *dap, int_least32_t hz); static int vsllink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq); /* VSLLink lowlevel functions */ struct vsllink { struct libusb_context *libusb_ctx; struct libusb_device_handle *usb_device_handle; }; static int vsllink_usb_open(struct vsllink *vsllink); static void vsllink_usb_close(struct vsllink *vsllink); #if defined _DEBUG_JTAG_IO_ static void vsllink_debug_buffer(uint8_t *buffer, int length); #endif static int tap_length; static int tap_buffer_size; static uint8_t *tms_buffer; static uint8_t *tdi_buffer; static uint8_t *tdo_buffer; static bool swd_mode; static struct vsllink *vsllink_handle; static int vsllink_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; int scan_size; enum scan_type type; uint8_t *buffer; DEBUG_JTAG_IO("-------------------------------------" " vsllink " "-------------------------------------"); while (cmd != NULL) { switch (cmd->type) { case JTAG_RUNTEST: DEBUG_JTAG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); vsllink_end_state(cmd->cmd.runtest->end_state); vsllink_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: DEBUG_JTAG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state)); vsllink_end_state(cmd->cmd.statemove->end_state); vsllink_state_move(); break; case JTAG_PATHMOVE: DEBUG_JTAG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); vsllink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); break; case JTAG_SCAN: DEBUG_JTAG_IO("JTAG Scan..."); vsllink_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer( cmd->cmd.scan, &buffer); if (cmd->cmd.scan->ir_scan) DEBUG_JTAG_IO( "JTAG Scan write IR(%d bits), " "end in %s:", scan_size, tap_state_name(cmd->cmd.scan->end_state)); else DEBUG_JTAG_IO( "JTAG Scan write DR(%d bits), " "end in %s:", scan_size, tap_state_name(cmd->cmd.scan->end_state)); #ifdef _DEBUG_JTAG_IO_ vsllink_debug_buffer(buffer, DIV_ROUND_UP(scan_size, 8)); #endif type = jtag_scan_type(cmd->cmd.scan); vsllink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); break; case JTAG_RESET: DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); vsllink_tap_execute(); if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); vsllink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_SLEEP: DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us); vsllink_tap_execute(); jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_STABLECLOCKS: DEBUG_JTAG_IO("add %d clocks", cmd->cmd.stableclocks->num_cycles); switch (tap_get_state()) { case TAP_RESET: /* tms must be '1' to stay * n TAP_RESET mode */ scan_size = 1; break; case TAP_DRSHIFT: case TAP_IDLE: case TAP_DRPAUSE: case TAP_IRSHIFT: case TAP_IRPAUSE: /* else, tms should be '0' */ scan_size = 0; break; /* above stable states are OK */ default: LOG_ERROR("jtag_add_clocks() " "in non-stable state \"%s\"", tap_state_name(tap_get_state()) ); exit(-1); } vsllink_stableclocks(cmd->cmd.stableclocks->num_cycles, scan_size); break; case JTAG_TMS: DEBUG_JTAG_IO("add %d jtag tms", cmd->cmd.tms->num_bits); vsllink_tms(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits); break; default: LOG_ERROR("BUG: unknown JTAG command type " "encountered: %d", cmd->type); exit(-1); } cmd = cmd->next; } return vsllink_tap_execute(); } static int vsllink_speed(int speed) { if (swd_mode) { vsllink_swd_frequency(NULL, speed * 1000); return ERROR_OK; } versaloon_interface.adaptors.jtag_raw.config(0, (uint16_t)speed); return versaloon_interface.adaptors.peripheral_commit(); } static int vsllink_khz(int khz, int *jtag_speed) { *jtag_speed = khz; return ERROR_OK; } static int vsllink_speed_div(int jtag_speed, int *khz) { *khz = jtag_speed; return ERROR_OK; } static void vsllink_free_buffer(void) { if (tdi_buffer != NULL) { free(tdi_buffer); tdi_buffer = NULL; } if (tdo_buffer != NULL) { free(tdo_buffer); tdo_buffer = NULL; } if (tms_buffer != NULL) { free(tms_buffer); tms_buffer = NULL; } } static int vsllink_quit(void) { versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST, 0, 0, GPIO_SRST | GPIO_TRST); versaloon_interface.adaptors.gpio.fini(0); if (swd_mode) versaloon_interface.adaptors.swd.fini(0); else versaloon_interface.adaptors.jtag_raw.fini(0); versaloon_interface.adaptors.peripheral_commit(); versaloon_interface.fini(); vsllink_free_buffer(); vsllink_usb_close(vsllink_handle); free(vsllink_handle); return ERROR_OK; } static int vsllink_interface_init(void) { vsllink_handle = malloc(sizeof(struct vsllink)); if (NULL == vsllink_handle) { LOG_ERROR("unable to allocate memory"); return ERROR_FAIL; } libusb_init(&vsllink_handle->libusb_ctx); if (ERROR_OK != vsllink_usb_open(vsllink_handle)) { LOG_ERROR("Can't find USB JTAG Interface!" \ "Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("vsllink found on %04X:%04X", versaloon_interface.usb_setting.vid, versaloon_interface.usb_setting.pid); versaloon_usb_device_handle = vsllink_handle->usb_device_handle; if (ERROR_OK != versaloon_interface.init()) return ERROR_FAIL; if (versaloon_interface.usb_setting.buf_size < 32) { versaloon_interface.fini(); return ERROR_FAIL; } return ERROR_OK; } static int vsllink_init(void) { int retval = vsllink_interface_init(); if (ERROR_OK != retval) return retval; versaloon_interface.adaptors.gpio.init(0); versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST, GPIO_SRST); versaloon_interface.adaptors.delay.delayms(100); versaloon_interface.adaptors.peripheral_commit(); if (swd_mode) { versaloon_interface.adaptors.gpio.config(0, GPIO_TRST, 0, GPIO_TRST, GPIO_TRST); versaloon_interface.adaptors.swd.init(0); vsllink_swd_frequency(NULL, jtag_get_speed_khz() * 1000); vsllink_swd_switch_seq(NULL, JTAG_TO_SWD); } else { /* malloc buffer size for tap */ tap_buffer_size = versaloon_interface.usb_setting.buf_size / 2 - 32; vsllink_free_buffer(); tdi_buffer = malloc(tap_buffer_size); tdo_buffer = malloc(tap_buffer_size); tms_buffer = malloc(tap_buffer_size); if ((NULL == tdi_buffer) || (NULL == tdo_buffer) || (NULL == tms_buffer)) { vsllink_quit(); return ERROR_FAIL; } versaloon_interface.adaptors.jtag_raw.init(0); versaloon_interface.adaptors.jtag_raw.config(0, jtag_get_speed_khz()); versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST, GPIO_TRST, GPIO_SRST, GPIO_SRST); } if (ERROR_OK != versaloon_interface.adaptors.peripheral_commit()) return ERROR_FAIL; vsllink_reset(0, 0); vsllink_tap_init(); return ERROR_OK; } /************************************************************************** * Queue command implementations */ static void vsllink_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } /* Goes to the end state. */ static void vsllink_state_move(void) { int i; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_scan_bits; i++) vsllink_tap_append_step((tms_scan >> i) & 1, 0); tap_set_state(tap_get_end_state()); } static void vsllink_path_move(int num_states, tap_state_t *path) { for (int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) vsllink_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) vsllink_tap_append_step(1, 0); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); exit(-1); } tap_set_state(path[i]); } tap_set_end_state(tap_get_state()); } static void vsllink_tms(int num_bits, const uint8_t *bits) { for (int i = 0; i < num_bits; i++) vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0); } static void vsllink_stableclocks(int num_cycles, int tms) { while (num_cycles > 0) { vsllink_tap_append_step(tms, 0); num_cycles--; } } static void vsllink_runtest(int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); if (tap_get_state() != TAP_IDLE) { /* enter IDLE state */ vsllink_end_state(TAP_IDLE); vsllink_state_move(); } vsllink_stableclocks(num_cycles, 0); /* post-process */ /* set end_state */ vsllink_end_state(saved_end_state); if (tap_get_end_state() != tap_get_end_state()) vsllink_state_move(); } static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { tap_state_t saved_end_state; saved_end_state = tap_get_end_state(); /* Move to appropriate scan state */ vsllink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); if (tap_get_state() != tap_get_end_state()) vsllink_state_move(); vsllink_end_state(saved_end_state); /* Scan */ vsllink_tap_append_scan(scan_size, buffer, command); /* Goto Pause and record position to insert tms:0 */ vsllink_tap_append_step(0, 0); vsllink_tms_offset = tap_length; tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) vsllink_state_move(); } static void vsllink_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (!srst) versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST, GPIO_SRST); else versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, GPIO_SRST, 0, 0); if (!swd_mode) { if (!trst) versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, GPIO_TRST); else versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, 0); } versaloon_interface.adaptors.peripheral_commit(); } COMMAND_HANDLER(vsllink_handle_usb_vid_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], versaloon_interface.usb_setting.vid); return ERROR_OK; } COMMAND_HANDLER(vsllink_handle_usb_pid_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], versaloon_interface.usb_setting.pid); return ERROR_OK; } COMMAND_HANDLER(vsllink_handle_usb_serial_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; free(versaloon_interface.usb_setting.serialstring); if (CMD_ARGC == 1) versaloon_interface.usb_setting.serialstring = strdup(CMD_ARGV[0]); else versaloon_interface.usb_setting.serialstring = NULL; return ERROR_OK; } COMMAND_HANDLER(vsllink_handle_usb_bulkin_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], versaloon_interface.usb_setting.ep_in); versaloon_interface.usb_setting.ep_in |= 0x80; return ERROR_OK; } COMMAND_HANDLER(vsllink_handle_usb_bulkout_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], versaloon_interface.usb_setting.ep_out); versaloon_interface.usb_setting.ep_out &= ~0x80; return ERROR_OK; } COMMAND_HANDLER(vsllink_handle_usb_interface_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], versaloon_interface.usb_setting.interface); return ERROR_OK; } /************************************************************************** * VSLLink tap functions */ static void vsllink_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; vsllink_tms_offset = 0; } static void vsllink_tap_ensure_pending(int scans) { int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; if (scans > available_scans) vsllink_tap_execute(); } static void vsllink_tap_append_step(int tms, int tdi) { int index_var = tap_length / 8; int bit_index = tap_length % 8; uint8_t bit = 1 << bit_index; if (tms) tms_buffer[index_var] |= bit; else tms_buffer[index_var] &= ~bit; if (tdi) tdi_buffer[index_var] |= bit; else tdi_buffer[index_var] &= ~bit; tap_length++; if (tap_buffer_size * 8 <= tap_length) vsllink_tap_execute(); } static void vsllink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command) { struct pending_scan_result *pending_scan_result; int len_tmp, len_all, i; len_all = 0; while (len_all < length) { vsllink_tap_ensure_pending(1); pending_scan_result = &pending_scan_results_buffer[ pending_scan_results_length]; if ((length - len_all) > (tap_buffer_size * 8 - tap_length)) { /* Use all memory available vsllink_tap_append_step will commit automatically */ len_tmp = tap_buffer_size * 8 - tap_length; pending_scan_result->last = false; } else { len_tmp = length - len_all; pending_scan_result->last = true; } pending_scan_result->src_offset = tap_length; pending_scan_result->dest_offset = len_all; pending_scan_result->length = len_tmp; pending_scan_result->command = command; pending_scan_result->buffer = buffer; pending_scan_results_length++; for (i = 0; i < len_tmp; i++) { vsllink_tap_append_step(((len_all + i) < length-1 ? 0 : 1), (buffer[(len_all + i)/8] >> ((len_all + i)%8)) & 1); } len_all += len_tmp; } } static int vsllink_jtag_execute(void) { int i; int result; if (tap_length <= 0) return ERROR_OK; versaloon_interface.adaptors.jtag_raw.execute(0, tdi_buffer, tms_buffer, tdo_buffer, tap_length); result = versaloon_interface.adaptors.peripheral_commit(); if (result == ERROR_OK) { for (i = 0; i < pending_scan_results_length; i++) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; uint8_t *buffer = pending_scan_result->buffer; int length = pending_scan_result->length; int src_first = pending_scan_result->src_offset; int dest_first = pending_scan_result->dest_offset; bool last = pending_scan_result->last; struct scan_command *command; command = pending_scan_result->command; buf_set_buf(tdo_buffer, src_first, buffer, dest_first, length); #ifdef _DEBUG_JTAG_IO_ DEBUG_JTAG_IO( "JTAG scan read(%d bits, from src %d bits to dest %d bits):", length, src_first, dest_first); vsllink_debug_buffer(buffer + dest_first / 8, DIV_ROUND_UP(length, 7)); #endif if (last) { if (jtag_read_buffer(buffer, command) != ERROR_OK) { vsllink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } if (pending_scan_result->buffer != NULL) free(pending_scan_result->buffer); } } } else { LOG_ERROR("vsllink_jtag_execute failure"); return ERROR_JTAG_QUEUE_FAILED; } vsllink_tap_init(); return ERROR_OK; } static int vsllink_tap_execute(void) { if (swd_mode) return ERROR_OK; return vsllink_jtag_execute(); } static int vsllink_swd_init(void) { LOG_INFO("VSLLink SWD mode enabled"); swd_mode = true; return ERROR_OK; } static int_least32_t vsllink_swd_frequency(struct adiv5_dap *dap, int_least32_t hz) { const int_least32_t delay2hz[] = { 1850000, 235000, 130000, 102000, 85000, 72000 }; if (hz > 0) { uint16_t delay = UINT16_MAX; for (uint16_t i = 0; i < ARRAY_SIZE(delay2hz); i++) { if (hz >= delay2hz[i]) { hz = delay2hz[i]; delay = i; break; } } if (delay == UINT16_MAX) delay = (500000 / hz) - 1; /* Calculate retry count after a WAIT response. This will give * a retry timeout at about ~250 ms. 54 is the number of bits * found in a transaction. */ uint16_t retry_count = 250 * hz / 1000 / 54; LOG_DEBUG("SWD delay: %d, retry count: %d", delay, retry_count); versaloon_interface.adaptors.swd.config(0, 2, retry_count, delay); } return hz; } static int vsllink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq) { switch (seq) { case LINE_RESET: LOG_DEBUG("SWD line reset"); versaloon_interface.adaptors.swd.seqout(0, swd_seq_line_reset, swd_seq_line_reset_len); break; case JTAG_TO_SWD: LOG_DEBUG("JTAG-to-SWD"); versaloon_interface.adaptors.swd.seqout(0, swd_seq_jtag_to_swd, swd_seq_jtag_to_swd_len); break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); versaloon_interface.adaptors.swd.seqout(0, swd_seq_swd_to_jtag, swd_seq_swd_to_jtag_len); break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; } return ERROR_OK; } static void vsllink_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value) { versaloon_interface.adaptors.swd.transact(0, cmd, value, NULL); } static void vsllink_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value) { versaloon_interface.adaptors.swd.transact(0, cmd, &value, NULL); } static int vsllink_swd_run_queue(struct adiv5_dap *dap) { return versaloon_interface.adaptors.peripheral_commit(); } /**************************************************************************** * VSLLink USB low-level functions */ static int vsllink_check_usb_strings( struct libusb_device_handle *usb_device_handle, struct libusb_device_descriptor *usb_desc) { char desc_string[256]; int retval; if (NULL != versaloon_interface.usb_setting.serialstring) { retval = libusb_get_string_descriptor_ascii(usb_device_handle, usb_desc->iSerialNumber, (unsigned char *)desc_string, sizeof(desc_string)); if (retval < 0) return ERROR_FAIL; if (strncmp(desc_string, versaloon_interface.usb_setting.serialstring, sizeof(desc_string))) return ERROR_FAIL; } retval = libusb_get_string_descriptor_ascii(usb_device_handle, usb_desc->iProduct, (unsigned char *)desc_string, sizeof(desc_string)); if (retval < 0) return ERROR_FAIL; if (strstr(desc_string, "Versaloon") == NULL) return ERROR_FAIL; return ERROR_OK; } static int vsllink_usb_open(struct vsllink *vsllink) { ssize_t num_devices, i; libusb_device **usb_devices; struct libusb_device_descriptor usb_desc; struct libusb_device_handle *usb_device_handle; int retval; num_devices = libusb_get_device_list(vsllink->libusb_ctx, &usb_devices); if (num_devices <= 0) return ERROR_FAIL; for (i = 0; i < num_devices; i++) { libusb_device *device = usb_devices[i]; retval = libusb_get_device_descriptor(device, &usb_desc); if (retval != 0) continue; if (usb_desc.idVendor != versaloon_interface.usb_setting.vid || usb_desc.idProduct != versaloon_interface.usb_setting.pid) continue; retval = libusb_open(device, &usb_device_handle); if (retval != 0) continue; retval = vsllink_check_usb_strings(usb_device_handle, &usb_desc); if (ERROR_OK == retval) break; libusb_close(usb_device_handle); } libusb_free_device_list(usb_devices, 1); if (i == num_devices) return ERROR_FAIL; retval = libusb_claim_interface(usb_device_handle, versaloon_interface.usb_setting.interface); if (retval != 0) { LOG_ERROR("unable to claim interface"); libusb_close(usb_device_handle); return ERROR_FAIL; } vsllink->usb_device_handle = usb_device_handle; return ERROR_OK; } static void vsllink_usb_close(struct vsllink *vsllink) { libusb_release_interface(vsllink->usb_device_handle, versaloon_interface.usb_setting.interface); libusb_close(vsllink->usb_device_handle); } #define BYTES_PER_LINE 16 #if defined _DEBUG_JTAG_IO_ static void vsllink_debug_buffer(uint8_t *buffer, int length) { char line[81]; char s[4]; int i; int j; for (i = 0; i < length; i += BYTES_PER_LINE) { snprintf(line, 5, "%04x", i); for (j = i; j < i + BYTES_PER_LINE && j < length; j++) { snprintf(s, 4, " %02x", buffer[j]); strcat(line, s); } LOG_DEBUG("%s", line); } } #endif /* _DEBUG_JTAG_IO_ */ static const struct command_registration vsllink_command_handlers[] = { { .name = "vsllink_usb_vid", .handler = &vsllink_handle_usb_vid_command, .mode = COMMAND_CONFIG, }, { .name = "vsllink_usb_pid", .handler = &vsllink_handle_usb_pid_command, .mode = COMMAND_CONFIG, }, { .name = "vsllink_usb_serial", .handler = &vsllink_handle_usb_serial_command, .mode = COMMAND_CONFIG, }, { .name = "vsllink_usb_bulkin", .handler = &vsllink_handle_usb_bulkin_command, .mode = COMMAND_CONFIG, }, { .name = "vsllink_usb_bulkout", .handler = &vsllink_handle_usb_bulkout_command, .mode = COMMAND_CONFIG, }, { .name = "vsllink_usb_interface", .handler = &vsllink_handle_usb_interface_command, .mode = COMMAND_CONFIG, }, COMMAND_REGISTRATION_DONE }; static const char * const vsllink_transports[] = {"jtag", "swd", NULL}; static const struct swd_driver vsllink_swd_driver = { .init = vsllink_swd_init, .frequency = vsllink_swd_frequency, .switch_seq = vsllink_swd_switch_seq, .read_reg = vsllink_swd_read_reg, .write_reg = vsllink_swd_write_reg, .run = vsllink_swd_run_queue, }; struct jtag_interface vsllink_interface = { .name = "vsllink", .supported = DEBUG_CAP_TMS_SEQ, .commands = vsllink_command_handlers, .transports = vsllink_transports, .swd = &vsllink_swd_driver, .init = vsllink_init, .quit = vsllink_quit, .khz = vsllink_khz, .speed = vsllink_speed, .speed_div = vsllink_speed_div, .execute_queue = vsllink_execute_queue, }; openocd-0.9.0/src/jtag/drivers/usbprog.c0000644000175000017500000004102612315575360015121 00000000000000/*************************************************************************** * Copyright (C) 2007 by Benedikt Sauter * * sauter@ixbat.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * This file is based on Dominic Rath's amt_jtagaccel.c. * * usbprog is a free programming adapter. You can easily install * different firmware versions from an "online pool" over USB. * The adapter can be used for programming and debugging AVR and ARM * processors, as USB to RS232 converter, as JTAG interface or as * simple I/O interface (5 lines). * * http://www.embedded-projects.net/usbprog */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "usb_common.h" #define VID 0x1781 #define PID 0x0c63 /* Pins at usbprog */ #define TDO_BIT 0 #define TDI_BIT 3 #define TCK_BIT 2 #define TMS_BIT 1 static void usbprog_end_state(tap_state_t state); static void usbprog_state_move(void); static void usbprog_path_move(struct pathmove_command *cmd); static void usbprog_runtest(int num_cycles); static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size); #define UNKNOWN_COMMAND 0x00 #define PORT_DIRECTION 0x01 #define PORT_SET 0x02 #define PORT_GET 0x03 #define PORT_SETBIT 0x04 #define PORT_GETBIT 0x05 #define WRITE_TDI 0x06 #define READ_TDO 0x07 #define WRITE_AND_READ 0x08 #define WRITE_TMS 0x09 #define WRITE_TMS_CHAIN 0x0A struct usbprog_jtag { struct usb_dev_handle *usb_handle; }; static struct usbprog_jtag *usbprog_jtag_handle; static struct usbprog_jtag *usbprog_jtag_open(void); /* static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag); */ static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag); static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen); static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char *buffer, int size); static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buffer, int size); static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char *buffer, int size); static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan); static char tms_chain[64]; static int tms_chain_index; static void usbprog_jtag_tms_collect(char tms_scan); static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag); static void usbprog_write(int tck, int tms, int tdi); static void usbprog_reset(int trst, int srst); static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction); static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag, unsigned char value); /* static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag); */ static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag, int bit, int value); /* static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit); */ static int usbprog_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; while (cmd) { switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif usbprog_end_state(cmd->cmd.runtest->end_state); usbprog_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif usbprog_end_state(cmd->cmd.statemove->end_state); usbprog_state_move(); break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif usbprog_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state); #endif usbprog_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) return ERROR_JTAG_QUEUE_FAILED; if (buffer) free(buffer); break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); #endif jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return ERROR_OK; } static int usbprog_init(void) { usbprog_jtag_handle = usbprog_jtag_open(); tms_chain_index = 0; if (usbprog_jtag_handle == 0) { LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } LOG_INFO("USB JTAG Interface ready!"); usbprog_jtag_init(usbprog_jtag_handle); usbprog_reset(0, 0); usbprog_write(0, 0, 0); return ERROR_OK; } static int usbprog_quit(void) { return ERROR_OK; } /*************** jtag execute commands **********************/ static void usbprog_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void usbprog_state_move(void) { uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan); tap_set_state(tap_get_end_state()); } static void usbprog_path_move(struct pathmove_command *cmd) { int num_states = cmd->num_states; int state_count; /* There may be queued transitions, and before following a specified path, we must flush those queued transitions */ usbprog_jtag_tms_send(usbprog_jtag_handle); state_count = 0; while (num_states) { if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) { /* LOG_INFO("1"); */ usbprog_write(0, 0, 0); usbprog_write(1, 0, 0); } else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) { /* LOG_INFO("2"); */ usbprog_write(0, 1, 0); usbprog_write(1, 1, 0); } else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); exit(-1); } tap_set_state(cmd->path[state_count]); state_count++; num_states--; } tap_set_end_state(tap_get_state()); } static void usbprog_runtest(int num_cycles) { int i; /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { usbprog_end_state(TAP_IDLE); usbprog_state_move(); } /* execute num_cycles */ if (num_cycles > 0) { usbprog_jtag_tms_send(usbprog_jtag_handle); usbprog_write(0, 0, 0); } else { usbprog_jtag_tms_send(usbprog_jtag_handle); /* LOG_INFO("NUM CYCLES %i",num_cycles); */ } for (i = 0; i < num_cycles; i++) { usbprog_write(1, 0, 0); usbprog_write(0, 0, 0); } #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name( tap_get_state()), tap_state_name(tap_get_end_state())); #endif /* finish in end_state */ /* usbprog_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) usbprog_state_move(); */ } static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { tap_state_t saved_end_state = tap_get_end_state(); if (ir_scan) usbprog_end_state(TAP_IRSHIFT); else usbprog_end_state(TAP_DRSHIFT); /* Only move if we're not already there */ if (tap_get_state() != tap_get_end_state()) usbprog_state_move(); usbprog_end_state(saved_end_state); usbprog_jtag_tms_send(usbprog_jtag_handle); void (*f)(struct usbprog_jtag *usbprog_jtag, char *buffer_local, int size); switch (type) { case SCAN_OUT: f = &usbprog_jtag_write_tdi; break; case SCAN_IN: f = &usbprog_jtag_read_tdo; break; case SCAN_IO: f = &usbprog_jtag_write_and_read; break; default: LOG_ERROR("unknown scan type: %i", type); exit(-1); } f(usbprog_jtag_handle, (char *)buffer, scan_size); /* The adapter does the transition to PAUSE internally */ if (ir_scan) tap_set_state(TAP_IRPAUSE); else tap_set_state(TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) usbprog_state_move(); } /*************** jtag wrapper functions *********************/ static void usbprog_write(int tck, int tms, int tdi) { unsigned char output_value = 0x00; if (tms) output_value |= (1 << TMS_BIT); if (tdi) output_value |= (1 << TDI_BIT); if (tck) output_value |= (1 << TCK_BIT); usbprog_jtag_write_slice(usbprog_jtag_handle, output_value); } /* (1) assert or (0) deassert reset lines */ static void usbprog_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst) usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0); else usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1); if (srst) usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0); else usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1); } /*************** jtag lowlevel functions ********************/ struct usb_bus *busses; struct usbprog_jtag *usbprog_jtag_open(void) { usb_set_debug(10); usb_init(); const uint16_t vids[] = { VID, 0 }; const uint16_t pids[] = { PID, 0 }; struct usb_dev_handle *dev; if (jtag_usb_open(vids, pids, &dev) != ERROR_OK) return NULL; struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag)); tmp->usb_handle = dev; usb_set_configuration(dev, 1); usb_claim_interface(dev, 0); usb_set_altinterface(dev, 0); return tmp; } #if 0 static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag) { usb_close(usbprog_jtag->usb_handle); free(usbprog_jtag); } #endif static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen) { int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg, msglen, 100); if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \ (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9)) return 1; if (res == msglen) { /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */ res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100); if (res > 0) return (unsigned char)msg[1]; else return -1; } else return -1; return 0; } static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag) { usbprog_jtag_set_direction(usbprog_jtag, 0xFE); } static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char *buffer, int size) { char tmp[64]; /* fastes packet size for usb controller */ int send_bits, bufindex = 0, fillindex = 0, i, loops; char swap; /* 61 byte can be transfered (488 bit) */ while (size > 0) { if (size > 488) { send_bits = 488; size = size - 488; loops = 61; } else { send_bits = size; loops = size / 8; loops++; size = 0; } tmp[0] = WRITE_AND_READ; tmp[1] = (char)(send_bits >> 8); /* high */ tmp[2] = (char)(send_bits); /* low */ for (i = 0; i < loops; i++) { tmp[3 + i] = buffer[bufindex]; bufindex++; } if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64) { /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */ usleep(1); int timeout = 0; while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1) { timeout++; if (timeout > 10) break; } for (i = 0; i < loops; i++) { swap = tmp[3 + i]; buffer[fillindex++] = swap; } } } } static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char *buffer, int size) { char tmp[64]; /* fastes packet size for usb controller */ int send_bits, fillindex = 0, i, loops; char swap; /* 61 byte can be transfered (488 bit) */ while (size > 0) { if (size > 488) { send_bits = 488; size = size - 488; loops = 61; } else { send_bits = size; loops = size / 8; loops++; size = 0; } tmp[0] = WRITE_AND_READ; tmp[1] = (char)(send_bits >> 8); /* high */ tmp[2] = (char)(send_bits); /* low */ usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000); /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */ int timeout = 0; usleep(1); while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1) { timeout++; if (timeout > 10) break; } for (i = 0; i < loops; i++) { swap = tmp[3 + i]; buffer[fillindex++] = swap; } } } static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buffer, int size) { char tmp[64]; /* fastes packet size for usb controller */ int send_bits, bufindex = 0, i, loops; /* 61 byte can be transfered (488 bit) */ while (size > 0) { if (size > 488) { send_bits = 488; size = size - 488; loops = 61; } else { send_bits = size; loops = size/8; /* if (loops == 0) */ loops++; size = 0; } tmp[0] = WRITE_TDI; tmp[1] = (char)(send_bits >> 8); /* high */ tmp[2] = (char)(send_bits); /* low */ for (i = 0; i < loops; i++) { tmp[3 + i] = buffer[bufindex]; bufindex++; } usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000); } } static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan) { usbprog_jtag_tms_collect(tms_scan); } static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction) { char tmp[2]; tmp[0] = PORT_DIRECTION; tmp[1] = (char)direction; usbprog_jtag_message(usbprog_jtag, tmp, 2); } static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag, unsigned char value) { char tmp[2]; tmp[0] = PORT_SET; tmp[1] = (char)value; usbprog_jtag_message(usbprog_jtag, tmp, 2); } #if 0 static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag) { char tmp[2]; tmp[0] = PORT_GET; tmp[1] = 0x00; return usbprog_jtag_message(usbprog_jtag, tmp, 2); } #endif static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag, int bit, int value) { char tmp[3]; tmp[0] = PORT_SETBIT; tmp[1] = (char)bit; if (value == 1) tmp[2] = 0x01; else tmp[2] = 0x00; usbprog_jtag_message(usbprog_jtag, tmp, 3); } #if 0 static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit) { char tmp[2]; tmp[0] = PORT_GETBIT; tmp[1] = (char)bit; if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0) return 1; else return 0; } #endif static void usbprog_jtag_tms_collect(char tms_scan) { tms_chain[tms_chain_index] = tms_scan; tms_chain_index++; } static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag) { int i; /* LOG_INFO("TMS SEND"); */ if (tms_chain_index > 0) { char tmp[tms_chain_index + 2]; tmp[0] = WRITE_TMS_CHAIN; tmp[1] = (char)(tms_chain_index); for (i = 0; i < tms_chain_index + 1; i++) tmp[2 + i] = tms_chain[i]; usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000); tms_chain_index = 0; } } struct jtag_interface usbprog_interface = { .name = "usbprog", .execute_queue = usbprog_execute_queue, .init = usbprog_init, .quit = usbprog_quit }; openocd-0.9.0/src/jtag/drivers/bitq.c0000644000175000017500000002132212315575360014374 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bitq.h" #include struct bitq_interface *bitq_interface; /* low level bit queue interface */ /* state of input queue */ struct bitq_state { struct jtag_command *cmd; /* command currently processed */ int field_idx; /* index of field currently being processed */ int bit_pos; /* position of bit currently being processed */ int status; /* processing status */ }; static struct bitq_state bitq_in_state; /* * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead * no parameters, makes use of stored state information */ static void bitq_in_proc(void) { /* loop through the queue */ while (bitq_in_state.cmd) { /* only JTAG_SCAN command may return data */ if (bitq_in_state.cmd->type == JTAG_SCAN) { /* loop through the fields */ while (bitq_in_state.field_idx < bitq_in_state.cmd->cmd.scan->num_fields) { struct scan_field *field; field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx]; if (field->in_value) { /* field scanning */ while (bitq_in_state.bit_pos < field->num_bits) { /* index of byte being scanned */ int in_idx = bitq_in_state.bit_pos / 8; /* mask of next bit to be scanned */ uint8_t in_mask = 1 << (bitq_in_state.bit_pos % 8); int tdo = bitq_interface->in(); if (tdo < 0) { #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("bitq in EOF"); #endif return; } if (in_mask == 0x01) field->in_value[in_idx] = 0; if (tdo) field->in_value[in_idx] |= in_mask; bitq_in_state.bit_pos++; } } bitq_in_state.field_idx++; /* advance to next field */ bitq_in_state.bit_pos = 0; /* start next field from the first bit */ } } bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */ bitq_in_state.field_idx = 0; /* preselect first field */ } } static void bitq_io(int tms, int tdi, int tdo_req) { bitq_interface->out(tms, tdi, tdo_req); /* check and process the input queue */ if (bitq_interface->in_rdy()) bitq_in_proc(); } static void bitq_end_state(tap_state_t state) { if (!tap_is_state_stable(state)) { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } tap_set_end_state(state); } static void bitq_state_move(tap_state_t new_state) { int i = 0; uint8_t tms_scan; if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state)) { LOG_ERROR("TAP move from or to unstable state"); exit(-1); } tms_scan = tap_get_tms_path(tap_get_state(), new_state); int tms_count = tap_get_tms_path_len(tap_get_state(), new_state); for (i = 0; i < tms_count; i++) { bitq_io(tms_scan & 1, 0, 0); tms_scan >>= 1; } tap_set_state(new_state); } static void bitq_path_move(struct pathmove_command *cmd) { int i; for (i = 0; i <= cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) bitq_io(0, 0, 0); else if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) bitq_io(1, 0, 0); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name( tap_get_state()), tap_state_name(cmd->path[i])); exit(-1); } tap_set_state(cmd->path[i]); } tap_set_end_state(tap_get_state()); } static void bitq_runtest(int num_cycles) { int i; /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) bitq_state_move(TAP_IDLE); /* execute num_cycles */ for (i = 0; i < num_cycles; i++) bitq_io(0, 0, 0); /* finish in end_state */ if (tap_get_state() != tap_get_end_state()) bitq_state_move(tap_get_end_state()); } static void bitq_scan_field(struct scan_field *field, int do_pause) { int bit_cnt; int tdo_req; const uint8_t *out_ptr; uint8_t out_mask; if (field->in_value) tdo_req = 1; else tdo_req = 0; if (field->out_value == NULL) { /* just send zeros and request data from TDO */ for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) bitq_io(0, 0, tdo_req); bitq_io(do_pause, 0, tdo_req); } else { /* send data, and optionally request TDO */ out_mask = 0x01; out_ptr = field->out_value; for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) { bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req); if (out_mask == 0x80) { out_mask = 0x01; out_ptr++; } else out_mask <<= 1; } bitq_io(do_pause, ((*out_ptr) & out_mask) != 0, tdo_req); } if (do_pause) { bitq_io(0, 0, 0); if (tap_get_state() == TAP_IRSHIFT) tap_set_state(TAP_IRPAUSE); else if (tap_get_state() == TAP_DRSHIFT) tap_set_state(TAP_DRPAUSE); } } static void bitq_scan(struct scan_command *cmd) { int i; if (cmd->ir_scan) bitq_state_move(TAP_IRSHIFT); else bitq_state_move(TAP_DRSHIFT); for (i = 0; i < cmd->num_fields - 1; i++) bitq_scan_field(&cmd->fields[i], 0); bitq_scan_field(&cmd->fields[i], 1); } int bitq_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ bitq_in_state.cmd = jtag_command_queue; bitq_in_state.field_idx = 0; bitq_in_state.bit_pos = 0; bitq_in_state.status = ERROR_OK; while (cmd) { switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) tap_set_state(TAP_RESET); bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); if (bitq_interface->in_rdy()) bitq_in_proc(); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif bitq_end_state(cmd->cmd.runtest->end_state); bitq_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif bitq_end_state(cmd->cmd.statemove->end_state); bitq_state_move(tap_get_end_state()); /* uncoditional TAP move */ break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif bitq_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state); if (cmd->cmd.scan->ir_scan) LOG_DEBUG("scan ir"); else LOG_DEBUG("scan dr"); #endif bitq_end_state(cmd->cmd.scan->end_state); bitq_scan(cmd->cmd.scan); if (tap_get_state() != tap_get_end_state()) bitq_state_move(tap_get_end_state()); break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); #endif bitq_interface->sleep(cmd->cmd.sleep->us); if (bitq_interface->in_rdy()) bitq_in_proc(); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } bitq_interface->flush(); bitq_in_proc(); if (bitq_in_state.cmd) { LOG_ERROR("missing data from bitq interface"); return ERROR_JTAG_QUEUE_FAILED; } if (bitq_interface->in() >= 0) { LOG_ERROR("extra data from bitq interface"); return ERROR_JTAG_QUEUE_FAILED; } return bitq_in_state.status; } void bitq_cleanup(void) { } openocd-0.9.0/src/jtag/drivers/bitq.h0000644000175000017500000000374012315575360014405 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef BITQ_H #define BITQ_H #include struct bitq_interface { /* function to enqueueing low level IO requests */ int (*out)(int tms, int tdi, int tdo_req); int (*flush)(void); int (*sleep)(unsigned long us); int (*reset)(int trst, int srst); /* delayed read of requested TDO data, * the input shall be checked after call to any enqueuing function */ int (*in_rdy)(void); int (*in)(void); }; extern struct bitq_interface *bitq_interface; int bitq_execute_queue(void); void bitq_cleanup(void); #endif /* BITQ_H */ openocd-0.9.0/src/jtag/drivers/driver.c0000644000175000017500000003100112315575360014723 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include struct jtag_callback_entry { struct jtag_callback_entry *next; jtag_callback_t callback; jtag_callback_data_t data0; jtag_callback_data_t data1; jtag_callback_data_t data2; jtag_callback_data_t data3; }; static struct jtag_callback_entry *jtag_callback_queue_head; static struct jtag_callback_entry *jtag_callback_queue_tail; static void jtag_callback_queue_reset(void) { jtag_callback_queue_head = NULL; jtag_callback_queue_tail = NULL; } /** * Copy a struct scan_field for insertion into the queue. * * This allocates a new copy of out_value using cmd_queue_alloc. */ static void cmd_queue_scan_field_clone(struct scan_field *dst, const struct scan_field *src) { dst->num_bits = src->num_bits; dst->out_value = buf_cpy(src->out_value, cmd_queue_alloc(DIV_ROUND_UP(src->num_bits, 8)), src->num_bits); dst->in_value = src->in_value; } /** * see jtag_add_ir_scan() * */ int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *in_fields, tap_state_t state) { size_t num_taps = jtag_tap_count_enabled(); struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); struct scan_field *out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field)); jtag_queue_command(cmd); cmd->type = JTAG_SCAN; cmd->cmd.scan = scan; scan->ir_scan = true; scan->num_fields = num_taps; /* one field per device */ scan->fields = out_fields; scan->end_state = state; struct scan_field *field = out_fields; /* keep track where we insert data */ /* loop over all enabled TAPs */ for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) { /* search the input field list for fields for the current TAP */ if (tap == active) { /* if TAP is listed in input fields, copy the value */ tap->bypass = 0; cmd_queue_scan_field_clone(field, in_fields); } else { /* if a TAP isn't listed in input fields, set it to BYPASS */ tap->bypass = 1; field->num_bits = tap->ir_length; field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length); field->in_value = NULL; /* do not collect input for tap's in bypass */ } /* update device information */ buf_cpy(field->out_value, tap->cur_instr, tap->ir_length); field++; } /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */ assert(field == out_fields + num_taps); return ERROR_OK; } /** * see jtag_add_dr_scan() * */ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state) { /* count devices in bypass */ size_t bypass_devices = 0; for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) { if (tap->bypass) bypass_devices++; } struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field)); jtag_queue_command(cmd); cmd->type = JTAG_SCAN; cmd->cmd.scan = scan; scan->ir_scan = false; scan->num_fields = in_num_fields + bypass_devices; scan->fields = out_fields; scan->end_state = state; struct scan_field *field = out_fields; /* keep track where we insert data */ /* loop over all enabled TAPs */ for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) { /* if TAP is not bypassed insert matching input fields */ if (!tap->bypass) { assert(active == tap); #ifndef NDEBUG /* remember initial position for assert() */ struct scan_field *start_field = field; #endif /* NDEBUG */ for (int j = 0; j < in_num_fields; j++) { cmd_queue_scan_field_clone(field, in_fields + j); field++; } assert(field > start_field); /* must have at least one input field per not bypassed TAP */ } /* if a TAP is bypassed, generated a dummy bit*/ else { field->num_bits = 1; field->out_value = NULL; field->in_value = NULL; field++; } } assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */ return ERROR_OK; } static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state, bool ir_scan) { struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field)); jtag_queue_command(cmd); cmd->type = JTAG_SCAN; cmd->cmd.scan = scan; scan->ir_scan = ir_scan; scan->num_fields = 1; scan->fields = out_fields; scan->end_state = state; out_fields->num_bits = num_bits; out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits); out_fields->in_value = in_bits; return ERROR_OK; } int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false); } int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true); } int interface_jtag_add_tlr(void) { tap_state_t state = TAP_RESET; /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_TLR_RESET; cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command)); cmd->cmd.statemove->end_state = state; return ERROR_OK; } int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) { struct jtag_command *cmd; cmd = cmd_queue_alloc(sizeof(struct jtag_command)); if (cmd == NULL) return ERROR_FAIL; cmd->type = JTAG_TMS; cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms)); if (!cmd->cmd.tms) return ERROR_FAIL; /* copy the bits; our caller doesn't guarantee they'll persist */ cmd->cmd.tms->num_bits = num_bits; cmd->cmd.tms->bits = buf_cpy(seq, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits); if (!cmd->cmd.tms->bits) return ERROR_FAIL; jtag_queue_command(cmd); return ERROR_OK; } int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_PATHMOVE; cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command)); cmd->cmd.pathmove->num_states = num_states; cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states); for (int i = 0; i < num_states; i++) cmd->cmd.pathmove->path[i] = path[i]; return ERROR_OK; } int interface_jtag_add_runtest(int num_cycles, tap_state_t state) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_RUNTEST; cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command)); cmd->cmd.runtest->num_cycles = num_cycles; cmd->cmd.runtest->end_state = state; return ERROR_OK; } int interface_jtag_add_clocks(int num_cycles) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_STABLECLOCKS; cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command)); cmd->cmd.stableclocks->num_cycles = num_cycles; return ERROR_OK; } int interface_jtag_add_reset(int req_trst, int req_srst) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_RESET; cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command)); cmd->cmd.reset->trst = req_trst; cmd->cmd.reset->srst = req_srst; return ERROR_OK; } int interface_jtag_add_sleep(uint32_t us) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); jtag_queue_command(cmd); cmd->type = JTAG_SLEEP; cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command)); cmd->cmd.sleep->us = us; return ERROR_OK; } /* add callback to end of queue */ void interface_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry)); entry->next = NULL; entry->callback = callback; entry->data0 = data0; entry->data1 = data1; entry->data2 = data2; entry->data3 = data3; if (jtag_callback_queue_head == NULL) { jtag_callback_queue_head = entry; jtag_callback_queue_tail = entry; } else { jtag_callback_queue_tail->next = entry; jtag_callback_queue_tail = entry; } } int interface_jtag_execute_queue(void) { static int reentry; assert(reentry == 0); reentry++; int retval = default_interface_jtag_execute_queue(); if (retval == ERROR_OK) { struct jtag_callback_entry *entry; for (entry = jtag_callback_queue_head; entry != NULL; entry = entry->next) { retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3); if (retval != ERROR_OK) break; } } jtag_command_queue_reset(); jtag_callback_queue_reset(); reentry--; return retval; } static int jtag_convert_to_callback4(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { ((jtag_callback1_t)data1)(data0); return ERROR_OK; } void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) { jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0); } void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0) { interface_jtag_add_callback(f, data0); } void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { interface_jtag_add_callback4(f, data0, data1, data2, data3); } openocd-0.9.0/src/jtag/drivers/rlink_call.m40000644000175000017500000003072712315575360015656 00000000000000m4_divert(`-1') /*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ m4_dnl Setup and hold times depend on SHIFTER_PRESCALER m4_define(`SETUP_DELAY_CYCLES', m4_eval(`('SHIFTER_PRESCALER` + 1) / 2')) m4_define(`HOLD_DELAY_CYCLES', m4_eval(`'SHIFTER_PRESCALER` / 2')) m4_dnl Some macros to make nybble handling a little easier m4_define(`m4_high_nybble', `m4_eval(`(($1) >> 4) & 0xf')') m4_define(`m4_low_nybble', `m4_eval(`($1) & 0xf')') m4_dnl A macro to generate a number of NOPs depending on the argument m4_define(`m4_0_to_5_nops', `m4_ifelse(m4_eval(`($1) >= 1'), 1, ` NOP 'm4_ifelse(m4_eval(`($1) >= 2'), 1, ` NOP 'm4_ifelse(m4_eval(`($1) >= 3'), 1, ` NOP 'm4_ifelse(m4_eval(`($1) >= 4'), 1, ` NOP 'm4_ifelse(m4_eval(`($1) >= 5'), 1, ` NOP ')))))') m4_dnl Some macros to facilitate bit-banging delays. m4_dnl There are 3 of them. One for self-contained delays, and two for those which must be split between setup and loop to keep from disturbing A at delay time. m4_dnl The argument passed to any of them is the number of cycles which the delay should consume. m4_dnl This one is self-contained. m4_define(`m4_delay', `; delay (m4_eval($1) cycles)' `m4_ifelse(m4_eval(`('$1`) < 6'), 1, m4_0_to_5_nops($1) , m4_ifelse(m4_eval(`(('$1`) - 3) % 2'), 1, ` NOP') A.H = m4_high_nybble(`(('$1`) - 3) / 2') A.L = m4_low_nybble(`(('$1`) - 3) / 2') Y = A DECY JP -1 )') m4_dnl These are the setup and loop parts of the split delay. m4_dnl The argument passed to both must match for the result to make sense. m4_dnl The setup does not figure into the delay. It takes 3 cycles when a loop is used and none if nops are used. m4_define(`m4_delay_setup', `; delay setup (m4_eval($1) cycles)' `m4_ifelse(m4_eval(`('$1`) < 6'), 0, ` ' A.H = m4_high_nybble(`('$1`) / 2') A.L = m4_low_nybble(`('$1`) / 2') Y = A )') m4_define(`m4_delay_loop', `; delay loop (m4_eval($1) cycles)' `m4_ifelse(m4_eval(`('$1`) < 6'), 1, m4_0_to_5_nops($1) , m4_ifelse(m4_eval(`('$1`) % 2'), 1, ` NOP') DECY JP -1 )') m4_dnl These are utility macros for use with delays. Specifically, there is code below which needs some predictability in code size for relative jumps to reach. The m4_delay macro generates an extra NOP when an even delay is needed, and the m4_delay_loop macro generates an extra NOP when an odd delay is needed. Using this for the argument to the respective macro rounds up the argument so that the extra NOP will not be generated. There is also logic built in to cancel the rounding when the result is small enough that a loop would not be generated. m4_define(`m4_delay_loop_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) + 1) / 2 * 2'))') m4_define(`m4_delay_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) / 2 * 2) + 1'))') m4_divert(`0')m4_dnl ;------------------------------------------------------------------------------ :opcode_error ; This is at address 0x00 in case of empty LUT entries STATUS STOP ERROR ;------------------------------------------------------------------------------ ; Command interpreter at address 0x01 because it is branched to a lot and having it be 0x01 means we can use X for it, which is already used for other purposes which want it to be 1. ; Assumes X is 1 ; Assumes ADR_BUFFER0 points to the next command byte ; Stores the current command byte in CMP01 :command_interpreter A = DATA_BUFFER0 ADR_BUFFER0 += X CMP01 = A ; store the current command for later EXCHANGE ; put MSN into LSN A.H = 0xc ; lookup table at 0x1550 + 0xc0 = 0x1610 ; branch to address in lookup table Y = A A = BRANCH ;------------------------------------------------------------------------------ ; LUT for high nybble ;LUT; c0 opcode_error ;LUT; c1 opcode_shift_tdi_andor_tms_bytes ;LUT; c2 opcode_shift_tdi_andor_tms_bytes ;LUT; c3 opcode_shift_tdi_andor_tms_bytes ;LUT; c4 opcode_shift_tdo_bytes ;LUT; c5 opcode_error ;LUT; c6 opcode_shift_tdio_bytes ;LUT; c7 opcode_error ;LUT; c8 opcode_shift_tms_tdi_bit_pair ;LUT; c9 opcode_shift_tms_bits ;LUT; ca opcode_error ;LUT; cb opcode_error ;LUT; cc opcode_error ;LUT; cd opcode_error ;LUT; ce opcode_shift_tdio_bits ;LUT; cf opcode_stop ;------------------------------------------------------------------------------ ; USB/buffer handling ; ;ENTRY; download entry_download opcode_stop: opcode_next_buffer: ; pointer to completion flag A.H = 0xf A.L = 0xf Y = A A = OR_MPEG ; buffer indicator from previous iteration = A ; either indicator will have bit 0 set BSET 1 ; was buffer 1 previously current? ; A.H = 0 ; already zero from OR_MPEG JP opcode_next_buffer_0 opcode_next_buffer_1: A.L = 0x1 ; ack buffer 0 BUFFER_MNGT = A ; A.H = 0x0 ; already zero from BUFFER_MNGT A.L = 0x3 ; Input buffer 1 = 0x1850 (0x0300) JP +4 opcode_next_buffer_0: A.L = 0x2 ; ack buffer 1 BUFFER_MNGT = A entry_download: A = X ; Input buffer 0 = 0x1650 (0x0100) ADR_BUFFER01 = A OR_MPEG = A ; store for next iteration A.L = 0x0 BUFFER_MNGT = A ; finish acking previous buffer Y = A ADR_BUFFER00 = A ADR_BUFFER11 = A A.H = 0x4 ; Output buffer = 0x1590 (0x0040) ADR_BUFFER10 = A EXCHANGE ; 0x04 X = A ; for the spin loop below ; pointer to status in shared memory DECY ; setting to 0 above and decrementing here saves a byte ; wait until a command buffer is available A = BUFFER_MNGT ; spin while neither of bits 2 or 3 are set CP A = A ; update status once done spinning ; restore X, since we used it ; A.H = 0 ; high nybble of BUFFER_MNGT will always be 0 the way we use it A.L = 1 X = A ; go to command interpreter BRANCH ;;------------------------------------------------------------------------------ ;:opcode_stop ;; ; ; ; Ack buffer 0 in download mode ; A.L = 0x1 ; BUFFER_MNGT = A ; ; STATUS STOP ;------------------------------------------------------------------------------ :opcode_shift_tdi_andor_tms_bytes ; A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1 A.H = 0 Y = A ; loop counter A = CMP01 EXCHANGE CMP01 = A ; we're interested in bits in the high nybble opcode_shift_tdi_andor_tms_bytes__loop: ; set tdi to supplied byte or zero A = CMP01 BSET 1 JP +4 A.H = 0 A.L = 0 JP +3 A = DATA_BUFFER0 ADR_BUFFER0 += X SHIFT_MPEG = A ; set tms to supplied byte or zero A = CMP01 BCLR 0 JP +5 A = DATA_BUFFER0 ADR_BUFFER0 += X SHIFT_CARD = A SHIFT CARD OUT=>PIN0 ; run both shifters as nearly simultaneously as possible SHIFT MPEG OUT=>PIN1 A = CTRL_FCI EXCHANGE BCLR 3 JP -3 DECY JP opcode_shift_tdi_andor_tms_bytes__loop A = X BRANCH ;------------------------------------------------------------------------------ :opcode_shift_tdo_bytes ; A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1 A.H = 0 Y = A ; loop counter opcode_shift_tdo_bytes__loop: SHIFT MPEG PIN0=>IN A = CTRL_FCI EXCHANGE BCLR 3 JP -3 ; put shifted byte into output buffer A = SHIFT_MPEG DATA_BUFFER1 = A ADR_BUFFER1 += X DECY JP opcode_shift_tdo_bytes__loop A = X BRANCH ;------------------------------------------------------------------------------ :opcode_shift_tdio_bytes ; A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1 A.H = 0 CMP10 = A ; byte loop counter A.H = opcode_shift_tdio_bytes__sub_return A.L = opcode_shift_tdio_bytes__sub_return CMP00 = A ; return address opcode_shift_tdio_bytes__loop: A.H = 0 A.L = 7 CMP11 = A ; always use 8 bits JP sub_shift_tdio_bits opcode_shift_tdio_bytes__sub_return: A = CMP10 ; byte loop counter CP A=>X CLC A -= X CMP10 = A JP opcode_shift_tdio_bytes__loop A = X ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it BRANCH ;------------------------------------------------------------------------------ :opcode_shift_tdio_bits ; A = CMP01 ; bits 2..0 contain the number of bits to shift - 1 A.H = 0 BCLR 3 ; set TMS=1 if bit 3 was set CMP11 = A ; bit loop counter A.H = opcode_shift_tdio_bits__sub_return A.L = opcode_shift_tdio_bits__sub_return CMP00 = A ; return address JP sub_shift_tdio_bits A.L = 0x1 ; TMS=1 DR_CARD = A JP sub_shift_tdio_bits opcode_shift_tdio_bits__sub_return: A = X ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it BRANCH ;------------------------------------------------------------------------------ :sub_shift_tdio_bits ; A = DATA_BUFFER0 ; get byte from input buffer ADR_BUFFER0 += X MASK = A ; put it in MASK where bit routine will use it :sub_shift_tdio_bits__loop m4_delay_setup(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1)) A = MASK ; shift TDO into and TDI out of MASK via carry A += MASK MASK = A ; shifting out TDI A.L = 0x2 ; TCK=0, TDI=1 CP CARRY JP +2 A.L = 0x0 ; TCK=0, TDI=0 DR_MPEG = A m4_delay_loop(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1)) BSET 2 ; TCK high DR_MPEG = A A = DR_MPEG ; set carry bit to TDO CLC BCLR 0 JP +2 SEC m4_delay(HOLD_DELAY_CYCLES - 10) A = CMP11 ; bit loop counter Y = A ; use Y to avoid corrupting carry bit with subtract DECY A = Y CMP11 = A JP :sub_shift_tdio_bits__loop ; shift last TDO bit into result A = MASK A += MASK DATA_BUFFER1 = A ADR_BUFFER1 += X A = CMP00 ; return to caller BRANCH ;------------------------------------------------------------------------------ :opcode_shift_tms_tdi_bit_pair ; ; set TMS line manually A = CMP01 ; bits 3..0 contain TDI and TMS bits and whether to return TDO BSET 0 ; TMS bit A.L = 0x1 ; TMS=1 JP +2 A.L = 0x0 ; TMS=0 DR_CARD = A ; stuff command buffer with bitmap of single TDI bit A = CMP01 BSET 1 ; TDI bit A.H = 0x8 ; TDI=1 JP +2 A.H = 0x0 ; TDI=0 ADR_BUFFER0 -= X DATA_BUFFER0 = A A.H = 0 A.L = 0 CMP11 = A ; bit loop counter (only doing one bit) A.H = opcode_shift_tms_tdi_bit_pair__sub_return A.L = opcode_shift_tms_tdi_bit_pair__sub_return CMP00 = A ; return address ; jump this way due to relative jump range issues A.H = sub_shift_tdio_bits A.L = sub_shift_tdio_bits BRANCH opcode_shift_tms_tdi_bit_pair__sub_return: A = CMP01 BSET 3 ; bit says whether to return TDO JP +2 ADR_BUFFER1 -= X ; subroutine returns it, so undo that A = X DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it BRANCH ;------------------------------------------------------------------------------ :opcode_shift_tms_bits ; A = CMP01 ; bits 3..0 contain the number of bits to shift - 1 (only 1-8 bits is valid... no checking, just improper operation) A.H = 0 CMP11 = A ; bit loop counter A = DATA_BUFFER0 ; get byte from input buffer ADR_BUFFER0 += X MASK = A ; The byte we'll be shifting :opcode_shift_tms_bits__loop m4_delay_setup(SETUP_DELAY_CYCLES - 1) A = MASK ; shift TMS out of MASK via carry A += MASK MASK = A ; shifting out TMS A.L = 0x1 ; TCK=0, TDI=0, TMS=1 CP CARRY JP +2 A.L = 0x0 ; TCK=0, TDI=0, TMS=0 DR_CARD = A DR_MPEG = A m4_delay_loop(SETUP_DELAY_CYCLES - 1) BSET 2 ; TCK high DR_MPEG = A m4_delay(HOLD_DELAY_CYCLES - 10) A = CMP11 ; bit loop counter CP A=>X CLC A -= X CMP11 = A JP :opcode_shift_tms_bits__loop A = X DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it BRANCH openocd-0.9.0/src/jtag/drivers/ftdi.c0000644000175000017500000007535512516456302014377 00000000000000/************************************************************************** * Copyright (C) 2012 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * JTAG adapters based on the FT2232 full and high speed USB parts are * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters * are discrete, but development boards may integrate them as alternatives * to more capable (and expensive) third party JTAG pods. * * JTAG uses only one of the two communications channels ("MPSSE engines") * on these devices. Adapters based on FT4232 parts have four ports/channels * (A/B/C/D), instead of just two (A/B). * * Especially on development boards integrating one of these chips (as * opposed to discrete pods/dongles), the additional channels can be used * for a variety of purposes, but OpenOCD only uses one channel at a time. * * - As a USB-to-serial adapter for the target's console UART ... * which may be able to support ROM boot loaders that load initial * firmware images to flash (or SRAM). * * - On systems which support ARM's SWD in addition to JTAG, or instead * of it, that second port can be used for reading SWV/SWO trace data. * * - Additional JTAG links, e.g. to a CPLD or * FPGA. * * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG * request/response interactions involve round trips over the USB link. * A "smart" JTAG adapter has intelligence close to the scan chain, so it * can for example poll quickly for a status change (usually taking on the * order of microseconds not milliseconds) before beginning a queued * transaction which require the previous one to have completed. * * There are dozens of adapters of this type, differing in details which * this driver needs to understand. Those "layout" details are required * as part of FT2232 driver configuration. * * This code uses information contained in the MPSSE specification which was * found here: * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf * Hereafter this is called the "MPSSE Spec". * * The datasheet for the ftdichip.com's FT2232D part is here: * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf * * Also note the issue with code 0x4b (clock data to TMS) noted in * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html * which can affect longer JTAG state paths. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #if IS_CYGWIN == 1 #include #endif #include /* FTDI access library includes */ #include "mpsse.h" #define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) #define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) static char *ftdi_device_desc; static char *ftdi_serial; static uint8_t ftdi_channel; static bool swd_mode; #define MAX_USB_IDS 8 /* vid = pid = 0 marks the end of the list */ static uint16_t ftdi_vid[MAX_USB_IDS + 1] = { 0 }; static uint16_t ftdi_pid[MAX_USB_IDS + 1] = { 0 }; static struct mpsse_ctx *mpsse_ctx; struct signal { const char *name; uint16_t data_mask; uint16_t oe_mask; bool invert_data; bool invert_oe; struct signal *next; }; static struct signal *signals; /* FIXME: Where to store per-instance data? We need an SWD context. */ static struct swd_cmd_queue_entry { uint8_t cmd; uint32_t *dst; uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; } *swd_cmd_queue; static size_t swd_cmd_queue_length; static size_t swd_cmd_queue_alloced; static int queued_retval; static int freq; static uint16_t output; static uint16_t direction; static uint16_t jtag_output_init; static uint16_t jtag_direction_init; static int ftdi_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq); static struct signal *find_signal_by_name(const char *name) { for (struct signal *sig = signals; sig; sig = sig->next) { if (strcmp(name, sig->name) == 0) return sig; } return NULL; } static struct signal *create_signal(const char *name) { struct signal **psig = &signals; while (*psig) psig = &(*psig)->next; *psig = calloc(1, sizeof(**psig)); if (*psig == NULL) return NULL; (*psig)->name = strdup(name); if ((*psig)->name == NULL) { free(*psig); *psig = NULL; } return *psig; } static int ftdi_set_signal(const struct signal *s, char value) { bool data; bool oe; if (s->data_mask == 0 && s->oe_mask == 0) { LOG_ERROR("interface doesn't provide signal '%s'", s->name); return ERROR_FAIL; } switch (value) { case '0': data = s->invert_data; oe = !s->invert_oe; break; case '1': if (s->data_mask == 0) { LOG_ERROR("interface can't drive '%s' high", s->name); return ERROR_FAIL; } data = !s->invert_data; oe = !s->invert_oe; break; case 'z': case 'Z': if (s->oe_mask == 0) { LOG_ERROR("interface can't tri-state '%s'", s->name); return ERROR_FAIL; } data = s->invert_data; oe = s->invert_oe; break; default: assert(0 && "invalid signal level specifier"); return ERROR_FAIL; } uint16_t old_output = output; uint16_t old_direction = direction; output = data ? output | s->data_mask : output & ~s->data_mask; if (s->oe_mask == s->data_mask) direction = oe ? direction | s->oe_mask : direction & ~s->oe_mask; else output = oe ? output | s->oe_mask : output & ~s->oe_mask; if ((output & 0xff) != (old_output & 0xff) || (direction & 0xff) != (old_direction & 0xff)) mpsse_set_data_bits_low_byte(mpsse_ctx, output & 0xff, direction & 0xff); if ((output >> 8 != old_output >> 8) || (direction >> 8 != old_direction >> 8)) mpsse_set_data_bits_high_byte(mpsse_ctx, output >> 8, direction >> 8); return ERROR_OK; } /** * Function move_to_state * moves the TAP controller from the current state to a * \a goal_state through a path given by tap_get_tms_path(). State transition * logging is performed by delegation to clock_tms(). * * @param goal_state is the destination state for the move. */ static void move_to_state(tap_state_t goal_state) { tap_state_t start_state = tap_get_state(); /* goal_state is 1/2 of a tuple/pair of states which allow convenient lookup of the required TMS pattern to move to this state from the start state. */ /* do the 2 lookups */ uint8_t tms_bits = tap_get_tms_path(start_state, goal_state); int tms_count = tap_get_tms_path_len(start_state, goal_state); assert(tms_count <= 8); DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state)); /* Track state transitions step by step */ for (int i = 0; i < tms_count; i++) tap_set_state(tap_state_transition(tap_get_state(), (tms_bits >> i) & 1)); mpsse_clock_tms_cs_out(mpsse_ctx, &tms_bits, 0, tms_count, false, JTAG_MODE); } static int ftdi_speed(int speed) { int retval; retval = mpsse_set_frequency(mpsse_ctx, speed); if (retval < 0) { LOG_ERROR("couldn't set FTDI TCK speed"); return retval; } return ERROR_OK; } static int ftdi_speed_div(int speed, int *khz) { *khz = speed / 1000; return ERROR_OK; } static int ftdi_khz(int khz, int *jtag_speed) { if (khz == 0 && !mpsse_is_high_speed(mpsse_ctx)) { LOG_DEBUG("RCLK not supported"); return ERROR_FAIL; } *jtag_speed = khz * 1000; return ERROR_OK; } static void ftdi_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state)); exit(-1); } } static void ftdi_execute_runtest(struct jtag_command *cmd) { int i; uint8_t zero = 0; DEBUG_JTAG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); if (tap_get_state() != TAP_IDLE) move_to_state(TAP_IDLE); /* TODO: Reuse ftdi_execute_stableclocks */ i = cmd->cmd.runtest->num_cycles; while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ unsigned this_len = i > 7 ? 7 : i; mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, JTAG_MODE); i -= this_len; } ftdi_end_state(cmd->cmd.runtest->end_state); if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); DEBUG_JTAG_IO("runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(tap_get_end_state())); } static void ftdi_execute_statemove(struct jtag_command *cmd) { DEBUG_JTAG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state)); ftdi_end_state(cmd->cmd.statemove->end_state); /* shortest-path move to desired end state */ if (tap_get_state() != tap_get_end_state() || tap_get_end_state() == TAP_RESET) move_to_state(tap_get_end_state()); } /** * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG * (or SWD) state machine. REVISIT: Not the best method, perhaps. */ static void ftdi_execute_tms(struct jtag_command *cmd) { DEBUG_JTAG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); /* TODO: Missing tap state tracking, also missing from ft2232.c! */ mpsse_clock_tms_cs_out(mpsse_ctx, cmd->cmd.tms->bits, 0, cmd->cmd.tms->num_bits, false, JTAG_MODE); } static void ftdi_execute_pathmove(struct jtag_command *cmd) { tap_state_t *path = cmd->cmd.pathmove->path; int num_states = cmd->cmd.pathmove->num_states; DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states, tap_state_name(tap_get_state()), tap_state_name(path[num_states-1])); int state_count = 0; unsigned bit_count = 0; uint8_t tms_byte = 0; DEBUG_JTAG_IO("-"); /* this loop verifies that the path is legal and logs each state in the path */ while (num_states--) { /* either TMS=0 or TMS=1 must work ... */ if (tap_state_transition(tap_get_state(), false) == path[state_count]) buf_set_u32(&tms_byte, bit_count++, 1, 0x0); else if (tap_state_transition(tap_get_state(), true) == path[state_count]) { buf_set_u32(&tms_byte, bit_count++, 1, 0x1); /* ... or else the caller goofed BADLY */ } else { LOG_ERROR("BUG: %s -> %s isn't a valid " "TAP state transition", tap_state_name(tap_get_state()), tap_state_name(path[state_count])); exit(-1); } tap_set_state(path[state_count]); state_count++; if (bit_count == 7 || num_states == 0) { mpsse_clock_tms_cs_out(mpsse_ctx, &tms_byte, 0, bit_count, false, JTAG_MODE); bit_count = 0; } } tap_set_end_state(tap_get_state()); } static void ftdi_execute_scan(struct jtag_command *cmd) { DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", jtag_scan_type(cmd->cmd.scan)); /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ while (cmd->cmd.scan->num_fields > 0 && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) { cmd->cmd.scan->num_fields--; LOG_DEBUG("discarding trailing empty field"); } if (cmd->cmd.scan->num_fields == 0) { LOG_DEBUG("empty scan, doing nothing"); return; } if (cmd->cmd.scan->ir_scan) { if (tap_get_state() != TAP_IRSHIFT) move_to_state(TAP_IRSHIFT); } else { if (tap_get_state() != TAP_DRSHIFT) move_to_state(TAP_DRSHIFT); } ftdi_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; unsigned scan_size = 0; for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; DEBUG_JTAG_IO("%s%s field %d/%d %d bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, cmd->cmd.scan->num_fields, field->num_bits); if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) { /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap * movement. This last field can't have length zero, it was checked above. */ mpsse_clock_data(mpsse_ctx, field->out_value, 0, field->in_value, 0, field->num_bits - 1, JTAG_MODE); uint8_t last_bit = 0; if (field->out_value) bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); uint8_t tms_bits = 0x01; mpsse_clock_tms_cs(mpsse_ctx, &tms_bits, 0, field->in_value, field->num_bits - 1, 1, last_bit, JTAG_MODE); tap_set_state(tap_state_transition(tap_get_state(), 1)); mpsse_clock_tms_cs_out(mpsse_ctx, &tms_bits, 1, 1, last_bit, JTAG_MODE); tap_set_state(tap_state_transition(tap_get_state(), 0)); } else mpsse_clock_data(mpsse_ctx, field->out_value, 0, field->in_value, 0, field->num_bits, JTAG_MODE); } if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); DEBUG_JTAG_IO("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, tap_state_name(tap_get_end_state())); } static void ftdi_execute_reset(struct jtag_command *cmd) { DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); if (cmd->cmd.reset->trst == 1 || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) tap_set_state(TAP_RESET); struct signal *trst = find_signal_by_name("nTRST"); if (cmd->cmd.reset->trst == 1) { if (trst) ftdi_set_signal(trst, '0'); else LOG_ERROR("Can't assert TRST: nTRST signal is not defined"); } else if (trst && jtag_get_reset_config() & RESET_HAS_TRST && cmd->cmd.reset->trst == 0) { if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) ftdi_set_signal(trst, 'z'); else ftdi_set_signal(trst, '1'); } struct signal *srst = find_signal_by_name("nSRST"); if (cmd->cmd.reset->srst == 1) { if (srst) ftdi_set_signal(srst, '0'); else LOG_ERROR("Can't assert SRST: nSRST signal is not defined"); } else if (srst && jtag_get_reset_config() & RESET_HAS_SRST && cmd->cmd.reset->srst == 0) { if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL) ftdi_set_signal(srst, '1'); else ftdi_set_signal(srst, 'z'); } DEBUG_JTAG_IO("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); } static void ftdi_execute_sleep(struct jtag_command *cmd) { DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us); mpsse_flush(mpsse_ctx); jtag_sleep(cmd->cmd.sleep->us); DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s", cmd->cmd.sleep->us, tap_state_name(tap_get_state())); } static void ftdi_execute_stableclocks(struct jtag_command *cmd) { /* this is only allowed while in a stable state. A check for a stable * state was done in jtag_add_clocks() */ int num_cycles = cmd->cmd.stableclocks->num_cycles; /* 7 bits of either ones or zeros. */ uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00; /* TODO: Use mpsse_clock_data with in=out=0 for this, if TMS can be set to * the correct level and remain there during the scan */ while (num_cycles > 0) { /* there are no state transitions in this code, so omit state tracking */ unsigned this_len = num_cycles > 7 ? 7 : num_cycles; mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, JTAG_MODE); num_cycles -= this_len; } DEBUG_JTAG_IO("clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name(tap_get_state())); } static void ftdi_execute_command(struct jtag_command *cmd) { switch (cmd->type) { case JTAG_RESET: ftdi_execute_reset(cmd); break; case JTAG_RUNTEST: ftdi_execute_runtest(cmd); break; case JTAG_TLR_RESET: ftdi_execute_statemove(cmd); break; case JTAG_PATHMOVE: ftdi_execute_pathmove(cmd); break; case JTAG_SCAN: ftdi_execute_scan(cmd); break; case JTAG_SLEEP: ftdi_execute_sleep(cmd); break; case JTAG_STABLECLOCKS: ftdi_execute_stableclocks(cmd); break; case JTAG_TMS: ftdi_execute_tms(cmd); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd->type); break; } } static int ftdi_execute_queue(void) { /* blink, if the current layout has that feature */ struct signal *led = find_signal_by_name("LED"); if (led) ftdi_set_signal(led, '1'); for (struct jtag_command *cmd = jtag_command_queue; cmd; cmd = cmd->next) { /* fill the write buffer with the desired command */ ftdi_execute_command(cmd); } if (led) ftdi_set_signal(led, '0'); int retval = mpsse_flush(mpsse_ctx); if (retval != ERROR_OK) LOG_ERROR("error while flushing MPSSE queue: %d", retval); return retval; } static int ftdi_initialize(void) { if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7) LOG_DEBUG("ftdi interface using 7 step jtag state transitions"); else LOG_DEBUG("ftdi interface using shortest path jtag state transitions"); for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) { mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc, ftdi_serial, ftdi_channel); if (mpsse_ctx) break; } if (!mpsse_ctx) return ERROR_JTAG_INIT_FAILED; output = jtag_output_init; direction = jtag_direction_init; if (swd_mode) { struct signal *sig = find_signal_by_name("SWD_EN"); if (!sig) { LOG_ERROR("SWD mode is active but SWD_EN signal is not defined"); return ERROR_JTAG_INIT_FAILED; } /* A dummy SWD_EN would have zero mask */ if (sig->data_mask) ftdi_set_signal(sig, '1'); } mpsse_set_data_bits_low_byte(mpsse_ctx, output & 0xff, direction & 0xff); mpsse_set_data_bits_high_byte(mpsse_ctx, output >> 8, direction >> 8); mpsse_loopback_config(mpsse_ctx, false); freq = mpsse_set_frequency(mpsse_ctx, jtag_get_speed_khz() * 1000); return mpsse_flush(mpsse_ctx); } static int ftdi_quit(void) { mpsse_close(mpsse_ctx); free(swd_cmd_queue); return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_device_desc_command) { if (CMD_ARGC == 1) { if (ftdi_device_desc) free(ftdi_device_desc); ftdi_device_desc = strdup(CMD_ARGV[0]); } else { LOG_ERROR("expected exactly one argument to ftdi_device_desc "); } return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_serial_command) { if (CMD_ARGC == 1) { if (ftdi_serial) free(ftdi_serial); ftdi_serial = strdup(CMD_ARGV[0]); } else { return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_channel_command) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], ftdi_channel); else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_layout_init_command) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], jtag_output_init); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], jtag_direction_init); return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_layout_signal_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; bool invert_data = false; uint16_t data_mask = 0; bool invert_oe = false; uint16_t oe_mask = 0; for (unsigned i = 1; i < CMD_ARGC; i += 2) { if (strcmp("-data", CMD_ARGV[i]) == 0) { invert_data = false; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask); } else if (strcmp("-ndata", CMD_ARGV[i]) == 0) { invert_data = true; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask); } else if (strcmp("-oe", CMD_ARGV[i]) == 0) { invert_oe = false; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask); } else if (strcmp("-noe", CMD_ARGV[i]) == 0) { invert_oe = true; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask); } else if (!strcmp("-alias", CMD_ARGV[i]) || !strcmp("-nalias", CMD_ARGV[i])) { if (!strcmp("-nalias", CMD_ARGV[i])) invert_data = true; struct signal *sig = find_signal_by_name(CMD_ARGV[i + 1]); if (!sig) { LOG_ERROR("signal %s is not defined", CMD_ARGV[i + 1]); return ERROR_FAIL; } data_mask = sig->data_mask; oe_mask = sig->oe_mask; invert_oe = sig->invert_oe; invert_data ^= sig->invert_data; } else { LOG_ERROR("unknown option '%s'", CMD_ARGV[i]); return ERROR_COMMAND_SYNTAX_ERROR; } } struct signal *sig; sig = find_signal_by_name(CMD_ARGV[0]); if (!sig) sig = create_signal(CMD_ARGV[0]); if (!sig) { LOG_ERROR("failed to create signal %s", CMD_ARGV[0]); return ERROR_FAIL; } sig->invert_data = invert_data; sig->data_mask = data_mask; sig->invert_oe = invert_oe; sig->oe_mask = oe_mask; return ERROR_OK; } COMMAND_HANDLER(ftdi_handle_set_signal_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct signal *sig; sig = find_signal_by_name(CMD_ARGV[0]); if (!sig) { LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]); return ERROR_FAIL; } switch (*CMD_ARGV[1]) { case '0': case '1': case 'z': case 'Z': /* single character level specifier only */ if (CMD_ARGV[1][1] == '\0') { ftdi_set_signal(sig, *CMD_ARGV[1]); break; } default: LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV[1]); return ERROR_COMMAND_SYNTAX_ERROR; } return mpsse_flush(mpsse_ctx); } COMMAND_HANDLER(ftdi_handle_vid_pid_command) { if (CMD_ARGC > MAX_USB_IDS * 2) { LOG_WARNING("ignoring extra IDs in ftdi_vid_pid " "(maximum is %d pairs)", MAX_USB_IDS); CMD_ARGC = MAX_USB_IDS * 2; } if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { LOG_WARNING("incomplete ftdi_vid_pid configuration directive"); if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* remove the incomplete trailing id */ CMD_ARGC -= 1; } unsigned i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ftdi_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ftdi_pid[i >> 1]); } /* * Explicitly terminate, in case there are multiples instances of * ftdi_vid_pid. */ ftdi_vid[i >> 1] = ftdi_pid[i >> 1] = 0; return ERROR_OK; } static const struct command_registration ftdi_command_handlers[] = { { .name = "ftdi_device_desc", .handler = &ftdi_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the FTDI device", .usage = "description_string", }, { .name = "ftdi_serial", .handler = &ftdi_handle_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the FTDI device", .usage = "serial_string", }, { .name = "ftdi_channel", .handler = &ftdi_handle_channel_command, .mode = COMMAND_CONFIG, .help = "set the channel of the FTDI device that is used as JTAG", .usage = "(0-3)", }, { .name = "ftdi_layout_init", .handler = &ftdi_handle_layout_init_command, .mode = COMMAND_CONFIG, .help = "initialize the FTDI GPIO signals used " "to control output-enables and reset signals", .usage = "data direction", }, { .name = "ftdi_layout_signal", .handler = &ftdi_handle_layout_signal_command, .mode = COMMAND_ANY, .help = "define a signal controlled by one or more FTDI GPIO as data " "and/or output enable", .usage = "name [-data mask|-ndata mask] [-oe mask|-noe mask] [-alias|-nalias name]", }, { .name = "ftdi_set_signal", .handler = &ftdi_handle_set_signal_command, .mode = COMMAND_EXEC, .help = "control a layout-specific signal", .usage = "name (1|0|z)", }, { .name = "ftdi_vid_pid", .handler = &ftdi_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the FTDI device", .usage = "(vid pid)* ", }, COMMAND_REGISTRATION_DONE }; static int create_default_signal(const char *name, uint16_t data_mask) { struct signal *sig = create_signal(name); if (!sig) { LOG_ERROR("failed to create signal %s", name); return ERROR_FAIL; } sig->invert_data = false; sig->data_mask = data_mask; sig->invert_oe = false; sig->oe_mask = 0; return ERROR_OK; } static int create_signals(void) { if (create_default_signal("TCK", 0x01) != ERROR_OK) return ERROR_FAIL; if (create_default_signal("TDI", 0x02) != ERROR_OK) return ERROR_FAIL; if (create_default_signal("TDO", 0x04) != ERROR_OK) return ERROR_FAIL; if (create_default_signal("TMS", 0x08) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int ftdi_swd_init(void) { LOG_INFO("FTDI SWD mode enabled"); swd_mode = true; if (create_signals() != ERROR_OK) return ERROR_FAIL; swd_cmd_queue_alloced = 10; swd_cmd_queue = malloc(swd_cmd_queue_alloced * sizeof(*swd_cmd_queue)); return swd_cmd_queue != NULL ? ERROR_OK : ERROR_FAIL; } static void ftdi_swd_swdio_en(bool enable) { struct signal *oe = find_signal_by_name("SWDIO_OE"); if (oe) ftdi_set_signal(oe, enable ? '1' : '0'); } /** * Flush the MPSSE queue and process the SWD transaction queue * @param dap * @return */ static int ftdi_swd_run_queue(struct adiv5_dap *dap) { LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length); int retval; struct signal *led = find_signal_by_name("LED"); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); goto skip; } /* A transaction must be followed by another transaction or at least 8 idle cycles to * ensure that data is clocked through the AP. */ mpsse_clock_data_out(mpsse_ctx, NULL, 0, 8, SWD_MODE); /* Terminate the "blink", if the current layout has that feature */ if (led) ftdi_set_signal(led, '0'); queued_retval = mpsse_flush(mpsse_ctx); if (queued_retval != ERROR_OK) { LOG_ERROR("MPSSE failed"); goto skip; } for (size_t i = 0; i < swd_cmd_queue_length; i++) { int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3); LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP", swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write", (swd_cmd_queue[i].cmd & SWD_CMD_A32) >> 1, buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + (swd_cmd_queue[i].cmd & SWD_CMD_RnW ? 0 : 1), 32)); if (ack != SWD_ACK_OK) { queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; goto skip; } else if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) { uint32_t data = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3, 32); int parity = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 32, 1); if (parity != parity_u32(data)) { LOG_ERROR("SWD Read data parity mismatch"); queued_retval = ERROR_FAIL; goto skip; } if (swd_cmd_queue[i].dst != NULL) *swd_cmd_queue[i].dst = data; } } skip: swd_cmd_queue_length = 0; retval = queued_retval; queued_retval = ERROR_OK; /* Queue a new "blink" */ if (led && retval == ERROR_OK) ftdi_set_signal(led, '1'); return retval; } static void ftdi_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data) { if (swd_cmd_queue_length >= swd_cmd_queue_alloced) { /* Not enough room in the queue. Run the queue and increase its size for next time. * Note that it's not possible to avoid running the queue here, because mpsse contains * pointers into the queue which may be invalid after the realloc. */ queued_retval = ftdi_swd_run_queue(dap); struct swd_cmd_queue_entry *q = realloc(swd_cmd_queue, swd_cmd_queue_alloced * 2 * sizeof(*swd_cmd_queue)); if (q != NULL) { swd_cmd_queue = q; swd_cmd_queue_alloced *= 2; LOG_DEBUG("Increased SWD command queue to %zu elements", swd_cmd_queue_alloced); } } if (queued_retval != ERROR_OK) return; size_t i = swd_cmd_queue_length++; swd_cmd_queue[i].cmd = cmd | SWD_CMD_START | SWD_CMD_PARK; mpsse_clock_data_out(mpsse_ctx, &swd_cmd_queue[i].cmd, 0, 8, SWD_MODE); if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) { /* Queue a read transaction */ swd_cmd_queue[i].dst = dst; ftdi_swd_swdio_en(false); mpsse_clock_data_in(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn, 0, 1 + 3 + 32 + 1 + 1, SWD_MODE); ftdi_swd_swdio_en(true); } else { /* Queue a write transaction */ ftdi_swd_swdio_en(false); mpsse_clock_data_in(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn, 0, 1 + 3 + 1, SWD_MODE); ftdi_swd_swdio_en(true); buf_set_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 1, 32, data); buf_set_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(data)); mpsse_clock_data_out(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1, SWD_MODE); } /* Insert idle cycles after AP accesses to avoid WAIT */ if (cmd & SWD_CMD_APnDP) mpsse_clock_data_out(mpsse_ctx, NULL, 0, dap->memaccess_tck, SWD_MODE); } static void ftdi_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value) { assert(cmd & SWD_CMD_RnW); ftdi_swd_queue_cmd(dap, cmd, value, 0); } static void ftdi_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value) { assert(!(cmd & SWD_CMD_RnW)); ftdi_swd_queue_cmd(dap, cmd, NULL, value); } static int_least32_t ftdi_swd_frequency(struct adiv5_dap *dap, int_least32_t hz) { if (hz > 0) freq = mpsse_set_frequency(mpsse_ctx, hz); return freq; } static int ftdi_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq) { switch (seq) { case LINE_RESET: LOG_DEBUG("SWD line reset"); mpsse_clock_data_out(mpsse_ctx, swd_seq_line_reset, 0, swd_seq_line_reset_len, SWD_MODE); break; case JTAG_TO_SWD: LOG_DEBUG("JTAG-to-SWD"); mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len, SWD_MODE); break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len, SWD_MODE); break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; } return ERROR_OK; } static const struct swd_driver ftdi_swd = { .init = ftdi_swd_init, .frequency = ftdi_swd_frequency, .switch_seq = ftdi_swd_switch_seq, .read_reg = ftdi_swd_read_reg, .write_reg = ftdi_swd_write_reg, .run = ftdi_swd_run_queue, }; static const char * const ftdi_transports[] = { "jtag", "swd", NULL }; struct jtag_interface ftdi_interface = { .name = "ftdi", .supported = DEBUG_CAP_TMS_SEQ, .commands = ftdi_command_handlers, .transports = ftdi_transports, .swd = &ftdi_swd, .init = ftdi_initialize, .quit = ftdi_quit, .speed = ftdi_speed, .speed_div = ftdi_speed_div, .khz = ftdi_khz, .execute_queue = ftdi_execute_queue, }; openocd-0.9.0/src/jtag/drivers/Makefile.am0000644000175000017500000000545412327155503015331 00000000000000include $(top_srcdir)/common.mk noinst_LTLIBRARIES = libocdjtagdrivers.la libocdjtagdrivers_la_LIBADD = libocdjtagdrivers_la_SOURCES = \ $(DRIVERFILES) libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS) ULINK_FIRMWARE = $(srcdir)/OpenULINK EXTRA_DIST = $(ULINK_FIRMWARE) \ usb_blaster/README.CheapClone \ Makefile.rlink \ rlink_call.m4 \ rlink_init.m4 DRIVERFILES = SUBDIRS= # Standard Driver: common files DRIVERFILES += driver.c if USE_LIBUSB1 DRIVERFILES += libusb1_common.c endif if USE_LIBUSB0 DRIVERFILES += usb_common.c if !USE_LIBUSB1 DRIVERFILES += libusb0_common.c endif endif if BITBANG DRIVERFILES += bitbang.c endif if PARPORT DRIVERFILES += parport.c endif if DUMMY DRIVERFILES += dummy.c endif if FT2232_DRIVER DRIVERFILES += ft2232.c endif if FTDI DRIVERFILES += ftdi.c mpsse.c endif if JTAG_VPI DRIVERFILES += jtag_vpi.c endif if USB_BLASTER_DRIVER SUBDIRS += usb_blaster libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la endif if AMTJTAGACCEL DRIVERFILES += amt_jtagaccel.c endif if EP93XX DRIVERFILES += ep93xx.c endif if AT91RM9200 DRIVERFILES += at91rm9200.c endif if GW16012 DRIVERFILES += gw16012.c endif if BITQ DRIVERFILES += bitq.c endif if PRESTO_DRIVER DRIVERFILES += presto.c endif if USBPROG DRIVERFILES += usbprog.c endif if JLINK DRIVERFILES += jlink.c endif if RLINK DRIVERFILES += rlink.c rlink_speed_table.c endif if ULINK DRIVERFILES += ulink.c ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex endif if VSLLINK DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c DRIVERFILES += versaloon/versaloon.c DRIVERFILES += vsllink.c endif if ARMJTAGEW DRIVERFILES += arm-jtag-ew.c endif if BUSPIRATE DRIVERFILES += buspirate.c endif if REMOTE_BITBANG DRIVERFILES += remote_bitbang.c endif if HLADAPTER DRIVERFILES += stlink_usb.c DRIVERFILES += ti_icdi_usb.c endif if OSBDM DRIVERFILES += osbdm.c endif if OPENDOUS DRIVERFILES += opendous.c endif if SYSFSGPIO DRIVERFILES += sysfsgpio.c endif if BCM2835GPIO DRIVERFILES += bcm2835gpio.c endif if OPENJTAG DRIVERFILES += openjtag.c endif if CMSIS_DAP DRIVERFILES += cmsis_dap_usb.c endif noinst_HEADERS = \ bitbang.h \ bitq.h \ ftd2xx_common.h \ libusb0_common.h \ libusb1_common.h \ libusb_common.h \ minidriver_imp.h \ mpsse.h \ rlink.h \ rlink_dtc_cmd.h \ rlink_ep1_cmd.h \ rlink_st7.h \ usb_common.h \ versaloon/usbtoxxx/usbtoxxx.h \ versaloon/usbtoxxx/usbtoxxx_internal.h \ versaloon/versaloon.h \ versaloon/versaloon_include.h \ versaloon/versaloon_internal.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/jtag/drivers/Makefile.in0000644000175000017500000024661512526201650015344 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(am__dist_ulink_DATA_DIST) $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @USE_LIBUSB1_TRUE@am__append_2 = libusb1_common.c @USE_LIBUSB0_TRUE@am__append_3 = usb_common.c @USE_LIBUSB0_TRUE@@USE_LIBUSB1_FALSE@am__append_4 = libusb0_common.c @BITBANG_TRUE@am__append_5 = bitbang.c @PARPORT_TRUE@am__append_6 = parport.c @DUMMY_TRUE@am__append_7 = dummy.c @FT2232_DRIVER_TRUE@am__append_8 = ft2232.c @FTDI_TRUE@am__append_9 = ftdi.c mpsse.c @JTAG_VPI_TRUE@am__append_10 = jtag_vpi.c @USB_BLASTER_DRIVER_TRUE@am__append_11 = usb_blaster @USB_BLASTER_DRIVER_TRUE@am__append_12 = $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la @AMTJTAGACCEL_TRUE@am__append_13 = amt_jtagaccel.c @EP93XX_TRUE@am__append_14 = ep93xx.c @AT91RM9200_TRUE@am__append_15 = at91rm9200.c @GW16012_TRUE@am__append_16 = gw16012.c @BITQ_TRUE@am__append_17 = bitq.c @PRESTO_DRIVER_TRUE@am__append_18 = presto.c @USBPROG_TRUE@am__append_19 = usbprog.c @JLINK_TRUE@am__append_20 = jlink.c @RLINK_TRUE@am__append_21 = rlink.c rlink_speed_table.c @ULINK_TRUE@am__append_22 = ulink.c @VSLLINK_TRUE@am__append_23 = versaloon/usbtoxxx/usbtogpio.c \ @VSLLINK_TRUE@ versaloon/usbtoxxx/usbtojtagraw.c \ @VSLLINK_TRUE@ versaloon/usbtoxxx/usbtoswd.c \ @VSLLINK_TRUE@ versaloon/usbtoxxx/usbtopwr.c \ @VSLLINK_TRUE@ versaloon/usbtoxxx/usbtoxxx.c \ @VSLLINK_TRUE@ versaloon/versaloon.c vsllink.c @ARMJTAGEW_TRUE@am__append_24 = arm-jtag-ew.c @BUSPIRATE_TRUE@am__append_25 = buspirate.c @REMOTE_BITBANG_TRUE@am__append_26 = remote_bitbang.c @HLADAPTER_TRUE@am__append_27 = stlink_usb.c ti_icdi_usb.c @OSBDM_TRUE@am__append_28 = osbdm.c @OPENDOUS_TRUE@am__append_29 = opendous.c @SYSFSGPIO_TRUE@am__append_30 = sysfsgpio.c @BCM2835GPIO_TRUE@am__append_31 = bcm2835gpio.c @OPENJTAG_TRUE@am__append_32 = openjtag.c @CMSIS_DAP_TRUE@am__append_33 = cmsis_dap_usb.c subdir = src/jtag/drivers ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdjtagdrivers_la_DEPENDENCIES = $(am__append_12) am__libocdjtagdrivers_la_SOURCES_DIST = driver.c libusb1_common.c \ usb_common.c libusb0_common.c bitbang.c parport.c dummy.c \ ft2232.c ftdi.c mpsse.c jtag_vpi.c amt_jtagaccel.c ep93xx.c \ at91rm9200.c gw16012.c bitq.c presto.c usbprog.c jlink.c \ rlink.c rlink_speed_table.c ulink.c \ versaloon/usbtoxxx/usbtogpio.c \ versaloon/usbtoxxx/usbtojtagraw.c \ versaloon/usbtoxxx/usbtoswd.c versaloon/usbtoxxx/usbtopwr.c \ versaloon/usbtoxxx/usbtoxxx.c versaloon/versaloon.c vsllink.c \ arm-jtag-ew.c buspirate.c remote_bitbang.c stlink_usb.c \ ti_icdi_usb.c osbdm.c opendous.c sysfsgpio.c bcm2835gpio.c \ openjtag.c cmsis_dap_usb.c @USE_LIBUSB1_TRUE@am__objects_1 = \ @USE_LIBUSB1_TRUE@ libocdjtagdrivers_la-libusb1_common.lo @USE_LIBUSB0_TRUE@am__objects_2 = libocdjtagdrivers_la-usb_common.lo @USE_LIBUSB0_TRUE@@USE_LIBUSB1_FALSE@am__objects_3 = libocdjtagdrivers_la-libusb0_common.lo @BITBANG_TRUE@am__objects_4 = libocdjtagdrivers_la-bitbang.lo @PARPORT_TRUE@am__objects_5 = libocdjtagdrivers_la-parport.lo @DUMMY_TRUE@am__objects_6 = libocdjtagdrivers_la-dummy.lo @FT2232_DRIVER_TRUE@am__objects_7 = libocdjtagdrivers_la-ft2232.lo @FTDI_TRUE@am__objects_8 = libocdjtagdrivers_la-ftdi.lo \ @FTDI_TRUE@ libocdjtagdrivers_la-mpsse.lo @JTAG_VPI_TRUE@am__objects_9 = libocdjtagdrivers_la-jtag_vpi.lo @AMTJTAGACCEL_TRUE@am__objects_10 = \ @AMTJTAGACCEL_TRUE@ libocdjtagdrivers_la-amt_jtagaccel.lo @EP93XX_TRUE@am__objects_11 = libocdjtagdrivers_la-ep93xx.lo @AT91RM9200_TRUE@am__objects_12 = libocdjtagdrivers_la-at91rm9200.lo @GW16012_TRUE@am__objects_13 = libocdjtagdrivers_la-gw16012.lo @BITQ_TRUE@am__objects_14 = libocdjtagdrivers_la-bitq.lo @PRESTO_DRIVER_TRUE@am__objects_15 = libocdjtagdrivers_la-presto.lo @USBPROG_TRUE@am__objects_16 = libocdjtagdrivers_la-usbprog.lo @JLINK_TRUE@am__objects_17 = libocdjtagdrivers_la-jlink.lo @RLINK_TRUE@am__objects_18 = libocdjtagdrivers_la-rlink.lo \ @RLINK_TRUE@ libocdjtagdrivers_la-rlink_speed_table.lo @ULINK_TRUE@am__objects_19 = libocdjtagdrivers_la-ulink.lo am__dirstamp = $(am__leading_dot)dirstamp @VSLLINK_TRUE@am__objects_20 = versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo \ @VSLLINK_TRUE@ versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo \ @VSLLINK_TRUE@ versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo \ @VSLLINK_TRUE@ versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo \ @VSLLINK_TRUE@ versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo \ @VSLLINK_TRUE@ versaloon/libocdjtagdrivers_la-versaloon.lo \ @VSLLINK_TRUE@ libocdjtagdrivers_la-vsllink.lo @ARMJTAGEW_TRUE@am__objects_21 = libocdjtagdrivers_la-arm-jtag-ew.lo @BUSPIRATE_TRUE@am__objects_22 = libocdjtagdrivers_la-buspirate.lo @REMOTE_BITBANG_TRUE@am__objects_23 = \ @REMOTE_BITBANG_TRUE@ libocdjtagdrivers_la-remote_bitbang.lo @HLADAPTER_TRUE@am__objects_24 = libocdjtagdrivers_la-stlink_usb.lo \ @HLADAPTER_TRUE@ libocdjtagdrivers_la-ti_icdi_usb.lo @OSBDM_TRUE@am__objects_25 = libocdjtagdrivers_la-osbdm.lo @OPENDOUS_TRUE@am__objects_26 = libocdjtagdrivers_la-opendous.lo @SYSFSGPIO_TRUE@am__objects_27 = libocdjtagdrivers_la-sysfsgpio.lo @BCM2835GPIO_TRUE@am__objects_28 = \ @BCM2835GPIO_TRUE@ libocdjtagdrivers_la-bcm2835gpio.lo @OPENJTAG_TRUE@am__objects_29 = libocdjtagdrivers_la-openjtag.lo @CMSIS_DAP_TRUE@am__objects_30 = \ @CMSIS_DAP_TRUE@ libocdjtagdrivers_la-cmsis_dap_usb.lo am__objects_31 = libocdjtagdrivers_la-driver.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) $(am__objects_12) $(am__objects_13) \ $(am__objects_14) $(am__objects_15) $(am__objects_16) \ $(am__objects_17) $(am__objects_18) $(am__objects_19) \ $(am__objects_20) $(am__objects_21) $(am__objects_22) \ $(am__objects_23) $(am__objects_24) $(am__objects_25) \ $(am__objects_26) $(am__objects_27) $(am__objects_28) \ $(am__objects_29) $(am__objects_30) am_libocdjtagdrivers_la_OBJECTS = $(am__objects_31) libocdjtagdrivers_la_OBJECTS = $(am_libocdjtagdrivers_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdjtagdrivers_la_SOURCES) DIST_SOURCES = $(am__libocdjtagdrivers_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__dist_ulink_DATA_DIST = $(ULINK_FIRMWARE)/ulink_firmware.hex am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(ulinkdir)" DATA = $(dist_ulink_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = usb_blaster DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) noinst_LTLIBRARIES = libocdjtagdrivers.la libocdjtagdrivers_la_LIBADD = $(am__append_12) libocdjtagdrivers_la_SOURCES = \ $(DRIVERFILES) libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS) ULINK_FIRMWARE = $(srcdir)/OpenULINK EXTRA_DIST = $(ULINK_FIRMWARE) \ usb_blaster/README.CheapClone \ Makefile.rlink \ rlink_call.m4 \ rlink_init.m4 # Standard Driver: common files DRIVERFILES = driver.c $(am__append_2) $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_13) $(am__append_14) $(am__append_15) \ $(am__append_16) $(am__append_17) $(am__append_18) \ $(am__append_19) $(am__append_20) $(am__append_21) \ $(am__append_22) $(am__append_23) $(am__append_24) \ $(am__append_25) $(am__append_26) $(am__append_27) \ $(am__append_28) $(am__append_29) $(am__append_30) \ $(am__append_31) $(am__append_32) $(am__append_33) SUBDIRS = $(am__append_11) @ULINK_TRUE@ulinkdir = $(pkgdatadir)/OpenULINK @ULINK_TRUE@dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex noinst_HEADERS = \ bitbang.h \ bitq.h \ ftd2xx_common.h \ libusb0_common.h \ libusb1_common.h \ libusb_common.h \ minidriver_imp.h \ mpsse.h \ rlink.h \ rlink_dtc_cmd.h \ rlink_ep1_cmd.h \ rlink_st7.h \ usb_common.h \ versaloon/usbtoxxx/usbtoxxx.h \ versaloon/usbtoxxx/usbtoxxx_internal.h \ versaloon/versaloon.h \ versaloon/versaloon_include.h \ versaloon/versaloon_internal.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/jtag/drivers/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/jtag/drivers/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } versaloon/usbtoxxx/$(am__dirstamp): @$(MKDIR_P) versaloon/usbtoxxx @: > versaloon/usbtoxxx/$(am__dirstamp) versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) versaloon/usbtoxxx/$(DEPDIR) @: > versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo: \ versaloon/usbtoxxx/$(am__dirstamp) \ versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo: \ versaloon/usbtoxxx/$(am__dirstamp) \ versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo: \ versaloon/usbtoxxx/$(am__dirstamp) \ versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo: \ versaloon/usbtoxxx/$(am__dirstamp) \ versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo: \ versaloon/usbtoxxx/$(am__dirstamp) \ versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) versaloon/$(am__dirstamp): @$(MKDIR_P) versaloon @: > versaloon/$(am__dirstamp) versaloon/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) versaloon/$(DEPDIR) @: > versaloon/$(DEPDIR)/$(am__dirstamp) versaloon/libocdjtagdrivers_la-versaloon.lo: \ versaloon/$(am__dirstamp) versaloon/$(DEPDIR)/$(am__dirstamp) libocdjtagdrivers.la: $(libocdjtagdrivers_la_OBJECTS) $(libocdjtagdrivers_la_DEPENDENCIES) $(EXTRA_libocdjtagdrivers_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdjtagdrivers_la_OBJECTS) $(libocdjtagdrivers_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f versaloon/*.$(OBJEXT) -rm -f versaloon/*.lo -rm -f versaloon/usbtoxxx/*.$(OBJEXT) -rm -f versaloon/usbtoxxx/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-amt_jtagaccel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-arm-jtag-ew.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-at91rm9200.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-bcm2835gpio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-bitbang.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-bitq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-buspirate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-cmsis_dap_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-ep93xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-ft2232.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-ftdi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-gw16012.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-jlink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-jtag_vpi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-libusb0_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-libusb1_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-mpsse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-opendous.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-openjtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-osbdm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-parport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-presto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-remote_bitbang.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-rlink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-rlink_speed_table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-stlink_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-sysfsgpio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-ti_icdi_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-ulink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-usb_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-usbprog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libocdjtagdrivers_la-vsllink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/$(DEPDIR)/libocdjtagdrivers_la-versaloon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtogpio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtojtagraw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtopwr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoswd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoxxx.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libocdjtagdrivers_la-driver.lo: driver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-driver.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-driver.Tpo -c -o libocdjtagdrivers_la-driver.lo `test -f 'driver.c' || echo '$(srcdir)/'`driver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-driver.Tpo $(DEPDIR)/libocdjtagdrivers_la-driver.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='driver.c' object='libocdjtagdrivers_la-driver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-driver.lo `test -f 'driver.c' || echo '$(srcdir)/'`driver.c libocdjtagdrivers_la-libusb1_common.lo: libusb1_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-libusb1_common.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-libusb1_common.Tpo -c -o libocdjtagdrivers_la-libusb1_common.lo `test -f 'libusb1_common.c' || echo '$(srcdir)/'`libusb1_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-libusb1_common.Tpo $(DEPDIR)/libocdjtagdrivers_la-libusb1_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libusb1_common.c' object='libocdjtagdrivers_la-libusb1_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-libusb1_common.lo `test -f 'libusb1_common.c' || echo '$(srcdir)/'`libusb1_common.c libocdjtagdrivers_la-usb_common.lo: usb_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-usb_common.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-usb_common.Tpo -c -o libocdjtagdrivers_la-usb_common.lo `test -f 'usb_common.c' || echo '$(srcdir)/'`usb_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-usb_common.Tpo $(DEPDIR)/libocdjtagdrivers_la-usb_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='usb_common.c' object='libocdjtagdrivers_la-usb_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-usb_common.lo `test -f 'usb_common.c' || echo '$(srcdir)/'`usb_common.c libocdjtagdrivers_la-libusb0_common.lo: libusb0_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-libusb0_common.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-libusb0_common.Tpo -c -o libocdjtagdrivers_la-libusb0_common.lo `test -f 'libusb0_common.c' || echo '$(srcdir)/'`libusb0_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-libusb0_common.Tpo $(DEPDIR)/libocdjtagdrivers_la-libusb0_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libusb0_common.c' object='libocdjtagdrivers_la-libusb0_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-libusb0_common.lo `test -f 'libusb0_common.c' || echo '$(srcdir)/'`libusb0_common.c libocdjtagdrivers_la-bitbang.lo: bitbang.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-bitbang.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-bitbang.Tpo -c -o libocdjtagdrivers_la-bitbang.lo `test -f 'bitbang.c' || echo '$(srcdir)/'`bitbang.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-bitbang.Tpo $(DEPDIR)/libocdjtagdrivers_la-bitbang.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bitbang.c' object='libocdjtagdrivers_la-bitbang.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-bitbang.lo `test -f 'bitbang.c' || echo '$(srcdir)/'`bitbang.c libocdjtagdrivers_la-parport.lo: parport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-parport.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-parport.Tpo -c -o libocdjtagdrivers_la-parport.lo `test -f 'parport.c' || echo '$(srcdir)/'`parport.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-parport.Tpo $(DEPDIR)/libocdjtagdrivers_la-parport.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parport.c' object='libocdjtagdrivers_la-parport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-parport.lo `test -f 'parport.c' || echo '$(srcdir)/'`parport.c libocdjtagdrivers_la-dummy.lo: dummy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-dummy.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-dummy.Tpo -c -o libocdjtagdrivers_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-dummy.Tpo $(DEPDIR)/libocdjtagdrivers_la-dummy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='libocdjtagdrivers_la-dummy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c libocdjtagdrivers_la-ft2232.lo: ft2232.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-ft2232.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-ft2232.Tpo -c -o libocdjtagdrivers_la-ft2232.lo `test -f 'ft2232.c' || echo '$(srcdir)/'`ft2232.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-ft2232.Tpo $(DEPDIR)/libocdjtagdrivers_la-ft2232.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ft2232.c' object='libocdjtagdrivers_la-ft2232.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-ft2232.lo `test -f 'ft2232.c' || echo '$(srcdir)/'`ft2232.c libocdjtagdrivers_la-ftdi.lo: ftdi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-ftdi.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-ftdi.Tpo -c -o libocdjtagdrivers_la-ftdi.lo `test -f 'ftdi.c' || echo '$(srcdir)/'`ftdi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-ftdi.Tpo $(DEPDIR)/libocdjtagdrivers_la-ftdi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftdi.c' object='libocdjtagdrivers_la-ftdi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-ftdi.lo `test -f 'ftdi.c' || echo '$(srcdir)/'`ftdi.c libocdjtagdrivers_la-mpsse.lo: mpsse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-mpsse.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-mpsse.Tpo -c -o libocdjtagdrivers_la-mpsse.lo `test -f 'mpsse.c' || echo '$(srcdir)/'`mpsse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-mpsse.Tpo $(DEPDIR)/libocdjtagdrivers_la-mpsse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mpsse.c' object='libocdjtagdrivers_la-mpsse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-mpsse.lo `test -f 'mpsse.c' || echo '$(srcdir)/'`mpsse.c libocdjtagdrivers_la-jtag_vpi.lo: jtag_vpi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-jtag_vpi.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-jtag_vpi.Tpo -c -o libocdjtagdrivers_la-jtag_vpi.lo `test -f 'jtag_vpi.c' || echo '$(srcdir)/'`jtag_vpi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-jtag_vpi.Tpo $(DEPDIR)/libocdjtagdrivers_la-jtag_vpi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jtag_vpi.c' object='libocdjtagdrivers_la-jtag_vpi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-jtag_vpi.lo `test -f 'jtag_vpi.c' || echo '$(srcdir)/'`jtag_vpi.c libocdjtagdrivers_la-amt_jtagaccel.lo: amt_jtagaccel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-amt_jtagaccel.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-amt_jtagaccel.Tpo -c -o libocdjtagdrivers_la-amt_jtagaccel.lo `test -f 'amt_jtagaccel.c' || echo '$(srcdir)/'`amt_jtagaccel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-amt_jtagaccel.Tpo $(DEPDIR)/libocdjtagdrivers_la-amt_jtagaccel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='amt_jtagaccel.c' object='libocdjtagdrivers_la-amt_jtagaccel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-amt_jtagaccel.lo `test -f 'amt_jtagaccel.c' || echo '$(srcdir)/'`amt_jtagaccel.c libocdjtagdrivers_la-ep93xx.lo: ep93xx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-ep93xx.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-ep93xx.Tpo -c -o libocdjtagdrivers_la-ep93xx.lo `test -f 'ep93xx.c' || echo '$(srcdir)/'`ep93xx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-ep93xx.Tpo $(DEPDIR)/libocdjtagdrivers_la-ep93xx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ep93xx.c' object='libocdjtagdrivers_la-ep93xx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-ep93xx.lo `test -f 'ep93xx.c' || echo '$(srcdir)/'`ep93xx.c libocdjtagdrivers_la-at91rm9200.lo: at91rm9200.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-at91rm9200.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-at91rm9200.Tpo -c -o libocdjtagdrivers_la-at91rm9200.lo `test -f 'at91rm9200.c' || echo '$(srcdir)/'`at91rm9200.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-at91rm9200.Tpo $(DEPDIR)/libocdjtagdrivers_la-at91rm9200.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='at91rm9200.c' object='libocdjtagdrivers_la-at91rm9200.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-at91rm9200.lo `test -f 'at91rm9200.c' || echo '$(srcdir)/'`at91rm9200.c libocdjtagdrivers_la-gw16012.lo: gw16012.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-gw16012.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-gw16012.Tpo -c -o libocdjtagdrivers_la-gw16012.lo `test -f 'gw16012.c' || echo '$(srcdir)/'`gw16012.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-gw16012.Tpo $(DEPDIR)/libocdjtagdrivers_la-gw16012.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gw16012.c' object='libocdjtagdrivers_la-gw16012.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-gw16012.lo `test -f 'gw16012.c' || echo '$(srcdir)/'`gw16012.c libocdjtagdrivers_la-bitq.lo: bitq.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-bitq.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-bitq.Tpo -c -o libocdjtagdrivers_la-bitq.lo `test -f 'bitq.c' || echo '$(srcdir)/'`bitq.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-bitq.Tpo $(DEPDIR)/libocdjtagdrivers_la-bitq.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bitq.c' object='libocdjtagdrivers_la-bitq.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-bitq.lo `test -f 'bitq.c' || echo '$(srcdir)/'`bitq.c libocdjtagdrivers_la-presto.lo: presto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-presto.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-presto.Tpo -c -o libocdjtagdrivers_la-presto.lo `test -f 'presto.c' || echo '$(srcdir)/'`presto.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-presto.Tpo $(DEPDIR)/libocdjtagdrivers_la-presto.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='presto.c' object='libocdjtagdrivers_la-presto.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-presto.lo `test -f 'presto.c' || echo '$(srcdir)/'`presto.c libocdjtagdrivers_la-usbprog.lo: usbprog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-usbprog.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-usbprog.Tpo -c -o libocdjtagdrivers_la-usbprog.lo `test -f 'usbprog.c' || echo '$(srcdir)/'`usbprog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-usbprog.Tpo $(DEPDIR)/libocdjtagdrivers_la-usbprog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='usbprog.c' object='libocdjtagdrivers_la-usbprog.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-usbprog.lo `test -f 'usbprog.c' || echo '$(srcdir)/'`usbprog.c libocdjtagdrivers_la-jlink.lo: jlink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-jlink.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-jlink.Tpo -c -o libocdjtagdrivers_la-jlink.lo `test -f 'jlink.c' || echo '$(srcdir)/'`jlink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-jlink.Tpo $(DEPDIR)/libocdjtagdrivers_la-jlink.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jlink.c' object='libocdjtagdrivers_la-jlink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-jlink.lo `test -f 'jlink.c' || echo '$(srcdir)/'`jlink.c libocdjtagdrivers_la-rlink.lo: rlink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-rlink.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-rlink.Tpo -c -o libocdjtagdrivers_la-rlink.lo `test -f 'rlink.c' || echo '$(srcdir)/'`rlink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-rlink.Tpo $(DEPDIR)/libocdjtagdrivers_la-rlink.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rlink.c' object='libocdjtagdrivers_la-rlink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-rlink.lo `test -f 'rlink.c' || echo '$(srcdir)/'`rlink.c libocdjtagdrivers_la-rlink_speed_table.lo: rlink_speed_table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-rlink_speed_table.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-rlink_speed_table.Tpo -c -o libocdjtagdrivers_la-rlink_speed_table.lo `test -f 'rlink_speed_table.c' || echo '$(srcdir)/'`rlink_speed_table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-rlink_speed_table.Tpo $(DEPDIR)/libocdjtagdrivers_la-rlink_speed_table.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rlink_speed_table.c' object='libocdjtagdrivers_la-rlink_speed_table.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-rlink_speed_table.lo `test -f 'rlink_speed_table.c' || echo '$(srcdir)/'`rlink_speed_table.c libocdjtagdrivers_la-ulink.lo: ulink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-ulink.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-ulink.Tpo -c -o libocdjtagdrivers_la-ulink.lo `test -f 'ulink.c' || echo '$(srcdir)/'`ulink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-ulink.Tpo $(DEPDIR)/libocdjtagdrivers_la-ulink.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ulink.c' object='libocdjtagdrivers_la-ulink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-ulink.lo `test -f 'ulink.c' || echo '$(srcdir)/'`ulink.c versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo: versaloon/usbtoxxx/usbtogpio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo -MD -MP -MF versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtogpio.Tpo -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo `test -f 'versaloon/usbtoxxx/usbtogpio.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtogpio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtogpio.Tpo versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtogpio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/usbtoxxx/usbtogpio.c' object='versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtogpio.lo `test -f 'versaloon/usbtoxxx/usbtogpio.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtogpio.c versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo: versaloon/usbtoxxx/usbtojtagraw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo -MD -MP -MF versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtojtagraw.Tpo -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo `test -f 'versaloon/usbtoxxx/usbtojtagraw.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtojtagraw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtojtagraw.Tpo versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtojtagraw.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/usbtoxxx/usbtojtagraw.c' object='versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtojtagraw.lo `test -f 'versaloon/usbtoxxx/usbtojtagraw.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtojtagraw.c versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo: versaloon/usbtoxxx/usbtoswd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo -MD -MP -MF versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoswd.Tpo -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo `test -f 'versaloon/usbtoxxx/usbtoswd.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtoswd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoswd.Tpo versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoswd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/usbtoxxx/usbtoswd.c' object='versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoswd.lo `test -f 'versaloon/usbtoxxx/usbtoswd.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtoswd.c versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo: versaloon/usbtoxxx/usbtopwr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo -MD -MP -MF versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtopwr.Tpo -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo `test -f 'versaloon/usbtoxxx/usbtopwr.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtopwr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtopwr.Tpo versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtopwr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/usbtoxxx/usbtopwr.c' object='versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtopwr.lo `test -f 'versaloon/usbtoxxx/usbtopwr.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtopwr.c versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo: versaloon/usbtoxxx/usbtoxxx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo -MD -MP -MF versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoxxx.Tpo -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo `test -f 'versaloon/usbtoxxx/usbtoxxx.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtoxxx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoxxx.Tpo versaloon/usbtoxxx/$(DEPDIR)/libocdjtagdrivers_la-usbtoxxx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/usbtoxxx/usbtoxxx.c' object='versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/usbtoxxx/libocdjtagdrivers_la-usbtoxxx.lo `test -f 'versaloon/usbtoxxx/usbtoxxx.c' || echo '$(srcdir)/'`versaloon/usbtoxxx/usbtoxxx.c versaloon/libocdjtagdrivers_la-versaloon.lo: versaloon/versaloon.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT versaloon/libocdjtagdrivers_la-versaloon.lo -MD -MP -MF versaloon/$(DEPDIR)/libocdjtagdrivers_la-versaloon.Tpo -c -o versaloon/libocdjtagdrivers_la-versaloon.lo `test -f 'versaloon/versaloon.c' || echo '$(srcdir)/'`versaloon/versaloon.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) versaloon/$(DEPDIR)/libocdjtagdrivers_la-versaloon.Tpo versaloon/$(DEPDIR)/libocdjtagdrivers_la-versaloon.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='versaloon/versaloon.c' object='versaloon/libocdjtagdrivers_la-versaloon.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o versaloon/libocdjtagdrivers_la-versaloon.lo `test -f 'versaloon/versaloon.c' || echo '$(srcdir)/'`versaloon/versaloon.c libocdjtagdrivers_la-vsllink.lo: vsllink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-vsllink.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-vsllink.Tpo -c -o libocdjtagdrivers_la-vsllink.lo `test -f 'vsllink.c' || echo '$(srcdir)/'`vsllink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-vsllink.Tpo $(DEPDIR)/libocdjtagdrivers_la-vsllink.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vsllink.c' object='libocdjtagdrivers_la-vsllink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-vsllink.lo `test -f 'vsllink.c' || echo '$(srcdir)/'`vsllink.c libocdjtagdrivers_la-arm-jtag-ew.lo: arm-jtag-ew.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-arm-jtag-ew.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-arm-jtag-ew.Tpo -c -o libocdjtagdrivers_la-arm-jtag-ew.lo `test -f 'arm-jtag-ew.c' || echo '$(srcdir)/'`arm-jtag-ew.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-arm-jtag-ew.Tpo $(DEPDIR)/libocdjtagdrivers_la-arm-jtag-ew.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='arm-jtag-ew.c' object='libocdjtagdrivers_la-arm-jtag-ew.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-arm-jtag-ew.lo `test -f 'arm-jtag-ew.c' || echo '$(srcdir)/'`arm-jtag-ew.c libocdjtagdrivers_la-buspirate.lo: buspirate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-buspirate.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-buspirate.Tpo -c -o libocdjtagdrivers_la-buspirate.lo `test -f 'buspirate.c' || echo '$(srcdir)/'`buspirate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-buspirate.Tpo $(DEPDIR)/libocdjtagdrivers_la-buspirate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buspirate.c' object='libocdjtagdrivers_la-buspirate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-buspirate.lo `test -f 'buspirate.c' || echo '$(srcdir)/'`buspirate.c libocdjtagdrivers_la-remote_bitbang.lo: remote_bitbang.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-remote_bitbang.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-remote_bitbang.Tpo -c -o libocdjtagdrivers_la-remote_bitbang.lo `test -f 'remote_bitbang.c' || echo '$(srcdir)/'`remote_bitbang.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-remote_bitbang.Tpo $(DEPDIR)/libocdjtagdrivers_la-remote_bitbang.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='remote_bitbang.c' object='libocdjtagdrivers_la-remote_bitbang.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-remote_bitbang.lo `test -f 'remote_bitbang.c' || echo '$(srcdir)/'`remote_bitbang.c libocdjtagdrivers_la-stlink_usb.lo: stlink_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-stlink_usb.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-stlink_usb.Tpo -c -o libocdjtagdrivers_la-stlink_usb.lo `test -f 'stlink_usb.c' || echo '$(srcdir)/'`stlink_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-stlink_usb.Tpo $(DEPDIR)/libocdjtagdrivers_la-stlink_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stlink_usb.c' object='libocdjtagdrivers_la-stlink_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-stlink_usb.lo `test -f 'stlink_usb.c' || echo '$(srcdir)/'`stlink_usb.c libocdjtagdrivers_la-ti_icdi_usb.lo: ti_icdi_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-ti_icdi_usb.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-ti_icdi_usb.Tpo -c -o libocdjtagdrivers_la-ti_icdi_usb.lo `test -f 'ti_icdi_usb.c' || echo '$(srcdir)/'`ti_icdi_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-ti_icdi_usb.Tpo $(DEPDIR)/libocdjtagdrivers_la-ti_icdi_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ti_icdi_usb.c' object='libocdjtagdrivers_la-ti_icdi_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-ti_icdi_usb.lo `test -f 'ti_icdi_usb.c' || echo '$(srcdir)/'`ti_icdi_usb.c libocdjtagdrivers_la-osbdm.lo: osbdm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-osbdm.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-osbdm.Tpo -c -o libocdjtagdrivers_la-osbdm.lo `test -f 'osbdm.c' || echo '$(srcdir)/'`osbdm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-osbdm.Tpo $(DEPDIR)/libocdjtagdrivers_la-osbdm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='osbdm.c' object='libocdjtagdrivers_la-osbdm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-osbdm.lo `test -f 'osbdm.c' || echo '$(srcdir)/'`osbdm.c libocdjtagdrivers_la-opendous.lo: opendous.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-opendous.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-opendous.Tpo -c -o libocdjtagdrivers_la-opendous.lo `test -f 'opendous.c' || echo '$(srcdir)/'`opendous.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-opendous.Tpo $(DEPDIR)/libocdjtagdrivers_la-opendous.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='opendous.c' object='libocdjtagdrivers_la-opendous.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-opendous.lo `test -f 'opendous.c' || echo '$(srcdir)/'`opendous.c libocdjtagdrivers_la-sysfsgpio.lo: sysfsgpio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-sysfsgpio.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-sysfsgpio.Tpo -c -o libocdjtagdrivers_la-sysfsgpio.lo `test -f 'sysfsgpio.c' || echo '$(srcdir)/'`sysfsgpio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-sysfsgpio.Tpo $(DEPDIR)/libocdjtagdrivers_la-sysfsgpio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysfsgpio.c' object='libocdjtagdrivers_la-sysfsgpio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-sysfsgpio.lo `test -f 'sysfsgpio.c' || echo '$(srcdir)/'`sysfsgpio.c libocdjtagdrivers_la-bcm2835gpio.lo: bcm2835gpio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-bcm2835gpio.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-bcm2835gpio.Tpo -c -o libocdjtagdrivers_la-bcm2835gpio.lo `test -f 'bcm2835gpio.c' || echo '$(srcdir)/'`bcm2835gpio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-bcm2835gpio.Tpo $(DEPDIR)/libocdjtagdrivers_la-bcm2835gpio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bcm2835gpio.c' object='libocdjtagdrivers_la-bcm2835gpio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-bcm2835gpio.lo `test -f 'bcm2835gpio.c' || echo '$(srcdir)/'`bcm2835gpio.c libocdjtagdrivers_la-openjtag.lo: openjtag.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-openjtag.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-openjtag.Tpo -c -o libocdjtagdrivers_la-openjtag.lo `test -f 'openjtag.c' || echo '$(srcdir)/'`openjtag.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-openjtag.Tpo $(DEPDIR)/libocdjtagdrivers_la-openjtag.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openjtag.c' object='libocdjtagdrivers_la-openjtag.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-openjtag.lo `test -f 'openjtag.c' || echo '$(srcdir)/'`openjtag.c libocdjtagdrivers_la-cmsis_dap_usb.lo: cmsis_dap_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libocdjtagdrivers_la-cmsis_dap_usb.lo -MD -MP -MF $(DEPDIR)/libocdjtagdrivers_la-cmsis_dap_usb.Tpo -c -o libocdjtagdrivers_la-cmsis_dap_usb.lo `test -f 'cmsis_dap_usb.c' || echo '$(srcdir)/'`cmsis_dap_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libocdjtagdrivers_la-cmsis_dap_usb.Tpo $(DEPDIR)/libocdjtagdrivers_la-cmsis_dap_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmsis_dap_usb.c' object='libocdjtagdrivers_la-cmsis_dap_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libocdjtagdrivers_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libocdjtagdrivers_la-cmsis_dap_usb.lo `test -f 'cmsis_dap_usb.c' || echo '$(srcdir)/'`cmsis_dap_usb.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf versaloon/.libs versaloon/_libs -rm -rf versaloon/usbtoxxx/.libs versaloon/usbtoxxx/_libs install-dist_ulinkDATA: $(dist_ulink_DATA) @$(NORMAL_INSTALL) @list='$(dist_ulink_DATA)'; test -n "$(ulinkdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(ulinkdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(ulinkdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(ulinkdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(ulinkdir)" || exit $$?; \ done uninstall-dist_ulinkDATA: @$(NORMAL_UNINSTALL) @list='$(dist_ulink_DATA)'; test -n "$(ulinkdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(ulinkdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(ulinkdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f versaloon/$(DEPDIR)/$(am__dirstamp) -rm -f versaloon/$(am__dirstamp) -rm -f versaloon/usbtoxxx/$(DEPDIR)/$(am__dirstamp) -rm -f versaloon/usbtoxxx/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) versaloon/$(DEPDIR) versaloon/usbtoxxx/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dist_ulinkDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) versaloon/$(DEPDIR) versaloon/usbtoxxx/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-dist_ulinkDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_ulinkDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-dist_ulinkDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/drivers/mpsse.c0000644000175000017500000006132012516456302014563 00000000000000/************************************************************************** * Copyright (C) 2012 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mpsse.h" #include "helper/log.h" #include /* Compatibility define for older libusb-1.0 */ #ifndef LIBUSB_CALL #define LIBUSB_CALL #endif #ifdef _DEBUG_JTAG_IO_ #define DEBUG_IO(expr...) LOG_DEBUG(expr) #define DEBUG_PRINT_BUF(buf, len) \ do { \ char buf_string[32 * 3 + 1]; \ int buf_string_pos = 0; \ for (int i = 0; i < len; i++) { \ buf_string_pos += sprintf(buf_string + buf_string_pos, " %02x", buf[i]); \ if (i % 32 == 32 - 1) { \ LOG_DEBUG("%s", buf_string); \ buf_string_pos = 0; \ } \ } \ if (buf_string_pos > 0) \ LOG_DEBUG("%s", buf_string);\ } while (0) #else #define DEBUG_IO(expr...) do {} while (0) #define DEBUG_PRINT_BUF(buf, len) do {} while (0) #endif #define FTDI_DEVICE_OUT_REQTYPE (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE) #define FTDI_DEVICE_IN_REQTYPE (0x80 | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE) #define BITMODE_MPSSE 0x02 #define SIO_RESET_REQUEST 0x00 #define SIO_SET_LATENCY_TIMER_REQUEST 0x09 #define SIO_GET_LATENCY_TIMER_REQUEST 0x0A #define SIO_SET_BITMODE_REQUEST 0x0B #define SIO_RESET_SIO 0 #define SIO_RESET_PURGE_RX 1 #define SIO_RESET_PURGE_TX 2 struct mpsse_ctx { libusb_context *usb_ctx; libusb_device_handle *usb_dev; unsigned int usb_write_timeout; unsigned int usb_read_timeout; uint8_t in_ep; uint8_t out_ep; uint16_t max_packet_size; uint16_t index; uint8_t interface; enum ftdi_chip_type type; uint8_t *write_buffer; unsigned write_size; unsigned write_count; uint8_t *read_buffer; unsigned read_size; unsigned read_count; uint8_t *read_chunk; unsigned read_chunk_size; struct bit_copy_queue read_queue; int retval; }; /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, const char *string) { int retval; char desc_string[256]; /* Max size of string descriptor */ retval = libusb_get_string_descriptor_ascii(device, str_index, (unsigned char *)desc_string, sizeof(desc_string)); if (retval < 0) { LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %s", libusb_error_name(retval)); return false; } return strncmp(string, desc_string, sizeof(desc_string)) == 0; } /* Helper to open a libusb device that matches vid, pid, product string and/or serial string. * Set any field to 0 as a wildcard. If the device is found true is returned, with ctx containing * the already opened handle. ctx->interface must be set to the desired interface (channel) number * prior to calling this function. */ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid, const char *product, const char *serial) { libusb_device **list; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config0; int err; bool found = false; ssize_t cnt = libusb_get_device_list(ctx->usb_ctx, &list); if (cnt < 0) LOG_ERROR("libusb_get_device_list() failed with %s", libusb_error_name(cnt)); for (ssize_t i = 0; i < cnt; i++) { libusb_device *device = list[i]; err = libusb_get_device_descriptor(device, &desc); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_get_device_descriptor() failed with %s", libusb_error_name(err)); continue; } if (vid && *vid != desc.idVendor) continue; if (pid && *pid != desc.idProduct) continue; err = libusb_open(device, &ctx->usb_dev); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_open() failed with %s", libusb_error_name(err)); continue; } if (product && !string_descriptor_equal(ctx->usb_dev, desc.iProduct, product)) { libusb_close(ctx->usb_dev); continue; } if (serial && !string_descriptor_equal(ctx->usb_dev, desc.iSerialNumber, serial)) { libusb_close(ctx->usb_dev); continue; } found = true; break; } libusb_free_device_list(list, 1); if (!found) { LOG_ERROR("no device found"); return false; } err = libusb_get_config_descriptor(libusb_get_device(ctx->usb_dev), 0, &config0); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_get_config_descriptor() failed with %s", libusb_error_name(err)); libusb_close(ctx->usb_dev); return false; } /* Make sure the first configuration is selected */ int cfg; err = libusb_get_configuration(ctx->usb_dev, &cfg); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_get_configuration() failed with %s", libusb_error_name(err)); goto error; } if (desc.bNumConfigurations > 0 && cfg != config0->bConfigurationValue) { err = libusb_set_configuration(ctx->usb_dev, config0->bConfigurationValue); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_set_configuration() failed with %s", libusb_error_name(err)); goto error; } } /* Try to detach ftdi_sio kernel module */ err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface); if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_NOT_SUPPORTED) { LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err)); goto error; } err = libusb_claim_interface(ctx->usb_dev, ctx->interface); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_claim_interface() failed with %s", libusb_error_name(err)); goto error; } /* Reset FTDI device */ err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_SIO, ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("failed to reset FTDI device: %s", libusb_error_name(err)); goto error; } switch (desc.bcdDevice) { case 0x500: ctx->type = TYPE_FT2232C; break; case 0x700: ctx->type = TYPE_FT2232H; break; case 0x800: ctx->type = TYPE_FT4232H; break; case 0x900: ctx->type = TYPE_FT232H; break; default: LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice); goto error; } /* Determine maximum packet size and endpoint addresses */ if (!(desc.bNumConfigurations > 0 && ctx->interface < config0->bNumInterfaces && config0->interface[ctx->interface].num_altsetting > 0)) goto desc_error; const struct libusb_interface_descriptor *descriptor; descriptor = &config0->interface[ctx->interface].altsetting[0]; if (descriptor->bNumEndpoints != 2) goto desc_error; ctx->in_ep = 0; ctx->out_ep = 0; for (int i = 0; i < descriptor->bNumEndpoints; i++) { if (descriptor->endpoint[i].bEndpointAddress & 0x80) { ctx->in_ep = descriptor->endpoint[i].bEndpointAddress; ctx->max_packet_size = descriptor->endpoint[i].wMaxPacketSize; } else { ctx->out_ep = descriptor->endpoint[i].bEndpointAddress; } } if (ctx->in_ep == 0 || ctx->out_ep == 0) goto desc_error; libusb_free_config_descriptor(config0); return true; desc_error: LOG_ERROR("unrecognized USB device descriptor"); error: libusb_free_config_descriptor(config0); libusb_close(ctx->usb_dev); return false; } struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, const char *serial, int channel) { struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx)); int err; if (!ctx) return 0; bit_copy_queue_init(&ctx->read_queue); ctx->read_chunk_size = 16384; ctx->read_size = 16384; ctx->write_size = 16384; ctx->read_chunk = malloc(ctx->read_chunk_size); ctx->read_buffer = malloc(ctx->read_size); ctx->write_buffer = malloc(ctx->write_size); if (!ctx->read_chunk || !ctx->read_buffer || !ctx->write_buffer) goto error; ctx->interface = channel; ctx->index = channel + 1; ctx->usb_read_timeout = 5000; ctx->usb_write_timeout = 5000; err = libusb_init(&ctx->usb_ctx); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_init() failed with %s", libusb_error_name(err)); goto error; } if (!open_matching_device(ctx, vid, pid, description, serial)) { /* Four hex digits plus terminating zero each */ char vidstr[5]; char pidstr[5]; LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s' and " "serial '%s'", vid ? sprintf(vidstr, "%04x", *vid), vidstr : "*", pid ? sprintf(pidstr, "%04x", *pid), pidstr : "*", description ? description : "*", serial ? serial : "*"); ctx->usb_dev = 0; goto error; } err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_LATENCY_TIMER_REQUEST, 255, ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to set latency timer: %s", libusb_error_name(err)); goto error; } err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_BITMODE_REQUEST, 0x0b | (BITMODE_MPSSE << 8), ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to set MPSSE bitmode: %s", libusb_error_name(err)); goto error; } mpsse_purge(ctx); return ctx; error: mpsse_close(ctx); return 0; } void mpsse_close(struct mpsse_ctx *ctx) { if (ctx->usb_dev) libusb_close(ctx->usb_dev); if (ctx->usb_ctx) libusb_exit(ctx->usb_ctx); bit_copy_discard(&ctx->read_queue); if (ctx->write_buffer) free(ctx->write_buffer); if (ctx->read_buffer) free(ctx->read_buffer); if (ctx->read_chunk) free(ctx->read_chunk); free(ctx); } bool mpsse_is_high_speed(struct mpsse_ctx *ctx) { return ctx->type != TYPE_FT2232C; } void mpsse_purge(struct mpsse_ctx *ctx) { int err; LOG_DEBUG("-"); ctx->write_count = 0; ctx->read_count = 0; ctx->retval = ERROR_OK; bit_copy_discard(&ctx->read_queue); err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_PURGE_RX, ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to purge ftdi rx buffers: %s", libusb_error_name(err)); return; } err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_PURGE_TX, ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to purge ftdi tx buffers: %s", libusb_error_name(err)); return; } } static unsigned buffer_write_space(struct mpsse_ctx *ctx) { /* Reserve one byte for SEND_IMMEDIATE */ return ctx->write_size - ctx->write_count - 1; } static unsigned buffer_read_space(struct mpsse_ctx *ctx) { return ctx->read_size - ctx->read_count; } static void buffer_write_byte(struct mpsse_ctx *ctx, uint8_t data) { DEBUG_IO("%02x", data); assert(ctx->write_count < ctx->write_size); ctx->write_buffer[ctx->write_count++] = data; } static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned bit_count) { DEBUG_IO("%d bits", bit_count); assert(ctx->write_count + DIV_ROUND_UP(bit_count, 8) <= ctx->write_size); bit_copy(ctx->write_buffer + ctx->write_count, 0, out, out_offset, bit_count); ctx->write_count += DIV_ROUND_UP(bit_count, 8); return bit_count; } static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned bit_count, unsigned offset) { DEBUG_IO("%d bits, offset %d", bit_count, offset); assert(ctx->read_count + DIV_ROUND_UP(bit_count, 8) <= ctx->read_size); bit_copy_queued(&ctx->read_queue, in, in_offset, ctx->read_buffer + ctx->read_count, offset, bit_count); ctx->read_count += DIV_ROUND_UP(bit_count, 8); return bit_count; } void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned length, uint8_t mode) { mpsse_clock_data(ctx, out, out_offset, 0, 0, length, mode); } void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, uint8_t mode) { mpsse_clock_data(ctx, 0, 0, in, in_offset, length, mode); } void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, unsigned in_offset, unsigned length, uint8_t mode) { /* TODO: Fix MSB first modes */ DEBUG_IO("%s%s %d bits", in ? "in" : "", out ? "out" : "", length); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } /* TODO: On H chips, use command 0x8E/0x8F if in and out are both 0 */ if (out || (!out && !in)) mode |= 0x10; if (in) mode |= 0x20; while (length > 0) { /* Guarantee buffer space enough for a minimum size transfer */ if (buffer_write_space(ctx) + (length < 8) < (out || (!out && !in) ? 4 : 3) || (in && buffer_read_space(ctx) < 1)) ctx->retval = mpsse_flush(ctx); if (length < 8) { /* Transfer remaining bits in bit mode */ buffer_write_byte(ctx, 0x02 | mode); buffer_write_byte(ctx, length - 1); if (out) out_offset += buffer_write(ctx, out, out_offset, length); if (in) in_offset += buffer_add_read(ctx, in, in_offset, length, 8 - length); if (!out && !in) buffer_write_byte(ctx, 0x00); length = 0; } else { /* Byte transfer */ unsigned this_bytes = length / 8; /* MPSSE command limit */ if (this_bytes > 65536) this_bytes = 65536; /* Buffer space limit. We already made sure there's space for the minimum * transfer. */ if ((out || (!out && !in)) && this_bytes + 3 > buffer_write_space(ctx)) this_bytes = buffer_write_space(ctx) - 3; if (in && this_bytes > buffer_read_space(ctx)) this_bytes = buffer_read_space(ctx); if (this_bytes > 0) { buffer_write_byte(ctx, mode); buffer_write_byte(ctx, (this_bytes - 1) & 0xff); buffer_write_byte(ctx, (this_bytes - 1) >> 8); if (out) out_offset += buffer_write(ctx, out, out_offset, this_bytes * 8); if (in) in_offset += buffer_add_read(ctx, in, in_offset, this_bytes * 8, 0); if (!out && !in) for (unsigned n = 0; n < this_bytes; n++) buffer_write_byte(ctx, 0x00); length -= this_bytes * 8; } } } } void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned length, bool tdi, uint8_t mode) { mpsse_clock_tms_cs(ctx, out, out_offset, 0, 0, length, tdi, mode); } void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, unsigned in_offset, unsigned length, bool tdi, uint8_t mode) { DEBUG_IO("%sout %d bits, tdi=%d", in ? "in" : "", length, tdi); assert(out); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } mode |= 0x42; if (in) mode |= 0x20; while (length > 0) { /* Guarantee buffer space enough for a minimum size transfer */ if (buffer_write_space(ctx) < 3 || (in && buffer_read_space(ctx) < 1)) ctx->retval = mpsse_flush(ctx); /* Byte transfer */ unsigned this_bits = length; /* MPSSE command limit */ /* NOTE: there's a report of an FT2232 bug in this area, where shifting * exactly 7 bits can make problems with TMS signaling for the last * clock cycle: * * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html */ if (this_bits > 7) this_bits = 7; if (this_bits > 0) { buffer_write_byte(ctx, mode); buffer_write_byte(ctx, this_bits - 1); uint8_t data = 0; /* TODO: Fix MSB first, if allowed in MPSSE */ bit_copy(&data, 0, out, out_offset, this_bits); out_offset += this_bits; buffer_write_byte(ctx, data | (tdi ? 0x80 : 0x00)); if (in) in_offset += buffer_add_read(ctx, in, in_offset, this_bits, 8 - this_bits); length -= this_bits; } } } void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir) { DEBUG_IO("-"); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 3) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, 0x80); buffer_write_byte(ctx, data); buffer_write_byte(ctx, dir); } void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir) { DEBUG_IO("-"); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 3) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, 0x82); buffer_write_byte(ctx, data); buffer_write_byte(ctx, dir); } void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data) { DEBUG_IO("-"); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 1 || buffer_read_space(ctx) < 1) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, 0x81); buffer_add_read(ctx, data, 0, 8, 0); } void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data) { DEBUG_IO("-"); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 1 || buffer_read_space(ctx) < 1) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, 0x83); buffer_add_read(ctx, data, 0, 8, 0); } static void single_byte_boolean_helper(struct mpsse_ctx *ctx, bool var, uint8_t val_if_true, uint8_t val_if_false) { if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 1) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, var ? val_if_true : val_if_false); } void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable) { LOG_DEBUG("%s", enable ? "on" : "off"); single_byte_boolean_helper(ctx, enable, 0x84, 0x85); } void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) { LOG_DEBUG("%d", divisor); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } if (buffer_write_space(ctx) < 3) ctx->retval = mpsse_flush(ctx); buffer_write_byte(ctx, 0x86); buffer_write_byte(ctx, divisor & 0xff); buffer_write_byte(ctx, divisor >> 8); } int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; LOG_DEBUG("%s", enable ? "on" : "off"); single_byte_boolean_helper(ctx, enable, 0x8b, 0x8a); return ERROR_OK; } int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; LOG_DEBUG("%s", enable ? "on" : "off"); single_byte_boolean_helper(ctx, enable, 0x96, 0x97); return ERROR_OK; } int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency) { LOG_DEBUG("target %d Hz", frequency); assert(frequency >= 0); int base_clock; if (frequency == 0) return mpsse_rtck_config(ctx, true); mpsse_rtck_config(ctx, false); /* just try */ if (frequency > 60000000 / 2 / 65536 && mpsse_divide_by_5_config(ctx, false) == ERROR_OK) { base_clock = 60000000; } else { mpsse_divide_by_5_config(ctx, true); /* just try */ base_clock = 12000000; } int divisor = (base_clock / 2 + frequency - 1) / frequency - 1; if (divisor > 65535) divisor = 65535; assert(divisor >= 0); mpsse_set_divisor(ctx, divisor); frequency = base_clock / 2 / (1 + divisor); LOG_DEBUG("actually %d Hz", frequency); return frequency; } /* Context needed by the callbacks */ struct transfer_result { struct mpsse_ctx *ctx; bool done; unsigned transferred; }; static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer) { struct transfer_result *res = transfer->user_data; struct mpsse_ctx *ctx = res->ctx; unsigned packet_size = ctx->max_packet_size; DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length); /* Strip the two status bytes sent at the beginning of each USB packet * while copying the chunk buffer to the read buffer */ unsigned num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size); unsigned chunk_remains = transfer->actual_length; for (unsigned i = 0; i < num_packets && chunk_remains > 2; i++) { unsigned this_size = packet_size - 2; if (this_size > chunk_remains - 2) this_size = chunk_remains - 2; if (this_size > ctx->read_count - res->transferred) this_size = ctx->read_count - res->transferred; memcpy(ctx->read_buffer + res->transferred, ctx->read_chunk + packet_size * i + 2, this_size); res->transferred += this_size; chunk_remains -= this_size + 2; if (res->transferred == ctx->read_count) { res->done = true; break; } } DEBUG_IO("raw chunk %d, transferred %d of %d", transfer->actual_length, res->transferred, ctx->read_count); if (!res->done) if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS) res->done = true; } static LIBUSB_CALL void write_cb(struct libusb_transfer *transfer) { struct transfer_result *res = transfer->user_data; struct mpsse_ctx *ctx = res->ctx; res->transferred += transfer->actual_length; DEBUG_IO("transferred %d of %d", res->transferred, ctx->write_count); DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length); if (res->transferred == ctx->write_count) res->done = true; else { transfer->length = ctx->write_count - res->transferred; transfer->buffer = ctx->write_buffer + res->transferred; if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS) res->done = true; } } int mpsse_flush(struct mpsse_ctx *ctx) { int retval = ctx->retval; if (retval != ERROR_OK) { DEBUG_IO("Ignoring flush due to previous error"); assert(ctx->write_count == 0 && ctx->read_count == 0); ctx->retval = ERROR_OK; return retval; } DEBUG_IO("write %d%s, read %d", ctx->write_count, ctx->read_count ? "+1" : "", ctx->read_count); assert(ctx->write_count > 0 || ctx->read_count == 0); /* No read data without write data */ if (ctx->write_count == 0) return retval; struct libusb_transfer *read_transfer = 0; struct transfer_result read_result = { .ctx = ctx, .done = true }; if (ctx->read_count) { buffer_write_byte(ctx, 0x87); /* SEND_IMMEDIATE */ read_result.done = false; /* delay read transaction to ensure the FTDI chip can support us with data immediately after processing the MPSSE commands in the write transaction */ } struct transfer_result write_result = { .ctx = ctx, .done = false }; struct libusb_transfer *write_transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer, ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout); retval = libusb_submit_transfer(write_transfer); if (ctx->read_count) { read_transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(read_transfer, ctx->usb_dev, ctx->in_ep, ctx->read_chunk, ctx->read_chunk_size, read_cb, &read_result, ctx->usb_read_timeout); retval = libusb_submit_transfer(read_transfer); } /* Polling loop, more or less taken from libftdi */ while (!write_result.done || !read_result.done) { retval = libusb_handle_events(ctx->usb_ctx); keep_alive(); if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) { libusb_cancel_transfer(write_transfer); if (read_transfer) libusb_cancel_transfer(read_transfer); while (!write_result.done || !read_result.done) if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS) break; } } if (retval != LIBUSB_SUCCESS) { LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval)); retval = ERROR_FAIL; } else if (write_result.transferred < ctx->write_count) { LOG_ERROR("ftdi device did not accept all data: %d, tried %d", write_result.transferred, ctx->write_count); retval = ERROR_FAIL; } else if (read_result.transferred < ctx->read_count) { LOG_ERROR("ftdi device did not return all data: %d, expected %d", read_result.transferred, ctx->read_count); retval = ERROR_FAIL; } else if (ctx->read_count) { ctx->write_count = 0; ctx->read_count = 0; bit_copy_execute(&ctx->read_queue); retval = ERROR_OK; } else { ctx->write_count = 0; bit_copy_discard(&ctx->read_queue); retval = ERROR_OK; } libusb_free_transfer(write_transfer); if (read_transfer) libusb_free_transfer(read_transfer); if (retval != ERROR_OK) mpsse_purge(ctx); return retval; } openocd-0.9.0/src/jtag/drivers/mpsse.h0000644000175000017500000000750212315575360014575 00000000000000/************************************************************************** * Copyright (C) 2012 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MPSSE_H_ #define MPSSE_H_ #include #include "helper/binarybuffer.h" /* Mode flags */ #define POS_EDGE_OUT 0x00 #define NEG_EDGE_OUT 0x01 #define POS_EDGE_IN 0x00 #define NEG_EDGE_IN 0x04 #define MSB_FIRST 0x00 #define LSB_FIRST 0x08 enum ftdi_chip_type { TYPE_FT2232C, TYPE_FT2232H, TYPE_FT4232H, TYPE_FT232H, }; struct mpsse_ctx; /* Device handling */ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, const char *serial, int channel); void mpsse_close(struct mpsse_ctx *ctx); bool mpsse_is_high_speed(struct mpsse_ctx *ctx); /* Command queuing. These correspond to the MPSSE commands with the same names, but no need to care * about bit/byte transfer or data length limitation. Read data is guaranteed to be available only * after the following mpsse_flush(). */ void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned length, uint8_t mode); void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, uint8_t mode); void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, unsigned in_offset, unsigned length, uint8_t mode); void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned length, bool tdi, uint8_t mode); void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, unsigned in_offset, unsigned length, bool tdi, uint8_t mode); void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable); void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor); int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable); int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable); /* Helper to set frequency in Hertz. Returns actual realizable frequency or negative error. * Frequency 0 means RTCK. */ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency); /* Queue handling */ int mpsse_flush(struct mpsse_ctx *ctx); void mpsse_purge(struct mpsse_ctx *ctx); #endif /* MPSSE_H_ */ openocd-0.9.0/src/jtag/drivers/rlink_init.m40000644000175000017500000000475612315575360015711 00000000000000m4_divert(`-1') /*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ m4_undefine(`CTRL_MPEG_L') m4_undefine(`CTRL_CARD_L') m4_ifelse(SHIFTER_PRESCALER, 1, ` m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x0')') ') m4_ifelse(SHIFTER_PRESCALER, 2, ` m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x2')') m4_define(`CTRL_CARD_L', `m4_eval(`0x8 | 0x1')') ') m4_ifelse(SHIFTER_PRESCALER, 8, ` m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x3')') ') m4_ifelse(SHIFTER_PRESCALER, 11, ` m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x4')') ') m4_ifelse(SHIFTER_PRESCALER, 64, ` m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x7')') ') m4_ifdef(`CTRL_MPEG_L',,` m4_errprint(`SHIFTER_PRESCALER was not defined with a supported value ') m4_m4exit(`1') ') m4_divert(`0')m4_dnl init: A.H = 0 A.L = 0 DR_MPEG = A ; TDI and TCK start out low DR_CARD = A ; TMS starts out low A.L = 0x6 CTRL_FCI = A ; MPEG and CARD driven by FCI DDR_MPEG = A ; TDI and TCK are outputs A.L = 0x1 X = A ; X == 1 DDR_CARD = A ; TMS is output A.L = CTRL_MPEG_L CTRL_MPEG = A m4_ifdef(`CTRL_CARD_L', ` A.L = 'CTRL_CARD_L` ')m4_dnl CTRL_CARD = A STATUS STOP openocd-0.9.0/src/jtag/drivers/ti_icdi_usb.c0000644000175000017500000004511312516456302015713 00000000000000/*************************************************************************** * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include #include #include #define ICDI_WRITE_ENDPOINT 0x02 #define ICDI_READ_ENDPOINT 0x83 #define ICDI_WRITE_TIMEOUT 1000 #define ICDI_READ_TIMEOUT 1000 #define ICDI_PACKET_SIZE 2048 #define PACKET_START "$" #define PACKET_END "#" struct icdi_usb_handle_s { libusb_context *usb_ctx; libusb_device_handle *usb_dev; char *read_buffer; char *write_buffer; int max_packet; int read_count; uint32_t max_rw_packet; /* max X packet (read/write memory) transfers */ }; static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer); static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer); static int remote_escape_output(const char *buffer, int len, char *out_buf, int *out_len, int out_maxlen) { int input_index, output_index; output_index = 0; for (input_index = 0; input_index < len; input_index++) { char b = buffer[input_index]; if (b == '$' || b == '#' || b == '}' || b == '*') { /* These must be escaped. */ if (output_index + 2 > out_maxlen) break; out_buf[output_index++] = '}'; out_buf[output_index++] = b ^ 0x20; } else { if (output_index + 1 > out_maxlen) break; out_buf[output_index++] = b; } } *out_len = input_index; return output_index; } static int remote_unescape_input(const char *buffer, int len, char *out_buf, int out_maxlen) { int input_index, output_index; int escaped; output_index = 0; escaped = 0; for (input_index = 0; input_index < len; input_index++) { char b = buffer[input_index]; if (output_index + 1 > out_maxlen) LOG_ERROR("Received too much data from the target."); if (escaped) { out_buf[output_index++] = b ^ 0x20; escaped = 0; } else if (b == '}') escaped = 1; else out_buf[output_index++] = b; } if (escaped) LOG_ERROR("Unmatched escape character in target response."); return output_index; } static int icdi_send_packet(void *handle, int len) { unsigned char cksum = 0; struct icdi_usb_handle_s *h = handle; int result, retry = 0; int transferred = 0; assert(handle != NULL); /* check we have a large enough buffer for checksum "#00" */ if (len + 3 > h->max_packet) { LOG_ERROR("packet buffer too small"); return ERROR_FAIL; } /* calculate checksum - offset start of packet */ for (int i = 1; i < len; i++) cksum += h->write_buffer[i]; len += sprintf(&h->write_buffer[len], PACKET_END "%02x", cksum); #ifdef _DEBUG_USB_COMMS_ char buffer[50]; char ch = h->write_buffer[1]; if (ch == 'x' || ch == 'X') LOG_DEBUG("writing packet: "); else { memcpy(buffer, h->write_buffer, len >= 50 ? 50-1 : len); buffer[len] = 0; LOG_DEBUG("writing packet: %s", buffer); } #endif while (1) { result = libusb_bulk_transfer(h->usb_dev, ICDI_WRITE_ENDPOINT, (unsigned char *)h->write_buffer, len, &transferred, ICDI_WRITE_TIMEOUT); if (result != 0 || transferred != len) { LOG_DEBUG("Error TX Data %d", result); return ERROR_FAIL; } /* check that the client got the message ok, or shall we resend */ result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer, h->max_packet, &transferred, ICDI_READ_TIMEOUT); if (result != 0 || transferred < 1) { LOG_DEBUG("Error RX Data %d", result); return ERROR_FAIL; } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("received reply: '%c' : count %d", h->read_buffer[0], transferred); #endif if (h->read_buffer[0] == '-') { LOG_DEBUG("Resending packet %d", ++retry); } else { if (h->read_buffer[0] != '+') LOG_DEBUG("Unexpected Reply from ICDI: %c", h->read_buffer[0]); break; } if (retry == 3) { LOG_DEBUG("maximum nack retries attempted"); return ERROR_FAIL; } } retry = 0; h->read_count = transferred; while (1) { /* read reply from icdi */ result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer + h->read_count, h->max_packet - h->read_count, &transferred, ICDI_READ_TIMEOUT); #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("received data: count %d", transferred); #endif /* check for errors but retry for timeout */ if (result != 0) { if (result == LIBUSB_ERROR_TIMEOUT) { LOG_DEBUG("Error RX timeout %d", result); } else { LOG_DEBUG("Error RX Data %d", result); return ERROR_FAIL; } } h->read_count += transferred; /* we need to make sure we have a full packet, including checksum */ if (h->read_count > 5) { /* check that we have received an packet delimiter * we do not validate the checksum * reply should contain $...#AA - so we check for # */ if (h->read_buffer[h->read_count - 3] == '#') return ERROR_OK; } if (retry++ == 3) { LOG_DEBUG("maximum data retries attempted"); break; } } return ERROR_FAIL; } static int icdi_send_cmd(void *handle, const char *cmd) { struct icdi_usb_handle_s *h = handle; int cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "%s", cmd); return icdi_send_packet(handle, cmd_len); } static int icdi_send_remote_cmd(void *handle, const char *data) { struct icdi_usb_handle_s *h = handle; size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len); return icdi_send_packet(handle, cmd_len); } static int icdi_get_cmd_result(void *handle) { struct icdi_usb_handle_s *h = handle; int offset = 0; char ch; assert(handle != NULL); do { ch = h->read_buffer[offset++]; if (offset > h->read_count) return ERROR_FAIL; } while (ch != '$'); if (memcmp("OK", h->read_buffer + offset, 2) == 0) return ERROR_OK; if (h->read_buffer[offset] == 'E') { /* get error code */ char result; if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1) return ERROR_FAIL; return result; } /* for now we assume everything else is ok */ return ERROR_OK; } static int icdi_usb_idcode(void *handle, uint32_t *idcode) { *idcode = 0; return ERROR_OK; } static int icdi_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) { uint8_t buf[4]; /* REVISIT: There's no target pointer here so there's no way to use target_buffer_set_u32(). * I guess all supported chips are little-endian anyway. */ h_u32_to_le(buf, val); return icdi_usb_write_mem(handle, addr, 4, 1, buf); } static enum target_state icdi_usb_state(void *handle) { int result; struct icdi_usb_handle_s *h = handle; uint32_t dhcsr; uint8_t buf[4]; result = icdi_usb_read_mem(h, DCB_DHCSR, 4, 1, buf); if (result != ERROR_OK) return TARGET_UNKNOWN; /* REVISIT: There's no target pointer here so there's no way to use target_buffer_get_u32(). * I guess all supported chips are little-endian anyway. */ dhcsr = le_to_h_u32(buf); if (dhcsr & S_HALT) return TARGET_HALTED; return TARGET_RUNNING; } static int icdi_usb_version(void *handle) { struct icdi_usb_handle_s *h = handle; char version[20]; /* get info about icdi */ int result = icdi_send_remote_cmd(handle, "version"); if (result != ERROR_OK) return result; if (h->read_count < 8) { LOG_ERROR("Invalid Reply Received"); return ERROR_FAIL; } /* convert reply */ if (unhexify(version, h->read_buffer + 2, 4) != 4) { LOG_WARNING("unable to get ICDI version"); return ERROR_OK; } /* null terminate and print info */ version[4] = 0; LOG_INFO("ICDI Firmware version: %s", version); return ERROR_OK; } static int icdi_usb_query(void *handle) { int result; struct icdi_usb_handle_s *h = handle; result = icdi_send_cmd(handle, "qSupported"); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("query supported failed: 0x%x", result); return ERROR_FAIL; } /* from this we can get the max packet supported */ /* query packet buffer size */ char *offset = strstr(h->read_buffer, "PacketSize"); if (offset) { char *separator; int max_packet; max_packet = strtol(offset + 11, &separator, 16); if (!max_packet) LOG_ERROR("invalid max packet, using defaults"); else h->max_packet = max_packet; LOG_DEBUG("max packet supported : %i bytes", h->max_packet); } /* if required re allocate packet buffer */ if (h->max_packet != ICDI_PACKET_SIZE) { h->read_buffer = realloc(h->read_buffer, h->max_packet); h->write_buffer = realloc(h->write_buffer, h->max_packet); if (h->read_buffer == 0 || h->write_buffer == 0) { LOG_ERROR("unable to reallocate memory"); return ERROR_FAIL; } } /* set extended mode */ result = icdi_send_cmd(handle, "!"); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("unable to enable extended mode: 0x%x", result); return ERROR_FAIL; } return ERROR_OK; } static int icdi_usb_reset(void *handle) { /* we do this in hla_target.c */ return ERROR_OK; } static int icdi_usb_assert_srst(void *handle, int srst) { /* TODO not supported yet */ return ERROR_COMMAND_NOTFOUND; } static int icdi_usb_run(void *handle) { int result; /* resume target at current address */ result = icdi_send_cmd(handle, "c"); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("continue failed: 0x%x", result); return ERROR_FAIL; } return result; } static int icdi_usb_halt(void *handle) { int result; /* this query halts the target ?? */ result = icdi_send_cmd(handle, "?"); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("halt failed: 0x%x", result); return ERROR_FAIL; } return result; } static int icdi_usb_step(void *handle) { int result; /* step target at current address */ result = icdi_send_cmd(handle, "s"); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("step failed: 0x%x", result); return ERROR_FAIL; } return result; } static int icdi_usb_read_regs(void *handle) { /* currently unsupported */ return ERROR_OK; } static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) { int result; struct icdi_usb_handle_s *h = handle; char cmd[10]; snprintf(cmd, sizeof(cmd), "p%x", num); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("register read failed: 0x%x", result); return ERROR_FAIL; } /* convert result */ uint8_t buf[4]; if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) { LOG_ERROR("failed to convert result"); return ERROR_FAIL; } *val = le_to_h_u32(buf); return result; } static int icdi_usb_write_reg(void *handle, int num, uint32_t val) { int result; char cmd[20]; uint8_t buf[4]; h_u32_to_le(buf, val); int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd)); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("register write failed: 0x%x", result); return ERROR_FAIL; } return result; } static int icdi_usb_read_mem_int(void *handle, uint32_t addr, uint32_t len, uint8_t *buffer) { int result; struct icdi_usb_handle_s *h = handle; char cmd[20]; snprintf(cmd, sizeof(cmd), "x%" PRIx32 ",%" PRIx32, addr, len); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("memory read failed: 0x%x", result); return ERROR_FAIL; } /* unescape input */ int read_len = remote_unescape_input(h->read_buffer + 5, h->read_count - 8, (char *)buffer, len); if (read_len != (int)len) { LOG_ERROR("read more bytes than expected: actual 0x%x expected 0x%" PRIx32, read_len, len); return ERROR_FAIL; } return ERROR_OK; } static int icdi_usb_write_mem_int(void *handle, uint32_t addr, uint32_t len, const uint8_t *buffer) { int result; struct icdi_usb_handle_s *h = handle; size_t cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "X%" PRIx32 ",%" PRIx32 ":", addr, len); int out_len; cmd_len += remote_escape_output((const char *)buffer, len, h->write_buffer + cmd_len, &out_len, h->max_packet - cmd_len); if (out_len < (int)len) { /* for now issue a error as we have no way of allocating a larger buffer */ LOG_ERROR("memory buffer too small: requires 0x%x actual 0x%" PRIx32, out_len, len); return ERROR_FAIL; } result = icdi_send_packet(handle, cmd_len); if (result != ERROR_OK) return result; /* check result */ result = icdi_get_cmd_result(handle); if (result != ERROR_OK) { LOG_ERROR("memory write failed: 0x%x", result); return ERROR_FAIL; } return ERROR_OK; } static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { int retval = ERROR_OK; struct icdi_usb_handle_s *h = handle; uint32_t bytes_remaining; /* calculate byte count */ count *= size; while (count) { bytes_remaining = h->max_rw_packet; if (count < bytes_remaining) bytes_remaining = count; retval = icdi_usb_read_mem_int(handle, addr, bytes_remaining, buffer); if (retval != ERROR_OK) return retval; buffer += bytes_remaining; addr += bytes_remaining; count -= bytes_remaining; } return retval; } static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval = ERROR_OK; struct icdi_usb_handle_s *h = handle; uint32_t bytes_remaining; /* calculate byte count */ count *= size; while (count) { bytes_remaining = h->max_rw_packet; if (count < bytes_remaining) bytes_remaining = count; retval = icdi_usb_write_mem_int(handle, addr, bytes_remaining, buffer); if (retval != ERROR_OK) return retval; buffer += bytes_remaining; addr += bytes_remaining; count -= bytes_remaining; } return retval; } static int icdi_usb_override_target(const char *targetname) { return !strcmp(targetname, "cortex_m"); } static int icdi_usb_close(void *handle) { struct icdi_usb_handle_s *h = handle; if (!h) return ERROR_OK; if (h->usb_dev) libusb_close(h->usb_dev); if (h->usb_ctx) libusb_exit(h->usb_ctx); if (h->read_buffer) free(h->read_buffer); if (h->write_buffer) free(h->write_buffer); free(handle); return ERROR_OK; } static int icdi_usb_open(struct hl_interface_param_s *param, void **fd) { int retval; struct icdi_usb_handle_s *h; LOG_DEBUG("icdi_usb_open"); h = calloc(1, sizeof(struct icdi_usb_handle_s)); if (h == 0) { LOG_ERROR("unable to allocate memory"); return ERROR_FAIL; } LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport, param->vid, param->pid); if (libusb_init(&h->usb_ctx) != 0) { LOG_ERROR("libusb init failed"); goto error_open; } h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid, param->pid); if (!h->usb_dev) { LOG_ERROR("open failed"); goto error_open; } if (libusb_claim_interface(h->usb_dev, 2)) { LOG_DEBUG("claim interface failed"); goto error_open; } /* check if mode is supported */ retval = ERROR_OK; switch (param->transport) { #if 0 /* TODO place holder as swd is not currently supported */ case HL_TRANSPORT_SWD: #endif case HL_TRANSPORT_JTAG: break; default: retval = ERROR_FAIL; break; } if (retval != ERROR_OK) { LOG_ERROR("mode (transport) not supported by device"); goto error_open; } /* allocate buffer */ h->read_buffer = malloc(ICDI_PACKET_SIZE); h->write_buffer = malloc(ICDI_PACKET_SIZE); h->max_packet = ICDI_PACKET_SIZE; if (h->read_buffer == 0 || h->write_buffer == 0) { LOG_DEBUG("malloc failed"); goto error_open; } /* query icdi version etc */ retval = icdi_usb_version(h); if (retval != ERROR_OK) goto error_open; /* query icdi support */ retval = icdi_usb_query(h); if (retval != ERROR_OK) goto error_open; *fd = h; /* set the max target read/write buffer in bytes * as we are using gdb binary packets to transfer memory we have to * reserve half the buffer for any possible escape chars plus * at least 64 bytes for the gdb packet header */ h->max_rw_packet = (((h->max_packet - 64) / 4) * 4) / 2; return ERROR_OK; error_open: icdi_usb_close(h); return ERROR_FAIL; } struct hl_layout_api_s icdi_usb_layout_api = { .open = icdi_usb_open, .close = icdi_usb_close, .idcode = icdi_usb_idcode, .state = icdi_usb_state, .reset = icdi_usb_reset, .assert_srst = icdi_usb_assert_srst, .run = icdi_usb_run, .halt = icdi_usb_halt, .step = icdi_usb_step, .read_regs = icdi_usb_read_regs, .read_reg = icdi_usb_read_reg, .write_reg = icdi_usb_write_reg, .read_mem = icdi_usb_read_mem, .write_mem = icdi_usb_write_mem, .write_debug_reg = icdi_usb_write_debug_reg, .override_target = icdi_usb_override_target, .custom_command = icdi_send_remote_cmd, }; openocd-0.9.0/src/jtag/drivers/ftd2xx_common.h0000644000175000017500000000565212315575360016241 00000000000000/*************************************************************************** * Copyright (C) 2011 by Spencer Oliver * * * * Written by Arnim Laeuger, 2008 (from urjtag) * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _FTD2XX_COMMON_H #define _FTD2XX_COMMON_H #if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1)) #include static const char *ftd2xx_status_string(FT_STATUS status) { switch (status) { case FT_OK: return "OK"; case FT_INVALID_HANDLE: return "invalid handle"; case FT_DEVICE_NOT_FOUND: return "device not found"; case FT_DEVICE_NOT_OPENED: return "device not opened"; case FT_IO_ERROR: return "io error"; case FT_INSUFFICIENT_RESOURCES: return "insufficient resources"; case FT_INVALID_PARAMETER: return "invalid parameter"; case FT_INVALID_BAUD_RATE: return "invalid baud rate"; case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase"; case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write"; case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device"; case FT_EEPROM_READ_FAILED: return "eeprom read failed"; case FT_EEPROM_WRITE_FAILED: return "eeprom write failed"; case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed"; case FT_EEPROM_NOT_PRESENT: return "eeprom not present"; case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed"; case FT_INVALID_ARGS: return "invalid args"; case FT_NOT_SUPPORTED: return "not supported"; case FT_OTHER_ERROR: return "other error"; } return "undefined FTD2xx error"; } #endif #endif /* _FTD2XX_COMMON_H */ openocd-0.9.0/src/jtag/drivers/stlink_usb.c0000644000175000017500000013240512526201107015604 00000000000000/*************************************************************************** * Copyright (C) 2011-2012 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2012 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This code is based on https://github.com/texane/stlink * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* project specific includes */ #include #include #include #include #include #include #include #include "libusb_common.h" #define ENDPOINT_IN 0x80 #define ENDPOINT_OUT 0x00 #define STLINK_WRITE_TIMEOUT 1000 #define STLINK_READ_TIMEOUT 1000 #define STLINK_NULL_EP 0 #define STLINK_RX_EP (1|ENDPOINT_IN) #define STLINK_TX_EP (2|ENDPOINT_OUT) #define STLINK_TRACE_EP (3|ENDPOINT_IN) #define STLINK_V2_1_TX_EP (1|ENDPOINT_OUT) #define STLINK_V2_1_TRACE_EP (2|ENDPOINT_IN) #define STLINK_SG_SIZE (31) #define STLINK_DATA_SIZE (4096) #define STLINK_CMD_SIZE_V2 (16) #define STLINK_CMD_SIZE_V1 (10) #define STLINK_V1_PID (0x3744) #define STLINK_V2_PID (0x3748) #define STLINK_V2_1_PID (0x374B) /* the current implementation of the stlink limits * 8bit read/writes to max 64 bytes. */ #define STLINK_MAX_RW8 (64) /* "WAIT" responses will be retried (with exponential backoff) at * most this many times before failing to caller. */ #define MAX_WAIT_RETRIES 8 enum stlink_jtag_api_version { STLINK_JTAG_API_V1 = 1, STLINK_JTAG_API_V2, }; /** */ struct stlink_usb_version { /** */ int stlink; /** */ int jtag; /** */ int swim; /** highest supported jtag api version */ enum stlink_jtag_api_version jtag_api_max; }; /** */ struct stlink_usb_handle_s { /** */ struct jtag_libusb_device_handle *fd; /** */ struct libusb_transfer *trans; /** */ uint8_t rx_ep; /** */ uint8_t tx_ep; /** */ uint8_t trace_ep; /** */ uint8_t cmdbuf[STLINK_SG_SIZE]; /** */ uint8_t cmdidx; /** */ uint8_t direction; /** */ uint8_t databuf[STLINK_DATA_SIZE]; /** */ uint32_t max_mem_packet; /** */ enum hl_transports transport; /** */ struct stlink_usb_version version; /** */ uint16_t vid; /** */ uint16_t pid; /** this is the currently used jtag api */ enum stlink_jtag_api_version jtag_api; /** */ struct { /** whether SWO tracing is enabled or not */ bool enabled; /** trace module source clock */ uint32_t source_hz; } trace; /** reconnect is needed next time we try to query the * status */ bool reconnect_pending; }; #define STLINK_DEBUG_ERR_OK 0x80 #define STLINK_DEBUG_ERR_FAULT 0x81 #define STLINK_SWD_AP_WAIT 0x10 #define STLINK_JTAG_WRITE_ERROR 0x0c #define STLINK_JTAG_WRITE_VERIF_ERROR 0x0d #define STLINK_SWD_DP_WAIT 0x14 #define STLINK_CORE_RUNNING 0x80 #define STLINK_CORE_HALTED 0x81 #define STLINK_CORE_STAT_UNKNOWN -1 #define STLINK_GET_VERSION 0xF1 #define STLINK_DEBUG_COMMAND 0xF2 #define STLINK_DFU_COMMAND 0xF3 #define STLINK_SWIM_COMMAND 0xF4 #define STLINK_GET_CURRENT_MODE 0xF5 #define STLINK_GET_TARGET_VOLTAGE 0xF7 #define STLINK_DEV_DFU_MODE 0x00 #define STLINK_DEV_MASS_MODE 0x01 #define STLINK_DEV_DEBUG_MODE 0x02 #define STLINK_DEV_SWIM_MODE 0x03 #define STLINK_DEV_BOOTLOADER_MODE 0x04 #define STLINK_DEV_UNKNOWN_MODE -1 #define STLINK_DFU_EXIT 0x07 #define STLINK_SWIM_ENTER 0x00 #define STLINK_SWIM_EXIT 0x01 #define STLINK_DEBUG_ENTER_JTAG 0x00 #define STLINK_DEBUG_GETSTATUS 0x01 #define STLINK_DEBUG_FORCEDEBUG 0x02 #define STLINK_DEBUG_APIV1_RESETSYS 0x03 #define STLINK_DEBUG_APIV1_READALLREGS 0x04 #define STLINK_DEBUG_APIV1_READREG 0x05 #define STLINK_DEBUG_APIV1_WRITEREG 0x06 #define STLINK_DEBUG_READMEM_32BIT 0x07 #define STLINK_DEBUG_WRITEMEM_32BIT 0x08 #define STLINK_DEBUG_RUNCORE 0x09 #define STLINK_DEBUG_STEPCORE 0x0a #define STLINK_DEBUG_APIV1_SETFP 0x0b #define STLINK_DEBUG_READMEM_8BIT 0x0c #define STLINK_DEBUG_WRITEMEM_8BIT 0x0d #define STLINK_DEBUG_APIV1_CLEARFP 0x0e #define STLINK_DEBUG_APIV1_WRITEDEBUGREG 0x0f #define STLINK_DEBUG_APIV1_SETWATCHPOINT 0x10 #define STLINK_DEBUG_ENTER_JTAG 0x00 #define STLINK_DEBUG_ENTER_SWD 0xa3 #define STLINK_DEBUG_APIV1_ENTER 0x20 #define STLINK_DEBUG_EXIT 0x21 #define STLINK_DEBUG_READCOREID 0x22 #define STLINK_DEBUG_APIV2_ENTER 0x30 #define STLINK_DEBUG_APIV2_READ_IDCODES 0x31 #define STLINK_DEBUG_APIV2_RESETSYS 0x32 #define STLINK_DEBUG_APIV2_READREG 0x33 #define STLINK_DEBUG_APIV2_WRITEREG 0x34 #define STLINK_DEBUG_APIV2_WRITEDEBUGREG 0x35 #define STLINK_DEBUG_APIV2_READDEBUGREG 0x36 #define STLINK_DEBUG_APIV2_READALLREGS 0x3A #define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B #define STLINK_DEBUG_APIV2_DRIVE_NRST 0x3C #define STLINK_DEBUG_APIV2_START_TRACE_RX 0x40 #define STLINK_DEBUG_APIV2_STOP_TRACE_RX 0x41 #define STLINK_DEBUG_APIV2_GET_TRACE_NB 0x42 #define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43 #define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW 0x00 #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 #define STLINK_TRACE_SIZE 1024 #define STLINK_TRACE_MAX_HZ 2000000 #define STLINK_TRACE_MIN_VERSION 13 /** */ enum stlink_mode { STLINK_MODE_UNKNOWN = 0, STLINK_MODE_DFU, STLINK_MODE_MASS, STLINK_MODE_DEBUG_JTAG, STLINK_MODE_DEBUG_SWD, STLINK_MODE_DEBUG_SWIM }; #define REQUEST_SENSE 0x03 #define REQUEST_SENSE_LENGTH 18 static const struct { int speed; int speed_divisor; } stlink_khz_to_speed_map[] = { {4000, 0}, {1800, 1}, /* default */ {1200, 2}, {950, 3}, {480, 7}, {240, 15}, {125, 31}, {100, 40}, {50, 79}, {25, 158}, {15, 265}, {5, 798} }; static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size); /** */ static int stlink_usb_xfer_v1_get_status(void *handle) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* read status */ memset(h->cmdbuf, 0, STLINK_SG_SIZE); if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13, STLINK_READ_TIMEOUT) != 13) return ERROR_FAIL; uint32_t t1; t1 = buf_get_u32(h->cmdbuf, 0, 32); /* check for USBS */ if (t1 != 0x53425355) return ERROR_FAIL; /* * CSW status: * 0 success * 1 command failure * 2 phase error */ if (h->cmdbuf[12] != 0) return ERROR_FAIL; return ERROR_OK; } /** */ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, cmdsize, STLINK_WRITE_TIMEOUT) != cmdsize) { return ERROR_FAIL; } if (h->direction == h->tx_ep && size) { if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf, size, STLINK_WRITE_TIMEOUT) != size) { LOG_DEBUG("bulk write failed"); return ERROR_FAIL; } } else if (h->direction == h->rx_ep && size) { if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf, size, STLINK_READ_TIMEOUT) != size) { LOG_DEBUG("bulk read failed"); return ERROR_FAIL; } } return ERROR_OK; } /** */ static int stlink_usb_xfer_v1_get_sense(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 16); h->cmdbuf[h->cmdidx++] = REQUEST_SENSE; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = REQUEST_SENSE_LENGTH; res = stlink_usb_xfer_rw(handle, REQUEST_SENSE_LENGTH, h->databuf, 16); if (res != ERROR_OK) return res; if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } /** */ static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size) { int err, cmdsize = STLINK_CMD_SIZE_V2; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->version.stlink == 1) cmdsize = STLINK_SG_SIZE; err = stlink_usb_xfer_rw(handle, cmdsize, buf, size); if (err != ERROR_OK) return err; if (h->version.stlink == 1) { if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) { /* check csw status */ if (h->cmdbuf[12] == 1) { LOG_DEBUG("get sense"); if (stlink_usb_xfer_v1_get_sense(handle) != ERROR_OK) return ERROR_FAIL; } return ERROR_FAIL; } } return ERROR_OK; } /** Converts an STLINK status code held in the first byte of a response to an openocd error, logs any error/wait status as debug output. */ static int stlink_usb_error_check(void *handle) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* TODO: no error checking yet on api V1 */ if (h->jtag_api == STLINK_JTAG_API_V1) h->databuf[0] = STLINK_DEBUG_ERR_OK; switch (h->databuf[0]) { case STLINK_DEBUG_ERR_OK: return ERROR_OK; case STLINK_DEBUG_ERR_FAULT: LOG_DEBUG("SWD fault response (0x%x)", STLINK_DEBUG_ERR_FAULT); return ERROR_FAIL; case STLINK_SWD_AP_WAIT: LOG_DEBUG("wait status SWD_AP_WAIT (0x%x)", STLINK_SWD_AP_WAIT); return ERROR_WAIT; case STLINK_SWD_DP_WAIT: LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_AP_WAIT); return ERROR_WAIT; case STLINK_JTAG_WRITE_ERROR: LOG_DEBUG("Write error"); return ERROR_FAIL; case STLINK_JTAG_WRITE_VERIF_ERROR: LOG_DEBUG("Verify error"); return ERROR_FAIL; default: LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]); return ERROR_FAIL; } } /** Issue an STLINK command via USB transfer, with retries on any wait status responses. Works for commands where the STLINK_DEBUG status is returned in the first byte of the response packet. Returns an openocd result code. */ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) { int retries = 0; int res; while (1) { res = stlink_usb_xfer(handle, buf, size); if (res != ERROR_OK) return res; res = stlink_usb_error_check(handle); if (res == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { usleep((1<version.stlink >= 2); if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size, STLINK_READ_TIMEOUT) != size) { LOG_ERROR("bulk trace read failed"); return ERROR_FAIL; } return ERROR_OK; } /** */ static void stlink_usb_xfer_v1_create_cmd(void *handle, uint8_t direction, uint32_t size) { struct stlink_usb_handle_s *h = handle; /* fill the send buffer */ strcpy((char *)h->cmdbuf, "USBC"); h->cmdidx += 4; /* csw tag not used */ h->cmdidx += 4; buf_set_u32(h->cmdbuf+h->cmdidx, 0, 32, size); h->cmdidx += 4; h->cmdbuf[h->cmdidx++] = (direction == h->rx_ep ? ENDPOINT_IN : ENDPOINT_OUT); h->cmdbuf[h->cmdidx++] = 0; /* lun */ h->cmdbuf[h->cmdidx++] = STLINK_CMD_SIZE_V1; } /** */ static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size) { struct stlink_usb_handle_s *h = handle; h->direction = direction; h->cmdidx = 0; memset(h->cmdbuf, 0, STLINK_SG_SIZE); memset(h->databuf, 0, STLINK_DATA_SIZE); if (h->version.stlink == 1) stlink_usb_xfer_v1_create_cmd(handle, direction, size); } /** */ static int stlink_usb_version(void *handle) { int res; uint16_t v; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 6); h->cmdbuf[h->cmdidx++] = STLINK_GET_VERSION; res = stlink_usb_xfer(handle, h->databuf, 6); if (res != ERROR_OK) return res; v = (h->databuf[0] << 8) | h->databuf[1]; h->version.stlink = (v >> 12) & 0x0f; h->version.jtag = (v >> 6) & 0x3f; h->version.swim = v & 0x3f; h->vid = buf_get_u32(h->databuf, 16, 16); h->pid = buf_get_u32(h->databuf, 32, 16); /* set the supported jtag api version * API V2 is supported since JTAG V11 */ if (h->version.jtag >= 11) h->version.jtag_api_max = STLINK_JTAG_API_V2; else h->version.jtag_api_max = STLINK_JTAG_API_V1; LOG_INFO("STLINK v%d JTAG v%d API v%d SWIM v%d VID 0x%04X PID 0x%04X", h->version.stlink, h->version.jtag, (h->version.jtag_api_max == STLINK_JTAG_API_V1) ? 1 : 2, h->version.swim, h->vid, h->pid); return ERROR_OK; } static int stlink_usb_check_voltage(void *handle, float *target_voltage) { struct stlink_usb_handle_s *h = handle; uint32_t adc_results[2]; /* only supported by stlink/v2 and for firmware >= 13 */ if (h->version.stlink == 1 || h->version.jtag < 13) return ERROR_COMMAND_NOTFOUND; stlink_usb_init_buffer(handle, h->rx_ep, 8); h->cmdbuf[h->cmdidx++] = STLINK_GET_TARGET_VOLTAGE; int result = stlink_usb_xfer(handle, h->databuf, 8); if (result != ERROR_OK) return result; /* convert result */ adc_results[0] = le_to_h_u32(h->databuf); adc_results[1] = le_to_h_u32(h->databuf + 4); *target_voltage = 0; if (adc_results[0]) *target_voltage = 2 * ((float)adc_results[1]) * (float)(1.2 / adc_results[0]); LOG_INFO("Target voltage: %f", (double)*target_voltage); return ERROR_OK; } static int stlink_usb_set_swdclk(void *handle, uint16_t clk_divisor) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* only supported by stlink/v2 and for firmware >= 22 */ if (h->version.stlink == 1 || h->version.jtag < 22) return ERROR_COMMAND_NOTFOUND; stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_SWD_SET_FREQ; h_u16_to_le(h->cmdbuf+h->cmdidx, clk_divisor); h->cmdidx += 2; int result = stlink_cmd_allow_retry(handle, h->databuf, 2); if (result != ERROR_OK) return result; return ERROR_OK; } /** */ static int stlink_usb_current_mode(void *handle, uint8_t *mode) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; *mode = h->databuf[0]; return ERROR_OK; } /** */ static int stlink_usb_mode_enter(void *handle, enum stlink_mode type) { int rx_size = 0; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* on api V2 we are able the read the latest command * status * TODO: we need the test on api V1 too */ if (h->jtag_api == STLINK_JTAG_API_V2) rx_size = 2; stlink_usb_init_buffer(handle, h->rx_ep, rx_size); switch (type) { case STLINK_MODE_DEBUG_JTAG: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG; break; case STLINK_MODE_DEBUG_SWD: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD; break; case STLINK_MODE_DEBUG_SWIM: h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER; break; case STLINK_MODE_DFU: case STLINK_MODE_MASS: default: return ERROR_FAIL; } return stlink_cmd_allow_retry(handle, h->databuf, rx_size); } /** */ static int stlink_usb_mode_leave(void *handle, enum stlink_mode type) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0); switch (type) { case STLINK_MODE_DEBUG_JTAG: case STLINK_MODE_DEBUG_SWD: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT; break; case STLINK_MODE_DEBUG_SWIM: h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT; break; case STLINK_MODE_DFU: h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT; break; case STLINK_MODE_MASS: default: return ERROR_FAIL; } res = stlink_usb_xfer(handle, 0, 0); if (res != ERROR_OK) return res; return ERROR_OK; } static int stlink_usb_assert_srst(void *handle, int srst); static enum stlink_mode stlink_get_mode(enum hl_transports t) { switch (t) { case HL_TRANSPORT_SWD: return STLINK_MODE_DEBUG_SWD; case HL_TRANSPORT_JTAG: return STLINK_MODE_DEBUG_JTAG; case HL_TRANSPORT_SWIM: return STLINK_MODE_DEBUG_SWIM; default: return STLINK_MODE_UNKNOWN; } } /** */ static int stlink_usb_init_mode(void *handle, bool connect_under_reset) { int res; uint8_t mode; enum stlink_mode emode; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); res = stlink_usb_current_mode(handle, &mode); if (res != ERROR_OK) return res; LOG_DEBUG("MODE: 0x%02X", mode); /* try to exit current mode */ switch (mode) { case STLINK_DEV_DFU_MODE: emode = STLINK_MODE_DFU; break; case STLINK_DEV_DEBUG_MODE: emode = STLINK_MODE_DEBUG_SWD; break; case STLINK_DEV_SWIM_MODE: emode = STLINK_MODE_DEBUG_SWIM; break; case STLINK_DEV_BOOTLOADER_MODE: case STLINK_DEV_MASS_MODE: default: emode = STLINK_MODE_UNKNOWN; break; } if (emode != STLINK_MODE_UNKNOWN) { res = stlink_usb_mode_leave(handle, emode); if (res != ERROR_OK) return res; } res = stlink_usb_current_mode(handle, &mode); if (res != ERROR_OK) return res; /* we check the target voltage here as an aid to debugging connection problems. * the stlink requires the target Vdd to be connected for reliable debugging. * this cmd is supported in all modes except DFU */ if (mode != STLINK_DEV_DFU_MODE) { float target_voltage; /* check target voltage (if supported) */ res = stlink_usb_check_voltage(h, &target_voltage); if (res != ERROR_OK) { if (res != ERROR_COMMAND_NOTFOUND) LOG_ERROR("voltage check failed"); /* attempt to continue as it is not a catastrophic failure */ } else { /* check for a sensible target voltage, operating range is 1.65-5.5v * according to datasheet */ if (target_voltage < 1.5) LOG_ERROR("target voltage may be too low for reliable debugging"); } } LOG_DEBUG("MODE: 0x%02X", mode); /* set selected mode */ emode = stlink_get_mode(h->transport); if (emode == STLINK_MODE_UNKNOWN) { LOG_ERROR("selected mode (transport) not supported"); return ERROR_FAIL; } if (connect_under_reset) { res = stlink_usb_assert_srst(handle, 0); if (res != ERROR_OK) return res; } res = stlink_usb_mode_enter(handle, emode); if (res != ERROR_OK) return res; res = stlink_usb_current_mode(handle, &mode); if (res != ERROR_OK) return res; LOG_DEBUG("MODE: 0x%02X", mode); return ERROR_OK; } /** */ static int stlink_usb_idcode(void *handle, uint32_t *idcode) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 4); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID; res = stlink_usb_xfer(handle, h->databuf, 4); if (res != ERROR_OK) return res; *idcode = le_to_h_u32(h->databuf); LOG_DEBUG("IDCODE: 0x%08" PRIX32, *idcode); return ERROR_OK; } static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val) { struct stlink_usb_handle_s *h = handle; int res; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READDEBUGREG; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; res = stlink_cmd_allow_retry(handle, h->databuf, 8); if (res != ERROR_OK) return res; *val = le_to_h_u32(h->databuf + 4); return ERROR_OK; } static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEDEBUGREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u32_to_le(h->cmdbuf+h->cmdidx, val); h->cmdidx += 4; return stlink_cmd_allow_retry(handle, h->databuf, 2); } /** */ static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->trace.enabled && h->version.jtag >= STLINK_TRACE_MIN_VERSION) { int res; stlink_usb_init_buffer(handle, h->rx_ep, 10); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GET_TRACE_NB; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; size_t bytes_avail = le_to_h_u16(h->databuf); *size = bytes_avail < *size ? bytes_avail : *size - 1; if (*size > 0) { res = stlink_usb_read_trace(handle, buf, *size); if (res != ERROR_OK) return res; return ERROR_OK; } } *size = 0; return ERROR_OK; } static enum target_state stlink_usb_v2_get_status(void *handle) { int result; uint32_t status; result = stlink_usb_v2_read_debug_reg(handle, DCB_DHCSR, &status); if (result != ERROR_OK) return TARGET_UNKNOWN; if (status & S_HALT) return TARGET_HALTED; else if (status & S_RESET_ST) return TARGET_RESET; return TARGET_RUNNING; } /** */ static enum target_state stlink_usb_state(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->reconnect_pending) { LOG_INFO("Previous state query failed, trying to reconnect"); res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport)); if (res != ERROR_OK) return TARGET_UNKNOWN; h->reconnect_pending = false; } if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_v2_get_status(handle); if (res == TARGET_UNKNOWN) h->reconnect_pending = true; return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return TARGET_UNKNOWN; if (h->databuf[0] == STLINK_CORE_RUNNING) return TARGET_RUNNING; if (h->databuf[0] == STLINK_CORE_HALTED) return TARGET_HALTED; h->reconnect_pending = true; return TARGET_UNKNOWN; } static int stlink_usb_assert_srst(void *handle, int srst) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->version.stlink == 1) return ERROR_COMMAND_NOTFOUND; stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_DRIVE_NRST; h->cmdbuf[h->cmdidx++] = srst; return stlink_cmd_allow_retry(handle, h->databuf, 2); } /** */ static void stlink_usb_trace_disable(void *handle) { int res = ERROR_OK; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); assert(h->version.jtag >= STLINK_TRACE_MIN_VERSION); LOG_DEBUG("Tracing: disable"); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX; res = stlink_usb_xfer(handle, h->databuf, 2); if (res == ERROR_OK) h->trace.enabled = false; } /** */ static int stlink_usb_trace_enable(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->version.jtag >= STLINK_TRACE_MIN_VERSION) { stlink_usb_init_buffer(handle, h->rx_ep, 10); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_START_TRACE_RX; h_u16_to_le(h->cmdbuf+h->cmdidx, (uint16_t)STLINK_TRACE_SIZE); h->cmdidx += 2; h_u32_to_le(h->cmdbuf+h->cmdidx, h->trace.source_hz); h->cmdidx += 4; res = stlink_usb_xfer(handle, h->databuf, 2); if (res == ERROR_OK) { h->trace.enabled = true; LOG_DEBUG("Tracing: recording at %" PRIu32 "Hz", h->trace.source_hz); } } else { LOG_ERROR("Tracing is not supported by this version."); res = ERROR_FAIL; } return res; } /** */ static int stlink_usb_reset(void *handle) { struct stlink_usb_handle_s *h = handle; int retval; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_RESETSYS; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_RESETSYS; retval = stlink_cmd_allow_retry(handle, h->databuf, 2); if (retval != ERROR_OK) return retval; if (h->trace.enabled) { stlink_usb_trace_disable(h); return stlink_usb_trace_enable(h); } return ERROR_OK; } /** */ static int stlink_usb_run(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN); return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_RUNCORE; return stlink_cmd_allow_retry(handle, h->databuf, 2); } /** */ static int stlink_usb_halt(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_FORCEDEBUG; return stlink_cmd_allow_retry(handle, h->databuf, 2); } /** */ static int stlink_usb_step(void *handle) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V2) { /* TODO: this emulates the v1 api, it should really use a similar auto mask isr * that the cortex-m3 currently does. */ stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_MASKINTS|C_DEBUGEN); stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_MASKINTS|C_DEBUGEN); return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_STEPCORE; return stlink_cmd_allow_retry(handle, h->databuf, 2); } /** */ static int stlink_usb_read_regs(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 84); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS; res = stlink_usb_xfer(handle, h->databuf, 84); if (res != ERROR_OK) return res; return ERROR_OK; } /** */ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READREG; h->cmdbuf[h->cmdidx++] = num; if (h->jtag_api == STLINK_JTAG_API_V1) { res = stlink_usb_xfer(handle, h->databuf, 4); if (res != ERROR_OK) return res; *val = le_to_h_u32(h->databuf); return ERROR_OK; } else { res = stlink_cmd_allow_retry(handle, h->databuf, 8); if (res != ERROR_OK) return res; *val = le_to_h_u32(h->databuf + 4); return ERROR_OK; } } /** */ static int stlink_usb_write_reg(void *handle, int num, uint32_t val) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEREG; h->cmdbuf[h->cmdidx++] = num; h_u32_to_le(h->cmdbuf+h->cmdidx, val); h->cmdidx += 4; return stlink_cmd_allow_retry(handle, h->databuf, 2); } static int stlink_usb_get_rw_status(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V1) return ERROR_OK; stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return stlink_usb_error_check(h); } /** */ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; uint16_t read_len = len; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* max 8bit read/write is 64bytes */ if (len > STLINK_MAX_RW8) { LOG_DEBUG("max buffer length exceeded"); return ERROR_FAIL; } stlink_usb_init_buffer(handle, h->rx_ep, read_len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_8BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; /* we need to fix read length for single bytes */ if (read_len == 1) read_len++; res = stlink_usb_xfer(handle, h->databuf, read_len); if (res != ERROR_OK) return res; memcpy(buffer, h->databuf, len); return stlink_usb_get_rw_status(handle); } /** */ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* max 8bit read/write is 64bytes */ if (len > STLINK_MAX_RW8) { LOG_DEBUG("max buffer length exceeded"); return ERROR_FAIL; } stlink_usb_init_buffer(handle, h->tx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_8BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; return stlink_usb_get_rw_status(handle); } /** */ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* data must be a multiple of 4 and word aligned */ if (len % 4 || addr % 4) { LOG_DEBUG("Invalid data alignment"); return ERROR_TARGET_UNALIGNED_ACCESS; } stlink_usb_init_buffer(handle, h->rx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_32BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, h->databuf, len); if (res != ERROR_OK) return res; memcpy(buffer, h->databuf, len); return stlink_usb_get_rw_status(handle); } /** */ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* data must be a multiple of 4 and word aligned */ if (len % 4 || addr % 4) { LOG_DEBUG("Invalid data alignment"); return ERROR_TARGET_UNALIGNED_ACCESS; } stlink_usb_init_buffer(handle, h->tx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; return stlink_usb_get_rw_status(handle); } static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t address) { uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address)); if (max_tar_block == 0) max_tar_block = 4; return max_tar_block; } static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { int retval = ERROR_OK; uint32_t bytes_remaining; int retries = 0; struct stlink_usb_handle_s *h = handle; /* calculate byte count */ count *= size; while (count) { bytes_remaining = (size == 4) ? \ stlink_max_block_size(h->max_mem_packet, addr) : STLINK_MAX_RW8; if (count < bytes_remaining) bytes_remaining = count; /* the stlink only supports 8/32bit memory read/writes * honour 32bit, all others will be handled as 8bit access */ if (size == 4) { /* When in jtag mode the stlink uses the auto-increment functinality. * However it expects us to pass the data correctly, this includes * alignment and any page boundaries. We already do this as part of the * adi_v5 implementation, but the stlink is a hla adapter and so this * needs implementiong manually. * currently this only affects jtag mode, according to ST they do single * access in SWD mode - but this may change and so we do it for both modes */ /* we first need to check for any unaligned bytes */ if (addr % 4) { uint32_t head_bytes = 4 - (addr % 4); retval = stlink_usb_read_mem8(handle, addr, head_bytes, buffer); if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { usleep((1<max_mem_packet, addr) : STLINK_MAX_RW8; if (count < bytes_remaining) bytes_remaining = count; /* the stlink only supports 8/32bit memory read/writes * honour 32bit, all others will be handled as 8bit access */ if (size == 4) { /* When in jtag mode the stlink uses the auto-increment functinality. * However it expects us to pass the data correctly, this includes * alignment and any page boundaries. We already do this as part of the * adi_v5 implementation, but the stlink is a hla adapter and so this * needs implementiong manually. * currently this only affects jtag mode, according to ST they do single * access in SWD mode - but this may change and so we do it for both modes */ /* we first need to check for any unaligned bytes */ if (addr % 4) { uint32_t head_bytes = 4 - (addr % 4); retval = stlink_usb_write_mem8(handle, addr, head_bytes, buffer); if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { usleep((1<= 22 */ if (h && (h->version.stlink == 1 || h->version.jtag < 22)) return khz; for (i = 0; i < ARRAY_SIZE(stlink_khz_to_speed_map); i++) { if (khz == stlink_khz_to_speed_map[i].speed) { speed_index = i; break; } else { int current_diff = khz - stlink_khz_to_speed_map[i].speed; /* get abs value for comparison */ current_diff = (current_diff > 0) ? current_diff : -current_diff; if ((current_diff < speed_diff) && khz >= stlink_khz_to_speed_map[i].speed) { speed_diff = current_diff; speed_index = i; } } } bool match = true; if (speed_index == -1) { /* this will only be here if we cannot match the slow speed. * use the slowest speed we support.*/ speed_index = ARRAY_SIZE(stlink_khz_to_speed_map) - 1; match = false; } else if (i == ARRAY_SIZE(stlink_khz_to_speed_map)) match = false; if (!match && query) { LOG_INFO("Unable to match requested speed %d kHz, using %d kHz", \ khz, stlink_khz_to_speed_map[speed_index].speed); } if (h && !query) { int result = stlink_usb_set_swdclk(h, stlink_khz_to_speed_map[speed_index].speed_divisor); if (result != ERROR_OK) { LOG_ERROR("Unable to set adapter speed"); return khz; } } return stlink_khz_to_speed_map[speed_index].speed; } /** */ static int stlink_usb_close(void *handle) { struct stlink_usb_handle_s *h = handle; if (h && h->fd) jtag_libusb_close(h->fd); free(h); return ERROR_OK; } /** */ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) { int err, retry_count = 1; struct stlink_usb_handle_s *h; enum stlink_jtag_api_version api; LOG_DEBUG("stlink_usb_open"); h = calloc(1, sizeof(struct stlink_usb_handle_s)); if (h == 0) { LOG_DEBUG("malloc failed"); return ERROR_FAIL; } h->transport = param->transport; const uint16_t vids[] = { param->vid, 0 }; const uint16_t pids[] = { param->pid, 0 }; const char *serial = param->serial; LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", param->transport, param->vid, param->pid, param->serial ? param->serial : ""); /* On certain host USB configurations(e.g. MacBook Air) STLINKv2 dongle seems to have its FW in a funky state if, after plugging it in, you try to use openocd with it more then once (by launching and closing openocd). In cases like that initial attempt to read the FW info via stlink_usb_version will fail and the device has to be reset in order to become operational. */ do { if (jtag_libusb_open(vids, pids, serial, &h->fd) != ERROR_OK) { LOG_ERROR("open failed"); goto error_open; } jtag_libusb_set_configuration(h->fd, 0); if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) { LOG_DEBUG("claim interface failed"); goto error_open; } /* RX EP is common for all versions */ h->rx_ep = STLINK_RX_EP; /* wrap version for first read */ switch (param->pid) { case STLINK_V1_PID: h->version.stlink = 1; h->tx_ep = STLINK_TX_EP; h->trace_ep = STLINK_TRACE_EP; break; case STLINK_V2_1_PID: h->version.stlink = 2; h->tx_ep = STLINK_V2_1_TX_EP; h->trace_ep = STLINK_V2_1_TRACE_EP; break; default: /* fall through - we assume V2 to be the default version*/ case STLINK_V2_PID: h->version.stlink = 2; h->tx_ep = STLINK_TX_EP; h->trace_ep = STLINK_TRACE_EP; break; } /* get the device version */ err = stlink_usb_version(h); if (err == ERROR_OK) { break; } else if (h->version.stlink == 1 || retry_count == 0) { LOG_ERROR("read version failed"); goto error_open; } else { err = jtag_libusb_release_interface(h->fd, 0); if (err != ERROR_OK) { LOG_ERROR("release interface failed"); goto error_open; } err = jtag_libusb_reset_device(h->fd); if (err != ERROR_OK) { LOG_ERROR("reset device failed"); goto error_open; } jtag_libusb_close(h->fd); /* Give the device one second to settle down and reenumerate. */ usleep(1 * 1000 * 1000); retry_count--; } } while (1); /* compare usb vid/pid */ if ((param->vid != h->vid) || (param->pid != h->pid)) LOG_INFO("vid/pid are not identical: 0x%04X/0x%04X 0x%04X/0x%04X", param->vid, param->pid, h->vid, h->pid); /* check if mode is supported */ err = ERROR_OK; switch (h->transport) { case HL_TRANSPORT_SWD: case HL_TRANSPORT_JTAG: if (h->version.jtag == 0) err = ERROR_FAIL; break; case HL_TRANSPORT_SWIM: if (h->version.swim == 0) err = ERROR_FAIL; break; default: err = ERROR_FAIL; break; } if (err != ERROR_OK) { LOG_ERROR("mode (transport) not supported by device"); goto error_open; } api = h->version.jtag_api_max; LOG_INFO("using stlink api v%d", api); /* set the used jtag api, this will default to the newest supported version */ h->jtag_api = api; /* initialize the debug hardware */ err = stlink_usb_init_mode(h, param->connect_under_reset); if (err != ERROR_OK) { LOG_ERROR("init mode failed (unable to connect to the target)"); goto error_open; } /* clock speed only supported by stlink/v2 and for firmware >= 22 */ if (h->version.stlink >= 2 && h->version.jtag >= 22) { LOG_DEBUG("Supported clock speeds are:"); for (unsigned i = 0; i < ARRAY_SIZE(stlink_khz_to_speed_map); i++) LOG_DEBUG("%d kHz", stlink_khz_to_speed_map[i].speed); stlink_speed(h, param->initial_interface_speed, false); } /* get cpuid, so we can determine the max page size * start with a safe default */ h->max_mem_packet = (1 << 10); uint8_t buffer[4]; err = stlink_usb_read_mem32(h, CPUID, 4, buffer); if (err == ERROR_OK) { uint32_t cpuid = le_to_h_u32(buffer); int i = (cpuid >> 4) & 0xf; if (i == 4 || i == 3) { /* Cortex-M3/M4 has 4096 bytes autoincrement range */ h->max_mem_packet = (1 << 12); } } LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet); *fd = h; return ERROR_OK; error_open: stlink_usb_close(h); return ERROR_FAIL; } int stlink_config_trace(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { struct stlink_usb_handle_s *h = handle; if (enabled && (h->jtag_api < 2 || pin_protocol != ASYNC_UART)) { LOG_ERROR("The attached ST-LINK version doesn't support this trace mode"); return ERROR_FAIL; } if (!enabled) { stlink_usb_trace_disable(h); return ERROR_OK; } if (*trace_freq > STLINK_TRACE_MAX_HZ) { LOG_ERROR("ST-LINK doesn't support SWO frequency higher than %u", STLINK_TRACE_MAX_HZ); return ERROR_FAIL; } stlink_usb_trace_disable(h); if (!*trace_freq) *trace_freq = STLINK_TRACE_MAX_HZ; h->trace.source_hz = *trace_freq; return stlink_usb_trace_enable(h); } /** */ struct hl_layout_api_s stlink_usb_layout_api = { /** */ .open = stlink_usb_open, /** */ .close = stlink_usb_close, /** */ .idcode = stlink_usb_idcode, /** */ .state = stlink_usb_state, /** */ .reset = stlink_usb_reset, /** */ .assert_srst = stlink_usb_assert_srst, /** */ .run = stlink_usb_run, /** */ .halt = stlink_usb_halt, /** */ .step = stlink_usb_step, /** */ .read_regs = stlink_usb_read_regs, /** */ .read_reg = stlink_usb_read_reg, /** */ .write_reg = stlink_usb_write_reg, /** */ .read_mem = stlink_usb_read_mem, /** */ .write_mem = stlink_usb_write_mem, /** */ .write_debug_reg = stlink_usb_write_debug_reg, /** */ .override_target = stlink_usb_override_target, /** */ .speed = stlink_speed, /** */ .config_trace = stlink_config_trace, /** */ .poll_trace = stlink_usb_trace_read, }; openocd-0.9.0/src/jtag/drivers/ulink.c0000644000175000017500000020346412516456302014565 00000000000000/*************************************************************************** * Copyright (C) 2011-2013 by Martin Schmoelzer * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "OpenULINK/include/msgtypes.h" /** USB Vendor ID of ULINK device in unconfigured state (no firmware loaded * yet) or with OpenULINK firmware. */ #define ULINK_VID 0xC251 /** USB Product ID of ULINK device in unconfigured state (no firmware loaded * yet) or with OpenULINK firmware. */ #define ULINK_PID 0x2710 /** Address of EZ-USB CPU Control & Status register. This register can be * written by issuing a Control EP0 vendor request. */ #define CPUCS_REG 0x7F92 /** USB Control EP0 bRequest: "Firmware Load". */ #define REQUEST_FIRMWARE_LOAD 0xA0 /** Value to write into CPUCS to put EZ-USB into reset. */ #define CPU_RESET 0x01 /** Value to write into CPUCS to put EZ-USB out of reset. */ #define CPU_START 0x00 /** Base address of firmware in EZ-USB code space. */ #define FIRMWARE_ADDR 0x0000 /** USB interface number */ #define USB_INTERFACE 0 /** libusb timeout in ms */ #define USB_TIMEOUT 5000 /** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */ #define ULINK_RENUMERATION_DELAY 1500000 /** Default location of OpenULINK firmware image. */ #define ULINK_FIRMWARE_FILE PKGDATADIR "/OpenULINK/ulink_firmware.hex" /** Maximum size of a single firmware section. Entire EZ-USB code space = 8kB */ #define SECTION_BUFFERSIZE 8192 /** Tuning of OpenOCD SCAN commands split into multiple OpenULINK commands. */ #define SPLIT_SCAN_THRESHOLD 10 /** ULINK hardware type */ enum ulink_type { /** Original ULINK adapter, based on Cypress EZ-USB (AN2131): * Full JTAG support, no SWD support. */ ULINK_1, /** Newer ULINK adapter, based on NXP LPC2148. Currently unsupported. */ ULINK_2, /** Newer ULINK adapter, based on EZ-USB FX2 + FPGA. Currently unsupported. */ ULINK_PRO, /** Newer ULINK adapter, possibly based on ULINK 2. Currently unsupported. */ ULINK_ME }; enum ulink_payload_direction { PAYLOAD_DIRECTION_OUT, PAYLOAD_DIRECTION_IN }; enum ulink_delay_type { DELAY_CLOCK_TCK, DELAY_CLOCK_TMS, DELAY_SCAN_IN, DELAY_SCAN_OUT, DELAY_SCAN_IO }; /** * OpenULINK command (OpenULINK command queue element). * * For the OUT direction payload, things are quite easy: Payload is stored * in a rather small array (up to 63 bytes), the payload is always allocated * by the function generating the command and freed by ulink_clear_queue(). * * For the IN direction payload, things get a little bit more complicated: * The maximum IN payload size for a single command is 64 bytes. Assume that * a single OpenOCD command needs to scan 256 bytes. This results in the * generation of four OpenULINK commands. The function generating these * commands shall allocate an uint8_t[256] array. Each command's #payload_in * pointer shall point to the corresponding offset where IN data shall be * placed, while #payload_in_start shall point to the first element of the 256 * byte array. * - first command: #payload_in_start + 0 * - second command: #payload_in_start + 64 * - third command: #payload_in_start + 128 * - fourth command: #payload_in_start + 192 * * The last command sets #needs_postprocessing to true. */ struct ulink_cmd { uint8_t id; /**< ULINK command ID */ uint8_t *payload_out; /**< OUT direction payload data */ uint8_t payload_out_size; /**< OUT direction payload size for this command */ uint8_t *payload_in_start; /**< Pointer to first element of IN payload array */ uint8_t *payload_in; /**< Pointer where IN payload shall be stored */ uint8_t payload_in_size; /**< IN direction payload size for this command */ /** Indicates if this command needs post-processing */ bool needs_postprocessing; /** Indicates if ulink_clear_queue() should free payload_in_start */ bool free_payload_in_start; /** Pointer to corresponding OpenOCD command for post-processing */ struct jtag_command *cmd_origin; struct ulink_cmd *next; /**< Pointer to next command (linked list) */ }; /** Describes one driver instance */ struct ulink { struct libusb_context *libusb_ctx; struct libusb_device_handle *usb_device_handle; enum ulink_type type; int delay_scan_in; /**< Delay value for SCAN_IN commands */ int delay_scan_out; /**< Delay value for SCAN_OUT commands */ int delay_scan_io; /**< Delay value for SCAN_IO commands */ int delay_clock_tck; /**< Delay value for CLOCK_TMS commands */ int delay_clock_tms; /**< Delay value for CLOCK_TCK commands */ int commands_in_queue; /**< Number of commands in queue */ struct ulink_cmd *queue_start; /**< Pointer to first command in queue */ struct ulink_cmd *queue_end; /**< Pointer to last command in queue */ }; /**************************** Function Prototypes *****************************/ /* USB helper functions */ int ulink_usb_open(struct ulink **device); int ulink_usb_close(struct ulink **device); /* ULINK MCU (Cypress EZ-USB) specific functions */ int ulink_cpu_reset(struct ulink *device, unsigned char reset_bit); int ulink_load_firmware_and_renumerate(struct ulink **device, const char *filename, uint32_t delay); int ulink_load_firmware(struct ulink *device, const char *filename); int ulink_write_firmware_section(struct ulink *device, struct image *firmware_image, int section_index); /* Generic helper functions */ void ulink_print_signal_states(uint8_t input_signals, uint8_t output_signals); /* OpenULINK command generation helper functions */ int ulink_allocate_payload(struct ulink_cmd *ulink_cmd, int size, enum ulink_payload_direction direction); /* OpenULINK command queue helper functions */ int ulink_get_queue_size(struct ulink *device, enum ulink_payload_direction direction); void ulink_clear_queue(struct ulink *device); int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd); int ulink_execute_queued_commands(struct ulink *device, int timeout); #ifdef _DEBUG_JTAG_IO_ const char *ulink_cmd_id_string(uint8_t id); void ulink_print_command(struct ulink_cmd *ulink_cmd); void ulink_print_queue(struct ulink *device); #endif int ulink_append_scan_cmd(struct ulink *device, enum scan_type scan_type, int scan_size_bits, uint8_t *tdi, uint8_t *tdo_start, uint8_t *tdo, uint8_t tms_count_start, uint8_t tms_sequence_start, uint8_t tms_count_end, uint8_t tms_sequence_end, struct jtag_command *origin, bool postprocess); int ulink_append_clock_tms_cmd(struct ulink *device, uint8_t count, uint8_t sequence); int ulink_append_clock_tck_cmd(struct ulink *device, uint16_t count); int ulink_append_get_signals_cmd(struct ulink *device); int ulink_append_set_signals_cmd(struct ulink *device, uint8_t low, uint8_t high); int ulink_append_sleep_cmd(struct ulink *device, uint32_t us); int ulink_append_configure_tck_cmd(struct ulink *device, int delay_scan_in, int delay_scan_out, int delay_scan_io, int delay_tck, int delay_tms); int ulink_append_led_cmd(struct ulink *device, uint8_t led_state); int ulink_append_test_cmd(struct ulink *device); /* OpenULINK TCK frequency helper functions */ int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay); int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f); /* Interface between OpenULINK and OpenOCD */ static void ulink_set_end_state(tap_state_t endstate); int ulink_queue_statemove(struct ulink *device); int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd); int ulink_queue_tlr_reset(struct ulink *device, struct jtag_command *cmd); int ulink_queue_runtest(struct ulink *device, struct jtag_command *cmd); int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd); int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd); int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd); int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd); int ulink_post_process_scan(struct ulink_cmd *ulink_cmd); int ulink_post_process_queue(struct ulink *device); /* JTAG driver functions (registered in struct jtag_interface) */ static int ulink_execute_queue(void); static int ulink_khz(int khz, int *jtag_speed); static int ulink_speed(int speed); static int ulink_speed_div(int speed, int *khz); static int ulink_init(void); static int ulink_quit(void); /****************************** Global Variables ******************************/ struct ulink *ulink_handle; /**************************** USB helper functions ****************************/ /** * Opens the ULINK device and claims its USB interface. * * Currently, only the original ULINK is supported * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_usb_open(struct ulink **device) { ssize_t num_devices, i; bool found; libusb_device **usb_devices; struct libusb_device_descriptor usb_desc; struct libusb_device_handle *usb_device_handle; num_devices = libusb_get_device_list((*device)->libusb_ctx, &usb_devices); if (num_devices <= 0) return ERROR_FAIL; found = false; for (i = 0; i < num_devices; i++) { if (libusb_get_device_descriptor(usb_devices[i], &usb_desc) != 0) continue; else if (usb_desc.idVendor == ULINK_VID && usb_desc.idProduct == ULINK_PID) { found = true; break; } } if (!found) return ERROR_FAIL; if (libusb_open(usb_devices[i], &usb_device_handle) != 0) return ERROR_FAIL; libusb_free_device_list(usb_devices, 1); if (libusb_claim_interface(usb_device_handle, 0) != 0) return ERROR_FAIL; (*device)->usb_device_handle = usb_device_handle; (*device)->type = ULINK_1; return ERROR_OK; } /** * Releases the ULINK interface and closes the USB device handle. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_usb_close(struct ulink **device) { if (libusb_release_interface((*device)->usb_device_handle, 0) != 0) return ERROR_FAIL; libusb_close((*device)->usb_device_handle); (*device)->usb_device_handle = NULL; return ERROR_OK; } /******************* ULINK CPU (EZ-USB) specific functions ********************/ /** * Writes '0' or '1' to the CPUCS register, putting the EZ-USB CPU into reset * or out of reset. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param reset_bit 0 to put CPU into reset, 1 to put CPU out of reset. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_cpu_reset(struct ulink *device, unsigned char reset_bit) { int ret; ret = libusb_control_transfer(device->usb_device_handle, (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1, USB_TIMEOUT); /* usb_control_msg() returns the number of bytes transferred during the * DATA stage of the control transfer - must be exactly 1 in this case! */ if (ret != 1) return ERROR_FAIL; return ERROR_OK; } /** * Puts the ULINK's EZ-USB microcontroller into reset state, downloads * the firmware image, resumes the microcontroller and re-enumerates * USB devices. * * @param device pointer to struct ulink identifying ULINK driver instance. * The usb_handle member will be modified during re-enumeration. * @param filename path to the Intel HEX file containing the firmware image. * @param delay the delay to wait for the device to re-enumerate. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_load_firmware_and_renumerate(struct ulink **device, const char *filename, uint32_t delay) { int ret; /* Basic process: After downloading the firmware, the ULINK will disconnect * itself and re-connect after a short amount of time so we have to close * the handle and re-enumerate USB devices */ ret = ulink_load_firmware(*device, filename); if (ret != ERROR_OK) return ret; ret = ulink_usb_close(device); if (ret != ERROR_OK) return ret; usleep(delay); ret = ulink_usb_open(device); if (ret != ERROR_OK) return ret; return ERROR_OK; } /** * Downloads a firmware image to the ULINK's EZ-USB microcontroller * over the USB bus. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param filename an absolute or relative path to the Intel HEX file * containing the firmware image. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_load_firmware(struct ulink *device, const char *filename) { struct image ulink_firmware_image; int ret, i; ret = ulink_cpu_reset(device, CPU_RESET); if (ret != ERROR_OK) { LOG_ERROR("Could not halt ULINK CPU"); return ret; } ulink_firmware_image.base_address = 0; ulink_firmware_image.base_address_set = 0; ret = image_open(&ulink_firmware_image, filename, "ihex"); if (ret != ERROR_OK) { LOG_ERROR("Could not load firmware image"); return ret; } /* Download all sections in the image to ULINK */ for (i = 0; i < ulink_firmware_image.num_sections; i++) { ret = ulink_write_firmware_section(device, &ulink_firmware_image, i); if (ret != ERROR_OK) return ret; } image_close(&ulink_firmware_image); ret = ulink_cpu_reset(device, CPU_START); if (ret != ERROR_OK) { LOG_ERROR("Could not restart ULINK CPU"); return ret; } return ERROR_OK; } /** * Send one contiguous firmware section to the ULINK's EZ-USB microcontroller * over the USB bus. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param firmware_image pointer to the firmware image that contains the section * which should be sent to the ULINK's EZ-USB microcontroller. * @param section_index index of the section within the firmware image. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_write_firmware_section(struct ulink *device, struct image *firmware_image, int section_index) { uint16_t addr, size, bytes_remaining, chunk_size; uint8_t data[SECTION_BUFFERSIZE]; uint8_t *data_ptr = data; size_t size_read; int ret; size = (uint16_t)firmware_image->sections[section_index].size; addr = (uint16_t)firmware_image->sections[section_index].base_address; LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr, size); /* Copy section contents to local buffer */ ret = image_read_section(firmware_image, section_index, 0, size, data, &size_read); if ((ret != ERROR_OK) || (size_read != size)) { /* Propagating the return code would return '0' (misleadingly indicating * successful execution of the function) if only the size check fails. */ return ERROR_FAIL; } bytes_remaining = size; /* Send section data in chunks of up to 64 bytes to ULINK */ while (bytes_remaining > 0) { if (bytes_remaining > 64) chunk_size = 64; else chunk_size = bytes_remaining; ret = libusb_control_transfer(device->usb_device_handle, (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (unsigned char *)data_ptr, chunk_size, USB_TIMEOUT); if (ret != (int)chunk_size) { /* Abort if libusb sent less data than requested */ return ERROR_FAIL; } bytes_remaining -= chunk_size; addr += chunk_size; data_ptr += chunk_size; } return ERROR_OK; } /************************** Generic helper functions **************************/ /** * Print state of interesting signals via LOG_INFO(). * * @param input_signals input signal states as returned by CMD_GET_SIGNALS * @param output_signals output signal states as returned by CMD_GET_SIGNALS */ void ulink_print_signal_states(uint8_t input_signals, uint8_t output_signals) { LOG_INFO("ULINK signal states: TDI: %i, TDO: %i, TMS: %i, TCK: %i, TRST: %i," " SRST: %i", (output_signals & SIGNAL_TDI ? 1 : 0), (input_signals & SIGNAL_TDO ? 1 : 0), (output_signals & SIGNAL_TMS ? 1 : 0), (output_signals & SIGNAL_TCK ? 1 : 0), (output_signals & SIGNAL_TRST ? 0 : 1), /* Inverted by hardware */ (output_signals & SIGNAL_RESET ? 0 : 1)); /* Inverted by hardware */ } /**************** OpenULINK command generation helper functions ***************/ /** * Allocate and initialize space in memory for OpenULINK command payload. * * @param ulink_cmd pointer to command whose payload should be allocated. * @param size the amount of memory to allocate (bytes). * @param direction which payload to allocate. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_allocate_payload(struct ulink_cmd *ulink_cmd, int size, enum ulink_payload_direction direction) { uint8_t *payload; payload = calloc(size, sizeof(uint8_t)); if (payload == NULL) { LOG_ERROR("Could not allocate OpenULINK command payload: out of memory"); return ERROR_FAIL; } switch (direction) { case PAYLOAD_DIRECTION_OUT: if (ulink_cmd->payload_out != NULL) { LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command"); free(payload); return ERROR_FAIL; } else { ulink_cmd->payload_out = payload; ulink_cmd->payload_out_size = size; } break; case PAYLOAD_DIRECTION_IN: if (ulink_cmd->payload_in_start != NULL) { LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command"); free(payload); return ERROR_FAIL; } else { ulink_cmd->payload_in_start = payload; ulink_cmd->payload_in = payload; ulink_cmd->payload_in_size = size; /* By default, free payload_in_start in ulink_clear_queue(). Commands * that do not want this behavior (e. g. split scans) must turn it off * separately! */ ulink_cmd->free_payload_in_start = true; } break; } return ERROR_OK; } /****************** OpenULINK command queue helper functions ******************/ /** * Get the current number of bytes in the queue, including command IDs. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param direction the transfer direction for which to get byte count. * @return the number of bytes currently stored in the queue for the specified * direction. */ int ulink_get_queue_size(struct ulink *device, enum ulink_payload_direction direction) { struct ulink_cmd *current = device->queue_start; int sum = 0; while (current != NULL) { switch (direction) { case PAYLOAD_DIRECTION_OUT: sum += current->payload_out_size + 1; /* + 1 byte for Command ID */ break; case PAYLOAD_DIRECTION_IN: sum += current->payload_in_size; break; } current = current->next; } return sum; } /** * Clear the OpenULINK command queue. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ void ulink_clear_queue(struct ulink *device) { struct ulink_cmd *current = device->queue_start; struct ulink_cmd *next = NULL; while (current != NULL) { /* Save pointer to next element */ next = current->next; /* Free payloads: OUT payload can be freed immediately */ free(current->payload_out); current->payload_out = NULL; /* IN payload MUST be freed ONLY if no other commands use the * payload_in_start buffer */ if (current->free_payload_in_start == true) { free(current->payload_in_start); current->payload_in_start = NULL; current->payload_in = NULL; } /* Free queue element */ free(current); /* Proceed with next element */ current = next; } device->commands_in_queue = 0; device->queue_start = NULL; device->queue_end = NULL; } /** * Add a command to the OpenULINK command queue. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param ulink_cmd pointer to command that shall be appended to the OpenULINK * command queue. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd) { int newsize_out, newsize_in; int ret; newsize_out = ulink_get_queue_size(device, PAYLOAD_DIRECTION_OUT) + 1 + ulink_cmd->payload_out_size; newsize_in = ulink_get_queue_size(device, PAYLOAD_DIRECTION_IN) + ulink_cmd->payload_in_size; /* Check if the current command can be appended to the queue */ if ((newsize_out > 64) || (newsize_in > 64)) { /* New command does not fit. Execute all commands in queue before starting * new queue with the current command as first entry. */ ret = ulink_execute_queued_commands(device, USB_TIMEOUT); if (ret != ERROR_OK) return ret; ret = ulink_post_process_queue(device); if (ret != ERROR_OK) return ret; ulink_clear_queue(device); } if (device->queue_start == NULL) { /* Queue was empty */ device->commands_in_queue = 1; device->queue_start = ulink_cmd; device->queue_end = ulink_cmd; } else { /* There are already commands in the queue */ device->commands_in_queue++; device->queue_end->next = ulink_cmd; device->queue_end = ulink_cmd; } return ERROR_OK; } /** * Sends all queued OpenULINK commands to the ULINK for execution. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_execute_queued_commands(struct ulink *device, int timeout) { struct ulink_cmd *current; int ret, i, index_out, index_in, count_out, count_in, transferred; uint8_t buffer[64]; #ifdef _DEBUG_JTAG_IO_ ulink_print_queue(device); #endif index_out = 0; count_out = 0; count_in = 0; for (current = device->queue_start; current; current = current->next) { /* Add command to packet */ buffer[index_out] = current->id; index_out++; count_out++; for (i = 0; i < current->payload_out_size; i++) buffer[index_out + i] = current->payload_out[i]; index_out += current->payload_out_size; count_in += current->payload_in_size; count_out += current->payload_out_size; } /* Send packet to ULINK */ ret = libusb_bulk_transfer(device->usb_device_handle, (2 | LIBUSB_ENDPOINT_OUT), (unsigned char *)buffer, count_out, &transferred, timeout); if (ret != 0) return ERROR_FAIL; if (transferred != count_out) return ERROR_FAIL; /* Wait for response if commands contain IN payload data */ if (count_in > 0) { ret = libusb_bulk_transfer(device->usb_device_handle, (2 | LIBUSB_ENDPOINT_IN), (unsigned char *)buffer, 64, &transferred, timeout); if (ret != 0) return ERROR_FAIL; if (transferred != count_in) return ERROR_FAIL; /* Write back IN payload data */ index_in = 0; for (current = device->queue_start; current; current = current->next) { for (i = 0; i < current->payload_in_size; i++) { current->payload_in[i] = buffer[index_in]; index_in++; } } } return ERROR_OK; } #ifdef _DEBUG_JTAG_IO_ /** * Convert an OpenULINK command ID (\a id) to a human-readable string. * * @param id the OpenULINK command ID. * @return the corresponding human-readable string. */ const char *ulink_cmd_id_string(uint8_t id) { switch (id) { case CMD_SCAN_IN: return "CMD_SCAN_IN"; break; case CMD_SLOW_SCAN_IN: return "CMD_SLOW_SCAN_IN"; break; case CMD_SCAN_OUT: return "CMD_SCAN_OUT"; break; case CMD_SLOW_SCAN_OUT: return "CMD_SLOW_SCAN_OUT"; break; case CMD_SCAN_IO: return "CMD_SCAN_IO"; break; case CMD_SLOW_SCAN_IO: return "CMD_SLOW_SCAN_IO"; break; case CMD_CLOCK_TMS: return "CMD_CLOCK_TMS"; break; case CMD_SLOW_CLOCK_TMS: return "CMD_SLOW_CLOCK_TMS"; break; case CMD_CLOCK_TCK: return "CMD_CLOCK_TCK"; break; case CMD_SLOW_CLOCK_TCK: return "CMD_SLOW_CLOCK_TCK"; break; case CMD_SLEEP_US: return "CMD_SLEEP_US"; break; case CMD_SLEEP_MS: return "CMD_SLEEP_MS"; break; case CMD_GET_SIGNALS: return "CMD_GET_SIGNALS"; break; case CMD_SET_SIGNALS: return "CMD_SET_SIGNALS"; break; case CMD_CONFIGURE_TCK_FREQ: return "CMD_CONFIGURE_TCK_FREQ"; break; case CMD_SET_LEDS: return "CMD_SET_LEDS"; break; case CMD_TEST: return "CMD_TEST"; break; default: return "CMD_UNKNOWN"; break; } } /** * Print one OpenULINK command to stdout. * * @param ulink_cmd pointer to OpenULINK command. */ void ulink_print_command(struct ulink_cmd *ulink_cmd) { int i; printf(" %-22s | OUT size = %i, bytes = 0x", ulink_cmd_id_string(ulink_cmd->id), ulink_cmd->payload_out_size); for (i = 0; i < ulink_cmd->payload_out_size; i++) printf("%02X ", ulink_cmd->payload_out[i]); printf("\n | IN size = %i\n", ulink_cmd->payload_in_size); } /** * Print the OpenULINK command queue to stdout. * * @param device pointer to struct ulink identifying ULINK driver instance. */ void ulink_print_queue(struct ulink *device) { struct ulink_cmd *current; printf("OpenULINK command queue:\n"); for (current = device->queue_start; current; current = current->next) ulink_print_command(current); } #endif /* _DEBUG_JTAG_IO_ */ /** * Perform JTAG scan * * Creates and appends a JTAG scan command to the OpenULINK command queue. * A JTAG scan consists of three steps: * - Move to the desired SHIFT state, depending on scan type (IR/DR scan). * - Shift TDI data into the JTAG chain, optionally reading the TDO pin. * - Move to the desired end state. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param scan_type the type of the scan (IN, OUT, IO (bidirectional)). * @param scan_size_bits number of bits to shift into the JTAG chain. * @param tdi pointer to array containing TDI data. * @param tdo_start pointer to first element of array where TDO data shall be * stored. See #ulink_cmd for details. * @param tdo pointer to array where TDO data shall be stored * @param tms_count_start number of TMS state transitions to perform BEFORE * shifting data into the JTAG chain. * @param tms_sequence_start sequence of TMS state transitions that will be * performed BEFORE shifting data into the JTAG chain. * @param tms_count_end number of TMS state transitions to perform AFTER * shifting data into the JTAG chain. * @param tms_sequence_end sequence of TMS state transitions that will be * performed AFTER shifting data into the JTAG chain. * @param origin pointer to OpenOCD command that generated this scan command. * @param postprocess whether this command needs to be post-processed after * execution. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_scan_cmd(struct ulink *device, enum scan_type scan_type, int scan_size_bits, uint8_t *tdi, uint8_t *tdo_start, uint8_t *tdo, uint8_t tms_count_start, uint8_t tms_sequence_start, uint8_t tms_count_end, uint8_t tms_sequence_end, struct jtag_command *origin, bool postprocess) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret, i, scan_size_bytes; uint8_t bits_last_byte; if (cmd == NULL) return ERROR_FAIL; /* Check size of command. USB buffer can hold 64 bytes, 1 byte is command ID, * 5 bytes are setup data -> 58 remaining payload bytes for TDI data */ if (scan_size_bits > (58 * 8)) { LOG_ERROR("BUG: Tried to create CMD_SCAN_IO OpenULINK command with too" " large payload"); free(cmd); return ERROR_FAIL; } scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8); bits_last_byte = scan_size_bits % 8; if (bits_last_byte == 0) bits_last_byte = 8; /* Allocate out_payload depending on scan type */ switch (scan_type) { case SCAN_IN: if (device->delay_scan_in < 0) cmd->id = CMD_SCAN_IN; else cmd->id = CMD_SLOW_SCAN_IN; ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT); break; case SCAN_OUT: if (device->delay_scan_out < 0) cmd->id = CMD_SCAN_OUT; else cmd->id = CMD_SLOW_SCAN_OUT; ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT); break; case SCAN_IO: if (device->delay_scan_io < 0) cmd->id = CMD_SCAN_IO; else cmd->id = CMD_SLOW_SCAN_IO; ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT); break; default: LOG_ERROR("BUG: ulink_append_scan_cmd() encountered an unknown scan type"); ret = ERROR_FAIL; break; } if (ret != ERROR_OK) { free(cmd); return ret; } /* Build payload_out that is common to all scan types */ cmd->payload_out[0] = scan_size_bytes & 0xFF; cmd->payload_out[1] = bits_last_byte & 0xFF; cmd->payload_out[2] = ((tms_count_start & 0x0F) << 4) | (tms_count_end & 0x0F); cmd->payload_out[3] = tms_sequence_start; cmd->payload_out[4] = tms_sequence_end; /* Setup payload_out for types with OUT transfer */ if ((scan_type == SCAN_OUT) || (scan_type == SCAN_IO)) { for (i = 0; i < scan_size_bytes; i++) cmd->payload_out[i + 5] = tdi[i]; } /* Setup payload_in pointers for types with IN transfer */ if ((scan_type == SCAN_IN) || (scan_type == SCAN_IO)) { cmd->payload_in_start = tdo_start; cmd->payload_in = tdo; cmd->payload_in_size = scan_size_bytes; } cmd->needs_postprocessing = postprocess; cmd->cmd_origin = origin; /* For scan commands, we free payload_in_start only when the command is * the last in a series of split commands or a stand-alone command */ cmd->free_payload_in_start = postprocess; return ulink_append_queue(device, cmd); } /** * Perform TAP state transitions * * @param device pointer to struct ulink identifying ULINK driver instance. * @param count defines the number of TCK clock cycles generated (up to 8). * @param sequence defines the TMS pin levels for each state transition. The * Least-Significant Bit is read first. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_clock_tms_cmd(struct ulink *device, uint8_t count, uint8_t sequence) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; if (device->delay_clock_tms < 0) cmd->id = CMD_CLOCK_TMS; else cmd->id = CMD_SLOW_CLOCK_TMS; /* CMD_CLOCK_TMS has two OUT payload bytes and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = count; cmd->payload_out[1] = sequence; return ulink_append_queue(device, cmd); } /** * Generate a defined amount of TCK clock cycles * * All other JTAG signals are left unchanged. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param count the number of TCK clock cycles to generate. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_clock_tck_cmd(struct ulink *device, uint16_t count) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; if (device->delay_clock_tck < 0) cmd->id = CMD_CLOCK_TCK; else cmd->id = CMD_SLOW_CLOCK_TCK; /* CMD_CLOCK_TCK has two OUT payload bytes and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = count & 0xff; cmd->payload_out[1] = (count >> 8) & 0xff; return ulink_append_queue(device, cmd); } /** * Read JTAG signals. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_get_signals_cmd(struct ulink *device) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_GET_SIGNALS; cmd->needs_postprocessing = true; /* CMD_GET_SIGNALS has two IN payload bytes */ ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_IN); if (ret != ERROR_OK) { free(cmd); return ret; } return ulink_append_queue(device, cmd); } /** * Arbitrarily set JTAG output signals. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param low defines which signals will be de-asserted. Each bit corresponds * to a JTAG signal: * - SIGNAL_TDI * - SIGNAL_TMS * - SIGNAL_TCK * - SIGNAL_TRST * - SIGNAL_BRKIN * - SIGNAL_RESET * - SIGNAL_OCDSE * @param high defines which signals will be asserted. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_set_signals_cmd(struct ulink *device, uint8_t low, uint8_t high) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_SET_SIGNALS; /* CMD_SET_SIGNALS has two OUT payload bytes and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = low; cmd->payload_out[1] = high; return ulink_append_queue(device, cmd); } /** * Sleep for a pre-defined number of microseconds * * @param device pointer to struct ulink identifying ULINK driver instance. * @param us the number microseconds to sleep. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_sleep_cmd(struct ulink *device, uint32_t us) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_SLEEP_US; /* CMD_SLEEP_US has two OUT payload bytes and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = us & 0x00ff; cmd->payload_out[1] = (us >> 8) & 0x00ff; return ulink_append_queue(device, cmd); } /** * Set TCK delay counters * * @param device pointer to struct ulink identifying ULINK driver instance. * @param delay_scan_in delay count top value in jtag_slow_scan_in() function. * @param delay_scan_out delay count top value in jtag_slow_scan_out() function. * @param delay_scan_io delay count top value in jtag_slow_scan_io() function. * @param delay_tck delay count top value in jtag_clock_tck() function. * @param delay_tms delay count top value in jtag_slow_clock_tms() function. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_configure_tck_cmd(struct ulink *device, int delay_scan_in, int delay_scan_out, int delay_scan_io, int delay_tck, int delay_tms) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_CONFIGURE_TCK_FREQ; /* CMD_CONFIGURE_TCK_FREQ has five OUT payload bytes and zero * IN payload bytes */ ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } if (delay_scan_in < 0) cmd->payload_out[0] = 0; else cmd->payload_out[0] = (uint8_t)delay_scan_in; if (delay_scan_out < 0) cmd->payload_out[1] = 0; else cmd->payload_out[1] = (uint8_t)delay_scan_out; if (delay_scan_io < 0) cmd->payload_out[2] = 0; else cmd->payload_out[2] = (uint8_t)delay_scan_io; if (delay_tck < 0) cmd->payload_out[3] = 0; else cmd->payload_out[3] = (uint8_t)delay_tck; if (delay_tms < 0) cmd->payload_out[4] = 0; else cmd->payload_out[4] = (uint8_t)delay_tms; return ulink_append_queue(device, cmd); } /** * Turn on/off ULINK LEDs. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param led_state which LED(s) to turn on or off. The following bits * influence the LEDS: * - Bit 0: Turn COM LED on * - Bit 1: Turn RUN LED on * - Bit 2: Turn COM LED off * - Bit 3: Turn RUN LED off * If both the on-bit and the off-bit for the same LED is set, the LED is * turned off. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_led_cmd(struct ulink *device, uint8_t led_state) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_SET_LEDS; /* CMD_SET_LEDS has one OUT payload byte and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 1, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = led_state; return ulink_append_queue(device, cmd); } /** * Test command. Used to check if the ULINK device is ready to accept new * commands. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_append_test_cmd(struct ulink *device) { struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd)); int ret; if (cmd == NULL) return ERROR_FAIL; cmd->id = CMD_TEST; /* CMD_TEST has one OUT payload byte and zero IN payload bytes */ ret = ulink_allocate_payload(cmd, 1, PAYLOAD_DIRECTION_OUT); if (ret != ERROR_OK) { free(cmd); return ret; } cmd->payload_out[0] = 0xAA; return ulink_append_queue(device, cmd); } /****************** OpenULINK TCK frequency helper functions ******************/ /** * Calculate delay values for a given TCK frequency. * * The OpenULINK firmware uses five different speed values for different * commands. These speed values are calculated in these functions. * * The five different commands which support variable TCK frequency are * implemented twice in the firmware: * 1. Maximum possible frequency without any artificial delay * 2. Variable frequency with artificial linear delay loop * * To set the ULINK to maximum frequency, it is only neccessary to use the * corresponding command IDs. To set the ULINK to a lower frequency, the * delay loop top values have to be calculated first. Then, a * CMD_CONFIGURE_TCK_FREQ command needs to be sent to the ULINK device. * * The delay values are described by linear equations: * t = k * x + d * (t = period, k = constant, x = delay value, d = constant) * * Thus, the delay can be calculated as in the following equation: * x = (t - d) / k * * The constants in these equations have been determined and validated by * measuring the frequency resulting from different delay values. * * @param type for which command to calculate the delay value. * @param f TCK frequency for which to calculate the delay value in Hz. * @param delay where to store resulting delay value. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay) { float t, x, x_ceil; /* Calculate period of requested TCK frequency */ t = 1.0 / (float)(f); switch (type) { case DELAY_CLOCK_TCK: x = (t - (float)(6E-6)) / (float)(4E-6); break; case DELAY_CLOCK_TMS: x = (t - (float)(8.5E-6)) / (float)(4E-6); break; case DELAY_SCAN_IN: x = (t - (float)(8.8308E-6)) / (float)(4E-6); break; case DELAY_SCAN_OUT: x = (t - (float)(1.0527E-5)) / (float)(4E-6); break; case DELAY_SCAN_IO: x = (t - (float)(1.3132E-5)) / (float)(4E-6); break; default: return ERROR_FAIL; break; } /* Check if the delay value is negative. This happens when a frequency is * requested that is too high for the delay loop implementation. In this * case, set delay value to zero. */ if (x < 0) x = 0; /* We need to convert the exact delay value to an integer. Therefore, we * round the exact value UP to ensure that the resulting frequency is NOT * higher than the requested frequency. */ x_ceil = ceilf(x); /* Check if the value is within limits */ if (x_ceil > 255) return ERROR_FAIL; *delay = (int)x_ceil; return ERROR_OK; } /** * Calculate frequency for a given delay value. * * Similar to the #ulink_calculate_delay function, this function calculates the * TCK frequency for a given delay value by using linear equations of the form: * t = k * x + d * (t = period, k = constant, x = delay value, d = constant) * * @param type for which command to calculate the delay value. * @param delay delay value for which to calculate the resulting TCK frequency. * @param f where to store the resulting TCK frequency. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f) { float t, f_float, f_rounded; if (delay > 255) return ERROR_FAIL; switch (type) { case DELAY_CLOCK_TCK: if (delay < 0) t = (float)(2.666E-6); else t = (float)(4E-6) * (float)(delay) + (float)(6E-6); break; case DELAY_CLOCK_TMS: if (delay < 0) t = (float)(5.666E-6); else t = (float)(4E-6) * (float)(delay) + (float)(8.5E-6); break; case DELAY_SCAN_IN: if (delay < 0) t = (float)(5.5E-6); else t = (float)(4E-6) * (float)(delay) + (float)(8.8308E-6); break; case DELAY_SCAN_OUT: if (delay < 0) t = (float)(7.0E-6); else t = (float)(4E-6) * (float)(delay) + (float)(1.0527E-5); break; case DELAY_SCAN_IO: if (delay < 0) t = (float)(9.926E-6); else t = (float)(4E-6) * (float)(delay) + (float)(1.3132E-5); break; default: return ERROR_FAIL; break; } f_float = 1.0 / t; f_rounded = roundf(f_float); *f = (long)f_rounded; return ERROR_OK; } /******************* Interface between OpenULINK and OpenOCD ******************/ /** * Sets the end state follower (see interface.h) if \a endstate is a stable * state. * * @param endstate the state the end state follower should be set to. */ static void ulink_set_end_state(tap_state_t endstate) { if (tap_is_state_stable(endstate)) tap_set_end_state(endstate); else { LOG_ERROR("BUG: %s is not a valid end state", tap_state_name(endstate)); exit(EXIT_FAILURE); } } /** * Move from the current TAP state to the current TAP end state. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_statemove(struct ulink *device) { uint8_t tms_sequence, tms_count; int ret; if (tap_get_state() == tap_get_end_state()) { /* Do nothing if we are already there */ return ERROR_OK; } tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state()); tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); ret = ulink_append_clock_tms_cmd(device, tms_count, tms_sequence); if (ret == ERROR_OK) tap_set_state(tap_get_end_state()); return ret; } /** * Perform a scan operation on a JTAG register. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd) { uint32_t scan_size_bits, scan_size_bytes, bits_last_scan; uint32_t scans_max_payload, bytecount; uint8_t *tdi_buffer_start = NULL, *tdi_buffer = NULL; uint8_t *tdo_buffer_start = NULL, *tdo_buffer = NULL; uint8_t first_tms_count, first_tms_sequence; uint8_t last_tms_count, last_tms_sequence; uint8_t tms_count_pause, tms_sequence_pause; uint8_t tms_count_resume, tms_sequence_resume; uint8_t tms_count_start, tms_sequence_start; uint8_t tms_count_end, tms_sequence_end; enum scan_type type; int ret; /* Determine scan size */ scan_size_bits = jtag_scan_size(cmd->cmd.scan); scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8); /* Determine scan type (IN/OUT/IO) */ type = jtag_scan_type(cmd->cmd.scan); /* Determine number of scan commands with maximum payload */ scans_max_payload = scan_size_bytes / 58; /* Determine size of last shift command */ bits_last_scan = scan_size_bits - (scans_max_payload * 58 * 8); /* Allocate TDO buffer if required */ if ((type == SCAN_IN) || (type == SCAN_IO)) { tdo_buffer_start = calloc(sizeof(uint8_t), scan_size_bytes); if (tdo_buffer_start == NULL) return ERROR_FAIL; tdo_buffer = tdo_buffer_start; } /* Fill TDI buffer if required */ if ((type == SCAN_OUT) || (type == SCAN_IO)) { jtag_build_buffer(cmd->cmd.scan, &tdi_buffer_start); tdi_buffer = tdi_buffer_start; } /* Get TAP state transitions */ if (cmd->cmd.scan->ir_scan) { ulink_set_end_state(TAP_IRSHIFT); first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state()); tap_set_state(TAP_IRSHIFT); tap_set_end_state(cmd->cmd.scan->end_state); last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state()); /* TAP state transitions for split scans */ tms_count_pause = tap_get_tms_path_len(TAP_IRSHIFT, TAP_IRPAUSE); tms_sequence_pause = tap_get_tms_path(TAP_IRSHIFT, TAP_IRPAUSE); tms_count_resume = tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRSHIFT); tms_sequence_resume = tap_get_tms_path(TAP_IRPAUSE, TAP_IRSHIFT); } else { ulink_set_end_state(TAP_DRSHIFT); first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state()); tap_set_state(TAP_DRSHIFT); tap_set_end_state(cmd->cmd.scan->end_state); last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state()); /* TAP state transitions for split scans */ tms_count_pause = tap_get_tms_path_len(TAP_DRSHIFT, TAP_DRPAUSE); tms_sequence_pause = tap_get_tms_path(TAP_DRSHIFT, TAP_DRPAUSE); tms_count_resume = tap_get_tms_path_len(TAP_DRPAUSE, TAP_DRSHIFT); tms_sequence_resume = tap_get_tms_path(TAP_DRPAUSE, TAP_DRSHIFT); } /* Generate scan commands */ bytecount = scan_size_bytes; while (bytecount > 0) { if (bytecount == scan_size_bytes) { /* This is the first scan */ tms_count_start = first_tms_count; tms_sequence_start = first_tms_sequence; } else { /* Resume from previous scan */ tms_count_start = tms_count_resume; tms_sequence_start = tms_sequence_resume; } if (bytecount > 58) { /* Full scan, at least one scan will follow */ tms_count_end = tms_count_pause; tms_sequence_end = tms_sequence_pause; ret = ulink_append_scan_cmd(device, type, 58 * 8, tdi_buffer, tdo_buffer_start, tdo_buffer, tms_count_start, tms_sequence_start, tms_count_end, tms_sequence_end, cmd, false); bytecount -= 58; /* Update TDI and TDO buffer pointers */ if (tdi_buffer_start != NULL) tdi_buffer += 58; if (tdo_buffer_start != NULL) tdo_buffer += 58; } else if (bytecount == 58) { /* Full scan, no further scans */ tms_count_end = last_tms_count; tms_sequence_end = last_tms_sequence; ret = ulink_append_scan_cmd(device, type, 58 * 8, tdi_buffer, tdo_buffer_start, tdo_buffer, tms_count_start, tms_sequence_start, tms_count_end, tms_sequence_end, cmd, true); bytecount = 0; } else {/* Scan with less than maximum payload, no further scans */ tms_count_end = last_tms_count; tms_sequence_end = last_tms_sequence; ret = ulink_append_scan_cmd(device, type, bits_last_scan, tdi_buffer, tdo_buffer_start, tdo_buffer, tms_count_start, tms_sequence_start, tms_count_end, tms_sequence_end, cmd, true); bytecount = 0; } if (ret != ERROR_OK) { free(tdi_buffer_start); return ret; } } free(tdi_buffer_start); /* Set current state to the end state requested by the command */ tap_set_state(cmd->cmd.scan->end_state); return ERROR_OK; } /** * Move the TAP into the Test Logic Reset state. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_tlr_reset(struct ulink *device, struct jtag_command *cmd) { int ret; ret = ulink_append_clock_tms_cmd(device, 5, 0xff); if (ret == ERROR_OK) tap_set_state(TAP_RESET); return ret; } /** * Run Test. * * Generate TCK clock cycles while remaining * in the Run-Test/Idle state. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_runtest(struct ulink *device, struct jtag_command *cmd) { int ret; /* Only perform statemove if the TAP currently isn't in the TAP_IDLE state */ if (tap_get_state() != TAP_IDLE) { ulink_set_end_state(TAP_IDLE); ulink_queue_statemove(device); } /* Generate the clock cycles */ ret = ulink_append_clock_tck_cmd(device, cmd->cmd.runtest->num_cycles); if (ret != ERROR_OK) return ret; /* Move to end state specified in command */ if (cmd->cmd.runtest->end_state != tap_get_state()) { tap_set_end_state(cmd->cmd.runtest->end_state); ulink_queue_statemove(device); } return ERROR_OK; } /** * Execute a JTAG_RESET command * * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd) { uint8_t low = 0, high = 0; if (cmd->cmd.reset->trst) { tap_set_state(TAP_RESET); high |= SIGNAL_TRST; } else low |= SIGNAL_TRST; if (cmd->cmd.reset->srst) high |= SIGNAL_RESET; else low |= SIGNAL_RESET; return ulink_append_set_signals_cmd(device, low, high); } /** * Move to one TAP state or several states in succession. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) { int ret, i, num_states, batch_size, state_count; tap_state_t *path; uint8_t tms_sequence; num_states = cmd->cmd.pathmove->num_states; path = cmd->cmd.pathmove->path; state_count = 0; while (num_states > 0) { tms_sequence = 0; /* Determine batch size */ if (num_states >= 8) batch_size = 8; else batch_size = num_states; for (i = 0; i < batch_size; i++) { if (tap_state_transition(tap_get_state(), false) == path[state_count]) { /* Append '0' transition: clear bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x0); } else if (tap_state_transition(tap_get_state(), true) == path[state_count]) { /* Append '1' transition: set bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x1); } else { /* Invalid state transition */ LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition", tap_state_name(tap_get_state()), tap_state_name(path[state_count])); return ERROR_FAIL; } tap_set_state(path[state_count]); state_count++; num_states--; } /* Append CLOCK_TMS command to OpenULINK command queue */ LOG_INFO( "pathmove batch: count = %i, sequence = 0x%x", batch_size, tms_sequence); ret = ulink_append_clock_tms_cmd(ulink_handle, batch_size, tms_sequence); if (ret != ERROR_OK) return ret; } return ERROR_OK; } /** * Sleep for a specific amount of time. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd) { /* IMPORTANT! Due to the time offset in command execution introduced by * command queueing, this needs to be implemented in the ULINK device */ return ulink_append_sleep_cmd(device, cmd->cmd.sleep->us); } /** * Generate TCK cycles while remaining in a stable state. * * @param device pointer to struct ulink identifying ULINK driver instance. * @param cmd pointer to the command that shall be executed. */ int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd) { int ret; unsigned num_cycles; if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("JTAG_STABLECLOCKS: state not stable"); return ERROR_FAIL; } num_cycles = cmd->cmd.stableclocks->num_cycles; /* TMS stays either high (Test Logic Reset state) or low (all other states) */ if (tap_get_state() == TAP_RESET) ret = ulink_append_set_signals_cmd(device, 0, SIGNAL_TMS); else ret = ulink_append_set_signals_cmd(device, SIGNAL_TMS, 0); if (ret != ERROR_OK) return ret; while (num_cycles > 0) { if (num_cycles > 0xFFFF) { /* OpenULINK CMD_CLOCK_TCK can generate up to 0xFFFF (uint16_t) cycles */ ret = ulink_append_clock_tck_cmd(device, 0xFFFF); num_cycles -= 0xFFFF; } else { ret = ulink_append_clock_tck_cmd(device, num_cycles); num_cycles = 0; } if (ret != ERROR_OK) return ret; } return ERROR_OK; } /** * Post-process JTAG_SCAN command * * @param ulink_cmd pointer to OpenULINK command that shall be processed. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_post_process_scan(struct ulink_cmd *ulink_cmd) { struct jtag_command *cmd = ulink_cmd->cmd_origin; int ret; switch (jtag_scan_type(cmd->cmd.scan)) { case SCAN_IN: case SCAN_IO: ret = jtag_read_buffer(ulink_cmd->payload_in_start, cmd->cmd.scan); break; case SCAN_OUT: /* Nothing to do for OUT scans */ ret = ERROR_OK; break; default: LOG_ERROR("BUG: ulink_post_process_scan() encountered an unknown" " JTAG scan type"); ret = ERROR_FAIL; break; } return ret; } /** * Perform post-processing of commands after OpenULINK queue has been executed. * * @param device pointer to struct ulink identifying ULINK driver instance. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ int ulink_post_process_queue(struct ulink *device) { struct ulink_cmd *current; struct jtag_command *openocd_cmd; int ret; current = device->queue_start; while (current != NULL) { openocd_cmd = current->cmd_origin; /* Check if a corresponding OpenOCD command is stored for this * OpenULINK command */ if ((current->needs_postprocessing == true) && (openocd_cmd != NULL)) { switch (openocd_cmd->type) { case JTAG_SCAN: ret = ulink_post_process_scan(current); break; case JTAG_TLR_RESET: case JTAG_RUNTEST: case JTAG_RESET: case JTAG_PATHMOVE: case JTAG_SLEEP: case JTAG_STABLECLOCKS: /* Nothing to do for these commands */ ret = ERROR_OK; break; default: ret = ERROR_FAIL; LOG_ERROR("BUG: ulink_post_process_queue() encountered unknown JTAG " "command type"); break; } if (ret != ERROR_OK) return ret; } current = current->next; } return ERROR_OK; } /**************************** JTAG driver functions ***************************/ /** * Executes the JTAG Command Queue. * * This is done in three stages: First, all OpenOCD commands are processed into * queued OpenULINK commands. Next, the OpenULINK command queue is sent to the * ULINK device and data received from the ULINK device is cached. Finally, * the post-processing function writes back data to the corresponding OpenOCD * commands. * * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; int ret; while (cmd) { switch (cmd->type) { case JTAG_SCAN: ret = ulink_queue_scan(ulink_handle, cmd); break; case JTAG_TLR_RESET: ret = ulink_queue_tlr_reset(ulink_handle, cmd); break; case JTAG_RUNTEST: ret = ulink_queue_runtest(ulink_handle, cmd); break; case JTAG_RESET: ret = ulink_queue_reset(ulink_handle, cmd); break; case JTAG_PATHMOVE: ret = ulink_queue_pathmove(ulink_handle, cmd); break; case JTAG_SLEEP: ret = ulink_queue_sleep(ulink_handle, cmd); break; case JTAG_STABLECLOCKS: ret = ulink_queue_stableclocks(ulink_handle, cmd); break; default: ret = ERROR_FAIL; LOG_ERROR("BUG: encountered unknown JTAG command type"); break; } if (ret != ERROR_OK) return ret; cmd = cmd->next; } if (ulink_handle->commands_in_queue > 0) { ret = ulink_execute_queued_commands(ulink_handle, USB_TIMEOUT); if (ret != ERROR_OK) return ret; ret = ulink_post_process_queue(ulink_handle); if (ret != ERROR_OK) return ret; ulink_clear_queue(ulink_handle); } return ERROR_OK; } /** * Set the TCK frequency of the ULINK adapter. * * @param khz desired JTAG TCK frequency. * @param jtag_speed where to store corresponding adapter-specific speed value. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_khz(int khz, int *jtag_speed) { int ret; if (khz == 0) { LOG_ERROR("RCLK not supported"); return ERROR_FAIL; } /* CLOCK_TCK commands are decoupled from others. Therefore, the frequency * setting can be done independently from all other commands. */ if (khz >= 375) ulink_handle->delay_clock_tck = -1; else { ret = ulink_calculate_delay(DELAY_CLOCK_TCK, khz * 1000, &ulink_handle->delay_clock_tck); if (ret != ERROR_OK) return ret; } /* SCAN_{IN,OUT,IO} commands invoke CLOCK_TMS commands. Therefore, if the * requested frequency goes below the maximum frequency for SLOW_CLOCK_TMS * commands, all SCAN commands MUST also use the variable frequency * implementation! */ if (khz >= 176) { ulink_handle->delay_clock_tms = -1; ulink_handle->delay_scan_in = -1; ulink_handle->delay_scan_out = -1; ulink_handle->delay_scan_io = -1; } else { ret = ulink_calculate_delay(DELAY_CLOCK_TMS, khz * 1000, &ulink_handle->delay_clock_tms); if (ret != ERROR_OK) return ret; ret = ulink_calculate_delay(DELAY_SCAN_IN, khz * 1000, &ulink_handle->delay_scan_in); if (ret != ERROR_OK) return ret; ret = ulink_calculate_delay(DELAY_SCAN_OUT, khz * 1000, &ulink_handle->delay_scan_out); if (ret != ERROR_OK) return ret; ret = ulink_calculate_delay(DELAY_SCAN_IO, khz * 1000, &ulink_handle->delay_scan_io); if (ret != ERROR_OK) return ret; } #ifdef _DEBUG_JTAG_IO_ long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io; ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck, &f_tck); ulink_calculate_frequency(DELAY_CLOCK_TMS, ulink_handle->delay_clock_tms, &f_tms); ulink_calculate_frequency(DELAY_SCAN_IN, ulink_handle->delay_scan_in, &f_scan_in); ulink_calculate_frequency(DELAY_SCAN_OUT, ulink_handle->delay_scan_out, &f_scan_out); ulink_calculate_frequency(DELAY_SCAN_IO, ulink_handle->delay_scan_io, &f_scan_io); DEBUG_JTAG_IO("ULINK TCK setup: delay_tck = %i (%li Hz),", ulink_handle->delay_clock_tck, f_tck); DEBUG_JTAG_IO(" delay_tms = %i (%li Hz),", ulink_handle->delay_clock_tms, f_tms); DEBUG_JTAG_IO(" delay_scan_in = %i (%li Hz),", ulink_handle->delay_scan_in, f_scan_in); DEBUG_JTAG_IO(" delay_scan_out = %i (%li Hz),", ulink_handle->delay_scan_out, f_scan_out); DEBUG_JTAG_IO(" delay_scan_io = %i (%li Hz),", ulink_handle->delay_scan_io, f_scan_io); #endif /* Configure the ULINK device with the new delay values */ ret = ulink_append_configure_tck_cmd(ulink_handle, ulink_handle->delay_scan_in, ulink_handle->delay_scan_out, ulink_handle->delay_scan_io, ulink_handle->delay_clock_tck, ulink_handle->delay_clock_tms); if (ret != ERROR_OK) return ret; *jtag_speed = khz; return ERROR_OK; } /** * Set the TCK frequency of the ULINK adapter. * * Because of the way the TCK frequency is set up in the OpenULINK firmware, * there are five different speed settings. To simplify things, the * adapter-specific speed setting value is identical to the TCK frequency in * khz. * * @param speed desired adapter-specific speed value. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_speed(int speed) { int dummy; return ulink_khz(speed, &dummy); } /** * Convert adapter-specific speed value to corresponding TCK frequency in kHz. * * Because of the way the TCK frequency is set up in the OpenULINK firmware, * there are five different speed settings. To simplify things, the * adapter-specific speed setting value is identical to the TCK frequency in * khz. * * @param speed adapter-specific speed value. * @param khz where to store corresponding TCK frequency in kHz. * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } /** * Initiates the firmware download to the ULINK adapter and prepares * the USB handle. * * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_init(void) { int ret, transferred; char str_manufacturer[20]; bool download_firmware = false; unsigned char *dummy; uint8_t input_signals, output_signals; ulink_handle = calloc(1, sizeof(struct ulink)); if (ulink_handle == NULL) return ERROR_FAIL; libusb_init(&ulink_handle->libusb_ctx); ret = ulink_usb_open(&ulink_handle); if (ret != ERROR_OK) { LOG_ERROR("Could not open ULINK device"); free(ulink_handle); ulink_handle = NULL; return ret; } /* Get String Descriptor to determine if firmware needs to be loaded */ ret = libusb_get_string_descriptor_ascii(ulink_handle->usb_device_handle, 1, (unsigned char *)str_manufacturer, 20); if (ret < 0) { /* Could not get descriptor -> Unconfigured or original Keil firmware */ download_firmware = true; } else { /* We got a String Descriptor, check if it is the correct one */ if (strncmp(str_manufacturer, "OpenULINK", 9) != 0) download_firmware = true; } if (download_firmware == true) { LOG_INFO("Loading OpenULINK firmware. This is reversible by power-cycling" " ULINK device."); ret = ulink_load_firmware_and_renumerate(&ulink_handle, ULINK_FIRMWARE_FILE, ULINK_RENUMERATION_DELAY); if (ret != ERROR_OK) { LOG_ERROR("Could not download firmware and re-numerate ULINK"); free(ulink_handle); ulink_handle = NULL; return ret; } } else LOG_INFO("ULINK device is already running OpenULINK firmware"); /* Initialize OpenULINK command queue */ ulink_clear_queue(ulink_handle); /* Issue one test command with short timeout */ ret = ulink_append_test_cmd(ulink_handle); if (ret != ERROR_OK) return ret; ret = ulink_execute_queued_commands(ulink_handle, 200); if (ret != ERROR_OK) { /* Sending test command failed. The ULINK device may be forever waiting for * the host to fetch an USB Bulk IN packet (e. g. OpenOCD crashed or was * shut down by the user via Ctrl-C. Try to retrieve this Bulk IN packet. */ dummy = calloc(64, sizeof(uint8_t)); ret = libusb_bulk_transfer(ulink_handle->usb_device_handle, (2 | LIBUSB_ENDPOINT_IN), dummy, 64, &transferred, 200); free(dummy); if (ret != 0 || transferred == 0) { /* Bulk IN transfer failed -> unrecoverable error condition */ LOG_ERROR("Cannot communicate with ULINK device. Disconnect ULINK from " "the USB port and re-connect, then re-run OpenOCD"); free(ulink_handle); ulink_handle = NULL; return ERROR_FAIL; } #ifdef _DEBUG_USB_COMMS_ else { /* Successfully received Bulk IN packet -> continue */ LOG_INFO("Recovered from lost Bulk IN packet"); } #endif } ulink_clear_queue(ulink_handle); ulink_append_get_signals_cmd(ulink_handle); ulink_execute_queued_commands(ulink_handle, 200); /* Post-process the single CMD_GET_SIGNALS command */ input_signals = ulink_handle->queue_start->payload_in[0]; output_signals = ulink_handle->queue_start->payload_in[1]; ulink_print_signal_states(input_signals, output_signals); ulink_clear_queue(ulink_handle); return ERROR_OK; } /** * Closes the USB handle for the ULINK device. * * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ static int ulink_quit(void) { int ret; ret = ulink_usb_close(&ulink_handle); free(ulink_handle); return ret; } /** * Set a custom path to ULINK firmware image and force downloading to ULINK. */ COMMAND_HANDLER(ulink_download_firmware_handler) { int ret; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; LOG_INFO("Downloading ULINK firmware image %s", CMD_ARGV[0]); /* Download firmware image in CMD_ARGV[0] */ ret = ulink_load_firmware_and_renumerate(&ulink_handle, CMD_ARGV[0], ULINK_RENUMERATION_DELAY); return ret; } /*************************** Command Registration **************************/ static const struct command_registration ulink_command_handlers[] = { { .name = "ulink_download_firmware", .handler = &ulink_download_firmware_handler, .mode = COMMAND_EXEC, .help = "download firmware image to ULINK device", .usage = "path/to/ulink_firmware.hex", }, COMMAND_REGISTRATION_DONE, }; struct jtag_interface ulink_interface = { .name = "ulink", .commands = ulink_command_handlers, .transports = jtag_only, .execute_queue = ulink_execute_queue, .khz = ulink_khz, .speed = ulink_speed, .speed_div = ulink_speed_div, .init = ulink_init, .quit = ulink_quit }; openocd-0.9.0/src/jtag/drivers/buspirate.c0000644000175000017500000007234112516456302015437 00000000000000/*************************************************************************** * Copyright (C) 2010 by Michal Demin * * based on usbprog.c and arm-jtag-ew.c * * Several fixes by R. Diez in 2013. * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #undef DEBUG_SERIAL /*#define DEBUG_SERIAL */ static int buspirate_execute_queue(void); static int buspirate_init(void); static int buspirate_quit(void); static void buspirate_end_state(tap_state_t state); static void buspirate_state_move(void); static void buspirate_path_move(int num_states, tap_state_t *path); static void buspirate_runtest(int num_cycles); static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void buspirate_stableclocks(int num_cycles); #define CMD_UNKNOWN 0x00 #define CMD_PORT_MODE 0x01 #define CMD_FEATURE 0x02 #define CMD_READ_ADCS 0x03 /*#define CMD_TAP_SHIFT 0x04 // old protocol */ #define CMD_TAP_SHIFT 0x05 #define CMD_ENTER_OOCD 0x06 #define CMD_UART_SPEED 0x07 #define CMD_JTAG_SPEED 0x08 /* Not all OSes have this speed defined */ #if !defined(B1000000) #define B1000000 0010010 #endif enum { MODE_HIZ = 0, MODE_JTAG = 1, /* push-pull outputs */ MODE_JTAG_OD = 2, /* open-drain outputs */ }; enum { FEATURE_LED = 0x01, FEATURE_VREG = 0x02, FEATURE_TRST = 0x04, FEATURE_SRST = 0x08, FEATURE_PULLUP = 0x10 }; enum { ACTION_DISABLE = 0, ACTION_ENABLE = 1 }; enum { SERIAL_NORMAL = 0, SERIAL_FAST = 1 }; static const cc_t SHORT_TIMEOUT = 1; /* Must be at least 1. */ static const cc_t NORMAL_TIMEOUT = 10; static int buspirate_fd = -1; static int buspirate_pinmode = MODE_JTAG_OD; static int buspirate_baudrate = SERIAL_NORMAL; static int buspirate_vreg; static int buspirate_pullup; static char *buspirate_port; static enum tap_state last_tap_state = TAP_RESET; /* TAP interface */ static void buspirate_tap_init(void); static int buspirate_tap_execute(void); static void buspirate_tap_append(int tms, int tdi); static void buspirate_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); static void buspirate_tap_make_space(int scan, int bits); static void buspirate_reset(int trst, int srst); /* low level interface */ static void buspirate_jtag_reset(int); static void buspirate_jtag_enable(int); static unsigned char buspirate_jtag_command(int, char *, int); static void buspirate_jtag_set_speed(int, char); static void buspirate_jtag_set_mode(int, char); static void buspirate_jtag_set_feature(int, char, char); static void buspirate_jtag_get_adcs(int); /* low level HW communication interface */ static int buspirate_serial_open(char *port); static int buspirate_serial_setspeed(int fd, char speed, cc_t timeout); static int buspirate_serial_write(int fd, char *buf, int size); static int buspirate_serial_read(int fd, char *buf, int size); static void buspirate_serial_close(int fd); static void buspirate_print_buffer(char *buf, int size); static int buspirate_execute_queue(void) { /* currently processed command */ struct jtag_command *cmd = jtag_command_queue; int scan_size; enum scan_type type; uint8_t *buffer; while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: DEBUG_JTAG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest ->end_state)); buspirate_end_state(cmd->cmd.runtest ->end_state); buspirate_runtest(cmd->cmd.runtest ->num_cycles); break; case JTAG_TLR_RESET: DEBUG_JTAG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove ->end_state)); buspirate_end_state(cmd->cmd.statemove ->end_state); buspirate_state_move(); break; case JTAG_PATHMOVE: DEBUG_JTAG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove ->path[cmd->cmd.pathmove ->num_states - 1])); buspirate_path_move(cmd->cmd.pathmove ->num_states, cmd->cmd.pathmove->path); break; case JTAG_SCAN: DEBUG_JTAG_IO("scan end in %s", tap_state_name(cmd->cmd.scan ->end_state)); buspirate_end_state(cmd->cmd.scan ->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); buspirate_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); break; case JTAG_RESET: DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); /* flush buffers, so we can reset */ buspirate_tap_execute(); if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); buspirate_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_SLEEP: DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us); buspirate_tap_execute(); jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_STABLECLOCKS: DEBUG_JTAG_IO("stable clock %i cycles", cmd->cmd.stableclocks->num_cycles); buspirate_stableclocks(cmd->cmd.stableclocks->num_cycles); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return buspirate_tap_execute(); } /* Returns true if successful, false if error. */ static bool read_and_discard_all_data(const int fd) { /* LOG_INFO("Discarding any stale data from a previous connection..."); */ bool was_msg_already_printed = false; for ( ; ; ) { char buffer[1024]; /* Any size will do, it's a trade-off between stack size and performance. */ const ssize_t read_count = read(fd, buffer, sizeof(buffer)); if (read_count == 0) { /* This is the "end of file" or "connection closed at the other end" condition. */ return true; } if (read_count > 0) { if (!was_msg_already_printed) { LOG_INFO("Some stale data from a previous connection was discarded."); was_msg_already_printed = true; } continue; } assert(read_count == -1); /* According to the specification. */ const int errno_code = errno; if (errno_code == EINTR) continue; if (errno_code == EAGAIN || errno_code == EWOULDBLOCK) { /* We know that the file descriptor has been opened with O_NONBLOCK or O_NDELAY, and these codes mean that there is no data to read at present. */ return true; } /* Some other error has occurred. */ return false; } } static int buspirate_init(void) { if (buspirate_port == NULL) { LOG_ERROR("You need to specify the serial port!"); return ERROR_JTAG_INIT_FAILED; } buspirate_fd = buspirate_serial_open(buspirate_port); if (buspirate_fd == -1) { LOG_ERROR("Could not open serial port"); return ERROR_JTAG_INIT_FAILED; } /* The Operating System or the device itself may deliver stale data from the last connection, so discard all available bytes right after the new connection has been established. After all, we are implementing here a master/slave protocol, so the slave should have nothing to say until the master sends the first command. In the past, there was a tcflush() call in buspirate_serial_setspeed(), but that was not enough. I guess you must actively read from the serial port to trigger any data collection from the device and/or lower USB layers. If you disable the serial port read timeout (if you set SHORT_TIMEOUT to 0), then the discarding does not work any more. Note that we are lowering the serial port timeout for this first read operation, otherwise the normal initialisation would be delayed for too long. */ if (-1 == buspirate_serial_setspeed(buspirate_fd, SERIAL_NORMAL, SHORT_TIMEOUT)) { LOG_ERROR("Error configuring the serial port."); return ERROR_JTAG_INIT_FAILED; } if (!read_and_discard_all_data(buspirate_fd)) { LOG_ERROR("Error while attempting to discard any stale data right after establishing the connection."); return ERROR_JTAG_INIT_FAILED; } if (-1 == buspirate_serial_setspeed(buspirate_fd, SERIAL_NORMAL, NORMAL_TIMEOUT)) { LOG_ERROR("Error configuring the serial port."); return ERROR_JTAG_INIT_FAILED; } buspirate_jtag_enable(buspirate_fd); if (buspirate_baudrate != SERIAL_NORMAL) buspirate_jtag_set_speed(buspirate_fd, SERIAL_FAST); LOG_INFO("Buspirate Interface ready!"); buspirate_tap_init(); buspirate_jtag_set_mode(buspirate_fd, buspirate_pinmode); buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG, (buspirate_vreg == 1) ? ACTION_ENABLE : ACTION_DISABLE); buspirate_jtag_set_feature(buspirate_fd, FEATURE_PULLUP, (buspirate_pullup == 1) ? ACTION_ENABLE : ACTION_DISABLE); buspirate_reset(0, 0); return ERROR_OK; } static int buspirate_quit(void) { LOG_INFO("Shutting down buspirate."); buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ); buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL); buspirate_jtag_reset(buspirate_fd); buspirate_serial_close(buspirate_fd); if (buspirate_port) { free(buspirate_port); buspirate_port = NULL; } return ERROR_OK; } /* openocd command interface */ COMMAND_HANDLER(buspirate_handle_adc_command) { if (buspirate_fd == -1) return ERROR_OK; /* send the command */ buspirate_jtag_get_adcs(buspirate_fd); return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_vreg_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (atoi(CMD_ARGV[0]) == 1) buspirate_vreg = 1; else if (atoi(CMD_ARGV[0]) == 0) buspirate_vreg = 0; else LOG_ERROR("usage: buspirate_vreg <1|0>"); return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_pullup_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (atoi(CMD_ARGV[0]) == 1) buspirate_pullup = 1; else if (atoi(CMD_ARGV[0]) == 0) buspirate_pullup = 0; else LOG_ERROR("usage: buspirate_pullup <1|0>"); return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_led_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (atoi(CMD_ARGV[0]) == 1) { /* enable led */ buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED, ACTION_ENABLE); } else if (atoi(CMD_ARGV[0]) == 0) { /* disable led */ buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED, ACTION_DISABLE); } else { LOG_ERROR("usage: buspirate_led <1|0>"); } return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_mode_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGV[0][0] == 'n') buspirate_pinmode = MODE_JTAG; else if (CMD_ARGV[0][0] == 'o') buspirate_pinmode = MODE_JTAG_OD; else LOG_ERROR("usage: buspirate_mode "); return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_speed_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGV[0][0] == 'n') buspirate_baudrate = SERIAL_NORMAL; else if (CMD_ARGV[0][0] == 'f') buspirate_baudrate = SERIAL_FAST; else LOG_ERROR("usage: buspirate_speed "); return ERROR_OK; } COMMAND_HANDLER(buspirate_handle_port_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (buspirate_port == NULL) buspirate_port = strdup(CMD_ARGV[0]); return ERROR_OK; } static const struct command_registration buspirate_command_handlers[] = { { .name = "buspirate_adc", .handler = &buspirate_handle_adc_command, .mode = COMMAND_EXEC, .help = "reads voltages on adc pins", }, { .name = "buspirate_vreg", .usage = "<1|0>", .handler = &buspirate_handle_vreg_command, .mode = COMMAND_CONFIG, .help = "changes the state of voltage regulators", }, { .name = "buspirate_pullup", .usage = "<1|0>", .handler = &buspirate_handle_pullup_command, .mode = COMMAND_CONFIG, .help = "changes the state of pullup", }, { .name = "buspirate_led", .usage = "<1|0>", .handler = &buspirate_handle_led_command, .mode = COMMAND_EXEC, .help = "changes the state of led", }, { .name = "buspirate_speed", .usage = "", .handler = &buspirate_handle_speed_command, .mode = COMMAND_CONFIG, .help = "speed of the interface", }, { .name = "buspirate_mode", .usage = "", .handler = &buspirate_handle_mode_command, .mode = COMMAND_CONFIG, .help = "pin mode of the interface", }, { .name = "buspirate_port", .usage = "/dev/ttyUSB0", .handler = &buspirate_handle_port_command, .mode = COMMAND_CONFIG, .help = "name of the serial port to open", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface buspirate_interface = { .name = "buspirate", .execute_queue = buspirate_execute_queue, .commands = buspirate_command_handlers, .init = buspirate_init, .quit = buspirate_quit }; /*************** jtag execute commands **********************/ static void buspirate_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void buspirate_state_move(void) { int i = 0, tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_count; i++) { tms = (tms_scan >> i) & 1; buspirate_tap_append(tms, 0); } tap_set_state(tap_get_end_state()); } static void buspirate_path_move(int num_states, tap_state_t *path) { int i; for (i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), false) == path[i]) { buspirate_tap_append(0, 0); } else if (tap_state_transition(tap_get_state(), true) == path[i]) { buspirate_tap_append(1, 0); } else { LOG_ERROR("BUG: %s -> %s isn't a valid " "TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); exit(-1); } tap_set_state(path[i]); } tap_set_end_state(tap_get_state()); } static void buspirate_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { buspirate_end_state(TAP_IDLE); buspirate_state_move(); } for (i = 0; i < num_cycles; i++) buspirate_tap_append(0, 0); DEBUG_JTAG_IO("runtest: cur_state %s end_state %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state())); /* finish in end_state */ buspirate_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) buspirate_state_move(); } static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { tap_state_t saved_end_state; buspirate_tap_make_space(1, scan_size+8); /* is 8 correct ? (2 moves = 16) */ saved_end_state = tap_get_end_state(); buspirate_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); /* Only move if we're not already there */ if (tap_get_state() != tap_get_end_state()) buspirate_state_move(); buspirate_tap_append_scan(scan_size, buffer, command); /* move to PAUSE */ buspirate_tap_append(0, 0); /* restore the saved state */ buspirate_end_state(saved_end_state); tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) buspirate_state_move(); } static void buspirate_stableclocks(int num_cycles) { int i; int tms = (tap_get_state() == TAP_RESET ? 1 : 0); buspirate_tap_make_space(0, num_cycles); for (i = 0; i < num_cycles; i++) buspirate_tap_append(tms, 0); } /************************* TAP related stuff **********/ /* This buffer size matches the maximum CMD_TAP_SHIFT bit length in the Bus Pirate firmware, look for constant 0x2000 in OpenOCD.c . */ #define BUSPIRATE_BUFFER_SIZE 1024 /* The old value of 32 scans was not enough to achieve near 100% utilisation ratio for the current BUSPIRATE_BUFFER_SIZE value of 1024. With 128 scans I am getting full USB 2.0 high speed packets (512 bytes long) when using the JtagDue firmware on the Arduino Due instead of the Bus Pirate, which amounts approximately to a 10% overall speed gain. Bigger packets should also benefit the Bus Pirate, but the speed difference is much smaller. Unfortunately, each 512-byte packet is followed by a 329-byte one, which is not ideal. However, increasing BUSPIRATE_BUFFER_SIZE for the benefit of the JtagDue would make it incompatible with the Bus Pirate firmware. */ #define BUSPIRATE_MAX_PENDING_SCANS 128 static char tms_chain[BUSPIRATE_BUFFER_SIZE]; /* send */ static char tdi_chain[BUSPIRATE_BUFFER_SIZE]; /* send */ static int tap_chain_index; struct pending_scan_result /* this was stolen from arm-jtag-ew */ { int first; /* First bit position in tdo_buffer to read */ int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ uint8_t *buffer; }; static struct pending_scan_result tap_pending_scans[BUSPIRATE_MAX_PENDING_SCANS]; static int tap_pending_scans_num; static void buspirate_tap_init(void) { tap_chain_index = 0; tap_pending_scans_num = 0; } static int buspirate_tap_execute(void) { static const int CMD_TAP_SHIFT_HEADER_LEN = 3; char tmp[4096]; uint8_t *in_buf; int i; int fill_index = 0; int ret; int bytes_to_send; if (tap_chain_index <= 0) return ERROR_OK; LOG_DEBUG("executing tap num bits = %i scans = %i", tap_chain_index, tap_pending_scans_num); bytes_to_send = DIV_ROUND_UP(tap_chain_index, 8); tmp[0] = CMD_TAP_SHIFT; /* this command expects number of bits */ tmp[1] = (char)(tap_chain_index >> 8); /* high */ tmp[2] = (char)(tap_chain_index); /* low */ fill_index = CMD_TAP_SHIFT_HEADER_LEN; for (i = 0; i < bytes_to_send; i++) { tmp[fill_index] = tdi_chain[i]; fill_index++; tmp[fill_index] = tms_chain[i]; fill_index++; } /* jlink.c calls the routine below, which may be useful for debugging purposes. For example, enabling this allows you to compare the log outputs from jlink.c and from this module for JTAG development or troubleshooting purposes. */ if (false) { last_tap_state = jtag_debug_state_machine(tms_chain, tdi_chain, tap_chain_index, last_tap_state); } ret = buspirate_serial_write(buspirate_fd, tmp, CMD_TAP_SHIFT_HEADER_LEN + bytes_to_send*2); if (ret != bytes_to_send*2+CMD_TAP_SHIFT_HEADER_LEN) { LOG_ERROR("error writing :("); return ERROR_JTAG_DEVICE_ERROR; } ret = buspirate_serial_read(buspirate_fd, tmp, bytes_to_send + CMD_TAP_SHIFT_HEADER_LEN); if (ret != bytes_to_send + CMD_TAP_SHIFT_HEADER_LEN) { LOG_ERROR("error reading"); return ERROR_FAIL; } in_buf = (uint8_t *)(&tmp[CMD_TAP_SHIFT_HEADER_LEN]); /* parse the scans */ for (i = 0; i < tap_pending_scans_num; i++) { uint8_t *buffer = tap_pending_scans[i].buffer; int length = tap_pending_scans[i].length; int first = tap_pending_scans[i].first; struct scan_command *command = tap_pending_scans[i].command; /* copy bits from buffer */ buf_set_buf(in_buf, first, buffer, 0, length); /* return buffer to higher level */ if (jtag_read_buffer(buffer, command) != ERROR_OK) { buspirate_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } free(buffer); } buspirate_tap_init(); return ERROR_OK; } static void buspirate_tap_make_space(int scans, int bits) { int have_scans = BUSPIRATE_MAX_PENDING_SCANS - tap_pending_scans_num; int have_bits = BUSPIRATE_BUFFER_SIZE * 8 - tap_chain_index; if ((have_scans < scans) || (have_bits < bits)) buspirate_tap_execute(); } static void buspirate_tap_append(int tms, int tdi) { int chain_index; buspirate_tap_make_space(0, 1); chain_index = tap_chain_index / 8; if (chain_index < BUSPIRATE_BUFFER_SIZE) { int bit_index = tap_chain_index % 8; uint8_t bit = 1 << bit_index; if (0 == bit_index) { /* Let's say that the TAP shift operation wants to shift 9 bits, so we will be sending to the Bus Pirate a bit count of 9 but still full 16 bits (2 bytes) of shift data. If we don't clear all bits at this point, the last 7 bits will contain random data from the last buffer contents, which is not pleasant to the eye. Besides, the Bus Pirate (or some clone) may want to assert in debug builds that, after consuming all significant data bits, the rest of them are zero. Therefore, for aesthetic and for assert purposes, we clear all bits below. */ tms_chain[chain_index] = 0; tdi_chain[chain_index] = 0; } if (tms) tms_chain[chain_index] |= bit; else tms_chain[chain_index] &= ~bit; if (tdi) tdi_chain[chain_index] |= bit; else tdi_chain[chain_index] &= ~bit; tap_chain_index++; } else { LOG_ERROR("tap_chain overflow, bad things will happen"); /* Exit abruptly, like jlink.c does. After a buffer overflow we don't want to carry on, as data will be corrupt. Another option would be to return some error code at this point. */ exit(-1); } } static void buspirate_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command) { int i; tap_pending_scans[tap_pending_scans_num].length = length; tap_pending_scans[tap_pending_scans_num].buffer = buffer; tap_pending_scans[tap_pending_scans_num].command = command; tap_pending_scans[tap_pending_scans_num].first = tap_chain_index; for (i = 0; i < length; i++) { int tms = (i < length-1 ? 0 : 1); int tdi = (buffer[i/8] >> (i%8)) & 1; buspirate_tap_append(tms, tdi); } tap_pending_scans_num++; } /*************** jtag wrapper functions *********************/ /* (1) assert or (0) deassert reset lines */ static void buspirate_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst) buspirate_jtag_set_feature(buspirate_fd, FEATURE_TRST, ACTION_DISABLE); else buspirate_jtag_set_feature(buspirate_fd, FEATURE_TRST, ACTION_ENABLE); if (srst) buspirate_jtag_set_feature(buspirate_fd, FEATURE_SRST, ACTION_DISABLE); else buspirate_jtag_set_feature(buspirate_fd, FEATURE_SRST, ACTION_ENABLE); } /*************** jtag lowlevel functions ********************/ static void buspirate_jtag_enable(int fd) { int ret; char tmp[21] = { [0 ... 20] = 0x00 }; int done = 0; int cmd_sent = 0; LOG_DEBUG("Entering binary mode"); buspirate_serial_write(fd, tmp, 20); usleep(10000); /* reads 1 to n "BBIO1"s and one "OCD1" */ while (!done) { ret = buspirate_serial_read(fd, tmp, 4); if (ret != 4) { LOG_ERROR("Buspirate error. Is binary" "/OpenOCD support enabled?"); exit(-1); } if (strncmp(tmp, "BBIO", 4) == 0) { ret = buspirate_serial_read(fd, tmp, 1); if (ret != 1) { LOG_ERROR("Buspirate did not answer correctly! " "Do you have correct firmware?"); exit(-1); } if (tmp[0] != '1') { LOG_ERROR("Unsupported binary protocol"); exit(-1); } if (cmd_sent == 0) { cmd_sent = 1; tmp[0] = CMD_ENTER_OOCD; ret = buspirate_serial_write(fd, tmp, 1); if (ret != 1) { LOG_ERROR("error reading"); exit(-1); } } } else if (strncmp(tmp, "OCD1", 4) == 0) done = 1; else { LOG_ERROR("Buspirate did not answer correctly! " "Do you have correct firmware?"); exit(-1); } } } static void buspirate_jtag_reset(int fd) { char tmp[5]; tmp[0] = 0x00; /* exit OCD1 mode */ buspirate_serial_write(fd, tmp, 1); usleep(10000); /* We ignore the return value here purposly, nothing we can do */ buspirate_serial_read(fd, tmp, 5); if (strncmp(tmp, "BBIO1", 5) == 0) { tmp[0] = 0x0F; /* reset BP */ buspirate_serial_write(fd, tmp, 1); } else LOG_ERROR("Unable to restart buspirate!"); } static void buspirate_jtag_set_speed(int fd, char speed) { int ret; char tmp[2]; char ack[2]; ack[0] = 0xAA; ack[1] = 0x55; tmp[0] = CMD_UART_SPEED; tmp[1] = speed; buspirate_jtag_command(fd, tmp, 2); /* here the adapter changes speed, we need follow */ if (-1 == buspirate_serial_setspeed(fd, speed, NORMAL_TIMEOUT)) { LOG_ERROR("Error configuring the serial port."); exit(-1); } buspirate_serial_write(fd, ack, 2); ret = buspirate_serial_read(fd, tmp, 2); if (ret != 2) { LOG_ERROR("Buspirate did not ack speed change"); exit(-1); } if ((tmp[0] != CMD_UART_SPEED) || (tmp[1] != speed)) { LOG_ERROR("Buspirate did not reply as expected to the speed change command"); exit(-1); } LOG_INFO("Buspirate switched to %s mode", (speed == SERIAL_NORMAL) ? "normal" : "FAST"); } static void buspirate_jtag_set_mode(int fd, char mode) { char tmp[2]; tmp[0] = CMD_PORT_MODE; tmp[1] = mode; buspirate_jtag_command(fd, tmp, 2); } static void buspirate_jtag_set_feature(int fd, char feat, char action) { char tmp[3]; tmp[0] = CMD_FEATURE; tmp[1] = feat; /* what */ tmp[2] = action; /* action */ buspirate_jtag_command(fd, tmp, 3); } static void buspirate_jtag_get_adcs(int fd) { uint8_t tmp[10]; uint16_t a, b, c, d; tmp[0] = CMD_READ_ADCS; buspirate_jtag_command(fd, (char *)tmp, 1); a = tmp[2] << 8 | tmp[3]; b = tmp[4] << 8 | tmp[5]; c = tmp[6] << 8 | tmp[7]; d = tmp[8] << 8 | tmp[9]; LOG_INFO("ADC: ADC_Pin = %.02f VPullup = %.02f V33 = %.02f " "V50 = %.02f", ((float)a)/155.1515, ((float)b)/155.1515, ((float)c)/155.1515, ((float)d)/155.1515); } static unsigned char buspirate_jtag_command(int fd, char *cmd, int cmdlen) { int res; int len = 0; res = buspirate_serial_write(fd, cmd, cmdlen); if ((cmd[0] == CMD_UART_SPEED) || (cmd[0] == CMD_PORT_MODE) || (cmd[0] == CMD_FEATURE) || (cmd[0] == CMD_JTAG_SPEED)) return 1; if (res == cmdlen) { switch (cmd[0]) { case CMD_READ_ADCS: len = 10; /* 2*sizeof(char)+4*sizeof(uint16_t) */ break; case CMD_TAP_SHIFT: len = cmdlen; break; default: LOG_INFO("Wrong !"); } res = buspirate_serial_read(fd, cmd, len); if (res > 0) return (unsigned char)cmd[1]; else return -1; } else return -1; return 0; } /* low level serial port */ /* TODO add support for WIN32 and others ! */ static int buspirate_serial_open(char *port) { int fd; fd = open(buspirate_port, O_RDWR | O_NOCTTY | O_NDELAY); return fd; } /* Returns -1 on error. */ static int buspirate_serial_setspeed(int fd, char speed, cc_t timeout) { struct termios t_opt; speed_t baud = (speed == SERIAL_FAST) ? B1000000 : B115200; /* set the serial port parameters */ fcntl(fd, F_SETFL, 0); if (0 != tcgetattr(fd, &t_opt)) return -1; if (0 != cfsetispeed(&t_opt, baud)) return -1; if (0 != cfsetospeed(&t_opt, baud)) return -1; t_opt.c_cflag |= (CLOCAL | CREAD); t_opt.c_cflag &= ~PARENB; t_opt.c_cflag &= ~CSTOPB; t_opt.c_cflag &= ~CSIZE; t_opt.c_cflag |= CS8; t_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* The serial port may have been configured for human interaction with the Bus Pirate console, but OpenOCD is going to use a binary protocol, so make sure to turn off any CR/LF translation and the like. */ t_opt.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL); t_opt.c_oflag &= ~OPOST; t_opt.c_cc[VMIN] = 0; t_opt.c_cc[VTIME] = timeout; /* Note that, in the past, TCSANOW was used below instead of TCSADRAIN, and CMD_UART_SPEED did not work properly then, at least with the Bus Pirate v3.5 (USB). */ if (0 != tcsetattr(fd, TCSADRAIN, &t_opt)) { /* According to the Linux documentation, this is actually not enough to detect errors, you need to call tcgetattr() and check that all changes have been performed successfully. */ return -1; } return 0; } static int buspirate_serial_write(int fd, char *buf, int size) { int ret = 0; ret = write(fd, buf, size); LOG_DEBUG("size = %d ret = %d", size, ret); buspirate_print_buffer(buf, size); if (ret != size) LOG_ERROR("Error sending data"); return ret; } static int buspirate_serial_read(int fd, char *buf, int size) { int len = 0; int ret = 0; int timeout = 0; while (len < size) { ret = read(fd, buf+len, size-len); if (ret == -1) return -1; if (ret == 0) { timeout++; if (timeout >= 10) break; continue; } len += ret; } LOG_DEBUG("should have read = %d actual size = %d", size, len); buspirate_print_buffer(buf, len); if (len != size) LOG_ERROR("Error reading data"); return len; } static void buspirate_serial_close(int fd) { close(fd); } #define LINE_SIZE 81 #define BYTES_PER_LINE 16 static void buspirate_print_buffer(char *buf, int size) { char line[LINE_SIZE]; char tmp[10]; int offset = 0; line[0] = 0; while (offset < size) { snprintf(tmp, 5, "%02x ", (uint8_t)buf[offset]); offset++; strcat(line, tmp); if (offset % BYTES_PER_LINE == 0) { LOG_DEBUG("%s", line); line[0] = 0; } } if (line[0] != 0) LOG_DEBUG("%s", line); } openocd-0.9.0/src/jtag/drivers/libusb0_common.c0000644000175000017500000001352312516456302016346 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * Copyright (C) 2011 by Mauro Gamba * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "libusb0_common.h" static bool jtag_libusb_match(struct jtag_libusb_device *dev, const uint16_t vids[], const uint16_t pids[]) { for (unsigned i = 0; vids[i]; i++) { if (dev->descriptor.idVendor == vids[i] && dev->descriptor.idProduct == pids[i]) { return true; } } return false; } /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index, const char *string) { int retval; bool matched; char desc_string[256+1]; /* Max size of string descriptor */ if (str_index == 0) return false; retval = usb_get_string_simple(device, str_index, desc_string, sizeof(desc_string)-1); if (retval < 0) { LOG_ERROR("usb_get_string_simple() failed with %d", retval); return false; } /* Null terminate descriptor string in case it needs to be logged. */ desc_string[sizeof(desc_string)-1] = '\0'; matched = strncmp(string, desc_string, sizeof(desc_string)) == 0; if (!matched) LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'", desc_string, string); return matched; } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], const char *serial, struct jtag_libusb_device_handle **out) { int retval = -ENODEV; struct jtag_libusb_device_handle *libusb_handle; usb_init(); usb_find_busses(); usb_find_devices(); struct usb_bus *busses = usb_get_busses(); for (struct usb_bus *bus = busses; bus; bus = bus->next) { for (struct usb_device *dev = bus->devices; dev; dev = dev->next) { if (!jtag_libusb_match(dev, vids, pids)) continue; libusb_handle = usb_open(dev); if (NULL == libusb_handle) { retval = -errno; continue; } /* Device must be open to use libusb_get_string_descriptor_ascii. */ if (serial != NULL && !string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) { usb_close(libusb_handle); continue; } *out = libusb_handle; retval = 0; break; } } return retval; } void jtag_libusb_close(jtag_libusb_device_handle *dev) { /* Close device */ usb_close(dev); } int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout) { int transferred = 0; transferred = usb_control_msg(dev, requestType, request, wValue, wIndex, bytes, size, timeout); if (transferred < 0) transferred = 0; return transferred; } int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_write(dev, ep, bytes, size, timeout); } int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { return usb_bulk_read(dev, ep, bytes, size, timeout); } int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); return usb_set_configuration(devh, udev->config[configuration].bConfigurationValue); } int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, int bclass, int subclass, int protocol) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct usb_interface *iface = udev->config->interface; struct usb_interface_descriptor *desc = iface->altsetting; *usb_read_ep = *usb_write_ep = 0; for (int i = 0; i < desc->bNumEndpoints; i++) { if ((bclass > 0 && desc->bInterfaceClass != bclass) || (subclass > 0 && desc->bInterfaceSubClass != subclass) || (protocol > 0 && desc->bInterfaceProtocol != protocol)) continue; uint8_t epnum = desc->endpoint[i].bEndpointAddress; bool is_input = epnum & 0x80; LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum); if (is_input) *usb_read_ep = epnum; else *usb_write_ep = epnum; if (*usb_read_ep && *usb_write_ep) { LOG_DEBUG("Claiming interface %d", (int)desc->bInterfaceNumber); usb_claim_interface(devh, (int)desc->bInterfaceNumber); return ERROR_OK; } } return ERROR_FAIL; } int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid) { if (!dev) return ERROR_FAIL; *pid = dev->descriptor.idProduct; return ERROR_OK; } openocd-0.9.0/src/jtag/drivers/libusb0_common.h0000644000175000017500000000706512516456302016357 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * Copyright (C) 2011 by Mauro Gamba * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_LIBUSB_COMMON_H #define JTAG_LIBUSB_COMMON_H #include #define jtag_libusb_device usb_device #define jtag_libusb_device_handle usb_dev_handle #define jtag_libusb_device_descriptor usb_device_descriptor #define jtag_libusb_interface usb_interface #define jtag_libusb_interface_descriptor usb_interface_descriptor #define jtag_libusb_endpoint_descriptor usb_endpoint_descriptor #define jtag_libusb_config_descriptor usb_config_descriptor #define jtag_libusb_reset_device(dev) usb_reset(dev) #define jtag_libusb_get_device(devh) usb_device(devh) /* make some defines compatible to libusb1 */ #define LIBUSB_REQUEST_TYPE_VENDOR USB_TYPE_VENDOR #define LIBUSB_RECIPIENT_DEVICE USB_RECIP_DEVICE #define LIBUSB_ENDPOINT_OUT USB_ENDPOINT_OUT #define LIBUSB_ENDPOINT_IN USB_ENDPOINT_IN static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh, int iface) { return usb_claim_interface(devh, iface); }; static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh, int iface) { return usb_release_interface(devh, iface); } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], const char *serial, struct jtag_libusb_device_handle **out); void jtag_libusb_close(jtag_libusb_device_handle *dev); int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout); int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, int bclass, int subclass, int protocol); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* JTAG_USB_COMMON_H */ openocd-0.9.0/src/jtag/drivers/presto.c0000644000175000017500000004730712315575360014764 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * Holds driver for PRESTO programmer from ASIX. * http://tools.asix.net/prg_presto.htm */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if IS_CYGWIN == 1 #include "windows.h" #endif #include #include #include "bitq.h" /* PRESTO access library includes */ #if BUILD_PRESTO_FTD2XX == 1 #include #include "ftd2xx_common.h" #elif BUILD_PRESTO_LIBFTDI == 1 #include #else #error "BUG: either FTD2XX and LIBFTDI has to be used" #endif /* -------------------------------------------------------------------------- */ #define FT_DEVICE_NAME_LEN 64 #define FT_DEVICE_SERNUM_LEN 64 #define PRESTO_VID_PID 0x0403f1a0 #define PRESTO_VID (0x0403) #define PRESTO_PID (0xf1a0) #define BUFFER_SIZE (64*62) struct presto { #if BUILD_PRESTO_FTD2XX == 1 FT_HANDLE handle; FT_STATUS status; #elif BUILD_PRESTO_LIBFTDI == 1 struct ftdi_context ftdic; int retval; #endif char serial[FT_DEVICE_SERNUM_LEN]; uint8_t buff_out[BUFFER_SIZE]; int buff_out_pos; uint8_t buff_in[BUFFER_SIZE]; int buff_in_exp;/* expected in buffer length */ int buff_in_len;/* length of data received */ int buff_in_pos; unsigned long total_out; unsigned long total_in; int jtag_tms; /* last tms state */ int jtag_tck; /* last tck state */ int jtag_rst; /* last trst state */ int jtag_tdi_data; int jtag_tdi_count; int jtag_speed; }; static struct presto presto_state; static struct presto *presto = &presto_state; static uint8_t presto_init_seq[] = { 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0 }; static int presto_write(uint8_t *buf, uint32_t size) { #if BUILD_PRESTO_FTD2XX == 1 DWORD ftbytes; presto->status = FT_Write(presto->handle, buf, size, &ftbytes); if (presto->status != FT_OK) { LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } #elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes; presto->retval = ftdi_write_data(&presto->ftdic, buf, size); if (presto->retval < 0) { LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic)); return ERROR_JTAG_DEVICE_ERROR; } ftbytes = presto->retval; #endif if (ftbytes != size) { LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", (unsigned)ftbytes, (unsigned)size); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int presto_read(uint8_t *buf, uint32_t size) { #if BUILD_PRESTO_FTD2XX == 1 DWORD ftbytes; presto->status = FT_Read(presto->handle, buf, size, &ftbytes); if (presto->status != FT_OK) { LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } #elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes = 0; struct timeval timeout, now; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, 1, 0); /* one second timeout */ while (ftbytes < size) { presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes); if (presto->retval < 0) { LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic)); return ERROR_JTAG_DEVICE_ERROR; } ftbytes += presto->retval; gettimeofday(&now, NULL); if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) break; } #endif if (ftbytes != size) { /* this is just a warning, there might have been timeout when detecting PRESTO, *which is not fatal */ LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)", (unsigned)ftbytes, (unsigned)size); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } #if BUILD_PRESTO_FTD2XX == 1 static int presto_open_ftd2xx(char *req_serial) { uint32_t i; DWORD numdevs; DWORD vidpid; char devname[FT_DEVICE_NAME_LEN]; FT_DEVICE device; BYTE presto_data; DWORD ftbytes; presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID); if (presto->status != FT_OK) { LOG_ERROR("couldn't add PRESTO VID/PID"); exit(-1); } #endif presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY); if (presto->status != FT_OK) { LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs); for (i = 0; i < numdevs; i++) { presto->status = FT_Open(i, &(presto->handle)); if (presto->status != FT_OK) { /* this is not fatal, the device may be legitimately open by other process, *hence debug message only */ LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status)); continue; } LOG_DEBUG("FTDI device %i open", (int)i); presto->status = FT_GetDeviceInfo(presto->handle, &device, &vidpid, presto->serial, devname, NULL); if (presto->status == FT_OK) { if (vidpid == PRESTO_VID_PID && (req_serial == NULL || !strcmp(presto->serial, req_serial))) break; } else LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string( presto->status)); LOG_DEBUG("FTDI device %i does not match, closing", (int)i); FT_Close(presto->handle); presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; } if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */ presto->status = FT_SetLatencyTimer(presto->handle, 1); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetTimeouts(presto->handle, 100, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0xD0; presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; /* delay between first write/read turnaround (after purge?) necessary * under Linux for unknown reason, * probably a bug in library threading */ usleep(100000); presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; if (ftbytes != 1) { LOG_DEBUG("PRESTO reset"); presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetBitMode(presto->handle, 0x80, 1); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetBaudRate(presto->handle, 9600); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0; for (i = 0; i < 4 * 62; i++) { presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; } usleep(100000); presto->status = FT_SetBitMode(presto->handle, 0x00, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0xD0; presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason, probably a bug in library threading */ usleep(100000); presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; if (ftbytes != 1) { LOG_DEBUG("PRESTO not responding"); return ERROR_JTAG_DEVICE_ERROR; } } presto->status = FT_SetTimeouts(presto->handle, 0, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Write(presto->handle, &presto_init_seq, sizeof(presto_init_seq), &ftbytes); if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) return ERROR_JTAG_DEVICE_ERROR; return ERROR_OK; } #elif BUILD_PRESTO_LIBFTDI == 1 static int presto_open_libftdi(char *req_serial) { uint8_t presto_data; LOG_DEBUG("searching for PRESTO using libftdi"); /* initialize FTDI context structure */ if (ftdi_init(&presto->ftdic) < 0) { LOG_ERROR("unable to init libftdi: %s", presto->ftdic.error_str); return ERROR_JTAG_DEVICE_ERROR; } /* context, vendor id, product id */ if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0) { LOG_ERROR("unable to open PRESTO: %s", presto->ftdic.error_str); return ERROR_JTAG_DEVICE_ERROR; } if (ftdi_usb_reset(&presto->ftdic) < 0) { LOG_ERROR("unable to reset PRESTO device"); return ERROR_JTAG_DEVICE_ERROR; } if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0) { LOG_ERROR("unable to set latency timer"); return ERROR_JTAG_DEVICE_ERROR; } if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) { LOG_ERROR("unable to purge PRESTO buffers"); return ERROR_JTAG_DEVICE_ERROR; } presto_data = 0xD0; if (presto_write(&presto_data, 1) != ERROR_OK) { LOG_ERROR("error writing to PRESTO"); return ERROR_JTAG_DEVICE_ERROR; } if (presto_read(&presto_data, 1) != ERROR_OK) { LOG_DEBUG("no response from PRESTO, retrying"); if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0xD0; if (presto_write(&presto_data, 1) != ERROR_OK) return ERROR_JTAG_DEVICE_ERROR; if (presto_read(&presto_data, 1) != ERROR_OK) { LOG_ERROR("no response from PRESTO, giving up"); return ERROR_JTAG_DEVICE_ERROR; } } if (presto_write(presto_init_seq, sizeof(presto_init_seq)) != ERROR_OK) { LOG_ERROR("error writing PRESTO init sequence"); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } #endif /* BUILD_PRESTO_LIBFTDI == 1 */ static int presto_open(char *req_serial) { presto->buff_out_pos = 0; presto->buff_in_pos = 0; presto->buff_in_len = 0; presto->buff_in_exp = 0; presto->total_out = 0; presto->total_in = 0; presto->jtag_tms = 0; presto->jtag_tck = 0; presto->jtag_rst = 0; presto->jtag_tdi_data = 0; presto->jtag_tdi_count = 0; presto->jtag_speed = 0; #if BUILD_PRESTO_FTD2XX == 1 return presto_open_ftd2xx(req_serial); #elif BUILD_PRESTO_LIBFTDI == 1 return presto_open_libftdi(req_serial); #endif } static int presto_close(void) { int result = ERROR_OK; #if BUILD_PRESTO_FTD2XX == 1 DWORD ftbytes; if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return result; presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) result = ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Write(presto->handle, &presto_init_seq, sizeof(presto_init_seq), &ftbytes); if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) result = ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetLatencyTimer(presto->handle, 16); if (presto->status != FT_OK) result = ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Close(presto->handle); if (presto->status != FT_OK) result = ERROR_JTAG_DEVICE_ERROR; else presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; #elif BUILD_PRESTO_LIBFTDI == 1 presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq)); if (presto->retval != sizeof(presto_init_seq)) result = ERROR_JTAG_DEVICE_ERROR; presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16); if (presto->retval < 0) result = ERROR_JTAG_DEVICE_ERROR; presto->retval = ftdi_usb_close(&presto->ftdic); if (presto->retval < 0) result = ERROR_JTAG_DEVICE_ERROR; else ftdi_deinit(&presto->ftdic); #endif return result; } static int presto_flush(void) { if (presto->buff_out_pos == 0) return ERROR_OK; #if BUILD_PRESTO_FTD2XX == 1 if (presto->status != FT_OK) { #elif BUILD_PRESTO_LIBFTDI == 1 if (presto->retval < 0) { #endif LOG_DEBUG("error in previous communication, canceling I/O operation"); return ERROR_JTAG_DEVICE_ERROR; } if (presto_write(presto->buff_out, presto->buff_out_pos) != ERROR_OK) { presto->buff_out_pos = 0; return ERROR_JTAG_DEVICE_ERROR; } presto->total_out += presto->buff_out_pos; presto->buff_out_pos = 0; if (presto->buff_in_exp == 0) return ERROR_OK; presto->buff_in_pos = 0; presto->buff_in_len = 0; if (presto_read(presto->buff_in, presto->buff_in_exp) != ERROR_OK) { presto->buff_in_exp = 0; return ERROR_JTAG_DEVICE_ERROR; } presto->total_in += presto->buff_in_exp; presto->buff_in_len = presto->buff_in_exp; presto->buff_in_exp = 0; return ERROR_OK; } static int presto_sendbyte(int data) { if (data == EOF) return presto_flush(); if (presto->buff_out_pos < BUFFER_SIZE) { presto->buff_out[presto->buff_out_pos++] = (uint8_t)data; if (((data & 0xC0) == 0x40) || ((data & 0xD0) == 0xD0)) presto->buff_in_exp++; } else return ERROR_JTAG_DEVICE_ERROR; #if BUILD_PRESTO_FTD2XX == 1 if (presto->buff_out_pos >= BUFFER_SIZE) #elif BUILD_PRESTO_LIBFTDI == 1 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 *bytes only!) */ if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128) #endif return presto_flush(); return ERROR_OK; } #if 0 static int presto_getbyte(void) { if (presto->buff_in_pos < presto->buff_in_len) return presto->buff_in[presto->buff_in_pos++]; if (presto->buff_in_exp == 0) return -1; if (presto_flush() != ERROR_OK) return -1; if (presto->buff_in_pos < presto->buff_in_len) return presto->buff_in[presto->buff_in_pos++]; return -1; } #endif /* -------------------------------------------------------------------------- */ static int presto_tdi_flush(void) { if (presto->jtag_tdi_count == 0) return 0; if (presto->jtag_tck == 0) { LOG_ERROR("BUG: unexpected TAP condition, TCK low"); return -1; } presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4; presto_sendbyte(presto->jtag_tdi_data); presto->jtag_tdi_count = 0; presto->jtag_tdi_data = 0; return 0; } static int presto_tck_idle(void) { if (presto->jtag_tck == 1) { presto_sendbyte(0xCA); presto->jtag_tck = 0; } return 0; } /* -------------------------------------------------------------------------- */ static int presto_bitq_out(int tms, int tdi, int tdo_req) { int i; unsigned char cmd; if (presto->jtag_tck == 0) presto_sendbyte(0xA4); /* LED idicator - JTAG active */ else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) { presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count; if (++presto->jtag_tdi_count == 4) presto_tdi_flush(); return 0; } presto_tdi_flush(); cmd = tdi ? 0xCB : 0xCA; presto_sendbyte(cmd); if (tms != presto->jtag_tms) { presto_sendbyte((tms ? 0xEC : 0xE8) | (presto->jtag_rst ? 0x02 : 0)); presto->jtag_tms = tms; } /* delay with TCK low */ for (i = presto->jtag_speed; i > 1; i--) presto_sendbyte(cmd); cmd |= 0x04; presto_sendbyte(cmd | (tdo_req ? 0x10 : 0)); /* delay with TCK high */ for (i = presto->jtag_speed; i > 1; i--) presto_sendbyte(cmd); presto->jtag_tck = 1; return 0; } static int presto_bitq_flush(void) { presto_tdi_flush(); presto_tck_idle(); presto_sendbyte(0xA0); /* LED idicator - JTAG idle */ return presto_flush(); } static int presto_bitq_in_rdy(void) { if (presto->buff_in_pos >= presto->buff_in_len) return 0; return presto->buff_in_len-presto->buff_in_pos; } static int presto_bitq_in(void) { if (presto->buff_in_pos >= presto->buff_in_len) return -1; if (presto->buff_in[presto->buff_in_pos++]&0x08) return 1; return 0; } static int presto_bitq_sleep(unsigned long us) { long waits; presto_tdi_flush(); presto_tck_idle(); if (us > 100000) { presto_bitq_flush(); jtag_sleep(us); return 0; } waits = us / 170 + 2; while (waits--) presto_sendbyte(0x80); return 0; } static int presto_bitq_reset(int trst, int srst) { presto_tdi_flush(); presto_tck_idle(); /* add a delay after possible TCK transition */ presto_sendbyte(0x80); presto_sendbyte(0x80); presto->jtag_rst = trst || srst; presto_sendbyte((presto->jtag_rst ? 0xEA : 0xE8) | (presto->jtag_tms ? 0x04 : 0)); return 0; } static struct bitq_interface presto_bitq = { .out = &presto_bitq_out, .flush = &presto_bitq_flush, .sleep = &presto_bitq_sleep, .reset = &presto_bitq_reset, .in_rdy = &presto_bitq_in_rdy, .in = &presto_bitq_in, }; /* -------------------------------------------------------------------------- */ static int presto_adapter_khz(int khz, int *jtag_speed) { if (khz < 0) { *jtag_speed = 0; return ERROR_COMMAND_SYNTAX_ERROR; } if (khz >= 3000) *jtag_speed = 0; else *jtag_speed = (1000 + khz-1)/khz; return 0; } static int presto_jtag_speed_div(int speed, int *khz) { if ((speed < 0) || (speed > 1000)) { *khz = 0; return ERROR_COMMAND_SYNTAX_ERROR; } if (speed == 0) *khz = 3000; else *khz = 1000/speed; return 0; } static int presto_jtag_speed(int speed) { int khz; if (presto_jtag_speed_div(speed, &khz)) return ERROR_COMMAND_SYNTAX_ERROR; presto->jtag_speed = speed; if (khz%1000 == 0) LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed, khz/1000); else LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed, khz); return 0; } static char *presto_serial; COMMAND_HANDLER(presto_handle_serial_command) { if (CMD_ARGC == 1) { if (presto_serial) free(presto_serial); presto_serial = strdup(CMD_ARGV[0]); } else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } static const struct command_registration presto_command_handlers[] = { { .name = "presto_serial", .handler = presto_handle_serial_command, .mode = COMMAND_CONFIG, .help = "Configure USB serial number of Presto device.", .usage = "serial_string", }, COMMAND_REGISTRATION_DONE }; static int presto_jtag_init(void) { if (presto_open(presto_serial) != ERROR_OK) { presto_close(); if (presto_serial != NULL) LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial); else LOG_ERROR("Cannot open PRESTO"); return ERROR_JTAG_INIT_FAILED; } LOG_INFO("PRESTO open, serial number '%s'", presto->serial); bitq_interface = &presto_bitq; return ERROR_OK; } static int presto_jtag_quit(void) { bitq_cleanup(); presto_close(); LOG_INFO("PRESTO closed"); if (presto_serial) { free(presto_serial); presto_serial = NULL; } return ERROR_OK; } struct jtag_interface presto_interface = { .name = "presto", .commands = presto_command_handlers, .execute_queue = bitq_execute_queue, .speed = presto_jtag_speed, .khz = presto_adapter_khz, .speed_div = presto_jtag_speed_div, .init = presto_jtag_init, .quit = presto_jtag_quit, }; openocd-0.9.0/src/jtag/drivers/gw16012.c0000644000175000017500000003302312315575360014445 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #if 1 #define _DEBUG_GW16012_IO_ #endif /* system includes */ /* -ino: 060521-1036 */ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define ioperm(startport, length, enable) \ 386_set_ioperm((startport), (length), (enable)) #else #endif /* __FreeBSD__, __FreeBSD_kernel__ */ #if PARPORT_USE_PPDEV == 1 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #define PPRSTATUS PPIGSTATUS #define PPWDATA PPISDATA #else #include #include #endif #include #include #else /* not PARPORT_USE_PPDEV */ #ifndef _WIN32 #include #endif #endif #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1 #include #endif /* configuration */ uint16_t gw16012_port; /* interface variables */ static uint8_t gw16012_msb; static uint8_t gw16012_control_value; #if PARPORT_USE_PPDEV == 1 static int device_handle; #endif static void gw16012_data(uint8_t value) { value = (value & 0x7f) | gw16012_msb; gw16012_msb ^= 0x80; /* toggle MSB */ #ifdef _DEBUG_GW16012_IO_ LOG_DEBUG("%2.2x", value); #endif #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &value); #else #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port, value); #else outb(value, gw16012_port); #endif #endif } static void gw16012_control(uint8_t value) { if (value != gw16012_control_value) { gw16012_control_value = value; #ifdef _DEBUG_GW16012_IO_ LOG_DEBUG("%2.2x", gw16012_control_value); #endif #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWCONTROL, &gw16012_control_value); #else #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port + 2, gw16012_control_value); #else outb(gw16012_control_value, gw16012_port + 2); #endif #endif } } static void gw16012_input(uint8_t *value) { #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPRSTATUS, value); #else *value = inb(gw16012_port + 1); #endif #ifdef _DEBUG_GW16012_IO_ LOG_DEBUG("%2.2x", *value); #endif } /* (1) assert or (0) deassert reset lines */ static void gw16012_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst == 0) gw16012_control(0x0d); else if (trst == 1) gw16012_control(0x0c); if (srst == 0) gw16012_control(0x0a); else if (srst == 1) gw16012_control(0x0b); } static void gw16012_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void gw16012_state_move(void) { int i = 0, tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); gw16012_control(0x0); /* single-bit mode */ for (i = 0; i < tms_count; i++) { tms = (tms_scan >> i) & 1; gw16012_data(tms << 1); /* output next TMS bit */ } tap_set_state(tap_get_end_state()); } static void gw16012_path_move(struct pathmove_command *cmd) { int num_states = cmd->num_states; int state_count; state_count = 0; while (num_states) { gw16012_control(0x0); /* single-bit mode */ if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) gw16012_data(0x0); /* TCK cycle with TMS low */ else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) gw16012_data(0x2); /* TCK cycle with TMS high */ else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); exit(-1); } tap_set_state(cmd->path[state_count]); state_count++; num_states--; } tap_set_end_state(tap_get_state()); } static void gw16012_runtest(int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); int i; /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { gw16012_end_state(TAP_IDLE); gw16012_state_move(); } for (i = 0; i < num_cycles; i++) { gw16012_control(0x0); /* single-bit mode */ gw16012_data(0x0); /* TMS cycle with TMS low */ } gw16012_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) gw16012_state_move(); } static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { int bits_left = scan_size; int bit_count = 0; tap_state_t saved_end_state = tap_get_end_state(); uint8_t scan_out, scan_in; /* only if we're not already in the correct Shift state */ if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { if (ir_scan) gw16012_end_state(TAP_IRSHIFT); else gw16012_end_state(TAP_DRSHIFT); gw16012_state_move(); gw16012_end_state(saved_end_state); } while (type == SCAN_OUT && ((bits_left - 1) > 7)) { gw16012_control(0x2); /* seven-bit mode */ scan_out = buf_get_u32(buffer, bit_count, 7); gw16012_data(scan_out); bit_count += 7; bits_left -= 7; } gw16012_control(0x0); /* single-bit mode */ while (bits_left-- > 0) { uint8_t tms = 0; scan_out = buf_get_u32(buffer, bit_count, 1); if (bits_left == 0) /* last bit */ { if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))) tms = 0; else tms = 2; } gw16012_data(scan_out | tms); if (type != SCAN_OUT) { gw16012_input(&scan_in); buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3)); } bit_count++; } if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))) { gw16012_data(0x0); if (ir_scan) tap_set_state(TAP_IRPAUSE); else tap_set_state(TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) gw16012_state_move(); } } static int gw16012_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; int retval; /* return ERROR_OK, unless a jtag_read_buffer returns a failed check * that wasn't handled by a caller-provided error handler */ retval = ERROR_OK; while (cmd) { switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif gw16012_end_state(cmd->cmd.runtest->end_state); gw16012_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif gw16012_end_state(cmd->cmd.statemove->end_state); gw16012_state_move(); break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif gw16012_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: gw16012_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr", type, scan_size, cmd->cmd.scan->end_state); #endif gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; if (buffer) free(buffer); break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); #endif jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return retval; } #if PARPORT_USE_GIVEIO == 1 static int gw16012_get_giveio_access(void) { HANDLE h; OSVERSIONINFO version; version.dwOSVersionInfoSize = sizeof version; if (!GetVersionEx(&version)) { errno = EINVAL; return -1; } if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0; h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { errno = ENODEV; return -1; } CloseHandle(h); return 0; } #endif #if PARPORT_USE_PPDEV == 1 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #define GW16012_PPDEV_NAME "ppi" static int gw16012_init_ioctls(void) { int temp = 0; temp = ioctl(device_handle, PPCLAIM); if (temp < 0) { LOG_ERROR("cannot claim device"); return ERROR_JTAG_INIT_FAILED; } temp = PARPORT_MODE_COMPAT; temp = ioctl(device_handle, PPSETMODE, &temp); if (temp < 0) { LOG_ERROR(" cannot set compatible mode to device"); return ERROR_JTAG_INIT_FAILED; } temp = IEEE1284_MODE_COMPAT; temp = ioctl(device_handle, PPNEGOT, &temp); if (temp < 0) { LOG_ERROR("cannot set compatible 1284 mode to device"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } #else #define GW16012_PPDEV_NAME "parport" static int gw16012_init_ioctls(void) { return ERROR_OK; } #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ static int gw16012_init_device(void) { const char *device_name = GW16012_PPDEV_NAME; char buffer[256]; if (device_handle > 0) { LOG_ERROR("device is already opened"); return ERROR_JTAG_INIT_FAILED; } snprintf(buffer, 256, "/dev/%s%d", device_name, gw16012_port); LOG_DEBUG("opening %s...", buffer); device_handle = open(buffer, O_WRONLY); if (device_handle < 0) { LOG_ERROR("cannot open device. check it exists and that user read and write rights are set"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...open"); if (gw16012_init_ioctls() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; return ERROR_OK; } #else /* PARPORT_USE_PPDEV */ static int gw16012_init_device(void) { if (gw16012_port == 0) { gw16012_port = 0x378; LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)"); } LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port)); #if PARPORT_USE_GIVEIO == 1 if (gw16012_get_giveio_access() != 0) { #else /* PARPORT_USE_GIVEIO */ if (ioperm(gw16012_port, 3, 1) != 0) { #endif /* PARPORT_USE_GIVEIO */ LOG_ERROR("missing privileges for direct i/o"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...privileges granted"); /* make sure parallel port is in right mode (clear tristate and interrupt */ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(gw16012_port + 2, 0x0); #else outb(0x0, gw16012_port + 2); #endif return ERROR_OK; } #endif /* PARPORT_USE_PPDEV */ static int gw16012_init(void) { uint8_t status_port; if (gw16012_init_device() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; gw16012_input(&status_port); gw16012_msb = (status_port & 0x80) ^ 0x80; gw16012_reset(0, 0); return ERROR_OK; } static int gw16012_quit(void) { return ERROR_OK; } COMMAND_HANDLER(gw16012_handle_parport_port_command) { if (CMD_ARGC == 1) { /* only if the port wasn't overwritten by cmdline */ if (gw16012_port == 0) COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], gw16012_port); else { LOG_ERROR("The parport port was already configured!"); return ERROR_FAIL; } } command_print(CMD_CTX, "parport port = %u", gw16012_port); return ERROR_OK; } static const struct command_registration gw16012_command_handlers[] = { { .name = "parport_port", .handler = gw16012_handle_parport_port_command, .mode = COMMAND_CONFIG, .help = "Display the address of the I/O port (e.g. 0x378) " "or the number of the '/dev/parport' device used. " "If a parameter is provided, first change that port.", .usage = "[port_number]", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface gw16012_interface = { .name = "gw16012", .commands = gw16012_command_handlers, .init = gw16012_init, .quit = gw16012_quit, .execute_queue = gw16012_execute_queue, }; openocd-0.9.0/src/jtag/drivers/usb_blaster/0000755000175000017500000000000012526202225015645 500000000000000openocd-0.9.0/src/jtag/drivers/usb_blaster/README.CheapClone0000644000175000017500000000565012315575360020464 00000000000000USB Blaster Cheap Clone ======================= The Altera USB Blaster has a cheap clone, based on : - a Cypress CY7C68013A-56PVXC as the main chip - a 74HC244D as the output latch - a 24 MHz quartz - a EEPROM 24C64BN The schematics (cut down to essential) is : /-----------------+----------------------\ +--------------+ | | | USB--| CY7C68013A | | +----------+ | | | | | | 74HC244D | | | . . | | | | | . . \--o 1 20 o | 10 pins header | | 47 o-- TCK --o 2 19 o---/ +-------+ | | 46 o-- TDO --o 3 18 o-- TCK -----o 1 2 o | | 45 o-- TMS --o 4 17 o-- TDO -----o 3 4 o | | 44 o o 5 16 o-- TMS -----o 5 6 o | | 43 o-- o 6 15 o o 7 8 o | | 42 o-- o 7 14 o +--o 9 10 o | | 41 o-- TDI --o 8 13 o-- ? | +-------+ | . 40 o-- nOE \ o 9 12 o-- TDI --+ | . . | o 10 11 o | o 28 29 o | | | | | | | +----------+ | +--------------+ \ | ---------------------------------------/ From this one can deduce that : - the cypress emulates the Altera chip - as the cypress pins used are 41-47, all output/input are controlled by 8051 PortA. - as the 8051 is clocked at 24Mhz, and because each USB byte is handled by the 8051, assuming a 40 instruction cycles per USB packet, the maximum throughput would be around 500 kHz. Pinout ====== Port A.0: nOE (output enable of 74HC244D) Port A.1: TDI Port A.5: TMS Port A.6: TDO Port A.7: TCK Throughput considerations ========================= Mesurements on a scope reveal that : - for bitbang mode, the throughtput is 56.5 kbits/s (as each clock transition is mesured at 17.7us) - for byteshift mode, the throughput is 107.7 kbits/s (as 63 bits TDI transmission is mesured in 585 us) Let's suppose that to upload a 32 bits value, it is necessary to : - move from IDLE to DR-SHIFT : 3 bitbang (3 TMS transitions) - input the 32 bits of data : 1 byteshift (24 bits) + 8 bitbang (8 bits) - move from DR-SHIFT to IDLE : 5 bitbang (5 TMS transitions) So for this 32 bits of data, the time would be : 3 * 17.7us + 1 * 585us/63*24 + 5 * 17.7us = 53.1us + 222us + 88.5us = 363us Throughtput in bit/s: 32 * (1 / 363E-6) = 88000 bits/s Throughtput in bytes/s: 11kBytes/s Conclusion ========== Contrary to the original USB Blaster, the cheap clone will never reach high transfer speeds over JTAG. openocd-0.9.0/src/jtag/drivers/usb_blaster/usb_blaster.c0000644000175000017500000007037712516456302020262 00000000000000/* * Driver for USB-JTAG, Altera USB-Blaster and compatibles * * Inspired from original code from Kolja Waschk's USB-JTAG project * (http://www.ixo.de/info/usb_jtag/), and from openocd project. * * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr * Copyright (C) 2011 Ali Lown ali@lown.me.uk * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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. * */ /* * The following information is originally from Kolja Waschk's USB-JTAG, * where it was obtained by reverse engineering an Altera USB-Blaster. * See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and * usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol. * * The same information is also on the UrJTAG mediawiki, with some additional * notes on bits marked as "unknown" by usb_jtag. * (http://sourceforge.net/apps/mediawiki/urjtag/index.php? * title=Cable_Altera_USB-Blaster) * * USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as * an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol: * * _________ * | | * | AT93C46 | * |_________| * __|__________ _________ * | | | | * USB__| FTDI 245BM |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK) * |_____________| |_________| * __|__________ _|___________ * | | | | * | 6 MHz XTAL | | 24 MHz Osc. | * |_____________| |_____________| * * USB-JTAG, Altera USB-Blaster II are typically implemented as a Cypress * EZ-USB FX2LP followed by a CPLD. * _____________ _________ * | | | | * USB__| EZ-USB FX2 |__| EPM570 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK) * |_____________| |_________| * __|__________ * | | * | 24 MHz XTAL | * |_____________| */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if IS_CYGWIN == 1 #include "windows.h" #undef LOG_ERROR #endif /* project specific includes */ #include #include #include #include "ublast_access.h" /* system includes */ #include #include #include #include #include /* Size of USB endpoint max packet size, ie. 64 bytes */ #define MAX_PACKET_SIZE 64 /* * Size of data buffer that holds bytes in byte-shift mode. * This buffer can hold multiple USB packets aligned to * MAX_PACKET_SIZE bytes boundaries. * BUF_LEN must be grater than or equal MAX_PACKET_SIZE. */ #define BUF_LEN 4096 /* USB-Blaster II specific command */ #define CMD_COPY_TDO_BUFFER 0x5F enum gpio_steer { FIXED_0 = 0, FIXED_1, SRST, TRST, }; struct ublast_info { enum gpio_steer pin6; enum gpio_steer pin8; int tms; int tdi; bool trst_asserted; bool srst_asserted; uint8_t buf[BUF_LEN]; int bufidx; char *lowlevel_name; struct ublast_lowlevel *drv; char *ublast_device_desc; uint16_t ublast_vid, ublast_pid; uint16_t ublast_vid_uninit, ublast_pid_uninit; int flags; char *firmware_path; }; /* * Global device control */ static struct ublast_info info = { .ublast_vid = 0x09fb, /* Altera */ .ublast_pid = 0x6001, /* USB-Blaster */ .lowlevel_name = NULL, .srst_asserted = false, .trst_asserted = false, .pin6 = FIXED_1, .pin8 = FIXED_1, }; /* * Available lowlevel drivers (FTDI, FTD2xx, ...) */ struct drvs_map { char *name; struct ublast_lowlevel *(*drv_register)(void); }; static struct drvs_map lowlevel_drivers_map[] = { #if BUILD_USB_BLASTER_LIBFTDI { .name = "ftdi", .drv_register = ublast_register_ftdi }, #endif #if BUILD_USB_BLASTER_FTD2XX { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx }, #endif #if BUILD_USB_BLASTER_2 { .name = "ublast2", .drv_register = ublast2_register_libusb }, #endif { NULL, NULL }, }; /* * Access functions to lowlevel driver, agnostic of libftdi/libftdxx */ static char *hexdump(uint8_t *buf, unsigned int size) { unsigned int i; char *str = calloc(size * 2 + 1, 1); for (i = 0; i < size; i++) sprintf(str + 2*i, "%02x", buf[i]); return str; } static int ublast_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) { int ret = info.drv->read(info.drv, buf, size, bytes_read); char *str = hexdump(buf, *bytes_read); DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str, *bytes_read); free(str); return ret; } static int ublast_buf_write(uint8_t *buf, int size, uint32_t *bytes_written) { int ret = info.drv->write(info.drv, buf, size, bytes_written); char *str = hexdump(buf, *bytes_written); DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str, *bytes_written); free(str); return ret; } static int nb_buf_remaining(void) { return BUF_LEN - info.bufidx; } static void ublast_flush_buffer(void) { unsigned int retlen; int nb = info.bufidx, ret = ERROR_OK; while (ret == ERROR_OK && nb > 0) { ret = ublast_buf_write(info.buf, nb, &retlen); nb -= retlen; } info.bufidx = 0; } /* * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data * bits (bidirectional) in a single USB packet. A header byte has to be sent as * the first byte in a packet with the following meaning: * * Bit 7 (0x80): Must be set to indicate byte-shift mode. * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write. * Bit 5..0: Define the number N of following bytes * * All N following bytes will then be clocked out serially on TDI. If Bit 6 was * set, it will afterwards return N bytes with TDO data read while clocking out * the TDI data. LSB of the first byte after the header byte will appear first * on TDI. */ /* Simple bit banging mode: * * Bit 7 (0x80): Must be zero (see byte-shift mode above) * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO * in return. * Bit 5 (0x20): Output Enable/LED. * Bit 4 (0x10): TDI Output. * Bit 3 (0x08): nCS Output (not used in JTAG mode). * Bit 2 (0x04): nCE Output (not used in JTAG mode). * Bit 1 (0x02): TMS Output. * Bit 0 (0x01): TCK Output. * * For transmitting a single data bit, you need to write two bytes (one for * setting up TDI/TMS/TCK=0, and one to trigger TCK high with same TDI/TMS * held). Up to 64 bytes can be combined in a single USB packet. * It isn't possible to read a data without transmitting data. */ #define TCK (1 << 0) #define TMS (1 << 1) #define NCE (1 << 2) #define NCS (1 << 3) #define TDI (1 << 4) #define LED (1 << 5) #define READ (1 << 6) #define SHMODE (1 << 7) #define READ_TDO (1 << 0) /** * ublast_queue_byte - queue one 'bitbang mode' byte for USB Blaster * @abyte: the byte to queue * * Queues one byte in 'bitbang mode' to the USB Blaster. The byte is not * actually sent, but stored in a buffer. The write is performed once * the buffer is filled, or if an explicit ublast_flush_buffer() is called. */ static void ublast_queue_byte(uint8_t abyte) { if (nb_buf_remaining() < 1) ublast_flush_buffer(); info.buf[info.bufidx++] = abyte; if (nb_buf_remaining() == 0) ublast_flush_buffer(); DEBUG_JTAG_IO("(byte=0x%02x)", abyte); } /** * ublast_compute_pin - compute if gpio should be asserted * @steer: control (ie. TRST driven, SRST driven, of fixed) * * Returns pin value (1 means driven high, 0 mean driven low) */ bool ublast_compute_pin(enum gpio_steer steer) { switch (steer) { case FIXED_0: return 0; case FIXED_1: return 1; case SRST: return !info.srst_asserted; case TRST: return !info.trst_asserted; default: return 1; } } /** * ublast_build_out - build bitbang mode output byte * @type: says if reading back TDO is required * * Returns the compute bitbang mode byte */ static uint8_t ublast_build_out(enum scan_type type) { uint8_t abyte = 0; abyte |= info.tms ? TMS : 0; abyte |= ublast_compute_pin(info.pin6) ? NCE : 0; abyte |= ublast_compute_pin(info.pin8) ? NCS : 0; abyte |= info.tdi ? TDI : 0; abyte |= LED; if (type == SCAN_IN || type == SCAN_IO) abyte |= READ; return abyte; } /** * ublast_reset - reset the JTAG device is possible * @trst: 1 if TRST is to be asserted * @srst: 1 if SRST is to be asserted */ static void ublast_reset(int trst, int srst) { uint8_t out_value; info.trst_asserted = trst; info.srst_asserted = srst; out_value = ublast_build_out(SCAN_OUT); ublast_queue_byte(out_value); ublast_flush_buffer(); } /** * ublast_clock_tms - clock a TMS transition * @tms: the TMS to be sent * * Triggers a TMS transition (ie. one JTAG TAP state move). */ static void ublast_clock_tms(int tms) { uint8_t out; DEBUG_JTAG_IO("(tms=%d)", !!tms); info.tms = !!tms; info.tdi = 0; out = ublast_build_out(SCAN_OUT); ublast_queue_byte(out); ublast_queue_byte(out | TCK); } /** * ublast_idle_clock - put back TCK to low level * * See ublast_queue_tdi() comment for the usage of this function. */ static void ublast_idle_clock(void) { uint8_t out = ublast_build_out(SCAN_OUT); DEBUG_JTAG_IO("."); ublast_queue_byte(out); } /** * ublast_clock_tdi - Output a TDI with bitbang mode * @tdi: the TDI bit to be shifted out * @type: scan type (ie. does a readback of TDO is required) * * Output a TDI bit and assert clock to push it into the JTAG device : * - writing out TCK=0, TMS==0, TDI= * - writing out TCK=1, TMS=, TDI= which triggers the JTAG * device aquiring the data. * * If a TDO is to be read back, the required read is requested (bitbang mode), * and the USB Blaster will send back a byte with bit0 reprensenting the TDO. */ static void ublast_clock_tdi(int tdi, enum scan_type type) { uint8_t out; DEBUG_JTAG_IO("(tdi=%d)", !!tdi); info.tdi = !!tdi; out = ublast_build_out(SCAN_OUT); ublast_queue_byte(out); out = ublast_build_out(type); ublast_queue_byte(out | TCK); } /** * ublast_clock_tdi_flip_tms - Output a TDI with bitbang mode, change JTAG state * @tdi: the TDI bit to be shifted out * @type: scan type (ie. does a readback of TDO is required) * * This function is the same as ublast_clock_tdi(), but it changes also the TMS * while outputing the TDI. This should be the last TDI output of a TDI * sequence, which will change state from : * - IRSHIFT -> IREXIT1 * - or DRSHIFT -> DREXIT1 */ static void ublast_clock_tdi_flip_tms(int tdi, enum scan_type type) { uint8_t out; DEBUG_JTAG_IO("(tdi=%d)", !!tdi); info.tdi = !!tdi; info.tms = !info.tms; out = ublast_build_out(SCAN_OUT); ublast_queue_byte(out); out = ublast_build_out(type); ublast_queue_byte(out | TCK); out = ublast_build_out(SCAN_OUT); ublast_queue_byte(out); } /** * ublast_queue_bytes - queue bytes for the USB Blaster * @bytes: byte array * @nb_bytes: number of bytes * * Queues bytes to be sent to the USB Blaster. The bytes are not * actually sent, but stored in a buffer. The write is performed once * the buffer is filled, or if an explicit ublast_flush_buffer() is called. */ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) { if (info.bufidx + nb_bytes > BUF_LEN) { LOG_ERROR("buggy code, should never queue more that %d bytes", info.bufidx + nb_bytes); exit(-1); } DEBUG_JTAG_IO("(nb_bytes=%d, bytes=[0x%02x, ...])", nb_bytes, bytes ? bytes[0] : 0); if (bytes) memcpy(&info.buf[info.bufidx], bytes, nb_bytes); else memset(&info.buf[info.bufidx], 0, nb_bytes); info.bufidx += nb_bytes; if (nb_buf_remaining() == 0) ublast_flush_buffer(); } /** * ublast_tms_seq - write a TMS sequence transition to JTAG * @bits: TMS bits to be written (bit0, bit1 .. bitN) * @nb_bits: number of TMS bits (between 1 and 8) * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=, TDI= * - writing out TCK=1, TMS=, TDI= which triggers the transition * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ static void ublast_tms_seq(const uint8_t *bits, int nb_bits) { int i; DEBUG_JTAG_IO("(bits=%02x..., nb_bits=%d)", bits[0], nb_bits); for (i = 0; i < nb_bits; i++) ublast_clock_tms((bits[i / 8] >> (i % 8)) & 0x01); ublast_idle_clock(); } /** * ublast_tms - write a tms command * @cmd: tms command */ static void ublast_tms(struct tms_command *cmd) { DEBUG_JTAG_IO("(num_bits=%d)", cmd->num_bits); ublast_tms_seq(cmd->bits, cmd->num_bits); } /** * ublast_path_move - write a TMS sequence transition to JTAG * @cmd: path transition * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=, TDI= * - writing out TCK=1, TMS=, TDI= which triggers the transition * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ static void ublast_path_move(struct pathmove_command *cmd) { int i; DEBUG_JTAG_IO("(num_states=%d, last_state=%d)", cmd->num_states, cmd->path[cmd->num_states - 1]); for (i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) ublast_clock_tms(0); if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) ublast_clock_tms(1); tap_set_state(cmd->path[i]); } ublast_idle_clock(); } /** * ublast_state_move - move JTAG state to the target state * @state: the target state * * Input the correct TMS sequence to the JTAG TAP so that we end up in the * target state. This assumes the current state (tap_get_state()) is correct. */ static void ublast_state_move(tap_state_t state) { uint8_t tms_scan; int tms_len; DEBUG_JTAG_IO("(from %s to %s)", tap_state_name(tap_get_state()), tap_state_name(state)); if (tap_get_state() == state) return; tms_scan = tap_get_tms_path(tap_get_state(), state); tms_len = tap_get_tms_path_len(tap_get_state(), state); ublast_tms_seq(&tms_scan, tms_len); tap_set_state(state); } /** * ublast_read_byteshifted_tdos - read TDO of byteshift writes * @buf: the buffer to store the bits * @nb_bits: the number of bits * * Reads back from USB Blaster TDO bits, triggered by a 'byteshift write', ie. eight * bits per received byte from USB interface, and store them in buffer. * * As the USB blaster stores the TDO bits in LSB (ie. first bit in (byte0, * bit0), second bit in (byte0, bit1), ...), which is what we want to return, * simply read bytes from USB interface and store them. * * Returns ERROR_OK if OK, ERROR_xxx if a read error occured */ static int ublast_read_byteshifted_tdos(uint8_t *buf, int nb_bytes) { unsigned int retlen; int ret = ERROR_OK; DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bytes * 8); ublast_flush_buffer(); while (ret == ERROR_OK && nb_bytes > 0) { ret = ublast_buf_read(buf, nb_bytes, &retlen); nb_bytes -= retlen; } return ret; } /** * ublast_read_bitbang_tdos - read TDO of bitbang writes * @buf: the buffer to store the bits * @nb_bits: the number of bits * * Reads back from USB Blaster TDO bits, triggered by a 'bitbang write', ie. one * bit per received byte from USB interface, and store them in buffer, where : * - first bit is stored in byte0, bit0 (LSB) * - second bit is stored in byte0, bit 1 * ... * - eight bit is sotred in byte0, bit 7 * - ninth bit is sotred in byte1, bit 0 * - etc ... * * Returns ERROR_OK if OK, ERROR_xxx if a read error occured */ static int ublast_read_bitbang_tdos(uint8_t *buf, int nb_bits) { int nb1 = nb_bits; int i, ret = ERROR_OK; unsigned int retlen; uint8_t tmp[8]; DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bits); /* * Ensure all previous bitbang writes were issued to the dongle, so that * it returns back the read values. */ ublast_flush_buffer(); ret = ublast_buf_read(tmp, nb1, &retlen); for (i = 0; ret == ERROR_OK && i < nb1; i++) if (tmp[i] & READ_TDO) *buf |= (1 << i); else *buf &= ~(1 << i); return ret; } /** * ublast_queue_tdi - short description * @bits: bits to be queued on TDI (or NULL if 0 are to be queued) * @nb_bits: number of bits * @scan: scan type (ie. if TDO read back is required or not) * * Outputs a serie of TDI bits on TDI. * As a side effect, the last TDI bit is sent along a TMS=1, and triggers a JTAG * TAP state shift if input bits were non NULL. * * In order to not saturate the USB Blaster queues, this method reads back TDO * if the scan type requests it, and stores them back in bits. * * As a side note, the state of TCK when entering this function *must* be * low. This is because byteshift mode outputs TDI on rising TCK and reads TDO * on falling TCK if and only if TCK is low before queuing byteshift mode bytes. * If TCK was high, the USB blaster will queue TDI on falling edge, and read TDO * on rising edge !!! */ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) { int nb8 = nb_bits / 8; int nb1 = nb_bits % 8; int nbfree_in_packet, i, trans = 0, read_tdos; uint8_t *tdos = calloc(1, nb_bits / 8 + 1); static uint8_t byte0[BUF_LEN]; /* * As the last TDI bit should always be output in bitbang mode in order * to activate the TMS=1 transition to EXIT_?R state. Therefore a * situation where nb_bits is a multiple of 8 is handled as follows: * - the number of TDI shifted out in "byteshift mode" is 8 less than * nb_bits * - nb1 = 8 * This ensures that nb1 is never 0, and allows the TMS transition. */ if (nb8 > 0 && nb1 == 0) { nb8--; nb1 = 8; } read_tdos = (scan == SCAN_IN || scan == SCAN_IO); for (i = 0; i < nb8; i += trans) { /* * Calculate number of bytes to fill USB packet of size MAX_PACKET_SIZE */ nbfree_in_packet = (MAX_PACKET_SIZE - (info.bufidx%MAX_PACKET_SIZE)); trans = MIN(nbfree_in_packet - 1, nb8 - i); /* * Queue a byte-shift mode transmission, with as many bytes as * is possible with regard to : * - current filling level of write buffer * - remaining bytes to write in byte-shift mode */ if (read_tdos) ublast_queue_byte(SHMODE | READ | trans); else ublast_queue_byte(SHMODE | trans); if (bits) ublast_queue_bytes(&bits[i], trans); else ublast_queue_bytes(byte0, trans); if (read_tdos) { if (info.flags & COPY_TDO_BUFFER) ublast_queue_byte(CMD_COPY_TDO_BUFFER); ublast_read_byteshifted_tdos(&tdos[i], trans); } } /* * Queue the remaining TDI bits in bitbang mode. */ for (i = 0; i < nb1; i++) { int tdi = bits ? bits[nb8 + i / 8] & (1 << i) : 0; if (bits && i == nb1 - 1) ublast_clock_tdi_flip_tms(tdi, scan); else ublast_clock_tdi(tdi, scan); } if (nb1 && read_tdos) { if (info.flags & COPY_TDO_BUFFER) ublast_queue_byte(CMD_COPY_TDO_BUFFER); ublast_read_bitbang_tdos(&tdos[nb8], nb1); } if (bits) memcpy(bits, tdos, DIV_ROUND_UP(nb_bits, 8)); free(tdos); /* * Ensure clock is in lower state */ ublast_idle_clock(); } static void ublast_runtest(int cycles, tap_state_t state) { DEBUG_JTAG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); ublast_state_move(TAP_IDLE); ublast_queue_tdi(NULL, cycles, SCAN_OUT); ublast_state_move(state); } static void ublast_stableclocks(int cycles) { DEBUG_JTAG_IO("%s(cycles=%i)", __func__, cycles); ublast_queue_tdi(NULL, cycles, SCAN_OUT); } /** * ublast_scan - launches a DR-scan or IR-scan * @cmd: the command to launch * * Launch a JTAG IR-scan or DR-scan * * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured. */ static int ublast_scan(struct scan_command *cmd) { int scan_bits; uint8_t *buf = NULL; enum scan_type type; int ret = ERROR_OK; static const char * const type2str[] = { "", "SCAN_IN", "SCAN_OUT", "SCAN_IO" }; char *log_buf = NULL; type = jtag_scan_type(cmd); scan_bits = jtag_build_buffer(cmd, &buf); if (cmd->ir_scan) ublast_state_move(TAP_IRSHIFT); else ublast_state_move(TAP_DRSHIFT); log_buf = hexdump(buf, DIV_ROUND_UP(scan_bits, 8)); DEBUG_JTAG_IO("%s(scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d)", __func__, cmd->ir_scan ? "IRSCAN" : "DRSCAN", type2str[type], scan_bits, log_buf, cmd->end_state); free(log_buf); ublast_queue_tdi(buf, scan_bits, type); /* * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it * forward to a stable IRPAUSE or DRPAUSE. */ ublast_clock_tms(0); if (cmd->ir_scan) tap_set_state(TAP_IRPAUSE); else tap_set_state(TAP_DRPAUSE); ret = jtag_read_buffer(buf, cmd); if (buf) free(buf); ublast_state_move(cmd->end_state); return ret; } static void ublast_usleep(int us) { DEBUG_JTAG_IO("%s(us=%d)", __func__, us); jtag_sleep(us); } static void ublast_initial_wipeout(void) { static uint8_t tms_reset = 0xff; uint8_t out_value; uint32_t retlen; int i; out_value = ublast_build_out(SCAN_OUT); for (i = 0; i < BUF_LEN; i++) info.buf[i] = out_value | ((i % 2) ? TCK : 0); /* * Flush USB-Blaster queue fifos * - empty the write FIFO (128 bytes) * - empty the read FIFO (384 bytes) */ ublast_buf_write(info.buf, BUF_LEN, &retlen); /* * Put JTAG in RESET state (five 1 on TMS) */ ublast_tms_seq(&tms_reset, 5); tap_set_state(TAP_RESET); } static int ublast_execute_queue(void) { struct jtag_command *cmd; static int first_call = 1; int ret = ERROR_OK; if (first_call) { first_call--; ublast_initial_wipeout(); } for (cmd = jtag_command_queue; ret == ERROR_OK && cmd != NULL; cmd = cmd->next) { switch (cmd->type) { case JTAG_RESET: ublast_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: ublast_runtest(cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); break; case JTAG_STABLECLOCKS: ublast_stableclocks(cmd->cmd.stableclocks->num_cycles); break; case JTAG_TLR_RESET: ublast_state_move(cmd->cmd.statemove->end_state); break; case JTAG_PATHMOVE: ublast_path_move(cmd->cmd.pathmove); break; case JTAG_TMS: ublast_tms(cmd->cmd.tms); break; case JTAG_SLEEP: ublast_usleep(cmd->cmd.sleep->us); break; case JTAG_SCAN: ret = ublast_scan(cmd->cmd.scan); break; } } ublast_flush_buffer(); return ret; } /** * ublast_init - Initialize the Altera device * * Initialize the device : * - open the USB device * - pretend it's initialized while actual init is delayed until first jtag command * * Returns ERROR_OK if USB device found, error if not. */ static int ublast_init(void) { int ret, i; if (info.lowlevel_name) { for (i = 0; lowlevel_drivers_map[i].name; i++) if (!strcmp(lowlevel_drivers_map[i].name, info.lowlevel_name)) break; if (lowlevel_drivers_map[i].name) info.drv = lowlevel_drivers_map[i].drv_register(); if (!info.drv) { LOG_ERROR("no lowlevel driver found for %s or lowlevel driver opening error", info.lowlevel_name); return ERROR_JTAG_DEVICE_ERROR; } } else { LOG_INFO("No lowlevel driver configured, will try them all"); for (i = 0; !info.drv && lowlevel_drivers_map[i].name; i++) info.drv = lowlevel_drivers_map[i].drv_register(); if (!info.drv) { LOG_ERROR("no lowlevel driver found"); return ERROR_JTAG_DEVICE_ERROR; } info.lowlevel_name = strdup(lowlevel_drivers_map[i-1].name); } /* * Register the lowlevel driver */ info.drv->ublast_vid = info.ublast_vid; info.drv->ublast_pid = info.ublast_pid; info.drv->ublast_vid_uninit = info.ublast_vid_uninit; info.drv->ublast_pid_uninit = info.ublast_pid_uninit; info.drv->ublast_device_desc = info.ublast_device_desc; info.drv->firmware_path = info.firmware_path; info.flags |= info.drv->flags; ret = info.drv->open(info.drv); /* * Let lie here : the TAP is in an unknown state, but the first * execute_queue() will trigger a ublast_initial_wipeout(), which will * put the TAP in RESET. */ tap_set_state(TAP_RESET); return ret; } /** * ublast_quit - Release the Altera device * * Releases the device : * - put the device pins in 'high impedance' mode * - close the USB device * * Returns always ERROR_OK */ static int ublast_quit(void) { uint8_t byte0 = 0; unsigned int retlen; ublast_buf_write(&byte0, 1, &retlen); return info.drv->close(info.drv); } COMMAND_HANDLER(ublast_handle_device_desc_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; info.ublast_device_desc = strdup(CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(ublast_handle_vid_pid_command) { if (CMD_ARGC > 4) { LOG_WARNING("ignoring extra IDs in ublast_vid_pid " "(maximum is 2 pairs)"); CMD_ARGC = 4; } if (CMD_ARGC >= 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], info.ublast_vid); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], info.ublast_pid); } else { LOG_WARNING("incomplete ublast_vid_pid configuration"); } if (CMD_ARGC == 4) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], info.ublast_vid_uninit); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], info.ublast_pid_uninit); } else { LOG_WARNING("incomplete ublast_vid_pid configuration"); } return ERROR_OK; } COMMAND_HANDLER(ublast_handle_pin_command) { uint8_t out_value; const char * const pin_name = CMD_ARGV[0]; enum gpio_steer *steer = NULL; static const char * const pin_val_str[] = { [FIXED_0] = "0", [FIXED_1] = "1", [SRST] = "SRST driven", [TRST] = "TRST driven", }; if (CMD_ARGC > 2) { LOG_ERROR("%s takes exactly one or two arguments", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } if (!strcmp(pin_name, "pin6")) steer = &info.pin6; if (!strcmp(pin_name, "pin8")) steer = &info.pin8; if (!steer) { LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } if (CMD_ARGC == 1) { LOG_INFO("%s: %s is set as %s\n", CMD_NAME, pin_name, pin_val_str[*steer]); } if (CMD_ARGC == 2) { const char * const pin_value = CMD_ARGV[1]; char val = pin_value[0]; if (strlen(pin_value) > 1) val = '?'; switch (tolower((unsigned char)val)) { case '0': *steer = FIXED_0; break; case '1': *steer = FIXED_1; break; case 't': *steer = TRST; break; case 's': *steer = SRST; break; default: LOG_ERROR("%s: pin value must be 0, 1, s (SRST) or t (TRST)", pin_value); return ERROR_COMMAND_SYNTAX_ERROR; } if (info.drv) { out_value = ublast_build_out(SCAN_OUT); ublast_queue_byte(out_value); ublast_flush_buffer(); } } return ERROR_OK; } COMMAND_HANDLER(ublast_handle_lowlevel_drv_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; info.lowlevel_name = strdup(CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(ublast_firmware_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; info.firmware_path = strdup(CMD_ARGV[0]); return ERROR_OK; } static const struct command_registration ublast_command_handlers[] = { { .name = "usb_blaster_device_desc", .handler = ublast_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the USB-Blaster", .usage = "description-string", }, { .name = "usb_blaster_vid_pid", .handler = ublast_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the USB-Blaster and " \ "vendor ID and product ID of the uninitialized device " \ "for USB-Blaster II", .usage = "vid pid vid_uninit pid_uninit", }, { .name = "usb_blaster_lowlevel_driver", .handler = ublast_handle_lowlevel_drv_command, .mode = COMMAND_CONFIG, .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)", .usage = "(ftdi|ftd2xx|ublast2)", }, { .name = "usb_blaster_pin", .handler = ublast_handle_pin_command, .mode = COMMAND_ANY, .help = "show or set pin state for the unused GPIO pins", .usage = "(pin6|pin8) (0|1|s|t)", }, { .name = "usb_blaster_firmware", .handler = &ublast_firmware_command, .mode = COMMAND_CONFIG, .help = "configure the USB-Blaster II firmware location", .usage = "path/to/blaster_xxxx.hex", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface usb_blaster_interface = { .name = "usb_blaster", .commands = ublast_command_handlers, .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = ublast_execute_queue, .init = ublast_init, .quit = ublast_quit, }; openocd-0.9.0/src/jtag/drivers/usb_blaster/ublast_access.h0000644000175000017500000000466612315575360020576 00000000000000/* * Driver for USB-JTAG, Altera USB-Blaster and compatibles * * Inspired from original code from Kolja Waschk's USB-JTAG project * (http://www.ixo.de/info/usb_jtag/), and from openocd project. * * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr * Copyright (C) 2011 Ali Lown ali@lown.me.uk * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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. * */ #ifndef JTAG_UBLAST_ACCESS_H #define JTAG_UBLAST_ACCESS_H #include /* Low level flags */ #define COPY_TDO_BUFFER (1 << 0) struct ublast_lowlevel { uint16_t ublast_vid; uint16_t ublast_pid; uint16_t ublast_vid_uninit; uint16_t ublast_pid_uninit; char *ublast_device_desc; struct jtag_libusb_device_handle *libusb_dev; char *firmware_path; int (*write)(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written); int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read); int (*open)(struct ublast_lowlevel *low); int (*close)(struct ublast_lowlevel *low); int (*speed)(struct ublast_lowlevel *low, int speed); void *priv; int flags; }; /** * ublast_register_ftdi - get a lowlevel USB Blaster driver * ublast_register_ftd2xx - get a lowlevel USB Blaster driver * ublast2_register_libusb - get a lowlevel USB Blaster II driver * * Get a lowlevel USB-Blaster driver. In the current implementation, there are 3 * possible lowlevel drivers : * - one based on libftdi from ftdichip.com * - one based on libftdxx, the free alternative * - one based on libusb, specific to the USB-Blaster II * * Returns the lowlevel driver structure. */ extern struct ublast_lowlevel *ublast_register_ftdi(void); extern struct ublast_lowlevel *ublast_register_ftd2xx(void); extern struct ublast_lowlevel *ublast2_register_libusb(void); #endif /* JTAG_UBLAST_ACCESS_H */ openocd-0.9.0/src/jtag/drivers/usb_blaster/Makefile.am0000644000175000017500000000102112327155503017620 00000000000000include $(top_srcdir)/common.mk AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) noinst_LTLIBRARIES = libocdusbblaster.la libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) USB_BLASTER_SRC = usb_blaster.c if USB_BLASTER_LIBFTDI USB_BLASTER_SRC += ublast_access_ftdi.c endif if USB_BLASTER_FTD2XX USB_BLASTER_SRC += ublast_access_ftd2xx.c endif if USB_BLASTER_2 USB_BLASTER_SRC += ublast2_access_libusb.c endif noinst_HEADERS = ublast_access.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/jtag/drivers/usb_blaster/Makefile.in0000644000175000017500000004603112526201650017637 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @USB_BLASTER_LIBFTDI_TRUE@am__append_2 = ublast_access_ftdi.c @USB_BLASTER_FTD2XX_TRUE@am__append_3 = ublast_access_ftd2xx.c @USB_BLASTER_2_TRUE@am__append_4 = ublast2_access_libusb.c subdir = src/jtag/drivers/usb_blaster ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdusbblaster_la_LIBADD = am__libocdusbblaster_la_SOURCES_DIST = usb_blaster.c \ ublast_access_ftdi.c ublast_access_ftd2xx.c \ ublast2_access_libusb.c @USB_BLASTER_LIBFTDI_TRUE@am__objects_1 = ublast_access_ftdi.lo @USB_BLASTER_FTD2XX_TRUE@am__objects_2 = ublast_access_ftd2xx.lo @USB_BLASTER_2_TRUE@am__objects_3 = ublast2_access_libusb.lo am__objects_4 = usb_blaster.lo $(am__objects_1) $(am__objects_2) \ $(am__objects_3) am_libocdusbblaster_la_OBJECTS = $(am__objects_4) libocdusbblaster_la_OBJECTS = $(am_libocdusbblaster_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdusbblaster_la_SOURCES) DIST_SOURCES = $(am__libocdusbblaster_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) \ -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) \ $(LIBFTDI_CFLAGS) noinst_LTLIBRARIES = libocdusbblaster.la libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) USB_BLASTER_SRC = usb_blaster.c $(am__append_2) $(am__append_3) \ $(am__append_4) noinst_HEADERS = ublast_access.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/jtag/drivers/usb_blaster/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/jtag/drivers/usb_blaster/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libocdusbblaster.la: $(libocdusbblaster_la_OBJECTS) $(libocdusbblaster_la_DEPENDENCIES) $(EXTRA_libocdusbblaster_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdusbblaster_la_OBJECTS) $(libocdusbblaster_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ublast2_access_libusb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ublast_access_ftd2xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ublast_access_ftdi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb_blaster.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c0000644000175000017500000000676212315575360021576 00000000000000/* * Driver for USB-JTAG, Altera USB-Blaster and compatibles * * Inspired from original code from Kolja Waschk's USB-JTAG project * (http://www.ixo.de/info/usb_jtag/), and from openocd project. * * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr * Copyright (C) 2011 Ali Lown ali@lown.me.uk * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "ublast_access.h" #include static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low) { return low->priv; } static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read) { int retval; int timeout = 100; struct ftdi_context *ftdic = ublast_getftdic(low); *bytes_read = 0; while ((*bytes_read < size) && timeout--) { retval = ftdi_read_data(ftdic, buf + *bytes_read, size - *bytes_read); if (retval < 0) { *bytes_read = 0; LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(ftdic)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += retval; } return ERROR_OK; } static int ublast_ftdi_write(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written) { int retval; struct ftdi_context *ftdic = ublast_getftdic(low); retval = ftdi_write_data(ftdic, buf, size); if (retval < 0) { *bytes_written = 0; LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(ftdic)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written = retval; return ERROR_OK; } static int ublast_ftdi_init(struct ublast_lowlevel *low) { uint8_t latency_timer; struct ftdi_context *ftdic = ublast_getftdic(low); LOG_INFO("usb blaster interface using libftdi"); if (ftdi_init(ftdic) < 0) return ERROR_JTAG_INIT_FAILED; /* context, vendor id, product id */ if (ftdi_usb_open(ftdic, low->ublast_vid, low->ublast_pid) < 0) { LOG_ERROR("unable to open ftdi device: %s", ftdic->error_str); return ERROR_JTAG_INIT_FAILED; } if (ftdi_usb_reset(ftdic) < 0) { LOG_ERROR("unable to reset ftdi device"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_set_latency_timer(ftdic, 2) < 0) { LOG_ERROR("unable to set latency timer"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0) LOG_ERROR("unable to get latency timer"); else LOG_DEBUG("current latency timer: %u", latency_timer); ftdi_disable_bitbang(ftdic); return ERROR_OK; } static int ublast_ftdi_quit(struct ublast_lowlevel *low) { struct ftdi_context *ftdic = ublast_getftdic(low); ftdi_usb_close(ftdic); ftdi_deinit(ftdic); return ERROR_OK; }; static struct ublast_lowlevel_priv { struct ftdi_context ftdic; } info; static struct ublast_lowlevel low = { .open = ublast_ftdi_init, .close = ublast_ftdi_quit, .read = ublast_ftdi_read, .write = ublast_ftdi_write, .priv = &info, }; struct ublast_lowlevel *ublast_register_ftdi(void) { return &low; } openocd-0.9.0/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c0000644000175000017500000001140712315575360022057 00000000000000/* * Driver for USB-JTAG, Altera USB-Blaster and compatibles * * Inspired from original code from Kolja Waschk's USB-JTAG project * (http://www.ixo.de/info/usb_jtag/), and from openocd project. * * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr * Copyright (C) 2011 Ali Lown ali@lown.me.uk * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "ublast_access.h" #include #include "jtag/drivers/ftd2xx_common.h" static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low) { return low->priv; } static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written) { FT_STATUS status; DWORD dw_bytes_written; FT_HANDLE *ftdih = ublast_getftdih(low); status = FT_Write(*ftdih, buf, size, &dw_bytes_written); if (status != FT_OK) { *bytes_written = dw_bytes_written; LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written = dw_bytes_written; return ERROR_OK; } static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read) { DWORD dw_bytes_read; FT_STATUS status; FT_HANDLE *ftdih = ublast_getftdih(low); status = FT_Read(*ftdih, buf, size, &dw_bytes_read); if (status != FT_OK) { *bytes_read = dw_bytes_read; LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read = dw_bytes_read; return ERROR_OK; } static int ublast_ftd2xx_init(struct ublast_lowlevel *low) { FT_STATUS status; FT_HANDLE *ftdih = ublast_getftdih(low); uint8_t latency_timer; LOG_INFO("usb blaster interface using FTD2XX"); /* Open by device description */ if (low->ublast_device_desc == NULL) { LOG_WARNING("no usb blaster device description specified, " "using default 'USB-Blaster'"); low->ublast_device_desc = "USB-Blaster"; } #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid); if (status != FT_OK) { LOG_WARNING("couldn't add %4.4x:%4.4x", low->ublast_vid, low->ublast_pid); } #endif status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION, ftdih); if (status != FT_OK) { DWORD num_devices; LOG_ERROR("unable to open ftdi device: %s", ftd2xx_status_string(status)); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); unsigned int i; for (i = 0; i < num_devices; i++) desc_array[i] = malloc(64); desc_array[num_devices] = NULL; status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); if (status == FT_OK) { LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%i: %s", i, desc_array[i]); } for (i = 0; i < num_devices; i++) free(desc_array[i]); free(desc_array); } else { printf("ListDevices: NONE\n"); } return ERROR_JTAG_INIT_FAILED; } status = FT_SetLatencyTimer(*ftdih, 2); if (status != FT_OK) { LOG_ERROR("unable to set latency timer: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } status = FT_GetLatencyTimer(*ftdih, &latency_timer); if (status != FT_OK) LOG_ERROR("unable to get latency timer: %s", ftd2xx_status_string(status)); else LOG_DEBUG("current latency timer: %i", latency_timer); status = FT_SetBitMode(*ftdih, 0x00, 0); if (status != FT_OK) { LOG_ERROR("unable to disable bit i/o mode: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } static int ublast_ftd2xx_quit(struct ublast_lowlevel *low) { FT_HANDLE *ftdih = ublast_getftdih(low); FT_Close(*ftdih); return ERROR_OK; } static struct ublast_lowlevel_priv { FT_HANDLE ftdih; } info; static struct ublast_lowlevel low = { .open = ublast_ftd2xx_init, .close = ublast_ftd2xx_quit, .read = ublast_ftd2xx_read, .write = ublast_ftd2xx_write, .priv = &info, }; struct ublast_lowlevel *ublast_register_ftd2xx(void) { return &low; } openocd-0.9.0/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c0000644000175000017500000001516312516456302022202 00000000000000/* * Driver for USB-JTAG, Altera USB-Blaster II and compatibles * * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "ublast_access.h" #define USBBLASTER_CTRL_READ_REV 0x94 #define USBBLASTER_CTRL_LOAD_FIRM 0xA0 #define USBBLASTER_EPOUT 4 #define USBBLASTER_EPIN 8 #define EZUSB_CPUCS 0xe600 #define CPU_RESET 1 /** Maximum size of a single firmware section. Entire EZ-USB code space = 16kB */ #define SECTION_BUFFERSIZE 16384 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read) { *bytes_read = jtag_libusb_bulk_read(low->libusb_dev, USBBLASTER_EPIN | \ LIBUSB_ENDPOINT_IN, (char *)buf, size, 100); return ERROR_OK; } static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written) { *bytes_written = jtag_libusb_bulk_write(low->libusb_dev, USBBLASTER_EPOUT | \ LIBUSB_ENDPOINT_OUT, (char *)buf, size, 100); return ERROR_OK; } static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev, struct image *firmware_image, int section_index) { uint16_t chunk_size; uint8_t data[SECTION_BUFFERSIZE]; uint8_t *data_ptr = data; size_t size_read; uint16_t size = (uint16_t)firmware_image->sections[section_index].size; uint16_t addr = (uint16_t)firmware_image->sections[section_index].base_address; LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr, size); /* Copy section contents to local buffer */ int ret = image_read_section(firmware_image, section_index, 0, size, data, &size_read); if ((ret != ERROR_OK) || (size_read != size)) { /* Propagating the return code would return '0' (misleadingly indicating * successful execution of the function) if only the size check fails. */ return ERROR_FAIL; } uint16_t bytes_remaining = size; /* Send section data in chunks of up to 64 bytes to ULINK */ while (bytes_remaining > 0) { if (bytes_remaining > 64) chunk_size = 64; else chunk_size = bytes_remaining; jtag_libusb_control_transfer(libusb_dev, LIBUSB_REQUEST_TYPE_VENDOR | \ LIBUSB_ENDPOINT_OUT, USBBLASTER_CTRL_LOAD_FIRM, addr, 0, (char *)data_ptr, chunk_size, 100); bytes_remaining -= chunk_size; addr += chunk_size; data_ptr += chunk_size; } return ERROR_OK; } static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_dev, struct ublast_lowlevel *low) { struct image ublast2_firmware_image; if (!low->firmware_path) { LOG_ERROR("No firmware path specified"); return ERROR_FAIL; } ublast2_firmware_image.base_address = 0; ublast2_firmware_image.base_address_set = 0; int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex"); if (ret != ERROR_OK) { LOG_ERROR("Could not load firmware image"); return ret; } /** A host loader program must write 0x01 to the CPUCS register * to put the CPU into RESET, load all or part of the EZUSB * RAM with firmware, then reload the CPUCS register * with ‘0’ to take the CPU out of RESET. The CPUCS register * (at 0xE600) is the only EZ-USB register that can be written * using the Firmware Download command. */ char value = CPU_RESET; jtag_libusb_control_transfer(libusb_dev, LIBUSB_REQUEST_TYPE_VENDOR | \ LIBUSB_ENDPOINT_OUT, USBBLASTER_CTRL_LOAD_FIRM, EZUSB_CPUCS, 0, &value, 1, 100); /* Download all sections in the image to ULINK */ for (int i = 0; i < ublast2_firmware_image.num_sections; i++) { ret = ublast2_write_firmware_section(libusb_dev, &ublast2_firmware_image, i); if (ret != ERROR_OK) { LOG_ERROR("Error while downloading the firmware"); return ret; } } value = !CPU_RESET; jtag_libusb_control_transfer(libusb_dev, LIBUSB_REQUEST_TYPE_VENDOR | \ LIBUSB_ENDPOINT_OUT, USBBLASTER_CTRL_LOAD_FIRM, EZUSB_CPUCS, 0, &value, 1, 100); image_close(&ublast2_firmware_image); return ERROR_OK; } static int ublast2_libusb_init(struct ublast_lowlevel *low) { const uint16_t vids[] = { low->ublast_vid_uninit, 0 }; const uint16_t pids[] = { low->ublast_pid_uninit, 0 }; struct jtag_libusb_device_handle *temp; bool renumeration = false; int ret; if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) { LOG_INFO("Altera USB-Blaster II (uninitialized) found"); LOG_INFO("Loading firmware..."); ret = load_usb_blaster_firmware(temp, low); jtag_libusb_close(temp); if (ret != ERROR_OK) return ret; renumeration = true; } const uint16_t vids_renum[] = { low->ublast_vid, 0 }; const uint16_t pids_renum[] = { low->ublast_pid, 0 }; if (renumeration == false) { if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) { LOG_ERROR("Altera USB-Blaster II not found"); return ERROR_FAIL; } } else { int retry = 10; while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) { usleep(1000000); LOG_INFO("Waiting for renumerate..."); } if (!retry) { LOG_ERROR("Altera USB-Blaster II not found"); return ERROR_FAIL; } } char buffer[5]; jtag_libusb_control_transfer(low->libusb_dev, LIBUSB_REQUEST_TYPE_VENDOR | \ LIBUSB_ENDPOINT_IN, USBBLASTER_CTRL_READ_REV, 0, 0, buffer, 5, 100); LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer); return ERROR_OK; } static int ublast2_libusb_quit(struct ublast_lowlevel *low) { jtag_libusb_close(low->libusb_dev); return ERROR_OK; }; static struct ublast_lowlevel low = { .open = ublast2_libusb_init, .close = ublast2_libusb_quit, .read = ublast2_libusb_read, .write = ublast2_libusb_write, .flags = COPY_TDO_BUFFER, }; struct ublast_lowlevel *ublast2_register_libusb(void) { return &low; } openocd-0.9.0/src/jtag/drivers/opendous.c0000644000175000017500000005543612516456302015303 00000000000000/*************************************************************************** * * * Copyright (C) 2009 by Cahya Wirawan * * Based on opendous driver by Vladimir Fonov * * * * Copyright (C) 2009 by Vladimir Fonov * * Based on J-link driver by Juergen Stuber * * * * Copyright (C) 2007 by Juergen Stuber * * based on Dominic Rath's and Benedikt Sauter's usbprog.c * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "libusb_common.h" #include #include #define OPENDOUS_MAX_VIDS_PIDS 4 /* define some probes with similar interface */ struct opendous_probe { const char *name; uint16_t VID[OPENDOUS_MAX_VIDS_PIDS]; uint16_t PID[OPENDOUS_MAX_VIDS_PIDS]; uint8_t READ_EP; uint8_t WRITE_EP; uint8_t CONTROL_TRANSFER; int BUFFERSIZE; }; static const struct opendous_probe opendous_probes[] = { {"usbprog-jtag", {0x1781, 0}, {0x0C63, 0}, 0x82, 0x02, 0x00, 510 }, {"opendous", {0x1781, 0x03EB, 0}, {0xC0C0, 0x204F, 0}, 0x81, 0x02, 0x00, 360 }, {"usbvlab", {0x16C0, 0}, {0x05DC, 0}, 0x81, 0x02, 0x01, 360 }, {NULL, {0x0000}, {0x0000}, 0x00, 0x00, 0x00, 0 } }; #define OPENDOUS_WRITE_ENDPOINT (opendous_probe->WRITE_EP) #define OPENDOUS_READ_ENDPOINT (opendous_probe->READ_EP) static unsigned int opendous_hw_jtag_version = 1; #define OPENDOUS_USB_TIMEOUT 1000 #define OPENDOUS_USB_BUFFER_SIZE (opendous_probe->BUFFERSIZE) #define OPENDOUS_IN_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE) #define OPENDOUS_OUT_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE) /* Global USB buffers */ static uint8_t *usb_in_buffer; static uint8_t *usb_out_buffer; /* Constants for OPENDOUS command */ #define OPENDOUS_MAX_SPEED 66 #define OPENDOUS_MAX_TAP_TRANSMIT ((opendous_probe->BUFFERSIZE)-10) #define OPENDOUS_MAX_INPUT_DATA (OPENDOUS_MAX_TAP_TRANSMIT*4) /* TAP */ #define OPENDOUS_TAP_BUFFER_SIZE 65536 struct pending_scan_result { int first; /* First bit position in tdo_buffer to read */ int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ uint8_t *buffer; }; static int pending_scan_results_length; static struct pending_scan_result *pending_scan_results_buffer; #define MAX_PENDING_SCAN_RESULTS (OPENDOUS_MAX_INPUT_DATA) /* JTAG usb commands */ #define JTAG_CMD_TAP_OUTPUT 0x0 #define JTAG_CMD_SET_TRST 0x1 #define JTAG_CMD_SET_SRST 0x2 #define JTAG_CMD_READ_INPUT 0x3 #define JTAG_CMD_TAP_OUTPUT_EMU 0x4 #define JTAG_CMD_SET_DELAY 0x5 #define JTAG_CMD_SET_SRST_TRST 0x6 #define JTAG_CMD_READ_CONFIG 0x7 /* usbvlab control transfer */ #define FUNC_START_BOOTLOADER 30 #define FUNC_WRITE_DATA 0x50 #define FUNC_READ_DATA 0x51 static char *opendous_type; static const struct opendous_probe *opendous_probe; /* External interface functions */ static int opendous_execute_queue(void); static int opendous_init(void); static int opendous_quit(void); /* Queue command functions */ static void opendous_end_state(tap_state_t state); static void opendous_state_move(void); static void opendous_path_move(int num_states, tap_state_t *path); static void opendous_runtest(int num_cycles); static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void opendous_reset(int trst, int srst); static void opendous_simple_command(uint8_t command, uint8_t _data); static int opendous_get_status(void); /* opendous tap buffer functions */ static void opendous_tap_init(void); static int opendous_tap_execute(void); static void opendous_tap_ensure_space(int scans, int bits); static void opendous_tap_append_step(int tms, int tdi); static void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); /* opendous lowlevel functions */ struct opendous_jtag { struct jtag_libusb_device_handle *usb_handle; }; static struct opendous_jtag *opendous_usb_open(void); static void opendous_usb_close(struct opendous_jtag *opendous_jtag); static int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, int in_length); static int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length); static int opendous_usb_read(struct opendous_jtag *opendous_jtag); /* helper functions */ int opendous_get_version_info(void); #ifdef _DEBUG_USB_COMMS_ static void opendous_debug_buffer(uint8_t *buffer, int length); #endif static struct opendous_jtag *opendous_jtag_handle; /***************************************************************************/ /* External interface implementation */ COMMAND_HANDLER(opendous_handle_opendous_type_command) { if (CMD_ARGC == 0) return ERROR_OK; /* only if the cable name wasn't overwritten by cmdline */ if (opendous_type == NULL) { /* REVISIT first verify that it's listed in cables[] ... */ opendous_type = strdup(CMD_ARGV[0]); } /* REVISIT it's probably worth returning the current value ... */ return ERROR_OK; } COMMAND_HANDLER(opendous_handle_opendous_info_command) { if (opendous_get_version_info() == ERROR_OK) { /* attempt to get status */ opendous_get_status(); } return ERROR_OK; } COMMAND_HANDLER(opendous_handle_opendous_hw_jtag_command) { switch (CMD_ARGC) { case 0: command_print(CMD_CTX, "opendous hw jtag %i", opendous_hw_jtag_version); break; case 1: { int request_version = atoi(CMD_ARGV[0]); switch (request_version) { case 2: case 3: opendous_hw_jtag_version = request_version; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } break; } default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static const struct command_registration opendous_command_handlers[] = { { .name = "opendous_info", .handler = &opendous_handle_opendous_info_command, .mode = COMMAND_EXEC, .help = "show opendous info", }, { .name = "opendous_hw_jtag", .handler = &opendous_handle_opendous_hw_jtag_command, .mode = COMMAND_EXEC, .help = "access opendous HW JTAG command version", .usage = "[2|3]", }, { .name = "opendous_type", .handler = &opendous_handle_opendous_type_command, .mode = COMMAND_CONFIG, .help = "set opendous type", .usage = "[usbvlab|usbprog-jtag|opendous]", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface opendous_interface = { .name = "opendous", .commands = opendous_command_handlers, .execute_queue = opendous_execute_queue, .init = opendous_init, .quit = opendous_quit, }; static int opendous_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; int scan_size; enum scan_type type; uint8_t *buffer; while (cmd != NULL) { switch (cmd->type) { case JTAG_RUNTEST: DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \ cmd->cmd.runtest->end_state); if (cmd->cmd.runtest->end_state != -1) opendous_end_state(cmd->cmd.runtest->end_state); opendous_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); if (cmd->cmd.statemove->end_state != -1) opendous_end_state(cmd->cmd.statemove->end_state); opendous_state_move(); break; case JTAG_PATHMOVE: DEBUG_JTAG_IO("pathmove: %i states, end in %i", \ cmd->cmd.pathmove->num_states, \ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); break; case JTAG_SCAN: DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state); if (cmd->cmd.scan->end_state != -1) opendous_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); DEBUG_JTAG_IO("scan input, length = %d", scan_size); #ifdef _DEBUG_USB_COMMS_ opendous_debug_buffer(buffer, (scan_size + 7) / 8); #endif type = jtag_scan_type(cmd->cmd.scan); opendous_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); break; case JTAG_RESET: DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); opendous_tap_execute(); if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); opendous_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_SLEEP: DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us); opendous_tap_execute(); jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return opendous_tap_execute(); } static int opendous_init(void) { int check_cnt; const struct opendous_probe *cur_opendous_probe; cur_opendous_probe = opendous_probes; if (opendous_type == NULL) { opendous_type = strdup("opendous"); LOG_WARNING("No opendous_type specified, using default 'opendous'"); } while (cur_opendous_probe->name) { if (strcmp(cur_opendous_probe->name, opendous_type) == 0) { opendous_probe = cur_opendous_probe; break; } cur_opendous_probe++; } if (!opendous_probe) { LOG_ERROR("No matching cable found for %s", opendous_type); return ERROR_JTAG_INIT_FAILED; } usb_in_buffer = malloc(opendous_probe->BUFFERSIZE); usb_out_buffer = malloc(opendous_probe->BUFFERSIZE); pending_scan_results_buffer = malloc( MAX_PENDING_SCAN_RESULTS * sizeof(*pending_scan_results_buffer)); opendous_jtag_handle = opendous_usb_open(); if (opendous_jtag_handle == 0) { LOG_ERROR("Cannot find opendous Interface! Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } check_cnt = 0; while (check_cnt < 3) { if (opendous_get_version_info() == ERROR_OK) { /* attempt to get status */ opendous_get_status(); break; } check_cnt++; } LOG_INFO("opendous JTAG Interface ready"); opendous_reset(0, 0); opendous_tap_init(); return ERROR_OK; } static int opendous_quit(void) { opendous_usb_close(opendous_jtag_handle); if (usb_out_buffer) { free(usb_out_buffer); usb_out_buffer = NULL; } if (usb_in_buffer) { free(usb_in_buffer); usb_in_buffer = NULL; } if (pending_scan_results_buffer) { free(pending_scan_results_buffer); pending_scan_results_buffer = NULL; } if (opendous_type) { free(opendous_type); opendous_type = NULL; } return ERROR_OK; } /***************************************************************************/ /* Queue command implementations */ void opendous_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } /* Goes to the end state. */ void opendous_state_move(void) { int i; int tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_scan_bits; i++) { tms = (tms_scan >> i) & 1; opendous_tap_append_step(tms, 0); } tap_set_state(tap_get_end_state()); } void opendous_path_move(int num_states, tap_state_t *path) { int i; for (i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) opendous_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) opendous_tap_append_step(1, 0); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); exit(-1); } tap_set_state(path[i]); } tap_set_end_state(tap_get_state()); } void opendous_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { opendous_end_state(TAP_IDLE); opendous_state_move(); } /* execute num_cycles */ for (i = 0; i < num_cycles; i++) opendous_tap_append_step(0, 0); /* finish in end_state */ opendous_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) opendous_state_move(); } void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { tap_state_t saved_end_state; opendous_tap_ensure_space(1, scan_size + 8); saved_end_state = tap_get_end_state(); /* Move to appropriate scan state */ opendous_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); if (tap_get_state() != tap_get_end_state()) opendous_state_move(); opendous_end_state(saved_end_state); /* Scan */ opendous_tap_append_scan(scan_size, buffer, command); /* We are in Exit1, go to Pause */ opendous_tap_append_step(0, 0); tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) opendous_state_move(); } void opendous_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); /* Signals are active low */ #if 0 if (srst == 0) opendous_simple_command(JTAG_CMD_SET_SRST, 1); else if (srst == 1) opendous_simple_command(JTAG_CMD_SET_SRST, 0); if (trst == 0) opendous_simple_command(JTAG_CMD_SET_TRST, 1); else if (trst == 1) opendous_simple_command(JTAG_CMD_SET_TRST, 0); #endif srst = srst ? 0 : 1; trst = trst ? 0 : 2; opendous_simple_command(JTAG_CMD_SET_SRST_TRST, srst | trst); } void opendous_simple_command(uint8_t command, uint8_t _data) { int result; DEBUG_JTAG_IO("0x%02x 0x%02x", command, _data); usb_out_buffer[0] = 2; usb_out_buffer[1] = 0; usb_out_buffer[2] = command; usb_out_buffer[3] = _data; result = opendous_usb_message(opendous_jtag_handle, 4, 1); if (result != 1) LOG_ERROR("opendous command 0x%02x failed (%d)", command, result); } int opendous_get_status(void) { return ERROR_OK; } int opendous_get_version_info(void) { return ERROR_OK; } /***************************************************************************/ /* Estick tap functions */ static int tap_length; static uint8_t tms_buffer[OPENDOUS_TAP_BUFFER_SIZE]; static uint8_t tdo_buffer[OPENDOUS_TAP_BUFFER_SIZE]; static int last_tms; void opendous_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; } void opendous_tap_ensure_space(int scans, int bits) { int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; int available_bits = OPENDOUS_TAP_BUFFER_SIZE / 2 - tap_length; if ((scans > available_scans) || (bits > available_bits)) opendous_tap_execute(); } void opendous_tap_append_step(int tms, int tdi) { last_tms = tms; unsigned char _tms = tms ? 1 : 0; unsigned char _tdi = tdi ? 1 : 0; opendous_tap_ensure_space(0, 1); int tap_index = tap_length / 4; int bits = (tap_length % 4) * 2; if (tap_length < OPENDOUS_TAP_BUFFER_SIZE) { if (!bits) tms_buffer[tap_index] = 0; tms_buffer[tap_index] |= (_tdi << bits)|(_tms << (bits + 1)) ; tap_length++; } else LOG_ERROR("opendous_tap_append_step, overflow"); } void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command) { DEBUG_JTAG_IO("append scan, length = %d", length); struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length]; int i; pending_scan_result->first = tap_length; pending_scan_result->length = length; pending_scan_result->command = command; pending_scan_result->buffer = buffer; for (i = 0; i < length; i++) opendous_tap_append_step((i < length-1 ? 0 : 1), (buffer[i / 8] >> (i % 8)) & 1); pending_scan_results_length++; } /* Pad and send a tap sequence to the device, and receive the answer. * For the purpose of padding we assume that we are in idle or pause state. */ int opendous_tap_execute(void) { int byte_length; int i, j; int result; #ifdef _DEBUG_USB_COMMS_ int byte_length_out; #endif if (tap_length > 0) { /* memset(tdo_buffer,0,OPENDOUS_TAP_BUFFER_SIZE); */ /* LOG_INFO("OPENDOUS tap execute %d",tap_length); */ byte_length = (tap_length + 3) / 4; #ifdef _DEBUG_USB_COMMS_ byte_length_out = (tap_length + 7) / 8; LOG_DEBUG("opendous is sending %d bytes", byte_length); #endif for (j = 0, i = 0; j < byte_length;) { int receive; int transmit = byte_length - j; if (transmit > OPENDOUS_MAX_TAP_TRANSMIT) { transmit = OPENDOUS_MAX_TAP_TRANSMIT; receive = (OPENDOUS_MAX_TAP_TRANSMIT) / 2; usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT; } else { usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT | ((tap_length % 4) << 4); receive = (transmit + 1) / 2; } usb_out_buffer[0] = (transmit + 1) & 0xff; usb_out_buffer[1] = ((transmit + 1) >> 8) & 0xff; memmove(usb_out_buffer + 3, tms_buffer + j, transmit); result = opendous_usb_message(opendous_jtag_handle, 3 + transmit, receive); if (result != receive) { LOG_ERROR("opendous_tap_execute, wrong result %d, expected %d", result, receive); return ERROR_JTAG_QUEUE_FAILED; } memmove(tdo_buffer + i, usb_in_buffer, receive); i += receive; j += transmit; } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("opendous tap result %d", byte_length_out); opendous_debug_buffer(tdo_buffer, byte_length_out); #endif /* LOG_INFO("eStick tap execute %d",tap_length); */ for (i = 0; i < pending_scan_results_length; i++) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; uint8_t *buffer = pending_scan_result->buffer; int length = pending_scan_result->length; int first = pending_scan_result->first; struct scan_command *command = pending_scan_result->command; /* Copy to buffer */ buf_set_buf(tdo_buffer, first, buffer, 0, length); DEBUG_JTAG_IO("pending scan result, length = %d", length); #ifdef _DEBUG_USB_COMMS_ opendous_debug_buffer(buffer, byte_length_out); #endif if (jtag_read_buffer(buffer, command) != ERROR_OK) { opendous_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } if (pending_scan_result->buffer != NULL) free(pending_scan_result->buffer); } opendous_tap_init(); } return ERROR_OK; } /*****************************************************************************/ /* Estick USB low-level functions */ struct opendous_jtag *opendous_usb_open(void) { struct opendous_jtag *result; struct jtag_libusb_device_handle *devh; if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK) return NULL; jtag_libusb_set_configuration(devh, 0); jtag_libusb_claim_interface(devh, 0); result = malloc(sizeof(*result)); result->usb_handle = devh; return result; } void opendous_usb_close(struct opendous_jtag *opendous_jtag) { jtag_libusb_close(opendous_jtag->usb_handle); free(opendous_jtag); } /* Send a message and receive the reply. */ int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, int in_length) { int result; result = opendous_usb_write(opendous_jtag, out_length); if (result == out_length) { result = opendous_usb_read(opendous_jtag); if (result == in_length) return result; else { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); return -1; } } else { LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result); return -1; } } /* Write data from out_buffer to USB. */ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length) { int result; if (out_length > OPENDOUS_OUT_BUFFER_SIZE) { LOG_ERROR("opendous_jtag_write illegal out_length=%d (max=%d)", out_length, OPENDOUS_OUT_BUFFER_SIZE); return -1; } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB write begin"); #endif if (opendous_probe->CONTROL_TRANSFER) { result = jtag_libusb_control_transfer(opendous_jtag->usb_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT); } else { result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \ (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT); } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB write end: %d bytes", result); #endif DEBUG_JTAG_IO("opendous_usb_write, out_length = %d, result = %d", out_length, result); #ifdef _DEBUG_USB_COMMS_ opendous_debug_buffer(usb_out_buffer, out_length); #endif return result; } /* Read data from USB into in_buffer. */ int opendous_usb_read(struct opendous_jtag *opendous_jtag) { #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB read begin"); #endif int result; if (opendous_probe->CONTROL_TRANSFER) { result = jtag_libusb_control_transfer(opendous_jtag->usb_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT); } else { result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT, (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT); } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB read end: %d bytes", result); #endif DEBUG_JTAG_IO("opendous_usb_read, result = %d", result); #ifdef _DEBUG_USB_COMMS_ opendous_debug_buffer(usb_in_buffer, result); #endif return result; } #ifdef _DEBUG_USB_COMMS_ #define BYTES_PER_LINE 16 void opendous_debug_buffer(uint8_t *buffer, int length) { char line[81]; char s[4]; int i; int j; for (i = 0; i < length; i += BYTES_PER_LINE) { snprintf(line, 5, "%04x", i); for (j = i; j < i + BYTES_PER_LINE && j < length; j++) { snprintf(s, 4, " %02x", buffer[j]); strcat(line, s); } LOG_DEBUG("%s", line); } } #endif openocd-0.9.0/src/jtag/drivers/remote_bitbang.c0000644000175000017500000001724012327155503016416 00000000000000/*************************************************************************** * Copyright (C) 2011 by Richard Uhler * * ruhler@mit.edu * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef _WIN32 #include #include #endif #include #include "bitbang.h" /* arbitrary limit on host name length: */ #define REMOTE_BITBANG_HOST_MAX 255 #define REMOTE_BITBANG_RAISE_ERROR(expr ...) \ do { \ LOG_ERROR(expr); \ LOG_ERROR("Terminating openocd."); \ exit(-1); \ } while (0) static char *remote_bitbang_host; static char *remote_bitbang_port; FILE *remote_bitbang_in; FILE *remote_bitbang_out; static void remote_bitbang_putc(int c) { if (EOF == fputc(c, remote_bitbang_out)) REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); } static int remote_bitbang_quit(void) { if (EOF == fputc('Q', remote_bitbang_out)) { LOG_ERROR("fputs: %s", strerror(errno)); return ERROR_FAIL; } if (EOF == fflush(remote_bitbang_out)) { LOG_ERROR("fflush: %s", strerror(errno)); return ERROR_FAIL; } /* We only need to close one of the FILE*s, because they both use the same */ /* underlying file descriptor. */ if (EOF == fclose(remote_bitbang_out)) { LOG_ERROR("fclose: %s", strerror(errno)); return ERROR_FAIL; } free(remote_bitbang_host); free(remote_bitbang_port); LOG_INFO("remote_bitbang interface quit"); return ERROR_OK; } /* Get the next read response. */ static int remote_bitbang_rread(void) { if (EOF == fflush(remote_bitbang_out)) { remote_bitbang_quit(); REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno)); } int c = fgetc(remote_bitbang_in); switch (c) { case '0': return 0; case '1': return 1; default: remote_bitbang_quit(); REMOTE_BITBANG_RAISE_ERROR( "remote_bitbang: invalid read response: %c(%i)", c, c); } } static int remote_bitbang_read(void) { remote_bitbang_putc('R'); return remote_bitbang_rread(); } static void remote_bitbang_write(int tck, int tms, int tdi) { char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0)); remote_bitbang_putc(c); } static void remote_bitbang_reset(int trst, int srst) { char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0)); remote_bitbang_putc(c); } static void remote_bitbang_blink(int on) { char c = on ? 'B' : 'b'; remote_bitbang_putc(c); } static struct bitbang_interface remote_bitbang_bitbang = { .read = &remote_bitbang_read, .write = &remote_bitbang_write, .reset = &remote_bitbang_reset, .blink = &remote_bitbang_blink, }; static int remote_bitbang_init_tcp(void) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo *result, *rp; int fd; LOG_INFO("Connecting to %s:%s", remote_bitbang_host ? remote_bitbang_host : "localhost", remote_bitbang_port); /* Obtain address(es) matching host/port */ int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result); if (s != 0) { LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s)); return ERROR_FAIL; } /* getaddrinfo() returns a list of address structures. Try each address until we successfully connect(2). If socket(2) (or connect(2)) fails, we (close the socket and) try the next address. */ for (rp = result; rp != NULL ; rp = rp->ai_next) { fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (fd == -1) continue; if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) break; /* Success */ close(fd); } freeaddrinfo(result); /* No longer needed */ if (rp == NULL) { /* No address succeeded */ LOG_ERROR("Failed to connect: %s", strerror(errno)); return ERROR_FAIL; } return fd; } static int remote_bitbang_init_unix(void) { if (remote_bitbang_host == NULL) { LOG_ERROR("host/socket not specified"); return ERROR_FAIL; } LOG_INFO("Connecting to unix socket %s", remote_bitbang_host); int fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { LOG_ERROR("socket: %s", strerror(errno)); return ERROR_FAIL; } struct sockaddr_un addr; addr.sun_family = AF_UNIX; strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path)); addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { LOG_ERROR("connect: %s", strerror(errno)); return ERROR_FAIL; } return fd; } static int remote_bitbang_init(void) { int fd; bitbang_interface = &remote_bitbang_bitbang; LOG_INFO("Initializing remote_bitbang driver"); if (remote_bitbang_port == NULL) fd = remote_bitbang_init_unix(); else fd = remote_bitbang_init_tcp(); if (fd < 0) return fd; remote_bitbang_in = fdopen(fd, "r"); if (remote_bitbang_in == NULL) { LOG_ERROR("fdopen: failed to open read stream"); close(fd); return ERROR_FAIL; } remote_bitbang_out = fdopen(fd, "w"); if (remote_bitbang_out == NULL) { LOG_ERROR("fdopen: failed to open write stream"); fclose(remote_bitbang_in); return ERROR_FAIL; } LOG_INFO("remote_bitbang driver initialized"); return ERROR_OK; } COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command) { if (CMD_ARGC == 1) { uint16_t port; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port); free(remote_bitbang_port); remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]); return ERROR_OK; } return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command) { if (CMD_ARGC == 1) { free(remote_bitbang_host); remote_bitbang_host = strdup(CMD_ARGV[0]); return ERROR_OK; } return ERROR_COMMAND_SYNTAX_ERROR; } static const struct command_registration remote_bitbang_command_handlers[] = { { .name = "remote_bitbang_port", .handler = remote_bitbang_handle_remote_bitbang_port_command, .mode = COMMAND_CONFIG, .help = "Set the port to use to connect to the remote jtag.\n" " if 0 or unset, use unix sockets to connect to the remote jtag.", .usage = "port_number", }, { .name = "remote_bitbang_host", .handler = remote_bitbang_handle_remote_bitbang_host_command, .mode = COMMAND_CONFIG, .help = "Set the host to use to connect to the remote jtag.\n" " if port is 0 or unset, this is the name of the unix socket to use.", .usage = "host_name", }, COMMAND_REGISTRATION_DONE, }; struct jtag_interface remote_bitbang_interface = { .name = "remote_bitbang", .execute_queue = &bitbang_execute_queue, .commands = remote_bitbang_command_handlers, .init = &remote_bitbang_init, .quit = &remote_bitbang_quit, }; openocd-0.9.0/src/jtag/drivers/arm-jtag-ew.c0000644000175000017500000005217112315575360015556 00000000000000/*************************************************************************** * Copyright (C) 2009 by Dimitar Dimitrov * * based on Dominic Rath's and Benedikt Sauter's usbprog.c * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "usb_common.h" #define USB_VID 0x15ba #define USB_PID 0x001e #define ARMJTAGEW_EPT_BULK_OUT 0x01u #define ARMJTAGEW_EPT_BULK_IN 0x82u #define ARMJTAGEW_USB_TIMEOUT 2000 #define ARMJTAGEW_IN_BUFFER_SIZE (4*1024) #define ARMJTAGEW_OUT_BUFFER_SIZE (4*1024) /* USB command request codes. */ #define CMD_GET_VERSION 0x00 #define CMD_SELECT_DPIMPL 0x10 #define CMD_SET_TCK_FREQUENCY 0x11 #define CMD_GET_TCK_FREQUENCY 0x12 #define CMD_MEASURE_MAX_TCK_FREQ 0x15 #define CMD_MEASURE_RTCK_RESPONSE 0x16 #define CMD_TAP_SHIFT 0x17 #define CMD_SET_TAPHW_STATE 0x20 #define CMD_GET_TAPHW_STATE 0x21 #define CMD_TGPWR_SETUP 0x22 /* Global USB buffers */ static uint8_t usb_in_buffer[ARMJTAGEW_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE]; /* Queue command functions */ static void armjtagew_end_state(tap_state_t state); static void armjtagew_state_move(void); static void armjtagew_path_move(int num_states, tap_state_t *path); static void armjtagew_runtest(int num_cycles); static void armjtagew_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void armjtagew_reset(int trst, int srst); /* static void armjtagew_simple_command(uint8_t command); */ static int armjtagew_get_status(void); /* tap buffer functions */ static void armjtagew_tap_init(void); static int armjtagew_tap_execute(void); static void armjtagew_tap_ensure_space(int scans, int bits); static void armjtagew_tap_append_step(int tms, int tdi); static void armjtagew_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); /* ARM-JTAG-EW lowlevel functions */ struct armjtagew { struct usb_dev_handle *usb_handle; }; static struct armjtagew *armjtagew_usb_open(void); static void armjtagew_usb_close(struct armjtagew *armjtagew); static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, int in_length); static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length); static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length); /* helper functions */ static int armjtagew_get_version_info(void); #ifdef _DEBUG_USB_COMMS_ static void armjtagew_debug_buffer(uint8_t *buffer, int length); #endif static struct armjtagew *armjtagew_handle; /************************************************************************** * External interface implementation */ static int armjtagew_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; int scan_size; enum scan_type type; uint8_t *buffer; while (cmd != NULL) { switch (cmd->type) { case JTAG_RUNTEST: DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \ cmd->cmd.runtest->end_state); armjtagew_end_state(cmd->cmd.runtest->end_state); armjtagew_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); armjtagew_end_state(cmd->cmd.statemove->end_state); armjtagew_state_move(); break; case JTAG_PATHMOVE: DEBUG_JTAG_IO("pathmove: %i states, end in %i", \ cmd->cmd.pathmove->num_states, \ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); armjtagew_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); break; case JTAG_SCAN: DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state); armjtagew_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); DEBUG_JTAG_IO("scan input, length = %d", scan_size); #ifdef _DEBUG_USB_COMMS_ armjtagew_debug_buffer(buffer, (scan_size + 7) / 8); #endif type = jtag_scan_type(cmd->cmd.scan); armjtagew_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); break; case JTAG_RESET: DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); armjtagew_tap_execute(); if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); armjtagew_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_SLEEP: DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us); armjtagew_tap_execute(); jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return armjtagew_tap_execute(); } /* Sets speed in kHz. */ static int armjtagew_speed(int speed) { int result; int speed_real; usb_out_buffer[0] = CMD_SET_TCK_FREQUENCY; buf_set_u32(usb_out_buffer + 1, 0, 32, speed*1000); result = armjtagew_usb_message(armjtagew_handle, 5, 4); if (result < 0) { LOG_ERROR("ARM-JTAG-EW setting speed failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } usb_out_buffer[0] = CMD_GET_TCK_FREQUENCY; result = armjtagew_usb_message(armjtagew_handle, 1, 4); speed_real = (int)buf_get_u32(usb_in_buffer, 0, 32) / 1000; if (result < 0) { LOG_ERROR("ARM-JTAG-EW getting speed failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } else LOG_INFO("Requested speed %dkHz, emulator reported %dkHz.", speed, speed_real); return ERROR_OK; } static int armjtagew_khz(int khz, int *jtag_speed) { *jtag_speed = khz; return ERROR_OK; } static int armjtagew_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } static int armjtagew_init(void) { int check_cnt; armjtagew_handle = armjtagew_usb_open(); if (armjtagew_handle == 0) { LOG_ERROR( "Cannot find ARM-JTAG-EW Interface! Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } check_cnt = 0; while (check_cnt < 3) { if (armjtagew_get_version_info() == ERROR_OK) { /* attempt to get status */ armjtagew_get_status(); break; } check_cnt++; } if (check_cnt == 3) LOG_INFO("ARM-JTAG-EW initial read failed, don't worry"); /* Initial JTAG speed (for reset and initialization): 32 kHz */ armjtagew_speed(32); LOG_INFO("ARM-JTAG-EW JTAG Interface ready"); armjtagew_reset(0, 0); armjtagew_tap_init(); return ERROR_OK; } static int armjtagew_quit(void) { armjtagew_usb_close(armjtagew_handle); return ERROR_OK; } /************************************************************************** * Queue command implementations */ static void armjtagew_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } /* Goes to the end state. */ static void armjtagew_state_move(void) { int i; int tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_count; i++) { tms = (tms_scan >> i) & 1; armjtagew_tap_append_step(tms, 0); } tap_set_state(tap_get_end_state()); } static void armjtagew_path_move(int num_states, tap_state_t *path) { int i; for (i = 0; i < num_states; i++) { /* * TODO: The ARM-JTAG-EW hardware delays TDI with 3 TCK cycles when in RTCK mode. * Either handle that here, or update the documentation with examples * how to fix that in the configuration files. */ if (path[i] == tap_state_transition(tap_get_state(), false)) armjtagew_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) armjtagew_tap_append_step(1, 0); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); exit(-1); } tap_set_state(path[i]); } tap_set_end_state(tap_get_state()); } static void armjtagew_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { armjtagew_end_state(TAP_IDLE); armjtagew_state_move(); } /* execute num_cycles */ for (i = 0; i < num_cycles; i++) armjtagew_tap_append_step(0, 0); /* finish in end_state */ armjtagew_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) armjtagew_state_move(); } static void armjtagew_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { tap_state_t saved_end_state; armjtagew_tap_ensure_space(1, scan_size + 8); saved_end_state = tap_get_end_state(); /* Move to appropriate scan state */ armjtagew_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); /* Only move if we're not already there */ if (tap_get_state() != tap_get_end_state()) armjtagew_state_move(); armjtagew_end_state(saved_end_state); /* Scan */ armjtagew_tap_append_scan(scan_size, buffer, command); /* We are in Exit1, go to Pause */ armjtagew_tap_append_step(0, 0); tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) armjtagew_state_move(); } static void armjtagew_reset(int trst, int srst) { const uint8_t trst_mask = (1u << 5); const uint8_t srst_mask = (1u << 6); uint8_t val = 0; uint8_t outp_en = 0; uint8_t change_mask = 0; int result; LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (srst == 0) { val |= srst_mask; outp_en &= ~srst_mask; /* tristate */ change_mask |= srst_mask; } else if (srst == 1) { val &= ~srst_mask; outp_en |= srst_mask; change_mask |= srst_mask; } if (trst == 0) { val |= trst_mask; outp_en &= ~trst_mask; /* tristate */ change_mask |= trst_mask; } else if (trst == 1) { val &= ~trst_mask; outp_en |= trst_mask; change_mask |= trst_mask; } usb_out_buffer[0] = CMD_SET_TAPHW_STATE; usb_out_buffer[1] = val; usb_out_buffer[2] = outp_en; usb_out_buffer[3] = change_mask; result = armjtagew_usb_write(armjtagew_handle, 4); if (result != 4) LOG_ERROR("ARM-JTAG-EW TRST/SRST pin set failed failed (%d)", result); } static int armjtagew_get_status(void) { int result; usb_out_buffer[0] = CMD_GET_TAPHW_STATE; result = armjtagew_usb_message(armjtagew_handle, 1, 12); if (result == 0) { unsigned int u_tg = buf_get_u32(usb_in_buffer, 0, 16); LOG_INFO( "U_tg = %d mV, U_aux = %d mV, U_tgpwr = %d mV, I_tgpwr = %d mA, D1 = %d, Target power %s %s", (int)(buf_get_u32(usb_in_buffer + 0, 0, 16)), (int)(buf_get_u32(usb_in_buffer + 2, 0, 16)), (int)(buf_get_u32(usb_in_buffer + 4, 0, 16)), (int)(buf_get_u32(usb_in_buffer + 6, 0, 16)), usb_in_buffer[9], usb_in_buffer[11] ? "OVERCURRENT" : "OK", usb_in_buffer[10] ? "enabled" : "disabled"); if (u_tg < 1500) LOG_ERROR("Vref too low. Check Target Power"); } else LOG_ERROR("ARM-JTAG-EW command CMD_GET_TAPHW_STATE failed (%d)", result); return ERROR_OK; } static int armjtagew_get_version_info(void) { int result; char sn[16]; char auxinfo[257]; /* query hardware version */ usb_out_buffer[0] = CMD_GET_VERSION; result = armjtagew_usb_message(armjtagew_handle, 1, 4 + 15 + 256); if (result != 0) { LOG_ERROR("ARM-JTAG-EW command CMD_GET_VERSION failed (%d)", result); return ERROR_JTAG_DEVICE_ERROR; } memcpy(sn, usb_in_buffer + 4, 15); sn[15] = '\0'; memcpy(auxinfo, usb_in_buffer + 4+15, 256); auxinfo[256] = '\0'; LOG_INFO( "ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s", \ usb_in_buffer[1], usb_in_buffer[0], \ isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X', \ sn, auxinfo); if (1 != usb_in_buffer[1] || 6 != usb_in_buffer[0]) LOG_WARNING( "ARM-JTAG-EW firmware version %d.%d is untested with this version of OpenOCD. You might experience unexpected behavior.", usb_in_buffer[1], usb_in_buffer[0]); return ERROR_OK; } COMMAND_HANDLER(armjtagew_handle_armjtagew_info_command) { if (armjtagew_get_version_info() == ERROR_OK) { /* attempt to get status */ armjtagew_get_status(); } return ERROR_OK; } static const struct command_registration armjtagew_command_handlers[] = { { .name = "armjtagew_info", .handler = &armjtagew_handle_armjtagew_info_command, .mode = COMMAND_EXEC, .help = "query armjtagew info", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface armjtagew_interface = { .name = "arm-jtag-ew", .commands = armjtagew_command_handlers, .transports = jtag_only, .execute_queue = armjtagew_execute_queue, .speed = armjtagew_speed, .speed_div = armjtagew_speed_div, .khz = armjtagew_khz, .init = armjtagew_init, .quit = armjtagew_quit, }; /************************************************************************** * ARM-JTAG-EW tap functions */ /* 2048 is the max value we can use here */ #define ARMJTAGEW_TAP_BUFFER_SIZE 2048 static int tap_length; static uint8_t tms_buffer[ARMJTAGEW_TAP_BUFFER_SIZE]; static uint8_t tdi_buffer[ARMJTAGEW_TAP_BUFFER_SIZE]; static uint8_t tdo_buffer[ARMJTAGEW_TAP_BUFFER_SIZE]; struct pending_scan_result { int first; /* First bit position in tdo_buffer to read */ int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ uint8_t *buffer; }; #define MAX_PENDING_SCAN_RESULTS 256 static int pending_scan_results_length; static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; static int last_tms; static void armjtagew_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; } static void armjtagew_tap_ensure_space(int scans, int bits) { int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; int available_bits = ARMJTAGEW_TAP_BUFFER_SIZE * 8 - tap_length; if (scans > available_scans || bits > available_bits) armjtagew_tap_execute(); } static void armjtagew_tap_append_step(int tms, int tdi) { last_tms = tms; int index_local = tap_length / 8; if (index_local < ARMJTAGEW_TAP_BUFFER_SIZE) { int bit_index = tap_length % 8; uint8_t bit = 1 << bit_index; if (tms) tms_buffer[index_local] |= bit; else tms_buffer[index_local] &= ~bit; if (tdi) tdi_buffer[index_local] |= bit; else tdi_buffer[index_local] &= ~bit; tap_length++; } else LOG_ERROR("armjtagew_tap_append_step, overflow"); } void armjtagew_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length]; int i; pending_scan_result->first = tap_length; pending_scan_result->length = length; pending_scan_result->command = command; pending_scan_result->buffer = buffer; for (i = 0; i < length; i++) armjtagew_tap_append_step((i < length-1 ? 0 : 1), (buffer[i/8] >> (i%8)) & 1); pending_scan_results_length++; } /* Pad and send a tap sequence to the device, and receive the answer. * For the purpose of padding we assume that we are in idle or pause state. */ static int armjtagew_tap_execute(void) { int byte_length; int tms_offset; int tdi_offset; int i; int result; if (tap_length > 0) { /* Pad last byte so that tap_length is divisible by 8 */ while (tap_length % 8 != 0) { /* More of the last TMS value keeps us in the same state, * analogous to free-running JTAG interfaces. */ armjtagew_tap_append_step(last_tms, 0); } byte_length = tap_length / 8; usb_out_buffer[0] = CMD_TAP_SHIFT; buf_set_u32(usb_out_buffer + 1, 0, 16, byte_length); tms_offset = 3; for (i = 0; i < byte_length; i++) usb_out_buffer[tms_offset + i] = flip_u32(tms_buffer[i], 8); tdi_offset = tms_offset + byte_length; for (i = 0; i < byte_length; i++) usb_out_buffer[tdi_offset + i] = flip_u32(tdi_buffer[i], 8); result = armjtagew_usb_message(armjtagew_handle, 3 + 2 * byte_length, byte_length + 4); if (result == 0) { int stat_local; stat_local = (int)buf_get_u32(usb_in_buffer + byte_length, 0, 32); if (stat_local) { LOG_ERROR( "armjtagew_tap_execute, emulator returned error code %d for a CMD_TAP_SHIFT command", stat_local); return ERROR_JTAG_QUEUE_FAILED; } for (i = 0; i < byte_length; i++) tdo_buffer[i] = flip_u32(usb_in_buffer[i], 8); for (i = 0; i < pending_scan_results_length; i++) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; uint8_t *buffer = pending_scan_result->buffer; int length = pending_scan_result->length; int first = pending_scan_result->first; struct scan_command *command = pending_scan_result->command; /* Copy to buffer */ buf_set_buf(tdo_buffer, first, buffer, 0, length); DEBUG_JTAG_IO("pending scan result, length = %d", length); #ifdef _DEBUG_USB_COMMS_ armjtagew_debug_buffer(buffer, byte_length); #endif if (jtag_read_buffer(buffer, command) != ERROR_OK) { armjtagew_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } if (pending_scan_result->buffer != NULL) free(pending_scan_result->buffer); } } else { LOG_ERROR("armjtagew_tap_execute, wrong result %d, expected %d", result, byte_length); return ERROR_JTAG_QUEUE_FAILED; } armjtagew_tap_init(); } return ERROR_OK; } /**************************************************************************** * JLink USB low-level functions */ static struct armjtagew *armjtagew_usb_open() { usb_init(); const uint16_t vids[] = { USB_VID, 0 }; const uint16_t pids[] = { USB_PID, 0 }; struct usb_dev_handle *dev; if (jtag_usb_open(vids, pids, &dev) != ERROR_OK) return NULL; struct armjtagew *result = malloc(sizeof(struct armjtagew)); result->usb_handle = dev; #if 0 /* usb_set_configuration required under win32 */ usb_set_configuration(dev, dev->config[0].bConfigurationValue); #endif usb_claim_interface(dev, 0); #if 0 /* * This makes problems under Mac OS X. And is not needed * under Windows. Hopefully this will not break a linux build */ usb_set_altinterface(dev, 0); #endif return result; } static void armjtagew_usb_close(struct armjtagew *armjtagew) { usb_close(armjtagew->usb_handle); free(armjtagew); } /* Send a message and receive the reply. */ static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, int in_length) { int result; result = armjtagew_usb_write(armjtagew, out_length); if (result == out_length) { result = armjtagew_usb_read(armjtagew, in_length); if (result != in_length) { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); return -1; } } else { LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result); return -1; } return 0; } /* Write data from out_buffer to USB. */ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length) { int result; if (out_length > ARMJTAGEW_OUT_BUFFER_SIZE) { LOG_ERROR("armjtagew_write illegal out_length=%d (max=%d)", out_length, ARMJTAGEW_OUT_BUFFER_SIZE); return -1; } result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT, \ (char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT); DEBUG_JTAG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result); #ifdef _DEBUG_USB_COMMS_ armjtagew_debug_buffer(usb_out_buffer, out_length); #endif return result; } /* Read data from USB into in_buffer. */ static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length) { int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN, \ (char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT); DEBUG_JTAG_IO("armjtagew_usb_read, result = %d", result); #ifdef _DEBUG_USB_COMMS_ armjtagew_debug_buffer(usb_in_buffer, result); #endif return result; } #ifdef _DEBUG_USB_COMMS_ #define BYTES_PER_LINE 16 static void armjtagew_debug_buffer(uint8_t *buffer, int length) { char line[81]; char s[4]; int i; int j; for (i = 0; i < length; i += BYTES_PER_LINE) { snprintf(line, 5, "%04x", i); for (j = i; j < i + BYTES_PER_LINE && j < length; j++) { snprintf(s, 4, " %02x", buffer[j]); strcat(line, s); } LOG_DEBUG("%s", line); /* Prevent GDB timeout (writing to log might take some time) */ keep_alive(); } } #endif openocd-0.9.0/src/jtag/drivers/osbdm.c0000644000175000017500000004054012516456302014541 00000000000000/*************************************************************************** * Copyright (C) 2012 by Jan Dakinevich * * jan.dakinevich@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "libusb_common.h" struct sequence { int len; void *tms; void *tdo; const void *tdi; struct sequence *next; }; struct queue { struct sequence *head; struct sequence *tail; }; static struct sequence *queue_add_tail(struct queue *queue, int len) { if (len <= 0) { LOG_ERROR("BUG: sequences with zero length are not allowed"); return NULL; } struct sequence *next; next = malloc(sizeof(*next)); if (next) { next->tms = calloc(1, DIV_ROUND_UP(len, 8)); if (next->tms) { next->len = len; next->tdo = NULL; next->tdi = NULL; next->next = NULL; if (!queue->head) { /* Queue is empty at the moment */ queue->head = next; } else { /* Queue already contains at least one sequence */ queue->tail->next = next; } queue->tail = next; } else { free(next); next = NULL; } } if (!next) LOG_ERROR("Not enough memory"); return next; } static void queue_drop_head(struct queue *queue) { struct sequence *head = queue->head->next; /* New head */ free(queue->head->tms); free(queue->head); queue->head = head; } static void queue_free(struct queue *queue) { if (queue) { while (queue->head) queue_drop_head(queue); free(queue); } } static struct queue *queue_alloc(void) { struct queue *queue = malloc(sizeof(*queue)); if (queue) queue->head = NULL; else LOG_ERROR("Not enough memory"); return queue; } /* Size of usb communication buffer */ #define OSBDM_USB_BUFSIZE 64 /* Timeout for USB transfer, ms */ #define OSBDM_USB_TIMEOUT 1000 /* Write end point */ #define OSBDM_USB_EP_WRITE 0x01 /* Read end point */ #define OSBDM_USB_EP_READ 0x82 /* Initialize OSBDM device */ #define OSBDM_CMD_INIT 0x11 /* Execute special, not-BDM command. But only this * command is used for JTAG operation */ #define OSBDM_CMD_SPECIAL 0x27 /* Execute JTAG swap (tms/tdi -> tdo) */ #define OSBDM_CMD_SPECIAL_SWAP 0x05 /* Reset control */ #define OSBDM_CMD_SPECIAL_SRST 0x01 /* Maximum bit-length in one swap */ #define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16) /* Lists of valid VID/PID pairs */ static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 }; static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 }; struct osbdm { struct jtag_libusb_device_handle *devh; /* USB handle */ uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and receive */ int count; /* Count data to send and to read */ }; /* osbdm instance */ static struct osbdm osbdm_context; static int osbdm_send_and_recv(struct osbdm *osbdm) { /* Send request */ int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE, (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT); if (count != osbdm->count) { LOG_ERROR("OSBDM communication error: can't write"); return ERROR_FAIL; } /* Save command code for next checking */ uint8_t cmd_saved = osbdm->buffer[0]; /* Reading answer */ osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ, (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT); /* Now perform basic checks for data sent by BDM device */ if (osbdm->count < 0) { LOG_ERROR("OSBDM communication error: can't read"); return ERROR_FAIL; } if (osbdm->count < 2) { LOG_ERROR("OSBDM communication error: reply too small"); return ERROR_FAIL; } if (osbdm->count != osbdm->buffer[1]) { LOG_ERROR("OSBDM communication error: reply size mismatch"); return ERROR_FAIL; } if (cmd_saved != osbdm->buffer[0]) { LOG_ERROR("OSBDM communication error: reply command mismatch"); return ERROR_FAIL; } return ERROR_OK; } static int osbdm_srst(struct osbdm *osbdm, int srst) { osbdm->count = 0; (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE); /* Composing request */ osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */ osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SRST; /* Subcommand */ /* Length in bytes - not used */ osbdm->buffer[osbdm->count++] = 0; osbdm->buffer[osbdm->count++] = 0; /* SRST state */ osbdm->buffer[osbdm->count++] = (srst ? 0 : 0x08); /* Sending data */ if (osbdm_send_and_recv(osbdm) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi, void *tdo, int length) { if (length > OSBDM_SWAP_MAX) { LOG_ERROR("BUG: bit sequence too long"); return ERROR_FAIL; } if (length <= 0) { LOG_ERROR("BUG: bit sequence equal or less than 0"); return ERROR_FAIL; } int swap_count = DIV_ROUND_UP(length, 16); /* cleanup */ osbdm->count = 0; (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE); /* Composing request */ osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */ osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SWAP; /* Subcommand */ /* Length in bytes - not used */ osbdm->buffer[osbdm->count++] = 0; osbdm->buffer[osbdm->count++] = 0; /* Swap count */ osbdm->buffer[osbdm->count++] = 0; osbdm->buffer[osbdm->count++] = (uint8_t)swap_count; for (int bit_idx = 0; bit_idx < length; ) { /* Bit count in swap */ int bit_count = length - bit_idx; if (bit_count > 16) bit_count = 16; osbdm->buffer[osbdm->count++] = (uint8_t)bit_count; /* Copying TMS and TDI data to output buffer */ uint32_t tms_data = buf_get_u32(tms, bit_idx, bit_count); uint32_t tdi_data = buf_get_u32(tdi, bit_idx, bit_count); osbdm->buffer[osbdm->count++] = (uint8_t)(tdi_data >> 8); osbdm->buffer[osbdm->count++] = (uint8_t)tdi_data; osbdm->buffer[osbdm->count++] = (uint8_t)(tms_data >> 8); osbdm->buffer[osbdm->count++] = (uint8_t)tms_data; /* Next bit offset */ bit_idx += bit_count; } assert(osbdm->count <= OSBDM_USB_BUFSIZE); /* Sending data */ if (osbdm_send_and_recv(osbdm) != ERROR_OK) return ERROR_FAIL; /* Extra check */ if (((osbdm->buffer[2] << 8) | osbdm->buffer[3]) != 2 * swap_count) { LOG_ERROR("OSBDM communication error: invalid swap command reply"); return ERROR_FAIL; } /* Copy TDO responce */ uint8_t *buffer = osbdm->buffer + 4; for (int bit_idx = 0; bit_idx < length; ) { int bit_count = length - bit_idx; if (bit_count > 16) bit_count = 16; /* Prepare data */ uint32_t tdo_data = 0; tdo_data |= (*buffer++) << 8; tdo_data |= (*buffer++); tdo_data >>= (16 - bit_count); /* Copy TDO to return */ buf_set_u32(tdo, bit_idx, bit_count, tdo_data); bit_idx += bit_count; } return ERROR_OK; } static int osbdm_flush(struct osbdm *osbdm, struct queue* queue) { uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)]; uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)]; uint8_t tdo[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)]; int seq_back_len = 0; while (queue->head) { (void)memset(tms, 0, sizeof(tms)); (void)memset(tdi, 0, sizeof(tdi)); (void)memset(tdo, 0, sizeof(tdo)); int seq_len; int swap_len; struct sequence *seq; /* Copy from queue to tms/tdi streams */ seq = queue->head; seq_len = seq_back_len; swap_len = 0; while (seq && swap_len != OSBDM_SWAP_MAX) { /* Count bit for copy at this iteration. * len should fit into remaining space * in tms/tdo bitstreams */ int len = seq->len - seq_len; if (len > OSBDM_SWAP_MAX - swap_len) len = OSBDM_SWAP_MAX - swap_len; /* Set tms data */ buf_set_buf(seq->tms, seq_len, tms, swap_len, len); /* Set tdi data if they exists */ if (seq->tdi) buf_set_buf(seq->tdi, seq_len, tdi, swap_len, len); swap_len += len; seq_len += len; if (seq_len == seq->len) { seq = seq->next; /* Move to next sequence */ seq_len = 0; } } if (osbdm_swap(osbdm, tms, tdi, tdo, swap_len)) return ERROR_FAIL; /* Copy from tdo stream to queue */ for (int swap_back_len = 0; swap_back_len < swap_len; ) { int len = queue->head->len - seq_back_len; if (len > swap_len - swap_back_len) len = swap_len - swap_back_len; if (queue->head->tdo) buf_set_buf(tdo, swap_back_len, queue->head->tdo, seq_back_len, len); swap_back_len += len; seq_back_len += len; if (seq_back_len == queue->head->len) { queue_drop_head(queue); seq_back_len = 0; } } } return ERROR_OK; } /* Basic operation for opening USB device */ static int osbdm_open(struct osbdm *osbdm) { (void)memset(osbdm, 0, sizeof(*osbdm)); if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK) return ERROR_FAIL; if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int osbdm_quit(void) { jtag_libusb_close(osbdm_context.devh); return ERROR_OK; } static int osbdm_add_pathmove( struct queue *queue, tap_state_t *path, int num_states) { assert(num_states <= 32); struct sequence *next = queue_add_tail(queue, num_states); if (!next) { LOG_ERROR("BUG: can't allocate bit sequence"); return ERROR_FAIL; } uint32_t tms = 0; for (int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), 1) == path[i]) { tms |= (1 << i); } else if (tap_state_transition(tap_get_state(), 0) == path[i]) { tms &= ~(1 << i); /* This line not so needed */ } else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); return ERROR_FAIL; } tap_set_state(path[i]); } buf_set_u32(next->tms, 0, num_states, tms); tap_set_end_state(tap_get_state()); return ERROR_OK; } static int osbdm_add_statemove( struct queue *queue, tap_state_t new_state, int skip_first) { int len = 0; int tms = 0; tap_set_end_state(new_state); if (tap_get_end_state() == TAP_RESET) { /* Ignore current state */ tms = 0xff; len = 5; } else if (tap_get_state() != tap_get_end_state()) { tms = tap_get_tms_path(tap_get_state(), new_state); len = tap_get_tms_path_len(tap_get_state(), new_state); } if (len && skip_first) { len--; tms >>= 1; } if (len) { struct sequence *next = queue_add_tail(queue, len); if (!next) { LOG_ERROR("BUG: can't allocate bit sequence"); return ERROR_FAIL; } buf_set_u32(next->tms, 0, len, tms); } tap_set_state(tap_get_end_state()); return ERROR_OK; } static int osbdm_add_stableclocks( struct queue *queue, int count) { if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("BUG: current state (%s) is not stable", tap_state_name(tap_get_state())); return ERROR_FAIL; } struct sequence *next = queue_add_tail(queue, count); if (!next) { LOG_ERROR("BUG: can't allocate bit sequence"); return ERROR_FAIL; } if (tap_get_state() == TAP_RESET) (void)memset(next->tms, 0xff, DIV_ROUND_UP(count, 8)); return ERROR_OK; } static int osbdm_add_tms( struct queue *queue, const uint8_t *tms, int num_bits) { struct sequence *next = queue_add_tail(queue, num_bits); if (!next) { LOG_ERROR("BUG: can't allocate bit sequence"); return ERROR_FAIL; } buf_set_buf(tms, 0, next->tms, 0, num_bits); return ERROR_OK; } static int osbdm_add_scan( struct queue *queue, struct scan_field *fields, int num_fields, tap_state_t end_state, bool ir_scan) { /* Move to desired shift state */ if (ir_scan) { if (tap_get_state() != TAP_IRSHIFT) { if (osbdm_add_statemove(queue, TAP_IRSHIFT, 0) != ERROR_OK) return ERROR_FAIL; } } else { if (tap_get_state() != TAP_DRSHIFT) { if (osbdm_add_statemove(queue, TAP_DRSHIFT, 0) != ERROR_OK) return ERROR_FAIL; } } /* Add scan */ tap_set_end_state(end_state); for (int idx = 0; idx < num_fields; idx++) { struct sequence *next = queue_add_tail(queue, fields[idx].num_bits); if (!next) { LOG_ERROR("Can't allocate bit sequence"); return ERROR_FAIL; } (void)memset(next->tms, 0, DIV_ROUND_UP(fields[idx].num_bits, 8)); next->tdi = fields[idx].out_value; next->tdo = fields[idx].in_value; } /* Move to end state */ if (tap_get_state() != tap_get_end_state()) { /* Exit from IRSHIFT/DRSHIFT */ buf_set_u32(queue->tail->tms, queue->tail->len - 1, 1, 1); /* Move with skip_first flag */ if (osbdm_add_statemove(queue, tap_get_end_state(), 1) != ERROR_OK) return ERROR_FAIL; } return ERROR_OK; } static int osbdm_add_runtest( struct queue *queue, int num_cycles, tap_state_t end_state) { if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK) return ERROR_FAIL; if (osbdm_add_stableclocks(queue, num_cycles) != ERROR_OK) return ERROR_FAIL; if (osbdm_add_statemove(queue, end_state, 0) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static int osbdm_execute_command( struct osbdm *osbdm, struct queue *queue, struct jtag_command *cmd) { int retval = ERROR_OK; switch (cmd->type) { case JTAG_RESET: if (cmd->cmd.reset->trst) { LOG_ERROR("BUG: nTRST signal is not supported"); retval = ERROR_FAIL; } else { retval = osbdm_flush(osbdm, queue); if (retval == ERROR_OK) retval = osbdm_srst(osbdm, cmd->cmd.reset->srst); } break; case JTAG_PATHMOVE: retval = osbdm_add_pathmove( queue, cmd->cmd.pathmove->path, cmd->cmd.pathmove->num_states); break; case JTAG_TLR_RESET: retval = osbdm_add_statemove( queue, cmd->cmd.statemove->end_state, 0); break; case JTAG_STABLECLOCKS: retval = osbdm_add_stableclocks( queue, cmd->cmd.stableclocks->num_cycles); break; case JTAG_TMS: retval = osbdm_add_tms( queue, cmd->cmd.tms->bits, cmd->cmd.tms->num_bits); break; case JTAG_SCAN: retval = osbdm_add_scan( queue, cmd->cmd.scan->fields, cmd->cmd.scan->num_fields, cmd->cmd.scan->end_state, cmd->cmd.scan->ir_scan); break; case JTAG_SLEEP: retval = osbdm_flush(osbdm, queue); if (retval == ERROR_OK) jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_RUNTEST: retval = osbdm_add_runtest( queue, cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); retval = ERROR_FAIL; break; } return retval; } static int osbdm_execute_queue(void) { int retval = ERROR_OK; struct queue *queue = queue_alloc(); if (!queue) { LOG_ERROR("BUG: can't allocate bit queue"); retval = ERROR_FAIL; } else { struct jtag_command *cmd = jtag_command_queue; while (retval == ERROR_OK && cmd) { retval = osbdm_execute_command(&osbdm_context, queue, cmd); cmd = cmd->next; } if (retval == ERROR_OK) retval = osbdm_flush(&osbdm_context, queue); queue_free(queue); } if (retval != ERROR_OK) { LOG_ERROR("FATAL: can't execute jtag command"); exit(-1); } return retval; } static int osbdm_init(void) { /* Open device */ if (osbdm_open(&osbdm_context) != ERROR_OK) { LOG_ERROR("Can't open OSBDM device"); return ERROR_FAIL; } else { /* Device successfully opened */ LOG_DEBUG("OSBDM init"); } /* Perform initialize command */ osbdm_context.count = 0; osbdm_context.buffer[osbdm_context.count++] = OSBDM_CMD_INIT; if (osbdm_send_and_recv(&osbdm_context) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } struct jtag_interface osbdm_interface = { .name = "osbdm", .transports = jtag_only, .execute_queue = osbdm_execute_queue, .init = osbdm_init, .quit = osbdm_quit }; openocd-0.9.0/src/jtag/drivers/bitbang.c0000644000175000017500000003751112516456302015047 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* 2014-12: Addition of the SWD protocol support is based on the initial work * by Paul Fertser and modifications by Jean-Christian de Rivaz. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "bitbang.h" #include #include /* YUK! - but this is currently a global.... */ extern struct jtag_interface *jtag_interface; /** * Function bitbang_stableclocks * issues a number of clock cycles while staying in a stable state. * Because the TMS value required to stay in the RESET state is a 1, whereas * the TMS value required to stay in any of the other stable states is a 0, * this function checks the current stable state to decide on the value of TMS * to use. */ static void bitbang_stableclocks(int num_cycles); struct bitbang_interface *bitbang_interface; /* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work! * * Set this to 1 and str912 reset halt will fail. * * If someone can submit a patch with an explanation it will be greatly * appreciated, but as far as I can tell (ØH) DCLK is generated upon * clk = 0 in TAP_IDLE. Good luck deducing that from the ARM documentation! * The ARM documentation uses the term "DCLK is asserted while in the TAP_IDLE * state". With hardware there is no such thing as *while* in a state. There * are only edges. So clk => 0 is in fact a very subtle state transition that * happens *while* in the TAP_IDLE state. "#&¤"#¤&"#&"#& * * For "reset halt" the last thing that happens before srst is asserted * is that the breakpoint is set up. If DCLK is not wiggled one last * time before the reset, then the breakpoint is not set up and * "reset halt" will fail to halt. * */ #define CLOCK_IDLE() 0 /* The bitbang driver leaves the TCK 0 when in idle */ static void bitbang_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void bitbang_state_move(int skip) { int i = 0, tms = 0; uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = skip; i < tms_count; i++) { tms = (tms_scan >> i) & 1; bitbang_interface->write(0, tms, 0); bitbang_interface->write(1, tms, 0); } bitbang_interface->write(CLOCK_IDLE(), tms, 0); tap_set_state(tap_get_end_state()); } /** * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG * (or SWD) state machine. */ static int bitbang_execute_tms(struct jtag_command *cmd) { unsigned num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; DEBUG_JTAG_IO("TMS: %d bits", num_bits); int tms = 0; for (unsigned i = 0; i < num_bits; i++) { tms = ((bits[i/8] >> (i % 8)) & 1); bitbang_interface->write(0, tms, 0); bitbang_interface->write(1, tms, 0); } bitbang_interface->write(CLOCK_IDLE(), tms, 0); return ERROR_OK; } static void bitbang_path_move(struct pathmove_command *cmd) { int num_states = cmd->num_states; int state_count; int tms = 0; state_count = 0; while (num_states) { if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) tms = 0; else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) tms = 1; else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); exit(-1); } bitbang_interface->write(0, tms, 0); bitbang_interface->write(1, tms, 0); tap_set_state(cmd->path[state_count]); state_count++; num_states--; } bitbang_interface->write(CLOCK_IDLE(), tms, 0); tap_set_end_state(tap_get_state()); } static void bitbang_runtest(int num_cycles) { int i; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { bitbang_end_state(TAP_IDLE); bitbang_state_move(0); } /* execute num_cycles */ for (i = 0; i < num_cycles; i++) { bitbang_interface->write(0, 0, 0); bitbang_interface->write(1, 0, 0); } bitbang_interface->write(CLOCK_IDLE(), 0, 0); /* finish in end_state */ bitbang_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) bitbang_state_move(0); } static void bitbang_stableclocks(int num_cycles) { int tms = (tap_get_state() == TAP_RESET ? 1 : 0); int i; /* send num_cycles clocks onto the cable */ for (i = 0; i < num_cycles; i++) { bitbang_interface->write(1, tms, 0); bitbang_interface->write(0, tms, 0); } } static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { tap_state_t saved_end_state = tap_get_end_state(); int bit_cnt; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { if (ir_scan) bitbang_end_state(TAP_IRSHIFT); else bitbang_end_state(TAP_DRSHIFT); bitbang_state_move(0); bitbang_end_state(saved_end_state); } for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { int val = 0; int tms = (bit_cnt == scan_size-1) ? 1 : 0; int tdi; int bytec = bit_cnt/8; int bcval = 1 << (bit_cnt % 8); /* if we're just reading the scan, but don't care about the output * default to outputting 'low', this also makes valgrind traces more readable, * as it removes the dependency on an uninitialised value */ tdi = 0; if ((type != SCAN_IN) && (buffer[bytec] & bcval)) tdi = 1; bitbang_interface->write(0, tms, tdi); if (type != SCAN_OUT) val = bitbang_interface->read(); bitbang_interface->write(1, tms, tdi); if (type != SCAN_OUT) { if (val) buffer[bytec] |= bcval; else buffer[bytec] &= ~bcval; } } if (tap_get_state() != tap_get_end_state()) { /* we *KNOW* the above loop transitioned out of * the shift state, so we skip the first state * and move directly to the end state. */ bitbang_state_move(1); } } int bitbang_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; int retval; if (!bitbang_interface) { LOG_ERROR("BUG: Bitbang interface called, but not yet initialized"); exit(-1); } /* return ERROR_OK, unless a jtag_read_buffer returns a failed check * that wasn't handled by a caller-provided error handler */ retval = ERROR_OK; if (bitbang_interface->blink) bitbang_interface->blink(1); while (cmd) { switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) tap_set_state(TAP_RESET); bitbang_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); #endif bitbang_end_state(cmd->cmd.runtest->end_state); bitbang_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_STABLECLOCKS: /* this is only allowed while in a stable state. A check for a stable * state was done in jtag_add_clocks() */ bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state)); #endif bitbang_end_state(cmd->cmd.statemove->end_state); bitbang_state_move(0); break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); #endif bitbang_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", tap_state_name(cmd->cmd.scan->end_state)); #endif bitbang_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; if (buffer) free(buffer); break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us); #endif jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_TMS: retval = bitbang_execute_tms(cmd); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } if (bitbang_interface->blink) bitbang_interface->blink(0); return retval; } bool swd_mode; static int queued_retval; static int bitbang_swd_init(void) { LOG_DEBUG("bitbang_swd_init"); swd_mode = true; return ERROR_OK; } static void bitbang_exchange(bool rnw, uint8_t buf[], unsigned int offset, unsigned int bit_cnt) { LOG_DEBUG("bitbang_exchange"); int tdi; for (unsigned int i = offset; i < bit_cnt + offset; i++) { int bytec = i/8; int bcval = 1 << (i % 8); tdi = !rnw && (buf[bytec] & bcval); bitbang_interface->write(0, 0, tdi); if (rnw && buf) { if (bitbang_interface->swdio_read()) buf[bytec] |= bcval; else buf[bytec] &= ~bcval; } bitbang_interface->write(1, 0, tdi); } } int bitbang_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq) { LOG_DEBUG("bitbang_swd_switch_seq"); switch (seq) { case LINE_RESET: LOG_DEBUG("SWD line reset"); bitbang_exchange(false, (uint8_t *)swd_seq_line_reset, 0, swd_seq_line_reset_len); break; case JTAG_TO_SWD: LOG_DEBUG("JTAG-to-SWD"); bitbang_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len); break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); bitbang_exchange(false, (uint8_t *)swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len); break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; } return ERROR_OK; } void bitbang_switch_to_swd(void) { LOG_DEBUG("bitbang_switch_to_swd"); bitbang_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len); } static void swd_clear_sticky_errors(struct adiv5_dap *dap) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); swd->write_reg(dap, swd_cmd(false, false, DP_ABORT), STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR); } static void bitbang_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value) { LOG_DEBUG("bitbang_swd_read_reg"); assert(cmd & SWD_CMD_RnW); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skip bitbang_swd_read_reg because queued_retval=%d", queued_retval); return; } for (;;) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; cmd |= SWD_CMD_START | (1 << 7); bitbang_exchange(false, &cmd, 0, 8); bitbang_interface->swdio_drive(false); bitbang_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 32 + 1 + 1); bitbang_interface->swdio_drive(true); int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3); uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32); int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1); LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", cmd & SWD_CMD_APnDP ? "AP" : "DP", cmd & SWD_CMD_RnW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, data); switch (ack) { case SWD_ACK_OK: if (parity != parity_u32(data)) { LOG_DEBUG("Wrong parity detected"); queued_retval = ERROR_FAIL; return; } if (value) *value = data; if (cmd & SWD_CMD_APnDP) bitbang_exchange(true, NULL, 0, dap->memaccess_tck); return; case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); swd_clear_sticky_errors(dap); break; case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; } } } static void bitbang_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value) { LOG_DEBUG("bitbang_swd_write_reg"); assert(!(cmd & SWD_CMD_RnW)); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skip bitbang_swd_write_reg because queued_retval=%d", queued_retval); return; } for (;;) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value); buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value)); cmd |= SWD_CMD_START | (1 << 7); bitbang_exchange(false, &cmd, 0, 8); bitbang_interface->swdio_drive(false); bitbang_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 1); bitbang_interface->swdio_drive(true); bitbang_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1); int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3); LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", cmd & SWD_CMD_APnDP ? "AP" : "DP", cmd & SWD_CMD_RnW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); switch (ack) { case SWD_ACK_OK: if (cmd & SWD_CMD_APnDP) bitbang_exchange(true, NULL, 0, dap->memaccess_tck); return; case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); swd_clear_sticky_errors(dap); break; case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; } } } static int bitbang_swd_run_queue(struct adiv5_dap *dap) { LOG_DEBUG("bitbang_swd_run_queue"); /* A transaction must be followed by another transaction or at least 8 idle cycles to * ensure that data is clocked through the AP. */ bitbang_exchange(true, NULL, 0, 8); int retval = queued_retval; queued_retval = ERROR_OK; LOG_DEBUG("SWD queue return value: %02x", retval); return retval; } const struct swd_driver bitbang_swd = { .init = bitbang_swd_init, .switch_seq = bitbang_swd_switch_seq, .read_reg = bitbang_swd_read_reg, .write_reg = bitbang_swd_write_reg, .run = bitbang_swd_run_queue, }; openocd-0.9.0/src/jtag/drivers/bitbang.h0000644000175000017500000000436512516456302015055 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef BITBANG_H #define BITBANG_H #include struct bitbang_interface { /* low level callbacks (for bitbang) */ int (*read)(void); void (*write)(int tck, int tms, int tdi); void (*reset)(int trst, int srst); void (*blink)(int on); int (*swdio_read)(void); void (*swdio_drive)(bool on); }; const struct swd_driver bitbang_swd; extern bool swd_mode; int bitbang_execute_queue(void); extern struct bitbang_interface *bitbang_interface; void bitbang_switch_to_swd(void); int bitbang_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq); #endif /* BITBANG_H */ openocd-0.9.0/src/jtag/drivers/openjtag.c0000644000175000017500000005266312315575360015260 00000000000000/******************************************************************************* * Driver for OpenJTAG Project (www.openjtag.org) * * Compatible with libftdi and ftd2xx drivers. * * * * Copyright (C) 2010 by Ivan Meleca * * * * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. * * Updated to work with OpenOCD v0.7.0. Fixed libftdi read speed issue. * * * * Based on usb_blaster.c * * Copyright (C) 2009 Catalin Patulea * * Copyright (C) 2006 Kolja Waschk * * * * And jlink.c * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /*************************************************************************** * Version 1.0 Tested on a MCBSTM32 board using a Cortex M3 (stm32f103x), * * GDB and Eclipse under Linux (Ubuntu 10.04) * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "usb_common.h" /* * OpenJTAG-OpenOCD state conversion */ typedef enum openjtag_tap_state { OPENJTAG_TAP_INVALID = -1, OPENJTAG_TAP_RESET = 0, OPENJTAG_TAP_IDLE = 1, OPENJTAG_TAP_SELECT_DR = 2, OPENJTAG_TAP_CAPTURE_DR = 3, OPENJTAG_TAP_SHIFT_DR = 4, OPENJTAG_TAP_EXIT1_DR = 5, OPENJTAG_TAP_PAUSE_DR = 6, OPENJTAG_TAP_EXIT2_DR = 7, OPENJTAG_TAP_UPDATE_DR = 8, OPENJTAG_TAP_SELECT_IR = 9, OPENJTAG_TAP_CAPURE_IR = 10, OPENJTAG_TAP_SHIFT_IR = 11, OPENJTAG_TAP_EXIT1_IR = 12, OPENJTAG_TAP_PAUSE_IR = 13, OPENJTAG_TAP_EXIT2_IR = 14, OPENJTAG_TAP_UPDATE_IR = 15, } openjtag_tap_state_t; #if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1) #error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI " "are mutually exclusive" #elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1) #error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen" #endif /* OPENJTAG access library includes */ #if BUILD_OPENJTAG_FTD2XX == 1 #include #elif BUILD_OPENJTAG_LIBFTDI == 1 #include #endif /* OpenJTAG vid/pid */ static uint16_t openjtag_vid = 0x0403; static uint16_t openjtag_pid = 0x6001; static char *openjtag_device_desc; #if BUILD_OPENJTAG_FTD2XX == 1 static FT_HANDLE ftdih; #elif BUILD_OPENJTAG_LIBFTDI == 1 static struct ftdi_context ftdic; #endif #define OPENJTAG_BUFFER_SIZE 504 #define OPENJTAG_MAX_PENDING_RESULTS 256 struct openjtag_scan_result { uint32_t bits; /* Length in bits*/ struct scan_command *command; /* Corresponding scan command */ uint8_t *buffer; }; /* USB RX/TX buffers */ static int usb_tx_buf_offs; static uint8_t usb_tx_buf[OPENJTAG_BUFFER_SIZE]; static uint32_t usb_rx_buf_len; static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE]; /* Pending readings */ static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS]; static int openjtag_scan_result_count; /* Openocd usb handler */ struct openocd { struct usb_dev_handle *usb_handle; }; #ifdef _DEBUG_USB_COMMS_ #define DEBUG_TYPE_READ 0 #define DEBUG_TYPE_WRITE 1 #define DEBUG_TYPE_OCD_READ 2 #define DEBUG_TYPE_BUFFER 3 #define LINE_LEN 16 static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type) { char line[128]; char s[4]; int i; int j; switch (type) { case DEBUG_TYPE_READ: sprintf(line, "USB READ %d bytes", length); break; case DEBUG_TYPE_WRITE: sprintf(line, "USB WRITE %d bytes", length); break; case DEBUG_TYPE_OCD_READ: sprintf(line, "TO OpenOCD %d bytes", length); break; case DEBUG_TYPE_BUFFER: sprintf(line, "Buffer %d bytes", length); break; } LOG_DEBUG("%s", line); for (i = 0; i < length; i += LINE_LEN) { switch (type) { case DEBUG_TYPE_READ: sprintf(line, "USB READ: %04x", i); break; case DEBUG_TYPE_WRITE: sprintf(line, "USB WRITE: %04x", i); break; case DEBUG_TYPE_OCD_READ: sprintf(line, "TO OpenOCD: %04x", i); break; case DEBUG_TYPE_BUFFER: sprintf(line, "BUFFER: %04x", i); break; } for (j = i; j < i + LINE_LEN && j < length; j++) { sprintf(s, " %02x", buffer[j]); strcat(line, s); } LOG_DEBUG("%s", line); } } #endif static int8_t openjtag_get_tap_state(int8_t state) { switch (state) { case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR; case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR; case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR; case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR; case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR; case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR; case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR; case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR; case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR; case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR; case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR; case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR; case TAP_IDLE: return OPENJTAG_TAP_IDLE; case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR; case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR; case TAP_RESET: return OPENJTAG_TAP_RESET; case TAP_INVALID: default: return OPENJTAG_TAP_INVALID; } } static int openjtag_buf_write( uint8_t *buf, int size, uint32_t *bytes_written) { #if BUILD_OPENJTAG_FTD2XX == 1 FT_STATUS status; DWORD dw_bytes_written; #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); #endif status = FT_Write(ftdih, buf, size, &dw_bytes_written); if (status != FT_OK) { *bytes_written = dw_bytes_written; LOG_ERROR("FT_Write returned: %u", status); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written = dw_bytes_written; return ERROR_OK; #elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); #endif retval = ftdi_write_data(&ftdic, buf, size); if (retval < 0) { *bytes_written = 0; LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written += retval; return ERROR_OK; #endif } static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) { #if BUILD_OPENJTAG_FTD2XX == 1 DWORD dw_bytes_read; FT_STATUS status; int timeout = 50; *bytes_read = 0; while (qty && (*bytes_read < qty) && timeout--) { status = FT_Read(ftdih, buf + *bytes_read, qty - *bytes_read, &dw_bytes_read); if (status != FT_OK) { *bytes_read = dw_bytes_read; LOG_ERROR("FT_Read returned: %u", status); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += dw_bytes_read; } #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif return ERROR_OK; #elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; int timeout = 5; *bytes_read = 0; while ((*bytes_read < qty) && timeout--) { retval = ftdi_read_data(&ftdic, buf + *bytes_read, qty - *bytes_read); if (retval < 0) { *bytes_read = 0; DEBUG_JTAG_IO("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += retval; } #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif #endif return ERROR_OK; } static int openjtag_sendcommand(uint8_t cmd) { uint32_t written; return openjtag_buf_write(&cmd, 1, &written); } static int openjtag_speed(int speed) { int clockcmd; switch (speed) { case 48000: clockcmd = 0x00; break; case 24000: clockcmd = 0x20; break; case 12000: clockcmd = 0x40; break; case 6000: clockcmd = 0x60; break; case 3000: clockcmd = 0x80; break; case 1500: clockcmd = 0xA0; break; case 750: clockcmd = 0xC0; break; case 375: clockcmd = 0xE0; break; default: clockcmd = 0xE0; LOG_WARNING("adapter speed not recognized, reverting to 375 kHz"); break; } openjtag_sendcommand(clockcmd); return ERROR_OK; } static int openjtag_init(void) { uint8_t latency_timer; #if BUILD_OPENJTAG_FTD2XX == 1 FT_STATUS status; #endif usb_tx_buf_offs = 0; usb_rx_buf_len = 0; openjtag_scan_result_count = 0; #if BUILD_OPENJTAG_FTD2XX == 1 LOG_DEBUG("'openjtag' interface using FTD2XX"); #elif BUILD_OPENJTAG_LIBFTDI == 1 LOG_DEBUG("'openjtag' interface using libftdi"); #endif /* Open by device description */ if (openjtag_device_desc == NULL) { LOG_WARNING("no openjtag device description specified, " "using default 'Open JTAG Project'"); openjtag_device_desc = "Open JTAG Project"; } #if BUILD_OPENJTAG_FTD2XX == 1 #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ status = FT_SetVIDPID(openjtag_vid, openjtag_pid); if (status != FT_OK) { LOG_WARNING("couldn't add %4.4x:%4.4x", openjtag_vid, openjtag_pid); } #endif status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION, &ftdih); if (status != FT_OK) { DWORD num_devices; LOG_ERROR("unable to open ftdi device: %u", status); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); unsigned int i; for (i = 0; i < num_devices; i++) desc_array[i] = malloc(64); desc_array[num_devices] = NULL; status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); if (status == FT_OK) { LOG_ERROR("ListDevices: %u\n", num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%i: %s", i, desc_array[i]); } for (i = 0; i < num_devices; i++) free(desc_array[i]); free(desc_array); } else { LOG_ERROR("ListDevices: NONE\n"); } return ERROR_JTAG_INIT_FAILED; } status = FT_SetLatencyTimer(ftdih, 2); if (status != FT_OK) { LOG_ERROR("unable to set latency timer: %u", status); return ERROR_JTAG_INIT_FAILED; } status = FT_GetLatencyTimer(ftdih, &latency_timer); if (status != FT_OK) { LOG_ERROR("unable to get latency timer: %u", status); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("current latency timer: %i", latency_timer); status = FT_SetBitMode(ftdih, 0x00, 0x40); if (status != FT_OK) { LOG_ERROR("unable to disable bit i/o mode: %u", status); return ERROR_JTAG_INIT_FAILED; } status = FT_SetTimeouts(ftdih, 50, 0); if (status != FT_OK) { LOG_ERROR("unable to set timeouts: %u", status); return ERROR_JTAG_INIT_FAILED; } status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); if (status != FT_OK) { LOG_ERROR("unable to FT_Purge() %u", status); return ERROR_JTAG_INIT_FAILED; } #elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; /* context, vendor id, product id, description, serial id */ if (ftdi_usb_open_desc(&ftdic, openjtag_vid, openjtag_pid, openjtag_device_desc, NULL) < 0) { LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } if (ftdi_usb_reset(&ftdic) < 0) { LOG_ERROR("unable to reset ftdi device"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_set_latency_timer(&ftdic, 2) < 0) { LOG_ERROR("unable to set latency timer"); return ERROR_JTAG_INIT_FAILED; } if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) { LOG_ERROR("unable to get latency timer"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("current latency timer: %u", latency_timer); ftdi_disable_bitbang(&ftdic); /* was (3000000 / 4) with a comment about a bug in libftdi when using high baudrate */ if (ftdi_set_baudrate(&ftdic, 3000000) < 0) { LOG_ERROR("Can't set baud rate to max: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; }; #endif #if BUILD_OPENJTAG_FTD2XX == 1 status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); if (status != FT_OK) return ERROR_JTAG_INIT_FAILED; #elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_usb_purge_buffers(&ftdic) < 0) { LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } #endif /* OpenJTAG speed */ openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ /* MSB */ openjtag_sendcommand(0x75); return ERROR_OK; } static int openjtag_quit(void) { #if BUILD_OPENJTAG_FTD2XX == 1 FT_Close(ftdih); #elif BUILD_OPENJTAG_LIBFTDI == 1 ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); #endif return ERROR_OK; } static void openjtag_write_tap_buffer(void) { uint32_t written; openjtag_buf_write(usb_tx_buf, usb_tx_buf_offs, &written); openjtag_buf_read(usb_rx_buf, usb_tx_buf_offs, &usb_rx_buf_len); usb_tx_buf_offs = 0; } static int openjtag_execute_tap_queue(void) { openjtag_write_tap_buffer(); int res_count = 0; if (openjtag_scan_result_count && usb_rx_buf_len) { int count; int rx_offs = 0; int len; /* for every pending result */ while (res_count < openjtag_scan_result_count) { /* get sent bits */ len = openjtag_scan_result_buffer[res_count].bits; count = 0; uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer; while (len) { if (len <= 8) { DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X", usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len)); buffer[count] = usb_rx_buf[rx_offs] >> (8 - len); len = 0; } else { buffer[count] = usb_rx_buf[rx_offs]; len -= 8; } rx_offs++; count++; } #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buffer, DIV_ROUND_UP(openjtag_scan_result_buffer[res_count].bits, 8), DEBUG_TYPE_OCD_READ); #endif jtag_read_buffer(buffer, openjtag_scan_result_buffer[res_count].command); if (openjtag_scan_result_buffer[res_count].buffer) free(openjtag_scan_result_buffer[res_count].buffer); res_count++; } } openjtag_scan_result_count = 0; return ERROR_OK; } static void openjtag_add_byte(char buf) { if (usb_tx_buf_offs == OPENJTAG_BUFFER_SIZE) { DEBUG_JTAG_IO("Forcing execute_tap_queue"); DEBUG_JTAG_IO("TX Buff offs=%d", usb_tx_buf_offs); openjtag_execute_tap_queue(); } usb_tx_buf[usb_tx_buf_offs] = buf; usb_tx_buf_offs++; } static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *scan_cmd) { /* Ensure space to send long chains */ /* We add two byte for each eight (or less) bits, one for command, one for data */ if (usb_tx_buf_offs + (DIV_ROUND_UP(length, 8) * 2) >= OPENJTAG_BUFFER_SIZE) { DEBUG_JTAG_IO("Forcing execute_tap_queue from scan"); DEBUG_JTAG_IO("TX Buff offs=%d len=%d", usb_tx_buf_offs, DIV_ROUND_UP(length, 8) * 2); openjtag_execute_tap_queue(); } openjtag_scan_result_buffer[openjtag_scan_result_count].bits = length; openjtag_scan_result_buffer[openjtag_scan_result_count].command = scan_cmd; openjtag_scan_result_buffer[openjtag_scan_result_count].buffer = buffer; uint8_t command; uint8_t bits; int count = 0; while (length) { /* write command */ command = 6; /* last bits? */ if (length <= 8) { /* tms high */ command |= (1 << 4); /* bits to transfer */ bits = (length - 1); command |= bits << 5; length = 0; } else { /* whole byte */ /* bits to transfer */ bits = 7; command |= (7 << 5); length -= 8; } openjtag_add_byte(command); openjtag_add_byte(buffer[count]); count++; } openjtag_scan_result_count++; } static void openjtag_execute_reset(struct jtag_command *cmd) { DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); uint8_t buf = 0x00; if (cmd->cmd.reset->trst) { buf = 0x03; } else { buf |= 0x04; buf |= 0x05 << 4; } openjtag_add_byte(buf); } static void openjtag_execute_sleep(struct jtag_command *cmd) { jtag_sleep(cmd->cmd.sleep->us); } static void openjtag_set_state(uint8_t openocd_state) { int8_t state = openjtag_get_tap_state(openocd_state); uint8_t buf = 0; buf = 0x01; buf |= state << 4; openjtag_add_byte(buf); } static void openjtag_execute_statemove(struct jtag_command *cmd) { DEBUG_JTAG_IO("state move to %i", cmd->cmd.statemove->end_state); tap_set_end_state(cmd->cmd.statemove->end_state); openjtag_set_state(cmd->cmd.statemove->end_state); tap_set_state(tap_get_end_state()); } static void openjtag_execute_scan(struct jtag_command *cmd) { int scan_size, old_state; uint8_t *buffer; DEBUG_JTAG_IO("scan ends in %s", tap_state_name(cmd->cmd.scan->end_state)); /* get scan info */ tap_set_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buffer, (scan_size + 7) / 8, DEBUG_TYPE_BUFFER); #endif /* set state */ old_state = tap_get_end_state(); openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); tap_set_end_state(old_state); openjtag_add_scan(buffer, scan_size, cmd->cmd.scan); openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); if (tap_get_state() != tap_get_end_state()) { openjtag_set_state(tap_get_end_state()); tap_set_state(tap_get_end_state()); } } static void openjtag_execute_runtest(struct jtag_command *cmd) { tap_state_t end_state = cmd->cmd.runtest->end_state; tap_set_end_state(end_state); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { openjtag_set_state(TAP_IDLE); tap_set_state(TAP_IDLE); } if (cmd->cmd.runtest->num_cycles > 16) LOG_WARNING("num_cycles > 16 on run test"); uint8_t command; command = 7; command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; openjtag_add_byte(command); tap_set_end_state(end_state); if (tap_get_end_state() != tap_get_state()) { openjtag_set_state(end_state); tap_set_state(end_state); } } static void openjtag_execute_command(struct jtag_command *cmd) { DEBUG_JTAG_IO("openjtag_execute_command %i", cmd->type); switch (cmd->type) { case JTAG_RESET: openjtag_execute_reset(cmd); break; case JTAG_SLEEP: openjtag_execute_sleep(cmd); break; case JTAG_TLR_RESET: openjtag_execute_statemove(cmd); break; case JTAG_SCAN: openjtag_execute_scan(cmd); break; case JTAG_RUNTEST: openjtag_execute_runtest(cmd); break; case JTAG_PATHMOVE: /* jlink_execute_pathmove(cmd); break; */ default: LOG_ERROR("BUG: unknown Open JTAG command type encountered"); exit(-1); } } static int openjtag_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; while (cmd != NULL) { openjtag_execute_command(cmd); cmd = cmd->next; } return openjtag_execute_tap_queue(); } static int openjtag_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } static int openjtag_khz(int khz, int *jtag_speed) { if (khz >= 48000) *jtag_speed = 48000; else if (khz >= 24000) *jtag_speed = 24000; else if (khz >= 12000) *jtag_speed = 12000; else if (khz >= 6000) *jtag_speed = 6000; else if (khz >= 3000) *jtag_speed = 3000; else if (khz >= 1500) *jtag_speed = 1500; else if (khz >= 750) *jtag_speed = 750; else *jtag_speed = 375; return ERROR_OK; } COMMAND_HANDLER(openjtag_handle_device_desc_command) { if (CMD_ARGC == 1) openjtag_device_desc = strdup(CMD_ARGV[0]); else LOG_ERROR("require exactly one argument to " "openjtag_device_desc "); return ERROR_OK; } static const struct command_registration openjtag_command_handlers[] = { { .name = "openjtag_device_desc", .handler = openjtag_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the OpenJTAG", .usage = "description-string", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface openjtag_interface = { .name = "openjtag", .commands = openjtag_command_handlers, .execute_queue = openjtag_execute_queue, .speed = openjtag_speed, .speed_div = openjtag_speed_div, .khz = openjtag_khz, .init = openjtag_init, .quit = openjtag_quit, }; openocd-0.9.0/src/jtag/drivers/versaloon/0000755000175000017500000000000012526202225015350 500000000000000openocd-0.9.0/src/jtag/drivers/versaloon/versaloon_include.h0000644000175000017500000001065012516456303021165 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* This file is used to include different header and macros */ /* according to different platform */ #include #include #define PARAM_CHECK 1 #define sleep_ms(ms) jtag_sleep((ms) * 1000) #define dimof(arr) (sizeof(arr) / sizeof((arr)[0])) #define TO_STR(name) #name #define RESULT int #define LOG_BUG LOG_ERROR /* Common error messages */ #define ERRMSG_NOT_ENOUGH_MEMORY "Lack of memory." #define ERRCODE_NOT_ENOUGH_MEMORY ERROR_FAIL #define ERRMSG_INVALID_VALUE "%d is invalid for %s." #define ERRMSG_INVALID_INDEX "Index %d is invalid for %s." #define ERRMSG_INVALID_USAGE "Invalid usage of %s" #define ERRMSG_INVALID_TARGET "Invalid %s" #define ERRMSG_INVALID_PARAMETER "Invalid parameter of %s." #define ERRMSG_INVALID_INTERFACE_NUM "invalid inteface %d" #define ERRMSG_INVALID_BUFFER "Buffer %s is not valid." #define ERRCODE_INVALID_BUFFER ERROR_FAIL #define ERRCODE_INVALID_PARAMETER ERROR_FAIL #define ERRMSG_NOT_SUPPORT_BY "%s is not supported by %s." #define ERRMSG_FAILURE_OPERATION "Fail to %s." #define ERRMSG_FAILURE_OPERATION_MESSAGE "Fail to %s, %s" #define ERRCODE_FAILURE_OPERATION ERROR_FAIL #define GET_U16_MSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 8) | \ ((*((uint8_t *)(p) + 1)) << 0)) #define GET_U32_MSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 24) | \ ((*((uint8_t *)(p) + 1)) << 16) | \ ((*((uint8_t *)(p) + 2)) << 8) | \ ((*((uint8_t *)(p) + 3)) << 0)) #define GET_U16_LSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 0) | \ ((*((uint8_t *)(p) + 1)) << 8)) #define GET_U32_LSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 0) | \ ((*((uint8_t *)(p) + 1)) << 8) | \ ((*((uint8_t *)(p) + 2)) << 16) | \ ((*((uint8_t *)(p) + 3)) << 24)) #define SET_U16_MSBFIRST(p, v) \ do {\ *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 8) & 0xFF;\ *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 0) & 0xFF;\ } while (0) #define SET_U32_MSBFIRST(p, v) \ do {\ *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 24) & 0xFF;\ *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 16) & 0xFF;\ *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 8) & 0xFF;\ *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 0) & 0xFF;\ } while (0) #define SET_U16_LSBFIRST(p, v) \ do {\ *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 0) & 0xFF;\ *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 8) & 0xFF;\ } while (0) #define SET_U32_LSBFIRST(p, v) \ do {\ *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 0) & 0xFF;\ *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 8) & 0xFF;\ *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 16) & 0xFF;\ *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 24) & 0xFF;\ } while (0) #define GET_LE_U16(p) GET_U16_LSBFIRST(p) #define GET_LE_U32(p) GET_U32_LSBFIRST(p) #define GET_BE_U16(p) GET_U16_MSBFIRST(p) #define GET_BE_U32(p) GET_U32_MSBFIRST(p) #define SET_LE_U16(p, v) SET_U16_LSBFIRST(p, v) #define SET_LE_U32(p, v) SET_U32_LSBFIRST(p, v) #define SET_BE_U16(p, v) SET_U16_MSBFIRST(p, v) #define SET_BE_U32(p, v) SET_U32_MSBFIRST(p, v) openocd-0.9.0/src/jtag/drivers/versaloon/versaloon.c0000644000175000017500000002370512516456303017462 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "versaloon_include.h" #include "versaloon.h" #include "versaloon_internal.h" #include "usbtoxxx/usbtoxxx.h" uint8_t *versaloon_buf; uint8_t *versaloon_cmd_buf; uint16_t versaloon_buf_size; struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; uint16_t versaloon_pending_idx; libusb_device_handle *versaloon_usb_device_handle; static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT; RESULT versaloon_init(void); RESULT versaloon_fini(void); RESULT versaloon_get_target_voltage(uint16_t *voltage); RESULT versaloon_set_target_voltage(uint16_t voltage); RESULT versaloon_delay_ms(uint16_t ms); RESULT versaloon_delay_us(uint16_t us); struct versaloon_interface_t versaloon_interface = { .init = versaloon_init, .fini = versaloon_fini, { /* adaptors */ { /* target_voltage */ .get = versaloon_get_target_voltage, .set = versaloon_set_target_voltage, }, { /* gpio */ .init = usbtogpio_init, .fini = usbtogpio_fini, .config = usbtogpio_config, .out = usbtogpio_out, .in = usbtogpio_in, }, { /* delay */ .delayms = versaloon_delay_ms, .delayus = versaloon_delay_us, }, { /* swd */ .init = usbtoswd_init, .fini = usbtoswd_fini, .config = usbtoswd_config, .seqout = usbtoswd_seqout, .seqin = usbtoswd_seqin, .transact = usbtoswd_transact, }, { /* jtag_raw */ .init = usbtojtagraw_init, .fini = usbtojtagraw_fini, .config = usbtojtagraw_config, .execute = usbtojtagraw_execute, }, .peripheral_commit = usbtoxxx_execute_command, }, { /* usb_setting */ .vid = VERSALOON_VID, .pid = VERSALOON_PID, .ep_out = VERSALOON_OUTP, .ep_in = VERSALOON_INP, .interface = VERSALOON_IFACE, .serialstring = NULL, .buf_size = 256, } }; /* programmer_cmd */ static uint32_t versaloon_pending_id; static versaloon_callback_t versaloon_callback; static void *versaloon_extra_data; static struct versaloon_want_pos_t *versaloon_want_pos; void versaloon_set_pending_id(uint32_t id) { versaloon_pending_id = id; } void versaloon_set_callback(versaloon_callback_t callback) { versaloon_callback = callback; } void versaloon_set_extra_data(void *p) { versaloon_extra_data = p; } void versaloon_free_want_pos(void) { uint16_t i; struct versaloon_want_pos_t *tmp, *free_tmp; tmp = versaloon_want_pos; while (tmp != NULL) { free_tmp = tmp; tmp = tmp->next; free(free_tmp); } versaloon_want_pos = NULL; for (i = 0; i < dimof(versaloon_pending); i++) { tmp = versaloon_pending[i].pos; while (tmp != NULL) { free_tmp = tmp; tmp = tmp->next; free(free_tmp); } versaloon_pending[i].pos = NULL; } } RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff) { struct versaloon_want_pos_t *new_pos = NULL; new_pos = malloc(sizeof(*new_pos)); if (NULL == new_pos) { LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); return ERRCODE_NOT_ENOUGH_MEMORY; } new_pos->offset = offset; new_pos->size = size; new_pos->buff = buff; new_pos->next = NULL; if (NULL == versaloon_want_pos) versaloon_want_pos = new_pos; else { struct versaloon_want_pos_t *tmp = versaloon_want_pos; while (tmp->next != NULL) tmp = tmp->next; tmp->next = new_pos; } return ERROR_OK; } RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect) { #if PARAM_CHECK if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) { LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx, "versaloon pending data"); return ERROR_FAIL; } #endif versaloon_pending[versaloon_pending_idx].type = type; versaloon_pending[versaloon_pending_idx].cmd = cmd; versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie; versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos; versaloon_pending[versaloon_pending_idx].want_data_size = want_size; versaloon_pending[versaloon_pending_idx].data_buffer = buffer; versaloon_pending[versaloon_pending_idx].collect = collect; versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id; versaloon_pending_id = 0; versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data; versaloon_extra_data = NULL; versaloon_pending[versaloon_pending_idx].callback = versaloon_callback; versaloon_callback = NULL; versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos; versaloon_want_pos = NULL; versaloon_pending_idx++; return ERROR_OK; } RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen) { int ret; int transferred; #if PARAM_CHECK if (NULL == versaloon_buf) { LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf)); return ERRCODE_INVALID_BUFFER; } if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) { LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__); return ERRCODE_INVALID_PARAMETER; } #endif ret = libusb_bulk_transfer(versaloon_usb_device_handle, versaloon_interface.usb_setting.ep_out, versaloon_buf, out_len, &transferred, versaloon_usb_to); if (0 != ret || transferred != out_len) { LOG_ERROR(ERRMSG_FAILURE_OPERATION, "send usb data"); return ERRCODE_FAILURE_OPERATION; } if (inlen != NULL) { ret = libusb_bulk_transfer(versaloon_usb_device_handle, versaloon_interface.usb_setting.ep_in, versaloon_buf, versaloon_interface.usb_setting.buf_size, &transferred, versaloon_usb_to); if (0 == ret) { *inlen = (uint16_t)transferred; return ERROR_OK; } else { LOG_ERROR(ERRMSG_FAILURE_OPERATION, "receive usb data"); return ERROR_FAIL; } } else return ERROR_OK; } #define VERSALOON_RETRY_CNT 10 RESULT versaloon_init(void) { uint16_t ret = 0; uint8_t retry; uint32_t timeout_tmp; /* malloc temporary buffer */ versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size); if (NULL == versaloon_buf) { LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); return ERRCODE_NOT_ENOUGH_MEMORY; } /* connect to versaloon */ timeout_tmp = versaloon_usb_to; /* not output error message when connectting */ /* 100ms delay when connect */ versaloon_usb_to = 100; for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) { versaloon_buf[0] = VERSALOON_GET_INFO; if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3)) break; } versaloon_usb_to = timeout_tmp; if (VERSALOON_RETRY_CNT == retry) { versaloon_fini(); LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon"); return ERRCODE_FAILURE_OPERATION; } versaloon_buf[ret] = 0; versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8); versaloon_interface.usb_setting.buf_size = versaloon_buf_size; LOG_INFO("%s", versaloon_buf + 2); /* free temporary buffer */ free(versaloon_buf); versaloon_buf = NULL; versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size); if (NULL == versaloon_buf) { versaloon_fini(); LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); return ERRCODE_NOT_ENOUGH_MEMORY; } versaloon_cmd_buf = malloc(versaloon_interface.usb_setting.buf_size - 3); if (NULL == versaloon_cmd_buf) { versaloon_fini(); LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); return ERRCODE_NOT_ENOUGH_MEMORY; } if (ERROR_OK != usbtoxxx_init()) { LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx"); return ERROR_FAIL; } return versaloon_get_target_voltage(&ret); } RESULT versaloon_fini(void) { if (versaloon_usb_device_handle != NULL) { usbtoxxx_fini(); versaloon_free_want_pos(); versaloon_usb_device_handle = NULL; if (versaloon_buf != NULL) { free(versaloon_buf); versaloon_buf = NULL; } if (versaloon_cmd_buf != NULL) { free(versaloon_cmd_buf); versaloon_cmd_buf = NULL; } } return ERROR_OK; } RESULT versaloon_set_target_voltage(uint16_t voltage) { usbtopwr_init(0); usbtopwr_config(0); usbtopwr_output(0, voltage); usbtopwr_fini(0); return usbtoxxx_execute_command(); } RESULT versaloon_get_target_voltage(uint16_t *voltage) { uint16_t inlen; #if PARAM_CHECK if (NULL == versaloon_buf) { LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf)); return ERRCODE_INVALID_BUFFER; } if (NULL == voltage) { LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__); return ERRCODE_INVALID_PARAMETER; } #endif versaloon_buf[0] = VERSALOON_GET_TVCC; if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) { LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon"); return ERRCODE_FAILURE_OPERATION; } else { *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8); return ERROR_OK; } } RESULT versaloon_delay_ms(uint16_t ms) { return usbtodelay_delay(ms | 0x8000); } RESULT versaloon_delay_us(uint16_t us) { return usbtodelay_delay(us & 0x7FFF); } openocd-0.9.0/src/jtag/drivers/versaloon/versaloon.h0000644000175000017500000000760112516456303017464 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __VERSALOON_H_INCLUDED__ #define __VERSALOON_H_INCLUDED__ #include struct usart_status_t { uint32_t tx_buff_avail; uint32_t tx_buff_size; uint32_t rx_buff_avail; uint32_t rx_buff_size; }; #include "usbtoxxx/usbtoxxx.h" /* GPIO pins */ #define GPIO_SRST (1 << 0) #define GPIO_TRST (1 << 1) #define GPIO_USR1 (1 << 2) #define GPIO_USR2 (1 << 3) #define GPIO_TCK (1 << 4) #define GPIO_TDO (1 << 5) #define GPIO_TDI (1 << 6) #define GPIO_RTCK (1 << 7) #define GPIO_TMS (1 << 8) struct interface_gpio_t { RESULT(*init)(uint8_t interface_index); RESULT(*fini)(uint8_t interface_index); RESULT(*config)(uint8_t interface_index, uint32_t pin_mask, uint32_t io, uint32_t pull_en_mask, uint32_t input_pull_mask); RESULT(*out)(uint8_t interface_index, uint32_t pin_mask, uint32_t value); RESULT(*in)(uint8_t interface_index, uint32_t pin_mask, uint32_t *value); }; struct interface_delay_t { RESULT(*delayms)(uint16_t ms); RESULT(*delayus)(uint16_t us); }; struct interface_swd_t { RESULT(*init)(uint8_t interface_index); RESULT(*fini)(uint8_t interface_index); RESULT(*config)(uint8_t interface_index, uint8_t trn, uint16_t retry, uint16_t dly); RESULT(*seqout)(uint8_t interface_index, const uint8_t *data, uint16_t bitlen); RESULT(*seqin)(uint8_t interface_index, uint8_t *data, uint16_t bitlen); RESULT(*transact)(uint8_t interface_index, uint8_t request, uint32_t *data, uint8_t *ack); }; struct interface_jtag_raw_t { RESULT(*init)(uint8_t interface_index); RESULT(*fini)(uint8_t interface_index); RESULT(*config)(uint8_t interface_index, uint32_t kHz); RESULT(*execute)(uint8_t interface_index, uint8_t *tdi, uint8_t *tms, uint8_t *tdo, uint32_t bitlen); }; struct interface_target_voltage_t { RESULT(*get)(uint16_t *voltage); RESULT(*set)(uint16_t voltage); }; struct versaloon_adaptors_t { struct interface_target_voltage_t target_voltage; struct interface_gpio_t gpio; struct interface_delay_t delay; struct interface_swd_t swd; struct interface_jtag_raw_t jtag_raw; RESULT(*peripheral_commit)(void); }; struct versaloon_usb_setting_t { uint16_t vid; uint16_t pid; uint8_t ep_out; uint8_t ep_in; uint8_t interface; char *serialstring; uint16_t buf_size; }; struct versaloon_interface_t { RESULT(*init)(void); RESULT(*fini)(void); struct versaloon_adaptors_t adaptors; struct versaloon_usb_setting_t usb_setting; }; extern struct versaloon_interface_t versaloon_interface; extern libusb_device_handle *versaloon_usb_device_handle; #endif /* __VERSALOON_H_INCLUDED__ */ openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/0000755000175000017500000000000012526202225017254 500000000000000openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c0000644000175000017500000000541012315575360022065 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "../versaloon_include.h" #include "../versaloon.h" #include "../versaloon_internal.h" #include "usbtoxxx.h" #include "usbtoxxx_internal.h" RESULT usbtojtagraw_init(uint8_t interface_index) { return usbtoxxx_init_command(USB_TO_JTAG_RAW, interface_index); } RESULT usbtojtagraw_fini(uint8_t interface_index) { return usbtoxxx_fini_command(USB_TO_JTAG_RAW, interface_index); } RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz) { uint8_t cfg_buf[4]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif SET_LE_U32(&cfg_buf[0], kHz); return usbtoxxx_conf_command(USB_TO_JTAG_RAW, interface_index, cfg_buf, 4); } RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi, uint8_t *tms, uint8_t *tdo, uint32_t bitlen) { uint16_t bytelen; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif if (bitlen > 8 * 0xFFFF) return ERROR_FAIL; bytelen = (uint16_t)((bitlen + 7) >> 3); SET_LE_U32(&versaloon_cmd_buf[0], bitlen); memcpy(versaloon_cmd_buf + 4, tdi, bytelen); memcpy(versaloon_cmd_buf + 4 + bytelen, tms, bytelen); return usbtoxxx_inout_command(USB_TO_JTAG_RAW, interface_index, versaloon_cmd_buf, 4 + bytelen * 2, bytelen, tdo, 0, bytelen, 0); } openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c0000644000175000017500000000450712315575360021244 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "../versaloon_include.h" #include "../versaloon.h" #include "../versaloon_internal.h" #include "usbtoxxx.h" #include "usbtoxxx_internal.h" RESULT usbtopwr_init(uint8_t interface_index) { return usbtoxxx_init_command(USB_TO_POWER, interface_index); } RESULT usbtopwr_fini(uint8_t interface_index) { return usbtoxxx_fini_command(USB_TO_POWER, interface_index); } RESULT usbtopwr_config(uint8_t interface_index) { #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif return usbtoxxx_conf_command(USB_TO_POWER, interface_index, NULL, 0); } RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV) { #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif return usbtoxxx_out_command(USB_TO_POWER, interface_index, (uint8_t *)&mV, 2, 0); } openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c0000644000175000017500000001107612516456302021225 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "../versaloon_include.h" #include "../versaloon.h" #include "../versaloon_internal.h" #include "usbtoxxx.h" #include "usbtoxxx_internal.h" RESULT usbtoswd_read_callback(void *p, uint8_t *src, uint8_t *processed) { struct versaloon_pending_t *pending = (struct versaloon_pending_t *)p; if (pending->extra_data != NULL) *((uint8_t *)pending->extra_data) = src[0]; return ERROR_OK; } RESULT usbtoswd_write_callback(void *p, uint8_t *src, uint8_t *processed) { struct versaloon_pending_t *pending = (struct versaloon_pending_t *)p; if (pending->extra_data != NULL) *((uint8_t *)pending->extra_data) = src[0]; /* mark it processed to ignore other input data */ *processed = 1; return ERROR_OK; } RESULT usbtoswd_init(uint8_t interface_index) { return usbtoxxx_init_command(USB_TO_SWD, interface_index); } RESULT usbtoswd_fini(uint8_t interface_index) { return usbtoxxx_fini_command(USB_TO_SWD, interface_index); } RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry, uint16_t dly) { uint8_t cfg_buf[5]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif cfg_buf[0] = trn; SET_LE_U16(&cfg_buf[1], retry); SET_LE_U16(&cfg_buf[3], dly); return usbtoxxx_conf_command(USB_TO_SWD, interface_index, cfg_buf, 5); } RESULT usbtoswd_seqout(uint8_t interface_index, const uint8_t *data, uint16_t bitlen) { uint16_t bytelen = (bitlen + 7) >> 3; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif SET_LE_U16(&versaloon_cmd_buf[0], bitlen); memcpy(versaloon_cmd_buf + 2, data, bytelen); return usbtoxxx_out_command(USB_TO_SWD, interface_index, versaloon_cmd_buf, bytelen + 2, 0); } RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen) { uint16_t bytelen = (bitlen + 7) >> 3; uint8_t buff[2]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif SET_LE_U16(&buff[0], bitlen); return usbtoxxx_in_command(USB_TO_SWD, interface_index, buff, 2, bytelen, data, 0, bytelen, 0); } RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request, uint32_t *data, uint8_t *ack) { uint8_t parity; uint8_t buff[5]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif parity = (request >> 1) & 1; parity += (request >> 2) & 1; parity += (request >> 3) & 1; parity += (request >> 4) & 1; parity &= 1; buff[0] = (request | 0x81 | (parity << 5)) & ~0x40; if (data != NULL) SET_LE_U32(&buff[1], *data); else memset(buff + 1, 0, 4); versaloon_set_extra_data(ack); if (request & 0x04) { /* read */ versaloon_set_callback(usbtoswd_read_callback); } else { /* write */ versaloon_set_callback(usbtoswd_write_callback); } /* Input buffer must be passed even for write operations. Otherwise * the callback function is not called and ack value is not set. */ return usbtoxxx_inout_command(USB_TO_SWD, interface_index, buff, 5, 5, (uint8_t *)data, 1, 4, 0); } openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c0000644000175000017500000004071712315575360021266 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "../versaloon_include.h" #include "../versaloon.h" #include "../versaloon_internal.h" #include "usbtoxxx.h" #include "usbtoxxx_internal.h" #define N_A "n/a" const char *types_name[96] = { "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm", "usbtoadc", "usbtodac", "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay", N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw", "usbtolpcicp", "usbtoswd", "usbtojtagraw", "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall" }; uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN]; #define usbtoxxx_get_type_name(type) \ types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \ % (sizeof(types_name) / sizeof(types_name[0]))] static uint8_t type_pre; static uint16_t usbtoxxx_buffer_index; static uint16_t usbtoxxx_current_cmd_index; static uint8_t *usbtoxxx_buffer; uint16_t collect_index; uint8_t collect_cmd; static uint8_t poll_nesting; struct usbtoxxx_context_t { uint8_t type_pre; uint8_t *usbtoxxx_buffer; uint16_t usbtoxxx_current_cmd_index; uint16_t usbtoxxx_buffer_index; uint16_t versaloon_pending_idx; }; static struct usbtoxxx_context_t poll_context; static void usbtoxxx_save_context(struct usbtoxxx_context_t *c) { c->type_pre = type_pre; c->usbtoxxx_buffer = usbtoxxx_buffer; c->usbtoxxx_buffer_index = usbtoxxx_buffer_index; c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index; c->versaloon_pending_idx = versaloon_pending_idx; } static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c) { type_pre = c->type_pre; usbtoxxx_buffer = c->usbtoxxx_buffer; usbtoxxx_buffer_index = c->usbtoxxx_buffer_index; usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index; versaloon_pending_idx = c->versaloon_pending_idx; } RESULT usbtoxxx_validate_current_command_type(void) { if (type_pre > 0) { /* not the first command */ if (NULL == usbtoxxx_buffer) { LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer)); return ERRCODE_INVALID_BUFFER; } usbtoxxx_buffer[0] = type_pre; SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index); usbtoxxx_buffer_index += usbtoxxx_current_cmd_index; } else { /* first command */ usbtoxxx_buffer_index = 3; } /* prepare for next command */ usbtoxxx_current_cmd_index = 3; usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index; collect_index = 0; collect_cmd = 0; return ERROR_OK; } RESULT usbtoxxx_execute_command(void) { uint16_t i; uint16_t inlen; RESULT result = ERROR_OK; if (poll_nesting) { LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL"); versaloon_free_want_pos(); return ERROR_FAIL; } if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); versaloon_free_want_pos(); return ERRCODE_FAILURE_OPERATION; } if (3 == usbtoxxx_buffer_index) { versaloon_free_want_pos(); return ERROR_OK; } versaloon_buf[0] = USB_TO_ALL; SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index); if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) { versaloon_free_want_pos(); return ERROR_FAIL; } /* process return data */ usbtoxxx_buffer_index = 0; for (i = 0; i < versaloon_pending_idx; i++) { /* check result */ if ((0 == i) || !((versaloon_pending[i].collect) && (versaloon_pending[i - 1].collect) && (versaloon_pending[i].cmd == versaloon_pending[i - 1].cmd))) { if (USB_TO_XXX_CMD_NOT_SUPPORT == versaloon_buf[usbtoxxx_buffer_index]) { LOG_ERROR(ERRMSG_NOT_SUPPORT_BY, usbtoxxx_get_type_name(versaloon_pending[i].type), "current dongle"); result = ERROR_FAIL; break; } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) { LOG_ERROR("%s command 0x%02x failed with 0x%02x", usbtoxxx_get_type_name(versaloon_pending[i].type), versaloon_pending[i].cmd, versaloon_buf[usbtoxxx_buffer_index]); result = ERROR_FAIL; break; } usbtoxxx_buffer_index++; } /* get result data */ if (versaloon_pending[i].pos != NULL) { uint8_t processed = 0; if (versaloon_pending[i].callback != NULL) { versaloon_pending[i].callback(&versaloon_pending[i], versaloon_buf + usbtoxxx_buffer_index, &processed); } if (!processed) { struct versaloon_want_pos_t *tmp; tmp = versaloon_pending[i].pos; while (tmp != NULL) { if ((tmp->buff != NULL) && (tmp->size > 0)) { memcpy(tmp->buff, versaloon_buf + usbtoxxx_buffer_index + tmp->offset, tmp->size); } struct versaloon_want_pos_t *free_tmp; free_tmp = tmp; tmp = tmp->next; free(free_tmp); } versaloon_pending[i].pos = NULL; } } else if ((versaloon_pending[i].want_data_size > 0) && (versaloon_pending[i].data_buffer != NULL)) { uint8_t processed = 0; if (versaloon_pending[i].callback != NULL) { versaloon_pending[i].callback(&versaloon_pending[i], versaloon_buf + usbtoxxx_buffer_index, &processed); } if (!processed) { memcpy(versaloon_pending[i].data_buffer, versaloon_buf + usbtoxxx_buffer_index + versaloon_pending[i].want_data_pos, versaloon_pending[i].want_data_size); } } usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size; if (usbtoxxx_buffer_index > inlen) { LOG_BUG("%s command 0x%02x process error", usbtoxxx_get_type_name(versaloon_pending[i].type), versaloon_pending[i].cmd); result = ERROR_FAIL; break; } } /* data is not the right size */ if (inlen != usbtoxxx_buffer_index) { LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data"); result = ERROR_FAIL; } if (versaloon_pending_idx > 0) versaloon_pending_idx = 0; else { /* no receive data, avoid collision */ sleep_ms(10); } type_pre = 0; collect_cmd = 0; collect_index = 0; versaloon_free_want_pos(); return result; } RESULT usbtoxxx_init(void) { versaloon_pending_idx = 0; if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) || (ERROR_OK != usbtoxxx_execute_command())) return ERROR_FAIL; LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X", GET_LE_U32(&usbtoxxx_abilities[0]), GET_LE_U32(&usbtoxxx_abilities[4]), GET_LE_U32(&usbtoxxx_abilities[8])); return ERROR_OK; } RESULT usbtoxxx_fini(void) { usbtoxxx_buffer = NULL; type_pre = 0; return ERROR_OK; } bool usbtoxxx_interface_supported(uint8_t cmd) { if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) || (cmd > VERSALOON_USB_TO_XXX_CMD_END)) return false; cmd -= VERSALOON_USB_TO_XXX_CMD_START; return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0; } RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen) { /* check free space, commit if not enough */ if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen) >= versaloon_buf_size) || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) { struct usbtoxxx_context_t context_tmp; uint8_t poll_nesting_tmp = 0; memset(&context_tmp, 0, sizeof(context_tmp)); if (poll_nesting) { if (0 == poll_context.type_pre) { LOG_BUG("USB_TO_POLL toooooo long"); return ERROR_OK; } usbtoxxx_save_context(&context_tmp); usbtoxxx_pop_context(&poll_context); poll_nesting_tmp = poll_nesting; poll_nesting = 0; } if (usbtoxxx_execute_command() != ERROR_OK) return ERROR_FAIL; if (poll_nesting_tmp) { uint16_t newlen, oldlen; newlen = context_tmp.versaloon_pending_idx - poll_context.versaloon_pending_idx; memcpy(&versaloon_pending[0], &versaloon_pending[poll_context.versaloon_pending_idx], sizeof(versaloon_pending[0]) * newlen); context_tmp.versaloon_pending_idx = newlen; oldlen = poll_context.usbtoxxx_buffer_index + poll_context.usbtoxxx_current_cmd_index; newlen = context_tmp.usbtoxxx_buffer_index + context_tmp.usbtoxxx_current_cmd_index; memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen); oldlen -= 3; context_tmp.usbtoxxx_buffer -= oldlen; context_tmp.usbtoxxx_buffer_index -= oldlen; usbtoxxx_pop_context(&context_tmp); poll_nesting = poll_nesting_tmp; } } return ERROR_OK; } RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf, uint16_t wantpos, uint16_t wantlen, uint8_t collect) { uint16_t len_tmp; /* 3 more bytes by usbtoxxx_validate_current_command_type */ /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */ if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6)) return ERROR_FAIL; if ((type_pre != type) || (NULL == usbtoxxx_buffer)) { if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = type; } if ((0 == collect_index) || (collect_cmd != cmd)) { usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd; if (collect) { collect_index = usbtoxxx_current_cmd_index; collect_cmd = cmd; } else { collect_index = 0; collect_cmd = 0; } SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen); usbtoxxx_current_cmd_index += 2; } else { len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen; SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp); } if (cmdbuf != NULL) { memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen); usbtoxxx_current_cmd_index += cmdlen; } return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen, wantbuf, collect); } RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN]) { if (ERROR_OK != usbtoxxx_ensure_buffer_size(3)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = USB_TO_INFO; return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0, USB_TO_XXX_ABILITIES_LEN, abilities, 0); } RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us) { if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5)) return ERROR_FAIL; if (!poll_nesting) usbtoxxx_save_context(&poll_context); if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } poll_nesting++; type_pre = USB_TO_POLL; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt); usbtoxxx_current_cmd_index += 2; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us); usbtoxxx_current_cmd_index += 2; return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0); } RESULT usbtopoll_end(void) { if (!poll_nesting) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); return ERRCODE_FAILURE_OPERATION; } if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } poll_nesting--; type_pre = USB_TO_POLL; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END; return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0); } RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value) { uint8_t i; if (size > 4) { LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__); return ERRCODE_INVALID_PARAMETER; } if (!poll_nesting) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); return ERRCODE_FAILURE_OPERATION; } if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = USB_TO_POLL; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); usbtoxxx_current_cmd_index += 2; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ; for (i = 0; i < size; i++) usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF; for (i = 0; i < size; i++) usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF; return ERROR_OK; } RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value) { uint8_t i; if (size > 4) { LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__); return ERRCODE_INVALID_PARAMETER; } if (!poll_nesting) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); return ERRCODE_FAILURE_OPERATION; } if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = USB_TO_POLL; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); usbtoxxx_current_cmd_index += 2; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ; for (i = 0; i < size; i++) usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF; for (i = 0; i < size; i++) usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF; return ERROR_OK; } RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff) { if (!poll_nesting) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); return ERRCODE_FAILURE_OPERATION; } if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = USB_TO_POLL; usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); usbtoxxx_current_cmd_index += 2; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size); usbtoxxx_current_cmd_index += 2; memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size); usbtoxxx_current_cmd_index += size; return ERROR_OK; } RESULT usbtodelay_delay(uint16_t dly) { if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2)) return ERROR_FAIL; if (ERROR_OK != usbtoxxx_validate_current_command_type()) { LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); return ERRCODE_FAILURE_OPERATION; } type_pre = USB_TO_DELAY; SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly); usbtoxxx_current_cmd_index += 2; return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0); } RESULT usbtodelay_delayms(uint16_t ms) { return usbtodelay_delay(ms | 0x8000); } RESULT usbtodelay_delayus(uint16_t us) { return usbtodelay_delay(us & 0x7FFF); } openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h0000644000175000017500000002614312516456302021265 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __USBTOXXX_H_INCLUDED__ #define __USBTOXXX_H_INCLUDED__ RESULT usbtoxxx_init(void); RESULT usbtoxxx_fini(void); RESULT usbtoxxx_execute_command(void); #define USB_TO_XXX_ABILITIES_LEN 12 extern uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN]; bool usbtoxxx_interface_supported(uint8_t cmd); /* USB_TO_INFO */ RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN]); /* USB_TO_DELAY */ RESULT usbtodelay_delay(uint16_t dly); RESULT usbtodelay_delayms(uint16_t ms); RESULT usbtodelay_delayus(uint16_t us); /* USB_TO_USART */ RESULT usbtousart_init(uint8_t interface_index); RESULT usbtousart_fini(uint8_t interface_index); RESULT usbtousart_config(uint8_t interface_index, uint32_t baudrate, uint8_t datalength, uint8_t mode); RESULT usbtousart_send(uint8_t interface_index, uint8_t *buf, uint16_t len); RESULT usbtousart_receive(uint8_t interface_index, uint8_t *buf, uint16_t len); RESULT usbtousart_status(uint8_t interface_index, struct usart_status_t *status); /* USB_TO_SPI */ RESULT usbtospi_init(uint8_t interface_index); RESULT usbtospi_fini(uint8_t interface_index); RESULT usbtospi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode); RESULT usbtospi_io(uint8_t interface_index, uint8_t *out, uint8_t *in, uint16_t bytelen); /* USB_TO_GPIO */ RESULT usbtogpio_init(uint8_t interface_index); RESULT usbtogpio_fini(uint8_t interface_index); RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask, uint32_t dir_mask, uint32_t pull_en_mask, uint32_t input_pull_mask); RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value); RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value); /* USB_TO_ISSP */ RESULT usbtoissp_init(uint8_t interface_index); RESULT usbtoissp_fini(uint8_t interface_index); RESULT usbtoissp_enter_program_mode(uint8_t interface_index, uint8_t mode); RESULT usbtoissp_leave_program_mode(uint8_t interface_index, uint8_t mode); RESULT usbtoissp_wait_and_poll(uint8_t interface_index); RESULT usbtoissp_vector(uint8_t interface_index, uint8_t operate, uint8_t addr, uint8_t data, uint8_t *buf); /* USB_TO_LPCICP */ RESULT usbtolpcicp_init(uint8_t interface_index); RESULT usbtolpcicp_fini(uint8_t interface_index); RESULT usbtolpcicp_config(uint8_t interface_index); RESULT usbtolpcicp_enter_program_mode(uint8_t interface_index); RESULT usbtolpcicp_in(uint8_t interface_index, uint8_t *buff, uint16_t len); RESULT usbtolpcicp_out(uint8_t interface_index, uint8_t *buff, uint16_t len); RESULT usbtolpcicp_poll_ready(uint8_t interface_index, uint8_t data, uint8_t *ret, uint8_t setmask, uint8_t clearmask, uint16_t pollcnt); /* USB_TO_JTAG_LL */ RESULT usbtojtagll_init(uint8_t interface_index); RESULT usbtojtagll_fini(uint8_t interface_index); RESULT usbtojtagll_config(uint8_t interface_index, uint32_t kHz); RESULT usbtojtagll_tms(uint8_t interface_index, uint8_t *tms, uint8_t bytelen); RESULT usbtojtagll_tms_clocks(uint8_t interface_index, uint32_t bytelen, uint8_t tms); RESULT usbtojtagll_scan(uint8_t interface_index, uint8_t *data, uint16_t bitlen, uint8_t tms_before_valid, uint8_t tms_before, uint8_t tms_after0, uint8_t tms_after1); /* USB_TO_JTAG_HL */ RESULT usbtojtaghl_init(uint8_t interface_index); RESULT usbtojtaghl_fini(uint8_t interface_index); RESULT usbtojtaghl_config(uint8_t interface_index, uint32_t kHz, uint8_t ub, uint8_t ua, uint16_t bb, uint16_t ba); RESULT usbtojtaghl_ir(uint8_t interface_index, uint8_t *ir, uint16_t bitlen, uint8_t idle, uint8_t want_ret); RESULT usbtojtaghl_dr(uint8_t interface_index, uint8_t *dr, uint16_t bitlen, uint8_t idle, uint8_t want_ret); RESULT usbtojtaghl_tms(uint8_t interface_index, uint8_t *tms, uint16_t bitlen); RESULT usbtojtaghl_runtest(uint8_t interface_index, uint32_t cycles); RESULT usbtojtaghl_register_callback(uint8_t index, jtag_callback_t send_callback, jtag_callback_t receive_callback); /* USB_TO_JTAG_RAW */ RESULT usbtojtagraw_init(uint8_t interface_index); RESULT usbtojtagraw_fini(uint8_t interface_index); RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz); RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi, uint8_t *tms, uint8_t *tdo, uint32_t bitlen); /* USB_TO_C2 */ RESULT usbtoc2_init(uint8_t interface_index); RESULT usbtoc2_fini(uint8_t interface_index); RESULT usbtoc2_writeaddr(uint8_t interface_index, uint8_t addr); RESULT usbtoc2_readaddr(uint8_t interface_index, uint8_t *data); RESULT usbtoc2_writedata(uint8_t interface_index, uint8_t *buf, uint8_t len); RESULT usbtoc2_readdata(uint8_t interface_index, uint8_t *buf, uint8_t len); /* USB_TO_I2C */ RESULT usbtoi2c_init(uint8_t interface_index); RESULT usbtoi2c_fini(uint8_t interface_index); RESULT usbtoi2c_config(uint8_t interface_index, uint16_t kHz, uint16_t byte_interval, uint16_t max_dly); RESULT usbtoi2c_read(uint8_t interface_index, uint16_t chip_addr, uint8_t *data, uint16_t data_len, uint8_t stop, bool nacklast); RESULT usbtoi2c_write(uint8_t interface_index, uint16_t chip_addr, uint8_t *data, uint16_t data_len, uint8_t stop); /* USB_TO_MSP430_JTAG */ RESULT usbtomsp430jtag_init(uint8_t interface_index); RESULT usbtomsp430jtag_fini(uint8_t interface_index); RESULT usbtomsp430jtag_config(uint8_t interface_index, uint8_t has_test); RESULT usbtomsp430jtag_ir(uint8_t interface_index, uint8_t *ir, uint8_t want_ret); RESULT usbtomsp430jtag_dr(uint8_t interface_index, uint32_t *dr, uint8_t bitlen, uint8_t want_ret); RESULT usbtomsp430jtag_tclk(uint8_t interface_index, uint8_t value); RESULT usbtomsp430jtag_tclk_strobe(uint8_t interface_index, uint16_t cnt); RESULT usbtomsp430jtag_reset(uint8_t interface_index); RESULT usbtomsp430jtag_poll(uint8_t interface_index, uint32_t dr, uint32_t mask, uint32_t value, uint8_t len, uint16_t poll_cnt, uint8_t toggle_tclk); /* USB_TO_MSP430_SBW */ RESULT usbtomsp430sbw_init(uint8_t interface_index); RESULT usbtomsp430sbw_fini(uint8_t interface_index); RESULT usbtomsp430sbw_config(uint8_t interface_index, uint8_t has_test); RESULT usbtomsp430sbw_ir(uint8_t interface_index, uint8_t *ir, uint8_t want_ret); RESULT usbtomsp430sbw_dr(uint8_t interface_index, uint32_t *dr, uint8_t bitlen, uint8_t want_ret); RESULT usbtomsp430sbw_tclk(uint8_t interface_index, uint8_t value); RESULT usbtomsp430sbw_tclk_strobe(uint8_t interface_index, uint16_t cnt); RESULT usbtomsp430sbw_reset(uint8_t interface_index); RESULT usbtomsp430sbw_poll(uint8_t interface_index, uint32_t dr, uint32_t mask, uint32_t value, uint8_t len, uint16_t poll_cnt, uint8_t toggle_tclk); /* USB_TO_POWER */ RESULT usbtopwr_init(uint8_t interface_index); RESULT usbtopwr_fini(uint8_t interface_index); RESULT usbtopwr_config(uint8_t interface_index); RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV); /* USB_TO_POLL */ RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us); RESULT usbtopoll_end(void); RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value); RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value); RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff); /* USB_TO_SWD */ RESULT usbtoswd_init(uint8_t interface_index); RESULT usbtoswd_fini(uint8_t interface_index); RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry, uint16_t dly); RESULT usbtoswd_seqout(uint8_t interface_index, const uint8_t *data, uint16_t bitlen); RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen); RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request, uint32_t *data, uint8_t *ack); /* USB_TO_SWIM */ RESULT usbtoswim_init(uint8_t interface_index); RESULT usbtoswim_fini(uint8_t interface_index); RESULT usbtoswim_config(uint8_t interface_index, uint8_t mHz, uint8_t cnt0, uint8_t cnt1); RESULT usbtoswim_srst(uint8_t interface_index); RESULT usbtoswim_wotf(uint8_t interface_index, uint8_t *data, uint16_t bytelen, uint32_t addr); RESULT usbtoswim_rotf(uint8_t interface_index, uint8_t *data, uint16_t bytelen, uint32_t addr); RESULT usbtoswim_sync(uint8_t interface_index, uint8_t mHz); RESULT usbtoswim_enable(uint8_t interface_index); /* USB_TO_BDM */ RESULT usbtobdm_init(uint8_t interface_index); RESULT usbtobdm_fini(uint8_t interface_index); RESULT usbtobdm_sync(uint8_t interface_index, uint16_t *khz); RESULT usbtobdm_transact(uint8_t interface_index, uint8_t *out, uint8_t outlen, uint8_t *in, uint8_t inlen, uint8_t delay, uint8_t ack); /* USB_TO_DUSI */ RESULT usbtodusi_init(uint8_t interface_index); RESULT usbtodusi_fini(uint8_t interface_index); RESULT usbtodusi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode); RESULT usbtodusi_io(uint8_t interface_index, uint8_t *mo, uint8_t *mi, uint8_t *so, uint8_t *si, uint32_t bitlen); /* USB_TO_MICROWIRE */ RESULT usbtomicrowire_init(uint8_t interface_index); RESULT usbtomicrowire_fini(uint8_t interface_index); RESULT usbtomicrowire_config(uint8_t interface_index, uint16_t kHz, uint8_t sel_polarity); RESULT usbtomicrowire_transport(uint8_t interface_index, uint32_t opcode, uint8_t opcode_bitlen, uint32_t addr, uint8_t addr_bitlen, uint32_t data, uint8_t data_bitlen, uint8_t *reply, uint8_t reply_bitlen); RESULT usbtomicrowire_poll(uint8_t interface_index, uint16_t interval_us, uint16_t retry_cnt); /* USB_TO_PWM */ RESULT usbtopwm_init(uint8_t interface_index); RESULT usbtopwm_fini(uint8_t interface_index); RESULT usbtopwm_config(uint8_t interface_index, uint16_t kHz, uint8_t mode); RESULT usbtopwm_out(uint8_t interface_index, uint16_t count, uint16_t *rate); RESULT usbtopwm_in(uint8_t interface_index, uint16_t count, uint16_t *rate); #endif /* __USBTOXXX_H_INCLUDED__ */ openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c0000644000175000017500000000602312315575360021365 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "../versaloon_include.h" #include "../versaloon.h" #include "../versaloon_internal.h" #include "usbtoxxx.h" #include "usbtoxxx_internal.h" RESULT usbtogpio_init(uint8_t interface_index) { return usbtoxxx_init_command(USB_TO_GPIO, interface_index); } RESULT usbtogpio_fini(uint8_t interface_index) { return usbtoxxx_fini_command(USB_TO_GPIO, interface_index); } RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask, uint32_t dir_mask, uint32_t pull_en_mask, uint32_t input_pull_mask) { uint8_t conf[8]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif dir_mask &= mask; SET_LE_U16(&conf[0], mask); SET_LE_U16(&conf[2], dir_mask); SET_LE_U16(&conf[4], pull_en_mask); SET_LE_U16(&conf[6], input_pull_mask); return usbtoxxx_conf_command(USB_TO_GPIO, interface_index, conf, sizeof(conf)); } RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value) { uint8_t buf[2]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif SET_LE_U16(&buf[0], mask); return usbtoxxx_in_command(USB_TO_GPIO, interface_index, buf, 2, 2, (uint8_t *)value, 0, 2, 0); } RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value) { uint8_t buf[4]; #if PARAM_CHECK if (interface_index > 7) { LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); return ERROR_FAIL; } #endif SET_LE_U16(&buf[0], mask); SET_LE_U16(&buf[2], value); return usbtoxxx_out_command(USB_TO_GPIO, interface_index, buf, 4, 0); } openocd-0.9.0/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h0000644000175000017500000002150212315575360023156 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __USBTOXXX_INTERNAL_H_INCLUDED__ #define __USBTOXXX_INTERNAL_H_INCLUDED__ /* USB_TO_XXX USB Commands */ /* Page0 */ #define USB_TO_USART (VERSALOON_USB_TO_XXX_CMD_START + 0x00) #define USB_TO_SPI (VERSALOON_USB_TO_XXX_CMD_START + 0x01) #define USB_TO_I2C (VERSALOON_USB_TO_XXX_CMD_START + 0x02) #define USB_TO_GPIO (VERSALOON_USB_TO_XXX_CMD_START + 0x03) #define USB_TO_CAN (VERSALOON_USB_TO_XXX_CMD_START + 0x04) #define USB_TO_PWM (VERSALOON_USB_TO_XXX_CMD_START + 0x05) #define USB_TO_ADC (VERSALOON_USB_TO_XXX_CMD_START + 0x06) #define USB_TO_DAC (VERSALOON_USB_TO_XXX_CMD_START + 0x07) #define USB_TO_MICROWIRE (VERSALOON_USB_TO_XXX_CMD_START + 0x08) #define USB_TO_SWIM (VERSALOON_USB_TO_XXX_CMD_START + 0x09) #define USB_TO_DUSI (VERSALOON_USB_TO_XXX_CMD_START + 0x0A) /* Page1 */ #define USB_TO_JTAG_LL (VERSALOON_USB_TO_XXX_CMD_START + 0x20) #define USB_TO_JTAG_HL (VERSALOON_USB_TO_XXX_CMD_START + 0x21) #define USB_TO_ISSP (VERSALOON_USB_TO_XXX_CMD_START + 0x22) #define USB_TO_C2 (VERSALOON_USB_TO_XXX_CMD_START + 0x23) #define USB_TO_SBW (VERSALOON_USB_TO_XXX_CMD_START + 0x24) #define USB_TO_LPCICP (VERSALOON_USB_TO_XXX_CMD_START + 0x25) #define USB_TO_SWD (VERSALOON_USB_TO_XXX_CMD_START + 0x26) #define USB_TO_JTAG_RAW (VERSALOON_USB_TO_XXX_CMD_START + 0x27) #define USB_TO_BDM (VERSALOON_USB_TO_XXX_CMD_START + 0x28) #define USB_TO_MSP430_JTAG (VERSALOON_USB_TO_XXX_CMD_START + 0x38) /* Page2 */ #define USB_TO_POWER (VERSALOON_USB_TO_XXX_CMD_START + 0x40) #define USB_TO_DELAY (VERSALOON_USB_TO_XXX_CMD_START + 0x41) #define USB_TO_POLL (VERSALOON_USB_TO_XXX_CMD_START + 0x42) #define USB_TO_INFO (VERSALOON_USB_TO_XXX_CMD_START + 0x5E) #define USB_TO_ALL (VERSALOON_USB_TO_XXX_CMD_START + 0x5F) /* USB_TO_XXX Masks */ #define USB_TO_XXX_CMDMASK 0xF8 #define USB_TO_XXX_CMDSHIFT 3 #define USB_TO_XXX_IDXMASK 0x07 /* USB_TO_XXX Sub Commands */ /* Common Sub Commands */ #define USB_TO_XXX_INIT (0x00 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_FINI (0x01 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_CONFIG (0x02 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_GETHWINFO (0x03 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_STATUS (0X04 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_IN_OUT (0x05 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_IN (0x06 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_OUT (0x07 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_POLL (0x08 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_SPECIAL (0x09 << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_RESET (0x0A << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_SYNC (0x0B << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_ENABLE (0x0C << USB_TO_XXX_CMDSHIFT) #define USB_TO_XXX_DISABLE (0x0D << USB_TO_XXX_CMDSHIFT) /* USB_TO_POLL */ #define USB_TO_POLL_START 0x00 #define USB_TO_POLL_END 0x01 #define USB_TO_POLL_CHECKOK 0x02 #define USB_TO_POLL_CHECKFAIL 0x03 #define USB_TO_POLL_VERIFYBUFF 0x04 /* USB_TO_XXX Replys */ #define USB_TO_XXX_OK 0x00 #define USB_TO_XXX_FAILED 0x01 #define USB_TO_XXX_TIME_OUT 0x02 #define USB_TO_XXX_INVALID_INDEX 0x03 #define USB_TO_XXX_INVALID_PARA 0x04 #define USB_TO_XXX_INVALID_CMD 0x05 #define USB_TO_XXX_CMD_NOT_SUPPORT 0x06 /* USB_TO_XXX */ RESULT usbtoxxx_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, uint16_t want_pos, uint16_t want_size, uint8_t *buffer); RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf, uint16_t wantpos, uint16_t wantlen, uint8_t collect); #define usbtoxxx_init_command(type, port) \ usbtoxxx_add_command((type), (USB_TO_XXX_INIT | (port)), \ NULL, 0, 0, NULL, 0, 0, 0) #define usbtoxxx_fini_command(type, port) \ usbtoxxx_add_command((type), (USB_TO_XXX_FINI | (port)), \ NULL, 0, 0, NULL, 0, 0, 0) #define usbtoxxx_conf_command(type, port, cmdbuf, cmdlen) \ usbtoxxx_add_command((type), (USB_TO_XXX_CONFIG | (port)), \ (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) #define usbtoxxx_inout_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ wantpos, wantlen, c) \ usbtoxxx_add_command((type), (USB_TO_XXX_IN_OUT | (port)), \ (cmdbuf), (cmdlen), (retlen), (wantbuf), \ (wantpos), (wantlen), (c)) #define usbtoxxx_in_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ wantpos, wantlen, c) \ usbtoxxx_add_command((type), (USB_TO_XXX_IN | (port)), (cmdbuf), \ (cmdlen), (retlen), (wantbuf), (wantpos), \ (wantlen), (c)) #define usbtoxxx_out_command(type, port, cmdbuf, cmdlen, c) \ usbtoxxx_add_command((type), (USB_TO_XXX_OUT | (port)), (cmdbuf), \ (cmdlen), 0, NULL, 0, 0, (c)) #define usbtoxxx_poll_command(type, port, cmdbuf, cmdlen, retbuf, retlen) \ usbtoxxx_add_command((type), (USB_TO_XXX_POLL | (port)), (cmdbuf), \ (cmdlen), (retlen), (retbuf), 0, (retlen), 0) #define usbtoxxx_status_command(type, port, retlen, wantbuf, wantpos, wantlen, c) \ usbtoxxx_add_command((type), (USB_TO_XXX_STATUS | (port)), \ NULL, 0, (retlen), (wantbuf), (wantpos), \ (wantlen), (c)) #define usbtoxxx_special_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ wantpos, wantlen, c) \ usbtoxxx_add_command((type), (USB_TO_XXX_SPECIAL | (port)), \ (cmdbuf), (cmdlen), retlen, wantbuf, \ wantpos, wantlen, (c)) #define usbtoxxx_reset_command(type, port, cmdbuf, cmdlen) \ usbtoxxx_add_command((type), (USB_TO_XXX_RESET | (port)), \ (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) #define usbtoxxx_sync_command(type, port, cmdbuf, cmdlen, retlen, wantbuf) \ usbtoxxx_add_command((type), (USB_TO_XXX_SYNC | (port)), \ (cmdbuf), (cmdlen), (retlen), (wantbuf), 0, \ (retlen), 0) #define usbtoxxx_enable_command(type, port, cmdbuf, cmdlen) \ usbtoxxx_add_command((type), (USB_TO_XXX_ENABLE | (port)), \ (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) #define usbtoxxx_disable_command(type, port, cmdbuf, cmdlen) \ usbtoxxx_add_command((type), (USB_TO_XXX_DISABLE | (port)), \ (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) /* USB_TO_SPI */ #define USB_TO_SPI_BAUDRATE_MSK 0x1F #define USB_TO_SPI_CPOL_MSK 0x20 #define USB_TO_SPI_CPHA_MSK 0x40 #define USB_TO_SPI_MSB_FIRST 0x80 /* USB_TO_DUSI */ #define USB_TO_DUSI_BAUDRATE_MSK 0x1F #define USB_TO_DUSI_CPOL_MSK 0x20 #define USB_TO_DUSI_CPHA_MSK 0x40 #define USB_TO_DUSI_MSB_FIRST 0x80 /* USB_TO_GPIO */ #define USB_TO_GPIO_DIR_MSK 0x01 #endif /* __USBTOXXX_INTERNAL_H_INCLUDED__ */ openocd-0.9.0/src/jtag/drivers/versaloon/versaloon_internal.h0000644000175000017500000001000212315575360021347 00000000000000/*************************************************************************** * Copyright (C) 2009 - 2010 by Simon Qian * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __VERSALOON_INTERNAL_H_INCLUDED__ #define __VERSALOON_INTERNAL_H_INCLUDED__ #define VERSALOON_PRODUCTSTRING_INDEX 2 #define VERSALOON_SERIALSTRING_INDEX 3 #define VERSALOON_PRODUCTSTRING "Versaloon" #define VERSALOON_VID 0x0483 #define VERSALOON_PID 0xA038 #define VERSALOON_INP 0x82 #define VERSALOON_OUTP 0x03 #define VERSALOON_IFACE 0x00 #define VERSALOON_FULL 1 #define VERSALOON_MINI 2 #define VERSALOON_NANO 3 #define VERSALOON_TIMEOUT 5000 #define VERSALOON_TIMEOUT_LONG 60000 /* USB Commands */ /* Common Commands */ #define VERSALOON_COMMON_CMD_START 0x00 #define VERSALOON_COMMON_CMD_END 0x0F #define VERSALOON_GET_INFO 0x00 #define VERSALOON_GET_TVCC 0x01 #define VERSALOON_GET_HARDWARE 0x02 #define VERSALOON_GET_OFFLINE_SIZE 0x08 #define VERSALOON_ERASE_OFFLINE_DATA 0x09 #define VERSALOON_WRITE_OFFLINE_DATA 0x0A #define VERSALOON_GET_OFFLINE_CHECKSUM 0x0B #define VERSALOON_FW_UPDATE 0x0F #define VERSALOON_FW_UPDATE_KEY 0xAA /* MCU Command */ #define VERSALOON_MCU_CMD_START 0x10 #define VERSALOON_MCU_CMD_END 0x1F /* USB_TO_XXX Command */ #define VERSALOON_USB_TO_XXX_CMD_START 0x20 #define VERSALOON_USB_TO_XXX_CMD_END 0x7F /* VSLLink Command */ #define VERSALOON_VSLLINK_CMD_START 0x80 #define VERSALOON_VSLLINK_CMD_END 0xFF /* Mass-product */ #define MP_OK 0x00 #define MP_FAIL 0x01 #define MP_ISSP 0x11 /* pending struct */ #define VERSALOON_MAX_PENDING_NUMBER 4096 typedef RESULT(*versaloon_callback_t)(void *, uint8_t *, uint8_t *); struct versaloon_want_pos_t { uint16_t offset; uint16_t size; uint8_t *buff; struct versaloon_want_pos_t *next; }; struct versaloon_pending_t { uint8_t type; uint8_t cmd; uint16_t want_data_pos; uint16_t want_data_size; uint16_t actual_data_size; uint8_t *data_buffer; uint8_t collect; uint32_t id; struct versaloon_want_pos_t *pos; void *extra_data; versaloon_callback_t callback; }; extern struct versaloon_pending_t \ versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; extern uint16_t versaloon_pending_idx; void versaloon_set_pending_id(uint32_t id); void versaloon_set_callback(versaloon_callback_t callback); void versaloon_set_extra_data(void *p); RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff); RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect); void versaloon_free_want_pos(void); RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen); extern uint8_t *versaloon_buf; extern uint8_t *versaloon_cmd_buf; extern uint16_t versaloon_buf_size; #endif /* __VERSALOON_INTERNAL_H_INCLUDED__ */ openocd-0.9.0/src/jtag/drivers/libusb1_common.c0000644000175000017500000001700212516456302016343 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * Copyright (C) 2011 by Mauro Gamba * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "libusb1_common.h" static struct libusb_context *jtag_libusb_context; /**< Libusb context **/ static libusb_device **devs; /**< The usb device list **/ static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc, const uint16_t vids[], const uint16_t pids[]) { for (unsigned i = 0; vids[i]; i++) { if (dev_desc->idVendor == vids[i] && dev_desc->idProduct == pids[i]) { return true; } } return false; } /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, const char *string) { int retval; bool matched; char desc_string[256+1]; /* Max size of string descriptor */ if (str_index == 0) return false; retval = libusb_get_string_descriptor_ascii(device, str_index, (unsigned char *)desc_string, sizeof(desc_string)-1); if (retval < 0) { LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval); return false; } /* Null terminate descriptor string in case it needs to be logged. */ desc_string[sizeof(desc_string)-1] = '\0'; matched = strncmp(string, desc_string, sizeof(desc_string)) == 0; if (!matched) LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'", desc_string, string); return matched; } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], const char *serial, struct jtag_libusb_device_handle **out) { int cnt, idx, errCode; int retval = -ENODEV; struct jtag_libusb_device_handle *libusb_handle = NULL; if (libusb_init(&jtag_libusb_context) < 0) return -ENODEV; cnt = libusb_get_device_list(jtag_libusb_context, &devs); for (idx = 0; idx < cnt; idx++) { struct libusb_device_descriptor dev_desc; if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0) continue; if (!jtag_libusb_match(&dev_desc, vids, pids)) continue; errCode = libusb_open(devs[idx], &libusb_handle); if (errCode) { LOG_ERROR("libusb_open() failed with %s", libusb_error_name(errCode)); continue; } /* Device must be open to use libusb_get_string_descriptor_ascii. */ if (serial != NULL && !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) { libusb_close(libusb_handle); continue; } /* Success. */ *out = libusb_handle; retval = 0; break; } if (cnt >= 0) libusb_free_device_list(devs, 1); return retval; } void jtag_libusb_close(jtag_libusb_device_handle *dev) { /* Close device */ libusb_close(dev); libusb_exit(jtag_libusb_context); } int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout) { int transferred = 0; transferred = libusb_control_transfer(dev, requestType, request, wValue, wIndex, (unsigned char *)bytes, size, timeout); if (transferred < 0) transferred = 0; return transferred; } int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { int transferred = 0; libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, &transferred, timeout); return transferred; } int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { int transferred = 0; libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, &transferred, timeout); return transferred; } int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); int retCode = -99; struct libusb_config_descriptor *config = NULL; int current_config = -1; retCode = libusb_get_configuration(devh, ¤t_config); if (retCode != 0) return retCode; retCode = libusb_get_config_descriptor(udev, configuration, &config); if (retCode != 0 || config == NULL) return retCode; /* Only change the configuration if it is not already set to the same one. Otherwise this issues a lightweight reset and hangs LPC-Link2 with JLink firmware. */ if (current_config != config->bConfigurationValue) retCode = libusb_set_configuration(devh, config->bConfigurationValue); libusb_free_config_descriptor(config); return retCode; } int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, int bclass, int subclass, int protocol) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); const struct libusb_interface *inter; const struct libusb_interface_descriptor *interdesc; const struct libusb_endpoint_descriptor *epdesc; struct libusb_config_descriptor *config; *usb_read_ep = *usb_write_ep = 0; libusb_get_config_descriptor(udev, 0, &config); for (int i = 0; i < (int)config->bNumInterfaces; i++) { inter = &config->interface[i]; interdesc = &inter->altsetting[0]; for (int k = 0; k < (int)interdesc->bNumEndpoints; k++) { if ((bclass > 0 && interdesc->bInterfaceClass != bclass) || (subclass > 0 && interdesc->bInterfaceSubClass != subclass) || (protocol > 0 && interdesc->bInterfaceProtocol != protocol)) continue; epdesc = &interdesc->endpoint[k]; uint8_t epnum = epdesc->bEndpointAddress; bool is_input = epnum & 0x80; LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum); if (is_input) *usb_read_ep = epnum; else *usb_write_ep = epnum; if (*usb_read_ep && *usb_write_ep) { LOG_DEBUG("Claiming interface %d", (int)interdesc->bInterfaceNumber); libusb_claim_interface(devh, (int)interdesc->bInterfaceNumber); libusb_free_config_descriptor(config); return ERROR_OK; } } } libusb_free_config_descriptor(config); return ERROR_FAIL; } int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid) { struct libusb_device_descriptor dev_desc; if (libusb_get_device_descriptor(dev, &dev_desc) == 0) { *pid = dev_desc.idProduct; return ERROR_OK; } return ERROR_FAIL; } openocd-0.9.0/src/jtag/drivers/libusb1_common.h0000644000175000017500000000772412516456302016362 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * Copyright (C) 2011 by Mauro Gamba * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_LIBUSB_COMMON_H #define JTAG_LIBUSB_COMMON_H #include #define jtag_libusb_device libusb_device #define jtag_libusb_device_handle libusb_device_handle #define jtag_libusb_device_descriptor libusb_device_descriptor #define jtag_libusb_interface libusb_interface #define jtag_libusb_interface_descriptor libusb_interface_descriptor #define jtag_libusb_endpoint_descriptor libusb_endpoint_descriptor #define jtag_libusb_config_descriptor libusb_config_descriptor #define jtag_libusb_reset_device(dev) libusb_reset_device(dev) #define jtag_libusb_get_device(devh) libusb_get_device(devh) static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh, int iface) { return libusb_claim_interface(devh, iface); }; static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh, int iface) { return libusb_release_interface(devh, iface); } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], const char *serial, struct jtag_libusb_device_handle **out); void jtag_libusb_close(jtag_libusb_device_handle *dev); int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout); int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); /** * Find the first interface optionally matching class, subclass and * protocol and claim it. * @param devh _libusb_ device handle. * @param usb_read_ep A pointer to a variable where the _IN_ endpoint * number will be stored. * @param usb_write_ep A pointer to a variable where the _OUT_ endpoint * number will be stored. * @param bclass `bInterfaceClass` to match, or -1 to ignore this field. * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. */ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, int bclass, int subclass, int protocol); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* JTAG_USB_COMMON_H */ openocd-0.9.0/src/jtag/drivers/Makefile.rlink0000644000175000017500000000530012315575360016045 00000000000000#*************************************************************************** #* Copyright (C) 2008 Lou Deluxe * #* lou.openocd012@fixit.nospammail.net * #* * #* This program 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 2 of the License, or * #* (at your option) any later version. * #* * #* This program 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, write to the * #* Free Software Foundation, Inc., * #* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * #*************************************************************************** TOP = ../../.. INTERFACE_NAME = rlink PERL = perl M4 = m4 TARGETDIR = ${TOP}/src/target TOOLSDIR = ${TOP}/tools MAKE_SPEED_TABLE = ${TOOLSDIR}/rlink_make_speed_table/rlink_make_speed_table ST7_DTC_AS = ${TOOLSDIR}/st7_dtc_as/st7_dtc_as OPENOCD = ${TOP}/src/openocd OPENOCD_CONFIG = -s ${TARGETDIR} OPENOCD_CONFIG += -f interface/rlink.cfg OPENOCD_CONFIG += -f board/stm32f10x_128k_eval.cfg PATCHFILE = /tmp/openocd_${INTERFACE_NAME}.diff.gz # relative to ${TOP} SVNADDFILES = SVNADDFILES += src/target/interface/rlink.cfg SVNADDFILES += src/jtag/${INTERFACE_NAME}.c SVNADDFILES += src/jtag/${INTERFACE_NAME} PRESCALERS = 64 11 8 2 DTCFILES = DTCFILES += $(addsuffix _init.dtc, ${PRESCALERS}) DTCFILES += $(addsuffix _call.dtc, ${PRESCALERS}) default: rlink_speed_table.c clean %_init.fsm: rlink_init.m4 ${M4} -P -DSHIFTER_PRESCALER=`echo "$@" | sed -e's/_.*//'` $< > $@ %_call.fsm: rlink_call.m4 ${M4} -P -DSHIFTER_PRESCALER=`echo "$@" | sed -e's/_.*//'` $< > $@ %.dtc: %.fsm ${ST7_DTC_AS} -b -o $@ -i $< > /dev/null rlink_speed_table.c: ${DTCFILES} ${MAKE_SPEED_TABLE} ${PRESCALERS} > $@ || rm $@ clean: -rm *.dtc *.fsm distclean: clean test: default (cd ${TOP} && (rm src/jtag/${INTERFACE_NAME}.o; ${MAKE})) ${OPENOCD} -d0 ${OPENOCD_CONFIG} -c init -c 'poll off' openocd-0.9.0/src/jtag/drivers/amt_jtagaccel.c0000644000175000017500000003746012516456302016222 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #if PARPORT_USE_PPDEV == 1 #include #include #include #else /* not PARPORT_USE_PPDEV */ #ifndef _WIN32 #include #endif #endif #if PARPORT_USE_GIVEIO == 1 #if IS_CYGWIN == 1 #include #endif #endif /** * @file * Support the Amontec Chameleon POD with JTAG Accelerator support. * This is a parallel port JTAG adapter with a CPLD between the * parallel port and the JTAG connection. VHDL code running in the * CPLD significantly accelerates JTAG operations compared to the * bitbanging "Wiggler" style of most parallel port adapters. */ /* configuration */ static uint16_t amt_jtagaccel_port; /* interface variables */ static uint8_t aw_control_rst; static uint8_t aw_control_fsm = 0x10; static uint8_t aw_control_baudrate = 0x20; static int rtck_enabled; #if PARPORT_USE_PPDEV == 1 static int device_handle; static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; /* FIXME do something sane when these ioctl/read/write calls fail. */ #define AMT_AW(val) \ do { \ int __retval; \ \ __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \ assert(__retval >= 0); \ __retval = write(device_handle, &val, 1); \ assert(__retval >= 0); \ } while (0) #define AMT_AR(val) \ do { \ int __retval; \ \ __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \ assert(__retval >= 0); \ __retval = read(device_handle, &val, 1); \ assert(__retval >= 0); \ } while (0) static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA; #define AMT_DW(val) \ do { \ int __retval; \ \ __retval = ioctl(device_handle, PPSETMODE, &data_mode); \ assert(__retval >= 0); \ __retval = write(device_handle, &val, 1); \ assert(__retval >= 0); \ } while (0) #define AMT_DR(val) \ do { \ int __retval; \ \ __retval = ioctl(device_handle, PPSETMODE, &data_mode); \ assert(__retval >= 0); \ __retval = read(device_handle, &val, 1); \ assert(__retval >= 0); \ } while (0) #else #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0) #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0) #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0) #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0) #endif /* PARPORT_USE_PPDEV */ /* tap_move[i][j]: tap movement command to go from state i to state j * 0: Test-Logic-Reset * 1: Run-Test/Idle * 2: Shift-DR * 3: Pause-DR * 4: Shift-IR * 5: Pause-IR */ static const uint8_t amt_jtagaccel_tap_move[6][6][2] = { /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */ { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */ { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */ { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */ { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */ { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */ }; static void amt_jtagaccel_reset(int trst, int srst) { if (trst == 1) aw_control_rst |= 0x4; else if (trst == 0) aw_control_rst &= ~0x4; if (srst == 1) aw_control_rst |= 0x1; else if (srst == 0) aw_control_rst &= ~0x1; AMT_AW(aw_control_rst); } static int amt_jtagaccel_speed(int speed) { aw_control_baudrate &= 0xf0; aw_control_baudrate |= speed & 0x0f; AMT_AW(aw_control_baudrate); return ERROR_OK; } static void amt_jtagaccel_end_state(tap_state_t state) { if (tap_is_state_stable(state)) tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } } static void amt_wait_scan_busy(void) { int timeout = 4096; uint8_t ar_status; AMT_AR(ar_status); while (((ar_status) & 0x80) && (timeout-- > 0)) AMT_AR(ar_status); if (ar_status & 0x80) { LOG_ERROR( "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x", (rtck_enabled) ? "enabled" : "disabled", ar_status); exit(-1); } } static void amt_jtagaccel_state_move(void) { uint8_t aw_scan_tms_5; uint8_t tms_scan[2]; tap_state_t cur_state = tap_get_state(); tap_state_t end_state = tap_get_end_state(); tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0]; tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1]; aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f); AMT_AW(aw_scan_tms_5); int jtag_speed = 0; int retval = jtag_get_speed(&jtag_speed); assert(retval == ERROR_OK); if (jtag_speed > 3 || rtck_enabled) amt_wait_scan_busy(); if (tms_scan[0] & 0x80) { aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f); AMT_AW(aw_scan_tms_5); if (jtag_speed > 3 || rtck_enabled) amt_wait_scan_busy(); } tap_set_state(end_state); } static void amt_jtagaccel_runtest(int num_cycles) { int i = 0; uint8_t aw_scan_tms_5; uint8_t aw_scan_tms_1to4; tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { amt_jtagaccel_end_state(TAP_IDLE); amt_jtagaccel_state_move(); } while (num_cycles - i >= 5) { aw_scan_tms_5 = 0x40; AMT_AW(aw_scan_tms_5); i += 5; } if (num_cycles - i > 0) { aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4; AMT_AW(aw_scan_tms_1to4); } amt_jtagaccel_end_state(saved_end_state); if (tap_get_state() != tap_get_end_state()) amt_jtagaccel_state_move(); } static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { int bits_left = scan_size; int bit_count = 0; tap_state_t saved_end_state = tap_get_end_state(); uint8_t aw_tdi_option; uint8_t dw_tdi_scan; uint8_t dr_tdo; uint8_t aw_tms_scan; uint8_t tms_scan[2]; int jtag_speed_var; int retval = jtag_get_speed(&jtag_speed_var); assert(retval == ERROR_OK); if (ir_scan) amt_jtagaccel_end_state(TAP_IRSHIFT); else amt_jtagaccel_end_state(TAP_DRSHIFT); /* Only move if we're not already there */ if (tap_get_state() != tap_get_end_state()) amt_jtagaccel_state_move(); amt_jtagaccel_end_state(saved_end_state); /* handle unaligned bits at the beginning */ if ((scan_size - 1) % 8) { aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1); AMT_AW(aw_tdi_option); dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff; AMT_DW(dw_tdi_scan); if (jtag_speed_var > 3 || rtck_enabled) amt_wait_scan_busy(); if ((type == SCAN_IN) || (type == SCAN_IO)) { AMT_DR(dr_tdo); dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8)); buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo); } bit_count += (scan_size - 1) % 8; bits_left -= (scan_size - 1) % 8; } while (bits_left - 1 >= 8) { dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff; AMT_DW(dw_tdi_scan); if (jtag_speed_var > 3 || rtck_enabled) amt_wait_scan_busy(); if ((type == SCAN_IN) || (type == SCAN_IO)) { AMT_DR(dr_tdo); buf_set_u32(buffer, bit_count, 8, dr_tdo); } bit_count += 8; bits_left -= 8; } tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0]; tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1]; aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5); AMT_AW(aw_tms_scan); if (jtag_speed_var > 3 || rtck_enabled) amt_wait_scan_busy(); if ((type == SCAN_IN) || (type == SCAN_IO)) { AMT_DR(dr_tdo); dr_tdo = dr_tdo >> 7; buf_set_u32(buffer, bit_count, 1, dr_tdo); } if (tms_scan[0] & 0x80) { aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f); AMT_AW(aw_tms_scan); if (jtag_speed_var > 3 || rtck_enabled) amt_wait_scan_busy(); } tap_set_state(tap_get_end_state()); } static int amt_jtagaccel_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; int retval; /* return ERROR_OK, unless a jtag_read_buffer returns a failed check * that wasn't handled by a caller-provided error handler */ retval = ERROR_OK; while (cmd) { switch (cmd->type) { case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif if (cmd->cmd.reset->trst == 1) tap_set_state(TAP_RESET); amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif amt_jtagaccel_end_state(cmd->cmd.runtest->end_state); amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_TLR_RESET: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif amt_jtagaccel_end_state(cmd->cmd.statemove->end_state); amt_jtagaccel_state_move(); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state); #endif amt_jtagaccel_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; if (buffer) free(buffer); break; case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us); #endif jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } return retval; } #if PARPORT_USE_GIVEIO == 1 int amt_jtagaccel_get_giveio_access(void) { HANDLE h; OSVERSIONINFO version; version.dwOSVersionInfoSize = sizeof version; if (!GetVersionEx(&version)) { errno = EINVAL; return -1; } if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0; h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { errno = ENODEV; return -1; } CloseHandle(h); return 0; } #endif static int amt_jtagaccel_init(void) { #if PARPORT_USE_PPDEV == 1 char buffer[256]; int i = 0; uint8_t control_port; #else uint8_t status_port; #endif uint8_t ar_status; #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { LOG_ERROR("device is already opened"); return ERROR_JTAG_INIT_FAILED; } snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port); device_handle = open(buffer, O_RDWR); if (device_handle < 0) { LOG_ERROR( "cannot open device. check it exists and that user read and write rights are set"); return ERROR_JTAG_INIT_FAILED; } i = ioctl(device_handle, PPCLAIM); if (i < 0) { LOG_ERROR("cannot claim device"); return ERROR_JTAG_INIT_FAILED; } i = IEEE1284_MODE_EPP; i = ioctl(device_handle, PPSETMODE, &i); if (i < 0) { LOG_ERROR(" cannot set compatible mode to device"); return ERROR_JTAG_INIT_FAILED; } control_port = 0x00; i = ioctl(device_handle, PPWCONTROL, &control_port); control_port = 0x04; i = ioctl(device_handle, PPWCONTROL, &control_port); #else if (amt_jtagaccel_port == 0) { amt_jtagaccel_port = 0x378; LOG_WARNING("No parport port specified, using default '0x378' (LPT1)"); } #if PARPORT_USE_GIVEIO == 1 if (amt_jtagaccel_get_giveio_access() != 0) { #else /* PARPORT_USE_GIVEIO */ if (ioperm(amt_jtagaccel_port, 5, 1) != 0) { #endif /* PARPORT_USE_GIVEIO */ LOG_ERROR("missing privileges for direct i/o"); return ERROR_JTAG_INIT_FAILED; } /* prepare epp port * clear timeout */ status_port = inb(amt_jtagaccel_port + 1); outb(status_port | 0x1, amt_jtagaccel_port + 1); /* reset epp port */ outb(0x00, amt_jtagaccel_port + 2); outb(0x04, amt_jtagaccel_port + 2); #endif if (rtck_enabled) { /* set RTCK enable bit */ aw_control_fsm |= 0x02; } /* enable JTAG port */ aw_control_fsm |= 0x04; AMT_AW(aw_control_fsm); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) aw_control_rst &= ~0x8; else aw_control_rst |= 0x8; if (jtag_reset_config & RESET_SRST_PUSH_PULL) aw_control_rst &= ~0x2; else aw_control_rst |= 0x2; amt_jtagaccel_reset(0, 0); /* read status register */ AMT_AR(ar_status); LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status); return ERROR_OK; } static int amt_jtagaccel_quit(void) { return ERROR_OK; } COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command) { if (CMD_ARGC == 1) { /* only if the port wasn't overwritten by cmdline */ if (amt_jtagaccel_port == 0) { uint16_t port; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port); amt_jtagaccel_port = port; } else { LOG_ERROR("The parport port was already configured!"); return ERROR_FAIL; } } command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port); return ERROR_OK; } COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command) { if (CMD_ARGC == 0) { command_print(CMD_CTX, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled"); return ERROR_OK; } else { if (strcmp(CMD_ARGV[0], "enabled") == 0) rtck_enabled = 1; else rtck_enabled = 0; } return ERROR_OK; } static const struct command_registration amtjtagaccel_command_handlers[] = { { .name = "parport_port", .handler = &amt_jtagaccel_handle_parport_port_command, .mode = COMMAND_CONFIG, .help = "configure or display the parallel port to use", .usage = "[port_num]", }, { /** * @todo Remove this "rtck" command; just use the standard * mechanism to enable/disable adaptive clocking. First * implement the standard mechanism and deprecate "rtck"; * after a year or so, it'll be safe to remove this. */ .name = "rtck", .handler = &amt_jtagaccel_handle_rtck_command, .mode = COMMAND_CONFIG, .help = "configure or display RTCK support", .usage = "[enable|disable]", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface amt_jtagaccel_interface = { .name = "amt_jtagaccel", .commands = amtjtagaccel_command_handlers, .init = amt_jtagaccel_init, .quit = amt_jtagaccel_quit, .speed = amt_jtagaccel_speed, .execute_queue = amt_jtagaccel_execute_queue, }; openocd-0.9.0/src/jtag/drivers/rlink_st7.h0000644000175000017500000000775512315575360015374 00000000000000/*************************************************************************** * Copyright (C) 2008 Lou Deluxe * * lou.openocd012@fixit.nospammail.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #define ST7_FOSC (12 * 1000000) /* This is not a complete enumeration of ST7 registers, but it is sufficient for this interface driver. */ #define ST7_PADR (0x0000) #define ST7_PADDR (ST7_PADR + 1) #define ST7_PAOR (ST7_PADR + 2) #define ST7_PBDR (0x0003) #define ST7_PBDDR (ST7_PBDR + 1) #define ST7_PCDR (0x0006) #define ST7_PCDDR (ST7_PCDR + 1) #define ST7_PCOR (ST7_PCDR + 2) #define ST7_PDDR (0x0009) #define ST7_PDDDR (ST7_PDDR + 1) #define ST7_PDOR (ST7_PDDR + 2) #define ST7_PEDR (0x000c) #define ST7_PEDDR (ST7_PEDR + 1) #define ST7_PEOR (ST7_PEDR + 2) #define ST7_PFDR (0x000f) #define ST7_PFDDR (ST7_PFDR + 1) #define ST7_ADCDR (0x0012) #define ST7_ADCCSR (ST7_ADCDR + 1) #define ST7_EP2TXR (0x003e) #define ST7_EP2TXR_STAT_TX0 (1 << 0) #define ST7_EP2TXR_STAT_TX1 (1 << 1) #define ST7_EP2TXR_STAT_DISABLED (0) #define ST7_EP2TXR_STAT_STALL (ST7_EP2TXR_STAT_TX0) #define ST7_EP2TXR_STAT_VALID (ST7_EP2TXR_STAT_TX1 | ST7_EP2TXR_STAT_TX0) #define ST7_EP2TXR_STAT_NAK (ST7_EP2TXR_STAT_TX1) #define ST7_EP2TXR_DTOG_TX (1 << 2) #define ST7_EP2TXR_CTR_TX (1 << 3) #define ST7_USB_BUF_EP0OUT (0x1550) #define ST7_USB_BUF_EP0IN (0x1560) #define ST7_USB_BUF_EP1OUT (0x1570) #define ST7_USB_BUF_EP1IN (0x1580) #define ST7_USB_BUF_EP2UODI (0x1590) #define ST7_USB_BUF_EP2UIDO (0x1650) #define ST7_PA0 (1 << 0) #define ST7_PA1 (1 << 1) #define ST7_PA2 (1 << 2) #define ST7_PA3 (1 << 3) #define ST7_PA4 (1 << 4) #define ST7_PA5 (1 << 5) #define ST7_PA6 (1 << 6) #define ST7_PA7 (1 << 7) #define ST7_PB0 (1 << 0) #define ST7_PB1 (1 << 1) #define ST7_PB2 (1 << 2) #define ST7_PB3 (1 << 3) #define ST7_PB4 (1 << 4) #define ST7_PB5 (1 << 5) #define ST7_PB6 (1 << 6) #define ST7_PB7 (1 << 7) #define ST7_PC0 (1 << 0) #define ST7_PC1 (1 << 1) #define ST7_PC2 (1 << 2) #define ST7_PC3 (1 << 3) #define ST7_PC4 (1 << 4) #define ST7_PC5 (1 << 5) #define ST7_PC6 (1 << 6) #define ST7_PC7 (1 << 7) #define ST7_PD0 (1 << 0) #define ST7_PD1 (1 << 1) #define ST7_PD2 (1 << 2) #define ST7_PD3 (1 << 3) #define ST7_PD4 (1 << 4) #define ST7_PD5 (1 << 5) #define ST7_PD6 (1 << 6) #define ST7_PD7 (1 << 7) #define ST7_PE0 (1 << 0) #define ST7_PE1 (1 << 1) #define ST7_PE2 (1 << 2) #define ST7_PE3 (1 << 3) #define ST7_PE4 (1 << 4) #define ST7_PE5 (1 << 5) #define ST7_PE6 (1 << 6) #define ST7_PE7 (1 << 7) #define ST7_PF0 (1 << 0) #define ST7_PF1 (1 << 1) #define ST7_PF2 (1 << 2) #define ST7_PF3 (1 << 3) #define ST7_PF4 (1 << 4) #define ST7_PF5 (1 << 5) #define ST7_PF6 (1 << 6) #define ST7_PF7 (1 << 7) openocd-0.9.0/src/jtag/drivers/cmsis_dap_usb.c0000644000175000017500000007160212516456302016253 00000000000000/*************************************************************************** * Copyright (C) 2014 by Paul Fertser * * fercerpav@gmail.com * * * * Copyright (C) 2013 by mike brown * * mike@theshedworks.org.uk * * * * Copyright (C) 2013 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include /* * See CMSIS-DAP documentation: * Version 0.01 - Beta. */ /* USB Config */ /* Known vid/pid pairs: * VID 0xc251: Keil Software * PID 0xf001: LPC-Link-II CMSIS_DAP * PID 0xf002: OPEN-SDA CMSIS_DAP (Freedom Board) * PID 0x2722: Keil ULINK2 CMSIS-DAP * * VID 0x0d28: mbed Software * PID 0x0204: MBED CMSIS-DAP */ #define MAX_USB_IDS 8 /* vid = pid = 0 marks the end of the list */ static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 }; static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 }; static wchar_t *cmsis_dap_serial; static bool swd_mode; #define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */ #define USB_TIMEOUT 1000 /* CMSIS-DAP General Commands */ #define CMD_DAP_INFO 0x00 #define CMD_DAP_LED 0x01 #define CMD_DAP_CONNECT 0x02 #define CMD_DAP_DISCONNECT 0x03 #define CMD_DAP_WRITE_ABORT 0x08 #define CMD_DAP_DELAY 0x09 #define CMD_DAP_RESET_TARGET 0x0A /* CMD_INFO */ #define INFO_ID_VID 0x00 /* string */ #define INFO_ID_PID 0x02 /* string */ #define INFO_ID_SERNUM 0x03 /* string */ #define INFO_ID_FW_VER 0x04 /* string */ #define INFO_ID_TD_VEND 0x05 /* string */ #define INFO_ID_TD_NAME 0x06 /* string */ #define INFO_ID_CAPS 0xf0 /* byte */ #define INFO_ID_PKT_CNT 0xfe /* byte */ #define INFO_ID_PKT_SZ 0xff /* short */ #define INFO_CAPS_SWD 0x01 #define INFO_CAPS_JTAG 0x02 /* CMD_LED */ #define LED_ID_CONNECT 0x00 #define LED_ID_RUN 0x01 #define LED_OFF 0x00 #define LED_ON 0x01 /* CMD_CONNECT */ #define CONNECT_DEFAULT 0x00 #define CONNECT_SWD 0x01 #define CONNECT_JTAG 0x02 /* CMSIS-DAP Common SWD/JTAG Commands */ #define CMD_DAP_DELAY 0x09 #define CMD_DAP_SWJ_PINS 0x10 #define CMD_DAP_SWJ_CLOCK 0x11 #define CMD_DAP_SWJ_SEQ 0x12 /* * PINS * Bit 0: SWCLK/TCK * Bit 1: SWDIO/TMS * Bit 2: TDI * Bit 3: TDO * Bit 5: nTRST * Bit 7: nRESET */ /* CMSIS-DAP SWD Commands */ #define CMD_DAP_SWD_CONFIGURE 0x13 /* CMSIS-DAP JTAG Commands */ #define CMD_DAP_JTAG_SEQ 0x14 #define CMD_DAP_JTAG_CONFIGURE 0x15 #define CMD_DAP_JTAG_IDCODE 0x16 /* CMSIS-DAP Transfer Commands */ #define CMD_DAP_TFER_CONFIGURE 0x04 #define CMD_DAP_TFER 0x05 #define CMD_DAP_TFER_BLOCK 0x06 #define CMD_DAP_TFER_ABORT 0x07 /* DAP Status Code */ #define DAP_OK 0 #define DAP_ERROR 0xFF /* CMSIS-DAP Vendor Commands * None as yet... */ static const char * const info_caps_str[] = { "SWD Supported", "JTAG Supported" }; /* max clock speed (kHz) */ #define DAP_MAX_CLOCK 5000 struct cmsis_dap { hid_device *dev_handle; uint16_t packet_size; uint16_t packet_count; uint8_t *packet_buffer; uint8_t caps; uint8_t mode; }; struct pending_transfer_result { uint8_t cmd; uint32_t data; void *buffer; }; static int pending_transfer_count, pending_queue_len; static struct pending_transfer_result *pending_transfers; static int queued_retval; static struct cmsis_dap *cmsis_dap_handle; static int cmsis_dap_usb_open(void) { hid_device *dev = NULL; int i; struct hid_device_info *devs, *cur_dev; unsigned short target_vid, target_pid; wchar_t *target_serial = NULL; bool found = false; bool serial_found = false; target_vid = 0; target_pid = 0; /* * The CMSIS-DAP specification stipulates: * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer." */ devs = hid_enumerate(0x0, 0x0); cur_dev = devs; while (NULL != cur_dev) { if (0 == cmsis_dap_vid[0]) { if (NULL == cur_dev->product_string) { LOG_DEBUG("Cannot read product string of device 0x%x:0x%x", cur_dev->vendor_id, cur_dev->product_id); } else { if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) { /* if the user hasn't specified VID:PID *and* * product string contains "CMSIS-DAP", pick it */ found = true; } } } else { /* otherwise, exhaustively compare against all VID:PID in list */ for (i = 0; cmsis_dap_vid[i] || cmsis_dap_pid[i]; i++) { if ((cmsis_dap_vid[i] == cur_dev->vendor_id) && (cmsis_dap_pid[i] == cur_dev->product_id)) found = true; } if (cmsis_dap_vid[i] || cmsis_dap_pid[i]) found = true; } if (found) { /* we have found an adapter, so exit further checks */ /* check serial number matches if given */ if (cmsis_dap_serial != NULL) { if (wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) { serial_found = true; break; } } else break; } cur_dev = cur_dev->next; } if (NULL != cur_dev) { target_vid = cur_dev->vendor_id; target_pid = cur_dev->product_id; if (serial_found) target_serial = cmsis_dap_serial; } hid_free_enumeration(devs); if (target_vid == 0 && target_pid == 0) { LOG_ERROR("unable to find CMSIS-DAP device"); return ERROR_FAIL; } if (hid_init() != 0) { LOG_ERROR("unable to open HIDAPI"); return ERROR_FAIL; } dev = hid_open(target_vid, target_pid, target_serial); if (dev == NULL) { LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid); return ERROR_FAIL; } struct cmsis_dap *dap = malloc(sizeof(struct cmsis_dap)); if (dap == NULL) { LOG_ERROR("unable to allocate memory"); return ERROR_FAIL; } dap->dev_handle = dev; dap->caps = 0; dap->mode = 0; cmsis_dap_handle = dap; /* allocate default packet buffer, may be changed later. * currently with HIDAPI we have no way of getting the output report length * without this info we cannot communicate with the adapter. * For the moment we ahve to hard code the packet size */ int packet_size = PACKET_SIZE; /* atmel cmsis-dap uses 512 byte reports */ /* TODO: HID report descriptor should be parsed instead of * hardcoding a match by VID */ if (target_vid == 0x03eb) packet_size = 512 + 1; cmsis_dap_handle->packet_buffer = malloc(packet_size); cmsis_dap_handle->packet_size = packet_size; if (cmsis_dap_handle->packet_buffer == NULL) { LOG_ERROR("unable to allocate memory"); return ERROR_FAIL; } return ERROR_OK; } static void cmsis_dap_usb_close(struct cmsis_dap *dap) { hid_close(dap->dev_handle); hid_exit(); free(cmsis_dap_handle->packet_buffer); free(cmsis_dap_handle); cmsis_dap_handle = NULL; free(cmsis_dap_serial); cmsis_dap_serial = NULL; free(pending_transfers); pending_transfers = NULL; return; } /* Send a message and receive the reply */ static int cmsis_dap_usb_xfer(struct cmsis_dap *dap, int txlen) { /* Pad the rest of the TX buffer with 0's */ memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen); /* write data to device */ int retval = hid_write(dap->dev_handle, dap->packet_buffer, dap->packet_size); if (retval == -1) { LOG_ERROR("error writing data: %ls", hid_error(dap->dev_handle)); return ERROR_FAIL; } /* get reply */ retval = hid_read_timeout(dap->dev_handle, dap->packet_buffer, dap->packet_size, USB_TIMEOUT); if (retval == -1 || retval == 0) { LOG_DEBUG("error reading data: %ls", hid_error(dap->dev_handle)); return ERROR_FAIL; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay, uint8_t *input) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_SWJ_PINS; buffer[2] = pins; buffer[3] = mask; buffer[4] = delay & 0xff; buffer[5] = (delay >> 8) & 0xff; buffer[6] = (delay >> 16) & 0xff; buffer[7] = (delay >> 24) & 0xff; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 8); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_PINS failed."); return ERROR_JTAG_DEVICE_ERROR; } if (input) *input = buffer[1]; return ERROR_OK; } static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; /* set clock in Hz */ swj_clock *= 1000; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_SWJ_CLOCK; buffer[2] = swj_clock & 0xff; buffer[3] = (swj_clock >> 8) & 0xff; buffer[4] = (swj_clock >> 16) & 0xff; buffer[5] = (swj_clock >> 24) & 0xff; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 6); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_INFO; buffer[2] = info; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_INFO failed."); return ERROR_JTAG_DEVICE_ERROR; } *data = &(buffer[1]); return ERROR_OK; } static int cmsis_dap_cmd_DAP_LED(uint8_t leds) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_LED; buffer[2] = 0x00; buffer[3] = leds; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4); if (retval != ERROR_OK || buffer[1] != 0x00) { LOG_ERROR("CMSIS-DAP command CMD_LED failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_Connect(uint8_t mode) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_CONNECT; buffer[2] = mode; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed."); return ERROR_JTAG_DEVICE_ERROR; } if (buffer[1] != mode) { LOG_ERROR("CMSIS-DAP failed to connect in mode (%d)", mode); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_Disconnect(void) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_DISCONNECT; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 2); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_DISCONNECT failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count, uint16_t match_retry) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_TFER_CONFIGURE; buffer[2] = idle; buffer[3] = retry_count & 0xff; buffer[4] = (retry_count >> 8) & 0xff; buffer[5] = match_retry & 0xff; buffer[6] = (match_retry >> 8) & 0xff; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 7); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_TFER_Configure failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_SWD_CONFIGURE; buffer[2] = cfg; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_SWD_Configure failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } #if 0 static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us) { int retval; uint8_t *buffer = cmsis_dap_handle->packet_buffer; buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_DELAY; buffer[2] = delay_us & 0xff; buffer[3] = (delay_us >> 8) & 0xff; retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_Delay failed."); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } #endif static int cmsis_dap_swd_run_queue(struct adiv5_dap *dap) { uint8_t *buffer = cmsis_dap_handle->packet_buffer; LOG_DEBUG("Executing %d queued transactions", pending_transfer_count); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); goto skip; } if (!pending_transfer_count) goto skip; size_t idx = 0; buffer[idx++] = 0; /* report number */ buffer[idx++] = CMD_DAP_TFER; buffer[idx++] = 0x00; /* DAP Index */ buffer[idx++] = pending_transfer_count; for (int i = 0; i < pending_transfer_count; i++) { uint8_t cmd = pending_transfers[i].cmd; uint32_t data = pending_transfers[i].data; LOG_DEBUG("%s %s reg %x %"PRIx32, cmd & SWD_CMD_APnDP ? "AP" : "DP", cmd & SWD_CMD_RnW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, data); /* When proper WAIT handling is implemented in the * common SWD framework, this kludge can be * removed. However, this might lead to minor * performance degradation as the adapter wouldn't be * able to automatically retry anything (because ARM * has forgotten to implement sticky error flags * clearing). See also comments regarding * cmsis_dap_cmd_DAP_TFER_Configure() and * cmsis_dap_cmd_DAP_SWD_Configure() in * cmsis_dap_init(). */ if (!(cmd & SWD_CMD_RnW) && !(cmd & SWD_CMD_APnDP) && (cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT && (data & CORUNDETECT)) { LOG_DEBUG("refusing to enable sticky overrun detection"); data &= ~CORUNDETECT; } buffer[idx++] = (cmd >> 1) & 0x0f; if (!(cmd & SWD_CMD_RnW)) { buffer[idx++] = (data) & 0xff; buffer[idx++] = (data >> 8) & 0xff; buffer[idx++] = (data >> 16) & 0xff; buffer[idx++] = (data >> 24) & 0xff; } } queued_retval = cmsis_dap_usb_xfer(cmsis_dap_handle, idx); if (queued_retval != ERROR_OK) goto skip; idx = 2; uint8_t ack = buffer[idx] & 0x07; if (ack != SWD_ACK_OK || (buffer[idx] & 0x08)) { LOG_DEBUG("SWD ack not OK: %d %s", buffer[idx-1], ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; goto skip; } idx++; if (pending_transfer_count != buffer[1]) LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d", pending_transfer_count, buffer[1]); for (int i = 0; i < buffer[1]; i++) { if (pending_transfers[i].cmd & SWD_CMD_RnW) { static uint32_t last_read; uint32_t data = le_to_h_u32(&buffer[idx]); uint32_t tmp = data; idx += 4; LOG_DEBUG("Read result: %"PRIx32, data); /* Imitate posted AP reads */ if ((pending_transfers[i].cmd & SWD_CMD_APnDP) || ((pending_transfers[i].cmd & SWD_CMD_A32) >> 1 == DP_RDBUFF)) { tmp = last_read; last_read = data; } if (pending_transfers[i].buffer) *(uint32_t *)pending_transfers[i].buffer = tmp; } } skip: pending_transfer_count = 0; int retval = queued_retval; queued_retval = ERROR_OK; return retval; } static void cmsis_dap_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data) { if (pending_transfer_count == pending_queue_len) { /* Not enough room in the queue. Run the queue. */ queued_retval = cmsis_dap_swd_run_queue(dap); } if (queued_retval != ERROR_OK) return; pending_transfers[pending_transfer_count].data = data; pending_transfers[pending_transfer_count].cmd = cmd; if (cmd & SWD_CMD_RnW) { /* Queue a read transaction */ pending_transfers[pending_transfer_count].buffer = dst; } pending_transfer_count++; } static void cmsis_dap_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value) { assert(!(cmd & SWD_CMD_RnW)); cmsis_dap_swd_queue_cmd(dap, cmd, NULL, value); } static void cmsis_dap_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value) { assert(cmd & SWD_CMD_RnW); cmsis_dap_swd_queue_cmd(dap, cmd, value, 0); } static int cmsis_dap_get_version_info(void) { uint8_t *data; /* INFO_ID_FW_VER - string */ int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_FW_VER, &data); if (retval != ERROR_OK) return retval; if (data[0]) /* strlen */ LOG_INFO("CMSIS-DAP: FW Version = %s", &data[1]); return ERROR_OK; } static int cmsis_dap_get_caps_info(void) { uint8_t *data; /* INFO_ID_CAPS - byte */ int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_CAPS, &data); if (retval != ERROR_OK) return retval; if (data[0] == 1) { uint8_t caps = data[1]; cmsis_dap_handle->caps = caps; if (caps & INFO_CAPS_SWD) LOG_INFO("CMSIS-DAP: %s", info_caps_str[0]); if (caps & INFO_CAPS_JTAG) LOG_INFO("CMSIS-DAP: %s", info_caps_str[1]); } return ERROR_OK; } static int cmsis_dap_get_status(void) { uint8_t d; int retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, 0, 0, &d); if (retval == ERROR_OK) { LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d", (d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */ (d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */ (d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */ (d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */ (d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */ (d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */ } return retval; } static int cmsis_dap_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq) { uint8_t *buffer = cmsis_dap_handle->packet_buffer; const uint8_t *s; unsigned int s_len; int retval; /* When we are reconnecting, DAP_Connect needs to be rerun, at * least on Keil ULINK-ME */ retval = cmsis_dap_cmd_DAP_Connect(seq == LINE_RESET || seq == JTAG_TO_SWD ? CONNECT_SWD : CONNECT_JTAG); if (retval != ERROR_OK) return retval; switch (seq) { case LINE_RESET: LOG_DEBUG("SWD line reset"); s = swd_seq_line_reset; s_len = swd_seq_line_reset_len; break; case JTAG_TO_SWD: LOG_DEBUG("JTAG-to-SWD"); s = swd_seq_jtag_to_swd; s_len = swd_seq_jtag_to_swd_len; break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); s = swd_seq_swd_to_jtag; s_len = swd_seq_swd_to_jtag_len; break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; } buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_SWJ_SEQ; buffer[2] = s_len; bit_copy(&buffer[3], 0, s, 0, s_len); retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); if (retval != ERROR_OK || buffer[1] != DAP_OK) return ERROR_FAIL; return ERROR_OK; } static int cmsis_dap_swd_open(void) { int retval; if (cmsis_dap_handle == NULL) { /* SWD init */ retval = cmsis_dap_usb_open(); if (retval != ERROR_OK) return retval; retval = cmsis_dap_get_caps_info(); if (retval != ERROR_OK) return retval; } if (!(cmsis_dap_handle->caps & INFO_CAPS_SWD)) { LOG_ERROR("CMSIS-DAP: SWD not supported"); return ERROR_JTAG_DEVICE_ERROR; } retval = cmsis_dap_cmd_DAP_Connect(CONNECT_SWD); if (retval != ERROR_OK) return retval; /* Add more setup here.??... */ LOG_INFO("CMSIS-DAP: Interface Initialised (SWD)"); return ERROR_OK; } static int cmsis_dap_init(void) { int retval; uint8_t *data; if (swd_mode) { retval = cmsis_dap_swd_open(); if (retval != ERROR_OK) return retval; } if (cmsis_dap_handle == NULL) { /* JTAG init */ retval = cmsis_dap_usb_open(); if (retval != ERROR_OK) return retval; retval = cmsis_dap_get_caps_info(); if (retval != ERROR_OK) return retval; /* Connect in JTAG mode */ if (!(cmsis_dap_handle->caps & INFO_CAPS_JTAG)) { LOG_ERROR("CMSIS-DAP: JTAG not supported"); return ERROR_JTAG_DEVICE_ERROR; } retval = cmsis_dap_cmd_DAP_Connect(CONNECT_JTAG); if (retval != ERROR_OK) return retval; LOG_INFO("CMSIS-DAP: Interface Initialised (JTAG)"); } retval = cmsis_dap_get_version_info(); if (retval != ERROR_OK) return retval; /* INFO_ID_PKT_SZ - short */ retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data); if (retval != ERROR_OK) return retval; if (data[0] == 2) { /* short */ uint16_t pkt_sz = data[1] + (data[2] << 8); /* 4 bytes of command header + 5 bytes per register * write. For bulk read sequences just 4 bytes are * needed per transfer, so this is suboptimal. */ pending_queue_len = (pkt_sz - 4) / 5; pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers)); if (!pending_transfers) { LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue"); return ERROR_FAIL; } if (cmsis_dap_handle->packet_size != pkt_sz + 1) { /* reallocate buffer */ cmsis_dap_handle->packet_size = pkt_sz + 1; cmsis_dap_handle->packet_buffer = realloc(cmsis_dap_handle->packet_buffer, cmsis_dap_handle->packet_size); if (cmsis_dap_handle->packet_buffer == NULL) { LOG_ERROR("unable to reallocate memory"); return ERROR_FAIL; } } LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRId16, pkt_sz); } /* INFO_ID_PKT_CNT - byte */ retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_CNT, &data); if (retval != ERROR_OK) return retval; if (data[0] == 1) { /* byte */ uint16_t pkt_cnt = data[1]; cmsis_dap_handle->packet_count = pkt_cnt; LOG_DEBUG("CMSIS-DAP: Packet Count = %" PRId16, pkt_cnt); } retval = cmsis_dap_get_status(); if (retval != ERROR_OK) return ERROR_FAIL; /* Now try to connect to the target * TODO: This is all SWD only @ present */ retval = cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); if (retval != ERROR_OK) return ERROR_FAIL; /* Ask CMSIS-DAP to automatically retry on receiving WAIT for * up to 64 times. This must be changed to 0 if sticky * overrun detection is enabled. */ retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0); if (retval != ERROR_OK) return ERROR_FAIL; /* Data Phase (bit 2) must be set to 1 if sticky overrun * detection is enabled */ retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */ if (retval != ERROR_OK) return ERROR_FAIL; retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */ if (retval != ERROR_OK) return ERROR_FAIL; /* support connecting with srst asserted */ enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { if (jtag_reset_config & RESET_SRST_NO_GATING) { retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, (1 << 7), 0, NULL); if (retval != ERROR_OK) return ERROR_FAIL; LOG_INFO("Connecting under reset"); } } cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */ LOG_INFO("CMSIS-DAP: Interface ready"); return ERROR_OK; } static int cmsis_dap_swd_init(void) { swd_mode = true; return ERROR_OK; } static int cmsis_dap_quit(void) { cmsis_dap_cmd_DAP_Disconnect(); cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */ cmsis_dap_usb_close(cmsis_dap_handle); return ERROR_OK; } static void cmsis_dap_execute_reset(struct jtag_command *cmd) { int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \ (1 << 7), 0, NULL); if (retval != ERROR_OK) LOG_ERROR("CMSIS-DAP: Interface reset failed"); } static void cmsis_dap_execute_sleep(struct jtag_command *cmd) { #if 0 int retval = cmsis_dap_cmd_DAP_Delay(cmd->cmd.sleep->us); if (retval != ERROR_OK) #endif jtag_sleep(cmd->cmd.sleep->us); } static void cmsis_dap_execute_command(struct jtag_command *cmd) { switch (cmd->type) { case JTAG_RESET: cmsis_dap_execute_reset(cmd); break; case JTAG_SLEEP: cmsis_dap_execute_sleep(cmd); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } } static int cmsis_dap_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; while (cmd != NULL) { cmsis_dap_execute_command(cmd); cmd = cmd->next; } return ERROR_OK; } static int cmsis_dap_speed(int speed) { if (speed > DAP_MAX_CLOCK) { LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK); speed = DAP_MAX_CLOCK; } if (speed == 0) { LOG_INFO("RTCK not supported"); return ERROR_JTAG_NOT_IMPLEMENTED; } return cmsis_dap_cmd_DAP_SWJ_Clock(speed); } static int cmsis_dap_speed_div(int speed, int *khz) { *khz = speed; return ERROR_OK; } static int cmsis_dap_khz(int khz, int *jtag_speed) { *jtag_speed = khz; return ERROR_OK; } static int_least32_t cmsis_dap_swd_frequency(struct adiv5_dap *dap, int_least32_t hz) { if (hz > 0) cmsis_dap_speed(hz / 1000); return hz; } COMMAND_HANDLER(cmsis_dap_handle_info_command) { if (cmsis_dap_get_version_info() == ERROR_OK) cmsis_dap_get_status(); return ERROR_OK; } COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) { if (CMD_ARGC > MAX_USB_IDS * 2) { LOG_WARNING("ignoring extra IDs in cmsis_dap_vid_pid " "(maximum is %d pairs)", MAX_USB_IDS); CMD_ARGC = MAX_USB_IDS * 2; } if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { LOG_WARNING("incomplete cmsis_dap_vid_pid configuration directive"); if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* remove the incomplete trailing id */ CMD_ARGC -= 1; } unsigned i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], cmsis_dap_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], cmsis_dap_pid[i >> 1]); } /* * Explicitly terminate, in case there are multiples instances of * cmsis_dap_vid_pid. */ cmsis_dap_vid[i >> 1] = cmsis_dap_pid[i >> 1] = 0; return ERROR_OK; } COMMAND_HANDLER(cmsis_dap_handle_serial_command) { if (CMD_ARGC == 1) { size_t len = mbstowcs(NULL, CMD_ARGV[0], 0); cmsis_dap_serial = calloc(len + 1, sizeof(wchar_t)); if (cmsis_dap_serial == NULL) { LOG_ERROR("unable to allocate memory"); return ERROR_OK; } if (mbstowcs(cmsis_dap_serial, CMD_ARGV[0], len + 1) == (size_t)-1) { free(cmsis_dap_serial); cmsis_dap_serial = NULL; LOG_ERROR("unable to convert serial"); } } else { LOG_ERROR("expected exactly one argument to cmsis_dap_serial "); } return ERROR_OK; } static const struct command_registration cmsis_dap_subcommand_handlers[] = { { .name = "info", .handler = &cmsis_dap_handle_info_command, .mode = COMMAND_EXEC, .usage = "", .help = "show cmsis-dap info", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration cmsis_dap_command_handlers[] = { { .name = "cmsis-dap", .mode = COMMAND_ANY, .help = "perform CMSIS-DAP management", .usage = "", .chain = cmsis_dap_subcommand_handlers, }, { .name = "cmsis_dap_vid_pid", .handler = &cmsis_dap_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the CMSIS-DAP device", .usage = "(vid pid)* ", }, { .name = "cmsis_dap_serial", .handler = &cmsis_dap_handle_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the adapter", .usage = "serial_string", }, COMMAND_REGISTRATION_DONE }; static const struct swd_driver cmsis_dap_swd_driver = { .init = cmsis_dap_swd_init, .frequency = cmsis_dap_swd_frequency, .switch_seq = cmsis_dap_swd_switch_seq, .read_reg = cmsis_dap_swd_read_reg, .write_reg = cmsis_dap_swd_write_reg, .run = cmsis_dap_swd_run_queue, }; static const char * const cmsis_dap_transport[] = { "swd", NULL }; struct jtag_interface cmsis_dap_interface = { .name = "cmsis-dap", .commands = cmsis_dap_command_handlers, .swd = &cmsis_dap_swd_driver, .transports = cmsis_dap_transport, .execute_queue = cmsis_dap_execute_queue, .speed = cmsis_dap_speed, .speed_div = cmsis_dap_speed_div, .khz = cmsis_dap_khz, .init = cmsis_dap_init, .quit = cmsis_dap_quit, }; openocd-0.9.0/src/jtag/startup.tcl0000644000175000017500000001030612516456303014017 00000000000000# Defines basic Tcl procs for OpenOCD JTAG module # Executed during "init". Can be overridden # by board/target/... scripts proc jtag_init {} { if {[catch {jtag arp_init} err]!=0} { # try resetting additionally init_reset startup } } # This reset logic may be overridden by board/target/... scripts as needed # to provide a reset that, if possible, is close to a power-up reset. # # Exit requirements include: (a) JTAG must be working, (b) the scan # chain was validated with "jtag arp_init" (or equivalent), (c) nothing # stays in reset. No TAP-specific scans were performed. It's OK if # some targets haven't been reset yet; they may need TAP-specific scans. # # The "mode" values include: halt, init, run (from "reset" command); # startup (at OpenOCD server startup, when JTAG may not yet work); and # potentially more (for reset types like cold, warm, etc) proc init_reset { mode } { if {[using_jtag]} { jtag arp_init-reset } } ######### # TODO: power_restore and power_dropout are currently neither # documented nor supported except on ZY1000. proc power_restore {} { echo "Sensed power restore, running reset init and halting GDB." reset init # Halt GDB so user can deal with a detected power restore. # # After GDB is halted, then output is no longer forwarded # to the GDB console. set targets [target names] foreach t $targets { # New event script. $t invoke-event arp_halt_gdb } } add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default." proc power_dropout {} { echo "Sensed power dropout." } ######### # TODO: srst_deasserted and srst_asserted are currently neither # documented nor supported except on ZY1000. proc srst_deasserted {} { echo "Sensed nSRST deasserted, running reset init and halting GDB." reset init # Halt GDB so user can deal with a detected reset. # # After GDB is halted, then output is no longer forwarded # to the GDB console. set targets [target names] foreach t $targets { # New event script. $t invoke-event arp_halt_gdb } } add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default." proc srst_asserted {} { echo "Sensed nSRST asserted." } # measure actual JTAG clock proc measure_clk {} { set start_time [ms]; set iterations 10000000; runtest $iterations; echo "Running at more than [expr $iterations.0 / ([ms]-$start_time)] kHz"; } add_help_text measure_clk "Runs a test to measure the JTAG clk. Useful with RCLK / RTCK." proc default_to_jtag { f args } { set current_transport [transport select] if {[using_jtag]} { eval $f $args } { error "session transport is \"$current_transport\" but your config requires JTAG" } } proc jtag args { eval default_to_jtag jtag $args } proc jtag_rclk args { eval default_to_jtag jtag_rclk $args } proc jtag_ntrst_delay args { eval default_to_jtag jtag_ntrst_delay $args } proc jtag_ntrst_assert_width args { eval default_to_jtag jtag_ntrst_assert_width $args } # BEGIN MIGRATION AIDS ... these adapter operations originally had # JTAG-specific names despite the fact that the operations were not # specific to JTAG, or otherewise had troublesome/misleading names. # # FIXME phase these aids out after about April 2011 # proc jtag_khz args { echo "DEPRECATED! use 'adapter_khz' not 'jtag_khz'" eval adapter_khz $args } proc jtag_nsrst_delay args { echo "DEPRECATED! use 'adapter_nsrst_delay' not 'jtag_nsrst_delay'" eval adapter_nsrst_delay $args } proc jtag_nsrst_assert_width args { echo "DEPRECATED! use 'adapter_nsrst_assert_width' not 'jtag_nsrst_assert_width'" eval adapter_nsrst_assert_width $args } # stlink migration helpers proc stlink_device_desc args { echo "DEPRECATED! use 'hla_device_desc' not 'stlink_device_desc'" eval hla_device_desc $args } proc stlink_serial args { echo "DEPRECATED! use 'hla_serial' not 'stlink_serial'" eval hla_serial $args } proc stlink_layout args { echo "DEPRECATED! use 'hla_layout' not 'stlink_layout'" eval hla_layout $args } proc stlink_vid_pid args { echo "DEPRECATED! use 'hla_vid_pid' not 'stlink_vid_pid'" eval hla_vid_pid $args } proc stlink args { echo "DEPRECATED! use 'hla' not 'stlink'" eval hla $args } # END MIGRATION AIDS openocd-0.9.0/src/jtag/interfaces.c0000644000175000017500000001631012315575361014104 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "interfaces.h" /** @file * This file includes declarations for all built-in jtag interfaces, * which are then listed in the jtag_interfaces array. * * Dynamic loading can be implemented be searching for shared libraries * that contain a jtag_interface structure that can added to this list. */ #if BUILD_ZY1000 == 1 extern struct jtag_interface zy1000_interface; #elif defined(BUILD_MINIDRIVER_DUMMY) extern struct jtag_interface minidummy_interface; #else /* standard drivers */ #if BUILD_PARPORT == 1 extern struct jtag_interface parport_interface; #endif #if BUILD_DUMMY == 1 extern struct jtag_interface dummy_interface; #endif #if BUILD_FT2232_FTD2XX == 1 extern struct jtag_interface ft2232_interface; #endif #if BUILD_FT2232_LIBFTDI == 1 extern struct jtag_interface ft2232_interface; #endif #if BUILD_FTDI == 1 extern struct jtag_interface ftdi_interface; #endif #if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 extern struct jtag_interface usb_blaster_interface; #endif #if BUILD_JTAG_VPI == 1 extern struct jtag_interface jtag_vpi_interface; #endif #if BUILD_AMTJTAGACCEL == 1 extern struct jtag_interface amt_jtagaccel_interface; #endif #if BUILD_EP93XX == 1 extern struct jtag_interface ep93xx_interface; #endif #if BUILD_AT91RM9200 == 1 extern struct jtag_interface at91rm9200_interface; #endif #if BUILD_GW16012 == 1 extern struct jtag_interface gw16012_interface; #endif #if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 extern struct jtag_interface presto_interface; #endif #if BUILD_USBPROG == 1 extern struct jtag_interface usbprog_interface; #endif #if BUILD_OPENJTAG == 1 extern struct jtag_interface openjtag_interface; #endif #if BUILD_JLINK == 1 extern struct jtag_interface jlink_interface; #endif #if BUILD_VSLLINK == 1 extern struct jtag_interface vsllink_interface; #endif #if BUILD_RLINK == 1 extern struct jtag_interface rlink_interface; #endif #if BUILD_ULINK == 1 extern struct jtag_interface ulink_interface; #endif #if BUILD_ARMJTAGEW == 1 extern struct jtag_interface armjtagew_interface; #endif #if BUILD_BUSPIRATE == 1 extern struct jtag_interface buspirate_interface; #endif #if BUILD_REMOTE_BITBANG == 1 extern struct jtag_interface remote_bitbang_interface; #endif #if BUILD_HLADAPTER == 1 extern struct jtag_interface hl_interface; #endif #if BUILD_OSBDM == 1 extern struct jtag_interface osbdm_interface; #endif #if BUILD_OPENDOUS == 1 extern struct jtag_interface opendous_interface; #endif #if BUILD_SYSFSGPIO == 1 extern struct jtag_interface sysfsgpio_interface; #endif #if BUILD_AICE == 1 extern struct jtag_interface aice_interface; #endif #if BUILD_BCM2835GPIO == 1 extern struct jtag_interface bcm2835gpio_interface; #endif #if BUILD_CMSIS_DAP == 1 extern struct jtag_interface cmsis_dap_interface; #endif #endif /* standard drivers */ /** * The list of built-in JTAG interfaces, containing entries for those * drivers that were enabled by the @c configure script. * * The list should be defined to contain either one minidriver interface * or some number of standard driver interfaces, never both. */ struct jtag_interface *jtag_interfaces[] = { #if BUILD_ZY1000 == 1 &zy1000_interface, #elif defined(BUILD_MINIDRIVER_DUMMY) &minidummy_interface, #else /* standard drivers */ #if BUILD_PARPORT == 1 &parport_interface, #endif #if BUILD_DUMMY == 1 &dummy_interface, #endif #if BUILD_FT2232_FTD2XX == 1 &ft2232_interface, #endif #if BUILD_FT2232_LIBFTDI == 1 &ft2232_interface, #endif #if BUILD_FTDI == 1 &ftdi_interface, #endif #if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 &usb_blaster_interface, #endif #if BUILD_JTAG_VPI == 1 &jtag_vpi_interface, #endif #if BUILD_AMTJTAGACCEL == 1 &amt_jtagaccel_interface, #endif #if BUILD_EP93XX == 1 &ep93xx_interface, #endif #if BUILD_AT91RM9200 == 1 &at91rm9200_interface, #endif #if BUILD_GW16012 == 1 &gw16012_interface, #endif #if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 &presto_interface, #endif #if BUILD_USBPROG == 1 &usbprog_interface, #endif #if BUILD_OPENJTAG == 1 &openjtag_interface, #endif #if BUILD_JLINK == 1 &jlink_interface, #endif #if BUILD_VSLLINK == 1 &vsllink_interface, #endif #if BUILD_RLINK == 1 &rlink_interface, #endif #if BUILD_ULINK == 1 &ulink_interface, #endif #if BUILD_ARMJTAGEW == 1 &armjtagew_interface, #endif #if BUILD_BUSPIRATE == 1 &buspirate_interface, #endif #if BUILD_REMOTE_BITBANG == 1 &remote_bitbang_interface, #endif #if BUILD_HLADAPTER == 1 &hl_interface, #endif #if BUILD_OSBDM == 1 &osbdm_interface, #endif #if BUILD_OPENDOUS == 1 &opendous_interface, #endif #if BUILD_SYSFSGPIO == 1 &sysfsgpio_interface, #endif #if BUILD_AICE == 1 &aice_interface, #endif #if BUILD_BCM2835GPIO == 1 &bcm2835gpio_interface, #endif #if BUILD_CMSIS_DAP == 1 &cmsis_dap_interface, #endif #endif /* standard drivers */ NULL, }; void jtag_interface_modules_load(const char *path) { /* @todo: implement dynamic module loading for JTAG interface drivers */ } openocd-0.9.0/src/jtag/interfaces.h0000644000175000017500000000522012315575361014107 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OPENOCD_JTAG_INTERFACES_H #define OPENOCD_JTAG_INTERFACES_H /** @file * Exports the list of JTAG interface drivers, along with routines * for loading and unloading them dynamically from shared libraries. */ #include /** Dynamically load all JTAG interface modules from specified directory. */ void jtag_interface_modules_load(const char *path); extern struct jtag_interface *jtag_interfaces[]; #endif /* OPENOCD_JTAG_INTERFACES_H */ openocd-0.9.0/src/jtag/minidummy/0000755000175000017500000000000012526202224013671 500000000000000openocd-0.9.0/src/jtag/minidummy/jtag_minidriver.h0000644000175000017500000000305212315575361017152 00000000000000/*************************************************************************** * Copyright (C) 2007-2008 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #define interface_jtag_add_callback(callback, in) callback(in) #define interface_jtag_add_callback4(callback, in, data1, data2, data3) \ jtag_set_error(callback(in, data1, data2, data3)) openocd-0.9.0/src/jtag/minidummy/minidummy.c0000644000175000017500000001102112315575361015773 00000000000000/*************************************************************************** * Copyright (C) 2007-2008 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include struct jtag_interface minidummy_interface = { .name = "minidummy", .execute_queue = NULL, .speed = NULL, .commands = NULL, .init = NULL, .quit = NULL, .khz = NULL, .speed_div = NULL, .power_dropout = NULL, .srst_asserted = NULL, }; int interface_jtag_execute_queue(void) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields, tap_state_t state) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields, const struct scan_field *fields, tap_state_t state) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_tlr() { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_reset(int req_trst, int req_srst) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_runtest(int num_cycles, tap_state_t state) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_clocks(int num_cycles) { /* synchronously do the operation here */ return ERROR_OK; } int interface_jtag_add_sleep(uint32_t us) { jtag_sleep(us); return ERROR_OK; } int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) { int state_count; int tms = 0; state_count = 0; tap_state_t cur_state = cmd_queue_cur_state; while (num_states) { if (tap_state_transition(cur_state, false) == path[state_count]) tms = 0; else if (tap_state_transition(cur_state, true) == path[state_count]) tms = 1; else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[state_count])); exit(-1); } /* synchronously do the operation here */ cur_state = path[state_count]; state_count++; num_states--; } /* synchronously do the operation here */ return ERROR_OK; } int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) { /* synchronously do the operation here */ return ERROR_OK; } void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count) { int i; for (i = 0; i < count; i++) { embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little)); buffer += 4; } } int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode, uint32_t *data, size_t count) { int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap, \ uint32_t opcode, uint32_t *data, size_t count); return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count); } openocd-0.9.0/src/jtag/core.c0000644000175000017500000014126012516456302012710 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * Copyright (C) 2007,2008,2009 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag.h" #include "swd.h" #include "interface.h" #include #ifdef HAVE_STRINGS_H #include #endif /* SVF and XSVF are higher level JTAG command sets (for boundary scan) */ #include "svf/svf.h" #include "xsvf/xsvf.h" /** The number of JTAG queue flushes (for profiling and debugging purposes). */ static int jtag_flush_queue_count; /* Sleep this # of ms after flushing the queue */ static int jtag_flush_queue_sleep; static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state), int in_num_fields, struct scan_field *in_fields, tap_state_t state); /** * The jtag_error variable is set when an error occurs while executing * the queue. Application code may set this using jtag_set_error(), * when an error occurs during processing that should be reported during * jtag_execute_queue(). * * The value is set and cleared, but never read by normal application code. * * This value is returned (and cleared) by jtag_execute_queue(). */ static int jtag_error = ERROR_OK; static const char *jtag_event_strings[] = { [JTAG_TRST_ASSERTED] = "TAP reset", [JTAG_TAP_EVENT_SETUP] = "TAP setup", [JTAG_TAP_EVENT_ENABLE] = "TAP enabled", [JTAG_TAP_EVENT_DISABLE] = "TAP disabled", }; /* * JTAG adapters must initialize with TRST and SRST de-asserted * (they're negative logic, so that means *high*). But some * hardware doesn't necessarily work that way ... so set things * up so that jtag_init() always forces that state. */ static int jtag_trst = -1; static int jtag_srst = -1; /** * List all TAPs that have been created. */ static struct jtag_tap *__jtag_all_taps; static enum reset_types jtag_reset_config = RESET_NONE; tap_state_t cmd_queue_cur_state = TAP_RESET; static bool jtag_verify_capture_ir = true; static int jtag_verify = 1; /* how long the OpenOCD should wait before attempting JTAG communication after reset lines *deasserted (in ms) */ static int adapter_nsrst_delay; /* default to no nSRST delay */ static int jtag_ntrst_delay;/* default to no nTRST delay */ static int adapter_nsrst_assert_width; /* width of assertion */ static int jtag_ntrst_assert_width; /* width of assertion */ /** * Contains a single callback along with a pointer that will be passed * when an event occurs. */ struct jtag_event_callback { /** a event callback */ jtag_event_handler_t callback; /** the private data to pass to the callback */ void *priv; /** the next callback */ struct jtag_event_callback *next; }; /* callbacks to inform high-level handlers about JTAG state changes */ static struct jtag_event_callback *jtag_event_callbacks; /* speed in kHz*/ static int speed_khz; /* speed to fallback to when RCLK is requested but not supported */ static int rclk_fallback_speed_khz; static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; static int jtag_speed; static struct jtag_interface *jtag; /* configuration */ struct jtag_interface *jtag_interface; void jtag_set_flush_queue_sleep(int ms) { jtag_flush_queue_sleep = ms; } void jtag_set_error(int error) { if ((error == ERROR_OK) || (jtag_error != ERROR_OK)) return; jtag_error = error; } int jtag_error_clear(void) { int temp = jtag_error; jtag_error = ERROR_OK; return temp; } /************/ static bool jtag_poll = 1; bool is_jtag_poll_safe(void) { /* Polling can be disabled explicitly with set_enabled(false). * It is also implicitly disabled while TRST is active and * while SRST is gating the JTAG clock. */ if (!transport_is_jtag()) return jtag_poll; if (!jtag_poll || jtag_trst != 0) return false; return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING); } bool jtag_poll_get_enabled(void) { return jtag_poll; } void jtag_poll_set_enabled(bool value) { jtag_poll = value; } /************/ struct jtag_tap *jtag_all_taps(void) { return __jtag_all_taps; }; unsigned jtag_tap_count(void) { struct jtag_tap *t = jtag_all_taps(); unsigned n = 0; while (t) { n++; t = t->next_tap; } return n; } unsigned jtag_tap_count_enabled(void) { struct jtag_tap *t = jtag_all_taps(); unsigned n = 0; while (t) { if (t->enabled) n++; t = t->next_tap; } return n; } /** Append a new TAP to the chain of all taps. */ void jtag_tap_add(struct jtag_tap *t) { unsigned jtag_num_taps = 0; struct jtag_tap **tap = &__jtag_all_taps; while (*tap != NULL) { jtag_num_taps++; tap = &(*tap)->next_tap; } *tap = t; t->abs_chain_position = jtag_num_taps; } /* returns a pointer to the n-th device in the scan chain */ struct jtag_tap *jtag_tap_by_position(unsigned n) { struct jtag_tap *t = jtag_all_taps(); while (t && n-- > 0) t = t->next_tap; return t; } struct jtag_tap *jtag_tap_by_string(const char *s) { /* try by name first */ struct jtag_tap *t = jtag_all_taps(); while (t) { if (0 == strcmp(t->dotted_name, s)) return t; t = t->next_tap; } /* no tap found by name, so try to parse the name as a number */ unsigned n; if (parse_uint(s, &n) != ERROR_OK) return NULL; /* FIXME remove this numeric fallback code late June 2010, along * with all info in the User's Guide that TAPs have numeric IDs. * Also update "scan_chain" output to not display the numbers. */ t = jtag_tap_by_position(n); if (t) LOG_WARNING("Specify TAP '%s' by name, not number %u", t->dotted_name, n); return t; } struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p) { p = p ? p->next_tap : jtag_all_taps(); while (p) { if (p->enabled) return p; p = p->next_tap; } return NULL; } const char *jtag_tap_name(const struct jtag_tap *tap) { return (tap == NULL) ? "(unknown)" : tap->dotted_name; } int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) { struct jtag_event_callback **callbacks_p = &jtag_event_callbacks; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; if (*callbacks_p) { while ((*callbacks_p)->next) callbacks_p = &((*callbacks_p)->next); callbacks_p = &((*callbacks_p)->next); } (*callbacks_p) = malloc(sizeof(struct jtag_event_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; return ERROR_OK; } int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv) { struct jtag_event_callback **p = &jtag_event_callbacks, *temp; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; while (*p) { if (((*p)->priv != priv) || ((*p)->callback != callback)) { p = &(*p)->next; continue; } temp = *p; *p = (*p)->next; free(temp); } return ERROR_OK; } int jtag_call_event_callbacks(enum jtag_event event) { struct jtag_event_callback *callback = jtag_event_callbacks; LOG_DEBUG("jtag event: %s", jtag_event_strings[event]); while (callback) { struct jtag_event_callback *next; /* callback may remove itself */ next = callback->next; callback->callback(event, callback->priv); callback = next; } return ERROR_OK; } static void jtag_checks(void) { assert(jtag_trst == 0); } static void jtag_prelude(tap_state_t state) { jtag_checks(); assert(state != TAP_INVALID); cmd_queue_cur_state = state; } void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields, tap_state_t state) { jtag_prelude(state); int retval = interface_jtag_add_ir_scan(active, in_fields, state); jtag_set_error(retval); } static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active, int dummy, const struct scan_field *in_fields, tap_state_t state) { jtag_add_ir_scan_noverify(active, in_fields, state); } /* If fields->in_value is filled out, then the captured IR value will be checked */ void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state) { assert(state != TAP_RESET); if (jtag_verify && jtag_verify_capture_ir) { /* 8 x 32 bit id's is enough for all invocations */ /* if we are to run a verification of the ir scan, we need to get the input back. * We may have to allocate space if the caller didn't ask for the input back. */ in_fields->check_value = active->expected; in_fields->check_mask = active->expected_mask; jtag_add_scan_check(active, jtag_add_ir_scan_noverify_callback, 1, in_fields, state); } else jtag_add_ir_scan_noverify(active, in_fields, state); } void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { assert(out_bits != NULL); assert(state != TAP_RESET); jtag_prelude(state); int retval = interface_jtag_add_plain_ir_scan( num_bits, out_bits, in_bits, state); jtag_set_error(retval); } static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits); static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { return jtag_check_value_inner((uint8_t *)data0, (uint8_t *)data1, (uint8_t *)data2, (int)data3); } static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state), int in_num_fields, struct scan_field *in_fields, tap_state_t state) { jtag_add_scan(active, in_num_fields, in_fields, state); for (int i = 0; i < in_num_fields; i++) { if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) { /* this is synchronous for a minidriver */ jtag_add_callback4(jtag_check_value_mask_callback, (jtag_callback_data_t)in_fields[i].in_value, (jtag_callback_data_t)in_fields[i].check_value, (jtag_callback_data_t)in_fields[i].check_mask, (jtag_callback_data_t)in_fields[i].num_bits); } } } void jtag_add_dr_scan_check(struct jtag_tap *active, int in_num_fields, struct scan_field *in_fields, tap_state_t state) { if (jtag_verify) jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state); else jtag_add_dr_scan(active, in_num_fields, in_fields, state); } void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state) { assert(state != TAP_RESET); jtag_prelude(state); int retval; retval = interface_jtag_add_dr_scan(active, in_num_fields, in_fields, state); jtag_set_error(retval); } void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { assert(out_bits != NULL); assert(state != TAP_RESET); jtag_prelude(state); int retval; retval = interface_jtag_add_plain_dr_scan(num_bits, out_bits, in_bits, state); jtag_set_error(retval); } void jtag_add_tlr(void) { jtag_prelude(TAP_RESET); jtag_set_error(interface_jtag_add_tlr()); /* NOTE: order here matches TRST path in jtag_add_reset() */ jtag_call_event_callbacks(JTAG_TRST_ASSERTED); jtag_notify_event(JTAG_TRST_ASSERTED); } /** * If supported by the underlying adapter, this clocks a raw bit sequence * onto TMS for switching betwen JTAG and SWD modes. * * DO NOT use this to bypass the integrity checks and logging provided * by the jtag_add_pathmove() and jtag_add_statemove() calls. * * @param nbits How many bits to clock out. * @param seq The bit sequence. The LSB is bit 0 of seq[0]. * @param state The JTAG tap state to record on completion. Use * TAP_INVALID to represent being in in SWD mode. * * @todo Update naming conventions to stop assuming everything is JTAG. */ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) { int retval; if (!(jtag->supported & DEBUG_CAP_TMS_SEQ)) return ERROR_JTAG_NOT_IMPLEMENTED; jtag_checks(); cmd_queue_cur_state = state; retval = interface_add_tms_seq(nbits, seq, state); jtag_set_error(retval); return retval; } void jtag_add_pathmove(int num_states, const tap_state_t *path) { tap_state_t cur_state = cmd_queue_cur_state; /* the last state has to be a stable state */ if (!tap_is_state_stable(path[num_states - 1])) { LOG_ERROR("BUG: TAP path doesn't finish in a stable state"); jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE); return; } for (int i = 0; i < num_states; i++) { if (path[i] == TAP_RESET) { LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); jtag_set_error(ERROR_JTAG_STATE_INVALID); return; } if (tap_state_transition(cur_state, true) != path[i] && tap_state_transition(cur_state, false) != path[i]) { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[i])); jtag_set_error(ERROR_JTAG_TRANSITION_INVALID); return; } cur_state = path[i]; } jtag_checks(); jtag_set_error(interface_jtag_add_pathmove(num_states, path)); cmd_queue_cur_state = path[num_states - 1]; } int jtag_add_statemove(tap_state_t goal_state) { tap_state_t cur_state = cmd_queue_cur_state; if (goal_state != cur_state) { LOG_DEBUG("cur_state=%s goal_state=%s", tap_state_name(cur_state), tap_state_name(goal_state)); } /* If goal is RESET, be paranoid and force that that transition * (e.g. five TCK cycles, TMS high). Else trust "cur_state". */ if (goal_state == TAP_RESET) jtag_add_tlr(); else if (goal_state == cur_state) /* nothing to do */; else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) { unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); tap_state_t moves[8]; assert(tms_count < ARRAY_SIZE(moves)); for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) { bool bit = tms_bits & 1; cur_state = tap_state_transition(cur_state, bit); moves[i] = cur_state; } jtag_add_pathmove(tms_count, moves); } else if (tap_state_transition(cur_state, true) == goal_state || tap_state_transition(cur_state, false) == goal_state) jtag_add_pathmove(1, &goal_state); else return ERROR_FAIL; return ERROR_OK; } void jtag_add_runtest(int num_cycles, tap_state_t state) { jtag_prelude(state); jtag_set_error(interface_jtag_add_runtest(num_cycles, state)); } void jtag_add_clocks(int num_cycles) { if (!tap_is_state_stable(cmd_queue_cur_state)) { LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"", tap_state_name(cmd_queue_cur_state)); jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE); return; } if (num_cycles > 0) { jtag_checks(); jtag_set_error(interface_jtag_add_clocks(num_cycles)); } } void swd_add_reset(int req_srst) { if (req_srst) { if (!(jtag_reset_config & RESET_HAS_SRST)) { LOG_ERROR("BUG: can't assert SRST"); jtag_set_error(ERROR_FAIL); return; } req_srst = 1; } /* Maybe change SRST signal state */ if (jtag_srst != req_srst) { int retval; retval = interface_jtag_add_reset(0, req_srst); if (retval != ERROR_OK) jtag_set_error(retval); else retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("TRST/SRST error"); return; } /* SRST resets everything hooked up to that signal */ jtag_srst = req_srst; if (jtag_srst) { LOG_DEBUG("SRST line asserted"); if (adapter_nsrst_assert_width) jtag_add_sleep(adapter_nsrst_assert_width * 1000); } else { LOG_DEBUG("SRST line released"); if (adapter_nsrst_delay) jtag_add_sleep(adapter_nsrst_delay * 1000); } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("SRST timings error"); return; } } } void jtag_add_reset(int req_tlr_or_trst, int req_srst) { int trst_with_tlr = 0; int new_srst = 0; int new_trst = 0; /* Without SRST, we must use target-specific JTAG operations * on each target; callers should not be requesting SRST when * that signal doesn't exist. * * RESET_SRST_PULLS_TRST is a board or chip level quirk, which * can kick in even if the JTAG adapter can't drive TRST. */ if (req_srst) { if (!(jtag_reset_config & RESET_HAS_SRST)) { LOG_ERROR("BUG: can't assert SRST"); jtag_set_error(ERROR_FAIL); return; } if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0 && !req_tlr_or_trst) { LOG_ERROR("BUG: can't assert only SRST"); jtag_set_error(ERROR_FAIL); return; } new_srst = 1; } /* JTAG reset (entry to TAP_RESET state) can always be achieved * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE * state first. TRST accelerates it, and bypasses those states. * * RESET_TRST_PULLS_SRST is a board or chip level quirk, which * can kick in even if the JTAG adapter can't drive SRST. */ if (req_tlr_or_trst) { if (!(jtag_reset_config & RESET_HAS_TRST)) trst_with_tlr = 1; else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0 && !req_srst) trst_with_tlr = 1; else new_trst = 1; } /* Maybe change TRST and/or SRST signal state */ if (jtag_srst != new_srst || jtag_trst != new_trst) { int retval; retval = interface_jtag_add_reset(new_trst, new_srst); if (retval != ERROR_OK) jtag_set_error(retval); else retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("TRST/SRST error"); return; } } /* SRST resets everything hooked up to that signal */ if (jtag_srst != new_srst) { jtag_srst = new_srst; if (jtag_srst) { LOG_DEBUG("SRST line asserted"); if (adapter_nsrst_assert_width) jtag_add_sleep(adapter_nsrst_assert_width * 1000); } else { LOG_DEBUG("SRST line released"); if (adapter_nsrst_delay) jtag_add_sleep(adapter_nsrst_delay * 1000); } } /* Maybe enter the JTAG TAP_RESET state ... * - using only TMS, TCK, and the JTAG state machine * - or else more directly, using TRST * * TAP_RESET should be invisible to non-debug parts of the system. */ if (trst_with_tlr) { LOG_DEBUG("JTAG reset with TLR instead of TRST"); jtag_add_tlr(); } else if (jtag_trst != new_trst) { jtag_trst = new_trst; if (jtag_trst) { LOG_DEBUG("TRST line asserted"); tap_set_state(TAP_RESET); if (jtag_ntrst_assert_width) jtag_add_sleep(jtag_ntrst_assert_width * 1000); } else { LOG_DEBUG("TRST line released"); if (jtag_ntrst_delay) jtag_add_sleep(jtag_ntrst_delay * 1000); /* We just asserted nTRST, so we're now in TAP_RESET. * Inform possible listeners about this, now that * JTAG instructions and data can be shifted. This * sequence must match jtag_add_tlr(). */ jtag_call_event_callbacks(JTAG_TRST_ASSERTED); jtag_notify_event(JTAG_TRST_ASSERTED); } } } void jtag_add_sleep(uint32_t us) { /** @todo Here, keep_alive() appears to be a layering violation!!! */ keep_alive(); jtag_set_error(interface_jtag_add_sleep(us)); } static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits) { int retval = ERROR_OK; int compare_failed; if (in_check_mask) compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); else compare_failed = buf_cmp(captured, in_check_value, num_bits); if (compare_failed) { char *captured_str, *in_check_value_str; int bits = (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits; /* NOTE: we've lost diagnostic context here -- 'which tap' */ captured_str = buf_to_str(captured, bits, 16); in_check_value_str = buf_to_str(in_check_value, bits, 16); LOG_WARNING("Bad value '%s' captured during DR or IR scan:", captured_str); LOG_WARNING(" check_value: 0x%s", in_check_value_str); free(captured_str); free(in_check_value_str); if (in_check_mask) { char *in_check_mask_str; in_check_mask_str = buf_to_str(in_check_mask, bits, 16); LOG_WARNING(" check_mask: 0x%s", in_check_mask_str); free(in_check_mask_str); } retval = ERROR_JTAG_QUEUE_FAILED; } return retval; } void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask) { assert(field->in_value != NULL); if (value == NULL) { /* no checking to do */ return; } jtag_execute_queue_noclear(); int retval = jtag_check_value_inner(field->in_value, value, mask, field->num_bits); jtag_set_error(retval); } int default_interface_jtag_execute_queue(void) { if (NULL == jtag) { LOG_ERROR("No JTAG interface configured yet. " "Issue 'init' command in startup scripts " "before communicating with targets."); return ERROR_FAIL; } return jtag->execute_queue(); } void jtag_execute_queue_noclear(void) { jtag_flush_queue_count++; jtag_set_error(interface_jtag_execute_queue()); if (jtag_flush_queue_sleep > 0) { /* For debug purposes it can be useful to test performance * or behavior when delaying after flushing the queue, * e.g. to simulate long roundtrip times. */ usleep(jtag_flush_queue_sleep * 1000); } } int jtag_get_flush_queue_count(void) { return jtag_flush_queue_count; } int jtag_execute_queue(void) { jtag_execute_queue_noclear(); return jtag_error_clear(); } static int jtag_reset_callback(enum jtag_event event, void *priv) { struct jtag_tap *tap = priv; if (event == JTAG_TRST_ASSERTED) { tap->enabled = !tap->disabled_after_reset; /* current instruction is either BYPASS or IDCODE */ buf_set_ones(tap->cur_instr, tap->ir_length); tap->bypass = 1; } return ERROR_OK; } /* sleep at least us microseconds. When we sleep more than 1000ms we * do an alive sleep, i.e. keep GDB alive. Note that we could starve * GDB if we slept for <1000ms many times. */ void jtag_sleep(uint32_t us) { if (us < 1000) usleep(us); else alive_sleep((us+999)/1000); } #define JTAG_MAX_AUTO_TAPS 20 #define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) /* A reserved manufacturer ID is used in END_OF_CHAIN_FLAG, so we * know that no valid TAP will have it as an IDCODE value. */ #define END_OF_CHAIN_FLAG 0xffffffff /* a larger IR length than we ever expect to autoprobe */ #define JTAG_IRLEN_MAX 60 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) { struct scan_field field = { .num_bits = num_idcode * 32, .out_value = idcode_buffer, .in_value = idcode_buffer, }; /* initialize to the end of chain ID value */ for (unsigned i = 0; i < num_idcode; i++) buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG); jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); jtag_add_tlr(); return jtag_execute_queue(); } static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count) { uint8_t zero_check = 0x0; uint8_t one_check = 0xff; for (unsigned i = 0; i < count * 4; i++) { zero_check |= idcodes[i]; one_check &= idcodes[i]; } /* if there wasn't a single non-zero bit or if all bits were one, * the scan is not valid. We wrote a mix of both values; either * * - There's a hardware issue (almost certainly): * + all-zeroes can mean a target stuck in JTAG reset * + all-ones tends to mean no target * - The scan chain is WAY longer than we can handle, *AND* either * + there are several hundreds of TAPs in bypass, or * + at least a few dozen TAPs all have an all-ones IDCODE */ if (zero_check == 0x00 || one_check == 0xff) { LOG_ERROR("JTAG scan chain interrogation failed: all %s", (zero_check == 0x00) ? "zeroes" : "ones"); LOG_ERROR("Check JTAG interface, timings, target power, etc."); return false; } return true; } static void jtag_examine_chain_display(enum log_levels level, const char *msg, const char *name, uint32_t idcode) { log_printf_lf(level, __FILE__, __LINE__, __func__, "JTAG tap: %s %16.16s: 0x%08x " "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)", name, msg, (unsigned int)idcode, (unsigned int)EXTRACT_MFG(idcode), (unsigned int)EXTRACT_PART(idcode), (unsigned int)EXTRACT_VER(idcode)); } static bool jtag_idcode_is_final(uint32_t idcode) { /* * Some devices, such as AVR8, will output all 1's instead * of TDI input value at end of chain. Allow those values * instead of failing. */ return idcode == END_OF_CHAIN_FLAG; } /** * This helper checks that remaining bits in the examined chain data are * all as expected, but a single JTAG device requires only 64 bits to be * read back correctly. This can help identify and diagnose problems * with the JTAG chain earlier, gives more helpful/explicit error messages. * Returns TRUE iff garbage was found. */ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) { bool triggered = false; for (; count < max - 31; count += 32) { uint32_t idcode = buf_get_u32(idcodes, count, 32); /* do not trigger the warning if the data looks good */ if (jtag_idcode_is_final(idcode)) continue; LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x", count, (unsigned int)idcode); triggered = true; } return triggered; } static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) { if (tap->expected_ids_cnt == 0 || !tap->hasidcode) return true; /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */ uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0; uint32_t idcode = tap->idcode & mask; /* Loop over the expected identification codes and test for a match */ for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { uint32_t expected = tap->expected_ids[ii] & mask; if (idcode == expected) return true; /* treat "-expected-id 0" as a "don't-warn" wildcard */ if (0 == tap->expected_ids[ii]) return true; } /* If none of the expected ids matched, warn */ jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED", tap->dotted_name, tap->idcode); for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { char msg[32]; snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt); jtag_examine_chain_display(LOG_LVL_ERROR, msg, tap->dotted_name, tap->expected_ids[ii]); } return false; } /* Try to examine chain layout according to IEEE 1149.1 §12 * This is called a "blind interrogation" of the scan chain. */ static int jtag_examine_chain(void) { int retval; unsigned max_taps = jtag_tap_count(); /* Autoprobe up to this many. */ if (max_taps < JTAG_MAX_AUTO_TAPS) max_taps = JTAG_MAX_AUTO_TAPS; /* Add room for end-of-chain marker. */ max_taps++; uint8_t *idcode_buffer = malloc(max_taps * 4); if (idcode_buffer == NULL) return ERROR_JTAG_INIT_FAILED; /* DR scan to collect BYPASS or IDCODE register contents. * Then make sure the scan data has both ones and zeroes. */ LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS"); retval = jtag_examine_chain_execute(idcode_buffer, max_taps); if (retval != ERROR_OK) goto out; if (!jtag_examine_chain_check(idcode_buffer, max_taps)) { retval = ERROR_JTAG_INIT_FAILED; goto out; } /* Point at the 1st predefined tap, if any */ struct jtag_tap *tap = jtag_tap_next_enabled(NULL); unsigned bit_count = 0; unsigned autocount = 0; for (unsigned i = 0; i < max_taps; i++) { assert(bit_count < max_taps * 32); uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32); /* No predefined TAP? Auto-probe. */ if (tap == NULL) { /* Is there another TAP? */ if (jtag_idcode_is_final(idcode)) break; /* Default everything in this TAP except IR length. * * REVISIT create a jtag_alloc(chip, tap) routine, and * share it with jim_newtap_cmd(). */ tap = calloc(1, sizeof *tap); if (!tap) { retval = ERROR_FAIL; goto out; } tap->chip = alloc_printf("auto%u", autocount++); tap->tapname = strdup("tap"); tap->dotted_name = alloc_printf("%s.%s", tap->chip, tap->tapname); tap->ir_length = 0; /* ... signifying irlen autoprobe */ tap->ir_capture_mask = 0x03; tap->ir_capture_value = 0x01; tap->enabled = true; jtag_tap_init(tap); } if ((idcode & 1) == 0) { /* Zero for LSB indicates a device in bypass */ LOG_INFO("TAP %s does not have IDCODE", tap->dotted_name); tap->hasidcode = false; tap->idcode = 0; bit_count += 1; } else { /* Friendly devices support IDCODE */ tap->hasidcode = true; tap->idcode = idcode; jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode); bit_count += 32; } /* ensure the TAP ID matches what was expected */ if (!jtag_examine_chain_match_tap(tap)) retval = ERROR_JTAG_INIT_SOFT_FAIL; tap = jtag_tap_next_enabled(tap); } /* After those IDCODE or BYPASS register values should be * only the data we fed into the scan chain. */ if (jtag_examine_chain_end(idcode_buffer, bit_count, max_taps * 32)) { LOG_ERROR("double-check your JTAG setup (interface, speed, ...)"); retval = ERROR_JTAG_INIT_FAILED; goto out; } /* Return success or, for backwards compatibility if only * some IDCODE values mismatched, a soft/continuable fault. */ out: free(idcode_buffer); return retval; } /* * Validate the date loaded by entry to the Capture-IR state, to help * find errors related to scan chain configuration (wrong IR lengths) * or communication. * * Entry state can be anything. On non-error exit, all TAPs are in * bypass mode. On error exits, the scan chain is reset. */ static int jtag_validate_ircapture(void) { struct jtag_tap *tap; int total_ir_length = 0; uint8_t *ir_test = NULL; struct scan_field field; uint64_t val; int chain_pos = 0; int retval; /* when autoprobing, accomodate huge IR lengths */ for (tap = NULL, total_ir_length = 0; (tap = jtag_tap_next_enabled(tap)) != NULL; total_ir_length += tap->ir_length) { if (tap->ir_length == 0) total_ir_length += JTAG_IRLEN_MAX; } /* increase length to add 2 bit sentinel after scan */ total_ir_length += 2; ir_test = malloc(DIV_ROUND_UP(total_ir_length, 8)); if (ir_test == NULL) return ERROR_FAIL; /* after this scan, all TAPs will capture BYPASS instructions */ buf_set_ones(ir_test, total_ir_length); field.num_bits = total_ir_length; field.out_value = ir_test; field.in_value = ir_test; jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, TAP_IDLE); LOG_DEBUG("IR capture validation scan"); retval = jtag_execute_queue(); if (retval != ERROR_OK) goto done; tap = NULL; chain_pos = 0; for (;; ) { tap = jtag_tap_next_enabled(tap); if (tap == NULL) break; /* If we're autoprobing, guess IR lengths. They must be at * least two bits. Guessing will fail if (a) any TAP does * not conform to the JTAG spec; or (b) when the upper bits * captured from some conforming TAP are nonzero. Or if * (c) an IR length is longer than JTAG_IRLEN_MAX bits, * an implementation limit, which could someday be raised. * * REVISIT optimization: if there's a *single* TAP we can * lift restrictions (a) and (b) by scanning a recognizable * pattern before the all-ones BYPASS. Check for where the * pattern starts in the result, instead of an 0...01 value. * * REVISIT alternative approach: escape to some tcl code * which could provide more knowledge, based on IDCODE; and * only guess when that has no success. */ if (tap->ir_length == 0) { tap->ir_length = 2; while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1 && tap->ir_length < JTAG_IRLEN_MAX) { tap->ir_length++; } LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d " "-expected-id 0x%08" PRIx32 "\"", tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode); } /* Validate the two LSBs, which must be 01 per JTAG spec. * * Or ... more bits could be provided by TAP declaration. * Plus, some taps (notably in i.MX series chips) violate * this part of the JTAG spec, so their capture mask/value * attributes might disable this test. */ val = buf_get_u64(ir_test, chain_pos, tap->ir_length); if ((val & tap->ir_capture_mask) != tap->ir_capture_value) { LOG_ERROR("%s: IR capture error; saw 0x%0*" PRIx64 " not 0x%0*" PRIx32, jtag_tap_name(tap), (tap->ir_length + 7) / tap->ir_length, val, (tap->ir_length + 7) / tap->ir_length, tap->ir_capture_value); retval = ERROR_JTAG_INIT_FAILED; goto done; } LOG_DEBUG("%s: IR capture 0x%0*" PRIx64, jtag_tap_name(tap), (tap->ir_length + 7) / tap->ir_length, val); chain_pos += tap->ir_length; } /* verify the '11' sentinel we wrote is returned at the end */ val = buf_get_u64(ir_test, chain_pos, 2); if (val != 0x3) { char *cbuf = buf_to_str(ir_test, total_ir_length, 16); LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3", chain_pos, cbuf); free(cbuf); retval = ERROR_JTAG_INIT_FAILED; } done: free(ir_test); if (retval != ERROR_OK) { jtag_add_tlr(); jtag_execute_queue(); } return retval; } void jtag_tap_init(struct jtag_tap *tap) { unsigned ir_len_bits; unsigned ir_len_bytes; /* if we're autoprobing, cope with potentially huge ir_length */ ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX; ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8); tap->expected = calloc(1, ir_len_bytes); tap->expected_mask = calloc(1, ir_len_bytes); tap->cur_instr = malloc(ir_len_bytes); /** @todo cope better with ir_length bigger than 32 bits */ if (ir_len_bits > 32) ir_len_bits = 32; buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value); buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask); /* TAP will be in bypass mode after jtag_validate_ircapture() */ tap->bypass = 1; buf_set_ones(tap->cur_instr, tap->ir_length); /* register the reset callback for the TAP */ jtag_register_event_callback(&jtag_reset_callback, tap); jtag_tap_add(tap); LOG_DEBUG("Created Tap: %s @ abs position %d, " "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name, tap->abs_chain_position, tap->ir_length, (unsigned) tap->ir_capture_value, (unsigned) tap->ir_capture_mask); } void jtag_tap_free(struct jtag_tap *tap) { jtag_unregister_event_callback(&jtag_reset_callback, tap); free(tap->expected); free(tap->expected_mask); free(tap->expected_ids); free(tap->cur_instr); free(tap->chip); free(tap->tapname); free(tap->dotted_name); free(tap); } /** * Do low-level setup like initializing registers, output signals, * and clocking. */ int adapter_init(struct command_context *cmd_ctx) { if (jtag) return ERROR_OK; if (!jtag_interface) { /* nothing was previously specified by "interface" command */ LOG_ERROR("Debug Adapter has to be specified, " "see \"interface\" command"); return ERROR_JTAG_INVALID_INTERFACE; } int retval; retval = jtag_interface->init(); if (retval != ERROR_OK) return retval; jtag = jtag_interface; /* LEGACY SUPPORT ... adapter drivers must declare what * transports they allow. Until they all do so, assume * the legacy drivers are JTAG-only */ if (!transports_are_declared()) { LOG_ERROR("Adapter driver '%s' did not declare " "which transports it allows; assuming " "JTAG-only", jtag->name); retval = allow_transports(cmd_ctx, jtag_only); if (retval != ERROR_OK) return retval; } if (jtag->speed == NULL) { LOG_INFO("This adapter doesn't support configurable speed"); return ERROR_OK; } if (CLOCK_MODE_UNSELECTED == clock_mode) { LOG_ERROR("An adapter speed is not selected in the init script." " Insert a call to adapter_khz or jtag_rclk to proceed."); return ERROR_JTAG_INIT_FAILED; } int requested_khz = jtag_get_speed_khz(); int actual_khz = requested_khz; int jtag_speed_var = 0; retval = jtag_get_speed(&jtag_speed_var); if (retval != ERROR_OK) return retval; retval = jtag->speed(jtag_speed_var); if (retval != ERROR_OK) return retval; retval = jtag_get_speed_readable(&actual_khz); if (ERROR_OK != retval) LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var); else if (actual_khz) { /* Adaptive clocking -- JTAG-specific */ if ((CLOCK_MODE_RCLK == clock_mode) || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz)) { LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz" , actual_khz); } else LOG_INFO("clock speed %d kHz", actual_khz); } else LOG_INFO("RCLK (adaptive clock speed)"); return ERROR_OK; } int jtag_init_inner(struct command_context *cmd_ctx) { struct jtag_tap *tap; int retval; bool issue_setup = true; LOG_DEBUG("Init JTAG chain"); tap = jtag_tap_next_enabled(NULL); if (tap == NULL) { /* Once JTAG itself is properly set up, and the scan chain * isn't absurdly large, IDCODE autoprobe should work fine. * * But ... IRLEN autoprobe can fail even on systems which * are fully conformant to JTAG. Also, JTAG setup can be * quite finicky on some systems. * * REVISIT: if TAP autoprobe works OK, then in many cases * we could escape to tcl code and set up targets based on * the TAP's IDCODE values. */ LOG_WARNING("There are no enabled taps. " "AUTO PROBING MIGHT NOT WORK!!"); /* REVISIT default clock will often be too fast ... */ } jtag_add_tlr(); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* Examine DR values first. This discovers problems which will * prevent communication ... hardware issues like TDO stuck, or * configuring the wrong number of (enabled) TAPs. */ retval = jtag_examine_chain(); switch (retval) { case ERROR_OK: /* complete success */ break; default: /* For backward compatibility reasons, try coping with * configuration errors involving only ID mismatches. * We might be able to talk to the devices. * * Also the device might be powered down during startup. * * After OpenOCD starts, we can try to power on the device * and run a reset. */ LOG_ERROR("Trying to use configured scan chain anyway..."); issue_setup = false; break; } /* Now look at IR values. Problems here will prevent real * communication. They mostly mean that the IR length is * wrong ... or that the IR capture value is wrong. (The * latter is uncommon, but easily worked around: provide * ircapture/irmask values during TAP setup.) */ retval = jtag_validate_ircapture(); if (retval != ERROR_OK) { /* The target might be powered down. The user * can power it up and reset it after firing * up OpenOCD. */ issue_setup = false; } if (issue_setup) jtag_notify_event(JTAG_TAP_EVENT_SETUP); else LOG_WARNING("Bypassing JTAG setup events due to errors"); return ERROR_OK; } int adapter_quit(void) { if (!jtag || !jtag->quit) return ERROR_OK; /* close the JTAG interface */ int result = jtag->quit(); if (ERROR_OK != result) LOG_ERROR("failed: %d", result); return ERROR_OK; } int swd_init_reset(struct command_context *cmd_ctx) { int retval = adapter_init(cmd_ctx); if (retval != ERROR_OK) return retval; LOG_DEBUG("Initializing with hard SRST reset"); if (jtag_reset_config & RESET_HAS_SRST) swd_add_reset(1); swd_add_reset(0); retval = jtag_execute_queue(); return retval; } int jtag_init_reset(struct command_context *cmd_ctx) { int retval = adapter_init(cmd_ctx); if (retval != ERROR_OK) return retval; LOG_DEBUG("Initializing with hard TRST+SRST reset"); /* * This procedure is used by default when OpenOCD triggers a reset. * It's now done through an overridable Tcl "init_reset" wrapper. * * This started out as a more powerful "get JTAG working" reset than * jtag_init_inner(), applying TRST because some chips won't activate * JTAG without a TRST cycle (presumed to be async, though some of * those chips synchronize JTAG activation using TCK). * * But some chips only activate JTAG as part of an SRST cycle; SRST * got mixed in. So it became a hard reset routine, which got used * in more places, and which coped with JTAG reset being forced as * part of SRST (srst_pulls_trst). * * And even more corner cases started to surface: TRST and/or SRST * assertion timings matter; some chips need other JTAG operations; * TRST/SRST sequences can need to be different from these, etc. * * Systems should override that wrapper to support system-specific * requirements that this not-fully-generic code doesn't handle. * * REVISIT once Tcl code can read the reset_config modes, this won't * need to be a C routine at all... */ if (jtag_reset_config & RESET_HAS_SRST) { jtag_add_reset(1, 1); if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) jtag_add_reset(0, 1); } else { jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */ } /* some targets enable us to connect with srst asserted */ if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { if (jtag_reset_config & RESET_SRST_NO_GATING) jtag_add_reset(0, 1); else { LOG_WARNING("\'srst_nogate\' reset_config option is required"); jtag_add_reset(0, 0); } } else jtag_add_reset(0, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* Check that we can communication on the JTAG chain + eventually we want to * be able to perform enumeration only after OpenOCD has started * telnet and GDB server * * That would allow users to more easily perform any magic they need to before * reset happens. */ return jtag_init_inner(cmd_ctx); } int jtag_init(struct command_context *cmd_ctx) { int retval = adapter_init(cmd_ctx); if (retval != ERROR_OK) return retval; /* guard against oddball hardware: force resets to be inactive */ jtag_add_reset(0, 0); /* some targets enable us to connect with srst asserted */ if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { if (jtag_reset_config & RESET_SRST_NO_GATING) jtag_add_reset(0, 1); else LOG_WARNING("\'srst_nogate\' reset_config option is required"); } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) return ERROR_FAIL; return ERROR_OK; } unsigned jtag_get_speed_khz(void) { return speed_khz; } static int adapter_khz_to_speed(unsigned khz, int *speed) { LOG_DEBUG("convert khz to interface specific speed value"); speed_khz = khz; if (jtag != NULL) { LOG_DEBUG("have interface set up"); int speed_div1; int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1); if (ERROR_OK != retval) return retval; *speed = speed_div1; } return ERROR_OK; } static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed) { int retval = adapter_khz_to_speed(0, speed); if ((ERROR_OK != retval) && fallback_speed_khz) { LOG_DEBUG("trying fallback speed..."); retval = adapter_khz_to_speed(fallback_speed_khz, speed); } return retval; } static int jtag_set_speed(int speed) { jtag_speed = speed; /* this command can be called during CONFIG, * in which case jtag isn't initialized */ return jtag ? jtag->speed(speed) : ERROR_OK; } int jtag_config_khz(unsigned khz) { LOG_DEBUG("handle jtag khz"); clock_mode = CLOCK_MODE_KHZ; int speed = 0; int retval = adapter_khz_to_speed(khz, &speed); return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); } int jtag_config_rclk(unsigned fallback_speed_khz) { LOG_DEBUG("handle jtag rclk"); clock_mode = CLOCK_MODE_RCLK; rclk_fallback_speed_khz = fallback_speed_khz; int speed = 0; int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed); return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); } int jtag_get_speed(int *speed) { switch (clock_mode) { case CLOCK_MODE_KHZ: adapter_khz_to_speed(jtag_get_speed_khz(), speed); break; case CLOCK_MODE_RCLK: jtag_rclk_to_speed(rclk_fallback_speed_khz, speed); break; default: LOG_ERROR("BUG: unknown jtag clock mode"); return ERROR_FAIL; } return ERROR_OK; } int jtag_get_speed_readable(int *khz) { int jtag_speed_var = 0; int retval = jtag_get_speed(&jtag_speed_var); if (retval != ERROR_OK) return retval; return jtag ? jtag->speed_div(jtag_speed_var, khz) : ERROR_OK; } void jtag_set_verify(bool enable) { jtag_verify = enable; } bool jtag_will_verify() { return jtag_verify; } void jtag_set_verify_capture_ir(bool enable) { jtag_verify_capture_ir = enable; } bool jtag_will_verify_capture_ir() { return jtag_verify_capture_ir; } int jtag_power_dropout(int *dropout) { if (jtag == NULL) { /* TODO: as the jtag interface is not valid all * we can do at the moment is exit OpenOCD */ LOG_ERROR("No Valid JTAG Interface Configured."); exit(-1); } return jtag->power_dropout(dropout); } int jtag_srst_asserted(int *srst_asserted) { return jtag->srst_asserted(srst_asserted); } enum reset_types jtag_get_reset_config(void) { return jtag_reset_config; } void jtag_set_reset_config(enum reset_types type) { jtag_reset_config = type; } int jtag_get_trst(void) { return jtag_trst; } int jtag_get_srst(void) { return jtag_srst; } void jtag_set_nsrst_delay(unsigned delay) { adapter_nsrst_delay = delay; } unsigned jtag_get_nsrst_delay(void) { return adapter_nsrst_delay; } void jtag_set_ntrst_delay(unsigned delay) { jtag_ntrst_delay = delay; } unsigned jtag_get_ntrst_delay(void) { return jtag_ntrst_delay; } void jtag_set_nsrst_assert_width(unsigned delay) { adapter_nsrst_assert_width = delay; } unsigned jtag_get_nsrst_assert_width(void) { return adapter_nsrst_assert_width; } void jtag_set_ntrst_assert_width(unsigned delay) { jtag_ntrst_assert_width = delay; } unsigned jtag_get_ntrst_assert_width(void) { return jtag_ntrst_assert_width; } static int jtag_select(struct command_context *ctx) { int retval; /* NOTE: interface init must already have been done. * That works with only C code ... no Tcl glue required. */ retval = jtag_register_commands(ctx); if (retval != ERROR_OK) return retval; retval = svf_register_commands(ctx); if (retval != ERROR_OK) return retval; return xsvf_register_commands(ctx); } static struct transport jtag_transport = { .name = "jtag", .select = jtag_select, .init = jtag_init, }; static void jtag_constructor(void) __attribute__((constructor)); static void jtag_constructor(void) { transport_register(&jtag_transport); } /** Returns true if the current debug session * is using JTAG as its transport. */ bool transport_is_jtag(void) { return get_current_transport() == &jtag_transport; } void adapter_assert_reset(void) { if (transport_is_jtag()) { if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else jtag_add_reset(0, 1); } else if (transport_is_swd()) swd_add_reset(1); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", get_current_transport()->name); else LOG_ERROR("transport is not selected"); } void adapter_deassert_reset(void) { if (transport_is_jtag()) jtag_add_reset(0, 0); else if (transport_is_swd()) swd_add_reset(0); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", get_current_transport()->name); else LOG_ERROR("transport is not selected"); } int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { if (jtag->config_trace) return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq); else if (enabled) { LOG_ERROR("The selected interface does not support tracing"); return ERROR_FAIL; } return ERROR_OK; } int adapter_poll_trace(uint8_t *buf, size_t *size) { if (jtag->poll_trace) return jtag->poll_trace(buf, size); return ERROR_FAIL; } openocd-0.9.0/src/jtag/driver.h0000644000175000017500000000313112315575360013255 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_DRIVER_H #define JTAG_DRIVER_H struct command_context; int interface_register_commands(struct command_context *ctx); #endif /* JTAG_DRIVER_H */ openocd-0.9.0/src/jtag/Makefile.am0000644000175000017500000000264412315575360013655 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libjtag.la SUBDIRS = DRIVERFILES = libjtag_la_LIBADD = CLEANFILES = BUILT_SOURCES = BUILT_SOURCES += minidriver_imp.h CLEANFILES += minidriver_imp.h if MINIDRIVER if ZY1000 DRIVERFILES += zy1000/zy1000.c JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 endif if MINIDRIVER_DUMMY DRIVERFILES += minidummy/minidummy.c commands.c JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy endif MINIDRIVER_IMP_DIR = $(srcdir)/minidriver jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h cp $< $@ BUILT_SOURCES += jtag_minidriver.h CLEANFILES += jtag_minidriver.h else MINIDRIVER_IMP_DIR = $(srcdir)/drivers DRIVERFILES += commands.c if HLADAPTER SUBDIRS += hla libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la endif if AICE SUBDIRS += aice libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la endif SUBDIRS += drivers libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la endif # endif // MINIDRIVER minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h cp $< $@ libjtag_la_SOURCES = \ adapter.c \ core.c \ interface.c \ interfaces.c \ tcl.c \ $(DRIVERFILES) noinst_HEADERS = \ commands.h \ driver.h \ interface.h \ interfaces.h \ minidriver.h \ jtag.h \ minidriver/minidriver_imp.h \ minidummy/jtag_minidriver.h \ swd.h \ tcl.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/jtag/Makefile.in0000644000175000017500000006402312526201650013655 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @MINIDRIVER_TRUE@@ZY1000_TRUE@am__append_2 = zy1000/zy1000.c @MINIDRIVER_DUMMY_TRUE@@MINIDRIVER_TRUE@am__append_3 = minidummy/minidummy.c commands.c @MINIDRIVER_TRUE@am__append_4 = jtag_minidriver.h @MINIDRIVER_TRUE@am__append_5 = jtag_minidriver.h @MINIDRIVER_FALSE@am__append_6 = commands.c @HLADAPTER_TRUE@@MINIDRIVER_FALSE@am__append_7 = hla @HLADAPTER_TRUE@@MINIDRIVER_FALSE@am__append_8 = $(top_builddir)/src/jtag/hla/libocdhla.la @AICE_TRUE@@MINIDRIVER_FALSE@am__append_9 = aice @AICE_TRUE@@MINIDRIVER_FALSE@am__append_10 = $(top_builddir)/src/jtag/aice/libocdaice.la @MINIDRIVER_FALSE@am__append_11 = drivers @MINIDRIVER_FALSE@am__append_12 = $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la subdir = src/jtag ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libjtag_la_DEPENDENCIES = $(am__append_8) $(am__append_10) \ $(am__append_12) am__libjtag_la_SOURCES_DIST = adapter.c core.c interface.c \ interfaces.c tcl.c zy1000/zy1000.c minidummy/minidummy.c \ commands.c am__dirstamp = $(am__leading_dot)dirstamp @MINIDRIVER_TRUE@@ZY1000_TRUE@am__objects_1 = zy1000/zy1000.lo @MINIDRIVER_DUMMY_TRUE@@MINIDRIVER_TRUE@am__objects_2 = minidummy/minidummy.lo \ @MINIDRIVER_DUMMY_TRUE@@MINIDRIVER_TRUE@ commands.lo @MINIDRIVER_FALSE@am__objects_3 = commands.lo am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3) am_libjtag_la_OBJECTS = adapter.lo core.lo interface.lo interfaces.lo \ tcl.lo $(am__objects_4) libjtag_la_OBJECTS = $(am_libjtag_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libjtag_la_SOURCES) DIST_SOURCES = $(am__libjtag_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = hla aice drivers DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libjtag.la SUBDIRS = $(am__append_7) $(am__append_9) $(am__append_11) DRIVERFILES = $(am__append_2) $(am__append_3) $(am__append_6) libjtag_la_LIBADD = $(am__append_8) $(am__append_10) $(am__append_12) CLEANFILES = minidriver_imp.h $(am__append_5) BUILT_SOURCES = minidriver_imp.h $(am__append_4) @MINIDRIVER_DUMMY_TRUE@@MINIDRIVER_TRUE@JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy @MINIDRIVER_TRUE@@ZY1000_TRUE@JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 @MINIDRIVER_FALSE@MINIDRIVER_IMP_DIR = $(srcdir)/drivers @MINIDRIVER_TRUE@MINIDRIVER_IMP_DIR = $(srcdir)/minidriver libjtag_la_SOURCES = \ adapter.c \ core.c \ interface.c \ interfaces.c \ tcl.c \ $(DRIVERFILES) noinst_HEADERS = \ commands.h \ driver.h \ interface.h \ interfaces.h \ minidriver.h \ jtag.h \ minidriver/minidriver_imp.h \ minidummy/jtag_minidriver.h \ swd.h \ tcl.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/jtag/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/jtag/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } zy1000/$(am__dirstamp): @$(MKDIR_P) zy1000 @: > zy1000/$(am__dirstamp) zy1000/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) zy1000/$(DEPDIR) @: > zy1000/$(DEPDIR)/$(am__dirstamp) zy1000/zy1000.lo: zy1000/$(am__dirstamp) \ zy1000/$(DEPDIR)/$(am__dirstamp) minidummy/$(am__dirstamp): @$(MKDIR_P) minidummy @: > minidummy/$(am__dirstamp) minidummy/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) minidummy/$(DEPDIR) @: > minidummy/$(DEPDIR)/$(am__dirstamp) minidummy/minidummy.lo: minidummy/$(am__dirstamp) \ minidummy/$(DEPDIR)/$(am__dirstamp) libjtag.la: $(libjtag_la_OBJECTS) $(libjtag_la_DEPENDENCIES) $(EXTRA_libjtag_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libjtag_la_OBJECTS) $(libjtag_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f minidummy/*.$(OBJEXT) -rm -f minidummy/*.lo -rm -f zy1000/*.$(OBJEXT) -rm -f zy1000/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adapter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commands.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interfaces.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@minidummy/$(DEPDIR)/minidummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@zy1000/$(DEPDIR)/zy1000.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf minidummy/.libs minidummy/_libs -rm -rf zy1000/.libs zy1000/_libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f minidummy/$(DEPDIR)/$(am__dirstamp) -rm -f minidummy/$(am__dirstamp) -rm -f zy1000/$(DEPDIR)/$(am__dirstamp) -rm -f zy1000/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) minidummy/$(DEPDIR) zy1000/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) minidummy/$(DEPDIR) zy1000/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am @MINIDRIVER_TRUE@jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h @MINIDRIVER_TRUE@ cp $< $@ # endif // MINIDRIVER minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h cp $< $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/jtag/jtag.h0000644000175000017500000005516312315575361012724 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_H #define JTAG_H #include #include #ifdef _DEBUG_JTAG_IO_ #define DEBUG_JTAG_IO(expr ...) \ do { if (1) LOG_DEBUG(expr); } while (0) #else #define DEBUG_JTAG_IO(expr ...) \ do { if (0) LOG_DEBUG(expr); } while (0) #endif #ifndef DEBUG_JTAG_IOZ #define DEBUG_JTAG_IOZ 64 #endif /*------------------------------------------------------*/ /** * Defines JTAG Test Access Port states. * * These definitions were gleaned from the ARM7TDMI-S Technical * Reference Manual and validated against several other ARM core * technical manuals. * * FIXME some interfaces require specific numbers be used, as they * are handed-off directly to their hardware implementations. * Fix those drivers to map as appropriate ... then pick some * sane set of numbers here (where 0/uninitialized == INVALID). */ typedef enum tap_state { TAP_INVALID = -1, #if BUILD_ZY1000 /* These are the old numbers. Leave as-is for now... */ TAP_RESET = 0, TAP_IDLE = 8, TAP_DRSELECT = 1, TAP_DRCAPTURE = 2, TAP_DRSHIFT = 3, TAP_DREXIT1 = 4, TAP_DRPAUSE = 5, TAP_DREXIT2 = 6, TAP_DRUPDATE = 7, TAP_IRSELECT = 9, TAP_IRCAPTURE = 10, TAP_IRSHIFT = 11, TAP_IREXIT1 = 12, TAP_IRPAUSE = 13, TAP_IREXIT2 = 14, TAP_IRUPDATE = 15, #else /* Proper ARM recommended numbers */ TAP_DREXIT2 = 0x0, TAP_DREXIT1 = 0x1, TAP_DRSHIFT = 0x2, TAP_DRPAUSE = 0x3, TAP_IRSELECT = 0x4, TAP_DRUPDATE = 0x5, TAP_DRCAPTURE = 0x6, TAP_DRSELECT = 0x7, TAP_IREXIT2 = 0x8, TAP_IREXIT1 = 0x9, TAP_IRSHIFT = 0xa, TAP_IRPAUSE = 0xb, TAP_IDLE = 0xc, TAP_IRUPDATE = 0xd, TAP_IRCAPTURE = 0xe, TAP_RESET = 0x0f, #endif } tap_state_t; /** * Function tap_state_name * Returns a string suitable for display representing the JTAG tap_state */ const char *tap_state_name(tap_state_t state); /** Provides user-friendly name lookup of TAP states. */ tap_state_t tap_state_by_name(const char *name); /** The current TAP state of the pending JTAG command queue. */ extern tap_state_t cmd_queue_cur_state; /** * This structure defines a single scan field in the scan. It provides * fields for the field's width and pointers to scan input and output * values. * * In addition, this structure includes a value and mask that is used by * jtag_add_dr_scan_check() to validate the value that was scanned out. */ struct scan_field { /** The number of bits this field specifies (up to 32) */ int num_bits; /** A pointer to value to be scanned into the device */ const uint8_t *out_value; /** A pointer to a 32-bit memory location for data scanned out */ uint8_t *in_value; /** The value used to check the data scanned out. */ uint8_t *check_value; /** The mask to go with check_value */ uint8_t *check_mask; }; struct jtag_tap { char *chip; char *tapname; char *dotted_name; int abs_chain_position; /** Is this TAP disabled after JTAG reset? */ bool disabled_after_reset; /** Is this TAP currently enabled? */ bool enabled; int ir_length; /**< size of instruction register */ uint32_t ir_capture_value; uint8_t *expected; /**< Capture-IR expected value */ uint32_t ir_capture_mask; uint8_t *expected_mask; /**< Capture-IR expected mask */ uint32_t idcode; /**< device identification code */ /** not all devices have idcode, * we'll discover this during chain examination */ bool hasidcode; /** Array of expected identification codes */ uint32_t *expected_ids; /** Number of expected identification codes */ uint8_t expected_ids_cnt; /** Flag saying whether to ignore version field in expected_ids[] */ bool ignore_version; /** current instruction */ uint8_t *cur_instr; /** Bypass register selected */ int bypass; struct jtag_tap_event_action *event_action; struct jtag_tap *next_tap; /* dap instance if some null if no instance , initialized to 0 by calloc*/ struct adiv5_dap *dap; /* private pointer to support none-jtag specific functions */ void *priv; }; void jtag_tap_init(struct jtag_tap *tap); void jtag_tap_free(struct jtag_tap *tap); struct jtag_tap *jtag_all_taps(void); const char *jtag_tap_name(const struct jtag_tap *tap); struct jtag_tap *jtag_tap_by_string(const char* dotted_name); struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp* interp, Jim_Obj *obj); struct jtag_tap *jtag_tap_by_position(unsigned abs_position); struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p); unsigned jtag_tap_count_enabled(void); unsigned jtag_tap_count(void); /* * - TRST_ASSERTED triggers two sets of callbacks, after operations to * reset the scan chain -- via TMS+TCK signaling, or deasserting the * nTRST signal -- are queued: * * + Callbacks in C code fire first, patching internal state * + Then post-reset event scripts fire ... activating JTAG circuits * via TCK cycles, exiting SWD mode via TMS sequences, etc * * During those callbacks, scan chain contents have not been validated. * JTAG operations that address a specific TAP (primarily DR/IR scans) * must *not* be queued. * * - TAP_EVENT_SETUP is reported after TRST_ASSERTED, and after the scan * chain has been validated. JTAG operations including scans that * target specific TAPs may be performed. * * - TAP_EVENT_ENABLE and TAP_EVENT_DISABLE implement TAP activation and * deactivation outside the core using scripted code that understands * the specific JTAG router type. They might be triggered indirectly * from EVENT_SETUP operations. */ enum jtag_event { JTAG_TRST_ASSERTED, JTAG_TAP_EVENT_SETUP, JTAG_TAP_EVENT_ENABLE, JTAG_TAP_EVENT_DISABLE, }; struct jtag_tap_event_action { /** The event for which this action will be triggered. */ enum jtag_event event; /** The interpreter to use for evaluating the @c body. */ Jim_Interp *interp; /** Contains a script to 'eval' when the @c event is triggered. */ Jim_Obj *body; /* next action in linked list */ struct jtag_tap_event_action *next; }; /** * Defines the function signature requide for JTAG event callback * functions, which are added with jtag_register_event_callback() * and removed jtag_unregister_event_callback(). * @param event The event to handle. * @param prive A pointer to data that was passed to * jtag_register_event_callback(). * @returns Must return ERROR_OK on success, or an error code on failure. * * @todo Change to return void or define a use for its return code. */ typedef int (*jtag_event_handler_t)(enum jtag_event event, void *priv); int jtag_register_event_callback(jtag_event_handler_t f, void *x); int jtag_unregister_event_callback(jtag_event_handler_t f, void *x); int jtag_call_event_callbacks(enum jtag_event event); /** @returns The current JTAG speed setting. */ int jtag_get_speed(int *speed); /** * Given a @a speed setting, use the interface @c speed_div callback to * adjust the setting. * @param speed The speed setting to convert back to readable KHz. * @returns ERROR_OK if the interface has not been initialized or on success; * otherwise, the error code produced by the @c speed_div callback. */ int jtag_get_speed_readable(int *speed); /** Attempt to configure the interface for the specified KHz. */ int jtag_config_khz(unsigned khz); /** * Attempt to enable RTCK/RCLK. If that fails, fallback to the * specified frequency. */ int jtag_config_rclk(unsigned fallback_speed_khz); /** Retreives the clock speed of the JTAG interface in KHz. */ unsigned jtag_get_speed_khz(void); enum reset_types { RESET_NONE = 0x0, RESET_HAS_TRST = 0x1, RESET_HAS_SRST = 0x2, RESET_TRST_AND_SRST = 0x3, RESET_SRST_PULLS_TRST = 0x4, RESET_TRST_PULLS_SRST = 0x8, RESET_TRST_OPEN_DRAIN = 0x10, RESET_SRST_PUSH_PULL = 0x20, RESET_SRST_NO_GATING = 0x40, RESET_CNCT_UNDER_SRST = 0x80 }; enum reset_types jtag_get_reset_config(void); void jtag_set_reset_config(enum reset_types type); void jtag_set_nsrst_delay(unsigned delay); unsigned jtag_get_nsrst_delay(void); void jtag_set_ntrst_delay(unsigned delay); unsigned jtag_get_ntrst_delay(void); void jtag_set_nsrst_assert_width(unsigned delay); unsigned jtag_get_nsrst_assert_width(void); void jtag_set_ntrst_assert_width(unsigned delay); unsigned jtag_get_ntrst_assert_width(void); /** @returns The current state of TRST. */ int jtag_get_trst(void); /** @returns The current state of SRST. */ int jtag_get_srst(void); /** Enable or disable data scan verification checking. */ void jtag_set_verify(bool enable); /** @returns True if data scan verification will be performed. */ bool jtag_will_verify(void); /** Enable or disable verification of IR scan checking. */ void jtag_set_verify_capture_ir(bool enable); /** @returns True if IR scan verification will be performed. */ bool jtag_will_verify_capture_ir(void); /** Initialize debug adapter upon startup. */ int adapter_init(struct command_context *cmd_ctx); /** Shutdown the debug adapter upon program exit. */ int adapter_quit(void); /** Set ms to sleep after jtag_execute_queue() flushes queue. Debug purposes. */ void jtag_set_flush_queue_sleep(int ms); /** * Initialize JTAG chain using only a RESET reset. If init fails, * try reset + init. */ int jtag_init(struct command_context *cmd_ctx); /** reset, then initialize JTAG chain */ int jtag_init_reset(struct command_context *cmd_ctx); int jtag_register_commands(struct command_context *cmd_ctx); int jtag_init_inner(struct command_context *cmd_ctx); /** * @file * The JTAG interface can be implemented with a software or hardware fifo. * * TAP_DRSHIFT and TAP_IRSHIFT are illegal end states; however, * TAP_DRSHIFT/IRSHIFT can be emulated as end states, by using longer * scans. * * Code that is relatively insensitive to the path taken through state * machine (as long as it is JTAG compliant) can use @a endstate for * jtag_add_xxx_scan(). Otherwise, the pause state must be specified as * end state and a subsequent jtag_add_pathmove() must be issued. */ /** * Generate an IR SCAN with a list of scan fields with one entry for * each enabled TAP. * * If the input field list contains an instruction value for a TAP then * that is used otherwise the TAP is set to bypass. * * TAPs for which no fields are passed are marked as bypassed for * subsequent DR SCANs. * */ void jtag_add_ir_scan(struct jtag_tap *tap, struct scan_field *fields, tap_state_t endstate); /** * The same as jtag_add_ir_scan except no verification is performed out * the output values. */ void jtag_add_ir_scan_noverify(struct jtag_tap *tap, const struct scan_field *fields, tap_state_t state); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); /** * Generate a DR SCAN using the fields passed to the function. * For connected TAPs, the function checks in_fields and uses fields * specified there. For bypassed TAPs, the function generates a dummy * 1-bit field. The bypass status of TAPs is set by jtag_add_ir_scan(). */ void jtag_add_dr_scan(struct jtag_tap *tap, int num_fields, const struct scan_field *fields, tap_state_t endstate); /** A version of jtag_add_dr_scan() that uses the check_value/mask fields */ void jtag_add_dr_scan_check(struct jtag_tap *tap, int num_fields, struct scan_field *fields, tap_state_t endstate); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); /** * Defines the type of data passed to the jtag_callback_t interface. * The underlying type must allow storing an @c int or pointer type. */ typedef intptr_t jtag_callback_data_t; /** * Defines a simple JTAG callback that can allow conversions on data * scanned in from an interface. * * This callback should only be used for conversion that cannot fail. * For conversion types or checks that can fail, use the more complete * variant: jtag_callback_t. */ typedef void (*jtag_callback1_t)(jtag_callback_data_t data0); /** A simpler version of jtag_add_callback4(). */ void jtag_add_callback(jtag_callback1_t, jtag_callback_data_t data0); /** * Defines the interface of the JTAG callback mechanism. Such * callbacks can be executed once the queue has been flushed. * * The JTAG queue can be executed synchronously or asynchronously. * Typically for USB, the queue is executed asynchronously. For * low-latency interfaces, the queue may be executed synchronously. * * The callback mechanism is very general and does not make many * assumptions about what the callback does or what its arguments are. * These callbacks are typically executed *after* the *entire* JTAG * queue has been executed for e.g. USB interfaces, and they are * guaranteeed to be invoked in the order that they were queued. * * If the execution of the queue fails before the callbacks, then -- * depending on driver implementation -- the callbacks may or may not be * invoked. * * @todo Make that behavior consistent. * * @param data0 Typically used to point to the data to operate on. * Frequently this will be the data clocked in during a shift operation. * @param data1 An integer big enough to use as an @c int or a pointer. * @param data2 An integer big enough to use as an @c int or a pointer. * @param data3 An integer big enough to use as an @c int or a pointer. * @returns an error code */ typedef int (*jtag_callback_t)(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); /** * Run a TAP_RESET reset where the end state is TAP_RESET, * regardless of the start state. */ void jtag_add_tlr(void); /** * Application code *must* assume that interfaces will * implement transitions between states with different * paths and path lengths through the state diagram. The * path will vary across interface and also across versions * of the same interface over time. Even if the OpenOCD code * is unchanged, the actual path taken may vary over time * and versions of interface firmware or PCB revisions. * * Use jtag_add_pathmove() when specific transition sequences * are required. * * Do not use jtag_add_pathmove() unless you need to, but do use it * if you have to. * * DANGER! If the target is dependent upon a particular sequence * of transitions for things to work correctly(e.g. as a workaround * for an errata that contradicts the JTAG standard), then pathmove * must be used, even if some jtag interfaces happen to use the * desired path. Worse, the jtag interface used for testing a * particular implementation, could happen to use the "desired" * path when transitioning to/from end * state. * * A list of unambigious single clock state transitions, not * all drivers can support this, but it is required for e.g. * XScale and Xilinx support * * Note! TAP_RESET must not be used in the path! * * Note that the first on the list must be reachable * via a single transition from the current state. * * All drivers are required to implement jtag_add_pathmove(). * However, if the pathmove sequence can not be precisely * executed, an interface_jtag_add_pathmove() or jtag_execute_queue() * must return an error. It is legal, but not recommended, that * a driver returns an error in all cases for a pathmove if it * can only implement a few transitions and therefore * a partial implementation of pathmove would have little practical * application. * * If an error occurs, jtag_error will contain one of these error codes: * - ERROR_JTAG_NOT_STABLE_STATE -- The final state was not stable. * - ERROR_JTAG_STATE_INVALID -- The path passed through TAP_RESET. * - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid * state transitions. */ void jtag_add_pathmove(int num_states, const tap_state_t *path); /** * jtag_add_statemove() moves from the current state to @a goal_state. * * @param goal_state The final TAP state. * @return ERROR_OK on success, or an error code on failure. * * Moves from the current state to the goal \a state. * Both states must be stable. */ int jtag_add_statemove(tap_state_t goal_state); /** * Goes to TAP_IDLE (if we're not already there), cycle * precisely num_cycles in the TAP_IDLE state, after which move * to @a endstate (unless it is also TAP_IDLE). * * @param num_cycles Number of cycles in TAP_IDLE state. This argument * may be 0, in which case this routine will navigate to @a endstate * via TAP_IDLE. * @param endstate The final state. */ void jtag_add_runtest(int num_cycles, tap_state_t endstate); /** * A reset of the TAP state machine can be requested. * * Whether tms or trst reset is used depends on the capabilities of * the target and jtag interface(reset_config command configures this). * * srst can driver a reset of the TAP state machine and vice * versa * * Application code may need to examine value of jtag_reset_config * to determine the proper codepath * * DANGER! Even though srst drives trst, trst might not be connected to * the interface, and it might actually be *harmful* to assert trst in this case. * * This is why combinations such as "reset_config srst_only srst_pulls_trst" * are supported. * * only req_tlr_or_trst and srst can have a transition for a * call as the effects of transitioning both at the "same time" * are undefined, but when srst_pulls_trst or vice versa, * then trst & srst *must* be asserted together. */ void jtag_add_reset(int req_tlr_or_trst, int srst); void jtag_add_sleep(uint32_t us); int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t); /** * Function jtag_add_clocks * first checks that the state in which the clocks are to be issued is * stable, then queues up num_cycles clocks for transmission. */ void jtag_add_clocks(int num_cycles); /** * For software FIFO implementations, the queued commands can be executed * during this call or earlier. A sw queue might decide to push out * some of the jtag_add_xxx() operations once the queue is "big enough". * * This fn will return an error code if any of the prior jtag_add_xxx() * calls caused a failure, e.g. check failure. Note that it does not * matter if the operation was executed *before* jtag_execute_queue(), * jtag_execute_queue() will still return an error code. * * All jtag_add_xxx() calls that have in_handler != NULL will have been * executed when this fn returns, but if what has been queued only * clocks data out, without reading anything back, then JTAG could * be running *after* jtag_execute_queue() returns. The API does * not define a way to flush a hw FIFO that runs *after* * jtag_execute_queue() returns. * * jtag_add_xxx() commands can either be executed immediately or * at some time between the jtag_add_xxx() fn call and jtag_execute_queue(). */ int jtag_execute_queue(void); /** same as jtag_execute_queue() but does not clear the error flag */ void jtag_execute_queue_noclear(void); /** @returns the number of times the scan queue has been flushed */ int jtag_get_flush_queue_count(void); /** Report Tcl event to all TAPs */ void jtag_notify_event(enum jtag_event); /* can be implemented by hw + sw */ int jtag_power_dropout(int *dropout); int jtag_srst_asserted(int *srst_asserted); /* JTAG support functions */ /** * Execute jtag queue and check value with an optional mask. * @param field Pointer to scan field. * @param value Pointer to scan value. * @param mask Pointer to scan mask; may be NULL. * @returns Nothing, but calls jtag_set_error() on any error. */ void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask); void jtag_sleep(uint32_t us); /* * The JTAG subsystem defines a number of error codes, * using codes between -100 and -199. */ #define ERROR_JTAG_INIT_FAILED (-100) #define ERROR_JTAG_INVALID_INTERFACE (-101) #define ERROR_JTAG_NOT_IMPLEMENTED (-102) #define ERROR_JTAG_TRST_ASSERTED (-103) #define ERROR_JTAG_QUEUE_FAILED (-104) #define ERROR_JTAG_NOT_STABLE_STATE (-105) #define ERROR_JTAG_DEVICE_ERROR (-107) #define ERROR_JTAG_STATE_INVALID (-108) #define ERROR_JTAG_TRANSITION_INVALID (-109) #define ERROR_JTAG_INIT_SOFT_FAIL (-110) /** * Set the current JTAG core execution error, unless one was set * by a previous call previously. Driver or application code must * use jtag_error_clear to reset jtag_error once this routine has been * called with a non-zero error code. */ void jtag_set_error(int error); /** * Resets jtag_error to ERROR_OK, returning its previous value. * @returns The previous value of @c jtag_error. */ int jtag_error_clear(void); /** * Return true if it's safe for a background polling task to access the * JTAG scan chain. Polling may be explicitly disallowed, and is also * unsafe while nTRST is active or the JTAG clock is gated off. */ bool is_jtag_poll_safe(void); /** * Return flag reporting whether JTAG polling is disallowed. */ bool jtag_poll_get_enabled(void); /** * Assign flag reporting whether JTAG polling is disallowed. */ void jtag_poll_set_enabled(bool value); /* The minidriver may have inline versions of some of the low * level APIs that are used in inner loops. */ #include bool transport_is_jtag(void); int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv); #endif /* JTAG_H */ openocd-0.9.0/src/jtag/commands.c0000644000175000017500000001615612315575360013571 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "commands.h" struct cmd_queue_page { void *address; size_t used; struct cmd_queue_page *next; }; #define CMD_QUEUE_PAGE_SIZE (1024 * 1024) static struct cmd_queue_page *cmd_queue_pages; struct jtag_command *jtag_command_queue; static struct jtag_command **next_command_pointer = &jtag_command_queue; void jtag_queue_command(struct jtag_command *cmd) { /* this command goes on the end, so ensure the queue terminates */ cmd->next = NULL; struct jtag_command **last_cmd = next_command_pointer; assert(NULL != last_cmd); assert(NULL == *last_cmd); *last_cmd = cmd; /* store location where the next command pointer will be stored */ next_command_pointer = &cmd->next; } void *cmd_queue_alloc(size_t size) { struct cmd_queue_page **p_page = &cmd_queue_pages; int offset; uint8_t *t; /* * WARNING: * We align/round the *SIZE* per below * so that all pointers returned by * this function are reasonably well * aligned. * * If we did not, then an "odd-length" request would cause the * *next* allocation to be at an *odd* address, and because * this function has the same type of api as malloc() - we * must also return pointers that have the same type of * alignment. * * What I do not/have is a reasonable portable means * to align by... * * The solution here, is based on these suggestions. * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html * */ union worse_case_align { int i; long l; float f; void *v; }; #define ALIGN_SIZE (sizeof(union worse_case_align)) /* The alignment process. */ size = (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1)); /* Done... */ if (*p_page) { while ((*p_page)->next) p_page = &((*p_page)->next); if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size) p_page = &((*p_page)->next); } if (!*p_page) { *p_page = malloc(sizeof(struct cmd_queue_page)); (*p_page)->used = 0; size_t alloc_size = (size < CMD_QUEUE_PAGE_SIZE) ? CMD_QUEUE_PAGE_SIZE : size; (*p_page)->address = malloc(alloc_size); (*p_page)->next = NULL; } offset = (*p_page)->used; (*p_page)->used += size; t = (*p_page)->address; return t + offset; } static void cmd_queue_free(void) { struct cmd_queue_page *page = cmd_queue_pages; while (page) { struct cmd_queue_page *last = page; free(page->address); page = page->next; free(last); } cmd_queue_pages = NULL; } void jtag_command_queue_reset(void) { cmd_queue_free(); jtag_command_queue = NULL; next_command_pointer = &jtag_command_queue; } enum scan_type jtag_scan_type(const struct scan_command *cmd) { int i; int type = 0; for (i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].in_value) type |= SCAN_IN; if (cmd->fields[i].out_value) type |= SCAN_OUT; } return type; } int jtag_scan_size(const struct scan_command *cmd) { int bit_count = 0; int i; /* count bits in scan command */ for (i = 0; i < cmd->num_fields; i++) bit_count += cmd->fields[i].num_bits; return bit_count; } int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) { int bit_count = 0; int i; bit_count = jtag_scan_size(cmd); *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8)); bit_count = 0; DEBUG_JTAG_IO("%s num_fields: %i", cmd->ir_scan ? "IRSCAN" : "DRSCAN", cmd->num_fields); for (i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].out_value) { #ifdef _DEBUG_JTAG_IO_ char *char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits, 16); LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); #endif buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); } else { DEBUG_JTAG_IO("fields[%i].out_value[%i]: NULL", i, cmd->fields[i].num_bits); } bit_count += cmd->fields[i].num_bits; } /*DEBUG_JTAG_IO("bit_count totalling: %i", bit_count); */ return bit_count; } int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) { int i; int bit_count = 0; int retval; /* we return ERROR_OK, unless a check fails, or a handler reports a problem */ retval = ERROR_OK; for (i = 0; i < cmd->num_fields; i++) { /* if neither in_value nor in_handler * are specified we don't have to examine this field */ if (cmd->fields[i].in_value) { int num_bits = cmd->fields[i].num_bits; uint8_t *captured = buf_set_buf(buffer, bit_count, malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits); #ifdef _DEBUG_JTAG_IO_ char *char_buf = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf); free(char_buf); #endif if (cmd->fields[i].in_value) buf_cpy(captured, cmd->fields[i].in_value, num_bits); free(captured); } bit_count += cmd->fields[i].num_bits; } return retval; } openocd-0.9.0/src/jtag/commands.h0000644000175000017500000001351612315575360013573 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef JTAG_COMMANDS_H #define JTAG_COMMANDS_H /** * The inferred type of a scan_command_s structure, indicating whether * the command has the host scan in from the device, the host scan out * to the device, or both. */ enum scan_type { /** From device to host, */ SCAN_IN = 1, /** From host to device, */ SCAN_OUT = 2, /** Full-duplex scan. */ SCAN_IO = 3 }; /** * The scan_command provide a means of encapsulating a set of scan_field_s * structures that should be scanned in/out to the device. */ struct scan_command { /** instruction/not data scan */ bool ir_scan; /** number of fields in *fields array */ int num_fields; /** pointer to an array of data scan fields */ struct scan_field *fields; /** state in which JTAG commands should finish */ tap_state_t end_state; }; struct statemove_command { /** state in which JTAG commands should finish */ tap_state_t end_state; }; struct pathmove_command { /** number of states in *path */ int num_states; /** states that have to be passed */ tap_state_t *path; }; struct runtest_command { /** number of cycles to spend in Run-Test/Idle state */ int num_cycles; /** state in which JTAG commands should finish */ tap_state_t end_state; }; struct stableclocks_command { /** number of clock cycles that should be sent */ int num_cycles; }; struct reset_command { /** Set TRST output: 0 = deassert, 1 = assert, -1 = no change */ int trst; /** Set SRST output: 0 = deassert, 1 = assert, -1 = no change */ int srst; }; struct end_state_command { /** state in which JTAG commands should finish */ tap_state_t end_state; }; struct sleep_command { /** number of microseconds to sleep */ uint32_t us; }; /** * Encapsulates a series of bits to be clocked out, affecting state * and mode of the interface. * * In JTAG mode these are clocked out on TMS, using TCK. They may be * used for link resets, transitioning between JTAG and SWD modes, or * to implement JTAG state machine transitions (implementing pathmove * or statemove operations). * * In SWD mode these are clocked out on SWDIO, using SWCLK, and are * used for link resets and transitioning between SWD and JTAG modes. */ struct tms_command { /** How many bits should be clocked out. */ unsigned num_bits; /** The bits to clock out; the LSB is bit 0 of bits[0]. */ const uint8_t *bits; }; /** * Defines a container type that hold a pointer to a JTAG command * structure of any defined type. */ union jtag_command_container { struct scan_command *scan; struct statemove_command *statemove; struct pathmove_command *pathmove; struct runtest_command *runtest; struct stableclocks_command *stableclocks; struct reset_command *reset; struct end_state_command *end_state; struct sleep_command *sleep; struct tms_command *tms; }; /** * The type of the @c jtag_command_container contained by a * @c jtag_command_s structure. */ enum jtag_command_type { JTAG_SCAN = 1, /* JTAG_TLR_RESET's non-minidriver implementation is a * vestige from a statemove cmd. The statemove command * is obsolete and replaced by pathmove. * * pathmove does not support reset as one of it's states, * hence the need for an explicit statemove command. */ JTAG_TLR_RESET = 2, JTAG_RUNTEST = 3, JTAG_RESET = 4, JTAG_PATHMOVE = 6, JTAG_SLEEP = 7, JTAG_STABLECLOCKS = 8, JTAG_TMS = 9, }; struct jtag_command { union jtag_command_container cmd; enum jtag_command_type type; struct jtag_command *next; }; /** The current queue of jtag_command_s structures. */ extern struct jtag_command *jtag_command_queue; void *cmd_queue_alloc(size_t size); void jtag_queue_command(struct jtag_command *cmd); void jtag_command_queue_reset(void); enum scan_type jtag_scan_type(const struct scan_command *cmd); int jtag_scan_size(const struct scan_command *cmd); int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd); int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer); #endif /* JTAG_COMMANDS_H */ openocd-0.9.0/src/jtag/zy1000/0000755000175000017500000000000012526202224012624 500000000000000openocd-0.9.0/src/jtag/zy1000/zy1000.c0000644000175000017500000007421412315575361013676 00000000000000/*************************************************************************** * Copyright (C) 2007-2010 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* This file supports the zy1000 debugger: * * http://www.ultsol.com/index.php/component/content/article/8/33-zylin-zy1000-jtag-probe * * The zy1000 is a standalone debugger that has a web interface and * requires no drivers on the developer host as all communication * is via TCP/IP. The zy1000 gets it performance(~400-700kBytes/s * DCC downloads @ 16MHz target) as it has an FPGA to hardware * accelerate the JTAG commands, while offering *very* low latency * between OpenOCD and the FPGA registers. * * The disadvantage of the zy1000 is that it has a feeble CPU compared to * a PC(ca. 50-500 DMIPS depending on how one counts it), whereas a PC * is on the order of 10000 DMIPS(i.e. at a factor of 20-200). * * The zy1000 revc hardware is using an Altera Nios CPU, whereas the * revb is using ARM7 + Xilinx. * * See Zylin web pages or contact Zylin for more information. * * The reason this code is in OpenOCD rather than OpenOCD linked with the * ZY1000 code is that OpenOCD is the long road towards getting * libopenocd into place. libopenocd will support both low performance, * low latency systems(embedded) and high performance high latency * systems(PCs). */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /* Assume we're connecting to a revc w/60MHz clock. */ #define ZYLIN_KHZ 60000 /* The software needs to check if it's in RCLK mode or not */ static bool zy1000_rclk; static int zy1000_khz(int khz, int *jtag_speed) { if (khz == 0) *jtag_speed = 0; else { int speed; /* Round speed up to nearest divisor. * * E.g. 16000kHz * (64000 + 15999) / 16000 = 4 * (4 + 1) / 2 = 2 * 2 * 2 = 4 * * 64000 / 4 = 16000 * * E.g. 15999 * (64000 + 15998) / 15999 = 5 * (5 + 1) / 2 = 3 * 3 * 2 = 6 * * 64000 / 6 = 10666 * */ speed = (ZYLIN_KHZ + (khz - 1)) / khz; speed = (speed + 1) / 2; speed *= 2; if (speed > 8190) { /* maximum dividend */ speed = 8190; } *jtag_speed = speed; } return ERROR_OK; } static int zy1000_speed_div(int speed, int *khz) { if (speed == 0) *khz = 0; else *khz = ZYLIN_KHZ / speed; return ERROR_OK; } static bool readPowerDropout(void) { uint32_t state; /* sample and clear power dropout */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x80); ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state); bool powerDropout; powerDropout = (state & 0x80) != 0; return powerDropout; } static bool readSRST(void) { uint32_t state; /* sample and clear SRST sensing */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000040); ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state); bool srstAsserted; srstAsserted = (state & 0x40) != 0; return srstAsserted; } static int zy1000_srst_asserted(int *srst_asserted) { *srst_asserted = readSRST(); return ERROR_OK; } static int zy1000_power_dropout(int *dropout) { *dropout = readPowerDropout(); return ERROR_OK; } /* Wait for SRST to assert or deassert */ static void waitSRST(bool asserted) { bool first = true; long long start = 0; long total = 0; const char *mode = asserted ? "assert" : "deassert"; for (;; ) { bool srstAsserted = readSRST(); if ((asserted && srstAsserted) || (!asserted && !srstAsserted)) { if (total > 1) LOG_USER("SRST took %dms to %s", (int)total, mode); break; } if (first) { first = false; start = timeval_ms(); } total = timeval_ms() - start; keep_alive(); if (total > 5000) { LOG_ERROR("SRST took too long to %s: %dms", mode, (int)total); break; } } } void zy1000_reset(int trst, int srst) { LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst); /* flush the JTAG FIFO. Not flushing the queue before messing with * reset has such interesting bugs as causing hard to reproduce * RCLK bugs as RCLK will stop responding when TRST is asserted */ waitIdle(); if (!srst) ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001); else { /* Danger!!! if clk != 0 when in * idle in TAP_IDLE, reset halt on str912 will fail. */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000001); waitSRST(true); } if (!trst) ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000002); else { /* assert reset */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000002); } if (trst || (srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) { /* we're now in the RESET state until trst is deasserted */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET); } else { /* We'll get RCLK failure when we assert TRST, so clear any false positives here */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400); } /* wait for srst to float back up */ if ((!srst && ((jtag_get_reset_config() & RESET_TRST_PULLS_SRST) == 0)) || (!srst && !trst && (jtag_get_reset_config() & RESET_TRST_PULLS_SRST))) waitSRST(false); } int zy1000_speed(int speed) { /* flush JTAG master FIFO before setting speed */ waitIdle(); zy1000_rclk = false; if (speed == 0) { /*0 means RCLK*/ ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x100); zy1000_rclk = true; LOG_DEBUG("jtag_speed using RCLK"); } else { if (speed > 8190 || speed < 2) { LOG_USER( "valid ZY1000 jtag_speed=[8190,2]. With divisor is %dkHz / even values between 8190-2, i.e. min %dHz, max %dMHz", ZYLIN_KHZ, (ZYLIN_KHZ * 1000) / 8190, ZYLIN_KHZ / (2 * 1000)); return ERROR_COMMAND_SYNTAX_ERROR; } int khz; speed &= ~1; zy1000_speed_div(speed, &khz); LOG_USER("jtag_speed %d => JTAG clk=%d kHz", speed, khz); ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x100); ZY1000_POKE(ZY1000_JTAG_BASE + 0x1c, speed); } return ERROR_OK; } static bool savePower; static void setPower(bool power) { savePower = power; if (power) ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x8); else ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x8); } COMMAND_HANDLER(handle_power_command) { switch (CMD_ARGC) { case 1: { bool enable; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); setPower(enable); /* fall through */ } case 0: LOG_INFO("Target power %s", savePower ? "on" : "off"); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } #if !BUILD_ZY1000_MASTER static char *tcp_server = "notspecified"; static int jim_zy1000_server(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc != 2) return JIM_ERR; tcp_server = strdup(Jim_GetString(argv[1], NULL)); return JIM_OK; } #endif static int zylinjtag_Jim_Command_powerstatus(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "powerstatus"); return JIM_ERR; } bool dropout = readPowerDropout(); Jim_SetResult(interp, Jim_NewIntObj(interp, dropout)); return JIM_OK; } int zy1000_quit(void) { return ERROR_OK; } int interface_jtag_execute_queue(void) { uint32_t empty; waitIdle(); /* We must make sure to write data read back to memory location before we return * from this fn */ zy1000_flush_readqueue(); /* and handle any callbacks... */ zy1000_flush_callbackqueue(); if (zy1000_rclk) { /* Only check for errors when using RCLK to speed up * jtag over TCP/IP */ ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty); /* clear JTAG error register */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400); if ((empty&0x400) != 0) { LOG_WARNING("RCLK timeout"); /* the error is informative only as we don't want to break the firmware if there * is a false positive. */ /* return ERROR_FAIL; */ } } return ERROR_OK; } static void writeShiftValue(uint8_t *data, int bits); /* here we shuffle N bits out/in */ static inline void scanBits(const uint8_t *out_value, uint8_t *in_value, int num_bits, bool pause_now, tap_state_t shiftState, tap_state_t end_state) { tap_state_t pause_state = shiftState; for (int j = 0; j < num_bits; j += 32) { int k = num_bits - j; if (k > 32) { k = 32; /* we have more to shift out */ } else if (pause_now) { /* this was the last to shift out this time */ pause_state = end_state; } /* we have (num_bits + 7)/8 bytes of bits to toggle out. */ /* bits are pushed out LSB to MSB */ uint32_t value; value = 0; if (out_value != NULL) { for (int l = 0; l < k; l += 8) value |= out_value[(j + l)/8]<= 32 is not defined by the C standard * and will in fact shift by &0x1f bits on nios */ } shiftValueInner(shiftState, pause_state, k, value); if (in_value != NULL) writeShiftValue(in_value + (j/8), k); } } static inline void scanFields(int num_fields, const struct scan_field *fields, tap_state_t shiftState, tap_state_t end_state) { for (int i = 0; i < num_fields; i++) { scanBits(fields[i].out_value, fields[i].in_value, fields[i].num_bits, (i == num_fields-1), shiftState, end_state); } } int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields, tap_state_t state) { int scan_size = 0; struct jtag_tap *tap, *nextTap; tap_state_t pause_state = TAP_IRSHIFT; for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) { nextTap = jtag_tap_next_enabled(tap); if (nextTap == NULL) pause_state = state; scan_size = tap->ir_length; /* search the list */ if (tap == active) { scanFields(1, fields, TAP_IRSHIFT, pause_state); /* update device information */ buf_cpy(fields[0].out_value, tap->cur_instr, scan_size); tap->bypass = 0; } else { /* if a device isn't listed, set it to BYPASS */ assert(scan_size <= 32); shiftValueInner(TAP_IRSHIFT, pause_state, scan_size, 0xffffffff); /* Optimization code will check what the cur_instr is set to, so * we must set it to bypass value. */ buf_set_ones(tap->cur_instr, tap->ir_length); tap->bypass = 1; } } return ERROR_OK; } int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { scanBits(out_bits, in_bits, num_bits, true, TAP_IRSHIFT, state); return ERROR_OK; } int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields, const struct scan_field *fields, tap_state_t state) { struct jtag_tap *tap, *nextTap; tap_state_t pause_state = TAP_DRSHIFT; for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) { nextTap = jtag_tap_next_enabled(tap); if (nextTap == NULL) pause_state = state; /* Find a range of fields to write to this tap */ if (tap == active) { assert(!tap->bypass); scanFields(num_fields, fields, TAP_DRSHIFT, pause_state); } else { /* Shift out a 0 for disabled tap's */ assert(tap->bypass); shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0); } } return ERROR_OK; } int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { scanBits(out_bits, in_bits, num_bits, true, TAP_DRSHIFT, state); return ERROR_OK; } int interface_jtag_add_tlr() { setCurrentState(TAP_RESET); return ERROR_OK; } int interface_jtag_add_reset(int req_trst, int req_srst) { zy1000_reset(req_trst, req_srst); return ERROR_OK; } static int zy1000_jtag_add_clocks(int num_cycles, tap_state_t state, tap_state_t clockstate) { /* num_cycles can be 0 */ setCurrentState(clockstate); /* execute num_cycles, 32 at the time. */ int i; for (i = 0; i < num_cycles; i += 32) { int num; num = 32; if (num_cycles-i < num) num = num_cycles-i; shiftValueInner(clockstate, clockstate, num, 0); } #if !TEST_MANUAL() /* finish in end_state */ setCurrentState(state); #else tap_state_t t = TAP_IDLE; /* test manual drive code on any target */ int tms; uint8_t tms_scan = tap_get_tms_path(t, state); int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); for (i = 0; i < tms_count; i++) { tms = (tms_scan >> i) & 1; waitIdle(); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms); } waitIdle(); ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state); #endif return ERROR_OK; } int interface_jtag_add_runtest(int num_cycles, tap_state_t state) { return zy1000_jtag_add_clocks(num_cycles, state, TAP_IDLE); } int interface_jtag_add_clocks(int num_cycles) { return zy1000_jtag_add_clocks(num_cycles, cmd_queue_cur_state, cmd_queue_cur_state); } int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) { /*wait for the fifo to be empty*/ waitIdle(); for (unsigned i = 0; i < num_bits; i++) { int tms; if (((seq[i/8] >> (i % 8)) & 1) == 0) tms = 0; else tms = 1; waitIdle(); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms); } waitIdle(); if (state != TAP_INVALID) ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state); else { /* this would be normal if * we are switching to SWD mode */ } return ERROR_OK; } int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) { int state_count; int tms = 0; state_count = 0; tap_state_t cur_state = cmd_queue_cur_state; uint8_t seq[16]; memset(seq, 0, sizeof(seq)); assert(num_states < (int)((sizeof(seq) * 8))); while (num_states) { if (tap_state_transition(cur_state, false) == path[state_count]) tms = 0; else if (tap_state_transition(cur_state, true) == path[state_count]) tms = 1; else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[state_count])); exit(-1); } seq[state_count/8] = seq[state_count/8] | (tms << (state_count % 8)); cur_state = path[state_count]; state_count++; num_states--; } return interface_add_tms_seq(state_count, seq, cur_state); } static void jtag_pre_post_bits(struct jtag_tap *tap, int *pre, int *post) { /* bypass bits before and after */ int pre_bits = 0; int post_bits = 0; bool found = false; struct jtag_tap *cur_tap, *nextTap; for (cur_tap = jtag_tap_next_enabled(NULL); cur_tap != NULL; cur_tap = nextTap) { nextTap = jtag_tap_next_enabled(cur_tap); if (cur_tap == tap) found = true; else { if (found) post_bits++; else pre_bits++; } } *pre = pre_bits; *post = post_bits; } void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count) { #if 0 int i; for (i = 0; i < count; i++) { embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little)); buffer += 4; } #else int pre_bits; int post_bits; jtag_pre_post_bits(tap, &pre_bits, &post_bits); if ((pre_bits > 32) || (post_bits + 6 > 32)) { int i; for (i = 0; i < count; i++) { embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little)); buffer += 4; } } else { int i; for (i = 0; i < count; i++) { /* Fewer pokes means we get to use the FIFO more efficiently */ shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0); shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, fast_target_buffer_get_u32(buffer, little)); /* Danger! here we need to exit into the TAP_IDLE state to make * DCC pick up this value. */ shiftValueInner(TAP_DRSHIFT, TAP_IDLE, 6 + post_bits, (reg_addr | (1 << 5))); buffer += 4; } } #endif } int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode, const uint32_t *data, size_t count) { /* bypass bits before and after */ int pre_bits; int post_bits; jtag_pre_post_bits(tap, &pre_bits, &post_bits); post_bits += 2; if ((pre_bits > 32) || (post_bits > 32)) { int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *, uint32_t, const uint32_t *, size_t); return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count); } else { static const uint8_t zero; /* FIX!!!!!! the target_write_memory() API started this nasty problem * with unaligned uint32_t * pointers... */ const uint8_t *t = (const uint8_t *)data; while (--count > 0) { #if 1 /* Danger! This code doesn't update cmd_queue_cur_state, so * invoking jtag_add_pathmove() before jtag_add_dr_scan() after * this loop would fail! */ shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0); uint32_t value; value = *t++; value |= (*t++<<8); value |= (*t++<<16); value |= (*t++<<24); shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, value); /* minimum 2 bits */ shiftValueInner(TAP_DRSHIFT, TAP_DRPAUSE, post_bits, 0); /* copy & paste from arm11_dbgtap.c */ /* TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, * TAP_DRCAPTURE, TAP_DRSHIFT */ /* KLUDGE! we have to flush the fifo or the Nios CPU locks up. * This is probably a bug in the Avalon bus(cross clocking bridge?) * or in the jtag registers module. */ waitIdle(); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0); /* we don't have to wait for the queue to empty here */ ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); waitIdle(); #else static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; struct scan_field fields[2] = { { .num_bits = 32, .out_value = t }, { .num_bits = 2, .out_value = &zero }, }; t += 4; jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); #endif } struct scan_field fields[2] = { { .num_bits = 32, .out_value = t }, { .num_bits = 2, .out_value = &zero }, }; /* This will happen on the last iteration updating cmd_queue_cur_state * so we don't have to track it during the common code path */ jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); return jtag_execute_queue(); } } static const struct command_registration zy1000_commands[] = { { .name = "power", .handler = handle_power_command, .mode = COMMAND_ANY, .help = "Turn power switch to target on/off. " "With no arguments, prints status.", .usage = "('on'|'off)", }, #if !BUILD_ZY1000_MASTER { .name = "zy1000_server", .mode = COMMAND_ANY, .jim_handler = jim_zy1000_server, .help = "Tcpip address for ZY1000 server.", .usage = "address", }, #endif { .name = "powerstatus", .mode = COMMAND_ANY, .jim_handler = zylinjtag_Jim_Command_powerstatus, .help = "Returns power status of target", }, COMMAND_REGISTRATION_DONE }; #if !BUILD_ZY1000_MASTER static int tcp_ip = -1; /* Write large packets if we can */ static size_t out_pos; static uint8_t out_buffer[16384]; static size_t in_pos; static size_t in_write; static uint8_t in_buffer[16384]; static bool flush_writes(void) { bool ok = (write(tcp_ip, out_buffer, out_pos) == (int)out_pos); out_pos = 0; return ok; } static bool writeLong(uint32_t l) { int i; for (i = 0; i < 4; i++) { uint8_t c = (l >> (i*8))&0xff; out_buffer[out_pos++] = c; if (out_pos >= sizeof(out_buffer)) { if (!flush_writes()) return false; } } return true; } static bool readLong(uint32_t *out_data) { uint32_t data = 0; int i; for (i = 0; i < 4; i++) { uint8_t c; if (in_pos == in_write) { /* If we have some data that we can send, send them before * we wait for more data */ if (out_pos > 0) { if (!flush_writes()) return false; } /* read more */ int t; t = read(tcp_ip, in_buffer, sizeof(in_buffer)); if (t < 1) return false; in_write = (size_t) t; in_pos = 0; } c = in_buffer[in_pos++]; data |= (c << (i*8)); } *out_data = data; return true; } enum ZY1000_CMD { ZY1000_CMD_POKE = 0x0, ZY1000_CMD_PEEK = 0x8, ZY1000_CMD_SLEEP = 0x1, ZY1000_CMD_WAITIDLE = 2 }; #include /* for socket(), connect(), send(), and recv() */ #include /* for sockaddr_in and inet_addr() */ /* We initialize this late since we need to know the server address * first. */ static void tcpip_open(void) { if (tcp_ip >= 0) return; struct sockaddr_in echoServAddr;/* Echo server address */ /* Create a reliable, stream socket using TCP */ tcp_ip = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (tcp_ip < 0) { fprintf(stderr, "Failed to connect to zy1000 server\n"); exit(-1); } /* Construct the server address structure */ memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */ echoServAddr.sin_family = AF_INET; /* Internet address family */ echoServAddr.sin_addr.s_addr = inet_addr(tcp_server); /* Server IP address */ echoServAddr.sin_port = htons(7777); /* Server port */ /* Establish the connection to the echo server */ if (connect(tcp_ip, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) { fprintf(stderr, "Failed to connect to zy1000 server\n"); exit(-1); } int flag = 1; setsockopt(tcp_ip, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char *)&flag, /* the cast is historical cruft */ sizeof(int)); /* length of option value */ } /* send a poke */ void zy1000_tcpout(uint32_t address, uint32_t data) { tcpip_open(); if (!writeLong((ZY1000_CMD_POKE << 24) | address) || !writeLong(data)) { fprintf(stderr, "Could not write to zy1000 server\n"); exit(-1); } } /* By sending the wait to the server, we avoid a readback * of status. Radically improves performance for this operation * with long ping times. */ void waitIdle(void) { tcpip_open(); if (!writeLong((ZY1000_CMD_WAITIDLE << 24))) { fprintf(stderr, "Could not write to zy1000 server\n"); exit(-1); } } uint32_t zy1000_tcpin(uint32_t address) { tcpip_open(); zy1000_flush_readqueue(); uint32_t data; if (!writeLong((ZY1000_CMD_PEEK << 24) | address) || !readLong(&data)) { fprintf(stderr, "Could not read from zy1000 server\n"); exit(-1); } return data; } int interface_jtag_add_sleep(uint32_t us) { tcpip_open(); if (!writeLong((ZY1000_CMD_SLEEP << 24)) || !writeLong(us)) { fprintf(stderr, "Could not read from zy1000 server\n"); exit(-1); } return ERROR_OK; } /* queue a readback */ #define readqueue_size 16384 static struct { uint8_t *dest; int bits; } readqueue[readqueue_size]; static int readqueue_pos; /* flush the readqueue, this means reading any data that * we're expecting and store them into the final position */ void zy1000_flush_readqueue(void) { if (readqueue_pos == 0) { /* simply debugging by allowing easy breakpoints when there * is something to do. */ return; } int i; tcpip_open(); for (i = 0; i < readqueue_pos; i++) { uint32_t value; if (!readLong(&value)) { fprintf(stderr, "Could not read from zy1000 server\n"); exit(-1); } uint8_t *in_value = readqueue[i].dest; int k = readqueue[i].bits; /* we're shifting in data to MSB, shift data to be aligned for returning the value */ value >>= 32-k; for (int l = 0; l < k; l += 8) in_value[l/8] = (value >> l)&0xff; } readqueue_pos = 0; } /* By queuing the callback's we avoid flushing the * read queue until jtag_execute_queue(). This can * reduce latency dramatically for cases where * callbacks are used extensively. */ #define callbackqueue_size 128 static struct callbackentry { jtag_callback_t callback; jtag_callback_data_t data0; jtag_callback_data_t data1; jtag_callback_data_t data2; jtag_callback_data_t data3; } callbackqueue[callbackqueue_size]; static int callbackqueue_pos; void zy1000_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { if (callbackqueue_pos >= callbackqueue_size) zy1000_flush_callbackqueue(); callbackqueue[callbackqueue_pos].callback = callback; callbackqueue[callbackqueue_pos].data0 = data0; callbackqueue[callbackqueue_pos].data1 = data1; callbackqueue[callbackqueue_pos].data2 = data2; callbackqueue[callbackqueue_pos].data3 = data3; callbackqueue_pos++; /* KLUDGE! * make callbacks synchronous for now as minidriver requires callback * to be synchronous. * * We can get away with making read and writes asynchronous so we * don't completely kill performance. */ zy1000_flush_callbackqueue(); } static int zy1000_jtag_convert_to_callback4(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { ((jtag_callback1_t)data1)(data0); return ERROR_OK; } void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) { zy1000_jtag_add_callback4(zy1000_jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0); } void zy1000_flush_callbackqueue(void) { /* we have to flush the read queue so we have access to the data the callbacks will use */ zy1000_flush_readqueue(); int i; for (i = 0; i < callbackqueue_pos; i++) { struct callbackentry *entry = &callbackqueue[i]; jtag_set_error(entry->callback(entry->data0, entry->data1, entry->data2, entry->data3)); } callbackqueue_pos = 0; } static void writeShiftValue(uint8_t *data, int bits) { waitIdle(); if (!writeLong((ZY1000_CMD_PEEK << 24) | (ZY1000_JTAG_BASE + 0xc))) { fprintf(stderr, "Could not read from zy1000 server\n"); exit(-1); } if (readqueue_pos >= readqueue_size) zy1000_flush_readqueue(); readqueue[readqueue_pos].dest = data; readqueue[readqueue_pos].bits = bits; readqueue_pos++; /* KLUDGE!!! minidriver requires readqueue to be synchronous */ zy1000_flush_readqueue(); } #else static void writeShiftValue(uint8_t *data, int bits) { uint32_t value; waitIdle(); ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, value); VERBOSE(LOG_INFO("getShiftValue %08x", value)); /* data in, LSB to MSB */ /* we're shifting in data to MSB, shift data to be aligned for returning the value */ value >>= 32 - bits; for (int l = 0; l < bits; l += 8) data[l/8] = (value >> l)&0xff; } #endif #if BUILD_ZY1000_MASTER #ifdef WATCHDOG_BASE /* If we connect to port 8888 we must send a char every 10s or the board resets itself */ static void watchdog_server(cyg_addrword_t data) { int so_reuseaddr_option = 1; int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { LOG_ERROR("error creating socket: %s", strerror(errno)); exit(-1); } setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &so_reuseaddr_option, sizeof(int)); struct sockaddr_in sin; unsigned int address_size; address_size = sizeof(sin); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(8888); if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1) { LOG_ERROR("couldn't bind to socket: %s", strerror(errno)); exit(-1); } if (listen(fd, 1) == -1) { LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); exit(-1); } for (;; ) { int watchdog_ip = accept(fd, (struct sockaddr *) &sin, &address_size); /* Start watchdog, must be reset every 10 seconds. */ HAL_WRITE_UINT32(WATCHDOG_BASE + 4, 4); if (watchdog_ip < 0) { LOG_ERROR("couldn't open watchdog socket: %s", strerror(errno)); exit(-1); } int flag = 1; setsockopt(watchdog_ip, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char *)&flag, /* the cast is historical cruft */ sizeof(int)); /* length of option value */ char buf; for (;; ) { if (read(watchdog_ip, &buf, 1) == 1) { /* Reset timer */ HAL_WRITE_UINT32(WATCHDOG_BASE + 8, 0x1234); /* Echo so we can telnet in and see that resetting works */ write(watchdog_ip, &buf, 1); } else { /* Stop tickling the watchdog, the CPU will reset in < 10 seconds * now. */ return; } } /* Never reached */ } } #endif #endif #if BUILD_ZY1000_MASTER int interface_jtag_add_sleep(uint32_t us) { jtag_sleep(us); return ERROR_OK; } #endif #if BUILD_ZY1000_MASTER volatile void *zy1000_jtag_master; #include #endif int zy1000_init(void) { #if BUILD_ZY1000_MASTER int fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { LOG_ERROR("No access to /dev/mem"); return ERROR_FAIL; } #ifndef REGISTERS_BASE #define REGISTERS_BASE 0x9002000 #define REGISTERS_SPAN 128 #endif zy1000_jtag_master = mmap(0, REGISTERS_SPAN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, REGISTERS_BASE); if (zy1000_jtag_master == (void *) -1) { close(fd); LOG_ERROR("No access to /dev/mem"); return ERROR_FAIL; } #endif ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x30); /* Turn on LED1 & LED2 */ setPower(true); /* on by default */ /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */ zy1000_reset(0, 0); return ERROR_OK; } struct jtag_interface zy1000_interface = { .name = "ZY1000", .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = NULL, .speed = zy1000_speed, .commands = zy1000_commands, .init = zy1000_init, .quit = zy1000_quit, .khz = zy1000_khz, .speed_div = zy1000_speed_div, .power_dropout = zy1000_power_dropout, .srst_asserted = zy1000_srst_asserted, }; openocd-0.9.0/src/jtag/adapter.c0000644000175000017500000003634312516456302013405 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * * http://softplc.com * * dick@softplc.com * * * * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag.h" #include "minidriver.h" #include "interface.h" #include "interfaces.h" #include #ifdef HAVE_STRINGS_H #include #endif /** * @file * Holds support for configuring debug adapters from TCl scripts. */ extern struct jtag_interface *jtag_interface; const char * const jtag_only[] = { "jtag", NULL }; static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); /* return the name of the interface */ /* TCL code might need to know the exact type... */ /* FUTURE: we allow this as a means to "set" the interface. */ if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)"); return JIM_ERR; } const char *name = jtag_interface ? jtag_interface->name : NULL; Jim_SetResultString(goi.interp, name ? : "undefined", -1); return JIM_OK; } static int default_khz(int khz, int *jtag_speed) { LOG_ERROR("Translation from khz to jtag_speed not implemented"); return ERROR_FAIL; } static int default_speed_div(int speed, int *khz) { LOG_ERROR("Translation from jtag_speed to khz not implemented"); return ERROR_FAIL; } static int default_power_dropout(int *dropout) { *dropout = 0; /* by default we can't detect power dropout */ return ERROR_OK; } static int default_srst_asserted(int *srst_asserted) { *srst_asserted = 0; /* by default we can't detect srst asserted */ return ERROR_OK; } COMMAND_HANDLER(interface_transport_command) { char **transports; int retval; retval = CALL_COMMAND_HANDLER(transport_list_parse, &transports); if (retval != ERROR_OK) return retval; retval = allow_transports(CMD_CTX, (const char **)transports); if (retval != ERROR_OK) { for (unsigned i = 0; transports[i]; i++) free(transports[i]); free(transports); } return retval; } COMMAND_HANDLER(handle_interface_list_command) { if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "The following debug interfaces are available:"); for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) { const char *name = jtag_interfaces[i]->name; command_print(CMD_CTX, "%u: %s", i + 1, name); } return ERROR_OK; } COMMAND_HANDLER(handle_interface_command) { int retval; /* check whether the interface is already configured */ if (jtag_interface) { LOG_WARNING("Interface already configured, ignoring"); return ERROR_OK; } /* interface name is a mandatory argument */ if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0') return ERROR_COMMAND_SYNTAX_ERROR; for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) { if (strcmp(CMD_ARGV[0], jtag_interfaces[i]->name) != 0) continue; if (NULL != jtag_interfaces[i]->commands) { retval = register_commands(CMD_CTX, NULL, jtag_interfaces[i]->commands); if (ERROR_OK != retval) return retval; } jtag_interface = jtag_interfaces[i]; /* LEGACY SUPPORT ... adapter drivers must declare what * transports they allow. Until they all do so, assume * the legacy drivers are JTAG-only */ if (!jtag_interface->transports) LOG_WARNING("Adapter driver '%s' did not declare " "which transports it allows; assuming " "legacy JTAG-only", jtag_interface->name); retval = allow_transports(CMD_CTX, jtag_interface->transports ? jtag_interface->transports : jtag_only); if (ERROR_OK != retval) return retval; if (jtag_interface->khz == NULL) jtag_interface->khz = default_khz; if (jtag_interface->speed_div == NULL) jtag_interface->speed_div = default_speed_div; if (jtag_interface->power_dropout == NULL) jtag_interface->power_dropout = default_power_dropout; if (jtag_interface->srst_asserted == NULL) jtag_interface->srst_asserted = default_srst_asserted; return ERROR_OK; } /* no valid interface was found (i.e. the configuration option, * didn't match one of the compiled-in interfaces */ LOG_ERROR("The specified debug interface was not found (%s)", CMD_ARGV[0]); CALL_COMMAND_HANDLER(handle_interface_list_command); return ERROR_JTAG_INVALID_INTERFACE; } COMMAND_HANDLER(handle_reset_config_command) { int new_cfg = 0; int mask = 0; /* Original versions cared about the order of these tokens: * reset_config signals [combination [trst_type [srst_type]]] * They also clobbered the previous configuration even on error. * * Here we don't care about the order, and only change values * which have been explicitly specified. */ for (; CMD_ARGC; CMD_ARGC--, CMD_ARGV++) { int tmp = 0; int m; /* gating */ m = RESET_SRST_NO_GATING; if (strcmp(*CMD_ARGV, "srst_gates_jtag") == 0) /* default: don't use JTAG while SRST asserted */; else if (strcmp(*CMD_ARGV, "srst_nogate") == 0) tmp = RESET_SRST_NO_GATING; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "gating", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* signals */ m = RESET_HAS_TRST | RESET_HAS_SRST; if (strcmp(*CMD_ARGV, "none") == 0) tmp = RESET_NONE; else if (strcmp(*CMD_ARGV, "trst_only") == 0) tmp = RESET_HAS_TRST; else if (strcmp(*CMD_ARGV, "srst_only") == 0) tmp = RESET_HAS_SRST; else if (strcmp(*CMD_ARGV, "trst_and_srst") == 0) tmp = RESET_HAS_TRST | RESET_HAS_SRST; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "signal", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* combination (options for broken wiring) */ m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST; if (strcmp(*CMD_ARGV, "separate") == 0) /* separate reset lines - default */; else if (strcmp(*CMD_ARGV, "srst_pulls_trst") == 0) tmp |= RESET_SRST_PULLS_TRST; else if (strcmp(*CMD_ARGV, "trst_pulls_srst") == 0) tmp |= RESET_TRST_PULLS_SRST; else if (strcmp(*CMD_ARGV, "combined") == 0) tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "combination", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* trst_type (NOP without HAS_TRST) */ m = RESET_TRST_OPEN_DRAIN; if (strcmp(*CMD_ARGV, "trst_open_drain") == 0) tmp |= RESET_TRST_OPEN_DRAIN; else if (strcmp(*CMD_ARGV, "trst_push_pull") == 0) /* push/pull from adapter - default */; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "trst_type", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* srst_type (NOP without HAS_SRST) */ m = RESET_SRST_PUSH_PULL; if (strcmp(*CMD_ARGV, "srst_push_pull") == 0) tmp |= RESET_SRST_PUSH_PULL; else if (strcmp(*CMD_ARGV, "srst_open_drain") == 0) /* open drain from adapter - default */; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "srst_type", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* connect_type - only valid when srst_nogate */ m = RESET_CNCT_UNDER_SRST; if (strcmp(*CMD_ARGV, "connect_assert_srst") == 0) tmp |= RESET_CNCT_UNDER_SRST; else if (strcmp(*CMD_ARGV, "connect_deassert_srst") == 0) /* connect normally - default */; else m = 0; if (mask & m) { LOG_ERROR("extra reset_config %s spec (%s)", "connect_type", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } if (m) goto next; /* caller provided nonsense; fail */ LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; next: /* Remember the bits which were specified (mask) * and their new values (new_cfg). */ mask |= m; new_cfg |= tmp; } /* clear previous values of those bits, save new values */ if (mask) { int old_cfg = jtag_get_reset_config(); old_cfg &= ~mask; new_cfg |= old_cfg; jtag_set_reset_config(new_cfg); } else new_cfg = jtag_get_reset_config(); /* * Display the (now-)current reset mode */ char *modes[6]; /* minimal JTAG has neither SRST nor TRST (so that's the default) */ switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) { case RESET_HAS_SRST: modes[0] = "srst_only"; break; case RESET_HAS_TRST: modes[0] = "trst_only"; break; case RESET_TRST_AND_SRST: modes[0] = "trst_and_srst"; break; default: modes[0] = "none"; break; } /* normally SRST and TRST are decoupled; but bugs happen ... */ switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) { case RESET_SRST_PULLS_TRST: modes[1] = "srst_pulls_trst"; break; case RESET_TRST_PULLS_SRST: modes[1] = "trst_pulls_srst"; break; case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST: modes[1] = "combined"; break; default: modes[1] = "separate"; break; } /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */ if (new_cfg & RESET_HAS_TRST) { if (new_cfg & RESET_TRST_OPEN_DRAIN) modes[3] = " trst_open_drain"; else modes[3] = " trst_push_pull"; } else modes[3] = ""; /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */ if (new_cfg & RESET_HAS_SRST) { if (new_cfg & RESET_SRST_NO_GATING) modes[2] = " srst_nogate"; else modes[2] = " srst_gates_jtag"; if (new_cfg & RESET_SRST_PUSH_PULL) modes[4] = " srst_push_pull"; else modes[4] = " srst_open_drain"; if (new_cfg & RESET_CNCT_UNDER_SRST) modes[5] = " connect_assert_srst"; else modes[5] = " connect_deassert_srst"; } else { modes[2] = ""; modes[4] = ""; modes[5] = ""; } command_print(CMD_CTX, "%s %s%s%s%s%s", modes[0], modes[1], modes[2], modes[3], modes[4], modes[5]); return ERROR_OK; } COMMAND_HANDLER(handle_adapter_nsrst_delay_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { unsigned delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_nsrst_delay(delay); } command_print(CMD_CTX, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay()); return ERROR_OK; } COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { unsigned width; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], width); jtag_set_nsrst_assert_width(width); } command_print(CMD_CTX, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width()); return ERROR_OK; } COMMAND_HANDLER(handle_adapter_khz_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; int retval = ERROR_OK; if (CMD_ARGC == 1) { unsigned khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = jtag_config_khz(khz); if (ERROR_OK != retval) return retval; } int cur_speed = jtag_get_speed_khz(); retval = jtag_get_speed_readable(&cur_speed); if (ERROR_OK != retval) return retval; if (cur_speed) command_print(CMD_CTX, "adapter speed: %d kHz", cur_speed); else command_print(CMD_CTX, "adapter speed: RCLK - adaptive"); return retval; } static const struct command_registration interface_command_handlers[] = { { .name = "adapter_khz", .handler = handle_adapter_khz_command, .mode = COMMAND_ANY, .help = "With an argument, change to the specified maximum " "jtag speed. For JTAG, 0 KHz signifies adaptive " " clocking. " "With or without argument, display current setting.", .usage = "[khz]", }, { .name = "adapter_name", .mode = COMMAND_ANY, .jim_handler = jim_adapter_name, .help = "Returns the name of the currently " "selected adapter (driver)", }, { .name = "adapter_nsrst_delay", .handler = handle_adapter_nsrst_delay_command, .mode = COMMAND_ANY, .help = "delay after deasserting SRST in ms", .usage = "[milliseconds]", }, { .name = "adapter_nsrst_assert_width", .handler = handle_adapter_nsrst_assert_width_command, .mode = COMMAND_ANY, .help = "delay after asserting SRST in ms", .usage = "[milliseconds]", }, { .name = "interface", .handler = handle_interface_command, .mode = COMMAND_CONFIG, .help = "Select a debug adapter interface (driver)", .usage = "driver_name", }, { .name = "interface_transports", .handler = interface_transport_command, .mode = COMMAND_CONFIG, .help = "Declare transports the interface supports.", .usage = "transport ... ", }, { .name = "interface_list", .handler = handle_interface_list_command, .mode = COMMAND_ANY, .help = "List all built-in debug adapter interfaces (drivers)", }, { .name = "reset_config", .handler = handle_reset_config_command, .mode = COMMAND_ANY, .help = "configure adapter reset behavior", .usage = "[none|trst_only|srst_only|trst_and_srst] " "[srst_pulls_trst|trst_pulls_srst|combined|separate] " "[srst_gates_jtag|srst_nogate] " "[trst_push_pull|trst_open_drain] " "[srst_push_pull|srst_open_drain] " "[connect_deassert_srst|connect_assert_srst]", }, COMMAND_REGISTRATION_DONE }; /** * Register the commands which deal with arbitrary debug adapter drivers. * * @todo Remove internal assumptions that all debug adapters use JTAG for * transport. Various types and data structures are not named generically. */ int interface_register_commands(struct command_context *ctx) { return register_commands(ctx, NULL, interface_command_handlers); } openocd-0.9.0/src/jtag/minidriver/0000755000175000017500000000000012526202224014031 500000000000000openocd-0.9.0/src/jtag/minidriver/minidriver_imp.h0000644000175000017500000000352012315575361017152 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MINIDRIVER_IMP_H #define MINIDRIVER_IMP_H #include #define jtag_add_callback(callback, in) interface_jtag_add_callback(callback, in) #define jtag_add_callback4(callback, in, data1, data2, data3) \ interface_jtag_add_callback4(callback, in, data1, data2, data3) #endif /* MINIDRIVER_IMP_H */ openocd-0.9.0/src/rtos/0000755000175000017500000000000012526202226011725 500000000000000openocd-0.9.0/src/rtos/FreeRTOS.c0000644000175000017500000004120512516456303013412 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_standard_stackings.h" #define FREERTOS_MAX_PRIORITIES 63 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset) struct FreeRTOS_params { const char *target_name; const unsigned char thread_count_width; const unsigned char pointer_width; const unsigned char list_next_offset; const unsigned char list_width; const unsigned char list_elem_next_offset; const unsigned char list_elem_content_offset; const unsigned char thread_stack_offset; const unsigned char thread_name_offset; const struct rtos_register_stacking *stacking_info; }; static const struct FreeRTOS_params FreeRTOS_params_list[] = { { "cortex_m", /* target_name */ 4, /* thread_count_width; */ 4, /* pointer_width; */ 16, /* list_next_offset; */ 20, /* list_width; */ 8, /* list_elem_next_offset; */ 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_Cortex_M3_stacking, /* stacking_info */ }, { "hla_target", /* target_name */ 4, /* thread_count_width; */ 4, /* pointer_width; */ 16, /* list_next_offset; */ 20, /* list_width; */ 8, /* list_elem_next_offset; */ 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_Cortex_M3_stacking, /* stacking_info */ }, { "nds32_v3", /* target_name */ 4, /* thread_count_width; */ 4, /* pointer_width; */ 16, /* list_next_offset; */ 20, /* list_width; */ 8, /* list_elem_next_offset; */ 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_NDS32_N1068_stacking, /* stacking_info */ }, }; #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params))) static int FreeRTOS_detect_rtos(struct target *target); static int FreeRTOS_create(struct target *target); static int FreeRTOS_update_threads(struct rtos *rtos); static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct rtos_type FreeRTOS_rtos = { .name = "FreeRTOS", .detect_rtos = FreeRTOS_detect_rtos, .create = FreeRTOS_create, .update_threads = FreeRTOS_update_threads, .get_thread_reg_list = FreeRTOS_get_thread_reg_list, .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup, }; enum FreeRTOS_symbol_values { FreeRTOS_VAL_pxCurrentTCB = 0, FreeRTOS_VAL_pxReadyTasksLists = 1, FreeRTOS_VAL_xDelayedTaskList1 = 2, FreeRTOS_VAL_xDelayedTaskList2 = 3, FreeRTOS_VAL_pxDelayedTaskList = 4, FreeRTOS_VAL_pxOverflowDelayedTaskList = 5, FreeRTOS_VAL_xPendingReadyList = 6, FreeRTOS_VAL_xTasksWaitingTermination = 7, FreeRTOS_VAL_xSuspendedTaskList = 8, FreeRTOS_VAL_uxCurrentNumberOfTasks = 9, FreeRTOS_VAL_uxTopUsedPriority = 10, }; struct symbols { const char *name; bool optional; }; static const struct symbols FreeRTOS_symbol_list[] = { { "pxCurrentTCB", false }, { "pxReadyTasksLists", false }, { "xDelayedTaskList1", false }, { "xDelayedTaskList2", false }, { "pxDelayedTaskList", false }, { "pxOverflowDelayedTaskList", false }, { "xPendingReadyList", false }, { "xTasksWaitingTermination", true }, /* Only if INCLUDE_vTaskDelete */ { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */ { "uxCurrentNumberOfTasks", false }, { "uxTopUsedPriority", true }, /* Unavailable since v7.5.3 */ { NULL, false } }; /* TODO: */ /* this is not safe for little endian yet */ /* may be problems reading if sizes are not 32 bit long integers. */ /* test mallocs for failure */ static int FreeRTOS_update_threads(struct rtos *rtos) { int i = 0; int retval; int tasks_found = 0; const struct FreeRTOS_params *param; if (rtos->rtos_specific_params == NULL) return -1; param = (const struct FreeRTOS_params *) rtos->rtos_specific_params; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for FreeRTOS"); return -3; } if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) { LOG_ERROR("Don't have the number of threads in FreeRTOS"); return -2; } int thread_list_size = 0; retval = target_read_buffer(rtos->target, rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address, param->thread_count_width, (uint8_t *)&thread_list_size); LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64 ", value %d\r\n", rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address, thread_list_size); if (retval != ERROR_OK) { LOG_ERROR("Could not read FreeRTOS thread count from target"); return retval; } /* wipe out previous thread details if any */ rtos_free_threadlist(rtos); /* read the current thread */ retval = target_read_buffer(rtos->target, rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, param->pointer_width, (uint8_t *)&rtos->current_thread); if (retval != ERROR_OK) { LOG_ERROR("Error reading current thread in FreeRTOS thread list"); return retval; } LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, rtos->current_thread); if ((thread_list_size == 0) || (rtos->current_thread == 0)) { /* Either : No RTOS threads - there is always at least the current execution though */ /* OR : No current thread - all threads suspended - show the current execution * of idling */ char tmp_str[] = "Current Execution"; thread_list_size++; tasks_found++; rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); if (!rtos->thread_details) { LOG_ERROR("Error allocating memory for %d threads", thread_list_size); return ERROR_FAIL; } rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); if (thread_list_size == 1) { rtos->thread_count = 1; return ERROR_OK; } } else { /* create space for new thread details */ rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); if (!rtos->thread_details) { LOG_ERROR("Error allocating memory for %d threads", thread_list_size); return ERROR_FAIL; } } /* Find out how many lists are needed to be read from pxReadyTasksLists, */ if (rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address == 0) { LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around"); return ERROR_FAIL; } int64_t max_used_priority = 0; retval = target_read_buffer(rtos->target, rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, param->pointer_width, (uint8_t *)&max_used_priority); if (retval != ERROR_OK) return retval; LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRId64 "\r\n", rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, max_used_priority); if (max_used_priority > FREERTOS_MAX_PRIORITIES) { LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64 "", max_used_priority); return ERROR_FAIL; } symbol_address_t *list_of_lists = malloc(sizeof(symbol_address_t) * (max_used_priority+1 + 5)); if (!list_of_lists) { LOG_ERROR("Error allocating memory for %" PRId64 " priorities", max_used_priority); return ERROR_FAIL; } int num_lists; for (num_lists = 0; num_lists <= max_used_priority; num_lists++) list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address + num_lists * param->list_width; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address; for (i = 0; i < num_lists; i++) { if (list_of_lists[i] == 0) continue; /* Read the number of threads in this list */ int64_t list_thread_count = 0; retval = target_read_buffer(rtos->target, list_of_lists[i], param->thread_count_width, (uint8_t *)&list_thread_count); if (retval != ERROR_OK) { LOG_ERROR("Error reading number of threads in FreeRTOS thread list"); free(list_of_lists); return retval; } LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64 ", value %" PRId64 "\r\n", i, list_of_lists[i], list_thread_count); if (list_thread_count == 0) continue; /* Read the location of first list item */ uint64_t prev_list_elem_ptr = -1; uint64_t list_elem_ptr = 0; retval = target_read_buffer(rtos->target, list_of_lists[i] + param->list_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading first thread item location in FreeRTOS thread list"); free(list_of_lists); return retval; } LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", i, list_of_lists[i] + param->list_next_offset, list_elem_ptr); while ((list_thread_count > 0) && (list_elem_ptr != 0) && (list_elem_ptr != prev_list_elem_ptr) && (tasks_found < thread_list_size)) { /* Get the location of the thread structure. */ rtos->thread_details[tasks_found].threadid = 0; retval = target_read_buffer(rtos->target, list_elem_ptr + param->list_elem_content_offset, param->pointer_width, (uint8_t *)&(rtos->thread_details[tasks_found].threadid)); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread list item object in FreeRTOS thread list"); free(list_of_lists); return retval; } LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", list_elem_ptr + param->list_elem_content_offset, rtos->thread_details[tasks_found].threadid); /* get thread name */ #define FREERTOS_THREAD_NAME_STR_SIZE (200) char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE]; /* Read the thread name */ retval = target_read_buffer(rtos->target, rtos->thread_details[tasks_found].threadid + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading first thread item location in FreeRTOS thread list"); free(list_of_lists); return retval; } tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00'; LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value \"%s\"\r\n", rtos->thread_details[tasks_found].threadid + param->thread_name_offset, tmp_str); if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); rtos->thread_details[tasks_found].thread_name_str = malloc(strlen(tmp_str)+1); strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str); rtos->thread_details[tasks_found].display_str = NULL; rtos->thread_details[tasks_found].exists = true; if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) { char running_str[] = "Running"; rtos->thread_details[tasks_found].extra_info_str = malloc( sizeof(running_str)); strcpy(rtos->thread_details[tasks_found].extra_info_str, running_str); } else rtos->thread_details[tasks_found].extra_info_str = NULL; tasks_found++; list_thread_count--; prev_list_elem_ptr = list_elem_ptr; list_elem_ptr = 0; retval = target_read_buffer(rtos->target, prev_list_elem_ptr + param->list_elem_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading next thread item location in FreeRTOS thread list"); free(list_of_lists); return retval; } LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", prev_list_elem_ptr + param->list_elem_next_offset, list_elem_ptr); } } free(list_of_lists); rtos->thread_count = tasks_found; return 0; } static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { int retval; const struct FreeRTOS_params *param; int64_t stack_ptr = 0; *hex_reg_list = NULL; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -1; param = (const struct FreeRTOS_params *) rtos->rtos_specific_params; /* Read the stack pointer */ retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t *)&stack_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading stack frame from FreeRTOS thread"); return retval; } LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", thread_id + param->thread_stack_offset, stack_ptr); return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); } static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = calloc( ARRAY_SIZE(FreeRTOS_symbol_list), sizeof(symbol_table_elem_t)); for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++) { (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i].name; (*symbol_list)[i].optional = FreeRTOS_symbol_list[i].optional; } return 0; } #if 0 static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id) { return 0; } static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info) { int retval; const struct FreeRTOS_params *param; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct FreeRTOS_params *) rtos->rtos_specific_params; #define FREERTOS_THREAD_NAME_STR_SIZE (200) char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE]; /* Read the thread name */ retval = target_read_buffer(rtos->target, thread_id + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading first thread item location in FreeRTOS thread list"); return retval; } tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00'; if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); *info = malloc(strlen(tmp_str)+1); strcpy(*info, tmp_str); return 0; } #endif static int FreeRTOS_detect_rtos(struct target *target) { if ((target->rtos->symbols != NULL) && (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) { /* looks like FreeRTOS */ return 1; } return 0; } static int FreeRTOS_create(struct target *target) { int i = 0; while ((i < FREERTOS_NUM_PARAMS) && (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) { i++; } if (i >= FREERTOS_NUM_PARAMS) { LOG_ERROR("Could not find target in FreeRTOS compatibility list"); return -1; } target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i]; return 0; } openocd-0.9.0/src/rtos/rtos_ecos_stackings.c0000644000175000017500000000432312315575361016072 00000000000000/*************************************************************************** * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/armv7m.h" static const struct stack_register_offset rtos_eCos_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { 0x0c, 32 }, /* r0 */ { 0x10, 32 }, /* r1 */ { 0x14, 32 }, /* r2 */ { 0x18, 32 }, /* r3 */ { 0x1c, 32 }, /* r4 */ { 0x20, 32 }, /* r5 */ { 0x24, 32 }, /* r6 */ { 0x28, 32 }, /* r7 */ { 0x2c, 32 }, /* r8 */ { 0x30, 32 }, /* r9 */ { 0x34, 32 }, /* r10 */ { 0x38, 32 }, /* r11 */ { 0x3c, 32 }, /* r12 */ { -2, 32 }, /* sp */ { -1, 32 }, /* lr */ { 0x40, 32 }, /* pc */ { -1, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking = { 0x44, /* stack_registers_size */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 8, /* stack_alignment */ rtos_eCos_Cortex_M3_stack_offsets /* register_offsets */ }; openocd-0.9.0/src/rtos/rtos_ecos_stackings.h0000644000175000017500000000307612315575361016103 00000000000000/*************************************************************************** * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ #define INCLUDED_RTOS_STANDARD_STACKINGS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" extern const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking; #endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */ openocd-0.9.0/src/rtos/embKernel.c0000644000175000017500000002701212516456303013725 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_embkernel_stackings.h" #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64) static int embKernel_detect_rtos(struct target *target); static int embKernel_create(struct target *target); static int embKernel_update_threads(struct rtos *rtos); static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct rtos_type embKernel_rtos = { .name = "embKernel", .detect_rtos = embKernel_detect_rtos, .create = embKernel_create, .update_threads = embKernel_update_threads, .get_thread_reg_list = embKernel_get_thread_reg_list, .get_symbol_list_to_lookup = embKernel_get_symbol_list_to_lookup, }; enum { SYMBOL_ID_sCurrentTask = 0, SYMBOL_ID_sListReady = 1, SYMBOL_ID_sListSleep = 2, SYMBOL_ID_sListSuspended = 3, SYMBOL_ID_sMaxPriorities = 4, SYMBOL_ID_sCurrentTaskCount = 5, }; static const char * const embKernel_symbol_list[] = { "Rtos::sCurrentTask", "Rtos::sListReady", "Rtos::sListSleep", "Rtos::sListSuspended", "Rtos::sMaxPriorities", "Rtos::sCurrentTaskCount", NULL }; struct embKernel_params { const char *target_name; const unsigned char pointer_width; const unsigned char thread_count_width; const unsigned char rtos_list_size; const unsigned char thread_stack_offset; const unsigned char thread_name_offset; const unsigned char thread_priority_offset; const unsigned char thread_priority_width; const unsigned char iterable_next_offset; const unsigned char iterable_task_owner_offset; const struct rtos_register_stacking *stacking_info; }; static const struct embKernel_params embKernel_params_list[] = { { "cortex_m", /* target_name */ 4, /* pointer_width */ 4, /* thread_count_width */ 8, /*rtos_list_size */ 0, /*thread_stack_offset */ 4, /*thread_name_offset */ 8, /*thread_priority_offset */ 4, /*thread_priority_width */ 4, /*iterable_next_offset */ 12, /*iterable_task_owner_offset */ &rtos_embkernel_Cortex_M_stacking, /* stacking_info*/ }, { "hla_target", /* target_name */ 4, /* pointer_width */ 4, /* thread_count_width */ 8, /*rtos_list_size */ 0, /*thread_stack_offset */ 4, /*thread_name_offset */ 8, /*thread_priority_offset */ 4, /*thread_priority_width */ 4, /*iterable_next_offset */ 12, /*iterable_task_owner_offset */ &rtos_embkernel_Cortex_M_stacking, /* stacking_info */ } }; static int embKernel_detect_rtos(struct target *target) { if (target->rtos->symbols != NULL) { if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0) return 1; } return 0; } static int embKernel_create(struct target *target) { size_t i = 0; while ((i < ARRAY_SIZE(embKernel_params_list)) && (0 != strcmp(embKernel_params_list[i].target_name, target->type->name))) i++; if (i >= ARRAY_SIZE(embKernel_params_list)) { LOG_WARNING("Could not find target \"%s\" in embKernel compatibility " "list", target->type->name); return -1; } target->rtos->rtos_specific_params = (void *) &embKernel_params_list[i]; return 0; } static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param, struct thread_detail *details, const char* state_str) { int64_t task = 0; int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width, (uint8_t *) &task); if (retval != ERROR_OK) return retval; details->threadid = (threadid_t) task; details->exists = true; details->display_str = NULL; int64_t name_ptr = 0; retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width, (uint8_t *) &name_ptr); if (retval != ERROR_OK) return retval; details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE); if (name_ptr) { retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, (uint8_t *) details->thread_name_str); if (retval != ERROR_OK) return retval; details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0; } else { snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task); } int64_t priority = 0; retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width, (uint8_t *) &priority); if (retval != ERROR_OK) return retval; details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE); if (task == rtos->current_thread) { snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running", (unsigned int) priority); } else { snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority, state_str); } LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable, (unsigned int)task, details->thread_name_str); return 0; } static int embKernel_update_threads(struct rtos *rtos) { /* int i = 0; */ int retval; const struct embKernel_params *param; if (rtos == NULL) return -1; if (rtos->rtos_specific_params == NULL) return -3; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for embKernel"); return -4; } if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) { LOG_ERROR("Don't have the thread list head"); return -2; } /* wipe out previous thread details if any */ rtos_free_threadlist(rtos); param = (const struct embKernel_params *) rtos->rtos_specific_params; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTask].address, param->pointer_width, (uint8_t *) &rtos->current_thread); if (retval != ERROR_OK) { LOG_ERROR("Error reading current thread in embKernel thread list"); return retval; } int64_t max_used_priority = 0; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sMaxPriorities].address, param->pointer_width, (uint8_t *) &max_used_priority); if (retval != ERROR_OK) return retval; int thread_list_size = 0; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTaskCount].address, param->thread_count_width, (uint8_t *) &thread_list_size); if (retval != ERROR_OK) { LOG_ERROR("Could not read embKernel thread count from target"); return retval; } /* create space for new thread details */ rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size); if (!rtos->thread_details) { LOG_ERROR("Error allocating memory for %d threads", thread_list_size); return ERROR_FAIL; } int threadIdx = 0; /* Look for ready tasks */ for (int pri = 0; pri < max_used_priority; pri++) { /* Get first item in queue */ int64_t iterable = 0; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; for (; iterable && threadIdx < thread_list_size; threadIdx++) { /* Get info from this iterable item */ retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready"); if (retval != ERROR_OK) return retval; /* Get next iterable item */ retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; } } /* Look for sleeping tasks */ int64_t iterable = 0; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSleep].address, param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; for (; iterable && threadIdx < thread_list_size; threadIdx++) { /*Get info from this iterable item */ retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping"); if (retval != ERROR_OK) return retval; /*Get next iterable item */ retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; } /* Look for suspended tasks */ iterable = 0; retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSuspended].address, param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; for (; iterable && threadIdx < thread_list_size; threadIdx++) { /* Get info from this iterable item */ retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended"); if (retval != ERROR_OK) return retval; /*Get next iterable item */ retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width, (uint8_t *) &iterable); if (retval != ERROR_OK) return retval; } rtos->thread_count = 0; rtos->thread_count = threadIdx; LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx); return 0; } static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { int retval; const struct embKernel_params *param; int64_t stack_ptr = 0; *hex_reg_list = NULL; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -1; param = (const struct embKernel_params *) rtos->rtos_specific_params; /* Read the stack pointer */ retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t *) &stack_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading stack frame from embKernel thread"); return retval; } return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); } static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(symbol_table_elem_t)); for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++) (*symbol_list)[i].symbol_name = embKernel_symbol_list[i]; return 0; } openocd-0.9.0/src/rtos/mqx.c0000644000175000017500000003766712516456303012647 00000000000000/*************************************************************************** * Copyright (C) 2014 by Marian Cingel * * cingel.marian@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "target/target.h" #include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_mqx_stackings.h" /* constants */ #define MQX_THREAD_NAME_LENGTH (255) #define MQX_KERNEL_OFFSET_TDLIST (0x0108) #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050) #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C) #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000) #define MQX_QUEUE_OFFSET_SIZE (0x0008) #define MQX_TASK_OFFSET_STATE (0x0008) #define MQX_TASK_OFFSET_ID (0x000c) #define MQX_TASK_OFFSET_TEMPLATE (0x0068) #define MQX_TASK_OFFSET_STACK (0x0014) #define MQX_TASK_OFFSET_TDLIST (0x006C) #define MQX_TASK_OFFSET_NEXT (0x0000) #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010) #define MQX_TASK_OFFSET_ERROR_CODE (0x005C) #define MQX_TASK_STATE_MASK (0xFFF) /* types */ enum mqx_symbols { mqx_VAL_mqx_kernel_data, mqx_VAL_MQX_init_struct, }; enum mqx_arch { mqx_arch_cortexm, }; struct mqx_params { const char *target_name; const enum mqx_arch target_arch; const struct rtos_register_stacking *stacking_info; }; struct mqx_state { uint32_t state; char *name; }; /* local data */ static const struct mqx_state mqx_states[] = { { 0x0002, "READY" }, { 0x0003, "BLOCKED" }, { 0x0005, "RCV_SPECIFIC_BLOCKED" }, { 0x0007, "RCV_ANY_BLOCKED" }, { 0x0009, "DYING" }, { 0x000B, "UNHANDLED_INT_BLOCKED" }, { 0x000D, "SEND_BLOCKED" }, { 0x000F, "BREAKPOINT_BLOCKED" }, { 0x0211, "IO_BLOCKED" }, { 0x0021, "SEM_BLOCKED" }, { 0x0223, "MUTEX_BLOCKED" }, { 0x0025, "EVENT_BLOCKED" }, { 0x0229, "TASK_QUEUE_BLOCKED" }, { 0x042B, "LWSEM_BLOCKED" }, { 0x042D, "LWEVENT_BLOCKED" }, }; static const char * const mqx_symbol_list[] = { "_mqx_kernel_data", "MQX_init_struct", NULL }; static const struct mqx_params mqx_params_list[] = { { "cortex_m", mqx_arch_cortexm, &rtos_mqx_arm_v7m_stacking }, }; /* * Perform simple address check to avoid bus fault. */ static int mqx_valid_address_check( struct rtos *rtos, uint32_t address ) { enum mqx_arch arch_type = ((struct mqx_params *)rtos->rtos_specific_params)->target_arch; const char * targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name; /* Cortex M address range */ if (arch_type == mqx_arch_cortexm) { if ( /* code and sram area */ (address && address <= 0x3FFFFFFFu) || /* external ram area*/ (address >= 0x6000000u && address <= 0x9FFFFFFFu) ) { return ERROR_OK; } return ERROR_FAIL; } LOG_ERROR("MQX RTOS - unknown architecture %s", targetname); return ERROR_FAIL; } /* * Wrapper of 'target_read_buffer' fn. * Include address check. */ static int mqx_target_read_buffer( struct target *target, uint32_t address, uint32_t size, uint8_t *buffer ) { int status = mqx_valid_address_check(target->rtos, address); if (status != ERROR_OK) { LOG_WARNING("MQX RTOS - target address 0x%" PRIx32 " is not allowed to read", address); return status; } status = target_read_buffer(target, address, size, buffer); if (status != ERROR_OK) { LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32" failed", address); return status; } return ERROR_OK; } /* * Get symbol address if present */ static int mqx_get_symbol( struct rtos *rtos, enum mqx_symbols symbol, void *result ) { /* TODO: additional check ?? */ (*(int *)result) = (uint32_t)rtos->symbols[symbol].address; return ERROR_OK; } /* * Get value of struct member by passing * member offset, width and name (debug purpose) */ static int mqx_get_member( struct rtos *rtos, const uint32_t base_address, int32_t member_offset, int32_t member_width, const char *member_name, void *result ) { int status = ERROR_FAIL; status = mqx_target_read_buffer( rtos->target, base_address + member_offset, member_width, result ); if (status != ERROR_OK) LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32, member_name, (uint32_t)(base_address + member_offset)); return status; } /* * Check whether scheduler started */ static int mqx_is_scheduler_running( struct rtos *rtos ) { uint32_t kernel_data_symbol = 0; uint32_t kernel_data_addr = 0; uint32_t system_td_addr = 0; uint32_t active_td_addr = 0; uint32_t capability_value = 0; /* get '_mqx_kernel_data' symbol */ if (ERROR_OK != mqx_get_symbol( rtos, mqx_VAL_mqx_kernel_data, &kernel_data_symbol )) { return ERROR_FAIL; } /* get '_mqx_kernel_data' */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_symbol, 0, 4, "_mqx_kernel_data", &kernel_data_addr )) { return ERROR_FAIL; } /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */ if (0 == kernel_data_addr || (uint32_t)(-1) == kernel_data_addr) return ERROR_FAIL; /* get kernel_data->ADDRESSING_CAPABILITY */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_addr, MQX_KERNEL_OFFSET_CAPABILITY, 4, "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value )) { return ERROR_FAIL; } /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'. it supose to be set to value 8 */ if (capability_value != 8) { LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value"); return ERROR_FAIL; } /* get active ptr */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4, "kernel_data->ACTIVE_PTR", (void *)&active_td_addr )) { return ERROR_FAIL; } /* active task is system task, scheduler has not not run yet */ system_td_addr = kernel_data_addr + MQX_KERNEL_OFFSET_SYSTEM_TASK; if (active_td_addr == system_td_addr) { LOG_WARNING("MQX RTOS - scheduler does not run"); return ERROR_FAIL; } return ERROR_OK; } /* * API function, return 1 if MQX is present */ static int mqx_detect_rtos( struct target *target ) { if ( (target->rtos->symbols != NULL) && (target->rtos->symbols[mqx_VAL_mqx_kernel_data].address != 0) ) { return 1; } return 0; } /* * API function, pass MQX extra info to context data */ static int mqx_create( struct target *target ) { /* check target name against supported architectures */ int mqx_params_list_num = (sizeof(mqx_params_list)/sizeof(struct mqx_params)); for (int i = 0; i < mqx_params_list_num; i++) { if (0 == strcmp(mqx_params_list[i].target_name, target->type->name)) { target->rtos->rtos_specific_params = (void *)&mqx_params_list[i]; /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */ return 0; } } LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target->type->name); return -1; } /* * API function, update list of threads */ static int mqx_update_threads( struct rtos *rtos ) { uint32_t task_queue_addr = 0; uint32_t kernel_data_addr = 0; uint16_t task_queue_size = 0; uint32_t active_td_addr = 0; if (!rtos->rtos_specific_params) return -3; if (!rtos->symbols) return -4; /* clear old data */ rtos_free_threadlist(rtos); /* check scheduler */ if (ERROR_OK != mqx_is_scheduler_running(rtos)) return ERROR_FAIL; /* get kernel_data symbol */ if (ERROR_OK != mqx_get_symbol( rtos, mqx_VAL_mqx_kernel_data, &kernel_data_addr )) { return ERROR_FAIL; } /* read kernel_data */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_addr, 0, 4, "_mqx_kernel_data", &kernel_data_addr )) { return ERROR_FAIL; } /* get task queue address */ task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST; /* get task queue size */ if (ERROR_OK != mqx_get_member( rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2, "kernel_data->TD_LIST.SIZE", &task_queue_size )) { return ERROR_FAIL; } /* get active ptr */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4, "kernel_data->ACTIVE_PTR", (void *)&active_td_addr )) { return ERROR_FAIL; } /* setup threads info */ rtos->thread_count = task_queue_size; rtos->current_thread = 0; rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail)); if (NULL == rtos->thread_details) return ERROR_FAIL; /* loop over each task and setup thread details, the current_taskpool_addr is set to queue head NOTE: debugging functions task create/destroy might cause to show invalid data. */ for ( uint32_t i = 0, taskpool_addr = task_queue_addr; i < (uint32_t)rtos->thread_count; i++ ) { uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1]; uint32_t task_addr = 0, task_template = 0, task_state = 0; uint32_t task_name_addr = 0, task_id = 0, task_errno = 0; uint32_t state_index = 0, state_max = 0; uint32_t extra_info_length = 0; char *state_name = "unknown state"; /* set current taskpool address */ if (ERROR_OK != mqx_get_member( rtos, taskpool_addr, MQX_TASK_OFFSET_NEXT, 4, "td_struct_ptr->NEXT", &taskpool_addr )) { return ERROR_FAIL; } /* get task address from taskpool */ task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST; /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */ if (ERROR_OK != mqx_get_member( rtos, task_addr, MQX_TASK_OFFSET_TEMPLATE, 4, "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template )) { return ERROR_FAIL; } /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */ if (ERROR_OK != mqx_get_member( rtos, task_template, MQX_TASK_TEMPLATE_OFFSET_NAME, 4, "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr )) { return ERROR_FAIL; } /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */ if (ERROR_OK != mqx_get_member( rtos, task_name_addr, 0, MQX_THREAD_NAME_LENGTH, "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name )) { return ERROR_FAIL; } /* always terminate last character by force, otherwise openocd might fail if task_name has corrupted data */ task_name[MQX_THREAD_NAME_LENGTH] = '\0'; /* get value of 'td_struct_ptr->TASK_ID' */ if (ERROR_OK != mqx_get_member( rtos, task_addr, MQX_TASK_OFFSET_ID, 4, "td_struct_ptr->TASK_ID", &task_id )) { return ERROR_FAIL; } /* get task errno */ if (ERROR_OK != mqx_get_member( rtos, task_addr, MQX_TASK_OFFSET_ERROR_CODE, 4, "td_struct_ptr->TASK_ERROR_CODE", &task_errno )) { return ERROR_FAIL; } /* get value of 'td_struct_ptr->STATE' */ if (ERROR_OK != mqx_get_member( rtos, task_addr, MQX_TASK_OFFSET_STATE, 4, "td_struct_ptr->STATE", &task_state )) { return ERROR_FAIL; } task_state &= MQX_TASK_STATE_MASK; /* and search for defined state */ state_max = (sizeof(mqx_states)/sizeof(struct mqx_state)); for (state_index = 0; (state_index < state_max); state_index++) { if (mqx_states[state_index].state == task_state) { state_name = mqx_states[state_index].name; break; } } /* setup thread details struct */ rtos->thread_details[i].threadid = task_id; rtos->thread_details[i].exists = true; rtos->thread_details[i].display_str = NULL; /* set thread name */ rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1); if (NULL == rtos->thread_details[i].thread_name_str) return ERROR_FAIL; strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name); /* set thread extra info * - task state * - task address * - task errno * calculate length as: * state length + address length + errno length + formatter length */ extra_info_length += strlen((void *)state_name) + 8 + 8 + 8; rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1); if (NULL == rtos->thread_details[i].extra_info_str) return ERROR_FAIL; snprintf( rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32, state_name, task_addr, task_errno ); /* set active thread */ if (active_td_addr == task_addr) rtos->current_thread = task_id; } return ERROR_OK; } /* * API function, get info of selected thread */ static int mqx_get_thread_reg_list( struct rtos *rtos, int64_t thread_id, char **hex_reg_list ) { int64_t stack_ptr = 0; uint32_t my_task_addr = 0; uint32_t task_queue_addr = 0; uint32_t task_queue_size = 0; uint32_t kernel_data_addr = 0; *hex_reg_list = NULL; if (thread_id == 0) { LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id); return ERROR_FAIL; } if (ERROR_OK != mqx_is_scheduler_running(rtos)) return ERROR_FAIL; /* get kernel_data symbol */ if (ERROR_OK != mqx_get_symbol( rtos, mqx_VAL_mqx_kernel_data, &kernel_data_addr )) { return ERROR_FAIL; } /* read kernel_data */ if (ERROR_OK != mqx_get_member( rtos, kernel_data_addr, 0, 4, "_mqx_kernel_data", &kernel_data_addr )) { return ERROR_FAIL; } /* get task queue address */ task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST; /* get task queue size */ if (ERROR_OK != mqx_get_member( rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2, "kernel_data->TD_LIST.SIZE", &task_queue_size )) { return ERROR_FAIL; } /* search for taskid */ for ( uint32_t i = 0, taskpool_addr = task_queue_addr; i < (uint32_t)rtos->thread_count; i++ ) { uint32_t tmp_address = 0, task_addr = 0; uint32_t task_id = 0; /* set current taskpool address */ tmp_address = taskpool_addr; if (ERROR_OK != mqx_get_member( rtos, tmp_address, MQX_TASK_OFFSET_NEXT, 4, "td_struct_ptr->NEXT", &taskpool_addr )) { return ERROR_FAIL; } /* get task address from taskpool */ task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST; /* get value of td_struct->TASK_ID */ if (ERROR_OK != mqx_get_member( rtos, task_addr, MQX_TASK_OFFSET_ID, 4, "td_struct_ptr->TASK_ID", &task_id )) { return ERROR_FAIL; } /* found taskid, break */ if (task_id == thread_id) { my_task_addr = task_addr; break; } } if (!my_task_addr) { LOG_ERROR("MQX_RTOS - threadid %" PRId64 " does not match any task", thread_id); return ERROR_FAIL; } /* get task stack head address */ if (ERROR_OK != mqx_get_member( rtos, my_task_addr, MQX_TASK_OFFSET_STACK, 4, "task->STACK_PTR", &stack_ptr )) { return ERROR_FAIL; } return rtos_generic_stack_read( rtos->target, ((struct mqx_params *)rtos->rtos_specific_params)->stacking_info, stack_ptr, hex_reg_list ); } /* API function, export list of required symbols */ static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { *symbol_list = malloc(sizeof(symbol_table_elem_t) * ARRAY_SIZE(mqx_symbol_list)); if (NULL == *symbol_list) return ERROR_FAIL; /* export required symbols */ for (int i = 0; i < (int)(ARRAY_SIZE(mqx_symbol_list)); i++) (*symbol_list)[i].symbol_name = mqx_symbol_list[i]; return ERROR_OK; } struct rtos_type mqx_rtos = { .name = "mqx", .detect_rtos = mqx_detect_rtos, .create = mqx_create, .update_threads = mqx_update_threads, .get_thread_reg_list = mqx_get_thread_reg_list, .get_symbol_list_to_lookup = mqx_get_symbol_list_to_lookup, }; openocd-0.9.0/src/rtos/linux.c0000644000175000017500000011752712516456303013173 00000000000000/*************************************************************************** * Copyright (C) 2011 by STEricsson * * Heythem Bouhaja heythem.bouhaja@stericsson.com : creation * * Michel JAOUEN michel.jaouen@stericsson.com : adaptation to rtos * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "helper/log.h" #include "helper/types.h" #include "rtos.h" #include "rtos_standard_stackings.h" #include #include "server/gdb_server.h" #define LINUX_USER_KERNEL_BORDER 0xc0000000 #include "linux_header.h" #define PHYS #define MAX_THREADS 200 /* specific task */ struct linux_os { const char *name; uint32_t init_task_addr; int thread_count; int threadid_count; int preupdtate_threadid_count; int nr_cpus; int threads_lookup; int threads_needs_update; struct current_thread *current_threads; struct threads *thread_list; /* virt2phys parameter */ uint32_t phys_mask; uint32_t phys_base; }; struct current_thread { int64_t threadid; int32_t core_id; #ifdef PID_CHECK uint32_t pid; #endif uint32_t TS; struct current_thread *next; }; struct threads { char name[17]; uint32_t base_addr; /* address to read magic */ uint32_t state; /* magic value : filled only at creation */ uint32_t pid; /* linux pid : id for identifying a thread */ uint32_t oncpu; /* content cpu number in current thread */ uint32_t asid; /* filled only at creation */ int64_t threadid; int status; /* dead = 1 alive = 2 current = 3 alive and current */ /* value that should not change during the live of a thread ? */ uint32_t thread_info_addr; /* contain latest thread_info_addr computed */ /* retrieve from thread_info */ struct cpu_context *context; struct threads *next; }; struct cpu_context { uint32_t R4; uint32_t R5; uint32_t R6; uint32_t R7; uint32_t R8; uint32_t R9; uint32_t IP; uint32_t FP; uint32_t SP; uint32_t PC; uint32_t preempt_count; }; struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr, uint32_t *info_addr); static int insert_into_threadlist(struct target *target, struct threads *t); static int linux_os_create(struct target *target); static int linux_os_dummy_update(struct rtos *rtos) { /* update is done only when thread request come * too many thread to do it on each stop */ return 0; } static int linux_compute_virt2phys(struct target *target, uint32_t address) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; uint32_t pa = 0; int retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) { LOG_ERROR("Cannot compute linux virt2phys translation"); /* fixes default address */ linux_os->phys_base = 0; return ERROR_FAIL; } linux_os->init_task_addr = address; address = address & linux_os->phys_mask; linux_os->phys_base = pa - address; return ERROR_OK; } static int linux_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { #ifdef PHYS struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; uint32_t pa = (address & linux_os->phys_mask) + linux_os->phys_base; #endif if (address < 0xc000000) { LOG_ERROR("linux awareness : address in user space"); return ERROR_FAIL; } #ifdef PHYS target_read_phys_memory(target, pa, size, count, buffer); #endif target_read_memory(target, address, size, count, buffer); return ERROR_OK; } static char *reg_converter(char *buffer, void *reg, int size) { int i; for (i = 0; i < size; i++) buffer += sprintf(buffer, "%02x", ((uint8_t *) reg)[i]); return buffer; } int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer) { if ((addr & 0xfffffffc) != addr) LOG_INFO("unaligned address %" PRIx32 "!!", addr); int retval = linux_read_memory(target, addr, 4, 1, buffer); return retval; } uint32_t get_buffer(struct target *target, const uint8_t *buffer) { uint32_t value = 0; const uint8_t *value_ptr = buffer; value = target_buffer_get_u32(target, value_ptr); return value; } static int linux_os_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { struct target *target = rtos->target; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; int i = 0; struct current_thread *tmp = linux_os->current_threads; struct current_thread *next; char *hex_string; int found = 0; int retval; /* check if a current thread is requested */ next = tmp; do { if (next->threadid == thread_id) found = 1; else next = next->next; } while ((found == 0) && (next != tmp) && (next != NULL)); if (found == 1) { /* search target to perfom the access */ struct reg **reg_list; int reg_list_size, reg_packet_size = 0; struct target_list *head; head = target->head; found = 0; do { if (head->target->coreid == next->core_id) { target = head->target; found = 1; } else head = head->next; } while ((head != (struct target_list *)NULL) && (found == 0)); if (found == 0) { LOG_ERROR ( "current thread %" PRIx64 ": no target to perform access of core id %" PRIx32, thread_id, next->core_id); return ERROR_FAIL; } /*LOG_INFO("thread %lx current on core %x",thread_id, * target->coreid);*/ retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_GENERAL); if (retval != ERROR_OK) return retval; for (i = 0; i < reg_list_size; i++) reg_packet_size += reg_list[i]->size; assert(reg_packet_size > 0); *hex_reg_list = malloc(DIV_ROUND_UP(reg_packet_size, 8) * 2); hex_string = *hex_reg_list; for (i = 0; i < reg_list_size; i++) { if (!reg_list[i]->valid) reg_list[i]->type->get(reg_list[i]); hex_string = reg_converter(hex_string, reg_list[i]->value, (reg_list[i]->size) / 8); } free(reg_list); } else { struct threads *temp = linux_os->thread_list; *hex_reg_list = calloc(1, 500 * sizeof(char)); hex_string = *hex_reg_list; for (i = 0; i < 16; i++) hex_string += sprintf(hex_string, "%02x", 0); while ((temp != NULL) && (temp->threadid != target->rtos->current_threadid)) temp = temp->next; if (temp != NULL) { if (temp->context == NULL) temp->context = cpu_context_read(target, temp-> base_addr, &temp-> thread_info_addr); hex_string = reg_converter(hex_string, &temp->context->R4, 4); hex_string = reg_converter(hex_string, &temp->context->R5, 4); hex_string = reg_converter(hex_string, &temp->context->R6, 4); hex_string = reg_converter(hex_string, &temp->context->R7, 4); hex_string = reg_converter(hex_string, &temp->context->R8, 4); hex_string = reg_converter(hex_string, &temp->context->R9, 4); for (i = 0; i < 4; i++) /*R10 = 0x0 */ hex_string += sprintf(hex_string, "%02x", 0); hex_string = reg_converter(hex_string, &temp->context->FP, 4); hex_string = reg_converter(hex_string, &temp->context->IP, 4); hex_string = reg_converter(hex_string, &temp->context->SP, 4); for (i = 0; i < 4; i++) hex_string += sprintf(hex_string, "%02x", 0); hex_string = reg_converter(hex_string, &temp->context->PC, 4); for (i = 0; i < 100; i++) /*100 */ hex_string += sprintf(hex_string, "%02x", 0); uint32_t cpsr = 0x00000000; reg_converter(hex_string, &cpsr, 4); } } return ERROR_OK; } static int linux_os_detect(struct target *target) { LOG_INFO("should no be called"); return 0; } static int linux_os_smp_init(struct target *target); static int linux_os_clean(struct target *target); #define INIT_TASK 0 static const char * const linux_symbol_list[] = { "init_task", NULL }; static int linux_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = (symbol_table_elem_t *) calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t)); for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++) (*symbol_list)[i].symbol_name = linux_symbol_list[i]; return 0; } static char *linux_ps_command(struct target *target); const struct rtos_type Linux_os = { .name = "linux", .detect_rtos = linux_os_detect, .create = linux_os_create, .smp_init = linux_os_smp_init, .update_threads = linux_os_dummy_update, .get_thread_reg_list = linux_os_thread_reg_list, .get_symbol_list_to_lookup = linux_get_symbol_list_to_lookup, .clean = linux_os_clean, .ps_command = linux_ps_command, }; static int linux_thread_packet(struct connection *connection, char const *packet, int packet_size); static void linux_identify_current_threads(struct target *target); #ifdef PID_CHECK int fill_task_pid(struct target *target, struct threads *t) { uint32_t pid_addr = t->base_addr + PID; uint8_t buffer[4]; int retval = fill_buffer(target, pid_addr, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); t->pid = val; } else LOG_ERROR("fill_task_pid: unable to read memory"); return retval; } #endif int fill_task(struct target *target, struct threads *t) { int retval; uint32_t pid_addr = t->base_addr + PID; uint32_t mem_addr = t->base_addr + MEM; uint32_t on_cpu = t->base_addr + ONCPU; uint8_t *buffer = calloc(1, 4); retval = fill_buffer(target, t->base_addr, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); t->state = val; } else LOG_ERROR("fill_task: unable to read memory"); retval = fill_buffer(target, pid_addr, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); t->pid = val; } else LOG_ERROR("fill task: unable to read memory"); retval = fill_buffer(target, on_cpu, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); t->oncpu = val; } else LOG_ERROR("fill task: unable to read memory"); retval = fill_buffer(target, mem_addr, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); if (val != 0) { uint32_t asid_addr = val + MM_CTX; retval = fill_buffer(target, asid_addr, buffer); if (retval == ERROR_OK) { val = get_buffer(target, buffer); t->asid = val; } else LOG_ERROR ("fill task: unable to read memory -- ASID"); } else t->asid = 0; } else LOG_ERROR("fill task: unable to read memory"); free(buffer); return retval; } int get_name(struct target *target, struct threads *t) { int retval; uint32_t full_name[4]; uint32_t comm = t->base_addr + COMM; int i; for (i = 0; i < 17; i++) t->name[i] = 0; retval = linux_read_memory(target, comm, 4, 4, (uint8_t *) full_name); if (retval != ERROR_OK) { LOG_ERROR("get_name: unable to read memory\n"); return ERROR_FAIL; } uint32_t raw_name = target_buffer_get_u32(target, (const uint8_t *) &full_name[0]); t->name[3] = raw_name >> 24; t->name[2] = raw_name >> 16; t->name[1] = raw_name >> 8; t->name[0] = raw_name; raw_name = target_buffer_get_u32(target, (const uint8_t *)&full_name[1]); t->name[7] = raw_name >> 24; t->name[6] = raw_name >> 16; t->name[5] = raw_name >> 8; t->name[4] = raw_name; raw_name = target_buffer_get_u32(target, (const uint8_t *)&full_name[2]); t->name[11] = raw_name >> 24; t->name[10] = raw_name >> 16; t->name[9] = raw_name >> 8; t->name[8] = raw_name; raw_name = target_buffer_get_u32(target, (const uint8_t *)&full_name[3]); t->name[15] = raw_name >> 24; t->name[14] = raw_name >> 16; t->name[13] = raw_name >> 8; t->name[12] = raw_name; return ERROR_OK; } int get_current(struct target *target, int create) { struct target_list *head; head = target->head; uint8_t *buf; uint32_t val; uint32_t ti_addr; uint8_t *buffer = calloc(1, 4); struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct current_thread *ctt = linux_os->current_threads; /* invalid current threads content */ while (ctt != NULL) { ctt->threadid = -1; ctt->TS = 0xdeadbeef; ctt = ctt->next; } while (head != (struct target_list *)NULL) { struct reg **reg_list; int reg_list_size; int retval; if (target_get_gdb_reg_list(head->target, ®_list, ®_list_size, REG_CLASS_GENERAL) != ERROR_OK) { free(buffer); return ERROR_TARGET_FAILURE; } if (!reg_list[13]->valid) reg_list[13]->type->get(reg_list[13]); buf = reg_list[13]->value; val = get_buffer(target, buf); ti_addr = (val & 0xffffe000); uint32_t TS_addr = ti_addr + 0xc; retval = fill_buffer(target, TS_addr, buffer); if (retval == ERROR_OK) { uint32_t TS = get_buffer(target, buffer); uint32_t cpu, on_cpu = TS + ONCPU; retval = fill_buffer(target, on_cpu, buffer); if (retval == ERROR_OK) { /*uint32_t cpu = get_buffer(target, buffer);*/ struct current_thread *ct = linux_os->current_threads; cpu = head->target->coreid; while ((ct != NULL) && (ct->core_id != (int32_t) cpu)) ct = ct->next; if ((ct != NULL) && (ct->TS == 0xdeadbeef)) ct->TS = TS; else LOG_ERROR ("error in linux current thread update"); if (create && ct) { struct threads *t; t = calloc(1, sizeof(struct threads)); t->base_addr = ct->TS; fill_task(target, t); get_name(target, t); t->oncpu = cpu; insert_into_threadlist(target, t); t->status = 3; t->thread_info_addr = 0xdeadbeef; ct->threadid = t->threadid; linux_os->thread_count++; #ifdef PID_CHECK ct->pid = t->pid; #endif /*LOG_INFO("Creation of current thread %s",t->name);*/ } } } free(reg_list); head = head->next; } free(buffer); return ERROR_OK; } struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr, uint32_t *thread_info_addr_old) { struct cpu_context *context = calloc(1, sizeof(struct cpu_context)); uint32_t preempt_count_addr = 0; uint32_t registers[10]; uint8_t *buffer = calloc(1, 4); uint32_t stack = base_addr + QAT; uint32_t thread_info_addr = 0; uint32_t thread_info_addr_update = 0; int retval = ERROR_FAIL; context->R4 = 0xdeadbeef; context->R5 = 0xdeadbeef; context->R6 = 0xdeadbeef; context->R7 = 0xdeadbeef; context->R8 = 0xdeadbeef; context->R9 = 0xdeadbeef; context->IP = 0xdeadbeef; context->FP = 0xdeadbeef; context->SP = 0xdeadbeef; context->PC = 0xdeadbeef; retry: if (*thread_info_addr_old == 0xdeadbeef) { retval = fill_buffer(target, stack, buffer); if (retval == ERROR_OK) thread_info_addr = get_buffer(target, buffer); else LOG_ERROR("cpu_context: unable to read memory"); thread_info_addr_update = thread_info_addr; } else thread_info_addr = *thread_info_addr_old; preempt_count_addr = thread_info_addr + PREEMPT; retval = fill_buffer(target, preempt_count_addr, buffer); if (retval == ERROR_OK) context->preempt_count = get_buffer(target, buffer); else { if (*thread_info_addr_old != 0xdeadbeef) { LOG_ERROR ("cpu_context: cannot read at thread_info_addr"); if (*thread_info_addr_old < LINUX_USER_KERNEL_BORDER) LOG_INFO ("cpu_context : thread_info_addr in userspace!!!"); *thread_info_addr_old = 0xdeadbeef; goto retry; } LOG_ERROR("cpu_context: unable to read memory"); } thread_info_addr += CPU_CONT; retval = linux_read_memory(target, thread_info_addr, 4, 10, (uint8_t *) registers); if (retval != ERROR_OK) { free(buffer); LOG_ERROR("cpu_context: unable to read memory\n"); return context; } context->R4 = target_buffer_get_u32(target, (const uint8_t *)®isters[0]); context->R5 = target_buffer_get_u32(target, (const uint8_t *)®isters[1]); context->R6 = target_buffer_get_u32(target, (const uint8_t *)®isters[2]); context->R7 = target_buffer_get_u32(target, (const uint8_t *)®isters[3]); context->R8 = target_buffer_get_u32(target, (const uint8_t *)®isters[4]); context->R9 = target_buffer_get_u32(target, (const uint8_t *)®isters[5]); context->IP = target_buffer_get_u32(target, (const uint8_t *)®isters[6]); context->FP = target_buffer_get_u32(target, (const uint8_t *)®isters[7]); context->SP = target_buffer_get_u32(target, (const uint8_t *)®isters[8]); context->PC = target_buffer_get_u32(target, (const uint8_t *)®isters[9]); if (*thread_info_addr_old == 0xdeadbeef) *thread_info_addr_old = thread_info_addr_update; free(buffer); return context; } uint32_t next_task(struct target *target, struct threads *t) { uint8_t *buffer = calloc(1, 4); uint32_t next_addr = t->base_addr + NEXT; int retval = fill_buffer(target, next_addr, buffer); if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); val = val - NEXT; free(buffer); return val; } else LOG_ERROR("next task: unable to read memory"); free(buffer); return 0; } struct current_thread *add_current_thread(struct current_thread *currents, struct current_thread *ct) { ct->next = NULL; if (currents == NULL) { currents = ct; return currents; } else { struct current_thread *temp = currents; while (temp->next != NULL) temp = temp->next; temp->next = ct; return currents; } } struct threads *liste_del_task(struct threads *task_list, struct threads **t, struct threads *prev) { LOG_INFO("del task %" PRId64, (*t)->threadid); prev->next = (*t)->next; if (prev == task_list) task_list = prev; /* free content of threads */ if ((*t)->context) free((*t)->context); free(*t); *t = prev; return task_list; } struct threads *liste_add_task(struct threads *task_list, struct threads *t, struct threads **last) { t->next = NULL; if (*last == NULL) if (task_list == NULL) { task_list = t; return task_list; } else { struct threads *temp = task_list; while (temp->next != NULL) temp = temp->next; temp->next = t; *last = t; return task_list; } else { (*last)->next = t; *last = t; return task_list; } } #ifdef PID_CHECK static int current_pid(struct linux_os *linux_os, uint32_t pid) #else static int current_base_addr(struct linux_os *linux_os, uint32_t base_addr) #endif { struct current_thread *ct = linux_os->current_threads; #ifdef PID_CHECK while ((ct != NULL) && (ct->pid != pid)) #else while ((ct != NULL) && (ct->TS != base_addr)) #endif ct = ct->next; #ifdef PID_CHECK if ((ct != NULL) && (ct->pid == pid)) #else if ((ct != NULL) && (ct->TS == base_addr)) #endif return 1; return 0; } int linux_get_tasks(struct target *target, int context) { int loop = 0; int retval = 0; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; linux_os->thread_list = NULL; linux_os->thread_count = 0; if (linux_os->init_task_addr == 0xdeadbeef) { LOG_INFO("no init symbol\n"); return ERROR_FAIL; } int64_t start = timeval_ms(); struct threads *t = calloc(1, sizeof(struct threads)); struct threads *last = NULL; t->base_addr = linux_os->init_task_addr; /* retrieve the thread id , currently running in the different smp core */ get_current(target, 1); while (((t->base_addr != linux_os->init_task_addr) && (t->base_addr != 0)) || (loop == 0)) { loop++; fill_task(target, t); retval = get_name(target, t); if (loop > MAX_THREADS) { free(t); LOG_INFO("more than %d threads !!", MAX_THREADS); return ERROR_FAIL; } if (retval != ERROR_OK) { free(t); return ERROR_FAIL; } /* check that this thread is not one the current threads already * created */ #ifdef PID_CHECK if (!current_pid(linux_os, t->pid)) { #else if (!current_base_addr(linux_os, t->base_addr)) { #endif t->threadid = linux_os->threadid_count; t->status = 1; linux_os->threadid_count++; linux_os->thread_list = liste_add_task(linux_os->thread_list, t, &last); /* no interest to fill the context if it is a current thread. */ linux_os->thread_count++; t->thread_info_addr = 0xdeadbeef; if (context) t->context = cpu_context_read(target, t->base_addr, &t->thread_info_addr); } else { /*LOG_INFO("thread %s is a current thread already created",t->name); */ free(t); } uint32_t base_addr = next_task(target, t); t = calloc(1, sizeof(struct threads)); t->base_addr = base_addr; } linux_os->threads_lookup = 1; linux_os->threads_needs_update = 0; linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1; /* check that all current threads have been identified */ LOG_INFO("complete time %" PRId64 ", thread mean %" PRId64 "\n", (timeval_ms() - start), (timeval_ms() - start) / linux_os->threadid_count); LOG_INFO("threadid count %d", linux_os->threadid_count); free(t); return ERROR_OK; } static int clean_threadlist(struct target *target) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct threads *old, *temp = linux_os->thread_list; while (temp != NULL) { old = temp; if (temp->context) free(temp->context); temp = temp->next; free(old); } return ERROR_OK; } static int linux_os_clean(struct target *target) { struct linux_os *os_linux = (struct linux_os *) target->rtos->rtos_specific_params; clean_threadlist(target); os_linux->init_task_addr = 0xdeadbeef; os_linux->name = "linux"; os_linux->thread_list = NULL; os_linux->thread_count = 0; os_linux->nr_cpus = 0; os_linux->threads_lookup = 0; os_linux->threads_needs_update = 0; os_linux->threadid_count = 1; return ERROR_OK; } static int insert_into_threadlist(struct target *target, struct threads *t) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct threads *temp = linux_os->thread_list; t->threadid = linux_os->threadid_count; linux_os->threadid_count++; t->status = 1; t->next = NULL; if (temp == NULL) linux_os->thread_list = t; else { while (temp->next != NULL) temp = temp->next; t->next = NULL; temp->next = t; } return ERROR_OK; } static void linux_identify_current_threads(struct target *target) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct threads *thread_list = linux_os->thread_list; struct current_thread *ct = linux_os->current_threads; struct threads *t = NULL; while ((ct != NULL)) { if (ct->threadid == -1) { /* un-identified thread */ int found = 0; t = calloc(1, sizeof(struct threads)); t->base_addr = ct->TS; #ifdef PID_CHECK if (fill_task_pid(target, t) != ERROR_OK) { error_handling: free(t); LOG_ERROR ("linux identify_current_threads: unable to read pid"); return; } #endif /* search in the list of threads if pid already present */ while ((thread_list != NULL) && (found == 0)) { #ifdef PID_CHECK if (thread_list->pid == t->pid) { #else if (thread_list->base_addr == t->base_addr) { #endif free(t); t = thread_list; found = 1; } thread_list = thread_list->next; } if (!found) { /* it is a new thread */ if (fill_task(target, t) != ERROR_OK) goto error_handling; get_name(target, t); insert_into_threadlist(target, t); t->thread_info_addr = 0xdeadbeef; } t->status = 3; ct->threadid = t->threadid; #ifdef PID_CHECK ct->pid = t->pid; #endif linux_os->thread_count++; #if 0 if (found == 0) LOG_INFO("current thread core %x identified %s", ct->core_id, t->name); else LOG_INFO("current thread core %x, reused %s", ct->core_id, t->name); #endif } #if 0 else { struct threads tmp; tmp.base_addr = ct->TS; get_name(target, &tmp); LOG_INFO("current thread core %x , already identified %s !!!", ct->core_id, tmp.name); } #endif ct = ct->next; } return; #ifndef PID_CHECK error_handling: free(t); LOG_ERROR("unable to read pid"); return; #endif } static int linux_task_update(struct target *target, int context) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct threads *thread_list = linux_os->thread_list; int retval; int loop = 0; linux_os->thread_count = 0; /*thread_list = thread_list->next; skip init_task*/ while (thread_list != NULL) { thread_list->status = 0; /*setting all tasks to dead state*/ if (thread_list->context) { free(thread_list->context); thread_list->context = NULL; } thread_list = thread_list->next; } int found = 0; if (linux_os->init_task_addr == 0xdeadbeef) { LOG_INFO("no init symbol\n"); return ERROR_FAIL; } int64_t start = timeval_ms(); struct threads *t = calloc(1, sizeof(struct threads)); uint32_t previous = 0xdeadbeef; t->base_addr = linux_os->init_task_addr; retval = get_current(target, 0); /*check that all current threads have been identified */ linux_identify_current_threads(target); while (((t->base_addr != linux_os->init_task_addr) && (t->base_addr != previous)) || (loop == 0)) { /* for avoiding any permanent loop for any reason possibly due to * target */ loop++; previous = t->base_addr; /* read only pid */ #ifdef PID_CHECK retval = fill_task_pid(target, t); #endif if (retval != ERROR_OK) { free(t); return ERROR_FAIL; } thread_list = linux_os->thread_list; while (thread_list != NULL) { #ifdef PID_CHECK if (t->pid == thread_list->pid) { #else if (t->base_addr == thread_list->base_addr) { #endif if (!thread_list->status) { #ifdef PID_CHECK if (t->base_addr != thread_list->base_addr) LOG_INFO("thread base_addr has changed !!"); #endif /* this is not a current thread */ thread_list->base_addr = t->base_addr; thread_list->status = 1; /* we don 't update this field any more */ /*thread_list->state = t->state; thread_list->oncpu = t->oncpu; thread_list->asid = t->asid; */ if (context) thread_list->context = cpu_context_read(target, thread_list-> base_addr, &thread_list-> thread_info_addr); } else { /* it is a current thread no need to read context */ } linux_os->thread_count++; found = 1; break; } else { found = 0; thread_list = thread_list->next; } } if (found == 0) { uint32_t base_addr; fill_task(target, t); get_name(target, t); retval = insert_into_threadlist(target, t); t->thread_info_addr = 0xdeadbeef; if (context) t->context = cpu_context_read(target, t->base_addr, &t->thread_info_addr); base_addr = next_task(target, t); t = calloc(1, sizeof(struct threads)); t->base_addr = base_addr; linux_os->thread_count++; } else t->base_addr = next_task(target, t); } LOG_INFO("update thread done %" PRId64 ", mean%" PRId64 "\n", (timeval_ms() - start), (timeval_ms() - start) / loop); free(t); linux_os->threads_needs_update = 0; return ERROR_OK; } int linux_gdb_thread_packet(struct target *target, struct connection *connection, char const *packet, int packet_size) { int retval; struct linux_os *linux_os = (struct linux_os *)target->rtos->rtos_specific_params; if (linux_os->init_task_addr == 0xdeadbeef) { /* it has not been initialized */ LOG_INFO("received thread request without init task address"); gdb_put_packet(connection, "l", 1); return ERROR_OK; } retval = linux_get_tasks(target, 1); if (retval != ERROR_OK) return ERROR_TARGET_FAILURE; char *out_str = calloc(1, 350 * sizeof(int64_t)); char *tmp_str = out_str; tmp_str += sprintf(tmp_str, "m"); struct threads *temp = linux_os->thread_list; while (temp != NULL) { tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid); temp = temp->next; if (temp) tmp_str += sprintf(tmp_str, ","); } gdb_put_packet(connection, out_str, strlen(out_str)); free(out_str); return ERROR_OK; } int linux_gdb_thread_update(struct target *target, struct connection *connection, char const *packet, int packet_size) { int found = 0; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct threads *temp = linux_os->thread_list; while (temp != NULL) { if (temp->threadid == linux_os->preupdtate_threadid_count + 1) { /*LOG_INFO("FOUND");*/ found = 1; break; } else temp = temp->next; } if (found == 1) { /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/ char *out_strr = calloc(1, 350 * sizeof(int64_t)); char *tmp_strr = out_strr; tmp_strr += sprintf(tmp_strr, "m"); /*LOG_INFO("CHAR MALLOC & M DONE");*/ tmp_strr += sprintf(tmp_strr, "%016" PRIx64, temp->threadid); temp = temp->next; while (temp != NULL) { /*LOG_INFO("INTO GDB THREAD UPDATE WHILE");*/ tmp_strr += sprintf(tmp_strr, ","); tmp_strr += sprintf(tmp_strr, "%016" PRIx64, temp->threadid); temp = temp->next; } /*tmp_str[0] = 0;*/ gdb_put_packet(connection, out_strr, strlen(out_strr)); linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1; free(out_strr); } else gdb_put_packet(connection, "l", 1); return ERROR_OK; } int linux_thread_extra_info(struct target *target, struct connection *connection, char const *packet, int packet_size) { int64_t threadid = 0; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid); /*LOG_INFO("lookup extra info for thread %" SCNx64, threadid);*/ struct threads *temp = linux_os->thread_list; while (temp != NULL) { if (temp->threadid == threadid) { char *pid = " PID: "; char *pid_current = "*PID: "; char *name = "NAME: "; int str_size = strlen(pid) + strlen(name); char *tmp_str = calloc(1, str_size + 50); char *tmp_str_ptr = tmp_str; /* discriminate current task */ if (temp->status == 3) tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid_current); else tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); tmp_str_ptr += sprintf(tmp_str_ptr, "%d", (int)temp->pid); tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | "); sprintf(tmp_str_ptr, "%s", name); sprintf(tmp_str_ptr, "%s", temp->name); char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); return ERROR_OK; } temp = temp->next; } LOG_INFO("thread not found"); return ERROR_OK; } int linux_gdb_T_packet(struct connection *connection, struct target *target, char const *packet, int packet_size) { int64_t threadid; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; int retval = ERROR_OK; sscanf(packet, "T%" SCNx64, &threadid); if (linux_os->threads_needs_update == 0) { struct threads *temp = linux_os->thread_list; struct threads *prev = linux_os->thread_list; while (temp != NULL) { if (temp->threadid == threadid) { if (temp->status != 0) { gdb_put_packet(connection, "OK", 2); return ERROR_OK; } else { /* delete item in the list */ linux_os->thread_list = liste_del_task(linux_os-> thread_list, &temp, prev); linux_os->thread_count--; gdb_put_packet(connection, "E01", 3); return ERROR_OK; } } /* for deletion */ prev = temp; temp = temp->next; } LOG_INFO("gdb requested status on non existing thread"); gdb_put_packet(connection, "E01", 3); return ERROR_OK; } else { retval = linux_task_update(target, 1); struct threads *temp = linux_os->thread_list; while (temp != NULL) { if (temp->threadid == threadid) { if (temp->status == 1) { gdb_put_packet(connection, "OK", 2); return ERROR_OK; } else { gdb_put_packet(connection, "E01", 3); return ERROR_OK; } } temp = temp->next; } } return retval; } int linux_gdb_h_packet(struct connection *connection, struct target *target, char const *packet, int packet_size) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct current_thread *ct = linux_os->current_threads; /* select to display the current thread of the selected target */ while ((ct != NULL) && (ct->core_id != target->coreid)) ct = ct->next; int64_t current_gdb_thread_rq; if (linux_os->threads_lookup == 1) { if ((ct != NULL) && (ct->threadid == -1)) { ct = linux_os->current_threads; while ((ct != NULL) && (ct->threadid == -1)) ct = ct->next; } if (ct == NULL) { /* no current thread can be identified * any way with smp */ LOG_INFO("no current thread identified"); /* attempt to display the name of the 2 threads identified with * get_current */ struct threads t; ct = linux_os->current_threads; while ((ct != NULL) && (ct->threadid == -1)) { t.base_addr = ct->TS; get_name(target, &t); LOG_INFO("name of unidentified thread %s", t.name); ct = ct->next; } gdb_put_packet(connection, "OK", 2); return ERROR_OK; } if (packet[1] == 'g') { sscanf(packet, "Hg%16" SCNx64, ¤t_gdb_thread_rq); if (current_gdb_thread_rq == 0) { target->rtos->current_threadid = ct->threadid; gdb_put_packet(connection, "OK", 2); } else { target->rtos->current_threadid = current_gdb_thread_rq; gdb_put_packet(connection, "OK", 2); } } else if (packet[1] == 'c') { sscanf(packet, "Hc%16" SCNx64, ¤t_gdb_thread_rq); if ((current_gdb_thread_rq == 0) || (current_gdb_thread_rq == ct->threadid)) { target->rtos->current_threadid = ct->threadid; gdb_put_packet(connection, "OK", 2); } else gdb_put_packet(connection, "E01", 3); } } else gdb_put_packet(connection, "OK", 2); return ERROR_OK; } static int linux_thread_packet(struct connection *connection, char const *packet, int packet_size) { int retval = ERROR_OK; struct current_thread *ct; struct target *target = get_target_from_connection(connection); struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; switch (packet[0]) { case 'T': /* Is thread alive?*/ linux_gdb_T_packet(connection, target, packet, packet_size); break; case 'H': /* Set current thread */ /* ( 'c' for step and continue, 'g' for all other operations )*/ /*LOG_INFO(" H packet received '%s'", packet);*/ linux_gdb_h_packet(connection, target, packet, packet_size); break; case 'q': if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { linux_compute_virt2phys(target, target->rtos-> symbols[INIT_TASK]. address); } break; } else if (strncmp(packet, "qfThreadInfo", 12) == 0) { if (linux_os->thread_list == NULL) { retval = linux_gdb_thread_packet(target, connection, packet, packet_size); break; } else { retval = linux_gdb_thread_update(target, connection, packet, packet_size); break; } } else if (strncmp(packet, "qsThreadInfo", 12) == 0) { gdb_put_packet(connection, "l", 1); break; } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) { linux_thread_extra_info(target, connection, packet, packet_size); break; } else { retval = GDB_THREAD_PACKET_NOT_CONSUMED; break; } case 'Q': /* previously response was : thread not found * gdb_put_packet(connection, "E01", 3); */ retval = GDB_THREAD_PACKET_NOT_CONSUMED; break; case 'c': case 's': { if (linux_os->threads_lookup == 1) { ct = linux_os->current_threads; while ((ct != NULL) && (ct->core_id) != target->coreid) ct = ct->next; if ((ct != NULL) && (ct->threadid == -1)) { ct = linux_os->current_threads; while ((ct != NULL) && (ct->threadid == -1)) ct = ct->next; } if ((ct != NULL) && (ct->threadid != target->rtos-> current_threadid) && (target->rtos->current_threadid != -1)) LOG_WARNING("WARNING! current GDB thread do not match" \ "current thread running." \ "Switch thread in GDB to threadid %d", (int)ct->threadid); LOG_INFO("threads_needs_update = 1"); linux_os->threads_needs_update = 1; } } /* if a packet handler returned an error, exit input loop */ if (retval != ERROR_OK) return retval; } return retval; } static int linux_os_smp_init(struct target *target) { struct target_list *head; /* keep only target->rtos */ struct rtos *rtos = target->rtos; struct linux_os *os_linux = (struct linux_os *)rtos->rtos_specific_params; struct current_thread *ct; head = target->head; while (head != (struct target_list *)NULL) { if (head->target->rtos != rtos) { struct linux_os *smp_os_linux = (struct linux_os *)head->target->rtos-> rtos_specific_params; /* remap smp target on rtos */ free(head->target->rtos); head->target->rtos = rtos; /* reuse allocated ct */ ct = smp_os_linux->current_threads; ct->threadid = -1; ct->TS = 0xdeadbeef; ct->core_id = head->target->coreid; os_linux->current_threads = add_current_thread(os_linux->current_threads, ct); os_linux->nr_cpus++; free(smp_os_linux); } head = head->next; } return ERROR_OK; } static int linux_os_create(struct target *target) { struct linux_os *os_linux = calloc(1, sizeof(struct linux_os)); struct current_thread *ct = calloc(1, sizeof(struct current_thread)); LOG_INFO("linux os creation\n"); os_linux->init_task_addr = 0xdeadbeef; os_linux->name = "linux"; os_linux->thread_list = NULL; os_linux->thread_count = 0; target->rtos->current_threadid = -1; os_linux->nr_cpus = 1; os_linux->threads_lookup = 0; os_linux->threads_needs_update = 0; os_linux->threadid_count = 1; os_linux->current_threads = NULL; target->rtos->rtos_specific_params = os_linux; ct->core_id = target->coreid; ct->threadid = -1; ct->TS = 0xdeadbeef; os_linux->current_threads = add_current_thread(os_linux->current_threads, ct); /* overload rtos thread default handler */ target->rtos->gdb_thread_packet = linux_thread_packet; /* initialize a default virt 2 phys translation */ os_linux->phys_mask = ~0xc0000000; os_linux->phys_base = 0x0; return JIM_OK; } static char *linux_ps_command(struct target *target) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; int retval = ERROR_OK; char *display; if (linux_os->threads_lookup == 0) retval = linux_get_tasks(target, 1); else { if (linux_os->threads_needs_update != 0) retval = linux_task_update(target, 0); } if (retval == ERROR_OK) { struct threads *temp = linux_os->thread_list; char *tmp; LOG_INFO("allocation for %d threads line", linux_os->thread_count); display = calloc((linux_os->thread_count + 2) * 80, 1); if (!display) goto error; tmp = display; tmp += sprintf(tmp, "PID\t\tCPU\t\tASID\t\tNAME\n"); tmp += sprintf(tmp, "---\t\t---\t\t----\t\t----\n"); while (temp != NULL) { if (temp->status) { if (temp->context) tmp += sprintf(tmp, "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n", temp->pid, temp->oncpu, temp->asid, temp->name); else tmp += sprintf(tmp, "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n", temp->pid, temp->oncpu, temp->asid, temp->name); } temp = temp->next; } return display; } error: display = calloc(40, 1); sprintf(display, "linux_ps_command failed\n"); return display; } openocd-0.9.0/src/rtos/rtos_chibios_stackings.c0000644000175000017500000000672612516456303016567 00000000000000/*************************************************************************** * Copyright (C) 2012 by Matthias Blaicher * * Matthias Blaicher - matthias@blaicher.com * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/armv7m.h" static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { -1, 32 }, /* r0 */ { -1, 32 }, /* r1 */ { -1, 32 }, /* r2 */ { -1, 32 }, /* r3 */ { 0x00, 32 }, /* r4 */ { 0x04, 32 }, /* r5 */ { 0x08, 32 }, /* r6 */ { 0x0c, 32 }, /* r7 */ { 0x10, 32 }, /* r8 */ { 0x14, 32 }, /* r9 */ { 0x18, 32 }, /* r10 */ { 0x1c, 32 }, /* r11 */ { -1, 32 }, /* r12 */ { -2, 32 }, /* sp */ { -1, 32 }, /* lr */ { 0x20, 32 }, /* pc */ { -1, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking = { 0x24, /* stack_registers_size */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 0, /* stack_alignment */ rtos_chibios_arm_v7m_stack_offsets /* register_offsets */ }; static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets_w_fpu[ARMV7M_NUM_CORE_REGS] = { { -1, 32 }, /* r0 */ { -1, 32 }, /* r1 */ { -1, 32 }, /* r2 */ { -1, 32 }, /* r3 */ { 0x40, 32 }, /* r4 */ { 0x44, 32 }, /* r5 */ { 0x48, 32 }, /* r6 */ { 0x4c, 32 }, /* r7 */ { 0x50, 32 }, /* r8 */ { 0x54, 32 }, /* r9 */ { 0x58, 32 }, /* r10 */ { 0x5c, 32 }, /* r11 */ { -1, 32 }, /* r12 */ { -2, 32 }, /* sp */ { -1, 32 }, /* lr */ { 0x60, 32 }, /* pc */ { -1, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu = { 0x64, /* stack_registers_size */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 0, /* stack_alignment */ rtos_chibios_arm_v7m_stack_offsets_w_fpu /* register_offsets */ }; openocd-0.9.0/src/rtos/rtos_chibios_stackings.h0000644000175000017500000000344612516456303016570 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ #define INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking; extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu; #endif /* ifndef INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ */ openocd-0.9.0/src/rtos/rtos_standard_stackings.c0000644000175000017500000001141512315575361016741 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/armv7m.h" static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { 0x20, 32 }, /* r0 */ { 0x24, 32 }, /* r1 */ { 0x28, 32 }, /* r2 */ { 0x2c, 32 }, /* r3 */ { 0x00, 32 }, /* r4 */ { 0x04, 32 }, /* r5 */ { 0x08, 32 }, /* r6 */ { 0x0c, 32 }, /* r7 */ { 0x10, 32 }, /* r8 */ { 0x14, 32 }, /* r9 */ { 0x18, 32 }, /* r10 */ { 0x1c, 32 }, /* r11 */ { 0x30, 32 }, /* r12 */ { -2, 32 }, /* sp */ { 0x34, 32 }, /* lr */ { 0x38, 32 }, /* pc */ { 0x3c, 32 }, /* xPSR */ }; static const struct stack_register_offset rtos_standard_Cortex_R4_stack_offsets[] = { { 0x08, 32 }, /* r0 (a1) */ { 0x0c, 32 }, /* r1 (a2) */ { 0x10, 32 }, /* r2 (a3) */ { 0x14, 32 }, /* r3 (a4) */ { 0x18, 32 }, /* r4 (v1) */ { 0x1c, 32 }, /* r5 (v2) */ { 0x20, 32 }, /* r6 (v3) */ { 0x24, 32 }, /* r7 (v4) */ { 0x28, 32 }, /* r8 (a1) */ { 0x2c, 32 }, /* r9 (sb) */ { 0x30, 32 }, /* r10 (sl) */ { 0x34, 32 }, /* r11 (fp) */ { 0x38, 32 }, /* r12 (ip) */ { -2, 32 }, /* sp */ { 0x3c, 32 }, /* lr */ { 0x40, 32 }, /* pc */ { -1, 96 }, /* FPA1 */ { -1, 96 }, /* FPA2 */ { -1, 96 }, /* FPA3 */ { -1, 96 }, /* FPA4 */ { -1, 96 }, /* FPA5 */ { -1, 96 }, /* FPA6 */ { -1, 96 }, /* FPA7 */ { -1, 96 }, /* FPA8 */ { -1, 32 }, /* FPS */ { 0x04, 32 }, /* CSPR */ }; static const struct stack_register_offset rtos_standard_NDS32_N1068_stack_offsets[] = { { 0x88, 32 }, /* R0 */ { 0x8C, 32 }, /* R1 */ { 0x14, 32 }, /* R2 */ { 0x18, 32 }, /* R3 */ { 0x1C, 32 }, /* R4 */ { 0x20, 32 }, /* R5 */ { 0x24, 32 }, /* R6 */ { 0x28, 32 }, /* R7 */ { 0x2C, 32 }, /* R8 */ { 0x30, 32 }, /* R9 */ { 0x34, 32 }, /* R10 */ { 0x38, 32 }, /* R11 */ { 0x3C, 32 }, /* R12 */ { 0x40, 32 }, /* R13 */ { 0x44, 32 }, /* R14 */ { 0x48, 32 }, /* R15 */ { 0x4C, 32 }, /* R16 */ { 0x50, 32 }, /* R17 */ { 0x54, 32 }, /* R18 */ { 0x58, 32 }, /* R19 */ { 0x5C, 32 }, /* R20 */ { 0x60, 32 }, /* R21 */ { 0x64, 32 }, /* R22 */ { 0x68, 32 }, /* R23 */ { 0x6C, 32 }, /* R24 */ { 0x70, 32 }, /* R25 */ { 0x74, 32 }, /* R26 */ { 0x78, 32 }, /* R27 */ { 0x7C, 32 }, /* R28 */ { 0x80, 32 }, /* R29 */ { 0x84, 32 }, /* R30 (LP) */ { 0x00, 32 }, /* R31 (SP) */ { 0x04, 32 }, /* PSW */ { 0x08, 32 }, /* IPC */ { 0x0C, 32 }, /* IPSW */ { 0x10, 32 }, /* IFC_LP */ }; const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = { 0x40, /* stack_registers_size */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 8, /* stack_alignment */ rtos_standard_Cortex_M3_stack_offsets /* register_offsets */ }; const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking = { 0x48, /* stack_registers_size */ -1, /* stack_growth_direction */ 26, /* num_output_registers */ 8, /* stack_alignment */ rtos_standard_Cortex_R4_stack_offsets /* register_offsets */ }; const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking = { 0x90, /* stack_registers_size */ -1, /* stack_growth_direction */ 32, /* num_output_registers */ 8, /* stack_alignment */ rtos_standard_NDS32_N1068_stack_offsets /* register_offsets */ }; openocd-0.9.0/src/rtos/rtos_standard_stackings.h0000644000175000017500000000357012315575361016751 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ #define INCLUDED_RTOS_STANDARD_STACKINGS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking; extern const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking; extern const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking; #endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */ openocd-0.9.0/src/rtos/rtos_mqx_stackings.c0000644000175000017500000000551512516456303015747 00000000000000/*************************************************************************** * Copyright (C) 2014 by Marian Cingel * * cingel.marian@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/armv7m.h" /* * standard exception stack * ( stack base, higher memory address ) * - xpsr - 0x48 * - pc - 0x44 * - lr - 0x40 * - r12 - 0x3C * - r3 - 0x38 * - r2 - 0x34 * - r1 - 0x30 * - r0 - 0x2C * extended stack in svc_pending handler * - lr - 0x28 * - r11 - 0x24 * - r10 - 0x20 * - r9 - 0x1C * - r8 - 0x18 * - r7 - 0x14 * - r6 - 0x10 * - r5 - 0x0C * - r4 - 0x08 * - BASEPRI - 0x04 * - SHPR3 - 0x00 ( contains pend_svc exception priority ) * ( stack head, lower address, stored in 'task->STACK_PTR' ) */ static const struct stack_register_offset rtos_mqx_arm_v7m_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { 0x2C, 32 }, /* r0 */ { 0x30, 32 }, /* r1 */ { 0x34, 32 }, /* r2 */ { 0x38, 32 }, /* r3 */ { 0x08, 32 }, /* r4 */ { 0x0C, 32 }, /* r5 */ { 0x10, 32 }, /* r6 */ { 0x14, 32 }, /* r7 */ { 0x18, 32 }, /* r8 */ { 0x1C, 32 }, /* r9 */ { 0x20, 32 }, /* r10 */ { 0x24, 32 }, /* r11 */ { 0x3C, 32 }, /* r12 */ { -2 , 32 }, /* sp */ { 0x28, 32 }, /* lr */ { 0x44, 32 }, /* pc */ { 0x48, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking = { 0x4C, /* stack_registers_size, calculate offset base address */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 0, /* stack_alignment */ rtos_mqx_arm_v7m_stack_offsets /* register_offsets */ }; openocd-0.9.0/src/rtos/rtos_mqx_stackings.h0000644000175000017500000000317212516456303015751 00000000000000/*************************************************************************** * Copyright (C) 2014 by Marian Cingel * * cingel.marian@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc. * ***************************************************************************/ #ifndef INCLUDED_RTOS_MQX_STACKINGS_H_ #define INCLUDED_RTOS_MQX_STACKINGS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" extern const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking; #endif /* ifndef INCLUDED_RTOS_MQX_STACKINGS_H_ */ openocd-0.9.0/src/rtos/eCos.c0000644000175000017500000002613512516456303012717 00000000000000/*************************************************************************** * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_ecos_stackings.h" static int eCos_detect_rtos(struct target *target); static int eCos_create(struct target *target); static int eCos_update_threads(struct rtos *rtos); static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct eCos_thread_state { int value; const char *desc; }; static const struct eCos_thread_state eCos_thread_states[] = { { 0, "Ready" }, { 1, "Sleeping" }, { 2, "Countsleep" }, { 4, "Suspended" }, { 8, "Creating" }, { 16, "Exited" } }; #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state)) struct eCos_params { const char *target_name; unsigned char pointer_width; unsigned char thread_stack_offset; unsigned char thread_name_offset; unsigned char thread_state_offset; unsigned char thread_next_offset; unsigned char thread_uniqueid_offset; const struct rtos_register_stacking *stacking_info; }; static const struct eCos_params eCos_params_list[] = { { "cortex_m", /* target_name */ 4, /* pointer_width; */ 0x0c, /* thread_stack_offset; */ 0x9c, /* thread_name_offset; */ 0x3c, /* thread_state_offset; */ 0xa0, /* thread_next_offset */ 0x4c, /* thread_uniqueid_offset */ &rtos_eCos_Cortex_M3_stacking /* stacking_info */ } }; #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params))) enum eCos_symbol_values { eCos_VAL_thread_list = 0, eCos_VAL_current_thread_ptr = 1 }; static const char * const eCos_symbol_list[] = { "Cyg_Thread::thread_list", "Cyg_Scheduler_Base::current_thread", NULL }; const struct rtos_type eCos_rtos = { .name = "eCos", .detect_rtos = eCos_detect_rtos, .create = eCos_create, .update_threads = eCos_update_threads, .get_thread_reg_list = eCos_get_thread_reg_list, .get_symbol_list_to_lookup = eCos_get_symbol_list_to_lookup, }; static int eCos_update_threads(struct rtos *rtos) { int retval; int tasks_found = 0; int thread_list_size = 0; const struct eCos_params *param; if (rtos == NULL) return -1; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct eCos_params *) rtos->rtos_specific_params; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for eCos"); return -4; } if (rtos->symbols[eCos_VAL_thread_list].address == 0) { LOG_ERROR("Don't have the thread list head"); return -2; } /* wipe out previous thread details if any */ rtos_free_threadlist(rtos); /* determine the number of current threads */ uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address; uint32_t thread_index; target_read_buffer(rtos->target, thread_list_head, param->pointer_width, (uint8_t *) &thread_index); uint32_t first_thread = thread_index; do { thread_list_size++; retval = target_read_buffer(rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index); if (retval != ERROR_OK) return retval; } while (thread_index != first_thread); /* read the current thread id */ uint32_t current_thread_addr; retval = target_read_buffer(rtos->target, rtos->symbols[eCos_VAL_current_thread_ptr].address, 4, (uint8_t *)¤t_thread_addr); if (retval != ERROR_OK) return retval; rtos->current_thread = 0; retval = target_read_buffer(rtos->target, current_thread_addr + param->thread_uniqueid_offset, 2, (uint8_t *)&rtos->current_thread); if (retval != ERROR_OK) { LOG_ERROR("Could not read eCos current thread from target"); return retval; } if ((thread_list_size == 0) || (rtos->current_thread == 0)) { /* Either : No RTOS threads - there is always at least the current execution though */ /* OR : No current thread - all threads suspended - show the current execution * of idling */ char tmp_str[] = "Current Execution"; thread_list_size++; tasks_found++; rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); if (thread_list_size == 0) { rtos->thread_count = 1; return ERROR_OK; } } else { /* create space for new thread details */ rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); } /* loop over all threads */ thread_index = first_thread; do { #define ECOS_THREAD_NAME_STR_SIZE (200) char tmp_str[ECOS_THREAD_NAME_STR_SIZE]; unsigned int i = 0; uint32_t name_ptr = 0; uint32_t prev_thread_ptr; /* Save the thread pointer */ uint16_t thread_id; retval = target_read_buffer(rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t *)&thread_id); if (retval != ERROR_OK) { LOG_ERROR("Could not read eCos thread id from target"); return retval; } rtos->thread_details[tasks_found].threadid = thread_id; /* read the name pointer */ retval = target_read_buffer(rtos->target, thread_index + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr); if (retval != ERROR_OK) { LOG_ERROR("Could not read eCos thread name pointer from target"); return retval; } /* Read the thread name */ retval = target_read_buffer(rtos->target, name_ptr, ECOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread name from eCos target"); return retval; } tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00'; if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); rtos->thread_details[tasks_found].thread_name_str = malloc(strlen(tmp_str)+1); strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str); /* Read the thread status */ int64_t thread_status = 0; retval = target_read_buffer(rtos->target, thread_index + param->thread_state_offset, 4, (uint8_t *)&thread_status); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread state from eCos target"); return retval; } for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) { /* * empty */ } const char *state_desc; if (i < ECOS_NUM_STATES) state_desc = eCos_thread_states[i].desc; else state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( state_desc)+1); strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); rtos->thread_details[tasks_found].exists = true; rtos->thread_details[tasks_found].display_str = NULL; tasks_found++; prev_thread_ptr = thread_index; /* Get the location of the next thread structure. */ thread_index = rtos->symbols[eCos_VAL_thread_list].address; retval = target_read_buffer(rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index); if (retval != ERROR_OK) { LOG_ERROR("Error reading next thread pointer in eCos thread list"); return retval; } } while (thread_index != first_thread); rtos->thread_count = tasks_found; return 0; } static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { int retval; const struct eCos_params *param; *hex_reg_list = NULL; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct eCos_params *) rtos->rtos_specific_params; /* Find the thread with that thread id */ uint16_t id = 0; uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address; uint32_t thread_index; target_read_buffer(rtos->target, thread_list_head, param->pointer_width, (uint8_t *)&thread_index); bool done = false; while (!done) { retval = target_read_buffer(rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t *)&id); if (retval != ERROR_OK) { LOG_ERROR("Error reading unique id from eCos thread"); return retval; } if (id == thread_id) { done = true; break; } target_read_buffer(rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index); } if (done) { /* Read the stack pointer */ int64_t stack_ptr = 0; retval = target_read_buffer(rtos->target, thread_index + param->thread_stack_offset, param->pointer_width, (uint8_t *)&stack_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading stack frame from eCos thread"); return retval; } return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); } return -1; } static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = calloc( ARRAY_SIZE(eCos_symbol_list), sizeof(symbol_table_elem_t)); for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++) (*symbol_list)[i].symbol_name = eCos_symbol_list[i]; return 0; } static int eCos_detect_rtos(struct target *target) { if ((target->rtos->symbols != NULL) && (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) { /* looks like eCos */ return 1; } return 0; } static int eCos_create(struct target *target) { int i = 0; while ((i < ECOS_NUM_PARAMS) && (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) { i++; } if (i >= ECOS_NUM_PARAMS) { LOG_ERROR("Could not find target in eCos compatibility list"); return -1; } target->rtos->rtos_specific_params = (void *) &eCos_params_list[i]; target->rtos->current_thread = 0; target->rtos->thread_details = NULL; return 0; } openocd-0.9.0/src/rtos/Makefile.am0000644000175000017500000000411712516456303013712 00000000000000# *************************************************************************** # * Copyright (C) 2011 by Broadcom Corporation * # * Evan Hunter - ehunter@broadcom.com * # * * # * This program 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 2 of the License, or * # * (at your option) any later version. * # * * # * This program 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, write to the * # * Free Software Foundation, Inc., * # * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * # *************************************************************************** include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = librtos.la noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c librtos_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform librtos_la_CFLAGS += -Wno-sign-compare endif MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/rtos/Makefile.in0000644000175000017500000010641712526201651013724 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # *************************************************************************** # * Copyright (C) 2011 by Broadcom Corporation * # * Evan Hunter - ehunter@broadcom.com * # * * # * This program 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 2 of the License, or * # * (at your option) any later version. * # * * # * This program 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, write to the * # * Free Software Foundation, Inc., * # * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * # *************************************************************************** VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl # FD_* macros are sloppy with their signs on MinGW32 platform @IS_MINGW_TRUE@am__append_2 = -Wno-sign-compare subdir = src/rtos ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) librtos_la_LIBADD = am_librtos_la_OBJECTS = librtos_la-rtos.lo \ librtos_la-rtos_standard_stackings.lo \ librtos_la-rtos_ecos_stackings.lo \ librtos_la-rtos_chibios_stackings.lo \ librtos_la-rtos_embkernel_stackings.lo \ librtos_la-rtos_mqx_stackings.lo librtos_la-FreeRTOS.lo \ librtos_la-ThreadX.lo librtos_la-eCos.lo librtos_la-linux.lo \ librtos_la-ChibiOS.lo librtos_la-embKernel.lo \ librtos_la-mqx.lo librtos_la_OBJECTS = $(am_librtos_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = librtos_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(librtos_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(librtos_la_SOURCES) DIST_SOURCES = $(librtos_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = librtos.la noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c librtos_la_CFLAGS = $(am__append_2) MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/rtos/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/rtos/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } librtos.la: $(librtos_la_OBJECTS) $(librtos_la_DEPENDENCIES) $(EXTRA_librtos_la_DEPENDENCIES) $(AM_V_CCLD)$(librtos_la_LINK) $(librtos_la_OBJECTS) $(librtos_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-ChibiOS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-FreeRTOS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-ThreadX.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-eCos.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-embKernel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-mqx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos_chibios_stackings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos_ecos_stackings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos_embkernel_stackings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos_mqx_stackings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librtos_la-rtos_standard_stackings.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< librtos_la-rtos.lo: rtos.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos.Tpo -c -o librtos_la-rtos.lo `test -f 'rtos.c' || echo '$(srcdir)/'`rtos.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos.Tpo $(DEPDIR)/librtos_la-rtos.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos.c' object='librtos_la-rtos.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos.lo `test -f 'rtos.c' || echo '$(srcdir)/'`rtos.c librtos_la-rtos_standard_stackings.lo: rtos_standard_stackings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos_standard_stackings.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos_standard_stackings.Tpo -c -o librtos_la-rtos_standard_stackings.lo `test -f 'rtos_standard_stackings.c' || echo '$(srcdir)/'`rtos_standard_stackings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos_standard_stackings.Tpo $(DEPDIR)/librtos_la-rtos_standard_stackings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos_standard_stackings.c' object='librtos_la-rtos_standard_stackings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos_standard_stackings.lo `test -f 'rtos_standard_stackings.c' || echo '$(srcdir)/'`rtos_standard_stackings.c librtos_la-rtos_ecos_stackings.lo: rtos_ecos_stackings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos_ecos_stackings.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos_ecos_stackings.Tpo -c -o librtos_la-rtos_ecos_stackings.lo `test -f 'rtos_ecos_stackings.c' || echo '$(srcdir)/'`rtos_ecos_stackings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos_ecos_stackings.Tpo $(DEPDIR)/librtos_la-rtos_ecos_stackings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos_ecos_stackings.c' object='librtos_la-rtos_ecos_stackings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos_ecos_stackings.lo `test -f 'rtos_ecos_stackings.c' || echo '$(srcdir)/'`rtos_ecos_stackings.c librtos_la-rtos_chibios_stackings.lo: rtos_chibios_stackings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos_chibios_stackings.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos_chibios_stackings.Tpo -c -o librtos_la-rtos_chibios_stackings.lo `test -f 'rtos_chibios_stackings.c' || echo '$(srcdir)/'`rtos_chibios_stackings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos_chibios_stackings.Tpo $(DEPDIR)/librtos_la-rtos_chibios_stackings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos_chibios_stackings.c' object='librtos_la-rtos_chibios_stackings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos_chibios_stackings.lo `test -f 'rtos_chibios_stackings.c' || echo '$(srcdir)/'`rtos_chibios_stackings.c librtos_la-rtos_embkernel_stackings.lo: rtos_embkernel_stackings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos_embkernel_stackings.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos_embkernel_stackings.Tpo -c -o librtos_la-rtos_embkernel_stackings.lo `test -f 'rtos_embkernel_stackings.c' || echo '$(srcdir)/'`rtos_embkernel_stackings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos_embkernel_stackings.Tpo $(DEPDIR)/librtos_la-rtos_embkernel_stackings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos_embkernel_stackings.c' object='librtos_la-rtos_embkernel_stackings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos_embkernel_stackings.lo `test -f 'rtos_embkernel_stackings.c' || echo '$(srcdir)/'`rtos_embkernel_stackings.c librtos_la-rtos_mqx_stackings.lo: rtos_mqx_stackings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-rtos_mqx_stackings.lo -MD -MP -MF $(DEPDIR)/librtos_la-rtos_mqx_stackings.Tpo -c -o librtos_la-rtos_mqx_stackings.lo `test -f 'rtos_mqx_stackings.c' || echo '$(srcdir)/'`rtos_mqx_stackings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-rtos_mqx_stackings.Tpo $(DEPDIR)/librtos_la-rtos_mqx_stackings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtos_mqx_stackings.c' object='librtos_la-rtos_mqx_stackings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-rtos_mqx_stackings.lo `test -f 'rtos_mqx_stackings.c' || echo '$(srcdir)/'`rtos_mqx_stackings.c librtos_la-FreeRTOS.lo: FreeRTOS.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-FreeRTOS.lo -MD -MP -MF $(DEPDIR)/librtos_la-FreeRTOS.Tpo -c -o librtos_la-FreeRTOS.lo `test -f 'FreeRTOS.c' || echo '$(srcdir)/'`FreeRTOS.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-FreeRTOS.Tpo $(DEPDIR)/librtos_la-FreeRTOS.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='FreeRTOS.c' object='librtos_la-FreeRTOS.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-FreeRTOS.lo `test -f 'FreeRTOS.c' || echo '$(srcdir)/'`FreeRTOS.c librtos_la-ThreadX.lo: ThreadX.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-ThreadX.lo -MD -MP -MF $(DEPDIR)/librtos_la-ThreadX.Tpo -c -o librtos_la-ThreadX.lo `test -f 'ThreadX.c' || echo '$(srcdir)/'`ThreadX.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-ThreadX.Tpo $(DEPDIR)/librtos_la-ThreadX.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ThreadX.c' object='librtos_la-ThreadX.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-ThreadX.lo `test -f 'ThreadX.c' || echo '$(srcdir)/'`ThreadX.c librtos_la-eCos.lo: eCos.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-eCos.lo -MD -MP -MF $(DEPDIR)/librtos_la-eCos.Tpo -c -o librtos_la-eCos.lo `test -f 'eCos.c' || echo '$(srcdir)/'`eCos.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-eCos.Tpo $(DEPDIR)/librtos_la-eCos.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='eCos.c' object='librtos_la-eCos.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-eCos.lo `test -f 'eCos.c' || echo '$(srcdir)/'`eCos.c librtos_la-linux.lo: linux.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-linux.lo -MD -MP -MF $(DEPDIR)/librtos_la-linux.Tpo -c -o librtos_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-linux.Tpo $(DEPDIR)/librtos_la-linux.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linux.c' object='librtos_la-linux.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c librtos_la-ChibiOS.lo: ChibiOS.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-ChibiOS.lo -MD -MP -MF $(DEPDIR)/librtos_la-ChibiOS.Tpo -c -o librtos_la-ChibiOS.lo `test -f 'ChibiOS.c' || echo '$(srcdir)/'`ChibiOS.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-ChibiOS.Tpo $(DEPDIR)/librtos_la-ChibiOS.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ChibiOS.c' object='librtos_la-ChibiOS.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-ChibiOS.lo `test -f 'ChibiOS.c' || echo '$(srcdir)/'`ChibiOS.c librtos_la-embKernel.lo: embKernel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-embKernel.lo -MD -MP -MF $(DEPDIR)/librtos_la-embKernel.Tpo -c -o librtos_la-embKernel.lo `test -f 'embKernel.c' || echo '$(srcdir)/'`embKernel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-embKernel.Tpo $(DEPDIR)/librtos_la-embKernel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='embKernel.c' object='librtos_la-embKernel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-embKernel.lo `test -f 'embKernel.c' || echo '$(srcdir)/'`embKernel.c librtos_la-mqx.lo: mqx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -MT librtos_la-mqx.lo -MD -MP -MF $(DEPDIR)/librtos_la-mqx.Tpo -c -o librtos_la-mqx.lo `test -f 'mqx.c' || echo '$(srcdir)/'`mqx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librtos_la-mqx.Tpo $(DEPDIR)/librtos_la-mqx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mqx.c' object='librtos_la-mqx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtos_la_CFLAGS) $(CFLAGS) -c -o librtos_la-mqx.lo `test -f 'mqx.c' || echo '$(srcdir)/'`mqx.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/rtos/linux_header.h0000644000175000017500000000211612315575361014476 00000000000000/* gdb script to update the header file according to kernel version and build option before executing function awareness kernel symbol must be loaded : symbol vmlinux define awareness set logging off set logging file linux_header.h set logging on printf "#define QAT %p\n",&((struct task_struct *)(0))->stack set $a=&((struct list_head *)(0))->next set $a=(int)$a+(int)&((struct task_struct *)(0))->tasks printf "#define NEXT %p\n",$a printf "#define COMM %p\n",&((struct task_struct *)(0))->comm printf "#define MEM %p\n",&((struct task_struct *)(0))->mm printf "#define ONCPU %p\n",&((struct task_struct *)(0))->on_cpu printf "#define PID %p\n",&((struct task_struct *)(0))->pid printf "#define CPU_CONT %p\n",&((struct thread_info *)(0))->cpu_context printf "#define PREEMPT %p\n",&((struct thread_info *)(0))->preempt_count printf "#define MM_CTX %p\n",&((struct mm_struct *)(0))->context end */ #define QAT 0x4 #define NEXT 0x1b0 #define COMM 0x2d4 #define MEM 0x1cc #define ONCPU 0x18 #define PID 0x1f4 #define CPU_CONT 0x1c #define PREEMPT 0x4 #define MM_CTX 0x160 openocd-0.9.0/src/rtos/rtos.c0000644000175000017500000004217512516456303013017 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/target.h" #include "helper/log.h" #include "helper/binarybuffer.h" #include "server/gdb_server.h" /* RTOSs */ extern struct rtos_type FreeRTOS_rtos; extern struct rtos_type ThreadX_rtos; extern struct rtos_type eCos_rtos; extern struct rtos_type Linux_os; extern struct rtos_type ChibiOS_rtos; extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; static struct rtos_type *rtos_types[] = { &ThreadX_rtos, &FreeRTOS_rtos, &eCos_rtos, &Linux_os, &ChibiOS_rtos, &embKernel_rtos, &mqx_rtos, NULL }; int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); int rtos_smp_init(struct target *target) { if (target->rtos->type->smp_init) return target->rtos->type->smp_init(target); return ERROR_TARGET_INIT_FAILED; } static int os_alloc(struct target *target, struct rtos_type *ostype) { struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos)); if (!os) return JIM_ERR; os->type = ostype; os->current_threadid = -1; os->current_thread = 0; os->symbols = NULL; os->target = target; /* RTOS drivers can override the packet handler in _create(). */ os->gdb_thread_packet = rtos_thread_packet; return JIM_OK; } static void os_free(struct target *target) { if (!target->rtos) return; if (target->rtos->symbols) free(target->rtos->symbols); free(target->rtos); target->rtos = NULL; } static int os_alloc_create(struct target *target, struct rtos_type *ostype) { int ret = os_alloc(target, ostype); if (JIM_OK == ret) { ret = target->rtos->type->create(target); if (ret != JIM_OK) os_free(target); } return ret; } int rtos_create(Jim_GetOptInfo *goi, struct target *target) { int x; char *cp; struct Jim_Obj *res; if (!goi->isconfigure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); return JIM_ERR; } os_free(target); Jim_GetOpt_String(goi, &cp, NULL); if (0 == strcmp(cp, "auto")) { /* Auto detect tries to look up all symbols for each RTOS, * and runs the RTOS driver's _detect() function when GDB * finds all symbols for any RTOS. See rtos_qsymbol(). */ target->rtos_auto_detect = true; /* rtos_qsymbol() will iterate over all RTOSes. Allocate * target->rtos here, and set it to the first RTOS type. */ return os_alloc(target, rtos_types[0]); } for (x = 0; rtos_types[x]; x++) if (0 == strcmp(cp, rtos_types[x]->name)) return os_alloc_create(target, rtos_types[x]); Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp); res = Jim_GetResult(goi->interp); for (x = 0; rtos_types[x]; x++) Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL); Jim_AppendStrings(goi->interp, res, " or auto", NULL); return JIM_ERR; } int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); if (target->rtos == NULL) return rtos_thread_packet(connection, packet, packet_size); /* thread not *found*/ return target->rtos->gdb_thread_packet(connection, packet, packet_size); } static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr) { symbol_table_elem_t *s; if (!os->symbols) os->type->get_symbol_list_to_lookup(&os->symbols); if (!cur_symbol[0]) return &os->symbols[0]; for (s = os->symbols; s->symbol_name; s++) if (!strcmp(s->symbol_name, cur_symbol)) { s->address = cur_addr; s++; return s; } return NULL; } /* searches for 'symbol' in the lookup table for 'os' and returns TRUE, * if 'symbol' is not declared optional */ static bool is_symbol_mandatory(const struct rtos *os, const char *symbol) { for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) { if (!strcmp(s->symbol_name, symbol)) return !s->optional; } return false; } /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB. * * GDB sends a qSymbol:: packet (empty address, empty name) to notify * that it can now answer qSymbol::hexcodedname queries, to look up symbols. * * If the qSymbol packet has no address that means GDB did not find the * symbol, in which case auto-detect will move on to try the next RTOS. * * rtos_qsymbol() then calls the next_symbol() helper function, which * iterates over symbol names for the current RTOS until it finds the * symbol in the received GDB packet, and then returns the next entry * in the list of symbols. * * If GDB replied about the last symbol for the RTOS and the RTOS was * specified explicitly, then no further symbol lookup is done. When * auto-detecting, the RTOS driver _detect() function must return success. * * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise. */ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size) { int rtos_detected = 0; uint64_t addr = 0; size_t reply_len; char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = ""; symbol_table_elem_t *next_sym = NULL; struct target *target = get_target_from_connection(connection); struct rtos *os = target->rtos; reply_len = sprintf(reply, "OK"); if (!os) goto done; /* Decode any symbol name in the packet*/ int len = unhexify(cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1)); cur_sym[len] = 0; if ((strcmp(packet, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */ (!sscanf(packet, "qSymbol:%" SCNx64 ":", &addr)) && /* GDB did not find an address for a symbol */ is_symbol_mandatory(os, cur_sym)) { /* the symbol is mandatory for this RTOS */ /* GDB could not find an address for the previous symbol */ if (!target->rtos_auto_detect) { LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os->type->name, cur_sym); goto done; } else { /* Autodetecting RTOS - try next RTOS */ if (!rtos_try_next(target)) { LOG_WARNING("No RTOS could be auto-detected!"); goto done; } /* Next RTOS selected - invalidate current symbol */ cur_sym[0] = '\x00'; } } next_sym = next_symbol(os, cur_sym, addr); if (!next_sym->symbol_name) { /* No more symbols need looking up */ if (!target->rtos_auto_detect) { rtos_detected = 1; goto done; } if (os->type->detect_rtos(target)) { LOG_INFO("Auto-detected RTOS: %s", os->type->name); rtos_detected = 1; goto done; } else { LOG_WARNING("No RTOS could be auto-detected!"); goto done; } } if (8 + (strlen(next_sym->symbol_name) * 2) + 1 > sizeof(reply)) { LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym->symbol_name); goto done; } reply_len = snprintf(reply, sizeof(reply), "qSymbol:"); reply_len += hexify(reply + reply_len, next_sym->symbol_name, 0, sizeof(reply) - reply_len); done: gdb_put_packet(connection, reply, reply_len); return rtos_detected; } int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) { if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0)) { threadid_t threadid = 0; int found = -1; sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid); if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) { int thread_num; for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) { if (target->rtos->thread_details[thread_num].threadid == threadid) { if (target->rtos->thread_details[thread_num].exists) found = thread_num; } } } if (found == -1) { gdb_put_packet(connection, "E01", 3); /* thread not found */ return ERROR_OK; } struct thread_detail *detail = &target->rtos->thread_details[found]; int str_size = 0; if (detail->display_str != NULL) str_size += strlen(detail->display_str); if (detail->thread_name_str != NULL) str_size += strlen(detail->thread_name_str); if (detail->extra_info_str != NULL) str_size += strlen(detail->extra_info_str); char *tmp_str = calloc(str_size + 7, sizeof(char)); char *tmp_str_ptr = tmp_str; if (detail->display_str != NULL) tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str); if (detail->thread_name_str != NULL) { if (tmp_str_ptr != tmp_str) tmp_str_ptr += sprintf(tmp_str_ptr, " : "); tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str); } if (detail->extra_info_str != NULL) { if (tmp_str_ptr != tmp_str) tmp_str_ptr += sprintf(tmp_str_ptr, " : "); tmp_str_ptr += sprintf(tmp_str_ptr, " : %s", detail->extra_info_str); } assert(strlen(tmp_str) == (size_t) (tmp_str_ptr - tmp_str)); char *hex_str = malloc(strlen(tmp_str) * 2 + 1); int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); return ERROR_OK; } gdb_put_packet(connection, "", 0); return ERROR_OK; } else if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { target->rtos_auto_detect = false; target->rtos->type->create(target); target->rtos->type->update_threads(target->rtos); } return ERROR_OK; } else if (strncmp(packet, "qfThreadInfo", 12) == 0) { int i; if (target->rtos != NULL) { if (target->rtos->thread_count == 0) { gdb_put_packet(connection, "l", 1); } else { /*thread id are 16 char +1 for ',' */ char *out_str = malloc(17 * target->rtos->thread_count + 1); char *tmp_str = out_str; for (i = 0; i < target->rtos->thread_count; i++) { tmp_str += sprintf(tmp_str, "%c%016" PRIx64, i == 0 ? 'm' : ',', target->rtos->thread_details[i].threadid); } gdb_put_packet(connection, out_str, strlen(out_str)); free(out_str); } } else gdb_put_packet(connection, "l", 1); return ERROR_OK; } else if (strncmp(packet, "qsThreadInfo", 12) == 0) { gdb_put_packet(connection, "l", 1); return ERROR_OK; } else if (strncmp(packet, "qAttached", 9) == 0) { gdb_put_packet(connection, "1", 1); return ERROR_OK; } else if (strncmp(packet, "qOffsets", 8) == 0) { char offsets[] = "Text=0;Data=0;Bss=0"; gdb_put_packet(connection, offsets, sizeof(offsets)-1); return ERROR_OK; } else if (strncmp(packet, "qCRC:", 5) == 0) { /* make sure we check this before "qC" packet below * otherwise it gets incorrectly handled */ return GDB_THREAD_PACKET_NOT_CONSUMED; } else if (strncmp(packet, "qC", 2) == 0) { if (target->rtos != NULL) { char buffer[19]; int size; size = snprintf(buffer, 19, "QC%016" PRIx64, target->rtos->current_thread); gdb_put_packet(connection, buffer, size); } else gdb_put_packet(connection, "QC0", 3); return ERROR_OK; } else if (packet[0] == 'T') { /* Is thread alive? */ threadid_t threadid; int found = -1; sscanf(packet, "T%" SCNx64, &threadid); if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) { int thread_num; for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) { if (target->rtos->thread_details[thread_num].threadid == threadid) { if (target->rtos->thread_details[thread_num].exists) found = thread_num; } } } if (found != -1) gdb_put_packet(connection, "OK", 2); /* thread alive */ else gdb_put_packet(connection, "E01", 3); /* thread not found */ return ERROR_OK; } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for * all other operations ) */ if ((packet[1] == 'g') && (target->rtos != NULL)) { sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid); LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n", target->rtos->current_threadid); } gdb_put_packet(connection, "OK", 2); return ERROR_OK; } return GDB_THREAD_PACKET_NOT_CONSUMED; } int rtos_get_gdb_reg_list(struct connection *connection) { struct target *target = get_target_from_connection(connection); int64_t current_threadid = target->rtos->current_threadid; if ((target->rtos != NULL) && (current_threadid != -1) && (current_threadid != 0) && ((current_threadid != target->rtos->current_thread) || (target->smp))) { /* in smp several current thread are possible */ char *hex_reg_list; LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64 ", target->rtos->current_thread=0x%" PRIx64 "\r\n", current_threadid, target->rtos->current_thread); target->rtos->type->get_thread_reg_list(target->rtos, current_threadid, &hex_reg_list); if (hex_reg_list != NULL) { gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list)); free(hex_reg_list); return ERROR_OK; } } return ERROR_FAIL; } int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, char **hex_reg_list) { int list_size = 0; char *tmp_str_ptr; int64_t new_stack_ptr; int i; int retval; if (stack_ptr == 0) { LOG_ERROR("Error: null stack pointer in thread"); return -5; } /* Read the stack */ uint8_t *stack_data = malloc(stacking->stack_registers_size); uint32_t address = stack_ptr; if (stacking->stack_growth_direction == 1) address -= stacking->stack_registers_size; retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data); if (retval != ERROR_OK) { free(stack_data); LOG_ERROR("Error reading stack frame from thread"); return retval; } LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32, address); #if 0 LOG_OUTPUT("Stack Data :"); for (i = 0; i < stacking->stack_registers_size; i++) LOG_OUTPUT("%02X", stack_data[i]); LOG_OUTPUT("\r\n"); #endif for (i = 0; i < stacking->num_output_registers; i++) list_size += stacking->register_offsets[i].width_bits/8; *hex_reg_list = malloc(list_size*2 + 1); tmp_str_ptr = *hex_reg_list; new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; if (stacking->stack_alignment != 0) { /* Align new stack pointer to x byte boundary */ new_stack_ptr = (new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) + ((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0); } for (i = 0; i < stacking->num_output_registers; i++) { int j; for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) { if (stacking->register_offsets[i].offset == -1) tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0); else if (stacking->register_offsets[i].offset == -2) tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", ((uint8_t *)&new_stack_ptr)[j]); else tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", stack_data[stacking->register_offsets[i].offset + j]); } } free(stack_data); /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */ return ERROR_OK; } int rtos_try_next(struct target *target) { struct rtos *os = target->rtos; struct rtos_type **type = rtos_types; if (!os) return 0; while (*type && os->type != *type) type++; if (!*type || !*(++type)) return 0; os->type = *type; if (os->symbols) { free(os->symbols); os->symbols = NULL; } return 1; } int rtos_update_threads(struct target *target) { if ((target->rtos != NULL) && (target->rtos->type != NULL)) target->rtos->type->update_threads(target->rtos); return ERROR_OK; } void rtos_free_threadlist(struct rtos *rtos) { if (rtos->thread_details) { int j; for (j = 0; j < rtos->thread_count; j++) { struct thread_detail *current_thread = &rtos->thread_details[j]; free(current_thread->display_str); free(current_thread->thread_name_str); free(current_thread->extra_info_str); } free(rtos->thread_details); rtos->thread_details = NULL; rtos->thread_count = 0; } } openocd-0.9.0/src/rtos/rtos.h0000644000175000017500000000765712516456303013032 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef RTOS_H #define RTOS_H #include "server/server.h" #include typedef int64_t threadid_t; typedef int64_t symbol_address_t; struct reg; /** * Table should be terminated by an element with NULL in symbol_name */ typedef struct symbol_table_elem_struct { const char *symbol_name; symbol_address_t address; bool optional; } symbol_table_elem_t; struct thread_detail { threadid_t threadid; bool exists; char *display_str; char *thread_name_str; char *extra_info_str; }; struct rtos { const struct rtos_type *type; symbol_table_elem_t *symbols; struct target *target; /* add a context variable instead of global variable */ int64_t current_threadid; threadid_t current_thread; struct thread_detail *thread_details; int thread_count; int (*gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size); void *rtos_specific_params; }; struct rtos_type { const char *name; int (*detect_rtos)(struct target *target); int (*create)(struct target *target); int (*smp_init)(struct target *target); int (*update_threads)(struct rtos *rtos); int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]); int (*clean)(struct target *target); char * (*ps_command)(struct target *target); }; struct stack_register_offset { signed short offset; /* offset in bytes from stack head, or -1 to indicate * register is not stacked, or -2 to indicate this is the * stack pointer register */ unsigned short width_bits; }; struct rtos_register_stacking { unsigned char stack_registers_size; signed char stack_growth_direction; unsigned char num_output_registers; unsigned char stack_alignment; const struct stack_register_offset *register_offsets; }; #define GDB_THREAD_PACKET_NOT_CONSUMED (-40) int rtos_create(Jim_GetOptInfo *goi, struct target *target); int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, char **hex_reg_list); int rtos_try_next(struct target *target); int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size); int rtos_get_gdb_reg_list(struct connection *connection); int rtos_update_threads(struct target *target); void rtos_free_threadlist(struct rtos *rtos); int rtos_smp_init(struct target *target); /* function for handling symbol access */ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size); #endif /* RTOS_H */ openocd-0.9.0/src/rtos/rtos_embkernel_stackings.c0000644000175000017500000000457512315575361017116 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" #include "target/armv7m.h" static const struct stack_register_offset rtos_embkernel_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { 0x24, 32 }, /* r0 */ { 0x28, 32 }, /* r1 */ { 0x2c, 32 }, /* r2 */ { 0x30, 32 }, /* r3 */ { 0x00, 32 }, /* r4 */ { 0x04, 32 }, /* r5 */ { 0x08, 32 }, /* r6 */ { 0x0c, 32 }, /* r7 */ { 0x10, 32 }, /* r8 */ { 0x14, 32 }, /* r9 */ { 0x18, 32 }, /* r10 */ { 0x1c, 32 }, /* r11 */ { 0x34, 32 }, /* r12 */ { -2, 32 }, /* sp */ { 0x38, 32 }, /* lr */ { 0x3c, 32 }, /* pc */ { 0x40, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking = { 0x40, /* stack_registers_size */ -1, /* stack_growth_direction */ ARMV7M_NUM_CORE_REGS, /* num_output_registers */ 8, /* stack_alignment */ rtos_embkernel_Cortex_M_stack_offsets /* register_offsets */ }; openocd-0.9.0/src/rtos/rtos_embkernel_stackings.h0000644000175000017500000000333712315575361017116 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ #define INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "rtos.h" extern const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking; #endif /* ifndef INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ */ openocd-0.9.0/src/rtos/ChibiOS.c0000644000175000017500000004330112516456303013300 00000000000000/*************************************************************************** * Copyright (C) 2012 by Matthias Blaicher * * Matthias Blaicher - matthias@blaicher.com * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "target/armv7m.h" #include "target/cortex_m.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_chibios_stackings.h" /** * @brief ChibiOS/RT memory signature record. * * @details Definition copied from os/kernel/include/chregistry.h of ChibiOS/RT. */ struct ChibiOS_chdebug { char ch_identifier[4]; /**< @brief Always set to "main". */ uint8_t ch_zero; /**< @brief Must be zero. */ uint8_t ch_size; /**< @brief Size of this structure. */ uint16_t ch_version; /**< @brief Encoded ChibiOS/RT version. */ uint8_t ch_ptrsize; /**< @brief Size of a pointer. */ uint8_t ch_timesize; /**< @brief Size of a @p systime_t. */ uint8_t ch_threadsize; /**< @brief Size of a @p Thread struct. */ uint8_t cf_off_prio; /**< @brief Offset of @p p_prio field. */ uint8_t cf_off_ctx; /**< @brief Offset of @p p_ctx field. */ uint8_t cf_off_newer; /**< @brief Offset of @p p_newer field. */ uint8_t cf_off_older; /**< @brief Offset of @p p_older field. */ uint8_t cf_off_name; /**< @brief Offset of @p p_name field. */ uint8_t cf_off_stklimit; /**< @brief Offset of @p p_stklimit field. */ uint8_t cf_off_state; /**< @brief Offset of @p p_state field. */ uint8_t cf_off_flags; /**< @brief Offset of @p p_flags field. */ uint8_t cf_off_refs; /**< @brief Offset of @p p_refs field. */ uint8_t cf_off_preempt; /**< @brief Offset of @p p_preempt field. */ uint8_t cf_off_time; /**< @brief Offset of @p p_time field. */ }; #define GET_CH_KERNEL_MAJOR(codedVersion) ((codedVersion >> 11) & 0x1f) #define GET_CH_KERNEL_MINOR(codedVersion) ((codedVersion >> 6) & 0x1f) #define GET_CH_KERNEL_PATCH(codedVersion) ((codedVersion >> 0) & 0x3f) /** * @brief ChibiOS thread states. */ static const char * const ChibiOS_thread_states[] = { "READY", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", "SLEEPING", "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "WTQUEUE", "FINAL" }; #define CHIBIOS_NUM_STATES (sizeof(ChibiOS_thread_states)/sizeof(char *)) /* Maximum ChibiOS thread name. There is no real limit set by ChibiOS but 64 * chars ought to be enough. */ #define CHIBIOS_THREAD_NAME_STR_SIZE (64) struct ChibiOS_params { const char *target_name; struct ChibiOS_chdebug *signature; const struct rtos_register_stacking *stacking_info; }; static struct ChibiOS_params ChibiOS_params_list[] = { { "cortex_m", /* target_name */ 0, NULL, /* stacking_info */ }, { "hla_target", /* target_name */ 0, NULL, /* stacking_info */ } }; #define CHIBIOS_NUM_PARAMS ((int)(sizeof(ChibiOS_params_list)/sizeof(struct ChibiOS_params))) static int ChibiOS_detect_rtos(struct target *target); static int ChibiOS_create(struct target *target); static int ChibiOS_update_threads(struct rtos *rtos); static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); static int ChibiOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct rtos_type ChibiOS_rtos = { .name = "ChibiOS", .detect_rtos = ChibiOS_detect_rtos, .create = ChibiOS_create, .update_threads = ChibiOS_update_threads, .get_thread_reg_list = ChibiOS_get_thread_reg_list, .get_symbol_list_to_lookup = ChibiOS_get_symbol_list_to_lookup, }; /* In ChibiOS/RT 3.0 the rlist structure has become part of a system * data structure ch. We declare both symbols as optional and later * use whatever is available. */ enum ChibiOS_symbol_values { ChibiOS_VAL_rlist = 0, ChibiOS_VAL_ch = 1, ChibiOS_VAL_ch_debug = 2, ChibiOS_VAL_chSysInit = 3 }; static symbol_table_elem_t ChibiOS_symbol_list[] = { { "rlist", 0, true}, /* Thread ready list */ { "ch", 0, true}, /* System data structure */ { "ch_debug", 0, false}, /* Memory Signature containing offsets of fields in rlist */ { "chSysInit", 0, false}, /* Necessary part of API, used for ChibiOS detection */ { NULL, 0, false} }; /* Offset of the rlist structure within the system data structure (ch) */ #define CH_RLIST_OFFSET 0x00 static int ChibiOS_update_memory_signature(struct rtos *rtos) { int retval; struct ChibiOS_params *param; struct ChibiOS_chdebug *signature; param = (struct ChibiOS_params *) rtos->rtos_specific_params; /* Free existing memory description.*/ if (param->signature) { free(param->signature); param->signature = 0; } signature = malloc(sizeof(*signature)); if (!signature) { LOG_ERROR("Could not allocate space for ChibiOS/RT memory signature"); return -1; } retval = target_read_buffer(rtos->target, rtos->symbols[ChibiOS_VAL_ch_debug].address, sizeof(*signature), (uint8_t *) signature); if (retval != ERROR_OK) { LOG_ERROR("Could not read ChibiOS/RT memory signature from target"); goto errfree; } if (strncmp(signature->ch_identifier, "main", 4) != 0) { LOG_ERROR("Memory signature identifier does not contain magic bytes."); goto errfree; } if (signature->ch_size < sizeof(*signature)) { LOG_ERROR("ChibiOS/RT memory signature claims to be smaller " "than expected"); goto errfree; } if (signature->ch_size > sizeof(*signature)) { LOG_WARNING("ChibiOS/RT memory signature claims to be bigger than" " expected. Assuming compatibility..."); } /* Convert endianness of version field */ const uint8_t *versionTarget = (const uint8_t *) &signature->ch_version; signature->ch_version = rtos->target->endianness == TARGET_LITTLE_ENDIAN ? le_to_h_u32(versionTarget) : be_to_h_u32(versionTarget); const uint16_t ch_version = signature->ch_version; LOG_INFO("Successfully loaded memory map of ChibiOS/RT target " "running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version), GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version)); /* Currently, we have the inherent assumption that all address pointers * are 32 bit wide. */ if (signature->ch_ptrsize != sizeof(uint32_t)) { LOG_ERROR("ChibiOS/RT target memory signature claims an address" "width unequal to 32 bits!"); free(signature); return -1; } param->signature = signature; return 0; errfree: /* Error reading the ChibiOS memory structure */ free(signature); param->signature = 0; return -1; } static int ChibiOS_update_stacking(struct rtos *rtos) { /* Sometimes the stacking can not be determined only by looking at the * target name but only a runtime. * * For example, this is the case for cortex-m4 targets and ChibiOS which * only stack the FPU registers if it is enabled during ChibiOS build. * * Terminating which stacking is used is target depending. * * Assumptions: * - Once ChibiOS is actually initialized, the stacking is fixed. * - During startup code, the FPU might not be initialized and the * detection might fail. * - Since no threads are running during startup, the problem is solved * by delaying stacking detection until there are more threads * available than the current execution. In which case * ChibiOS_get_thread_reg_list is called. */ int retval; if (!rtos->rtos_specific_params) return -1; struct ChibiOS_params *param; param = (struct ChibiOS_params *) rtos->rtos_specific_params; /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4 */ struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); if (is_armv7m(armv7m_target)) { if (armv7m_target->fp_feature == FPv4_SP) { /* Found ARM v7m target which includes a FPU */ uint32_t cpacr; retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); if (retval != ERROR_OK) { LOG_ERROR("Could not read CPACR register to check FPU state"); return -1; } /* Check if CP10 and CP11 are set to full access. * In ChibiOS this is done in ResetHandler() in crt0.c */ if (cpacr & 0x00F00000) { LOG_DEBUG("Enabled FPU detected."); param->stacking_info = &rtos_chibios_arm_v7m_stacking_w_fpu; return 0; } } /* Found ARM v7m target with no or disabled FPU */ param->stacking_info = &rtos_chibios_arm_v7m_stacking; return 0; } return -1; } static int ChibiOS_update_threads(struct rtos *rtos) { int retval; const struct ChibiOS_params *param; int tasks_found = 0; int rtos_valid = -1; if (!rtos->rtos_specific_params) return -1; if (!rtos->symbols) { LOG_ERROR("No symbols for ChibiOS"); return -3; } param = (const struct ChibiOS_params *) rtos->rtos_specific_params; /* Update the memory signature saved in the target memory */ if (!param->signature) { retval = ChibiOS_update_memory_signature(rtos); if (retval != ERROR_OK) { LOG_ERROR("Reading the memory signature of ChibiOS/RT failed"); return retval; } } /* wipe out previous thread details if any */ rtos_free_threadlist(rtos); /* ChibiOS does not save the current thread count. We have to first * parse the double linked thread list to check for errors and the number of * threads. */ const uint32_t rlist = rtos->symbols[ChibiOS_VAL_rlist].address ? rtos->symbols[ChibiOS_VAL_rlist].address : rtos->symbols[ChibiOS_VAL_ch].address + CH_RLIST_OFFSET /* ChibiOS3 */; const struct ChibiOS_chdebug *signature = param->signature; uint32_t current; uint32_t previous; uint32_t older; current = rlist; previous = rlist; while (1) { retval = target_read_u32(rtos->target, current + signature->cf_off_newer, ¤t); if (retval != ERROR_OK) { LOG_ERROR("Could not read next ChibiOS thread"); return retval; } /* Could be NULL if the kernel is not initialized yet or if the * registry is corrupted. */ if (current == 0) { LOG_ERROR("ChibiOS registry integrity check failed, NULL pointer"); rtos_valid = 0; break; } /* Fetch previous thread in the list as a integrity check. */ retval = target_read_u32(rtos->target, current + signature->cf_off_older, &older); if ((retval != ERROR_OK) || (older == 0) || (older != previous)) { LOG_ERROR("ChibiOS registry integrity check failed, " "double linked list violation"); rtos_valid = 0; break; } /* Check for full iteration of the linked list. */ if (current == rlist) break; tasks_found++; previous = current; } if (!rtos_valid) { /* No RTOS, there is always at least the current execution, though */ LOG_INFO("Only showing current execution because of a broken " "ChibiOS thread registry."); const char tmp_thread_name[] = "Current Execution"; const char tmp_thread_extra_info[] = "No RTOS thread"; rtos->thread_details = malloc( sizeof(struct thread_detail)); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = malloc( sizeof(tmp_thread_extra_info)); strcpy(rtos->thread_details->extra_info_str, tmp_thread_extra_info); rtos->thread_details->thread_name_str = malloc( sizeof(tmp_thread_name)); strcpy(rtos->thread_details->thread_name_str, tmp_thread_name); rtos->current_thread = 1; rtos->thread_count = 1; return ERROR_OK; } /* create space for new thread details */ rtos->thread_details = malloc( sizeof(struct thread_detail) * tasks_found); if (!rtos->thread_details) { LOG_ERROR("Could not allocate space for thread details"); return -1; } rtos->thread_count = tasks_found; /* Loop through linked list. */ struct thread_detail *curr_thrd_details = rtos->thread_details; while (curr_thrd_details < rtos->thread_details + tasks_found) { uint32_t name_ptr = 0; char tmp_str[CHIBIOS_THREAD_NAME_STR_SIZE]; retval = target_read_u32(rtos->target, current + signature->cf_off_newer, ¤t); if (retval != ERROR_OK) { LOG_ERROR("Could not read next ChibiOS thread"); return -6; } /* Check for full iteration of the linked list. */ if (current == rlist) break; /* Save the thread pointer */ curr_thrd_details->threadid = current; /* read the name pointer */ retval = target_read_u32(rtos->target, current + signature->cf_off_name, &name_ptr); if (retval != ERROR_OK) { LOG_ERROR("Could not read ChibiOS thread name pointer from target"); return retval; } /* Read the thread name */ retval = target_read_buffer(rtos->target, name_ptr, CHIBIOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread name from ChibiOS target"); return retval; } tmp_str[CHIBIOS_THREAD_NAME_STR_SIZE - 1] = '\x00'; if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); curr_thrd_details->thread_name_str = malloc( strlen(tmp_str) + 1); strcpy(curr_thrd_details->thread_name_str, tmp_str); /* State info */ uint8_t threadState; const char *state_desc; retval = target_read_u8(rtos->target, current + signature->cf_off_state, &threadState); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread state from ChibiOS target"); return retval; } if (threadState < CHIBIOS_NUM_STATES) state_desc = ChibiOS_thread_states[threadState]; else state_desc = "Unknown state"; curr_thrd_details->extra_info_str = malloc(strlen( state_desc)+1); strcpy(curr_thrd_details->extra_info_str, state_desc); curr_thrd_details->exists = true; curr_thrd_details->display_str = NULL; curr_thrd_details++; } uint32_t current_thrd; /* NOTE: By design, cf_off_name equals readylist_current_offset */ retval = target_read_u32(rtos->target, rlist + signature->cf_off_name, ¤t_thrd); if (retval != ERROR_OK) { LOG_ERROR("Could not read current Thread from ChibiOS target"); return retval; } rtos->current_thread = current_thrd; return 0; } static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { int retval; const struct ChibiOS_params *param; uint32_t stack_ptr = 0; *hex_reg_list = NULL; if ((rtos == NULL) || (thread_id == 0) || (rtos->rtos_specific_params == NULL)) return -1; param = (const struct ChibiOS_params *) rtos->rtos_specific_params; if (!param->signature) return -1; /* Update stacking if it can only be determined from runtime information */ if ((param->stacking_info == 0) && (ChibiOS_update_stacking(rtos) != ERROR_OK)) { LOG_ERROR("Failed to determine exact stacking for the target type %s", rtos->target->type->name); return -1; } /* Read the stack pointer */ retval = target_read_u32(rtos->target, thread_id + param->signature->cf_off_ctx, &stack_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading stack frame from ChibiOS thread"); return retval; } return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); } static int ChibiOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { *symbol_list = malloc(sizeof(ChibiOS_symbol_list)); if (*symbol_list == NULL) return ERROR_FAIL; memcpy(*symbol_list, ChibiOS_symbol_list, sizeof(ChibiOS_symbol_list)); return 0; } static int ChibiOS_detect_rtos(struct target *target) { if ((target->rtos->symbols != NULL) && ((target->rtos->symbols[ChibiOS_VAL_rlist].address != 0) || (target->rtos->symbols[ChibiOS_VAL_ch].address != 0)) && (target->rtos->symbols[ChibiOS_VAL_chSysInit].address != 0)) { if (target->rtos->symbols[ChibiOS_VAL_ch_debug].address == 0) { LOG_INFO("It looks like the target is running ChibiOS without " "ch_debug."); return 0; } /* looks like ChibiOS with memory map enabled.*/ return 1; } return 0; } static int ChibiOS_create(struct target *target) { int i = 0; while ((i < CHIBIOS_NUM_PARAMS) && (0 != strcmp(ChibiOS_params_list[i].target_name, target->type->name))) { i++; } if (i >= CHIBIOS_NUM_PARAMS) { LOG_WARNING("Could not find target \"%s\" in ChibiOS compatibility " "list", target->type->name); return -1; } target->rtos->rtos_specific_params = (void *) &ChibiOS_params_list[i]; return 0; } openocd-0.9.0/src/rtos/ThreadX.c0000644000175000017500000003150012516456303013355 00000000000000/*************************************************************************** * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target/target.h" #include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" #include "rtos_standard_stackings.h" static int ThreadX_detect_rtos(struct target *target); static int ThreadX_create(struct target *target); static int ThreadX_update_threads(struct rtos *rtos); static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list); static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct ThreadX_thread_state { int value; const char *desc; }; static const struct ThreadX_thread_state ThreadX_thread_states[] = { { 0, "Ready" }, { 1, "Completed" }, { 2, "Terminated" }, { 3, "Suspended" }, { 4, "Sleeping" }, { 5, "Waiting - Queue" }, { 6, "Waiting - Semaphore" }, { 7, "Waiting - Event flag" }, { 8, "Waiting - Memory" }, { 9, "Waiting - Memory" }, { 10, "Waiting - I/O" }, { 11, "Waiting - Filesystem" }, { 12, "Waiting - Network" }, { 13, "Waiting - Mutex" }, }; #define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state)) struct ThreadX_params { const char *target_name; unsigned char pointer_width; unsigned char thread_stack_offset; unsigned char thread_name_offset; unsigned char thread_state_offset; unsigned char thread_next_offset; const struct rtos_register_stacking *stacking_info; }; static const struct ThreadX_params ThreadX_params_list[] = { { "cortex_m", /* target_name */ 4, /* pointer_width; */ 8, /* thread_stack_offset; */ 40, /* thread_name_offset; */ 48, /* thread_state_offset; */ 136, /* thread_next_offset */ &rtos_standard_Cortex_M3_stacking, /* stacking_info */ }, { "cortex_r4", /* target_name */ 4, /* pointer_width; */ 8, /* thread_stack_offset; */ 40, /* thread_name_offset; */ 48, /* thread_state_offset; */ 136, /* thread_next_offset */ &rtos_standard_Cortex_R4_stacking, /* stacking_info */ }, }; #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params))) enum ThreadX_symbol_values { ThreadX_VAL_tx_thread_current_ptr = 0, ThreadX_VAL_tx_thread_created_ptr = 1, ThreadX_VAL_tx_thread_created_count = 2, }; static const char * const ThreadX_symbol_list[] = { "_tx_thread_current_ptr", "_tx_thread_created_ptr", "_tx_thread_created_count", NULL }; const struct rtos_type ThreadX_rtos = { .name = "ThreadX", .detect_rtos = ThreadX_detect_rtos, .create = ThreadX_create, .update_threads = ThreadX_update_threads, .get_thread_reg_list = ThreadX_get_thread_reg_list, .get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup, }; static int ThreadX_update_threads(struct rtos *rtos) { int retval; int tasks_found = 0; int thread_list_size = 0; const struct ThreadX_params *param; if (rtos == NULL) return -1; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct ThreadX_params *) rtos->rtos_specific_params; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for ThreadX"); return -4; } if (rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0) { LOG_ERROR("Don't have the number of threads in ThreadX"); return -2; } /* read the number of threads */ retval = target_read_buffer(rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_count].address, 4, (uint8_t *)&thread_list_size); if (retval != ERROR_OK) { LOG_ERROR("Could not read ThreadX thread count from target"); return retval; } /* wipe out previous thread details if any */ rtos_free_threadlist(rtos); /* read the current thread id */ retval = target_read_buffer(rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address, 4, (uint8_t *)&rtos->current_thread); if (retval != ERROR_OK) { LOG_ERROR("Could not read ThreadX current thread from target"); return retval; } if ((thread_list_size == 0) || (rtos->current_thread == 0)) { /* Either : No RTOS threads - there is always at least the current execution though */ /* OR : No current thread - all threads suspended - show the current execution * of idling */ char tmp_str[] = "Current Execution"; thread_list_size++; tasks_found++; rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); if (thread_list_size == 0) { rtos->thread_count = 1; return ERROR_OK; } } else { /* create space for new thread details */ rtos->thread_details = malloc( sizeof(struct thread_detail) * thread_list_size); } /* Read the pointer to the first thread */ int64_t thread_ptr = 0; retval = target_read_buffer(rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address, param->pointer_width, (uint8_t *)&thread_ptr); if (retval != ERROR_OK) { LOG_ERROR("Could not read ThreadX thread location from target"); return retval; } /* loop over all threads */ int64_t prev_thread_ptr = 0; while ((thread_ptr != prev_thread_ptr) && (tasks_found < thread_list_size)) { #define THREADX_THREAD_NAME_STR_SIZE (200) char tmp_str[THREADX_THREAD_NAME_STR_SIZE]; unsigned int i = 0; int64_t name_ptr = 0; /* Save the thread pointer */ rtos->thread_details[tasks_found].threadid = thread_ptr; /* read the name pointer */ retval = target_read_buffer(rtos->target, thread_ptr + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr); if (retval != ERROR_OK) { LOG_ERROR("Could not read ThreadX thread name pointer from target"); return retval; } /* Read the thread name */ retval = target_read_buffer(rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread name from ThreadX target"); return retval; } tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00'; if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); rtos->thread_details[tasks_found].thread_name_str = malloc(strlen(tmp_str)+1); strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str); /* Read the thread status */ int64_t thread_status = 0; retval = target_read_buffer(rtos->target, thread_ptr + param->thread_state_offset, 4, (uint8_t *)&thread_status); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread state from ThreadX target"); return retval; } for (i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value != thread_status); i++) { /* empty */ } const char *state_desc; if (i < THREADX_NUM_STATES) state_desc = ThreadX_thread_states[i].desc; else state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( state_desc)+1); strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); rtos->thread_details[tasks_found].exists = true; rtos->thread_details[tasks_found].display_str = NULL; tasks_found++; prev_thread_ptr = thread_ptr; /* Get the location of the next thread structure. */ thread_ptr = 0; retval = target_read_buffer(rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading next thread pointer in ThreadX thread list"); return retval; } } rtos->thread_count = tasks_found; return 0; } static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { int retval; const struct ThreadX_params *param; *hex_reg_list = NULL; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct ThreadX_params *) rtos->rtos_specific_params; /* Read the stack pointer */ int64_t stack_ptr = 0; retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t *)&stack_ptr); if (retval != ERROR_OK) { LOG_ERROR("Error reading stack frame from ThreadX thread"); return retval; } return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); } static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = calloc( ARRAY_SIZE(ThreadX_symbol_list), sizeof(symbol_table_elem_t)); for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++) (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i]; return 0; } static int ThreadX_detect_rtos(struct target *target) { if ((target->rtos->symbols != NULL) && (target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) { /* looks like ThreadX */ return 1; } return 0; } #if 0 static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id) { return 0; } static int ThreadX_get_thread_detail(struct rtos *rtos, threadid_t thread_id, struct thread_detail *detail) { unsigned int i = 0; int retval; #define THREADX_THREAD_NAME_STR_SIZE (200) char tmp_str[THREADX_THREAD_NAME_STR_SIZE]; const struct ThreadX_params *param; if (rtos == NULL) return -1; if (thread_id == 0) return -2; if (rtos->rtos_specific_params == NULL) return -3; param = (const struct ThreadX_params *) rtos->rtos_specific_params; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for ThreadX"); return -3; } detail->threadid = thread_id; int64_t name_ptr = 0; /* read the name pointer */ retval = target_read_buffer(rtos->target, thread_id + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr); if (retval != ERROR_OK) { LOG_ERROR("Could not read ThreadX thread name pointer from target"); return retval; } /* Read the thread name */ retval = target_read_buffer(rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread name from ThreadX target"); return retval; } tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00'; if (tmp_str[0] == '\x00') strcpy(tmp_str, "No Name"); detail->thread_name_str = malloc(strlen(tmp_str)+1); /* Read the thread status */ int64_t thread_status = 0; retval = target_read_buffer(rtos->target, thread_id + param->thread_state_offset, 4, (uint8_t *)&thread_status); if (retval != ERROR_OK) { LOG_ERROR("Error reading thread state from ThreadX target"); return retval; } for (i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value != thread_status); i++) { /* empty */ } char *state_desc; if (i < THREADX_NUM_STATES) state_desc = ThreadX_thread_states[i].desc; else state_desc = "Unknown state"; detail->extra_info_str = malloc(strlen(state_desc)+1); detail->exists = true; detail->display_str = NULL; return 0; } #endif static int ThreadX_create(struct target *target) { int i = 0; while ((i < THREADX_NUM_PARAMS) && (0 != strcmp(ThreadX_params_list[i].target_name, target->type->name))) { i++; } if (i >= THREADX_NUM_PARAMS) { LOG_ERROR("Could not find target in ThreadX compatibility list"); return -1; } target->rtos->rtos_specific_params = (void *) &ThreadX_params_list[i]; target->rtos->current_thread = 0; target->rtos->thread_details = NULL; return 0; } openocd-0.9.0/src/xsvf/0000755000175000017500000000000012526202226011724 500000000000000openocd-0.9.0/src/xsvf/Makefile.am0000644000175000017500000000026612315575361013715 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libxsvf.la noinst_HEADERS = xsvf.h libxsvf_la_SOURCES = xsvf.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/xsvf/Makefile.in0000644000175000017500000004353612526201652013726 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/xsvf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libxsvf_la_LIBADD = am_libxsvf_la_OBJECTS = xsvf.lo libxsvf_la_OBJECTS = $(am_libxsvf_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libxsvf_la_SOURCES) DIST_SOURCES = $(libxsvf_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libxsvf.la noinst_HEADERS = xsvf.h libxsvf_la_SOURCES = xsvf.c MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/xsvf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/xsvf/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libxsvf.la: $(libxsvf_la_OBJECTS) $(libxsvf_la_DEPENDENCIES) $(EXTRA_libxsvf_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libxsvf_la_OBJECTS) $(libxsvf_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsvf.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/xsvf/xsvf.c0000644000175000017500000006464312315575361013024 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 Peter Hettkamp * * peter.hettkamp@htp-tel.de * * * * Copyright (C) 2009 SoftPLC Corporation. http://softplc.com * * Dick Hollenbeck * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* The specification for SVF is available here: * http://www.asset-intertech.com/support/svf.pdf * Below, this document is refered to as the "SVF spec". * * The specification for XSVF is available here: * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf * Below, this document is refered to as the "XSVF spec". */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xsvf.h" #include #include /* XSVF commands, from appendix B of xapp503.pdf */ #define XCOMPLETE 0x00 #define XTDOMASK 0x01 #define XSIR 0x02 #define XSDR 0x03 #define XRUNTEST 0x04 #define XREPEAT 0x07 #define XSDRSIZE 0x08 #define XSDRTDO 0x09 #define XSETSDRMASKS 0x0A #define XSDRINC 0x0B #define XSDRB 0x0C #define XSDRC 0x0D #define XSDRE 0x0E #define XSDRTDOB 0x0F #define XSDRTDOC 0x10 #define XSDRTDOE 0x11 #define XSTATE 0x12 #define XENDIR 0x13 #define XENDDR 0x14 #define XSIR2 0x15 #define XCOMMENT 0x16 #define XWAIT 0x17 /* XWAITSTATE is not in the xilinx XSVF spec, but the svf2xsvf.py translator * generates this. Arguably it is needed because the XSVF XRUNTEST command * was ill conceived and does not directly flow out of the SVF RUNTEST command. * This XWAITSTATE does map directly from the SVF RUNTEST command. */ #define XWAITSTATE 0x18 /* Lattice has extended the SVF file format, and Dick Hollenbeck's python based * SVF2XSVF converter supports these 3 additional XSVF opcodes, LCOUNT, LDELAY, LSDR. * Here is an example of usage of the 3 lattice opcode extensions: ! Set the maximum loop count to 25. LCOUNT 25; ! Step to DRPAUSE give 5 clocks and wait for 1.00e + 000 SEC. LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; ! Test for the completed status. Match means pass. ! Loop back to LDELAY line if not match and loop count less than 25. LSDR 1 TDI (0) TDO (1); */ #define LCOUNT 0x19 #define LDELAY 0x1A #define LSDR 0x1B #define XTRST 0x1C /* XSVF valid state values for the XSTATE command, from appendix B of xapp503.pdf */ #define XSV_RESET 0x00 #define XSV_IDLE 0x01 #define XSV_DRSELECT 0x02 #define XSV_DRCAPTURE 0x03 #define XSV_DRSHIFT 0x04 #define XSV_DREXIT1 0x05 #define XSV_DRPAUSE 0x06 #define XSV_DREXIT2 0x07 #define XSV_DRUPDATE 0x08 #define XSV_IRSELECT 0x09 #define XSV_IRCAPTURE 0x0A #define XSV_IRSHIFT 0x0B #define XSV_IREXIT1 0x0C #define XSV_IRPAUSE 0x0D #define XSV_IREXIT2 0x0E #define XSV_IRUPDATE 0x0F /* arguments to XTRST */ #define XTRST_ON 0 #define XTRST_OFF 1 #define XTRST_Z 2 #define XTRST_ABSENT 3 #define XSTATE_MAX_PATH 12 static int xsvf_fd; /* map xsvf tap state to an openocd "tap_state_t" */ static tap_state_t xsvf_to_tap(int xsvf_state) { tap_state_t ret; switch (xsvf_state) { case XSV_RESET: ret = TAP_RESET; break; case XSV_IDLE: ret = TAP_IDLE; break; case XSV_DRSELECT: ret = TAP_DRSELECT; break; case XSV_DRCAPTURE: ret = TAP_DRCAPTURE; break; case XSV_DRSHIFT: ret = TAP_DRSHIFT; break; case XSV_DREXIT1: ret = TAP_DREXIT1; break; case XSV_DRPAUSE: ret = TAP_DRPAUSE; break; case XSV_DREXIT2: ret = TAP_DREXIT2; break; case XSV_DRUPDATE: ret = TAP_DRUPDATE; break; case XSV_IRSELECT: ret = TAP_IRSELECT; break; case XSV_IRCAPTURE: ret = TAP_IRCAPTURE; break; case XSV_IRSHIFT: ret = TAP_IRSHIFT; break; case XSV_IREXIT1: ret = TAP_IREXIT1; break; case XSV_IRPAUSE: ret = TAP_IRPAUSE; break; case XSV_IREXIT2: ret = TAP_IREXIT2; break; case XSV_IRUPDATE: ret = TAP_IRUPDATE; break; default: LOG_ERROR("UNKNOWN XSVF STATE 0x%02X", xsvf_state); exit(1); } return ret; } static int xsvf_read_buffer(int num_bits, int fd, uint8_t *buf) { int num_bytes; for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--) { /* reverse the order of bytes as they are read sequentially from file */ if (read(fd, buf + num_bytes - 1, 1) < 0) return ERROR_XSVF_EOF; } return ERROR_OK; } COMMAND_HANDLER(handle_xsvf_command) { uint8_t *dr_out_buf = NULL; /* from host to device (TDI) */ uint8_t *dr_in_buf = NULL; /* from device to host (TDO) */ uint8_t *dr_in_mask = NULL; int xsdrsize = 0; int xruntest = 0; /* number of TCK cycles OR *microseconds */ int xrepeat = 0; /* number of retries */ tap_state_t xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial *xendir to be TAP_IDLE */ tap_state_t xenddr = TAP_IDLE; uint8_t opcode; uint8_t uc = 0; long file_offset = 0; int loop_count = 0; tap_state_t loop_state = TAP_IDLE; int loop_clocks = 0; int loop_usecs = 0; int do_abort = 0; int unsupported = 0; int tdo_mismatch = 0; int result; int verbose = 1; bool collecting_path = false; tap_state_t path[XSTATE_MAX_PATH]; unsigned pathlen = 0; /* a flag telling whether to clock TCK during waits, * or simply sleep, controled by virt2 */ int runtest_requires_tck = 0; /* use NULL to indicate a "plain" xsvf file which accounts for * additional devices in the scan chain, otherwise the device * that should be affected */ struct jtag_tap *tap = NULL; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* we mess with CMD_ARGV starting point below, snapshot filename here */ const char *filename = CMD_ARGV[1]; if (strcmp(CMD_ARGV[0], "plain") != 0) { tap = jtag_tap_by_string(CMD_ARGV[0]); if (!tap) { command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[0]); return ERROR_FAIL; } } xsvf_fd = open(filename, O_RDONLY); if (xsvf_fd < 0) { command_print(CMD_CTX, "file \"%s\" not found", filename); return ERROR_FAIL; } /* if this argument is present, then interpret xruntest counts as TCK cycles rather than as *usecs */ if ((CMD_ARGC > 2) && (strcmp(CMD_ARGV[2], "virt2") == 0)) { runtest_requires_tck = 1; --CMD_ARGC; ++CMD_ARGV; } if ((CMD_ARGC > 2) && (strcmp(CMD_ARGV[2], "quiet") == 0)) verbose = 0; LOG_USER("xsvf processing file: \"%s\"", filename); while (read(xsvf_fd, &opcode, 1) > 0) { /* record the position of this opcode within the file */ file_offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1; /* maybe collect another state for a pathmove(); * or terminate a path. */ if (collecting_path) { tap_state_t mystate; switch (opcode) { case XCOMMENT: /* ignore/show comments between XSTATE ops */ break; case XSTATE: /* try to collect another transition */ if (pathlen == XSTATE_MAX_PATH) { LOG_ERROR("XSVF: path too long"); do_abort = 1; break; } if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; break; } mystate = xsvf_to_tap(uc); path[pathlen++] = mystate; LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate)); /* If path is incomplete, collect more */ if (!svf_tap_state_is_stable(mystate)) continue; /* Else execute the path transitions we've * collected so far. * * NOTE: Punting on the saved path is not * strictly correct, but we must to do this * unless jtag_add_pathmove() stops rejecting * paths containing RESET. This is probably * harmless, since there aren't many options * for going from a stable state to reset; * at the worst, we may issue extra clocks * once we get to RESET. */ if (mystate == TAP_RESET) { LOG_WARNING("XSVF: dodgey RESET"); path[0] = mystate; } /* FALL THROUGH */ default: /* Execute the path we collected * * NOTE: OpenOCD requires something that XSVF * doesn't: the last TAP state in the path * must be stable. In practice, tools that * create XSVF seem to follow that rule too. */ collecting_path = false; if (path[0] == TAP_RESET) jtag_add_tlr(); else jtag_add_pathmove(pathlen, path); result = jtag_execute_queue(); if (result != ERROR_OK) { LOG_ERROR("XSVF: pathmove error %d", result); do_abort = 1; break; } continue; } } switch (opcode) { case XCOMPLETE: LOG_DEBUG("XCOMPLETE"); result = jtag_execute_queue(); if (result != ERROR_OK) { tdo_mismatch = 1; break; } break; case XTDOMASK: LOG_DEBUG("XTDOMASK"); if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK)) do_abort = 1; break; case XRUNTEST: { uint8_t xruntest_buf[4]; if (read(xsvf_fd, xruntest_buf, 4) < 0) { do_abort = 1; break; } xruntest = be_to_h_u32(xruntest_buf); LOG_DEBUG("XRUNTEST %d 0x%08X", xruntest, xruntest); } break; case XREPEAT: { uint8_t myrepeat; if (read(xsvf_fd, &myrepeat, 1) < 0) do_abort = 1; else { xrepeat = myrepeat; LOG_DEBUG("XREPEAT %d", xrepeat); } } break; case XSDRSIZE: { uint8_t xsdrsize_buf[4]; if (read(xsvf_fd, xsdrsize_buf, 4) < 0) { do_abort = 1; break; } xsdrsize = be_to_h_u32(xsdrsize_buf); LOG_DEBUG("XSDRSIZE %d", xsdrsize); if (dr_out_buf) free(dr_out_buf); if (dr_in_buf) free(dr_in_buf); if (dr_in_mask) free(dr_in_mask); dr_out_buf = malloc((xsdrsize + 7) / 8); dr_in_buf = malloc((xsdrsize + 7) / 8); dr_in_mask = malloc((xsdrsize + 7) / 8); } break; case XSDR: /* these two are identical except for the dr_in_buf */ case XSDRTDO: { int limit = xrepeat; int matched = 0; int attempt; const char *op_name = (opcode == XSDR ? "XSDR" : "XSDRTDO"); if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) { do_abort = 1; break; } if (opcode == XSDRTDO) { if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) { do_abort = 1; break; } } if (limit < 1) limit = 1; LOG_DEBUG("%s %d", op_name, xsdrsize); for (attempt = 0; attempt < limit; ++attempt) { struct scan_field field; if (attempt > 0) { /* perform the XC9500 exception handling sequence shown in xapp067.pdf and * illustrated in psuedo code at end of this file. We start from state * DRPAUSE: * go to Exit2-DR * go to Shift-DR * go to Exit1-DR * go to Update-DR * go to Run-Test/Idle * * This sequence should be harmless for other devices, and it * will be skipped entirely if xrepeat is set to zero. */ static tap_state_t exception_path[] = { TAP_DREXIT2, TAP_DRSHIFT, TAP_DREXIT1, TAP_DRUPDATE, TAP_IDLE, }; jtag_add_pathmove(ARRAY_SIZE(exception_path), exception_path); if (verbose) LOG_USER("%s mismatch, xsdrsize=%d retry=%d", op_name, xsdrsize, attempt); } field.num_bits = xsdrsize; field.out_value = dr_out_buf; field.in_value = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); if (tap == NULL) jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); else jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE); jtag_check_value_mask(&field, dr_in_buf, dr_in_mask); free(field.in_value); /* LOG_DEBUG("FLUSHING QUEUE"); */ result = jtag_execute_queue(); if (result == ERROR_OK) { matched = 1; break; } } if (!matched) { LOG_USER("%s mismatch", op_name); tdo_mismatch = 1; break; } /* See page 19 of XSVF spec regarding opcode "XSDR" */ if (xruntest) { result = svf_add_statemove(TAP_IDLE); if (result != ERROR_OK) return result; if (runtest_requires_tck) jtag_add_clocks(xruntest); else jtag_add_sleep(xruntest); } else if (xendir != TAP_DRPAUSE) { /* we are already in TAP_DRPAUSE */ result = svf_add_statemove(xenddr); if (result != ERROR_OK) return result; } } break; case XSETSDRMASKS: LOG_ERROR("unsupported XSETSDRMASKS"); unsupported = 1; break; case XSDRINC: LOG_ERROR("unsupported XSDRINC"); unsupported = 1; break; case XSDRB: LOG_ERROR("unsupported XSDRB"); unsupported = 1; break; case XSDRC: LOG_ERROR("unsupported XSDRC"); unsupported = 1; break; case XSDRE: LOG_ERROR("unsupported XSDRE"); unsupported = 1; break; case XSDRTDOB: LOG_ERROR("unsupported XSDRTDOB"); unsupported = 1; break; case XSDRTDOC: LOG_ERROR("unsupported XSDRTDOC"); unsupported = 1; break; case XSDRTDOE: LOG_ERROR("unsupported XSDRTDOE"); unsupported = 1; break; case XSTATE: { tap_state_t mystate; if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; break; } mystate = xsvf_to_tap(uc); LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate)); if (mystate == TAP_INVALID) { LOG_ERROR("XSVF: bad XSTATE %02x", uc); do_abort = 1; break; } /* NOTE: the current state is SVF-stable! */ /* no change == NOP */ if (mystate == cmd_queue_cur_state && mystate != TAP_RESET) break; /* Hand off to SVF? */ if (svf_tap_state_is_stable(mystate)) { result = svf_add_statemove(mystate); if (result != ERROR_OK) unsupported = 1; break; } /* * A sequence of XSTATE transitions, each TAP * state adjacent to the previous one. Start * collecting them. */ collecting_path = true; pathlen = 1; path[0] = mystate; } break; case XENDIR: if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; break; } /* see page 22 of XSVF spec */ if (uc == 0) xendir = TAP_IDLE; else if (uc == 1) xendir = TAP_IRPAUSE; else { LOG_ERROR("illegial XENDIR argument: 0x%02X", uc); unsupported = 1; break; } LOG_DEBUG("XENDIR 0x%02X %s", uc, tap_state_name(xendir)); break; case XENDDR: if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; break; } /* see page 22 of XSVF spec */ if (uc == 0) xenddr = TAP_IDLE; else if (uc == 1) xenddr = TAP_DRPAUSE; else { LOG_ERROR("illegial XENDDR argument: 0x%02X", uc); unsupported = 1; break; } LOG_DEBUG("XENDDR %02X %s", uc, tap_state_name(xenddr)); break; case XSIR: case XSIR2: { uint8_t short_buf[2]; uint8_t *ir_buf; int bitcount; tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir; if (opcode == XSIR) { /* one byte bitcount */ if (read(xsvf_fd, short_buf, 1) < 0) { do_abort = 1; break; } bitcount = short_buf[0]; LOG_DEBUG("XSIR %d", bitcount); } else { if (read(xsvf_fd, short_buf, 2) < 0) { do_abort = 1; break; } bitcount = be_to_h_u16(short_buf); LOG_DEBUG("XSIR2 %d", bitcount); } ir_buf = malloc((bitcount + 7) / 8); if (xsvf_read_buffer(bitcount, xsvf_fd, ir_buf) != ERROR_OK) do_abort = 1; else { struct scan_field field; field.num_bits = bitcount; field.out_value = ir_buf; field.in_value = NULL; if (tap == NULL) jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, my_end_state); else jtag_add_ir_scan(tap, &field, my_end_state); if (xruntest) { if (runtest_requires_tck) jtag_add_clocks(xruntest); else jtag_add_sleep(xruntest); } /* Note that an -irmask of non-zero in your config file * can cause this to fail. Setting -irmask to zero cand work * around the problem. */ /* LOG_DEBUG("FLUSHING QUEUE"); */ result = jtag_execute_queue(); if (result != ERROR_OK) tdo_mismatch = 1; } free(ir_buf); } break; case XCOMMENT: { unsigned int ndx = 0; char comment[128]; do { if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; break; } if (ndx < sizeof(comment)-1) comment[ndx++] = uc; } while (uc != 0); comment[sizeof(comment)-1] = 0; /* regardless, terminate */ if (verbose) LOG_USER("# %s", comment); } break; case XWAIT: { /* expected in stream: XWAIT */ uint8_t wait_local; uint8_t end; uint8_t delay_buf[4]; tap_state_t wait_state; tap_state_t end_state; int delay; if (read(xsvf_fd, &wait_local, 1) < 0 || read(xsvf_fd, &end, 1) < 0 || read(xsvf_fd, delay_buf, 4) < 0) { do_abort = 1; break; } wait_state = xsvf_to_tap(wait_local); end_state = xsvf_to_tap(end); delay = be_to_h_u32(delay_buf); LOG_DEBUG("XWAIT %s %s usecs:%d", tap_state_name( wait_state), tap_state_name(end_state), delay); if (runtest_requires_tck && wait_state == TAP_IDLE) jtag_add_runtest(delay, end_state); else { /* FIXME handle statemove errors ... */ result = svf_add_statemove(wait_state); if (result != ERROR_OK) return result; jtag_add_sleep(delay); result = svf_add_statemove(end_state); if (result != ERROR_OK) return result; } } break; case XWAITSTATE: { /* expected in stream: * XWAITSTATE * */ uint8_t clock_buf[4]; uint8_t usecs_buf[4]; uint8_t wait_local; uint8_t end; tap_state_t wait_state; tap_state_t end_state; int clock_count; int usecs; if (read(xsvf_fd, &wait_local, 1) < 0 || read(xsvf_fd, &end, 1) < 0 || read(xsvf_fd, clock_buf, 4) < 0 || read(xsvf_fd, usecs_buf, 4) < 0) { do_abort = 1; break; } wait_state = xsvf_to_tap(wait_local); end_state = xsvf_to_tap(end); clock_count = be_to_h_u32(clock_buf); usecs = be_to_h_u32(usecs_buf); LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i", tap_state_name(wait_state), tap_state_name(end_state), clock_count, usecs); /* the following states are 'stable', meaning that they have a transition * in the state diagram back to themselves. This is necessary because we will * be issuing a number of clocks in this state. This set of allowed states is also * determined by the SVF RUNTEST command's allowed states. */ if (!svf_tap_state_is_stable(wait_state)) { LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", tap_state_name(wait_state)); unsupported = 1; /* REVISIT "break" so we won't run? */ } /* FIXME handle statemove errors ... */ result = svf_add_statemove(wait_state); if (result != ERROR_OK) return result; jtag_add_clocks(clock_count); jtag_add_sleep(usecs); result = svf_add_statemove(end_state); if (result != ERROR_OK) return result; } break; case LCOUNT: { /* expected in stream: * LCOUNT */ uint8_t count_buf[4]; if (read(xsvf_fd, count_buf, 4) < 0) { do_abort = 1; break; } loop_count = be_to_h_u32(count_buf); LOG_DEBUG("LCOUNT %d", loop_count); } break; case LDELAY: { /* expected in stream: * LDELAY */ uint8_t state; uint8_t clock_buf[4]; uint8_t usecs_buf[4]; if (read(xsvf_fd, &state, 1) < 0 || read(xsvf_fd, clock_buf, 4) < 0 || read(xsvf_fd, usecs_buf, 4) < 0) { do_abort = 1; break; } /* NOTE: loop_state must be stable! */ loop_state = xsvf_to_tap(state); loop_clocks = be_to_h_u32(clock_buf); loop_usecs = be_to_h_u32(usecs_buf); LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", tap_state_name( loop_state), loop_clocks, loop_usecs); } break; /* LSDR is more like XSDRTDO than it is like XSDR. It uses LDELAY which * comes with clocks !AND! sleep requirements. */ case LSDR: { int limit = loop_count; int matched = 0; int attempt; LOG_DEBUG("LSDR"); if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) { do_abort = 1; break; } if (limit < 1) limit = 1; for (attempt = 0; attempt < limit; ++attempt) { struct scan_field field; result = svf_add_statemove(loop_state); if (result != ERROR_OK) return result; jtag_add_clocks(loop_clocks); jtag_add_sleep(loop_usecs); field.num_bits = xsdrsize; field.out_value = dr_out_buf; field.in_value = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); if (attempt > 0 && verbose) LOG_USER("LSDR retry %d", attempt); if (tap == NULL) jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); else jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE); jtag_check_value_mask(&field, dr_in_buf, dr_in_mask); free(field.in_value); /* LOG_DEBUG("FLUSHING QUEUE"); */ result = jtag_execute_queue(); if (result == ERROR_OK) { matched = 1; break; } } if (!matched) { LOG_USER("LSDR mismatch"); tdo_mismatch = 1; break; } } break; case XTRST: { uint8_t trst_mode; if (read(xsvf_fd, &trst_mode, 1) < 0) { do_abort = 1; break; } switch (trst_mode) { case XTRST_ON: jtag_add_reset(1, 0); break; case XTRST_OFF: case XTRST_Z: jtag_add_reset(0, 0); break; case XTRST_ABSENT: break; default: LOG_ERROR("XTRST mode argument (0x%02X) out of range", trst_mode); do_abort = 1; } } break; default: LOG_ERROR("unknown xsvf command (0x%02X)", uc); unsupported = 1; } if (do_abort || unsupported || tdo_mismatch) { LOG_DEBUG("xsvf failed, setting taps to reasonable state"); /* upon error, return the TAPs to a reasonable state */ result = svf_add_statemove(TAP_IDLE); if (result != ERROR_OK) return result; result = jtag_execute_queue(); if (result != ERROR_OK) return result; break; } } if (tdo_mismatch) { command_print(CMD_CTX, "TDO mismatch, somewhere near offset %lu in xsvf file, aborting", file_offset); return ERROR_FAIL; } if (unsupported) { off_t offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1; command_print(CMD_CTX, "unsupported xsvf command (0x%02X) at offset %jd, aborting", uc, (intmax_t)offset); return ERROR_FAIL; } if (do_abort) { command_print(CMD_CTX, "premature end of xsvf file detected, aborting"); return ERROR_FAIL; } if (dr_out_buf) free(dr_out_buf); if (dr_in_buf) free(dr_in_buf); if (dr_in_mask) free(dr_in_mask); close(xsvf_fd); command_print(CMD_CTX, "XSVF file programmed successfully"); return ERROR_OK; } static const struct command_registration xsvf_command_handlers[] = { { .name = "xsvf", .handler = handle_xsvf_command, .mode = COMMAND_EXEC, .help = "Runs a XSVF file. If 'virt2' is given, xruntest " "counts are interpreted as TCK cycles rather than " "as microseconds. Without the 'quiet' option, all " "comments, retries, and mismatches will be reported.", .usage = "(tapname|'plain') filename ['virt2'] ['quiet']", }, COMMAND_REGISTRATION_DONE }; int xsvf_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, xsvf_command_handlers); } /* PSUEDO-Code from Xilinx Appnote XAPP067.pdf : the following pseudo code clarifies the intent of the xrepeat support.The flow given is for the entire processing of an SVF file, not an XSVF file. No idea if this is just for the XC9500/XL/XV devices or all Xilinx parts. "Pseudo-Code Algorithm for SVF-Based ISP" 1. Go to Test-Logic-Reset state 2. Go to Run-Test Idle state 3. Read SVF record 4. if SIR record then go to Shift-IR state Scan in 5. else if SDR record then set to 0 store as store as 6. go to Shift-DR state scan in if < current TDO value > is specified then if < current TDO value > does not equal then if < repeat count > > 32 then LOG ERROR go to Run-Test Idle state go to Step 3 end if go to Pause-DR go to Exit2-DR go to Shift-DR go to Exit1-DR go to Update-DR go to Run-Test/Idle increment by 1 pause microseconds go to Step 6) end if else go to Run-Test Idle state go to Step 3 endif else if RUNTEST record then pause tester for < TCK value > microseconds store as end if */ openocd-0.9.0/src/xsvf/xsvf.h0000644000175000017500000000321612315575361013016 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef XSVF_H #define XSVF_H #include int xsvf_register_commands(struct command_context *cmd_ctx); #define ERROR_XSVF_EOF (-200) #define ERROR_XSVF_FAILED (-201) #endif /* XSVF_H */ openocd-0.9.0/src/transport/0000755000175000017500000000000012526202226012772 500000000000000openocd-0.9.0/src/transport/Makefile.am0000644000175000017500000000032212315575361014754 00000000000000include $(top_srcdir)/common.mk #METASOURCES = AUTO noinst_LTLIBRARIES = libtransport.la libtransport_la_SOURCES = \ transport.c noinst_HEADERS = \ transport.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/transport/Makefile.in0000644000175000017500000004372112526201652014770 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/transport ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtransport_la_LIBADD = am_libtransport_la_OBJECTS = transport.lo libtransport_la_OBJECTS = $(am_libtransport_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libtransport_la_SOURCES) DIST_SOURCES = $(libtransport_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) #METASOURCES = AUTO noinst_LTLIBRARIES = libtransport.la libtransport_la_SOURCES = \ transport.c noinst_HEADERS = \ transport.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/transport/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/transport/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libtransport.la: $(libtransport_la_OBJECTS) $(libtransport_la_DEPENDENCIES) $(EXTRA_libtransport_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtransport_la_OBJECTS) $(libtransport_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/transport/transport.c0000644000175000017500000002503512516456304015126 00000000000000/* * Copyright (c) 2010 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * This program 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, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /** @file * Infrastructure for specifying and managing the transport protocol * used in a given debug or programming session. * * Examples of "debug-capable" transports are JTAG or SWD. * Additionally, JTAG supports boundary scan testing. * * Examples of "programming-capable" transports include SPI or UART; * those are used (often mediated by a ROM bootloader) for ISP style * programming, to perform an initial load of code into flash, or * sometimes into SRAM. Target code could use "variant" options to * decide how to use such protocols. For example, Cortex-M3 cores * from TI/Luminary and from NXP use different protocols for for * UART or SPI based firmware loading. * * As a rule, there are protocols layered on top of the transport. * For example, different chip families use JTAG in different ways * for debugging. Also, each family that supports programming over * a UART link for initial firmware loading tends to define its own * messaging and error handling. */ #include #include extern struct command_context *global_cmd_ctx; /*-----------------------------------------------------------------------*/ /* * Infrastructure internals */ /** List of transports known to OpenOCD. */ static struct transport *transport_list; /** * NULL-terminated Vector of names of transports which the * currently selected debug adapter supports. This is declared * by the time that adapter is fully set up. */ static const char * const *allowed_transports; /** * The transport being used for the current OpenOCD session. */ static struct transport *session; static int transport_select(struct command_context *ctx, const char *name) { /* name may only identify a known transport; * caller guarantees session's transport isn't yet set.*/ for (struct transport *t = transport_list; t; t = t->next) { if (strcmp(t->name, name) == 0) { int retval = t->select(ctx); /* select() registers commands specific to this * transport, and may also reset the link, e.g. * forcing it to JTAG or SWD mode. */ if (retval == ERROR_OK) session = t; else LOG_ERROR("Error selecting '%s' as transport", t->name); return retval; } } LOG_ERROR("No transport named '%s' is available.", name); return ERROR_FAIL; } /** * Called by debug adapter drivers, or affiliated Tcl config scripts, * to declare the set of transports supported by an adapter. When * there is only one member of that set, it is automatically selected. */ int allow_transports(struct command_context *ctx, const char * const *vector) { /* NOTE: caller is required to provide only a list * of *valid* transport names * * REVISIT should we validate that? and insist there's * at least one non-NULL element in that list? * * ... allow removals, e.g. external strapping prevents use * of one transport; C code should be definitive about what * can be used when all goes well. */ if (allowed_transports != NULL || session) { LOG_ERROR("Can't modify the set of allowed transports."); return ERROR_FAIL; } allowed_transports = vector; /* autoselect if there's no choice ... */ if (!vector[1]) { LOG_INFO("only one transport option; autoselect '%s'", vector[0]); return transport_select(ctx, vector[0]); } return ERROR_OK; } /** * Used to verify corrrect adapter driver initialization. * * @returns true iff the adapter declared one or more transports. */ bool transports_are_declared(void) { return allowed_transports != NULL; } /** * Registers a transport. There are general purpose transports * (such as JTAG), as well as relatively proprietary ones which are * specific to a given chip (or chip family). * * Code implementing a transport needs to register it before it can * be selected and then activated. This is a dynamic process, so * that chips (and families) can define transports as needed (without * nneeding error-prone static tables). * * @param new_transport the transport being registered. On a * successful return, this memory is owned by the transport framework. * * @returns ERROR_OK on success, else a fault code. */ int transport_register(struct transport *new_transport) { struct transport *t; for (t = transport_list; t; t = t->next) { if (strcmp(t->name, new_transport->name) == 0) { LOG_ERROR("transport name already used"); return ERROR_FAIL; } } if (!new_transport->select || !new_transport->init) LOG_ERROR("invalid transport %s", new_transport->name); /* splice this into the list */ new_transport->next = transport_list; transport_list = new_transport; LOG_DEBUG("register '%s'", new_transport->name); return ERROR_OK; } /** * Returns the transport currently being used by this debug or * programming session. * * @returns handle to the read-only transport entity. */ struct transport *get_current_transport(void) { /* REVISIT -- constify */ return session; } /*-----------------------------------------------------------------------*/ /* * Infrastructure for Tcl interface to transports. */ /** * Makes and stores a copy of a set of transports passed as * parameters to a command. * * @param vector where the resulting copy is stored, as an argv-style * NULL-terminated vector. */ COMMAND_HELPER(transport_list_parse, char ***vector) { char **argv; unsigned n = CMD_ARGC; unsigned j = 0; *vector = NULL; if (n < 1) return ERROR_COMMAND_SYNTAX_ERROR; /* our return vector must be NULL terminated */ argv = calloc(n + 1, sizeof(char *)); if (argv == NULL) return ERROR_FAIL; for (unsigned i = 0; i < n; i++) { struct transport *t; for (t = transport_list; t; t = t->next) { if (strcmp(t->name, CMD_ARGV[i]) != 0) continue; argv[j++] = strdup(CMD_ARGV[i]); break; } if (!t) { LOG_ERROR("no such transport '%s'", CMD_ARGV[i]); goto fail; } } *vector = argv; return ERROR_OK; fail: for (unsigned i = 0; i < n; i++) free(argv[i]); free(argv); return ERROR_FAIL; } COMMAND_HANDLER(handle_transport_init) { LOG_DEBUG("%s", __func__); if (!session) { LOG_ERROR("session transport was not selected. Use 'transport select '"); /* no session transport configured, print transports then fail */ LOG_ERROR("Transports available:"); const char * const *vector = allowed_transports; while (*vector) { LOG_ERROR("%s", *vector); vector++; } return ERROR_FAIL; } return session->init(CMD_CTX); } COMMAND_HANDLER(handle_transport_list) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "The following transports are available:"); for (struct transport *t = transport_list; t; t = t->next) command_print(CMD_CTX, "\t%s", t->name); return ERROR_OK; } /** * Implements the Tcl "transport select" command, choosing the * transport to be used in this debug session from among the * set supported by the debug adapter being used. Return value * is scriptable (allowing "if swd then..." etc). */ static int jim_transport_select(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { int res; switch (argc) { case 1: /* autoselect if necessary, then return/display current config */ if (!session) { if (!allowed_transports) { LOG_ERROR("Debug adapter does not support any transports? Check config file order."); return JIM_ERR; } LOG_INFO("auto-selecting first available session transport \"%s\". " "To override use 'transport select '.", allowed_transports[0]); res = transport_select(global_cmd_ctx, allowed_transports[0]); if (res != JIM_OK) return res; } Jim_SetResultString(interp, session->name, -1); return JIM_OK; break; case 2: /* assign */ if (session) { if (!strcmp(session->name, argv[1]->bytes)) { LOG_WARNING("Transport \"%s\" was already selected", session->name); Jim_SetResultString(interp, session->name, -1); return JIM_OK; } else { LOG_ERROR("Can't change session's transport after the initial selection was made"); return JIM_ERR; } } /* Is this transport supported by our debug adapter? * Example, "JTAG-only" means SWD is not supported. * * NOTE: requires adapter to have been set up, with * transports declared via C. */ if (!allowed_transports) { LOG_ERROR("Debug adapter doesn't support any transports?"); return JIM_ERR; } for (unsigned i = 0; allowed_transports[i]; i++) { if (strcmp(allowed_transports[i], argv[1]->bytes) == 0) { if (transport_select(global_cmd_ctx, argv[1]->bytes) == ERROR_OK) { Jim_SetResultString(interp, session->name, -1); return JIM_OK; } return JIM_ERR; } } LOG_ERROR("Debug adapter doesn't support '%s' transport", argv[1]->bytes); return JIM_ERR; break; default: Jim_WrongNumArgs(interp, 1, argv, "[too many parameters]"); return JIM_ERR; } } static const struct command_registration transport_commands[] = { { .name = "init", .handler = handle_transport_init, /* this would be COMMAND_CONFIG ... except that * it needs to trigger event handlers that may * require COMMAND_EXEC ... */ .mode = COMMAND_ANY, .help = "Initialize this session's transport", .usage = "" }, { .name = "list", .handler = handle_transport_list, .mode = COMMAND_ANY, .help = "list all built-in transports", .usage = "" }, { .name = "select", .jim_handler = jim_transport_select, .mode = COMMAND_ANY, .help = "Select this session's transport", .usage = "[transport_name]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration transport_group[] = { { .name = "transport", .mode = COMMAND_ANY, .help = "Transport command group", .chain = transport_commands, .usage = "" }, COMMAND_REGISTRATION_DONE }; int transport_register_commands(struct command_context *ctx) { return register_commands(ctx, NULL, transport_group); } openocd-0.9.0/src/transport/transport.h0000644000175000017500000000567012516456304015136 00000000000000/* * Copyright (c) 2010 by David Brownell * Copyright (C) 2011 Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info) * * This program 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 2 of the License, or * (at your option) any later version. * This program 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, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef TRANSPORT_H #define TRANSPORT_H #include "helper/command.h" /** * Wrapper for transport lifecycle operations. * * OpenOCD talks to targets through some kind of debugging * or programming adapter, using some protocol that probably * has target-specific aspects. * * A "transport" reflects electrical protocol to the target, * e..g jtag, swd, spi, uart, ... NOT the messaging protocols * layered over it (e.g. JTAG has eICE, CoreSight, Nexus, OnCE, * and more). * * In addition to the lifecycle operations packaged by this * structure, a transport also involves an interface supported * by debug adapters and used by components such as debug targets. * For non-debug transports, there may be interfaces used to * write to flash chips. */ struct transport { /** * Each transport has a unique name, used to select it * from among the alternatives. Examples might include * "jtag", * "swd", "AVR_ISP" and more. */ const char *name; /** * When a transport is selected, this method registers * its commands and activates the transport (e.g. resets * the link). * * After those commands are registered, they will often * be used for further configuration of the debug link. */ int (*select)(struct command_context *ctx); /** * server startup uses this method to validate transport * configuration. (For example, with JTAG this interrogates * the scan chain against the list of expected TAPs.) */ int (*init)(struct command_context *ctx); /** * Optional. If defined, allows transport to override target * name prior to initialisation. * * @returns ERROR_OK on success, or an error code on failure. */ int (*override_target)(const char **targetname); /** * Transports are stored in a singly linked list. */ struct transport *next; }; int transport_register(struct transport *new_transport); struct transport *get_current_transport(void); int transport_register_commands(struct command_context *ctx); COMMAND_HELPER(transport_list_parse, char ***vector); int allow_transports(struct command_context *ctx, const char * const *vector); bool transports_are_declared(void); #endif openocd-0.9.0/src/flash/0000755000175000017500000000000012526202226012033 500000000000000openocd-0.9.0/src/flash/nor/0000755000175000017500000000000012526202226012631 500000000000000openocd-0.9.0/src/flash/nor/cfi.c0000644000175000017500000027671312315575360013506 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2009 Michael Schwingen * * michael@schwingen.org * * Copyright (C) 2010 Øyvind Harboe * * Copyright (C) 2010 by Antonio Borneo * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "cfi.h" #include "non_cfi.h" #include #include #include #include #include #include #define CFI_MAX_BUS_WIDTH 4 #define CFI_MAX_CHIP_WIDTH 4 /* defines internal maximum size for code fragment in cfi_intel_write_block() */ #define CFI_MAX_INTEL_CODESIZE 256 /* some id-types with specific handling */ #define AT49BV6416 0x00d6 #define AT49BV6416T 0x00d2 static const struct cfi_unlock_addresses cfi_unlock_addresses[] = { [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa }, [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa }, }; static const int cfi_status_poll_mask_dq6_dq7 = CFI_STATUS_POLL_MASK_DQ6_DQ7; /* CFI fixups forward declarations */ static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param); static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param); static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param); static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param); static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param); /* fixup after reading cmdset 0002 primary query table */ static const struct cfi_fixup cfi_0002_fixups[] = { {CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x274b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x235f, cfi_fixup_0002_polling_bits, /* 39VF3201C */ &cfi_status_poll_mask_dq6_dq7}, {CFI_MFR_SST, 0x236d, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_reversed_erase_regions, NULL}, {CFI_MFR_ST, 0x22C4, cfi_fixup_reversed_erase_regions, NULL}, /* M29W160ET */ {CFI_MFR_FUJITSU, 0x22ea, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_FUJITSU, 0x226b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_AMIC, 0xb31a, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_MX, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_EON, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_AMD, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL}, {CFI_MFR_ST, 0x227E, cfi_fixup_0002_write_buffer, NULL},/* M29W128G */ {0, 0, NULL, NULL} }; /* fixup after reading cmdset 0001 primary query table */ static const struct cfi_fixup cfi_0001_fixups[] = { {0, 0, NULL, NULL} }; static void cfi_fixup(struct flash_bank *bank, const struct cfi_fixup *fixups) { struct cfi_flash_bank *cfi_info = bank->driver_priv; const struct cfi_fixup *f; for (f = fixups; f->fixup; f++) { if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) && ((f->id == CFI_ID_ANY) || (f->id == cfi_info->device_id))) f->fixup(bank, f->param); } } static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32_t offset) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (cfi_info->x16_as_x8) offset *= 2; /* while the sector list isn't built, only accesses to sector 0 work */ if (sector == 0) return bank->base + offset * bank->bus_width; else { if (!bank->sectors) { LOG_ERROR("BUG: sector list not yet built"); exit(-1); } return bank->base + bank->sectors[sector].offset + offset * bank->bus_width; } } static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) { int i; /* clear whole buffer, to ensure bits that exceed the bus_width * are set to zero */ for (i = 0; i < CFI_MAX_BUS_WIDTH; i++) cmd_buf[i] = 0; if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { for (i = bank->bus_width; i > 0; i--) *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; } else { for (i = 1; i <= bank->bus_width; i++) *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; } } static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address) { uint8_t command[CFI_MAX_BUS_WIDTH]; cfi_command(bank, cmd, command); return target_write_memory(bank->target, address, bank->bus_width, 1, command); } /* read unsigned 8-bit value from the bank * flash banks are expected to be made of similar chips * the query result should be the same for all */ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { struct target *target = bank->target; uint8_t data[CFI_MAX_BUS_WIDTH]; int retval; retval = target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data); if (retval != ERROR_OK) return retval; if (bank->target->endianness == TARGET_LITTLE_ENDIAN) *val = data[0]; else *val = data[bank->bus_width - 1]; return ERROR_OK; } /* read unsigned 8-bit value from the bank * in case of a bank made of multiple chips, * the individual values are ORed */ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { struct target *target = bank->target; uint8_t data[CFI_MAX_BUS_WIDTH]; int i; int retval; retval = target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data); if (retval != ERROR_OK) return retval; if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { for (i = 0; i < bank->bus_width / bank->chip_width; i++) data[0] |= data[i]; *val = data[0]; } else { uint8_t value = 0; for (i = 0; i < bank->bus_width / bank->chip_width; i++) value |= data[bank->bus_width - 1 - i]; *val = value; } return ERROR_OK; } static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, uint16_t *val) { struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH * 2]; int retval; if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 2; i++) { retval = target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { retval = target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data); if (retval != ERROR_OK) return retval; } if (bank->target->endianness == TARGET_LITTLE_ENDIAN) *val = data[0] | data[bank->bus_width] << 8; else *val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8; return ERROR_OK; } static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, uint32_t *val) { struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH * 4]; int retval; if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 4; i++) { retval = target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { retval = target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data); if (retval != ERROR_OK) return retval; } if (bank->target->endianness == TARGET_LITTLE_ENDIAN) *val = data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24; else *val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8 | data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24; return ERROR_OK; } static int cfi_reset(struct flash_bank *bank) { struct cfi_flash_bank *cfi_info = bank->driver_priv; int retval = ERROR_OK; retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; if (cfi_info->manufacturer == 0x20 && (cfi_info->device_id == 0x227E || cfi_info->device_id == 0x7E)) { /* Numonix M29W128G is cmd 0xFF intolerant - causes internal undefined state * so we send an extra 0xF0 reset to fix the bug */ retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00)); if (retval != ERROR_OK) return retval; } return retval; } static void cfi_intel_clear_status_register(struct flash_bank *bank) { cfi_send_command(bank, 0x50, flash_address(bank, 0, 0x0)); } static int cfi_intel_wait_status_busy(struct flash_bank *bank, int timeout, uint8_t *val) { uint8_t status; int retval = ERROR_OK; for (;; ) { if (timeout-- < 0) { LOG_ERROR("timeout while waiting for WSM to become ready"); return ERROR_FAIL; } retval = cfi_get_u8(bank, 0, 0x0, &status); if (retval != ERROR_OK) return retval; if (status & 0x80) break; alive_sleep(1); } /* mask out bit 0 (reserved) */ status = status & 0xfe; LOG_DEBUG("status: 0x%x", status); if (status != 0x80) { LOG_ERROR("status register: 0x%x", status); if (status & 0x2) LOG_ERROR("Block Lock-Bit Detected, Operation Abort"); if (status & 0x4) LOG_ERROR("Program suspended"); if (status & 0x8) LOG_ERROR("Low Programming Voltage Detected, Operation Aborted"); if (status & 0x10) LOG_ERROR("Program Error / Error in Setting Lock-Bit"); if (status & 0x20) LOG_ERROR("Error in Block Erasure or Clear Lock-Bits"); if (status & 0x40) LOG_ERROR("Block Erase Suspended"); cfi_intel_clear_status_register(bank); retval = ERROR_FAIL; } *val = status; return retval; } static int cfi_spansion_wait_status_busy(struct flash_bank *bank, int timeout) { uint8_t status, oldstatus; struct cfi_flash_bank *cfi_info = bank->driver_priv; int retval; retval = cfi_get_u8(bank, 0, 0x0, &oldstatus); if (retval != ERROR_OK) return retval; do { retval = cfi_get_u8(bank, 0, 0x0, &status); if (retval != ERROR_OK) return retval; if ((status ^ oldstatus) & 0x40) { if (status & cfi_info->status_poll_mask & 0x20) { retval = cfi_get_u8(bank, 0, 0x0, &oldstatus); if (retval != ERROR_OK) return retval; retval = cfi_get_u8(bank, 0, 0x0, &status); if (retval != ERROR_OK) return retval; if ((status ^ oldstatus) & 0x40) { LOG_ERROR("dq5 timeout, status: 0x%x", status); return ERROR_FLASH_OPERATION_FAILED; } else { LOG_DEBUG("status: 0x%x", status); return ERROR_OK; } } } else {/* no toggle: finished, OK */ LOG_DEBUG("status: 0x%x", status); return ERROR_OK; } oldstatus = status; alive_sleep(1); } while (timeout-- > 0); LOG_ERROR("timeout, status: 0x%x", status); return ERROR_FLASH_BUSY; } static int cfi_read_intel_pri_ext(struct flash_bank *bank) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_intel_pri_ext *pri_ext; if (cfi_info->pri_ext) free(cfi_info->pri_ext); pri_ext = malloc(sizeof(struct cfi_intel_pri_ext)); if (pri_ext == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } cfi_info->pri_ext = pri_ext; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &pri_ext->pri[0]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &pri_ext->pri[1]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &pri_ext->pri[2]); if (retval != ERROR_OK) return retval; if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) { retval = cfi_reset(bank); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not read bank flash bank information"); return ERROR_FLASH_BANK_INVALID; } retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &pri_ext->major_version); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &pri_ext->minor_version); if (retval != ERROR_OK) return retval; LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version); retval = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5, &pri_ext->feature_support); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9, &pri_ext->suspend_cmd_support); if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa, &pri_ext->blk_status_reg_mask); if (retval != ERROR_OK) return retval; LOG_DEBUG("feature_support: 0x%" PRIx32 ", suspend_cmd_support: " "0x%x, blk_status_reg_mask: 0x%x", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask); retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc, &pri_ext->vcc_optimal); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd, &pri_ext->vpp_optimal); if (retval != ERROR_OK) return retval; LOG_DEBUG("Vcc opt: %x.%x, Vpp opt: %u.%x", (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f, (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f); retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe, &pri_ext->num_protection_fields); if (retval != ERROR_OK) return retval; if (pri_ext->num_protection_fields != 1) { LOG_WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields); } retval = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf, &pri_ext->prot_reg_addr); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11, &pri_ext->fact_prot_reg_size); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12, &pri_ext->user_prot_reg_size); if (retval != ERROR_OK) return retval; LOG_DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, " "factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size); return ERROR_OK; } static int cfi_read_spansion_pri_ext(struct flash_bank *bank) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext; if (cfi_info->pri_ext) free(cfi_info->pri_ext); pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext)); if (pri_ext == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } cfi_info->pri_ext = pri_ext; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &pri_ext->pri[0]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &pri_ext->pri[1]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &pri_ext->pri[2]); if (retval != ERROR_OK) return retval; /* default values for implementation specific workarounds */ pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1; pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2; pri_ext->_reversed_geometry = 0; if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not read spansion bank information"); return ERROR_FLASH_BANK_INVALID; } retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &pri_ext->major_version); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &pri_ext->minor_version); if (retval != ERROR_OK) return retval; LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version); retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5, &pri_ext->SiliconRevision); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6, &pri_ext->EraseSuspend); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7, &pri_ext->BlkProt); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8, &pri_ext->TmpBlkUnprotect); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9, &pri_ext->BlkProtUnprot); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10, &pri_ext->SimultaneousOps); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11, &pri_ext->BurstMode); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12, &pri_ext->PageMode); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13, &pri_ext->VppMin); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14, &pri_ext->VppMax); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15, &pri_ext->TopBottom); if (retval != ERROR_OK) return retval; LOG_DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x", pri_ext->SiliconRevision, pri_ext->EraseSuspend, pri_ext->BlkProt); LOG_DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, " "Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect, pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps); LOG_DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode); LOG_DEBUG("Vpp min: %u.%x, Vpp max: %u.%x", (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f, (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f); LOG_DEBUG("WP# protection 0x%x", pri_ext->TopBottom); return ERROR_OK; } static int cfi_read_atmel_pri_ext(struct flash_bank *bank) { int retval; struct cfi_atmel_pri_ext atmel_pri_ext; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext; if (cfi_info->pri_ext) free(cfi_info->pri_ext); pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext)); if (pri_ext == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion, * but a different primary extended query table. * We read the atmel table, and prepare a valid AMD/Spansion query table. */ memset(pri_ext, 0, sizeof(struct cfi_spansion_pri_ext)); cfi_info->pri_ext = pri_ext; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &atmel_pri_ext.pri[0]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &atmel_pri_ext.pri[1]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &atmel_pri_ext.pri[2]); if (retval != ERROR_OK) return retval; if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I')) { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not read atmel bank information"); return ERROR_FLASH_BANK_INVALID; } pri_ext->pri[0] = atmel_pri_ext.pri[0]; pri_ext->pri[1] = atmel_pri_ext.pri[1]; pri_ext->pri[2] = atmel_pri_ext.pri[2]; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &atmel_pri_ext.major_version); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &atmel_pri_ext.minor_version); if (retval != ERROR_OK) return retval; LOG_DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0], atmel_pri_ext.pri[1], atmel_pri_ext.pri[2], atmel_pri_ext.major_version, atmel_pri_ext.minor_version); pri_ext->major_version = atmel_pri_ext.major_version; pri_ext->minor_version = atmel_pri_ext.minor_version; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5, &atmel_pri_ext.features); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6, &atmel_pri_ext.bottom_boot); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7, &atmel_pri_ext.burst_mode); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8, &atmel_pri_ext.page_mode); if (retval != ERROR_OK) return retval; LOG_DEBUG( "features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x", atmel_pri_ext.features, atmel_pri_ext.bottom_boot, atmel_pri_ext.burst_mode, atmel_pri_ext.page_mode); if (atmel_pri_ext.features & 0x02) pri_ext->EraseSuspend = 2; /* some chips got it backwards... */ if (cfi_info->device_id == AT49BV6416 || cfi_info->device_id == AT49BV6416T) { if (atmel_pri_ext.bottom_boot) pri_ext->TopBottom = 3; else pri_ext->TopBottom = 2; } else { if (atmel_pri_ext.bottom_boot) pri_ext->TopBottom = 2; else pri_ext->TopBottom = 3; } pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1; pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2; return ERROR_OK; } static int cfi_read_0002_pri_ext(struct flash_bank *bank) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (cfi_info->manufacturer == CFI_MFR_ATMEL) return cfi_read_atmel_pri_ext(bank); else return cfi_read_spansion_pri_ext(bank); } static int cfi_spansion_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n"); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n", (pri_ext->SiliconRevision) >> 2, (pri_ext->SiliconRevision) & 0x03); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n", pri_ext->EraseSuspend, pri_ext->BlkProt); buf += printed; buf_size -= printed; snprintf(buf, buf_size, "VppMin: %u.%x, VppMax: %u.%x\n", (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f, (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f); return ERROR_OK; } static int cfi_intel_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext; printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n"); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "feature_support: 0x%" PRIx32 ", " "suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "Vcc opt: %x.%x, Vpp opt: %u.%x\n", (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f, (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f); buf += printed; buf_size -= printed; snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, " "factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size); return ERROR_OK; } /* flash_bank cfi [options] */ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command) { struct cfi_flash_bank *cfi_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; /* both widths must: * - not exceed max value; * - not be null; * - be equal to a power of 2. * bus must be wide enough to hold one chip */ if ((bank->chip_width > CFI_MAX_CHIP_WIDTH) || (bank->bus_width > CFI_MAX_BUS_WIDTH) || (bank->chip_width == 0) || (bank->bus_width == 0) || (bank->chip_width & (bank->chip_width - 1)) || (bank->bus_width & (bank->bus_width - 1)) || (bank->chip_width > bank->bus_width)) { LOG_ERROR("chip and bus width have to specified in bytes"); return ERROR_FLASH_BANK_INVALID; } cfi_info = malloc(sizeof(struct cfi_flash_bank)); cfi_info->probed = 0; cfi_info->erase_region_info = NULL; cfi_info->pri_ext = NULL; bank->driver_priv = cfi_info; cfi_info->x16_as_x8 = 0; cfi_info->jedec_probe = 0; cfi_info->not_cfi = 0; for (unsigned i = 6; i < CMD_ARGC; i++) { if (strcmp(CMD_ARGV[i], "x16_as_x8") == 0) cfi_info->x16_as_x8 = 1; else if (strcmp(CMD_ARGV[i], "jedec_probe") == 0) cfi_info->jedec_probe = 1; } /* bank wasn't probed yet */ cfi_info->qry[0] = 0xff; return ERROR_OK; } static int cfi_intel_erase(struct flash_bank *bank, int first, int last) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; int i; cfi_intel_clear_status_register(bank); for (i = first; i <= last; i++) { retval = cfi_send_command(bank, 0x20, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; uint8_t status; retval = cfi_intel_wait_status_busy(bank, cfi_info->block_erase_timeout, &status); if (retval != ERROR_OK) return retval; if (status == 0x80) bank->sectors[i].is_erased = 1; else { retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" PRIx32, i, bank->base); return ERROR_FLASH_OPERATION_FAILED; } } return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); } static int cfi_spansion_erase(struct flash_bank *bank, int first, int last) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; int i; for (i = first; i <= last; i++) { retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x80, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x30, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->block_erase_timeout) == ERROR_OK) bank->sectors[i].is_erased = 1; else { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" PRIx32, i, bank->base); return ERROR_FLASH_OPERATION_FAILED; } } return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); } static int cfi_erase(struct flash_bank *bank, int first, int last) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; if (cfi_info->qry[0] != 'Q') return ERROR_FLASH_BANK_NOT_PROBED; switch (cfi_info->pri_id) { case 1: case 3: return cfi_intel_erase(bank, first, last); break; case 2: return cfi_spansion_erase(bank, first, last); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } return ERROR_OK; } static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int last) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext; int retry = 0; int i; /* if the device supports neither legacy lock/unlock (bit 3) nor * instant individual block locking (bit 5). */ if (!(pri_ext->feature_support & 0x28)) { LOG_ERROR("lock/unlock not supported on flash"); return ERROR_FLASH_OPERATION_FAILED; } cfi_intel_clear_status_register(bank); for (i = first; i <= last; i++) { retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; if (set) { retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; bank->sectors[i].is_protected = 1; } else { retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; bank->sectors[i].is_protected = 0; } /* instant individual block locking doesn't require reading of the status register **/ if (!(pri_ext->feature_support & 0x20)) { /* Clear lock bits operation may take up to 1.4s */ uint8_t status; retval = cfi_intel_wait_status_busy(bank, 1400, &status); if (retval != ERROR_OK) return retval; } else { uint8_t block_status; /* read block lock bit, to verify status */ retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; retval = cfi_get_u8(bank, i, 0x2, &block_status); if (retval != ERROR_OK) return retval; if ((block_status & 0x1) != set) { LOG_ERROR( "couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status); retval = cfi_send_command(bank, 0x70, flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; uint8_t status; retval = cfi_intel_wait_status_busy(bank, 10, &status); if (retval != ERROR_OK) return retval; if (retry > 10) return ERROR_FLASH_OPERATION_FAILED; else { i--; retry++; } } } } /* if the device doesn't support individual block lock bits set/clear, * all blocks have been unlocked in parallel, so we set those that should be protected */ if ((!set) && (!(pri_ext->feature_support & 0x20))) { /* FIX!!! this code path is broken!!! * * The correct approach is: * * 1. read out current protection status * * 2. override read out protection status w/unprotected. * * 3. re-protect what should be protected. * */ for (i = 0; i < bank->num_sectors; i++) { if (bank->sectors[i].is_protected == 1) { cfi_intel_clear_status_register(bank); retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; uint8_t status; retval = cfi_intel_wait_status_busy(bank, 100, &status); if (retval != ERROR_OK) return retval; } } } return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); } static int cfi_protect(struct flash_bank *bank, int set, int first, int last) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Invalid sector range"); return ERROR_FLASH_SECTOR_INVALID; } if (cfi_info->qry[0] != 'Q') return ERROR_FLASH_BANK_NOT_PROBED; switch (cfi_info->pri_id) { case 1: case 3: return cfi_intel_protect(bank, set, first, last); break; default: LOG_WARNING("protect: cfi primary command set %i unsupported", cfi_info->pri_id); return ERROR_OK; } } static uint32_t cfi_command_val(struct flash_bank *bank, uint8_t cmd) { struct target *target = bank->target; uint8_t buf[CFI_MAX_BUS_WIDTH]; cfi_command(bank, cmd, buf); switch (bank->bus_width) { case 1: return buf[0]; break; case 2: return target_buffer_get_u16(target, buf); break; case 4: return target_buffer_get_u32(target, buf); break; default: LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width); return 0; } } static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct target *target = bank->target; struct reg_param reg_params[7]; struct arm_algorithm arm_algo; struct working_area *write_algorithm; struct working_area *source = NULL; uint32_t buffer_size = 32768; uint32_t write_command_val, busy_pattern_val, error_pattern_val; /* algorithm register usage: * r0: source address (in RAM) * r1: target address (in Flash) * r2: count * r3: flash write command * r4: status byte (returned to host) * r5: busy test pattern * r6: error test pattern */ /* see contib/loaders/flash/armv4_5_cfi_intel_32.s for src */ static const uint32_t word_32_code[] = { 0xe4904004, /* loop: ldr r4, [r0], #4 */ 0xe5813000, /* str r3, [r1] */ 0xe5814000, /* str r4, [r1] */ 0xe5914000, /* busy: ldr r4, [r1] */ 0xe0047005, /* and r7, r4, r5 */ 0xe1570005, /* cmp r7, r5 */ 0x1afffffb, /* bne busy */ 0xe1140006, /* tst r4, r6 */ 0x1a000003, /* bne done */ 0xe2522001, /* subs r2, r2, #1 */ 0x0a000001, /* beq done */ 0xe2811004, /* add r1, r1 #4 */ 0xeafffff2, /* b loop */ 0xeafffffe /* done: b -2 */ }; /* see contib/loaders/flash/armv4_5_cfi_intel_16.s for src */ static const uint32_t word_16_code[] = { 0xe0d040b2, /* loop: ldrh r4, [r0], #2 */ 0xe1c130b0, /* strh r3, [r1] */ 0xe1c140b0, /* strh r4, [r1] */ 0xe1d140b0, /* busy ldrh r4, [r1] */ 0xe0047005, /* and r7, r4, r5 */ 0xe1570005, /* cmp r7, r5 */ 0x1afffffb, /* bne busy */ 0xe1140006, /* tst r4, r6 */ 0x1a000003, /* bne done */ 0xe2522001, /* subs r2, r2, #1 */ 0x0a000001, /* beq done */ 0xe2811002, /* add r1, r1 #2 */ 0xeafffff2, /* b loop */ 0xeafffffe /* done: b -2 */ }; /* see contib/loaders/flash/armv4_5_cfi_intel_8.s for src */ static const uint32_t word_8_code[] = { 0xe4d04001, /* loop: ldrb r4, [r0], #1 */ 0xe5c13000, /* strb r3, [r1] */ 0xe5c14000, /* strb r4, [r1] */ 0xe5d14000, /* busy ldrb r4, [r1] */ 0xe0047005, /* and r7, r4, r5 */ 0xe1570005, /* cmp r7, r5 */ 0x1afffffb, /* bne busy */ 0xe1140006, /* tst r4, r6 */ 0x1a000003, /* bne done */ 0xe2522001, /* subs r2, r2, #1 */ 0x0a000001, /* beq done */ 0xe2811001, /* add r1, r1 #1 */ 0xeafffff2, /* b loop */ 0xeafffffe /* done: b -2 */ }; uint8_t target_code[4*CFI_MAX_INTEL_CODESIZE]; const uint32_t *target_code_src; uint32_t target_code_size; int retval = ERROR_OK; /* check we have a supported arch */ if (is_arm(target_to_arm(target))) { /* All other ARM CPUs have 32 bit instructions */ arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; } else { LOG_ERROR("Unknown architecture"); return ERROR_FAIL; } cfi_intel_clear_status_register(bank); /* If we are setting up the write_algorith, we need target_code_src * if not we only need target_code_size. */ /* However, we don't want to create multiple code paths, so we * do the unnecessary evaluation of target_code_src, which the * compiler will probably nicely optimize away if not needed */ /* prepare algorithm code for target endian */ switch (bank->bus_width) { case 1: target_code_src = word_8_code; target_code_size = sizeof(word_8_code); break; case 2: target_code_src = word_16_code; target_code_size = sizeof(word_16_code); break; case 4: target_code_src = word_32_code; target_code_size = sizeof(word_32_code); break; default: LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* flash write code */ if (target_code_size > sizeof(target_code)) { LOG_WARNING("Internal error - target code buffer to small. " "Increase CFI_MAX_INTEL_CODESIZE and recompile."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* Get memory for block write handler */ retval = target_alloc_working_area(target, target_code_size, &write_algorithm); if (retval != ERROR_OK) { LOG_WARNING("No working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } ; /* write algorithm code to working area */ retval = target_write_buffer(target, write_algorithm->address, target_code_size, target_code); if (retval != ERROR_OK) { LOG_ERROR("Unable to write block write code to target"); goto cleanup; } /* Get a workspace buffer for the data to flash starting with 32k size. * Half size until buffer would be smaller 256 Bytes then fail back */ /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { LOG_WARNING( "no large enough working area available, can't do block memory writes"); retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; goto cleanup; } } ; /* setup algo registers */ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_OUT); init_reg_param(®_params[4], "r4", 32, PARAM_IN); init_reg_param(®_params[5], "r5", 32, PARAM_OUT); init_reg_param(®_params[6], "r6", 32, PARAM_OUT); /* prepare command and status register patterns */ write_command_val = cfi_command_val(bank, 0x40); busy_pattern_val = cfi_command_val(bank, 0x80); error_pattern_val = cfi_command_val(bank, 0x7e); LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, source->address, buffer_size); /* Programming main loop */ while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; uint32_t wsm_error; retval = target_write_buffer(target, source->address, thisrun_count, buffer); if (retval != ERROR_OK) goto cleanup; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); buf_set_u32(reg_params[3].value, 0, 32, write_command_val); buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val); buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val); LOG_DEBUG("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32, thisrun_count, address); /* Execute algorithm, assume breakpoint for last instruction */ retval = target_run_algorithm(target, 0, NULL, 7, reg_params, write_algorithm->address, write_algorithm->address + target_code_size - sizeof(uint32_t), 10000, /* 10s should be enough for max. 32k of data */ &arm_algo); /* On failure try a fall back to direct word writes */ if (retval != ERROR_OK) { cfi_intel_clear_status_register(bank); LOG_ERROR( "Execution of flash algorythm failed. Can't fall back. Please report."); retval = ERROR_FLASH_OPERATION_FAILED; /* retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; */ /* FIXME To allow fall back or recovery, we must save the actual status * somewhere, so that a higher level code can start recovery. */ goto cleanup; } /* Check return value from algo code */ wsm_error = buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val; if (wsm_error) { /* read status register (outputs debug information) */ uint8_t status; cfi_intel_wait_status_busy(bank, 100, &status); cfi_intel_clear_status_register(bank); retval = ERROR_FLASH_OPERATION_FAILED; goto cleanup; } buffer += thisrun_count; address += thisrun_count; count -= thisrun_count; keep_alive(); } /* free up resources */ cleanup: if (source) target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); destroy_reg_param(®_params[6]); return retval; } static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; struct target *target = bank->target; struct reg_param reg_params[10]; struct mips32_algorithm mips32_info; struct working_area *write_algorithm; struct working_area *source; uint32_t buffer_size = 32768; uint32_t status; int retval = ERROR_OK; /* input parameters - * 4 A0 = source address * 5 A1 = destination address * 6 A2 = number of writes * 7 A3 = flash write command * 8 T0 = constant to mask DQ7 bits (also used for Dq5 with shift) * output parameters - * 9 T1 = 0x80 ok 0x00 bad * temp registers - * 10 T2 = value read from flash to test status * 11 T3 = holding register * unlock registers - * 12 T4 = unlock1_addr * 13 T5 = unlock1_cmd * 14 T6 = unlock2_addr * 15 T7 = unlock2_cmd */ static const uint32_t mips_word_16_code[] = { /* start: */ MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ MIPS32_NOP, /* nop */ /* busy: */ MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_NOP, /* nop */ MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ MIPS32_NOP, /* nop */ MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_NOP, /* nop */ MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ MIPS32_NOP, /* nop */ /* cont: */ MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ MIPS32_NOP, /* nop */ MIPS32_LUI(9, 0), /* lui $t1, 0 */ MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ MIPS32_B(4), /* b done ; goto done */ MIPS32_NOP, /* nop */ /* cont2: */ MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ MIPS32_B(NEG16(33)), /* b start ; goto start */ MIPS32_NOP, /* nop */ /* done: */ MIPS32_SDBBP, /* sdbbp ; break(); */ }; mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; int target_code_size = 0; const uint32_t *target_code_src = NULL; switch (bank->bus_width) { case 2: /* Check for DQ5 support */ if (cfi_info->status_poll_mask & (1 << 5)) { target_code_src = mips_word_16_code; target_code_size = sizeof(mips_word_16_code); } else { LOG_ERROR("Need DQ5 support"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* target_code_src = mips_word_16_code_dq7only; */ /* target_code_size = sizeof(mips_word_16_code_dq7only); */ } break; default: LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* flash write code */ uint8_t *target_code; /* convert bus-width dependent algorithm code to correct endianness */ target_code = malloc(target_code_size); if (target_code == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* allocate working area */ retval = target_alloc_working_area(target, target_code_size, &write_algorithm); if (retval != ERROR_OK) { free(target_code); return retval; } /* write algorithm code to working area */ retval = target_write_buffer(target, write_algorithm->address, target_code_size, target_code); if (retval != ERROR_OK) { free(target_code); return retval; } free(target_code); /* the following code still assumes target code is fixed 24*4 bytes */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING( "not enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } ; init_reg_param(®_params[0], "a0", 32, PARAM_OUT); init_reg_param(®_params[1], "a1", 32, PARAM_OUT); init_reg_param(®_params[2], "a2", 32, PARAM_OUT); init_reg_param(®_params[3], "a3", 32, PARAM_OUT); init_reg_param(®_params[4], "t0", 32, PARAM_OUT); init_reg_param(®_params[5], "t1", 32, PARAM_IN); init_reg_param(®_params[6], "t4", 32, PARAM_OUT); init_reg_param(®_params[7], "t5", 32, PARAM_OUT); init_reg_param(®_params[8], "t6", 32, PARAM_OUT); init_reg_param(®_params[9], "t7", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; retval = target_write_buffer(target, source->address, thisrun_count, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0)); buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80)); buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1)); buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa); buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2)); buf_set_u32(reg_params[9].value, 0, 32, 0x55555555); retval = target_run_algorithm(target, 0, NULL, 10, reg_params, write_algorithm->address, write_algorithm->address + ((target_code_size) - 4), 10000, &mips32_info); if (retval != ERROR_OK) break; status = buf_get_u32(reg_params[5].value, 0, 32); if (status != 0x80) { LOG_ERROR("flash write block failed status: 0x%" PRIx32, status); retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count; address += thisrun_count; count -= thisrun_count; } target_free_all_working_areas(target); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); destroy_reg_param(®_params[6]); destroy_reg_param(®_params[7]); destroy_reg_param(®_params[8]); destroy_reg_param(®_params[9]); return retval; } static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; struct target *target = bank->target; struct reg_param reg_params[10]; void *arm_algo; struct arm_algorithm armv4_5_algo; struct armv7m_algorithm armv7m_algo; struct working_area *write_algorithm; struct working_area *source; uint32_t buffer_size = 32768; uint32_t status; int retval = ERROR_OK; /* input parameters - * R0 = source address * R1 = destination address * R2 = number of writes * R3 = flash write command * R4 = constant to mask DQ7 bits (also used for Dq5 with shift) * output parameters - * R5 = 0x80 ok 0x00 bad * temp registers - * R6 = value read from flash to test status * R7 = holding register * unlock registers - * R8 = unlock1_addr * R9 = unlock1_cmd * R10 = unlock2_addr * R11 = unlock2_cmd */ /* see contib/loaders/flash/armv4_5_cfi_span_32.s for src */ static const uint32_t armv4_5_word_32_code[] = { /* 00008100 : */ 0xe4905004, /* ldr r5, [r0], #4 */ 0xe5889000, /* str r9, [r8] */ 0xe58ab000, /* str r11, [r10] */ 0xe5883000, /* str r3, [r8] */ 0xe5815000, /* str r5, [r1] */ 0xe1a00000, /* nop */ /* 00008110 : */ 0xe5916000, /* ldr r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000007, /* beq 8140 ; b if DQ7 == Data7 */ 0xe0166124, /* ands r6, r6, r4, lsr #2 */ 0x0afffff9, /* beq 8110 ; b if DQ5 low */ 0xe5916000, /* ldr r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000001, /* beq 8140 ; b if DQ7 == Data7 */ 0xe3a05000, /* mov r5, #0 ; 0x0 - return 0x00, error */ 0x1a000004, /* bne 8154 */ /* 00008140 : */ 0xe2522001, /* subs r2, r2, #1 ; 0x1 */ 0x03a05080, /* moveq r5, #128 ; 0x80 */ 0x0a000001, /* beq 8154 */ 0xe2811004, /* add r1, r1, #4 ; 0x4 */ 0xeaffffe8, /* b 8100 */ /* 00008154 : */ 0xeafffffe /* b 8154 */ }; /* see contib/loaders/flash/armv4_5_cfi_span_16.s for src */ static const uint32_t armv4_5_word_16_code[] = { /* 00008158 : */ 0xe0d050b2, /* ldrh r5, [r0], #2 */ 0xe1c890b0, /* strh r9, [r8] */ 0xe1cab0b0, /* strh r11, [r10] */ 0xe1c830b0, /* strh r3, [r8] */ 0xe1c150b0, /* strh r5, [r1] */ 0xe1a00000, /* nop (mov r0,r0) */ /* 00008168 : */ 0xe1d160b0, /* ldrh r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000007, /* beq 8198 */ 0xe0166124, /* ands r6, r6, r4, lsr #2 */ 0x0afffff9, /* beq 8168 */ 0xe1d160b0, /* ldrh r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000001, /* beq 8198 */ 0xe3a05000, /* mov r5, #0 ; 0x0 */ 0x1a000004, /* bne 81ac */ /* 00008198 : */ 0xe2522001, /* subs r2, r2, #1 ; 0x1 */ 0x03a05080, /* moveq r5, #128 ; 0x80 */ 0x0a000001, /* beq 81ac */ 0xe2811002, /* add r1, r1, #2 ; 0x2 */ 0xeaffffe8, /* b 8158 */ /* 000081ac : */ 0xeafffffe /* b 81ac */ }; /* see contrib/loaders/flash/armv7m_cfi_span_16.s for src */ static const uint32_t armv7m_word_16_code[] = { 0x5B02F830, 0x9000F8A8, 0xB000F8AA, 0x3000F8A8, 0xBF00800D, 0xEA85880E, 0x40270706, 0xEA16D00A, 0xD0F70694, 0xEA85880E, 0x40270706, 0xF04FD002, 0xD1070500, 0xD0023A01, 0x0102F101, 0xF04FE7E0, 0xE7FF0580, 0x0000BE00 }; /* see contrib/loaders/flash/armv7m_cfi_span_16_dq7.s for src */ static const uint32_t armv7m_word_16_code_dq7only[] = { /* 00000000 : */ 0x5B02F830, /* ldrh.w r5, [r0], #2 */ 0x9000F8A8, /* strh.w r9, [r8] */ 0xB000F8AA, /* strh.w fp, [sl] */ 0x3000F8A8, /* strh.w r3, [r8] */ 0xBF00800D, /* strh r5, [r1, #0] */ /* nop */ /* 00000014 : */ 0xEA85880E, /* ldrh r6, [r1, #0] */ /* eor.w r7, r5, r6 */ 0x40270706, /* ands r7, r4 */ 0x3A01D1FA, /* bne.n 14 */ /* subs r2, #1 */ 0xF101D002, /* beq.n 28 */ 0xE7EB0102, /* add.w r1, r1, #2 */ /* b.n 0 */ /* 00000028 : */ 0x0580F04F, /* mov.w r5, #128 */ 0xBF00E7FF, /* b.n 30 */ /* nop (for alignment purposes) */ /* 00000030 : */ 0x0000BE00 /* bkpt 0x0000 */ }; /* see contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */ static const uint32_t armv4_5_word_16_code_dq7only[] = { /* : */ 0xe0d050b2, /* ldrh r5, [r0], #2 */ 0xe1c890b0, /* strh r9, [r8] */ 0xe1cab0b0, /* strh r11, [r10] */ 0xe1c830b0, /* strh r3, [r8] */ 0xe1c150b0, /* strh r5, [r1] */ 0xe1a00000, /* nop (mov r0,r0) */ /* : */ 0xe1d160b0, /* ldrh r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe2177080, /* ands r7, #0x80 */ 0x1afffffb, /* bne 8168 */ /* */ 0xe2522001, /* subs r2, r2, #1 ; 0x1 */ 0x03a05080, /* moveq r5, #128 ; 0x80 */ 0x0a000001, /* beq 81ac */ 0xe2811002, /* add r1, r1, #2 ; 0x2 */ 0xeafffff0, /* b 8158 */ /* 000081ac : */ 0xeafffffe /* b 81ac */ }; /* see contrib/loaders/flash/armv4_5_cfi_span_8.s for src */ static const uint32_t armv4_5_word_8_code[] = { /* 000081b0 : */ 0xe4d05001, /* ldrb r5, [r0], #1 */ 0xe5c89000, /* strb r9, [r8] */ 0xe5cab000, /* strb r11, [r10] */ 0xe5c83000, /* strb r3, [r8] */ 0xe5c15000, /* strb r5, [r1] */ 0xe1a00000, /* nop (mov r0,r0) */ /* 000081c0 : */ 0xe5d16000, /* ldrb r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000007, /* beq 81f0 */ 0xe0166124, /* ands r6, r6, r4, lsr #2 */ 0x0afffff9, /* beq 81c0 */ 0xe5d16000, /* ldrb r6, [r1] */ 0xe0257006, /* eor r7, r5, r6 */ 0xe0147007, /* ands r7, r4, r7 */ 0x0a000001, /* beq 81f0 */ 0xe3a05000, /* mov r5, #0 ; 0x0 */ 0x1a000004, /* bne 8204 */ /* 000081f0 : */ 0xe2522001, /* subs r2, r2, #1 ; 0x1 */ 0x03a05080, /* moveq r5, #128 ; 0x80 */ 0x0a000001, /* beq 8204 */ 0xe2811001, /* add r1, r1, #1 ; 0x1 */ 0xeaffffe8, /* b 81b0 */ /* 00008204 : */ 0xeafffffe /* b 8204 */ }; if (strncmp(target_type_name(target), "mips_m4k", 8) == 0) return cfi_spansion_write_block_mips(bank, buffer, address, count); if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */ armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; armv7m_algo.core_mode = ARM_MODE_THREAD; arm_algo = &armv7m_algo; } else if (is_arm(target_to_arm(target))) { /* All other ARM CPUs have 32 bit instructions */ armv4_5_algo.common_magic = ARM_COMMON_MAGIC; armv4_5_algo.core_mode = ARM_MODE_SVC; armv4_5_algo.core_state = ARM_STATE_ARM; arm_algo = &armv4_5_algo; } else { LOG_ERROR("Unknown architecture"); return ERROR_FAIL; } int target_code_size = 0; const uint32_t *target_code_src = NULL; switch (bank->bus_width) { case 1: if (is_armv7m(target_to_armv7m(target))) { LOG_ERROR("Unknown ARM architecture"); return ERROR_FAIL; } target_code_src = armv4_5_word_8_code; target_code_size = sizeof(armv4_5_word_8_code); break; case 2: /* Check for DQ5 support */ if (cfi_info->status_poll_mask & (1 << 5)) { if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */ target_code_src = armv7m_word_16_code; target_code_size = sizeof(armv7m_word_16_code); } else { /* armv4_5 target */ target_code_src = armv4_5_word_16_code; target_code_size = sizeof(armv4_5_word_16_code); } } else { /* No DQ5 support. Use DQ7 DATA# polling only. */ if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */ target_code_src = armv7m_word_16_code_dq7only; target_code_size = sizeof(armv7m_word_16_code_dq7only); } else { /* armv4_5 target */ target_code_src = armv4_5_word_16_code_dq7only; target_code_size = sizeof(armv4_5_word_16_code_dq7only); } } break; case 4: if (is_armv7m(target_to_armv7m(target))) { LOG_ERROR("Unknown ARM architecture"); return ERROR_FAIL; } target_code_src = armv4_5_word_32_code; target_code_size = sizeof(armv4_5_word_32_code); break; default: LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* flash write code */ uint8_t *target_code; /* convert bus-width dependent algorithm code to correct endianness */ target_code = malloc(target_code_size); if (target_code == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* allocate working area */ retval = target_alloc_working_area(target, target_code_size, &write_algorithm); if (retval != ERROR_OK) { free(target_code); return retval; } /* write algorithm code to working area */ retval = target_write_buffer(target, write_algorithm->address, target_code_size, target_code); if (retval != ERROR_OK) { free(target_code); return retval; } free(target_code); /* the following code still assumes target code is fixed 24*4 bytes */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING( "not enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } ; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_OUT); init_reg_param(®_params[4], "r4", 32, PARAM_OUT); init_reg_param(®_params[5], "r5", 32, PARAM_IN); init_reg_param(®_params[6], "r8", 32, PARAM_OUT); init_reg_param(®_params[7], "r9", 32, PARAM_OUT); init_reg_param(®_params[8], "r10", 32, PARAM_OUT); init_reg_param(®_params[9], "r11", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; retval = target_write_buffer(target, source->address, thisrun_count, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0)); buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80)); buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1)); buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa); buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2)); buf_set_u32(reg_params[9].value, 0, 32, 0x55555555); retval = target_run_algorithm(target, 0, NULL, 10, reg_params, write_algorithm->address, write_algorithm->address + ((target_code_size) - 4), 10000, arm_algo); if (retval != ERROR_OK) break; status = buf_get_u32(reg_params[5].value, 0, 32); if (status != 0x80) { LOG_ERROR("flash write block failed status: 0x%" PRIx32, status); retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count; address += thisrun_count; count -= thisrun_count; } target_free_all_working_areas(target); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); destroy_reg_param(®_params[6]); destroy_reg_param(®_params[7]); destroy_reg_param(®_params[8]); destroy_reg_param(®_params[9]); return retval; } static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; cfi_intel_clear_status_register(bank); retval = cfi_send_command(bank, 0x40, address); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, address, bank->bus_width, 1, word); if (retval != ERROR_OK) return retval; uint8_t status; retval = cfi_intel_wait_status_busy(bank, cfi_info->word_write_timeout, &status); if (retval != 0x80) { retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("couldn't write word at base 0x%" PRIx32 ", address 0x%" PRIx32, bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; /* Calculate buffer size and boundary mask * buffersize is (buffer size per chip) * (number of chips) * bufferwsize is buffersize in words */ uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width); uint32_t buffermask = buffersize-1; uint32_t bufferwsize = buffersize / bank->bus_width; /* Check for valid range */ if (address & buffermask) { LOG_ERROR("Write address at base 0x%" PRIx32 ", address 0x%" PRIx32 " not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size); return ERROR_FLASH_OPERATION_FAILED; } /* Check for valid size */ if (wordcount > bufferwsize) { LOG_ERROR("Number of data words %" PRId32 " exceeds available buffersize %" PRId32, wordcount, buffersize); return ERROR_FLASH_OPERATION_FAILED; } /* Write to flash buffer */ cfi_intel_clear_status_register(bank); /* Initiate buffer operation _*/ retval = cfi_send_command(bank, 0xe8, address); if (retval != ERROR_OK) return retval; uint8_t status; retval = cfi_intel_wait_status_busy(bank, cfi_info->buf_write_timeout, &status); if (retval != ERROR_OK) return retval; if (status != 0x80) { retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR( "couldn't start buffer write operation at base 0x%" PRIx32 ", address 0x%" PRIx32, bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } /* Write buffer wordcount-1 and data words */ retval = cfi_send_command(bank, bufferwsize-1, address); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, address, bank->bus_width, bufferwsize, word); if (retval != ERROR_OK) return retval; /* Commit write operation */ retval = cfi_send_command(bank, 0xd0, address); if (retval != ERROR_OK) return retval; retval = cfi_intel_wait_status_busy(bank, cfi_info->buf_write_timeout, &status); if (retval != ERROR_OK) return retval; if (status != 0x80) { retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("Buffer write at base 0x%" PRIx32 ", address 0x%" PRIx32 " failed.", bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; struct target *target = bank->target; retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0xa0, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, address, bank->bus_width, 1, word); if (retval != ERROR_OK) return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->word_write_timeout) != ERROR_OK) { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("couldn't write word at base 0x%" PRIx32 ", address 0x%" PRIx32, bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; /* Calculate buffer size and boundary mask * buffersize is (buffer size per chip) * (number of chips) * bufferwsize is buffersize in words */ uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width); uint32_t buffermask = buffersize-1; uint32_t bufferwsize = buffersize / bank->bus_width; /* Check for valid range */ if (address & buffermask) { LOG_ERROR("Write address at base 0x%" PRIx32 ", address 0x%" PRIx32 " not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size); return ERROR_FLASH_OPERATION_FAILED; } /* Check for valid size */ if (wordcount > bufferwsize) { LOG_ERROR("Number of data words %" PRId32 " exceeds available buffersize %" PRId32, wordcount, buffersize); return ERROR_FLASH_OPERATION_FAILED; } /* Unlock */ retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; /* Buffer load command */ retval = cfi_send_command(bank, 0x25, address); if (retval != ERROR_OK) return retval; /* Write buffer wordcount-1 and data words */ retval = cfi_send_command(bank, bufferwsize-1, address); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, address, bank->bus_width, bufferwsize, word); if (retval != ERROR_OK) return retval; /* Commit write operation */ retval = cfi_send_command(bank, 0x29, address); if (retval != ERROR_OK) return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->buf_write_timeout) != ERROR_OK) { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("couldn't write block at base 0x%" PRIx32 ", address 0x%" PRIx32 ", size 0x%" PRIx32, bank->base, address, bufferwsize); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address) { struct cfi_flash_bank *cfi_info = bank->driver_priv; switch (cfi_info->pri_id) { case 1: case 3: return cfi_intel_write_word(bank, word, address); break; case 2: return cfi_spansion_write_word(bank, word, address); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } return ERROR_FLASH_OPERATION_FAILED; } static int cfi_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (cfi_info->buf_write_timeout_typ == 0) { /* buffer writes are not supported */ LOG_DEBUG("Buffer Writes Not Supported"); return ERROR_FLASH_OPER_UNSUPPORTED; } switch (cfi_info->pri_id) { case 1: case 3: return cfi_intel_write_words(bank, word, wordcount, address); break; case 2: return cfi_spansion_write_words(bank, word, wordcount, address); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } return ERROR_FLASH_OPERATION_FAILED; } static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; uint32_t address = bank->base + offset; uint32_t read_p; int align; /* number of unaligned bytes */ uint8_t current_word[CFI_MAX_BUS_WIDTH]; int i; int retval; LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", (int)count, (unsigned)offset); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; if (cfi_info->qry[0] != 'Q') return ERROR_FLASH_BANK_NOT_PROBED; /* start at the first byte of the first word (bus_width size) */ read_p = address & ~(bank->bus_width - 1); align = address - read_p; if (align != 0) { LOG_INFO("Fixup %d unaligned read head bytes", align); /* read a complete word from flash */ retval = target_read_memory(target, read_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; /* take only bytes we need */ for (i = align; (i < bank->bus_width) && (count > 0); i++, count--) *buffer++ = current_word[i]; read_p += bank->bus_width; } align = count / bank->bus_width; if (align) { retval = target_read_memory(target, read_p, bank->bus_width, align, buffer); if (retval != ERROR_OK) return retval; read_p += align * bank->bus_width; buffer += align * bank->bus_width; count -= align * bank->bus_width; } if (count) { LOG_INFO("Fixup %" PRIu32 " unaligned read tail bytes", count); /* read a complete word from flash */ retval = target_read_memory(target, read_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; /* take only bytes we need */ for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--) *buffer++ = current_word[i]; } return ERROR_OK; } static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; uint32_t address = bank->base + offset; /* address of first byte to be programmed */ uint32_t write_p; int align; /* number of unaligned bytes */ int blk_count; /* number of bus_width bytes for block copy */ uint8_t current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being *programmed */ int i; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; if (cfi_info->qry[0] != 'Q') return ERROR_FLASH_BANK_NOT_PROBED; /* start at the first byte of the first word (bus_width size) */ write_p = address & ~(bank->bus_width - 1); align = address - write_p; if (align != 0) { LOG_INFO("Fixup %d unaligned head bytes", align); /* read a complete word from flash */ retval = target_read_memory(target, write_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; /* replace only bytes that must be written */ for (i = align; (i < bank->bus_width) && (count > 0); i++, count--) current_word[i] = *buffer++; retval = cfi_write_word(bank, current_word, write_p); if (retval != ERROR_OK) return retval; write_p += bank->bus_width; } /* handle blocks of bus_size aligned bytes */ blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */ switch (cfi_info->pri_id) { /* try block writes (fails without working area) */ case 1: case 3: retval = cfi_intel_write_block(bank, buffer, write_p, blk_count); break; case 2: retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (retval == ERROR_OK) { /* Increment pointers and decrease count on succesful block write */ buffer += blk_count; write_p += blk_count; count -= blk_count; } else { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* Calculate buffer size and boundary mask * buffersize is (buffer size per chip) * (number of chips) * bufferwsize is buffersize in words */ uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width); uint32_t buffermask = buffersize-1; uint32_t bufferwsize = buffersize / bank->bus_width; /* fall back to memory writes */ while (count >= (uint32_t)bank->bus_width) { int fallback; if ((write_p & 0xff) == 0) { LOG_INFO("Programming at 0x%08" PRIx32 ", count 0x%08" PRIx32 " bytes remaining", write_p, count); } fallback = 1; if ((bufferwsize > 0) && (count >= buffersize) && !(write_p & buffermask)) { retval = cfi_write_words(bank, buffer, bufferwsize, write_p); if (retval == ERROR_OK) { buffer += buffersize; write_p += buffersize; count -= buffersize; fallback = 0; } else if (retval != ERROR_FLASH_OPER_UNSUPPORTED) return retval; } /* try the slow way? */ if (fallback) { for (i = 0; i < bank->bus_width; i++) current_word[i] = *buffer++; retval = cfi_write_word(bank, current_word, write_p); if (retval != ERROR_OK) return retval; write_p += bank->bus_width; count -= bank->bus_width; } } } else return retval; } /* return to read array mode, so we can read from flash again for padding */ retval = cfi_reset(bank); if (retval != ERROR_OK) return retval; /* handle unaligned tail bytes */ if (count > 0) { LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count); /* read a complete word from flash */ retval = target_read_memory(target, write_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; /* replace only bytes that must be written */ for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--) current_word[i] = *buffer++; retval = cfi_write_word(bank, current_word, write_p); if (retval != ERROR_OK) return retval; } /* return to read array mode */ return cfi_reset(bank); } static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param) { (void) param; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; pri_ext->_reversed_geometry = 1; } static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param) { int i; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; (void) param; if ((pri_ext->_reversed_geometry) || (pri_ext->TopBottom == 3)) { LOG_DEBUG("swapping reversed erase region information on cmdset 0002 device"); for (i = 0; i < cfi_info->num_erase_regions / 2; i++) { int j = (cfi_info->num_erase_regions - 1) - i; uint32_t swap; swap = cfi_info->erase_region_info[i]; cfi_info->erase_region_info[i] = cfi_info->erase_region_info[j]; cfi_info->erase_region_info[j] = swap; } } } static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; const struct cfi_unlock_addresses *unlock_addresses = param; pri_ext->_unlock1 = unlock_addresses->unlock1; pri_ext->_unlock2 = unlock_addresses->unlock2; } static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param) { struct cfi_flash_bank *cfi_info = bank->driver_priv; const int *status_poll_mask = param; cfi_info->status_poll_mask = *status_poll_mask; } static int cfi_query_string(struct flash_bank *bank, int address) { struct cfi_flash_bank *cfi_info = bank->driver_priv; int retval; retval = cfi_send_command(bank, 0x98, flash_address(bank, 0, address)); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x10, &cfi_info->qry[0]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x11, &cfi_info->qry[1]); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x12, &cfi_info->qry[2]); if (retval != ERROR_OK) return retval; LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]); if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y')) { retval = cfi_reset(bank); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not probe bank: no QRY"); return ERROR_FLASH_BANK_INVALID; } return ERROR_OK; } static int cfi_probe(struct flash_bank *bank) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; int num_sectors = 0; int i; int sector = 0; uint32_t unlock1 = 0x555; uint32_t unlock2 = 0x2aa; int retval; uint8_t value_buf0[CFI_MAX_BUS_WIDTH], value_buf1[CFI_MAX_BUS_WIDTH]; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } cfi_info->probed = 0; cfi_info->num_erase_regions = 0; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } if (cfi_info->erase_region_info) { free(cfi_info->erase_region_info); cfi_info->erase_region_info = NULL; } /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses, * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa */ if (cfi_info->jedec_probe) { unlock1 = 0x5555; unlock2 = 0x2aaa; } /* switch to read identifier codes mode ("AUTOSELECT") */ retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, unlock2)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, unlock1)); if (retval != ERROR_OK) return retval; retval = target_read_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, value_buf0); if (retval != ERROR_OK) return retval; retval = target_read_memory(target, flash_address(bank, 0, 0x01), bank->bus_width, 1, value_buf1); if (retval != ERROR_OK) return retval; switch (bank->chip_width) { case 1: cfi_info->manufacturer = *value_buf0; cfi_info->device_id = *value_buf1; break; case 2: cfi_info->manufacturer = target_buffer_get_u16(target, value_buf0); cfi_info->device_id = target_buffer_get_u16(target, value_buf1); break; case 4: cfi_info->manufacturer = target_buffer_get_u32(target, value_buf0); cfi_info->device_id = target_buffer_get_u32(target, value_buf1); break; default: LOG_ERROR("Unsupported bank chipwidth %d, can't probe memory", bank->chip_width); return ERROR_FLASH_OPERATION_FAILED; } LOG_INFO("Flash Manufacturer/Device: 0x%04x 0x%04x", cfi_info->manufacturer, cfi_info->device_id); /* switch back to read array mode */ retval = cfi_reset(bank); if (retval != ERROR_OK) return retval; /* check device/manufacturer ID for known non-CFI flashes. */ cfi_fixup_non_cfi(bank); /* query only if this is a CFI compatible flash, * otherwise the relevant info has already been filled in */ if (cfi_info->not_cfi == 0) { /* enter CFI query mode * according to JEDEC Standard No. 68.01, * a single bus sequence with address = 0x55, data = 0x98 should put * the device into CFI query mode. * * SST flashes clearly violate this, and we will consider them incompatible for now */ retval = cfi_query_string(bank, 0x55); if (retval != ERROR_OK) { /* * Spansion S29WS-N CFI query fix is to try 0x555 if 0x55 fails. Should * be harmless enough: * * http://www.infradead.org/pipermail/linux-mtd/2005-September/013618.html */ LOG_USER("Try workaround w/0x555 instead of 0x55 to get QRY."); retval = cfi_query_string(bank, 0x555); } if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, 0x13, &cfi_info->pri_id); if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, 0x15, &cfi_info->pri_addr); if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, 0x17, &cfi_info->alt_id); if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, 0x19, &cfi_info->alt_addr); if (retval != ERROR_OK) return retval; LOG_DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: " "0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr); retval = cfi_query_u8(bank, 0, 0x1b, &cfi_info->vcc_min); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x1c, &cfi_info->vcc_max); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x1d, &cfi_info->vpp_min); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x1e, &cfi_info->vpp_max); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x1f, &cfi_info->word_write_timeout_typ); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x20, &cfi_info->buf_write_timeout_typ); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x21, &cfi_info->block_erase_timeout_typ); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x22, &cfi_info->chip_erase_timeout_typ); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x23, &cfi_info->word_write_timeout_max); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x24, &cfi_info->buf_write_timeout_max); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x25, &cfi_info->block_erase_timeout_max); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x26, &cfi_info->chip_erase_timeout_max); if (retval != ERROR_OK) return retval; uint8_t data; retval = cfi_query_u8(bank, 0, 0x27, &data); if (retval != ERROR_OK) return retval; cfi_info->dev_size = 1 << data; retval = cfi_query_u16(bank, 0, 0x28, &cfi_info->interface_desc); if (retval != ERROR_OK) return retval; retval = cfi_query_u16(bank, 0, 0x2a, &cfi_info->max_buf_write_size); if (retval != ERROR_OK) return retval; retval = cfi_query_u8(bank, 0, 0x2c, &cfi_info->num_erase_regions); if (retval != ERROR_OK) return retval; LOG_DEBUG("size: 0x%" PRIx32 ", interface desc: %i, max buffer write size: 0x%x", cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size)); if (cfi_info->num_erase_regions) { cfi_info->erase_region_info = malloc(sizeof(*cfi_info->erase_region_info) * cfi_info->num_erase_regions); for (i = 0; i < cfi_info->num_erase_regions; i++) { retval = cfi_query_u32(bank, 0, 0x2d + (4 * i), &cfi_info->erase_region_info[i]); if (retval != ERROR_OK) return retval; LOG_DEBUG( "erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32 "", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256); } } else cfi_info->erase_region_info = NULL; /* We need to read the primary algorithm extended query table before calculating * the sector layout to be able to apply fixups */ switch (cfi_info->pri_id) { /* Intel command set (standard and extended) */ case 0x0001: case 0x0003: cfi_read_intel_pri_ext(bank); break; /* AMD/Spansion, Atmel, ... command set */ case 0x0002: cfi_info->status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7; /* *default *for *all *CFI *flashs **/ cfi_read_0002_pri_ext(bank); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } /* return to read array mode * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command */ retval = cfi_reset(bank); if (retval != ERROR_OK) return retval; } /* end CFI case */ LOG_DEBUG("Vcc min: %x.%x, Vcc max: %x.%x, Vpp min: %u.%x, Vpp max: %u.%x", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f, (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f, (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f, (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f); LOG_DEBUG("typ. word write timeout: %u us, typ. buf write timeout: %u us, " "typ. block erase timeout: %u ms, typ. chip erase timeout: %u ms", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ, 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ); LOG_DEBUG("max. word write timeout: %u us, max. buf write timeout: %u us, " "max. block erase timeout: %u ms, max. chip erase timeout: %u ms", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ), (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ), (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ), (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ)); /* convert timeouts to real values in ms */ cfi_info->word_write_timeout = DIV_ROUND_UP((1L << cfi_info->word_write_timeout_typ) * (1L << cfi_info->word_write_timeout_max), 1000); cfi_info->buf_write_timeout = DIV_ROUND_UP((1L << cfi_info->buf_write_timeout_typ) * (1L << cfi_info->buf_write_timeout_max), 1000); cfi_info->block_erase_timeout = (1L << cfi_info->block_erase_timeout_typ) * (1L << cfi_info->block_erase_timeout_max); cfi_info->chip_erase_timeout = (1L << cfi_info->chip_erase_timeout_typ) * (1L << cfi_info->chip_erase_timeout_max); LOG_DEBUG("calculated word write timeout: %u ms, buf write timeout: %u ms, " "block erase timeout: %u ms, chip erase timeout: %u ms", cfi_info->word_write_timeout, cfi_info->buf_write_timeout, cfi_info->block_erase_timeout, cfi_info->chip_erase_timeout); /* apply fixups depending on the primary command set */ switch (cfi_info->pri_id) { /* Intel command set (standard and extended) */ case 0x0001: case 0x0003: cfi_fixup(bank, cfi_0001_fixups); break; /* AMD/Spansion, Atmel, ... command set */ case 0x0002: cfi_fixup(bank, cfi_0002_fixups); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } if ((cfi_info->dev_size * bank->bus_width / bank->chip_width) != bank->size) { LOG_WARNING("configuration specifies 0x%" PRIx32 " size, but a 0x%" PRIx32 " size flash was found", bank->size, cfi_info->dev_size); } if (cfi_info->num_erase_regions == 0) { /* a device might have only one erase block, spanning the whole device */ bank->num_sectors = 1; bank->sectors = malloc(sizeof(struct flash_sector)); bank->sectors[sector].offset = 0x0; bank->sectors[sector].size = bank->size; bank->sectors[sector].is_erased = -1; bank->sectors[sector].is_protected = -1; } else { uint32_t offset = 0; for (i = 0; i < cfi_info->num_erase_regions; i++) num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); for (i = 0; i < cfi_info->num_erase_regions; i++) { uint32_t j; for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++) { bank->sectors[sector].offset = offset; bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width; offset += bank->sectors[sector].size; bank->sectors[sector].is_erased = -1; bank->sectors[sector].is_protected = -1; sector++; } } if (offset != (cfi_info->dev_size * bank->bus_width / bank->chip_width)) { LOG_WARNING( "CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", \ (cfi_info->dev_size * bank->bus_width / bank->chip_width), offset); } } cfi_info->probed = 1; return ERROR_OK; } static int cfi_auto_probe(struct flash_bank *bank) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (cfi_info->probed) return ERROR_OK; return cfi_probe(bank); } static int cfi_intel_protect_check(struct flash_bank *bank) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext; int i; /* check if block lock bits are supported on this device */ if (!(pri_ext->blk_status_reg_mask & 0x1)) return ERROR_FLASH_OPERATION_FAILED; retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { uint8_t block_status; retval = cfi_get_u8(bank, i, 0x2, &block_status); if (retval != ERROR_OK) return retval; if (block_status & 1) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); } static int cfi_spansion_protect_check(struct flash_bank *bank) { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; int i; retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { uint8_t block_status; retval = cfi_get_u8(bank, i, 0x2, &block_status); if (retval != ERROR_OK) return retval; if (block_status & 1) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); } static int cfi_protect_check(struct flash_bank *bank) { struct cfi_flash_bank *cfi_info = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (cfi_info->qry[0] != 'Q') return ERROR_FLASH_BANK_NOT_PROBED; switch (cfi_info->pri_id) { case 1: case 3: return cfi_intel_protect_check(bank); break; case 2: return cfi_spansion_protect_check(bank); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } return ERROR_OK; } static int get_cfi_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct cfi_flash_bank *cfi_info = bank->driver_priv; if (cfi_info->qry[0] == 0xff) { snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n"); return ERROR_OK; } if (cfi_info->not_cfi == 0) printed = snprintf(buf, buf_size, "\nCFI flash: "); else printed = snprintf(buf, buf_size, "\nnon-CFI flash: "); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "mfr: 0x%4.4x, id:0x%4.4x\n\n", cfi_info->manufacturer, cfi_info->device_id); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: " "0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "Vcc min: %x.%x, Vcc max: %x.%x, " "Vpp min: %u.%x, Vpp max: %u.%x\n", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f, (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f, (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f, (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "typ. word write timeout: %u us, " "typ. buf write timeout: %u us, " "typ. block erase timeout: %u ms, " "typ. chip erase timeout: %u ms\n", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ, 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "max. word write timeout: %u us, " "max. buf write timeout: %u us, max. " "block erase timeout: %u ms, max. chip erase timeout: %u ms\n", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ), (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ), (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ), (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ)); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "size: 0x%" PRIx32 ", interface desc: %i, " "max buffer write size: 0x%x\n", cfi_info->dev_size, cfi_info->interface_desc, 1 << cfi_info->max_buf_write_size); buf += printed; buf_size -= printed; switch (cfi_info->pri_id) { case 1: case 3: cfi_intel_info(bank, buf, buf_size); break; case 2: cfi_spansion_info(bank, buf, buf_size); break; default: LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id); break; } return ERROR_OK; } static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param) { struct cfi_flash_bank *cfi_info = bank->driver_priv; /* disable write buffer for M29W128G */ cfi_info->buf_write_timeout_typ = 0; } struct flash_driver cfi_flash = { .name = "cfi", .flash_bank_command = cfi_flash_bank_command, .erase = cfi_erase, .protect = cfi_protect, .write = cfi_write, .read = cfi_read, .probe = cfi_probe, .auto_probe = cfi_auto_probe, /* FIXME: access flash at bus_width size */ .erase_check = default_flash_blank_check, .protect_check = cfi_protect_check, .info = get_cfi_info, }; openocd-0.9.0/src/flash/nor/cfi.h0000644000175000017500000001075212315575360013500 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef CFI_H #define CFI_H #define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */ #define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */ struct cfi_flash_bank { int x16_as_x8; int jedec_probe; int not_cfi; int probed; uint16_t manufacturer; uint16_t device_id; uint8_t qry[3]; /* identification string */ uint16_t pri_id; uint16_t pri_addr; uint16_t alt_id; uint16_t alt_addr; /* device-system interface */ uint8_t vcc_min; uint8_t vcc_max; uint8_t vpp_min; uint8_t vpp_max; uint8_t word_write_timeout_typ; uint8_t buf_write_timeout_typ; uint8_t block_erase_timeout_typ; uint8_t chip_erase_timeout_typ; uint8_t word_write_timeout_max; uint8_t buf_write_timeout_max; uint8_t block_erase_timeout_max; uint8_t chip_erase_timeout_max; uint8_t status_poll_mask; /* flash geometry */ uint32_t dev_size; uint16_t interface_desc; uint16_t max_buf_write_size; uint8_t num_erase_regions; uint32_t *erase_region_info; void *pri_ext; void *alt_ext; /* calculated timeouts */ unsigned word_write_timeout; unsigned buf_write_timeout; unsigned block_erase_timeout; unsigned chip_erase_timeout; }; /* Intel primary extended query table * as defined for the Advanced+ Boot Block Flash Memory (C3) * and used by the linux kernel cfi driver (as of 2.6.14) */ struct cfi_intel_pri_ext { uint8_t pri[3]; uint8_t major_version; uint8_t minor_version; uint32_t feature_support; uint8_t suspend_cmd_support; uint16_t blk_status_reg_mask; uint8_t vcc_optimal; uint8_t vpp_optimal; uint8_t num_protection_fields; uint16_t prot_reg_addr; uint8_t fact_prot_reg_size; uint8_t user_prot_reg_size; uint8_t extra[0]; }; /* Spansion primary extended query table as defined for and used by * the linux kernel cfi driver (as of 2.6.15) */ struct cfi_spansion_pri_ext { uint8_t pri[3]; uint8_t major_version; uint8_t minor_version; uint8_t SiliconRevision; /* bits 1-0: Address Sensitive Unlock */ uint8_t EraseSuspend; uint8_t BlkProt; uint8_t TmpBlkUnprotect; uint8_t BlkProtUnprot; uint8_t SimultaneousOps; uint8_t BurstMode; uint8_t PageMode; uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; int _reversed_geometry; uint32_t _unlock1; uint32_t _unlock2; }; /* Atmel primary extended query table as defined for and used by * the linux kernel cfi driver (as of 2.6.20+) */ struct cfi_atmel_pri_ext { uint8_t pri[3]; uint8_t major_version; uint8_t minor_version; uint8_t features; uint8_t bottom_boot; uint8_t burst_mode; uint8_t page_mode; }; enum { CFI_UNLOCK_555_2AA, CFI_UNLOCK_5555_2AAA, }; struct cfi_unlock_addresses { uint32_t unlock1; uint32_t unlock2; }; struct cfi_fixup { uint16_t mfr; uint16_t id; void (*fixup)(struct flash_bank *bank, const void *param); const void *param; }; #define CFI_MFR_AMD 0x0001 #define CFI_MFR_FUJITSU 0x0004 #define CFI_MFR_ATMEL 0x001F #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ #define CFI_MFR_AMIC 0x0037 #define CFI_MFR_SST 0x00BF #define CFI_MFR_MX 0x00C2 #define CFI_MFR_EON 0x007F #define CFI_MFR_ANY 0xffff #define CFI_ID_ANY 0xffff #endif /* CFI_H */ openocd-0.9.0/src/flash/nor/fm3.c0000644000175000017500000010654412516456302013421 00000000000000/*************************************************************************** * Copyright (C) 2011 by Marc Willam, Holger Wech * * openOCD.fseu(AT)de.fujitsu.com * * Copyright (C) 2011 Ronny Strutz * * * * Copyright (C) 2013 Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #define FLASH_DQ6 0x40 /* Data toggle flag bit (TOGG) position */ #define FLASH_DQ5 0x20 /* Time limit exceeding flag bit (TLOV) position */ enum fm3_variant { mb9bfxx1, /* Flash Type '1' */ mb9bfxx2, mb9bfxx3, mb9bfxx4, mb9bfxx5, mb9bfxx6, mb9bfxx7, mb9bfxx8, mb9afxx1, /* Flash Type '2' */ mb9afxx2, mb9afxx3, mb9afxx4, mb9afxx5, mb9afxx6, mb9afxx7, mb9afxx8, }; enum fm3_flash_type { fm3_no_flash_type = 0, fm3_flash_type1 = 1, fm3_flash_type2 = 2 }; struct fm3_flash_bank { enum fm3_variant variant; enum fm3_flash_type flashtype; int probed; }; FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command) { struct fm3_flash_bank *fm3_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; fm3_info = malloc(sizeof(struct fm3_flash_bank)); bank->driver_priv = fm3_info; /* Flash type '1' */ if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0) { fm3_info->variant = mb9bfxx1; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0) { fm3_info->variant = mb9bfxx2; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0) { fm3_info->variant = mb9bfxx3; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0) { fm3_info->variant = mb9bfxx4; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0) { fm3_info->variant = mb9bfxx5; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0) { fm3_info->variant = mb9bfxx6; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx7.cpu") == 0) { fm3_info->variant = mb9bfxx7; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9bfxx8.cpu") == 0) { fm3_info->variant = mb9bfxx8; fm3_info->flashtype = fm3_flash_type1; } else if (strcmp(CMD_ARGV[5], "mb9afxx1.cpu") == 0) { /* Flash type '2' */ fm3_info->variant = mb9afxx1; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx2.cpu") == 0) { fm3_info->variant = mb9afxx2; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx3.cpu") == 0) { fm3_info->variant = mb9afxx3; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx4.cpu") == 0) { fm3_info->variant = mb9afxx4; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx5.cpu") == 0) { fm3_info->variant = mb9afxx5; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx6.cpu") == 0) { fm3_info->variant = mb9afxx6; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx7.cpu") == 0) { fm3_info->variant = mb9afxx7; fm3_info->flashtype = fm3_flash_type2; } else if (strcmp(CMD_ARGV[5], "mb9afxx8.cpu") == 0) { fm3_info->variant = mb9afxx8; fm3_info->flashtype = fm3_flash_type2; } /* unknown Flash type */ else { LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]); free(fm3_info); return ERROR_FLASH_BANK_INVALID; } fm3_info->probed = 0; return ERROR_OK; } /* Data polling algorithm */ static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms) { int retval = ERROR_OK; uint8_t state1, state2; int ms = 0; /* While(1) loop exit via "break" and "return" on error */ while (1) { /* dummy-read - see flash manual */ retval = target_read_u8(target, offset, &state1); if (retval != ERROR_OK) return retval; /* Data polling 1 */ retval = target_read_u8(target, offset, &state1); if (retval != ERROR_OK) return retval; /* Data polling 2 */ retval = target_read_u8(target, offset, &state2); if (retval != ERROR_OK) return retval; /* Flash command finished via polled data equal? */ if ((state1 & FLASH_DQ6) == (state2 & FLASH_DQ6)) break; /* Timeout Flag? */ else if (state1 & FLASH_DQ5) { /* Retry data polling */ /* Data polling 1 */ retval = target_read_u8(target, offset, &state1); if (retval != ERROR_OK) return retval; /* Data polling 2 */ retval = target_read_u8(target, offset, &state2); if (retval != ERROR_OK) return retval; /* Flash command finished via polled data equal? */ if ((state1 & FLASH_DQ6) != (state2 & FLASH_DQ6)) return ERROR_FLASH_OPERATION_FAILED; /* finish anyway */ break; } usleep(1000); ++ms; /* Polling time exceeded? */ if (ms > timeout_ms) { LOG_ERROR("Polling data reading timed out!"); return ERROR_FLASH_OPERATION_FAILED; } } if (retval == ERROR_OK) LOG_DEBUG("fm3_busy_wait(%" PRIx32 ") needs about %d ms", offset, ms); return retval; } static int fm3_erase(struct flash_bank *bank, int first, int last) { struct fm3_flash_bank *fm3_info = bank->driver_priv; struct target *target = bank->target; int retval = ERROR_OK; uint32_t u32DummyRead; int sector, odd; uint32_t u32FlashType; uint32_t u32FlashSeqAddress1; uint32_t u32FlashSeqAddress2; struct working_area *write_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; u32FlashType = (uint32_t) fm3_info->flashtype; if (u32FlashType == fm3_flash_type1) { u32FlashSeqAddress1 = 0x00001550; u32FlashSeqAddress2 = 0x00000AA8; } else if (u32FlashType == fm3_flash_type2) { u32FlashSeqAddress1 = 0x00000AA8; u32FlashSeqAddress2 = 0x00000554; } else { LOG_ERROR("Flash/Device type unknown!"); return ERROR_FLASH_OPERATION_FAILED; } if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* RAMCODE used for fm3 Flash sector erase: */ /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */ /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */ /* R2 keeps Flash Offset address (ofs) */ static const uint8_t fm3_flash_erase_sector_code[] = { /* *(uint16_t*)u32FlashSeq1 = 0xAA; */ 0xAA, 0x24, /* MOVS R4, #0xAA */ 0x04, 0x80, /* STRH R4, [R0, #0] */ /* *(uint16_t*)u32FlashSeq2 = 0x55; */ 0x55, 0x23, /* MOVS R3, #0x55 */ 0x0B, 0x80, /* STRH R3, [R1, #0] */ /* *(uint16_t*)u32FlashSeq1 = 0x80; */ 0x80, 0x25, /* MOVS R5, #0x80 */ 0x05, 0x80, /* STRH R5, [R0, #0] */ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */ 0x04, 0x80, /* STRH R4, [R0, #0] */ /* *(uint16_t*)u32FlashSeq2 = 0x55; */ 0x0B, 0x80, /* STRH R3, [R1, #0] */ /* Sector_Erase Command (0x30) */ /* *(uint16_t*)ofs = 0x30; */ 0x30, 0x20, /* MOVS R0, #0x30 */ 0x10, 0x80, /* STRH R0, [R2, #0] */ /* End Code */ 0x00, 0xBE, /* BKPT #0 */ }; LOG_INFO("Fujitsu MB9[A/B]FXXX: Sector Erase ... (%d to %d)", first, last); /* disable HW watchdog */ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011C00, 0xE5331AAE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011008, 0x00000000); if (retval != ERROR_OK) return retval; /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */ retval = target_write_u32(target, 0x40000000, 0x0001); if (retval != ERROR_OK) return retval; /* dummy read of FASZR */ retval = target_read_u32(target, 0x40000000, &u32DummyRead); if (retval != ERROR_OK) return retval; /* allocate working area with flash sector erase code */ if (target_alloc_working_area(target, sizeof(fm3_flash_erase_sector_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = target_write_buffer(target, write_algorithm->address, sizeof(fm3_flash_erase_sector_code), fm3_flash_erase_sector_code); if (retval != ERROR_OK) return retval; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* offset */ /* write code buffer and use Flash sector erase code within fm3 */ for (sector = first ; sector <= last ; sector++) { uint32_t offset = bank->sectors[sector].offset; for (odd = 0; odd < 2 ; odd++) { if (odd) offset += 4; buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1); buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2); buf_set_u32(reg_params[2].value, 0, 32, offset); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, 0, 100000, &armv7m_info); if (retval != ERROR_OK) { LOG_ERROR("Error executing flash erase programming algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; return retval; } retval = fm3_busy_wait(target, offset, 500); if (retval != ERROR_OK) return retval; } bank->sectors[sector].is_erased = 1; } target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */ retval = target_write_u32(target, 0x40000000, 0x0002); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */ return retval; } static int fm3_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct fm3_flash_bank *fm3_info = bank->driver_priv; struct target *target = bank->target; uint32_t buffer_size = 2048; /* Default minimum value */ struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[6]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; uint32_t u32FlashType; uint32_t u32FlashSeqAddress1; uint32_t u32FlashSeqAddress2; /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size / 2)) buffer_size = (target->working_area_size / 2); u32FlashType = (uint32_t) fm3_info->flashtype; if (u32FlashType == fm3_flash_type1) { u32FlashSeqAddress1 = 0x00001550; u32FlashSeqAddress2 = 0x00000AA8; } else if (u32FlashType == fm3_flash_type2) { u32FlashSeqAddress1 = 0x00000AA8; u32FlashSeqAddress2 = 0x00000554; } else { LOG_ERROR("Flash/Device type unknown!"); return ERROR_FLASH_OPERATION_FAILED; } /* RAMCODE used for fm3 Flash programming: */ /* R0 keeps source start address (u32Source) */ /* R1 keeps target start address (u32Target) */ /* R2 keeps number of halfwords to write (u32Count) */ /* R3 keeps Flash Sequence address 1 (u32FlashSeq1) */ /* R4 keeps Flash Sequence address 2 (u32FlashSeq2) */ /* R5 returns result value (u32FlashResult) */ static const uint8_t fm3_flash_write_code[] = { /* fm3_FLASH_IF->FASZ &= 0xFFFD; */ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x4F, 0xF6, 0xFD, 0x76, /* MOVW R6, #0xFFFD */ 0x35, 0x40, /* ANDS R5, R5, R6 */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x35, 0x60, /* STR R5, [R6] */ /* fm3_FLASH_IF->FASZ |= 1; */ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */ 0x2D, 0x68, /* LDR R5, [R3] */ 0x55, 0xF0, 0x01, 0x05, /* ORRS.W R5, R5, #1 */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x35, 0x60, /* STR R5, [R6] */ /* u32DummyRead = fm3_FLASH_IF->FASZ; */ 0x28, 0x4D, /* LDR.N R5, ??u32DummyRead */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x36, 0x68, /* LDR R6, [R6] */ 0x2E, 0x60, /* STR R6, [R5] */ /* u32FlashResult = FLASH_WRITE_NO_RESULT */ 0x26, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x00, 0x26, /* MOVS R6, #0 */ 0x2E, 0x60, /* STR R6, [R5] */ /* while ((u32Count > 0 ) */ /* && (u32FlashResult */ /* == FLASH_WRITE_NO_RESULT)) */ 0x01, 0x2A, /* L0: CMP R2, #1 */ 0x2C, 0xDB, /* BLT.N L1 */ 0x24, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x00, 0x2D, /* CMP R5, #0 */ 0x28, 0xD1, /* BNE.N L1 */ /* *u32FlashSeq1 = FLASH_WRITE_1; */ 0xAA, 0x25, /* MOVS R5, #0xAA */ 0x1D, 0x60, /* STR R5, [R3] */ /* *u32FlashSeq2 = FLASH_WRITE_2; */ 0x55, 0x25, /* MOVS R5, #0x55 */ 0x25, 0x60, /* STR R5, [R4] */ /* *u32FlashSeq1 = FLASH_WRITE_3; */ 0xA0, 0x25, /* MOVS R5, #0xA0 */ 0x1D, 0x60, /* STRH R5, [R3] */ /* *(volatile uint16_t*)u32Target */ /* = *(volatile uint16_t*)u32Source; */ 0x05, 0x88, /* LDRH R5, [R0] */ 0x0D, 0x80, /* STRH R5, [R1] */ /* while (u32FlashResult */ /* == FLASH_WRITE_NO_RESTULT) */ 0x1E, 0x4D, /* L2: LDR.N R5, ??u32FlashResult */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x00, 0x2D, /* CMP R5, #0 */ 0x11, 0xD1, /* BNE.N L3 */ /* if ((*(volatile uint16_t*)u32Target */ /* & FLASH_DQ5) == FLASH_DQ5) */ 0x0D, 0x88, /* LDRH R5, [R1] */ 0xAD, 0x06, /* LSLS R5, R5, #0x1A */ 0x02, 0xD5, /* BPL.N L4 */ /* u32FlashResult = FLASH_WRITE_TIMEOUT */ 0x1A, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x02, 0x26, /* MOVS R6, #2 */ 0x2E, 0x60, /* STR R6, [R5] */ /* if ((*(volatile uint16_t *)u32Target */ /* & FLASH_DQ7) */ /* == (*(volatile uint16_t*)u32Source */ /* & FLASH_DQ7)) */ 0x0D, 0x88, /* L4: LDRH R5, [R1] */ 0x15, 0xF0, 0x80, 0x05, /* ANDS.W R5, R5, #0x80 */ 0x06, 0x88, /* LDRH R6, [R0] */ 0x16, 0xF0, 0x80, 0x06, /* ANDS.W R6, R6, #0x80 */ 0xB5, 0x42, /* CMP R5, R6 */ 0xED, 0xD1, /* BNE.N L2 */ /* u32FlashResult = FLASH_WRITE_OKAY */ 0x15, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x01, 0x26, /* MOVS R6, #1 */ 0x2E, 0x60, /* STR R6, [R5] */ 0xE9, 0xE7, /* B.N L2 */ /* if (u32FlashResult */ /* != FLASH_WRITE_TIMEOUT) */ 0x13, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x02, 0x2D, /* CMP R5, #2 */ 0x02, 0xD0, /* BEQ.N L5 */ /* u32FlashResult = FLASH_WRITE_NO_RESULT */ 0x11, 0x4D, /* LDR.N R5, ??u32FlashResult */ 0x00, 0x26, /* MOVS R6, #0 */ 0x2E, 0x60, /* STR R6, [R5] */ /* u32Count--; */ 0x52, 0x1E, /* L5: SUBS R2, R2, #1 */ /* u32Source += 2; */ 0x80, 0x1C, /* ADDS R0, R0, #2 */ /* u32Target += 2; */ 0x89, 0x1C, /* ADDS R1, R1, #2 */ 0xD0, 0xE7, /* B.N L0 */ /* fm3_FLASH_IF->FASZ &= 0xFFFE; */ 0x5F, 0xF0, 0x80, 0x45, /* L1: MOVS.W R5, #(fm3_FLASH_IF->FASZ) */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x4F, 0xF6, 0xFE, 0x76, /* MOVW R6, #0xFFFE */ 0x35, 0x40, /* ANDS R5, R5, R6 */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x35, 0x60, /* STR R5, [R6] */ /* fm3_FLASH_IF->FASZ |= 2; */ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */ 0x2D, 0x68, /* LDR R5, [R5] */ 0x55, 0xF0, 0x02, 0x05, /* ORRS.W R5, R5, #2 */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x35, 0x60, /* STR R5, [R6] */ /* u32DummyRead = fm3_FLASH_IF->FASZ; */ 0x04, 0x4D, /* LDR.N R5, ??u32DummyRead */ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */ 0x36, 0x68, /* LDR R6, [R6] */ 0x2E, 0x60, /* STR R6, [R5] */ /* copy u32FlashResult to R3 for return */ /* value */ 0xDF, 0xF8, 0x08, 0x50, /* LDR.W R5, ??u32FlashResult */ 0x2D, 0x68, /* LDR R5, [R5] */ /* Breakpoint here */ 0x00, 0xBE, /* BKPT #0 */ /* The following address pointers assume, that the code is running from */ /* SRAM basic-address + 8.These address pointers will be patched, if a */ /* different start address in RAM is used (e.g. for Flash type 2)! */ /* Default SRAM basic-address is 0x20000000. */ 0x00, 0x00, 0x00, 0x20, /* u32DummyRead address in RAM (0x20000000) */ 0x04, 0x00, 0x00, 0x20 /* u32FlashResult address in RAM (0x20000004) */ }; LOG_INFO("Fujitsu MB9[A/B]FXXX: FLASH Write ..."); /* disable HW watchdog */ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011C00, 0xE5331AAE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011008, 0x00000000); if (retval != ERROR_OK) return retval; count = count / 2; /* number bytes -> number halfwords */ /* check code alignment */ if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* allocate working area and variables with flash programming code */ if (target_alloc_working_area(target, sizeof(fm3_flash_write_code) + 8, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = target_write_buffer(target, write_algorithm->address + 8, sizeof(fm3_flash_write_code), fm3_flash_write_code); if (retval != ERROR_OK) return retval; /* Patching 'local variable address' */ /* Algorithm: u32DummyRead: */ retval = target_write_u32(target, (write_algorithm->address + 8) + sizeof(fm3_flash_write_code) - 8, (write_algorithm->address)); if (retval != ERROR_OK) return retval; /* Algorithm: u32FlashResult: */ retval = target_write_u32(target, (write_algorithm->address + 8) + sizeof(fm3_flash_write_code) - 4, (write_algorithm->address) + 4); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* free working area, write algorithm already allocated */ target_free_working_area(target, write_algorithm); LOG_WARNING("No large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* source start address */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* target start address */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */ init_reg_param(®_params[5], "r5", 32, PARAM_IN); /* result */ /* write code buffer and use Flash programming code within fm3 */ /* Set breakpoint to 0 with time-out of 1000 ms */ while (count > 0) { uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1); buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2); retval = target_run_algorithm(target, 0, NULL, 6, reg_params, (write_algorithm->address + 8), 0, 1000, &armv7m_info); if (retval != ERROR_OK) { LOG_ERROR("Error executing fm3 Flash programming algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK) { LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) -> Reg R3: %" PRIx32, buf_get_u32(reg_params[5].value, 0, 32)); retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count * 2; address += thisrun_count * 2; count -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); return retval; } static int fm3_probe(struct flash_bank *bank) { struct fm3_flash_bank *fm3_info = bank->driver_priv; uint16_t num_pages; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* -- page-- start -- blocksize - mpu - totalFlash -- page0 0x00000 16k page1 0x04000 16k page2 0x08000 96k ___ fxx3 128k Flash page3 0x20000 128k ___ fxx4 256k Flash page4 0x40000 128k ___ fxx5 384k Flash page5 0x60000 128k ___ fxx6 512k Flash ----------------------- page6 0x80000 128k page7 0xa0000 128k ___ fxx7 256k Flash page8 0xc0000 128k page9 0xe0000 128k ___ fxx8 256k Flash */ num_pages = 10; /* max number of Flash pages for malloc */ fm3_info->probed = 0; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); bank->base = 0x00000000; bank->size = 32 * 1024; /* bytes */ bank->sectors[0].offset = 0; bank->sectors[0].size = 16 * 1024; bank->sectors[0].is_erased = -1; bank->sectors[0].is_protected = -1; bank->sectors[1].offset = 0x4000; bank->sectors[1].size = 16 * 1024; bank->sectors[1].is_erased = -1; bank->sectors[1].is_protected = -1; if ((fm3_info->variant == mb9bfxx1) || (fm3_info->variant == mb9afxx1)) { num_pages = 3; bank->size = 64 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[2].offset = 0x8000; bank->sectors[2].size = 32 * 1024; bank->sectors[2].is_erased = -1; bank->sectors[2].is_protected = -1; } if ((fm3_info->variant == mb9bfxx2) || (fm3_info->variant == mb9bfxx4) || (fm3_info->variant == mb9bfxx5) || (fm3_info->variant == mb9bfxx6) || (fm3_info->variant == mb9bfxx7) || (fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx2) || (fm3_info->variant == mb9afxx4) || (fm3_info->variant == mb9afxx5) || (fm3_info->variant == mb9afxx6) || (fm3_info->variant == mb9afxx7) || (fm3_info->variant == mb9afxx8)) { num_pages = 3; bank->size = 128 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[2].offset = 0x8000; bank->sectors[2].size = 96 * 1024; bank->sectors[2].is_erased = -1; bank->sectors[2].is_protected = -1; } if ((fm3_info->variant == mb9bfxx4) || (fm3_info->variant == mb9bfxx5) || (fm3_info->variant == mb9bfxx6) || (fm3_info->variant == mb9bfxx7) || (fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx4) || (fm3_info->variant == mb9afxx5) || (fm3_info->variant == mb9afxx6) || (fm3_info->variant == mb9afxx7) || (fm3_info->variant == mb9afxx8)) { num_pages = 4; bank->size = 256 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[3].offset = 0x20000; bank->sectors[3].size = 128 * 1024; bank->sectors[3].is_erased = -1; bank->sectors[3].is_protected = -1; } if ((fm3_info->variant == mb9bfxx5) || (fm3_info->variant == mb9bfxx6) || (fm3_info->variant == mb9bfxx7) || (fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx5) || (fm3_info->variant == mb9afxx6) || (fm3_info->variant == mb9afxx7) || (fm3_info->variant == mb9afxx8)) { num_pages = 5; bank->size = 384 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[4].offset = 0x40000; bank->sectors[4].size = 128 * 1024; bank->sectors[4].is_erased = -1; bank->sectors[4].is_protected = -1; } if ((fm3_info->variant == mb9bfxx6) || (fm3_info->variant == mb9bfxx7) || (fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx6) || (fm3_info->variant == mb9afxx7) || (fm3_info->variant == mb9afxx8)) { num_pages = 6; bank->size = 512 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[5].offset = 0x60000; bank->sectors[5].size = 128 * 1024; bank->sectors[5].is_erased = -1; bank->sectors[5].is_protected = -1; } if ((fm3_info->variant == mb9bfxx7) || (fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx7) || (fm3_info->variant == mb9afxx8)) { num_pages = 8; bank->size = 768 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[6].offset = 0x80000; bank->sectors[6].size = 128 * 1024; bank->sectors[6].is_erased = -1; bank->sectors[6].is_protected = -1; bank->sectors[7].offset = 0xa0000; bank->sectors[7].size = 128 * 1024; bank->sectors[7].is_erased = -1; bank->sectors[7].is_protected = -1; } if ((fm3_info->variant == mb9bfxx8) || (fm3_info->variant == mb9afxx8)) { num_pages = 10; bank->size = 1024 * 1024; /* bytes */ bank->num_sectors = num_pages; bank->sectors[8].offset = 0xc0000; bank->sectors[8].size = 128 * 1024; bank->sectors[8].is_erased = -1; bank->sectors[8].is_protected = -1; bank->sectors[9].offset = 0xe0000; bank->sectors[9].size = 128 * 1024; bank->sectors[9].is_erased = -1; bank->sectors[9].is_protected = -1; } fm3_info->probed = 1; return ERROR_OK; } static int fm3_auto_probe(struct flash_bank *bank) { struct fm3_flash_bank *fm3_info = bank->driver_priv; if (fm3_info->probed) return ERROR_OK; return fm3_probe(bank); } /* Chip erase */ static int fm3_chip_erase(struct flash_bank *bank) { struct target *target = bank->target; struct fm3_flash_bank *fm3_info2 = bank->driver_priv; int retval = ERROR_OK; uint32_t u32DummyRead; uint32_t u32FlashType; uint32_t u32FlashSeqAddress1; uint32_t u32FlashSeqAddress2; struct working_area *write_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; u32FlashType = (uint32_t) fm3_info2->flashtype; if (u32FlashType == fm3_flash_type1) { LOG_INFO("*** Erasing mb9bfxxx type"); u32FlashSeqAddress1 = 0x00001550; u32FlashSeqAddress2 = 0x00000AA8; } else if (u32FlashType == fm3_flash_type2) { LOG_INFO("*** Erasing mb9afxxx type"); u32FlashSeqAddress1 = 0x00000AA8; u32FlashSeqAddress2 = 0x00000554; } else { LOG_ERROR("Flash/Device type unknown!"); return ERROR_FLASH_OPERATION_FAILED; } if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* RAMCODE used for fm3 Flash chip erase: */ /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */ /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */ static const uint8_t fm3_flash_erase_chip_code[] = { /* *(uint16_t*)u32FlashSeq1 = 0xAA; */ 0xAA, 0x22, /* MOVS R2, #0xAA */ 0x02, 0x80, /* STRH R2, [R0, #0] */ /* *(uint16_t*)u32FlashSeq2 = 0x55; */ 0x55, 0x23, /* MOVS R3, #0x55 */ 0x0B, 0x80, /* STRH R3, [R1, #0] */ /* *(uint16_t*)u32FlashSeq1 = 0x80; */ 0x80, 0x24, /* MOVS R4, #0x80 */ 0x04, 0x80, /* STRH R4, [R0, #0] */ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */ 0x02, 0x80, /* STRH R2, [R0, #0] */ /* *(uint16_t*)u32FlashSeq2 = 0x55; */ 0x0B, 0x80, /* STRH R3, [R1, #0] */ /* Chip_Erase Command 0x10 */ /* *(uint16_t*)u32FlashSeq1 = 0x10; */ 0x10, 0x21, /* MOVS R1, #0x10 */ 0x01, 0x80, /* STRH R1, [R0, #0] */ /* End Code */ 0x00, 0xBE, /* BKPT #0 */ }; LOG_INFO("Fujitsu MB9[A/B]xxx: Chip Erase ... (may take several seconds)"); /* disable HW watchdog */ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011C00, 0xE5331AAE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, 0x40011008, 0x00000000); if (retval != ERROR_OK) return retval; /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */ retval = target_write_u32(target, 0x40000000, 0x0001); if (retval != ERROR_OK) return retval; /* dummy read of FASZR */ retval = target_read_u32(target, 0x40000000, &u32DummyRead); if (retval != ERROR_OK) return retval; /* allocate working area with flash chip erase code */ if (target_alloc_working_area(target, sizeof(fm3_flash_erase_chip_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = target_write_buffer(target, write_algorithm->address, sizeof(fm3_flash_erase_chip_code), fm3_flash_erase_chip_code); if (retval != ERROR_OK) return retval; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */ buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1); buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2); retval = target_run_algorithm(target, 0, NULL, 2, reg_params, write_algorithm->address, 0, 100000, &armv7m_info); if (retval != ERROR_OK) { LOG_ERROR("Error executing flash erase programming algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; return retval; } target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000); /* 20s timeout */ if (retval != ERROR_OK) return retval; /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */ retval = target_write_u32(target, 0x40000000, 0x0002); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */ return retval; } COMMAND_HANDLER(fm3_handle_chip_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; if (fm3_chip_erase(bank) == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "fm3 chip erase complete"); } else { command_print(CMD_CTX, "fm3 chip erase failed"); } return ERROR_OK; } static const struct command_registration fm3_exec_command_handlers[] = { { .name = "chip_erase", .usage = "", .handler = fm3_handle_chip_erase_command, .mode = COMMAND_EXEC, .help = "Erase entire Flash device.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration fm3_command_handlers[] = { { .name = "fm3", .mode = COMMAND_ANY, .help = "fm3 Flash command group", .usage = "", .chain = fm3_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver fm3_flash = { .name = "fm3", .commands = fm3_command_handlers, .flash_bank_command = fm3_flash_bank_command, .erase = fm3_erase, .write = fm3_write_block, .probe = fm3_probe, .auto_probe = fm3_auto_probe, .erase_check = default_flash_blank_check, }; openocd-0.9.0/src/flash/nor/imp.h0000644000175000017500000000454212315575360013524 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NOR_IMP_H #define FLASH_NOR_IMP_H /* this is an internal header */ #include "core.h" #include "driver.h" /* almost all drivers will need this file */ #include /** * Adds a new NOR bank to the global list of banks. * @param bank The bank that should be added. */ void flash_bank_add(struct flash_bank *bank); /** * @return The first bank in the global list. */ struct flash_bank *flash_bank_list(void); int flash_driver_erase(struct flash_bank *bank, int first, int last); int flash_driver_protect(struct flash_bank *bank, int set, int first, int last); int flash_driver_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count); int flash_driver_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count); /* write (optional verify) an image to flash memory of the given target */ int flash_write_unlock(struct target *target, struct image *image, uint32_t *written, int erase, bool unlock); #endif /* FLASH_NOR_IMP_H */ openocd-0.9.0/src/flash/nor/mdr.c0000644000175000017500000004226412516456302013514 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * Copyright (C) 2013 by Paul Fertser * * fercerpav@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #define MD_RST_CLK 0x40020000 #define MD_PER_CLOCK (MD_RST_CLK + 0x1C) #define MD_PER_CLOCK_EEPROM (1 << 3) #define MD_PER_CLOCK_RST_CLK (1 << 4) #define FLASH_REG_BASE 0x40018000 #define FLASH_CMD (FLASH_REG_BASE + 0x00) #define FLASH_ADR (FLASH_REG_BASE + 0x04) #define FLASH_DI (FLASH_REG_BASE + 0x08) #define FLASH_DO (FLASH_REG_BASE + 0x0C) #define FLASH_KEY (FLASH_REG_BASE + 0x10) #define FLASH_NVSTR (1 << 13) #define FLASH_PROG (1 << 12) #define FLASH_MAS1 (1 << 11) #define FLASH_ERASE (1 << 10) #define FLASH_IFREN (1 << 9) #define FLASH_SE (1 << 8) #define FLASH_YE (1 << 7) #define FLASH_XE (1 << 6) #define FLASH_RD (1 << 2) #define FLASH_WR (1 << 1) #define FLASH_CON (1 << 0) #define FLASH_DELAY_MASK (7 << 3) #define KEY 0x8AAA5551 struct mdr_flash_bank { int probed; unsigned int mem_type; unsigned int page_count; unsigned int sec_count; }; /* flash bank mdr 0 0 */ FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command) { struct mdr_flash_bank *mdr_info; if (CMD_ARGC < 9) return ERROR_COMMAND_SYNTAX_ERROR; mdr_info = malloc(sizeof(struct mdr_flash_bank)); bank->driver_priv = mdr_info; mdr_info->probed = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count); return ERROR_OK; } static int mdr_protect_check(struct flash_bank *bank) { return ERROR_OK; } static int mdr_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; struct mdr_flash_bank *mdr_info = bank->driver_priv; uint32_t flash_cmd; int retval; unsigned int i; retval = target_read_u32(target, FLASH_CMD, &flash_cmd); if (retval != ERROR_OK) return retval; for (i = 0; i < mdr_info->sec_count; i++) { retval = target_write_u32(target, FLASH_ADR, i << 2); if (retval != ERROR_OK) return retval; flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) return retval; flash_cmd |= FLASH_NVSTR; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) return retval; flash_cmd &= ~FLASH_ERASE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) return retval; flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR); retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) return retval; } return retval; } static int mdr_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct mdr_flash_bank *mdr_info = bank->driver_priv; int i, retval, retval2; unsigned int j; uint32_t flash_cmd, cur_per_clock; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock); if (retval != ERROR_OK) return retval; if (!(cur_per_clock & 0x10)) { LOG_ERROR("Target needs reset before flash operations"); return ERROR_FLASH_OPERATION_FAILED; } retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, FLASH_KEY, KEY); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, FLASH_CMD, &flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; /* Switch on register access */ flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON; if (mdr_info->mem_type) flash_cmd |= FLASH_IFREN; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; if ((first == 0) && (last == (bank->num_sectors - 1))) { retval = mdr_mass_erase(bank); goto reset_pg_and_lock; } unsigned int page_size = bank->size / mdr_info->page_count; for (i = first; i <= last; i++) { for (j = 0; j < mdr_info->sec_count; j++) { retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2)); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd |= FLASH_XE | FLASH_ERASE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd |= FLASH_NVSTR; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd &= ~FLASH_ERASE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd &= ~(FLASH_XE | FLASH_NVSTR); retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; } bank->sectors[i].is_erased = 1; } reset_pg_and_lock: flash_cmd &= FLASH_DELAY_MASK; retval2 = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval == ERROR_OK) retval = retval2; retval2 = target_write_u32(target, FLASH_KEY, 0); if (retval == ERROR_OK) retval = retval2; return retval; } static int mdr_protect(struct flash_bank *bank, int set, int first, int last) { return ERROR_OK; } static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* see contrib/loaders/flash/mdr32fx.S for src */ static const uint8_t mdr32fx_flash_write_code[] = { 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42, 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43, 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43, 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43, 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34, 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39, 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e, 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00 }; /* flash write code */ if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; retval = target_write_buffer(target, write_algorithm->address, sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } }; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer start */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[4], "r4", 32, PARAM_IN_OUT); /* target address */ buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE); buf_set_u32(reg_params[1].value, 0, 32, count); buf_set_u32(reg_params[2].value, 0, 32, source->address); buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[4].value, 0, 32, address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; retval = target_run_flash_async_algorithm(target, buffer, count, 4, 0, NULL, 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (retval == ERROR_FLASH_OPERATION_FAILED) LOG_ERROR("flash write failed at address 0x%"PRIx32, buf_get_u32(reg_params[4].value, 0, 32)); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return retval; } static int mdr_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct mdr_flash_bank *mdr_info = bank->driver_priv; uint8_t *new_buffer = NULL; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x3) { LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* If there's an odd number of bytes, the data has to be padded. Duplicate * the buffer and use the normal code path with a single block write since * it's probably cheaper than to special case the last odd write using * discrete accesses. */ int rem = count % 4; if (rem) { new_buffer = malloc(count + rem); if (new_buffer == NULL) { LOG_ERROR("odd number of bytes to write and no memory for padding buffer"); return ERROR_FAIL; } LOG_INFO("odd number of bytes to write, padding with 0xff"); buffer = memcpy(new_buffer, buffer, count); while (rem--) new_buffer[count++] = 0xff; } uint32_t flash_cmd, cur_per_clock; int retval, retval2; retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock); if (retval != ERROR_OK) goto free_buffer; if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) { /* Something's very wrong if the RST_CLK module is not clocked */ LOG_ERROR("Target needs reset before flash operations"); retval = ERROR_FLASH_OPERATION_FAILED; goto free_buffer; } retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM); if (retval != ERROR_OK) goto free_buffer; retval = target_write_u32(target, FLASH_KEY, KEY); if (retval != ERROR_OK) goto free_buffer; retval = target_read_u32(target, FLASH_CMD, &flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; /* Switch on register access */ flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON; if (mdr_info->mem_type) flash_cmd |= FLASH_IFREN; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; /* try using block write */ retval = mdr_write_block(bank, buffer, offset, count/4); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single halfword accesses */ LOG_WARNING("Can't use block writes, falling back to single memory accesses"); unsigned int page_size = bank->size / mdr_info->page_count; unsigned int page_mask = page_size - 1; while (count > 0) { unsigned int i, j; unsigned int cur_page = offset & ~page_mask; unsigned int bytes_to_write = cur_page + page_size - offset; if (count < bytes_to_write) bytes_to_write = count; /*LOG_INFO("Selecting next page: %08x", cur_page);*/ for (i = 0; i < mdr_info->sec_count; i++) { retval = target_write_u32(target, FLASH_ADR, offset + i*4); if (retval != ERROR_OK) goto reset_pg_and_lock; /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/ flash_cmd |= FLASH_XE | FLASH_PROG; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd |= FLASH_NVSTR; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; for (j = 0; (((offset + j + i*4) & ~page_mask) == cur_page) && (j + i*4 < count); j += mdr_info->sec_count*4) { uint32_t value; memcpy(&value, buffer + j + i*4, sizeof(uint32_t)); retval = target_write_u32(target, FLASH_DI, value); if (retval != ERROR_OK) goto reset_pg_and_lock; /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/ retval = target_write_u32(target, FLASH_ADR, offset + j + i*4); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd |= FLASH_YE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd &= ~FLASH_YE; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; } flash_cmd &= ~FLASH_NVSTR; retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; flash_cmd &= ~(FLASH_XE | FLASH_PROG); retval = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval != ERROR_OK) goto reset_pg_and_lock; } buffer += bytes_to_write; offset += bytes_to_write; count -= bytes_to_write; } } reset_pg_and_lock: flash_cmd &= FLASH_DELAY_MASK; retval2 = target_write_u32(target, FLASH_CMD, flash_cmd); if (retval == ERROR_OK) retval = retval2; retval2 = target_write_u32(target, FLASH_KEY, 0); if (retval == ERROR_OK) retval = retval2; free_buffer: if (new_buffer) free(new_buffer); return retval; } static int mdr_probe(struct flash_bank *bank) { struct mdr_flash_bank *mdr_info = bank->driver_priv; unsigned int page_count, page_size, i; page_count = mdr_info->page_count; page_size = bank->size / page_count; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->num_sectors = page_count; bank->sectors = malloc(sizeof(struct flash_sector) * page_count); for (i = 0; i < page_count; i++) { bank->sectors[i].offset = i * page_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; } mdr_info->probed = 1; return ERROR_OK; } static int mdr_auto_probe(struct flash_bank *bank) { struct mdr_flash_bank *mdr_info = bank->driver_priv; if (mdr_info->probed) return ERROR_OK; return mdr_probe(bank); } static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size) { struct mdr_flash_bank *mdr_info = bank->driver_priv; snprintf(buf, buf_size, "MDR32Fx - %s", mdr_info->mem_type ? "info memory" : "main memory"); return ERROR_OK; } struct flash_driver mdr_flash = { .name = "mdr", .usage = "flash bank mdr 0 0 \n" ": 0 for main memory, 1 for info memory", .flash_bank_command = mdr_flash_bank_command, .erase = mdr_erase, .protect = mdr_protect, .write = mdr_write, .read = default_flash_read, .probe = mdr_probe, .auto_probe = mdr_auto_probe, .erase_check = default_flash_blank_check, .protect_check = mdr_protect_check, .info = get_mdr_info, }; openocd-0.9.0/src/flash/nor/ocl.c0000644000175000017500000002306212315575360013505 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "ocl.h" #include struct ocl_priv { struct arm_jtag *jtag_info; unsigned int buflen; unsigned int bufalign; }; static int ocl_erase_check(struct flash_bank *bank) { return ERROR_OK; } static int ocl_protect_check(struct flash_bank *bank) { return ERROR_OK; } /* flash_bank ocl 0 0 0 0 */ FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command) { struct arm7_9_common *arm7_9; struct ocl_priv *ocl; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; arm7_9 = target_to_arm7_9(bank->target); if (!is_arm7_9(arm7_9)) return ERROR_TARGET_INVALID; ocl = bank->driver_priv = malloc(sizeof(struct ocl_priv)); ocl->jtag_info = &arm7_9->jtag_info; ocl->buflen = 0; ocl->bufalign = 1; return ERROR_OK; } static int ocl_erase(struct flash_bank *bank, int first, int last) { struct ocl_priv *ocl = bank->driver_priv; int retval; uint32_t dcc_buffer[3]; /* check preconditions */ if (bank->num_sectors == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_RUNNING) { LOG_ERROR("target has to be running to communicate with the loader"); return ERROR_TARGET_NOT_RUNNING; } if ((first == 0) && (last == bank->num_sectors - 1)) { dcc_buffer[0] = OCL_ERASE_ALL; retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; } else { dcc_buffer[0] = OCL_ERASE_BLOCK; dcc_buffer[1] = first; dcc_buffer[2] = last; retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3); if (retval != ERROR_OK) return retval; } /* wait for response, fixed timeout of 1 s */ retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); if (retval != ERROR_OK) return retval; /* receive response */ retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1); if (retval != ERROR_OK) return retval; if (dcc_buffer[1] != OCL_CMD_DONE) { if (dcc_buffer[0] == OCL_ERASE_ALL) LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]); else LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int ocl_protect(struct flash_bank *bank, int set, int first, int last) { return ERROR_OK; } static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct ocl_priv *ocl = bank->driver_priv; int retval; uint32_t *dcc_buffer; uint32_t *dcc_bufptr; int byteofs; int runlen; uint32_t chksum; int i; /* check preconditions */ if (ocl->buflen == 0 || ocl->bufalign == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_RUNNING) { LOG_ERROR("target has to be running to communicate with the loader"); return ERROR_TARGET_NOT_RUNNING; } /* allocate buffer for max. ocl buffer + overhead */ dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3)); while (count) { if (count + (offset % ocl->bufalign) > ocl->buflen) runlen = ocl->buflen - (offset % ocl->bufalign); else runlen = count; dcc_buffer[0] = OCL_FLASH_BLOCK | runlen; dcc_buffer[1] = offset; dcc_bufptr = &dcc_buffer[2]; *dcc_bufptr = 0xffffffff; byteofs = (offset % ocl->bufalign) % 4; chksum = OCL_CHKS_INIT; /* copy data to DCC buffer in proper byte order and properly aligned */ for (i = 0; i < runlen; i++) { switch (byteofs++) { case 0: *dcc_bufptr &= *(buffer++) | 0xffffff00; break; case 1: *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff; break; case 2: *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff; break; case 3: *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff; chksum ^= *(dcc_bufptr++); *dcc_bufptr = 0xffffffff; byteofs = 0; break; } } /* add the remaining word to checksum */ if (byteofs) chksum ^= *(dcc_bufptr++); *(dcc_bufptr++) = chksum; /* send the data */ retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer); if (retval != ERROR_OK) { free(dcc_buffer); return retval; } /* wait for response, fixed timeout of 1 s */ retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); if (retval != ERROR_OK) { free(dcc_buffer); return retval; } /* receive response */ retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) { free(dcc_buffer); return retval; } if (dcc_buffer[0] != OCL_CMD_DONE) { LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]); free(dcc_buffer); return ERROR_FLASH_OPERATION_FAILED; } count -= runlen; offset += runlen; } free(dcc_buffer); return ERROR_OK; } static int ocl_probe(struct flash_bank *bank) { struct ocl_priv *ocl = bank->driver_priv; int retval; uint32_t dcc_buffer[1]; int sectsize; int i; /* purge pending data in DCC */ embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); dcc_buffer[0] = OCL_PROBE; retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; /* wait for response, fixed timeout of 1 s */ retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); if (retval != ERROR_OK) return retval; /* receive response */ retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; if (dcc_buffer[0] != OCL_CMD_DONE) { LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]); return ERROR_FLASH_OPERATION_FAILED; } /* receive and fill in parameters, detection of loader is important, receive it one by one */ retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); if (retval != ERROR_OK) return retval; retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; bank->base = dcc_buffer[0]; retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); if (retval != ERROR_OK) return retval; retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; bank->size = dcc_buffer[0]; retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); if (retval != ERROR_OK) return retval; retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; bank->num_sectors = dcc_buffer[0]; retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); if (retval != ERROR_OK) return retval; retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); if (retval != ERROR_OK) return retval; ocl->buflen = dcc_buffer[0] & 0xffff; ocl->bufalign = dcc_buffer[0] >> 16; bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors); if (bank->num_sectors == 0) { LOG_ERROR("number of sectors shall be non zero value"); return ERROR_FLASH_BANK_INVALID; } if (bank->size % bank->num_sectors) { LOG_ERROR("bank size not divisible by number of sectors"); return ERROR_FLASH_BANK_INVALID; } sectsize = bank->size / bank->num_sectors; for (i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = i * sectsize; bank->sectors[i].size = sectsize; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } if (ocl->bufalign == 0) ocl->bufalign = 1; if (ocl->buflen == 0) { LOG_ERROR("buflen shall be non zero value"); return ERROR_FLASH_BANK_INVALID; } if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) { LOG_ERROR("buflen is not multiple of bufalign"); return ERROR_FLASH_BANK_INVALID; } if (ocl->buflen % 4) { LOG_ERROR("buflen shall be divisible by 4"); return ERROR_FLASH_BANK_INVALID; } return ERROR_OK; } static int ocl_auto_probe(struct flash_bank *bank) { struct ocl_priv *ocl = bank->driver_priv; if (ocl->buflen == 0 || ocl->bufalign == 0) return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_OK; } struct flash_driver ocl_flash = { .name = "ocl", .flash_bank_command = ocl_flash_bank_command, .erase = ocl_erase, .protect = ocl_protect, .write = ocl_write, .read = default_flash_read, .probe = ocl_probe, .erase_check = ocl_erase_check, .protect_check = ocl_protect_check, .auto_probe = ocl_auto_probe, }; openocd-0.9.0/src/flash/nor/ocl.h0000644000175000017500000000356712315575360013522 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OCL_H #define OCL_H /* command/response mask */ #define OCL_CMD_MASK 0xFFFF0000L /* commads */ #define OCL_FLASH_BLOCK 0x0CFB0000L #define OCL_ERASE_BLOCK 0x0CEB0000L #define OCL_ERASE_ALL 0x0CEA0000L #define OCL_PROBE 0x0CBE0000L /* responses */ #define OCL_CMD_DONE 0x0ACD0000L #define OCL_CMD_ERR 0x0ACE0000L #define OCL_CHKS_FAIL 0x0ACF0000L #define OCL_BUFF_OVER 0x0AB00000L #define OCL_CHKS_INIT 0xC100CD0CL #endif /* OCL_H */ openocd-0.9.0/src/flash/nor/tcl.c0000644000175000017500000005760212516456302013516 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include /** * @file * Implements Tcl commands used to access NOR flash facilities. */ COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index, struct flash_bank **bank, bool do_probe) { const char *name = CMD_ARGV[name_index]; int retval; if (do_probe) { retval = get_flash_bank_by_name(name, bank); } else { *bank = get_flash_bank_by_name_noprobe(name); retval = ERROR_OK; } if (retval != ERROR_OK) return retval; if (*bank) return ERROR_OK; unsigned bank_num; COMMAND_PARSE_NUMBER(uint, name, bank_num); if (do_probe) { return get_flash_bank_by_num(bank_num, bank); } else { *bank = get_flash_bank_by_num_noprobe(bank_num); retval = (bank) ? ERROR_OK : ERROR_FAIL; return retval; } } COMMAND_HELPER(flash_command_get_bank, unsigned name_index, struct flash_bank **bank) { return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, name_index, bank, true); } COMMAND_HANDLER(handle_flash_info_command) { struct flash_bank *p; int j = 0; int retval; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (retval != ERROR_OK) return retval; if (p != NULL) { char buf[1024]; /* attempt auto probe */ retval = p->driver->auto_probe(p); if (retval != ERROR_OK) return retval; /* We must query the hardware to avoid printing stale information! */ retval = p->driver->protect_check(p); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "#%d : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i", p->bank_number, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); for (j = 0; j < p->num_sectors; j++) { char *protect_state; if (p->sectors[j].is_protected == 0) protect_state = "not protected"; else if (p->sectors[j].is_protected == 1) protect_state = "protected"; else protect_state = "protection state unknown"; command_print(CMD_CTX, "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size >> 10, protect_state); } if (p->driver->info != NULL) { retval = p->driver->info(p, buf, sizeof(buf)); if (retval == ERROR_OK) command_print(CMD_CTX, "%s", buf); else LOG_ERROR("error retrieving flash info"); } } return retval; } COMMAND_HANDLER(handle_flash_probe_command) { struct flash_bank *p; int retval; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; retval = CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, 0, &p, false); if (retval != ERROR_OK) return retval; if (p) { retval = p->driver->probe(p); if (retval == ERROR_OK) command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base); } else { command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]); retval = ERROR_FAIL; } return retval; } COMMAND_HANDLER(handle_flash_erase_check_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *p; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (ERROR_OK != retval) return retval; int j; retval = p->driver->erase_check(p); if (retval == ERROR_OK) command_print(CMD_CTX, "successfully checked erase state"); else { command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32, CMD_ARGV[0], p->base); } for (j = 0; j < p->num_sectors; j++) { char *erase_state; if (p->sectors[j].is_erased == 0) erase_state = "not erased"; else if (p->sectors[j].is_erased == 1) erase_state = "erased"; else erase_state = "erase state unknown"; command_print(CMD_CTX, "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size >> 10, erase_state); } return retval; } COMMAND_HANDLER(handle_flash_erase_address_command) { struct flash_bank *p; int retval = ERROR_OK; uint32_t address; uint32_t length; bool do_pad = false; bool do_unlock = false; struct target *target = get_current_target(CMD_CTX); while (CMD_ARGC >= 3) { /* Optionally pad out the address range to block/sector * boundaries. We can't know if there's data in that part * of the flash; only do padding if we're told to. */ if (strcmp("pad", CMD_ARGV[0]) == 0) do_pad = true; else if (strcmp("unlock", CMD_ARGV[0]) == 0) do_unlock = true; else return ERROR_COMMAND_SYNTAX_ERROR; CMD_ARGC--; CMD_ARGV++; } if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); if (length <= 0) { command_print(CMD_CTX, "Length must be >0"); return ERROR_COMMAND_SYNTAX_ERROR; } retval = get_flash_bank_by_addr(target, address, true, &p); if (retval != ERROR_OK) return retval; /* We can't know if we did a resume + halt, in which case we no longer know the erased state **/ flash_set_dirty(); struct duration bench; duration_start(&bench); if (do_unlock) retval = flash_unlock_address_range(target, address, length); if (retval == ERROR_OK) retval = flash_erase_address_range(target, do_pad, address, length); if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "erased address 0x%8.8" PRIx32 " (length %" PRIi32 ")" " in %fs (%0.3f KiB/s)", address, length, duration_elapsed(&bench), duration_kbps(&bench, length)); } return retval; } static int flash_check_sector_parameters(struct command_context *cmd_ctx, uint32_t first, uint32_t last, uint32_t num_sectors) { if (!(first <= last)) { command_print(cmd_ctx, "ERROR: " "first sector must be <= last sector"); return ERROR_FAIL; } if (!(last <= (num_sectors - 1))) { command_print(cmd_ctx, "ERROR: last sector must be <= %d", (int) num_sectors - 1); return ERROR_FAIL; } return ERROR_OK; } COMMAND_HANDLER(handle_flash_erase_command) { if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t first; uint32_t last; struct flash_bank *p; int retval; retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (retval != ERROR_OK) return retval; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); if (strcmp(CMD_ARGV[2], "last") == 0) last = p->num_sectors - 1; else COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); if (retval != ERROR_OK) return retval; struct duration bench; duration_start(&bench); retval = flash_driver_erase(p, first, last); if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "erased sectors %" PRIu32 " " "through %" PRIu32 " on flash bank %d " "in %fs", first, last, p->bank_number, duration_elapsed(&bench)); } return ERROR_OK; } COMMAND_HANDLER(handle_flash_protect_command) { if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t first; uint32_t last; struct flash_bank *p; int retval; retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (retval != ERROR_OK) return retval; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); if (strcmp(CMD_ARGV[2], "last") == 0) last = p->num_sectors - 1; else COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); bool set; COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); if (retval != ERROR_OK) return retval; retval = flash_driver_protect(p, set, first, last); if (retval == ERROR_OK) { command_print(CMD_CTX, "%s protection for sectors %i " "through %i on flash bank %d", (set) ? "set" : "cleared", (int) first, (int) last, p->bank_number); } return retval; } COMMAND_HANDLER(handle_flash_write_image_command) { struct target *target = get_current_target(CMD_CTX); struct image image; uint32_t written; int retval; /* flash auto-erase is disabled by default*/ int auto_erase = 0; bool auto_unlock = false; while (CMD_ARGC) { if (strcmp(CMD_ARGV[0], "erase") == 0) { auto_erase = 1; CMD_ARGV++; CMD_ARGC--; command_print(CMD_CTX, "auto erase enabled"); } else if (strcmp(CMD_ARGV[0], "unlock") == 0) { auto_unlock = true; CMD_ARGV++; CMD_ARGC--; command_print(CMD_CTX, "auto unlock enabled"); } else break; } if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (!target) { LOG_ERROR("no target selected"); return ERROR_FAIL; } struct duration bench; duration_start(&bench); if (CMD_ARGC >= 2) { image.base_address_set = 1; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address); } else { image.base_address_set = 0; image.base_address = 0x0; } image.start_address_set = 0; retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) return retval; retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock); if (retval != ERROR_OK) { image_close(&image); return retval; } if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s " "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0], duration_elapsed(&bench), duration_kbps(&bench, written)); } image_close(&image); return retval; } COMMAND_HANDLER(handle_flash_fill_command) { int err = ERROR_OK; uint32_t address; uint32_t pattern; uint32_t count; uint32_t wrote = 0; uint32_t cur_size = 0; uint32_t chunk_count; struct target *target = get_current_target(CMD_CTX); unsigned i; uint32_t wordsize; int retval = ERROR_OK; static size_t const chunksize = 1024; uint8_t *chunk = NULL, *readback = NULL; if (CMD_ARGC != 3) { retval = ERROR_COMMAND_SYNTAX_ERROR; goto done; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); chunk = malloc(chunksize); if (chunk == NULL) return ERROR_FAIL; readback = malloc(chunksize); if (readback == NULL) { free(chunk); return ERROR_FAIL; } if (count == 0) goto done; switch (CMD_NAME[4]) { case 'w': wordsize = 4; break; case 'h': wordsize = 2; break; case 'b': wordsize = 1; break; default: retval = ERROR_COMMAND_SYNTAX_ERROR; goto done; } chunk_count = MIN(count, (chunksize / wordsize)); switch (wordsize) { case 4: for (i = 0; i < chunk_count; i++) target_buffer_set_u32(target, chunk + i * wordsize, pattern); break; case 2: for (i = 0; i < chunk_count; i++) target_buffer_set_u16(target, chunk + i * wordsize, pattern); break; case 1: memset(chunk, pattern, chunk_count); break; default: LOG_ERROR("BUG: can't happen"); exit(-1); } struct duration bench; duration_start(&bench); for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) { struct flash_bank *bank; retval = get_flash_bank_by_addr(target, address, true, &bank); if (retval != ERROR_OK) goto done; cur_size = MIN((count * wordsize - wrote), chunksize); err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size); if (err != ERROR_OK) { retval = err; goto done; } err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size); if (err != ERROR_OK) { retval = err; goto done; } for (i = 0; i < cur_size; i++) { if (readback[i] != chunk[i]) { LOG_ERROR( "Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x", address + wrote + i, readback[i], chunk[i]); retval = ERROR_FAIL; goto done; } } } if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", wrote, address, duration_elapsed(&bench), duration_kbps(&bench, wrote)); } done: free(readback); free(chunk); return retval; } COMMAND_HANDLER(handle_flash_write_bank_command) { uint32_t offset; uint8_t *buffer; struct fileio fileio; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; struct duration bench; duration_start(&bench); struct flash_bank *p; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (ERROR_OK != retval) return retval; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) return ERROR_OK; int filesize; retval = fileio_size(&fileio, &filesize); if (retval != ERROR_OK) { fileio_close(&fileio); return retval; } buffer = malloc(filesize); if (buffer == NULL) { fileio_close(&fileio); LOG_ERROR("Out of memory"); return ERROR_FAIL; } size_t buf_cnt; if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { free(buffer); fileio_close(&fileio); return ERROR_OK; } retval = flash_driver_write(p, buffer, offset, buf_cnt); free(buffer); buffer = NULL; if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", (long)filesize, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, filesize)); } fileio_close(&fileio); return retval; } void flash_set_dirty(void) { struct flash_bank *c; int i; /* set all flash to require erasing */ for (c = flash_bank_list(); c; c = c->next) { for (i = 0; i < c->num_sectors; i++) c->sectors[i].is_erased = 0; } } COMMAND_HANDLER(handle_flash_padded_value_command) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *p; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (ERROR_OK != retval) return retval; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value); command_print(CMD_CTX, "Default padded value set to 0x%" PRIx8 " for flash bank %u", \ p->default_padded_value, p->bank_number); return retval; } static const struct command_registration flash_exec_command_handlers[] = { { .name = "probe", .handler = handle_flash_probe_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Identify a flash bank.", }, { .name = "info", .handler = handle_flash_info_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Print information about a flash bank.", }, { .name = "erase_check", .handler = handle_flash_erase_check_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Check erase state of all blocks in a " "flash bank.", }, { .name = "erase_sector", .handler = handle_flash_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id first_sector_num last_sector_num", .help = "Erase a range of sectors in a flash bank.", }, { .name = "erase_address", .handler = handle_flash_erase_address_command, .mode = COMMAND_EXEC, .usage = "['pad'] ['unlock'] address length", .help = "Erase flash sectors starting at address and " "continuing for length bytes. If 'pad' is specified, " "data outside that range may also be erased: the start " "address may be decreased, and length increased, so " "that all of the first and last sectors are erased. " "If 'unlock' is specified, then the flash is unprotected " "before erasing.", }, { .name = "fillw", .handler = handle_flash_fill_command, .mode = COMMAND_EXEC, .usage = "address value n", .help = "Fill n words with 32-bit value, starting at " "word address. (No autoerase.)", }, { .name = "fillh", .handler = handle_flash_fill_command, .mode = COMMAND_EXEC, .usage = "address value n", .help = "Fill n halfwords with 16-bit value, starting at " "word address. (No autoerase.)", }, { .name = "fillb", .handler = handle_flash_fill_command, .mode = COMMAND_EXEC, .usage = "address value n", .help = "Fill n bytes with 8-bit value, starting at " "word address. (No autoerase.)", }, { .name = "write_bank", .handler = handle_flash_write_bank_command, .mode = COMMAND_EXEC, .usage = "bank_id filename offset", .help = "Write binary data from file to flash bank, " "starting at specified byte offset from the " "beginning of the bank.", }, { .name = "write_image", .handler = handle_flash_write_image_command, .mode = COMMAND_EXEC, .usage = "[erase] [unlock] filename [offset [file_type]]", .help = "Write an image to flash. Optionally first unprotect " "and/or erase the region to be used. Allow optional " "offset from beginning of bank (defaults to zero)", }, { .name = "protect", .handler = handle_flash_protect_command, .mode = COMMAND_EXEC, .usage = "bank_id first_sector [last_sector|'last'] " "('on'|'off')", .help = "Turn protection on or off for a range of sectors " "in a given flash bank.", }, { .name = "padded_value", .handler = handle_flash_padded_value_command, .mode = COMMAND_EXEC, .usage = "bank_id value", .help = "Set default flash padded value", }, COMMAND_REGISTRATION_DONE }; static int flash_init_drivers(struct command_context *cmd_ctx) { if (!flash_bank_list()) return ERROR_OK; struct command *parent = command_find_in_context(cmd_ctx, "flash"); return register_commands(cmd_ctx, parent, flash_exec_command_handlers); } COMMAND_HANDLER(handle_flash_bank_command) { if (CMD_ARGC < 7) { LOG_ERROR("usage: flash bank " " "); return ERROR_COMMAND_SYNTAX_ERROR; } /* save bank name and advance arguments for compatibility */ const char *bank_name = *CMD_ARGV++; CMD_ARGC--; struct target *target = get_target(CMD_ARGV[5]); if (target == NULL) { LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); return ERROR_FAIL; } const char *driver_name = CMD_ARGV[0]; struct flash_driver *driver = flash_driver_find_by_name(driver_name); if (NULL == driver) { /* no matching flash driver found */ LOG_ERROR("flash driver '%s' not found", driver_name); return ERROR_FAIL; } /* check the flash bank name is unique */ if (get_flash_bank_by_name_noprobe(bank_name) != NULL) { /* flash bank name already exists */ LOG_ERROR("flash bank name '%s' already exists", bank_name); return ERROR_FAIL; } /* register flash specific commands */ if (NULL != driver->commands) { int retval = register_commands(CMD_CTX, NULL, driver->commands); if (ERROR_OK != retval) { LOG_ERROR("couldn't register '%s' commands", driver_name); return ERROR_FAIL; } } struct flash_bank *c = malloc(sizeof(*c)); c->name = strdup(bank_name); c->target = target; c->driver = driver; c->driver_priv = NULL; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width); c->default_padded_value = 0xff; c->num_sectors = 0; c->sectors = NULL; c->next = NULL; int retval; retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c); if (ERROR_OK != retval) { LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "; usage: %s", driver_name, c->base, driver->usage); free(c); return retval; } if (driver->usage == NULL) LOG_DEBUG("'%s' driver usage field missing", driver_name); flash_bank_add(c); return ERROR_OK; } COMMAND_HANDLER(handle_flash_banks_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; unsigned n = 0; for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) { LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", " "buswidth %u, chipwidth %u", p->bank_number, p->name, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); } return ERROR_OK; } static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "no arguments to 'flash list' command"); return JIM_ERR; } Jim_Obj *list = Jim_NewListObj(interp, NULL, 0); for (struct flash_bank *p = flash_bank_list(); p; p = p->next) { Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width)); Jim_ListAppendElement(interp, list, elem); } Jim_SetResult(interp, list); return JIM_OK; } COMMAND_HANDLER(handle_flash_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool flash_initialized; if (flash_initialized) { LOG_INFO("'flash init' has already been called"); return ERROR_OK; } flash_initialized = true; LOG_DEBUG("Initializing flash devices..."); return flash_init_drivers(CMD_CTX); } static const struct command_registration flash_config_command_handlers[] = { { .name = "bank", .handler = handle_flash_bank_command, .mode = COMMAND_CONFIG, .usage = "bank_id driver_name base_address size_bytes " "chip_width_bytes bus_width_bytes target " "[driver_options ...]", .help = "Define a new bank with the given name, " "using the specified NOR flash driver.", }, { .name = "init", .mode = COMMAND_CONFIG, .handler = handle_flash_init_command, .help = "Initialize flash devices.", }, { .name = "banks", .mode = COMMAND_ANY, .handler = handle_flash_banks_command, .help = "Display table with information about flash banks.", }, { .name = "list", .mode = COMMAND_ANY, .jim_handler = jim_flash_list, .help = "Returns a list of details about the flash banks.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration flash_command_handlers[] = { { .name = "flash", .mode = COMMAND_ANY, .help = "NOR flash command group", .chain = flash_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; int flash_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, flash_command_handlers); } openocd-0.9.0/src/flash/nor/spi.c0000644000175000017500000001251212516456302013516 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * Copyright (C) 2010 by Antonio Borneo * * borneo.antonio@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "spi.h" #include /* Shared table of known SPI flash devices for SPI-based flash drivers. Taken * from device datasheets and Linux SPI flash drivers. */ const struct flash_device flash_devices[] = { /* name, erase_cmd, chip_erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */ FLASH_ID("st m25p05", 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000), FLASH_ID("st m25p10", 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000), FLASH_ID("st m25p20", 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000), FLASH_ID("st m25p40", 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000), FLASH_ID("st m25p80", 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000), FLASH_ID("st m25p16", 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000), FLASH_ID("st m25p32", 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000), FLASH_ID("st m25p64", 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000), FLASH_ID("st m25p128", 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000), FLASH_ID("st m45pe10", 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000), FLASH_ID("st m45pe20", 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000), FLASH_ID("st m45pe40", 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000), FLASH_ID("st m45pe80", 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000), FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000), FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000), FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000), FLASH_ID("sp s25fl116k", 0xd8, 0xC7, 0x00154001, 0x100, 0x10000, 0x200000), FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000), FLASH_ID("sp s25fl132k", 0xd8, 0xC7, 0x00164001, 0x100, 0x10000, 0x400000), FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000), FLASH_ID("sp s25fl164k", 0xd8, 0xC7, 0x00174001, 0x100, 0x10000, 0x800000), FLASH_ID("sp s25fl128", 0xd8, 0xC7, 0x00182001, 0x100, 0x10000, 0x1000000), FLASH_ID("sp s25fl256", 0xd8, 0xC7, 0x00190201, 0x100, 0x10000, 0x2000000), FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000), FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000), FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000), FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000), FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000), FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000), FLASH_ID("mac 25l1005", 0xd8, 0xd8, 0x001120c2, 0x010, 0x10000, 0x20000), FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000), FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000), FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000), FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000), FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000), FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000), FLASH_ID("mcr n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000), FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000), FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000), FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000), FLASH_ID("win w25q64cv", 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000), FLASH_ID("gd gd25q20", 0x20, 0xc7, 0x00c84012, 0x100, 0x1000, 0x80000), FLASH_ID(NULL, 0, 0, 0, 0, 0, 0) }; openocd-0.9.0/src/flash/nor/spi.h0000644000175000017500000000537012315575360013532 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * Copyright (C) 2010 by Antonio Borneo * * borneo.antonio@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* data structure to maintain flash ids from different vendors */ struct flash_device { char *name; uint8_t erase_cmd; uint8_t chip_erase_cmd; uint32_t device_id; uint32_t pagesize; unsigned long sectorsize; unsigned long size_in_bytes; }; #define FLASH_ID(n, es, ces, id, psize, ssize, size) \ { \ .name = n, \ .erase_cmd = es, \ .chip_erase_cmd = ces, \ .device_id = id, \ .pagesize = psize, \ .sectorsize = ssize, \ .size_in_bytes = size \ } extern const struct flash_device flash_devices[]; /* fields in SPI flash status register */ #define SPIFLASH_BSY_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */ #define SPIFLASH_WE_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */ /* SPI Flash Commands */ #define SPIFLASH_READ_ID 0x9F /* Read Flash Identification */ #define SPIFLASH_READ_STATUS 0x05 /* Read Status Register */ #define SPIFLASH_WRITE_ENABLE 0x06 /* Write Enable */ #define SPIFLASH_PAGE_PROGRAM 0x02 /* Page Program */ #define SPIFLASH_FAST_READ 0x0B /* Fast Read */ #define SPIFLASH_READ 0x03 /* Normal Read */ openocd-0.9.0/src/flash/nor/drivers.c0000644000175000017500000000757712516456302014420 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" extern struct flash_driver lpc2000_flash; extern struct flash_driver lpc288x_flash; extern struct flash_driver lpc2900_flash; extern struct flash_driver lpcspifi_flash; extern struct flash_driver cfi_flash; extern struct flash_driver at91sam3_flash; extern struct flash_driver at91sam4_flash; extern struct flash_driver at91sam4l_flash; extern struct flash_driver at91samd_flash; extern struct flash_driver at91sam7_flash; extern struct flash_driver str7x_flash; extern struct flash_driver str9x_flash; extern struct flash_driver aduc702x_flash; extern struct flash_driver stellaris_flash; extern struct flash_driver str9xpec_flash; extern struct flash_driver stm32f1x_flash; extern struct flash_driver stm32f2x_flash; extern struct flash_driver stm32lx_flash; extern struct flash_driver tms470_flash; extern struct flash_driver ocl_flash; extern struct flash_driver pic32mx_flash; extern struct flash_driver avr_flash; extern struct flash_driver faux_flash; extern struct flash_driver virtual_flash; extern struct flash_driver stmsmi_flash; extern struct flash_driver em357_flash; extern struct flash_driver dsp5680xx_flash; extern struct flash_driver fm3_flash; extern struct flash_driver kinetis_flash; extern struct flash_driver efm32_flash; extern struct flash_driver mdr_flash; extern struct flash_driver mini51_flash; extern struct flash_driver nuc1x_flash; extern struct flash_driver nrf51_flash; extern struct flash_driver mrvlqspi_flash; extern struct flash_driver psoc4_flash; extern struct flash_driver sim3x_flash; /** * The list of built-in flash drivers. * @todo Make this dynamically extendable with loadable modules. */ static struct flash_driver *flash_drivers[] = { &lpc2000_flash, &lpc288x_flash, &lpc2900_flash, &lpcspifi_flash, &cfi_flash, &at91sam7_flash, &at91sam3_flash, &at91sam4_flash, &at91sam4l_flash, &at91samd_flash, &str7x_flash, &str9x_flash, &aduc702x_flash, &stellaris_flash, &str9xpec_flash, &stm32f1x_flash, &stm32f2x_flash, &stm32lx_flash, &tms470_flash, &ocl_flash, &pic32mx_flash, &avr_flash, &faux_flash, &virtual_flash, &stmsmi_flash, &em357_flash, &fm3_flash, &dsp5680xx_flash, &kinetis_flash, &efm32_flash, &mdr_flash, &mini51_flash, &nuc1x_flash, &nrf51_flash, &mrvlqspi_flash, &psoc4_flash, &sim3x_flash, NULL, }; struct flash_driver *flash_driver_find_by_name(const char *name) { for (unsigned i = 0; flash_drivers[i]; i++) { if (strcmp(name, flash_drivers[i]->name) == 0) return flash_drivers[i]; } return NULL; } openocd-0.9.0/src/flash/nor/kinetis.c0000644000175000017500000012732612516456302014403 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * kesmtp@freenet.de * * * * Copyright (C) 2011 sleep(5) ltd * * tomas@sleepfive.com * * * * Copyright (C) 2012 by Christopher D. Kilgour * * techie at whiterocker.com * * * * Copyright (C) 2013 Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/interface.h" #include "imp.h" #include #include #include #include /* * Implementation Notes * * The persistent memories in the Kinetis chip families K10 through * K70 are all manipulated with the Flash Memory Module. Some * variants call this module the FTFE, others call it the FTFL. To * indicate that both are considered here, we use FTFX. * * Within the module, according to the chip variant, the persistent * memory is divided into what Freescale terms Program Flash, FlexNVM, * and FlexRAM. All chip variants have Program Flash. Some chip * variants also have FlexNVM and FlexRAM, which always appear * together. * * A given Kinetis chip may have 2 or 4 blocks of flash. Here we map * each block to a separate bank. Each block size varies by chip and * may be determined by the read-only SIM_FCFG1 register. The sector * size within each bank/block varies by the chip granularity as * described below. * * Kinetis offers four different of flash granularities applicable * across the chip families. The granularity is apparently reflected * by at least the reference manual suffix. For example, for chip * MK60FN1M0VLQ12, reference manual K60P144M150SF3RM ends in "SF3RM", * where the "3" indicates there are four flash blocks with 4kiB * sectors. All possible granularities are indicated below. * * The first half of the flash (1 or 2 blocks, depending on the * granularity) is always Program Flash and always starts at address * 0x00000000. The "PFLSH" flag, bit 23 of the read-only SIM_FCFG2 * register, determines whether the second half of the flash is also * Program Flash or FlexNVM+FlexRAM. When PFLSH is set, the second * half of flash is Program Flash and is contiguous in the memory map * from the first half. When PFLSH is clear, the second half of flash * is FlexNVM and always starts at address 0x10000000. FlexRAM, which * is also present when PFLSH is clear, always starts at address * 0x14000000. * * The Flash Memory Module provides a register set where flash * commands are loaded to perform flash operations like erase and * program. Different commands are available depending on whether * Program Flash or FlexNVM/FlexRAM is being manipulated. Although * the commands used are quite consistent between flash blocks, the * parameters they accept differ according to the flash granularity. * Some Kinetis chips have different granularity between Program Flash * and FlexNVM/FlexRAM, so flash command arguments may differ between * blocks in the same chip. * */ static const struct { unsigned pflash_sector_size_bytes; unsigned nvm_sector_size_bytes; unsigned num_blocks; } kinetis_flash_params[4] = { { 1<<10, 1<<10, 2 }, { 2<<10, 1<<10, 2 }, { 2<<10, 2<<10, 2 }, { 4<<10, 4<<10, 4 } }; /* Addressess */ #define FLEXRAM 0x14000000 #define FTFx_FSTAT 0x40020000 #define FTFx_FCNFG 0x40020001 #define FTFx_FCCOB3 0x40020004 #define FTFx_FPROT3 0x40020010 #define SIM_SDID 0x40048024 #define SIM_FCFG1 0x4004804c #define SIM_FCFG2 0x40048050 /* Commands */ #define FTFx_CMD_BLOCKSTAT 0x00 #define FTFx_CMD_SECTSTAT 0x01 #define FTFx_CMD_LWORDPROG 0x06 #define FTFx_CMD_SECTERASE 0x09 #define FTFx_CMD_SECTWRITE 0x0b #define FTFx_CMD_SETFLEXRAM 0x81 #define FTFx_CMD_MASSERASE 0x44 /* The Kinetis K series uses the following SDID layout : * Bit 31-16 : 0 * Bit 15-12 : REVID * Bit 11-7 : DIEID * Bit 6-4 : FAMID * Bit 3-0 : PINID * * The Kinetis KL series uses the following SDID layout : * Bit 31-28 : FAMID * Bit 27-24 : SUBFAMID * Bit 23-20 : SERIESID * Bit 19-16 : SRAMSIZE * Bit 15-12 : REVID * Bit 6-4 : Reserved (0) * Bit 3-0 : PINID * * SERIESID should be 1 for the KL-series so we assume that if * bits 31-16 are 0 then it's a K-series MCU. */ #define KINETIS_SDID_K_SERIES_MASK 0x0000FFFF #define KINETIS_SDID_DIEID_MASK 0x00000F80 #define KINETIS_SDID_DIEID_K_A 0x00000100 #define KINETIS_SDID_DIEID_K_B 0x00000200 #define KINETIS_SDID_DIEID_KL 0x00000000 /* We can't rely solely on the FAMID field to determine the MCU * type since some FAMID values identify multiple MCUs with * different flash sector sizes (K20 and K22 for instance). * Therefore we combine it with the DIEID bits which may possibly * break if Freescale bumps the DIEID for a particular MCU. */ #define KINETIS_K_SDID_TYPE_MASK 0x00000FF0 #define KINETIS_K_SDID_K10_M50 0x00000000 #define KINETIS_K_SDID_K10_M72 0x00000080 #define KINETIS_K_SDID_K10_M100 0x00000100 #define KINETIS_K_SDID_K10_M120 0x00000180 #define KINETIS_K_SDID_K11 0x00000220 #define KINETIS_K_SDID_K12 0x00000200 #define KINETIS_K_SDID_K20_M50 0x00000010 #define KINETIS_K_SDID_K20_M72 0x00000090 #define KINETIS_K_SDID_K20_M100 0x00000110 #define KINETIS_K_SDID_K20_M120 0x00000190 #define KINETIS_K_SDID_K21_M50 0x00000230 #define KINETIS_K_SDID_K21_M120 0x00000330 #define KINETIS_K_SDID_K22_M50 0x00000210 #define KINETIS_K_SDID_K22_M120 0x00000310 #define KINETIS_K_SDID_K30_M72 0x000000A0 #define KINETIS_K_SDID_K30_M100 0x00000120 #define KINETIS_K_SDID_K40_M72 0x000000B0 #define KINETIS_K_SDID_K40_M100 0x00000130 #define KINETIS_K_SDID_K50_M72 0x000000E0 #define KINETIS_K_SDID_K51_M72 0x000000F0 #define KINETIS_K_SDID_K53 0x00000170 #define KINETIS_K_SDID_K60_M100 0x00000140 #define KINETIS_K_SDID_K60_M150 0x000001C0 #define KINETIS_K_SDID_K70_M150 0x000001D0 #define KINETIS_KL_SDID_SERIESID_MASK 0x00F00000 #define KINETIS_KL_SDID_SERIESID_KL 0x00100000 struct kinetis_flash_bank { unsigned granularity; unsigned bank_ordinal; uint32_t sector_size; uint32_t protection_size; uint32_t klxx; uint32_t sim_sdid; uint32_t sim_fcfg1; uint32_t sim_fcfg2; enum { FC_AUTO = 0, FC_PFLASH, FC_FLEX_NVM, FC_FLEX_RAM, } flash_class; }; #define MDM_REG_STAT 0x00 #define MDM_REG_CTRL 0x04 #define MDM_REG_ID 0xfc #define MDM_STAT_FMEACK (1<<0) #define MDM_STAT_FREADY (1<<1) #define MDM_STAT_SYSSEC (1<<2) #define MDM_STAT_SYSRES (1<<3) #define MDM_STAT_FMEEN (1<<5) #define MDM_STAT_BACKDOOREN (1<<6) #define MDM_STAT_LPEN (1<<7) #define MDM_STAT_VLPEN (1<<8) #define MDM_STAT_LLSMODEXIT (1<<9) #define MDM_STAT_VLLSXMODEXIT (1<<10) #define MDM_STAT_CORE_HALTED (1<<16) #define MDM_STAT_CORE_SLEEPDEEP (1<<17) #define MDM_STAT_CORESLEEPING (1<<18) #define MEM_CTRL_FMEIP (1<<0) #define MEM_CTRL_DBG_DIS (1<<1) #define MEM_CTRL_DBG_REQ (1<<2) #define MEM_CTRL_SYS_RES_REQ (1<<3) #define MEM_CTRL_CORE_HOLD_RES (1<<4) #define MEM_CTRL_VLLSX_DBG_REQ (1<<5) #define MEM_CTRL_VLLSX_DBG_ACK (1<<6) #define MEM_CTRL_VLLSX_STAT_ACK (1<<7) #define MDM_ACCESS_TIMEOUT 3000 /* iterations */ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); retval = dap_queue_ap_write(dap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); return retval; } retval = dap_run(dap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; } return ERROR_OK; } static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { int retval; retval = dap_queue_ap_read(dap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); return retval; } retval = dap_run(dap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; } LOG_DEBUG("MDM_REG[0x%02x]: %08" PRIX32, reg, *result); return ERROR_OK; } static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value) { uint32_t val; int retval; int timeout = MDM_ACCESS_TIMEOUT; do { retval = kinetis_mdm_read_register(dap, reg, &val); if (retval != ERROR_OK || (val & mask) == value) return retval; alive_sleep(1); } while (timeout--); LOG_DEBUG("MDM: polling timed out"); return ERROR_FAIL; } /* * This function implements the procedure to mass erase the flash via * SWD/JTAG on Kinetis K and L series of devices as it is described in * AN4835 "Production Flash Programming Best Practices for Kinetis K- * and L-series MCUs" Section 4.2.1 */ COMMAND_HANDLER(kinetis_mdm_mass_erase) { struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; if (!dap) { LOG_ERROR("Cannot perform mass erase with a high-level adapter"); return ERROR_FAIL; } int retval; const uint8_t original_ap = dap->ap_current; /* * ... Power on the processor, or if power has already been * applied, assert the RESET pin to reset the processor. For * devices that do not have a RESET pin, write the System * Reset Request bit in the MDM-AP control register after * establishing communication... */ /* assert SRST */ if (jtag_get_reset_config() & RESET_HAS_SRST) adapter_assert_reset(); else LOG_WARNING("Attempting mass erase without hardware reset. This is not reliable; " "it's recommended you connect SRST and use ``reset_config srst_only''."); dap_ap_select(dap, 1); retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ); if (retval != ERROR_OK) return retval; /* * ... Read the MDM-AP status register until the Flash Ready bit sets... */ retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, MDM_STAT_FREADY | MDM_STAT_SYSRES, MDM_STAT_FREADY); if (retval != ERROR_OK) { LOG_ERROR("MDM : flash ready timeout"); return retval; } /* * ... Write the MDM-AP control register to set the Flash Mass * Erase in Progress bit. This will start the mass erase * process... */ retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ | MEM_CTRL_FMEIP); if (retval != ERROR_OK) return retval; /* As a sanity check make sure that device started mass erase procedure */ retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, MDM_STAT_FMEACK, MDM_STAT_FMEACK); if (retval != ERROR_OK) return retval; /* * ... Read the MDM-AP control register until the Flash Mass * Erase in Progress bit clears... */ retval = kinetis_mdm_poll_register(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP, 0); if (retval != ERROR_OK) return retval; /* * ... Negate the RESET signal or clear the System Reset Request * bit in the MDM-AP control register... */ retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0); if (retval != ERROR_OK) return retval; if (jtag_get_reset_config() & RESET_HAS_SRST) adapter_deassert_reset(); dap_ap_select(dap, original_ap); return ERROR_OK; } static const uint32_t kinetis_known_mdm_ids[] = { 0x001C0000, /* Kinetis-K Series */ 0x001C0020, /* Kinetis-L/M/V/E Series */ }; /* * This function implements the procedure to connect to * SWD/JTAG on Kinetis K and L series of devices as it is described in * AN4835 "Production Flash Programming Best Practices for Kinetis K- * and L-series MCUs" Section 4.1.1 */ COMMAND_HANDLER(kinetis_check_flash_security_status) { struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; if (!dap) { LOG_WARNING("Cannot check flash security status with a high-level adapter"); return ERROR_OK; } uint32_t val; int retval; const uint8_t origninal_ap = dap->ap_current; dap_ap_select(dap, 1); /* * ... The MDM-AP ID register can be read to verify that the * connection is working correctly... */ retval = kinetis_mdm_read_register(dap, MDM_REG_ID, &val); if (retval != ERROR_OK) { LOG_ERROR("MDM: failed to read ID register"); goto fail; } bool found = false; for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) { if (val == kinetis_known_mdm_ids[i]) { found = true; break; } } if (!found) LOG_WARNING("MDM: unknown ID %08" PRIX32, val); /* * ... Read the MDM-AP status register until the Flash Ready bit sets... */ retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, MDM_STAT_FREADY, MDM_STAT_FREADY); if (retval != ERROR_OK) { LOG_ERROR("MDM: flash ready timeout"); goto fail; } /* * ... Read the System Security bit to determine if security is enabled. * If System Security = 0, then proceed. If System Security = 1, then * communication with the internals of the processor, including the * flash, will not be possible without issuing a mass erase command or * unsecuring the part through other means (backdoor key unlock)... */ retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val); if (retval != ERROR_OK) { LOG_ERROR("MDM: failed to read MDM_REG_STAT"); goto fail; } if (val & MDM_STAT_SYSSEC) { jtag_poll_set_enabled(false); LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********"); LOG_WARNING("**** ****"); LOG_WARNING("**** Your Kinetis MCU is in secured state, which means that, ****"); LOG_WARNING("**** with exception for very basic communication, JTAG/SWD ****"); LOG_WARNING("**** interface will NOT work. In order to restore its ****"); LOG_WARNING("**** functionality please issue 'kinetis mdm mass_erase' ****"); LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****"); LOG_WARNING("**** ****"); LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********"); } else { LOG_INFO("MDM: Chip is unsecured. Continuing."); jtag_poll_set_enabled(true); } dap_ap_select(dap, origninal_ap); return ERROR_OK; fail: LOG_ERROR("MDM: Failed to check security status of the MCU. Cannot proceed further"); jtag_poll_set_enabled(false); return retval; } FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) { struct kinetis_flash_bank *bank_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; LOG_INFO("add flash_bank kinetis %s", bank->name); bank_info = malloc(sizeof(struct kinetis_flash_bank)); memset(bank_info, 0, sizeof(struct kinetis_flash_bank)); bank->driver_priv = bank_info; return ERROR_OK; } /* Kinetis Program-LongWord Microcodes */ static const uint8_t kinetis_flash_write_code[] = { /* Params: * r0 - workarea buffer * r1 - target address * r2 - wordcount * Clobbered: * r4 - tmp * r5 - tmp * r6 - tmp * r7 - tmp */ /* .L1: */ /* for(register uint32_t i=0;itarget; uint32_t buffer_size = 2048; /* Default minimum value */ struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* Params: * r0 - workarea buffer * r1 - target address * r2 - wordcount * Clobbered: * r4 - tmp * r5 - tmp * r6 - tmp * r7 - tmp */ /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size/2)) buffer_size = (target->working_area_size/2); LOG_INFO("Kinetis: FLASH Write ..."); /* check code alignment */ if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* allocate working area with flash programming code */ if (target_alloc_working_area(target, sizeof(kinetis_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = target_write_buffer(target, write_algorithm->address, sizeof(kinetis_flash_write_code), kinetis_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 4; if (buffer_size <= 256) { /* free working area, write algorithm already allocated */ target_free_working_area(target, write_algorithm); LOG_WARNING("No large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ /* write code buffer and use Flash programming code within kinetis */ /* Set breakpoint to 0 with time-out of 1000 ms */ while (wcount > 0) { uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, 0, 100000, &armv7m_info); if (retval != ERROR_OK) { LOG_ERROR("Error executing kinetis Flash programming algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count * 4; address += thisrun_count * 4; wcount -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); return retval; } static int kinetis_protect(struct flash_bank *bank, int set, int first, int last) { LOG_WARNING("kinetis_protect not supported yet"); /* FIXME: TODO */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return ERROR_FLASH_BANK_INVALID; } static int kinetis_protect_check(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (kinfo->flash_class == FC_PFLASH) { int result; uint8_t buffer[4]; uint32_t fprot, psec; int i, b; /* read protection register */ result = target_read_memory(bank->target, FTFx_FPROT3, 1, 4, buffer); if (result != ERROR_OK) return result; fprot = target_buffer_get_u32(bank->target, buffer); /* * Every bit protects 1/32 of the full flash (not necessarily * just this bank), but we enforce the bank ordinals for * PFlash to start at zero. */ b = kinfo->bank_ordinal * (bank->size / kinfo->protection_size); for (psec = 0, i = 0; i < bank->num_sectors; i++) { if ((fprot >> b) & 1) bank->sectors[i].is_protected = 0; else bank->sectors[i].is_protected = 1; psec += bank->sectors[i].size; if (psec >= kinfo->protection_size) { psec = 0; b++; } } } else { LOG_ERROR("Protection checks for FlexNVM not yet supported"); return ERROR_FLASH_BANK_INVALID; } return ERROR_OK; } static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t faddr, uint8_t fccob4, uint8_t fccob5, uint8_t fccob6, uint8_t fccob7, uint8_t fccob8, uint8_t fccob9, uint8_t fccoba, uint8_t fccobb, uint8_t *ftfx_fstat) { uint8_t command[12] = {faddr & 0xff, (faddr >> 8) & 0xff, (faddr >> 16) & 0xff, fcmd, fccob7, fccob6, fccob5, fccob4, fccobb, fccoba, fccob9, fccob8}; int result, i; uint8_t buffer; /* wait for done */ for (i = 0; i < 50; i++) { result = target_read_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); if (result != ERROR_OK) return result; if (buffer & 0x80) break; buffer = 0x00; } if (buffer != 0x80) { /* reset error flags */ buffer = 0x30; result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); if (result != ERROR_OK) return result; } result = target_write_memory(bank->target, FTFx_FCCOB3, 4, 3, command); if (result != ERROR_OK) return result; /* start command */ buffer = 0x80; result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); if (result != ERROR_OK) return result; /* wait for done */ for (i = 0; i < 240; i++) { /* Need longtime for "Mass Erase" Command Nemui Changed */ result = target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat); if (result != ERROR_OK) return result; if (*ftfx_fstat & 0x80) break; } if ((*ftfx_fstat & 0xf0) != 0x80) { LOG_ERROR ("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X", *ftfx_fstat, command[3], command[2], command[1], command[0], command[7], command[6], command[5], command[4], command[11], command[10], command[9], command[8]); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } COMMAND_HANDLER(kinetis_securing_test) { int result; uint8_t ftfx_fstat; struct target *target = get_current_target(CMD_CTX); struct flash_bank *bank = NULL; result = get_flash_bank_by_addr(target, 0x00000000, true, &bank); if (result != ERROR_OK) return result; assert(bank != NULL); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + 0x00000400, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); } static int kinetis_erase(struct flash_bank *bank, int first, int last) { int result, i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first > bank->num_sectors) || (last > bank->num_sectors)) return ERROR_FLASH_OPERATION_FAILED; /* * FIXME: TODO: use the 'Erase Flash Block' command if the * requested erase is PFlash or NVM and encompasses the entire * block. Should be quicker. */ for (i = first; i <= last; i++) { uint8_t ftfx_fstat; /* set command and sector address */ result = kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + bank->sectors[i].offset, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) { LOG_WARNING("erase sector %d failed", i); return ERROR_FLASH_OPERATION_FAILED; } bank->sectors[i].is_erased = 1; } if (first == 0) { LOG_WARNING ("flash configuration field erased, please reset the device"); } return ERROR_OK; } static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { unsigned int i, result, fallback = 0; uint8_t buf[8]; uint32_t wc; struct kinetis_flash_bank *kinfo = bank->driver_priv; uint8_t *new_buffer = NULL; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (kinfo->klxx) { /* fallback to longword write */ fallback = 1; LOG_WARNING("Kinetis L Series supports Program Longword execution only."); LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset); } else if (kinfo->flash_class == FC_FLEX_NVM) { uint8_t ftfx_fstat; LOG_DEBUG("flash write into FlexNVM @%08" PRIX32, offset); /* make flex ram available */ result = kinetis_ftfx_command(bank, FTFx_CMD_SETFLEXRAM, 0x00ff0000, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; /* check if ram ready */ result = target_read_memory(bank->target, FTFx_FCNFG, 1, 1, buf); if (result != ERROR_OK) return result; if (!(buf[0] & (1 << 1))) { /* fallback to longword write */ fallback = 1; LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", buf[0]); } } else { LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset); } /* program section command */ if (fallback == 0) { /* * Kinetis uses different terms for the granularity of * sector writes, e.g. "phrase" or "128 bits". We use * the generic term "chunk". The largest possible * Kinetis "chunk" is 16 bytes (128 bits). */ unsigned prog_section_chunk_bytes = kinfo->sector_size >> 8; /* assume the NVM sector size is half the FlexRAM size */ unsigned prog_size_bytes = MIN(kinfo->sector_size, kinetis_flash_params[kinfo->granularity].nvm_sector_size_bytes); for (i = 0; i < count; i += prog_size_bytes) { uint8_t residual_buffer[16]; uint8_t ftfx_fstat; uint32_t section_count = prog_size_bytes / prog_section_chunk_bytes; uint32_t residual_wc = 0; /* * Assume the word count covers an entire * sector. */ wc = prog_size_bytes / 4; /* * If bytes to be programmed are less than the * full sector, then determine the number of * full-words to program, and put together the * residual buffer so that a full "section" * may always be programmed. */ if ((count - i) < prog_size_bytes) { /* number of bytes to program beyond full section */ unsigned residual_bc = (count-i) % prog_section_chunk_bytes; /* number of complete words to copy directly from buffer */ wc = (count - i) / 4; /* number of total sections to write, including residual */ section_count = DIV_ROUND_UP((count-i), prog_section_chunk_bytes); /* any residual bytes delivers a whole residual section */ residual_wc = (residual_bc ? prog_section_chunk_bytes : 0)/4; /* clear residual buffer then populate residual bytes */ (void) memset(residual_buffer, 0xff, prog_section_chunk_bytes); (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc); } LOG_DEBUG("write section @ %08" PRIX32 " with length %" PRIu32 " bytes", offset + i, (uint32_t)wc*4); /* write data to flexram as whole-words */ result = target_write_memory(bank->target, FLEXRAM, 4, wc, buffer + i); if (result != ERROR_OK) { LOG_ERROR("target_write_memory failed"); return result; } /* write the residual words to the flexram */ if (residual_wc) { result = target_write_memory(bank->target, FLEXRAM+4*wc, 4, residual_wc, residual_buffer); if (result != ERROR_OK) { LOG_ERROR("target_write_memory failed"); return result; } } /* execute section-write command */ result = kinetis_ftfx_command(bank, FTFx_CMD_SECTWRITE, bank->base + offset + i, section_count>>8, section_count, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; } } /* program longword command, not supported in "SF3" devices */ else if ((kinfo->granularity != 3) || (kinfo->klxx)) { if (count & 0x3) { uint32_t old_count = count; count = (old_count | 3) + 1; new_buffer = malloc(count); if (new_buffer == NULL) { LOG_ERROR("odd number of bytes to write and no memory " "for padding buffer"); return ERROR_FAIL; } LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " " "and padding with 0xff", old_count, count); memset(new_buffer, 0xff, count); buffer = memcpy(new_buffer, buffer, old_count); } uint32_t words_remaining = count / 4; /* try using a block write */ int retval = kinetis_write_block(bank, buffer, offset, words_remaining); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single word accesses */ LOG_WARNING("couldn't use block writes, falling back to single " "memory accesses"); for (i = 0; i < count; i += 4) { uint8_t ftfx_fstat; LOG_DEBUG("write longword @ %08" PRIX32, (uint32_t)(offset + i)); uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff}; memcpy(padding, buffer + i, MIN(4, count-i)); result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, bank->base + offset + i, padding[3], padding[2], padding[1], padding[0], 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; } } } else { LOG_ERROR("Flash write strategy not implemented"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int kinetis_read_part_info(struct flash_bank *bank) { int result, i; uint32_t offset = 0; uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg2_pflsh; uint32_t nvm_size = 0, pf_size = 0, ee_size = 0; unsigned granularity, num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0, reassign = 0; struct target *target = bank->target; struct kinetis_flash_bank *kinfo = bank->driver_priv; result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid); if (result != ERROR_OK) return result; kinfo->klxx = 0; /* K-series MCU? */ if ((kinfo->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) { uint32_t mcu_type = kinfo->sim_sdid & KINETIS_K_SDID_TYPE_MASK; switch (mcu_type) { case KINETIS_K_SDID_K10_M50: case KINETIS_K_SDID_K20_M50: /* 1kB sectors */ granularity = 0; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: case KINETIS_K_SDID_K30_M72: case KINETIS_K_SDID_K30_M100: case KINETIS_K_SDID_K40_M72: case KINETIS_K_SDID_K40_M100: case KINETIS_K_SDID_K50_M72: /* 2kB sectors, 1kB FlexNVM sectors */ granularity = 1; break; case KINETIS_K_SDID_K10_M100: case KINETIS_K_SDID_K20_M100: case KINETIS_K_SDID_K11: case KINETIS_K_SDID_K12: case KINETIS_K_SDID_K21_M50: case KINETIS_K_SDID_K22_M50: case KINETIS_K_SDID_K51_M72: case KINETIS_K_SDID_K53: case KINETIS_K_SDID_K60_M100: /* 2kB sectors */ granularity = 2; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: case KINETIS_K_SDID_K60_M150: case KINETIS_K_SDID_K70_M150: /* 4kB sectors */ granularity = 3; break; default: LOG_ERROR("Unsupported K-family FAMID"); return ERROR_FLASH_OPER_UNSUPPORTED; } } /* KL-series? */ else if ((kinfo->sim_sdid & KINETIS_KL_SDID_SERIESID_MASK) == KINETIS_KL_SDID_SERIESID_KL) { kinfo->klxx = 1; granularity = 0; } else { LOG_ERROR("MCU is unsupported"); return ERROR_FLASH_OPER_UNSUPPORTED; } result = target_read_u32(target, SIM_FCFG1, &kinfo->sim_fcfg1); if (result != ERROR_OK) return result; result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2); if (result != ERROR_OK) return result; fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01; LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid, kinfo->sim_fcfg1, kinfo->sim_fcfg2); fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f); fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f); fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f); /* when the PFLSH bit is set, there is no FlexNVM/FlexRAM */ if (!fcfg2_pflsh) { switch (fcfg1_nvmsize) { case 0x03: case 0x07: case 0x09: case 0x0b: nvm_size = 1 << (14 + (fcfg1_nvmsize >> 1)); break; case 0x0f: if (granularity == 3) nvm_size = 512<<10; else nvm_size = 256<<10; break; default: nvm_size = 0; break; } switch (fcfg1_eesize) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: ee_size = (16 << (10 - fcfg1_eesize)); break; default: ee_size = 0; break; } } switch (fcfg1_pfsize) { case 0x03: case 0x05: case 0x07: case 0x09: case 0x0b: case 0x0d: pf_size = 1 << (14 + (fcfg1_pfsize >> 1)); break; case 0x0f: if (granularity == 3) pf_size = 1024<<10; else if (fcfg2_pflsh) pf_size = 512<<10; else pf_size = 256<<10; break; default: pf_size = 0; break; } LOG_DEBUG("FlexNVM: %" PRIu32 " PFlash: %" PRIu32 " FlexRAM: %" PRIu32 " PFLSH: %d", nvm_size, pf_size, ee_size, fcfg2_pflsh); if (kinfo->klxx) num_blocks = 1; else num_blocks = kinetis_flash_params[granularity].num_blocks; num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh); first_nvm_bank = num_pflash_blocks; num_nvm_blocks = num_blocks - num_pflash_blocks; LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM", num_blocks, num_pflash_blocks, num_nvm_blocks); /* * If the flash class is already assigned, verify the * parameters. */ if (kinfo->flash_class != FC_AUTO) { if (kinfo->bank_ordinal != (unsigned) bank->bank_number) { LOG_WARNING("Flash ordinal/bank number mismatch"); reassign = 1; } else if (kinfo->granularity != granularity) { LOG_WARNING("Flash granularity mismatch"); reassign = 1; } else { switch (kinfo->flash_class) { case FC_PFLASH: if (kinfo->bank_ordinal >= first_nvm_bank) { LOG_WARNING("Class mismatch, bank %d is not PFlash", bank->bank_number); reassign = 1; } else if (bank->size != (pf_size / num_pflash_blocks)) { LOG_WARNING("PFlash size mismatch"); reassign = 1; } else if (bank->base != (0x00000000 + bank->size * kinfo->bank_ordinal)) { LOG_WARNING("PFlash address range mismatch"); reassign = 1; } else if (kinfo->sector_size != kinetis_flash_params[granularity].pflash_sector_size_bytes) { LOG_WARNING("PFlash sector size mismatch"); reassign = 1; } else { LOG_DEBUG("PFlash bank %d already configured okay", kinfo->bank_ordinal); } break; case FC_FLEX_NVM: if ((kinfo->bank_ordinal >= num_blocks) || (kinfo->bank_ordinal < first_nvm_bank)) { LOG_WARNING("Class mismatch, bank %d is not FlexNVM", bank->bank_number); reassign = 1; } else if (bank->size != (nvm_size / num_nvm_blocks)) { LOG_WARNING("FlexNVM size mismatch"); reassign = 1; } else if (bank->base != (0x10000000 + bank->size * kinfo->bank_ordinal)) { LOG_WARNING("FlexNVM address range mismatch"); reassign = 1; } else if (kinfo->sector_size != kinetis_flash_params[granularity].nvm_sector_size_bytes) { LOG_WARNING("FlexNVM sector size mismatch"); reassign = 1; } else { LOG_DEBUG("FlexNVM bank %d already configured okay", kinfo->bank_ordinal); } break; case FC_FLEX_RAM: if (kinfo->bank_ordinal != num_blocks) { LOG_WARNING("Class mismatch, bank %d is not FlexRAM", bank->bank_number); reassign = 1; } else if (bank->size != ee_size) { LOG_WARNING("FlexRAM size mismatch"); reassign = 1; } else if (bank->base != FLEXRAM) { LOG_WARNING("FlexRAM address mismatch"); reassign = 1; } else if (kinfo->sector_size != kinetis_flash_params[granularity].nvm_sector_size_bytes) { LOG_WARNING("FlexRAM sector size mismatch"); reassign = 1; } else { LOG_DEBUG("FlexRAM bank %d already configured okay", kinfo->bank_ordinal); } break; default: LOG_WARNING("Unknown or inconsistent flash class"); reassign = 1; break; } } } else { LOG_INFO("Probing flash info for bank %d", bank->bank_number); reassign = 1; } if (!reassign) return ERROR_OK; kinfo->granularity = granularity; if ((unsigned)bank->bank_number < num_pflash_blocks) { /* pflash, banks start at address zero */ kinfo->flash_class = FC_PFLASH; bank->size = (pf_size / num_pflash_blocks); bank->base = 0x00000000 + bank->size * bank->bank_number; kinfo->sector_size = kinetis_flash_params[granularity].pflash_sector_size_bytes; kinfo->protection_size = pf_size / 32; } else if ((unsigned)bank->bank_number < num_blocks) { /* nvm, banks start at address 0x10000000 */ kinfo->flash_class = FC_FLEX_NVM; bank->size = (nvm_size / num_nvm_blocks); bank->base = 0x10000000 + bank->size * (bank->bank_number - first_nvm_bank); kinfo->sector_size = kinetis_flash_params[granularity].nvm_sector_size_bytes; kinfo->protection_size = 0; /* FIXME: TODO: depends on DEPART bits, chip */ } else if ((unsigned)bank->bank_number == num_blocks) { LOG_ERROR("FlexRAM support not yet implemented"); return ERROR_FLASH_OPER_UNSUPPORTED; } else { LOG_ERROR("Cannot determine parameters for bank %d, only %d banks on device", bank->bank_number, num_blocks); return ERROR_FLASH_BANK_INVALID; } if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->num_sectors = bank->size / kinfo->sector_size; assert(bank->num_sectors > 0); bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = kinfo->sector_size; offset += kinfo->sector_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } return ERROR_OK; } static int kinetis_probe(struct flash_bank *bank) { if (bank->target->state != TARGET_HALTED) { LOG_WARNING("Cannot communicate... target not halted."); return ERROR_TARGET_NOT_HALTED; } return kinetis_read_part_info(bank); } static int kinetis_auto_probe(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; if (kinfo->sim_sdid) return ERROR_OK; return kinetis_probe(bank); } static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size) { const char *bank_class_names[] = { "(ANY)", "PFlash", "FlexNVM", "FlexRAM" }; struct kinetis_flash_bank *kinfo = bank->driver_priv; (void) snprintf(buf, buf_size, "%s driver for %s flash bank %s at 0x%8.8" PRIx32 "", bank->driver->name, bank_class_names[kinfo->flash_class], bank->name, bank->base); return ERROR_OK; } static int kinetis_blank_check(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (kinfo->flash_class == FC_PFLASH) { int result; uint8_t ftfx_fstat; /* check if whole bank is blank */ result = kinetis_ftfx_command(bank, FTFx_CMD_BLOCKSTAT, bank->base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) return result; if (ftfx_fstat & 0x01) { /* the whole bank is not erased, check sector-by-sector */ int i; for (i = 0; i < bank->num_sectors; i++) { /* normal margin */ result = kinetis_ftfx_command(bank, FTFx_CMD_SECTSTAT, bank->base + bank->sectors[i].offset, 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result == ERROR_OK) { bank->sectors[i].is_erased = !(ftfx_fstat & 0x01); } else { LOG_DEBUG("Ignoring errored PFlash sector blank-check"); bank->sectors[i].is_erased = -1; } } } else { /* the whole bank is erased, update all sectors */ int i; for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; } } else { LOG_WARNING("kinetis_blank_check not supported yet for FlexNVM"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static const struct command_registration kinetis_securtiy_command_handlers[] = { { .name = "check_security", .mode = COMMAND_EXEC, .help = "", .usage = "", .handler = kinetis_check_flash_security_status, }, { .name = "mass_erase", .mode = COMMAND_EXEC, .help = "", .usage = "", .handler = kinetis_mdm_mass_erase, }, { .name = "test_securing", .mode = COMMAND_EXEC, .help = "", .usage = "", .handler = kinetis_securing_test, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration kinetis_exec_command_handlers[] = { { .name = "mdm", .mode = COMMAND_ANY, .help = "", .usage = "", .chain = kinetis_securtiy_command_handlers, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration kinetis_command_handler[] = { { .name = "kinetis", .mode = COMMAND_ANY, .help = "kinetis NAND flash controller commands", .usage = "", .chain = kinetis_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver kinetis_flash = { .name = "kinetis", .commands = kinetis_command_handler, .flash_bank_command = kinetis_flash_bank_command, .erase = kinetis_erase, .protect = kinetis_protect, .write = kinetis_write, .read = default_flash_read, .probe = kinetis_probe, .auto_probe = kinetis_auto_probe, .erase_check = kinetis_blank_check, .protect_check = kinetis_protect_check, .info = kinetis_info, }; openocd-0.9.0/src/flash/nor/efm32.c0000644000175000017500000007155712516456302013655 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * Copyright (C) 2013 by Roman Dmitrienko * * me@iamroman.org * * * * Copyright (C) 2014 Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /* keep family IDs in decimal */ #define EFM_FAMILY_ID_GECKO 71 #define EFM_FAMILY_ID_GIANT_GECKO 72 #define EFM_FAMILY_ID_TINY_GECKO 73 #define EFM_FAMILY_ID_LEOPARD_GECKO 74 #define EFM_FAMILY_ID_WONDER_GECKO 75 #define EFM_FAMILY_ID_ZERO_GECKO 76 #define EZR_FAMILY_ID_WONDER_GECKO 120 #define EZR_FAMILY_ID_LEOPARD_GECKO 121 #define EFM32_FLASH_ERASE_TMO 100 #define EFM32_FLASH_WDATAREADY_TMO 100 #define EFM32_FLASH_WRITE_TMO 100 /* size in bytes, not words; must fit all Gecko devices */ #define LOCKBITS_PAGE_SZ 512 #define EFM32_MSC_INFO_BASE 0x0fe00000 #define EFM32_MSC_USER_DATA EFM32_MSC_INFO_BASE #define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE+0x4000) #define EFM32_MSC_DEV_INFO (EFM32_MSC_INFO_BASE+0x8000) /* PAGE_SIZE is only present in Leopard, Giant and Wonder Gecko MCUs */ #define EFM32_MSC_DI_PAGE_SIZE (EFM32_MSC_DEV_INFO+0x1e7) #define EFM32_MSC_DI_FLASH_SZ (EFM32_MSC_DEV_INFO+0x1f8) #define EFM32_MSC_DI_RAM_SZ (EFM32_MSC_DEV_INFO+0x1fa) #define EFM32_MSC_DI_PART_NUM (EFM32_MSC_DEV_INFO+0x1fc) #define EFM32_MSC_DI_PART_FAMILY (EFM32_MSC_DEV_INFO+0x1fe) #define EFM32_MSC_DI_PROD_REV (EFM32_MSC_DEV_INFO+0x1ff) #define EFM32_MSC_REGBASE 0x400c0000 #define EFM32_MSC_WRITECTRL (EFM32_MSC_REGBASE+0x008) #define EFM32_MSC_WRITECTRL_WREN_MASK 0x1 #define EFM32_MSC_WRITECMD (EFM32_MSC_REGBASE+0x00c) #define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x1 #define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x2 #define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x8 #define EFM32_MSC_ADDRB (EFM32_MSC_REGBASE+0x010) #define EFM32_MSC_WDATA (EFM32_MSC_REGBASE+0x018) #define EFM32_MSC_STATUS (EFM32_MSC_REGBASE+0x01c) #define EFM32_MSC_STATUS_BUSY_MASK 0x1 #define EFM32_MSC_STATUS_LOCKED_MASK 0x2 #define EFM32_MSC_STATUS_INVADDR_MASK 0x4 #define EFM32_MSC_STATUS_WDATAREADY_MASK 0x8 #define EFM32_MSC_STATUS_WORDTIMEOUT_MASK 0x10 #define EFM32_MSC_STATUS_ERASEABORTED_MASK 0x20 #define EFM32_MSC_LOCK (EFM32_MSC_REGBASE+0x03c) #define EFM32_MSC_LOCK_LOCKKEY 0x1b71 struct efm32x_flash_bank { int probed; uint32_t lb_page[LOCKBITS_PAGE_SZ/4]; }; struct efm32_info { uint16_t flash_sz_kib; uint16_t ram_sz_kib; uint16_t part_num; uint8_t part_family; uint8_t prod_rev; uint16_t page_size; }; static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); static int efm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_sz) { return target_read_u16(bank->target, EFM32_MSC_DI_FLASH_SZ, flash_sz); } static int efm32x_get_ram_size(struct flash_bank *bank, uint16_t *ram_sz) { return target_read_u16(bank->target, EFM32_MSC_DI_RAM_SZ, ram_sz); } static int efm32x_get_part_num(struct flash_bank *bank, uint16_t *pnum) { return target_read_u16(bank->target, EFM32_MSC_DI_PART_NUM, pnum); } static int efm32x_get_part_family(struct flash_bank *bank, uint8_t *pfamily) { return target_read_u8(bank->target, EFM32_MSC_DI_PART_FAMILY, pfamily); } static int efm32x_get_prod_rev(struct flash_bank *bank, uint8_t *prev) { return target_read_u8(bank->target, EFM32_MSC_DI_PROD_REV, prev); } static int efm32x_read_info(struct flash_bank *bank, struct efm32_info *efm32_info) { int ret; uint32_t cpuid = 0; memset(efm32_info, 0, sizeof(struct efm32_info)); ret = target_read_u32(bank->target, CPUID, &cpuid); if (ERROR_OK != ret) return ret; if (((cpuid >> 4) & 0xfff) == 0xc23) { /* Cortex M3 device */ } else if (((cpuid >> 4) & 0xfff) == 0xc24) { /* Cortex M4 device(WONDER GECKO) */ } else if (((cpuid >> 4) & 0xfff) == 0xc60) { /* Cortex M0plus device(ZERO GECKO) */ } else { LOG_ERROR("Target is not Cortex-Mx Device"); return ERROR_FAIL; } ret = efm32x_get_flash_size(bank, &(efm32_info->flash_sz_kib)); if (ERROR_OK != ret) return ret; ret = efm32x_get_ram_size(bank, &(efm32_info->ram_sz_kib)); if (ERROR_OK != ret) return ret; ret = efm32x_get_part_num(bank, &(efm32_info->part_num)); if (ERROR_OK != ret) return ret; ret = efm32x_get_part_family(bank, &(efm32_info->part_family)); if (ERROR_OK != ret) return ret; ret = efm32x_get_prod_rev(bank, &(efm32_info->prod_rev)); if (ERROR_OK != ret) return ret; if (EFM_FAMILY_ID_GECKO == efm32_info->part_family || EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family) efm32_info->page_size = 512; else if (EFM_FAMILY_ID_ZERO_GECKO == efm32_info->part_family) efm32_info->page_size = 1024; else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family || EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) { if (efm32_info->prod_rev >= 18) { uint8_t pg_size = 0; ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE, &pg_size); if (ERROR_OK != ret) return ret; efm32_info->page_size = (1 << ((pg_size+10) & 0xff)); } else { /* EFM32 GG/LG errata: MEM_INFO_PAGE_SIZE is invalid for MCUs with PROD_REV < 18 */ if (efm32_info->flash_sz_kib < 512) efm32_info->page_size = 2048; else efm32_info->page_size = 4096; } if ((2048 != efm32_info->page_size) && (4096 != efm32_info->page_size)) { LOG_ERROR("Invalid page size %u", efm32_info->page_size); return ERROR_FAIL; } } else if (EFM_FAMILY_ID_WONDER_GECKO == efm32_info->part_family || EZR_FAMILY_ID_WONDER_GECKO == efm32_info->part_family || EZR_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) { uint8_t pg_size = 0; ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE, &pg_size); if (ERROR_OK != ret) return ret; efm32_info->page_size = (1 << ((pg_size+10) & 0xff)); if (2048 != efm32_info->page_size) { LOG_ERROR("Invalid page size %u", efm32_info->page_size); return ERROR_FAIL; } } else { LOG_ERROR("Unknown MCU family %d", efm32_info->part_family); return ERROR_FAIL; } return ERROR_OK; } /* flash bank efm32 0 0 */ FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command) { struct efm32x_flash_bank *efm32x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; efm32x_info = malloc(sizeof(struct efm32x_flash_bank)); bank->driver_priv = efm32x_info; efm32x_info->probed = 0; memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ); return ERROR_OK; } /* set or reset given bits in a register */ static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg, uint32_t bitmask, int set) { int ret = 0; uint32_t reg_val = 0; ret = target_read_u32(bank->target, reg, ®_val); if (ERROR_OK != ret) return ret; if (set) reg_val |= bitmask; else reg_val &= ~bitmask; return target_write_u32(bank->target, reg, reg_val); } static int efm32x_set_wren(struct flash_bank *bank, int write_enable) { return efm32x_set_reg_bits(bank, EFM32_MSC_WRITECTRL, EFM32_MSC_WRITECTRL_WREN_MASK, write_enable); } static int efm32x_msc_lock(struct flash_bank *bank, int lock) { return target_write_u32(bank->target, EFM32_MSC_LOCK, (lock ? 0 : EFM32_MSC_LOCK_LOCKKEY)); } static int efm32x_wait_status(struct flash_bank *bank, int timeout, uint32_t wait_mask, int wait_for_set) { int ret = 0; uint32_t status = 0; while (1) { ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status); if (ERROR_OK != ret) break; LOG_DEBUG("status: 0x%" PRIx32 "", status); if (((status & wait_mask) == 0) && (0 == wait_for_set)) break; else if (((status & wait_mask) != 0) && wait_for_set) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for MSC status"); return ERROR_FAIL; } alive_sleep(1); } if (status & EFM32_MSC_STATUS_ERASEABORTED_MASK) LOG_WARNING("page erase was aborted"); return ret; } static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr) { /* this function DOES NOT set WREN; must be set already */ /* 1. write address to ADDRB 2. write LADDRIM 3. check status (INVADDR, LOCKED) 4. write ERASEPAGE 5. wait until !STATUS_BUSY */ int ret = 0; uint32_t status = 0; LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr); ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr); if (ERROR_OK != ret) return ret; ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_LADDRIM_MASK, 1); if (ERROR_OK != ret) return ret; ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status); if (ERROR_OK != ret) return ret; LOG_DEBUG("status 0x%" PRIx32, status); if (status & EFM32_MSC_STATUS_LOCKED_MASK) { LOG_ERROR("Page is locked"); return ERROR_FAIL; } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) { LOG_ERROR("Invalid address 0x%" PRIx32, addr); return ERROR_FAIL; } ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_ERASEPAGE_MASK, 1); if (ERROR_OK != ret) return ret; return efm32x_wait_status(bank, EFM32_FLASH_ERASE_TMO, EFM32_MSC_STATUS_BUSY_MASK, 0); } static int efm32x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i = 0; int ret = 0; if (TARGET_HALTED != target->state) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } efm32x_msc_lock(bank, 0); ret = efm32x_set_wren(bank, 1); if (ERROR_OK != ret) { LOG_ERROR("Failed to enable MSC write"); return ret; } for (i = first; i <= last; i++) { ret = efm32x_erase_page(bank, bank->sectors[i].offset); if (ERROR_OK != ret) LOG_ERROR("Failed to erase page %d", i); } ret = efm32x_set_wren(bank, 0); efm32x_msc_lock(bank, 1); return ret; } static int efm32x_read_lock_data(struct flash_bank *bank) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; struct target *target = bank->target; int i = 0; int data_size = 0; uint32_t *ptr = NULL; int ret = 0; assert(!(bank->num_sectors & 0x1f)); data_size = bank->num_sectors / 8; /* number of data bytes */ data_size /= 4; /* ...and data dwords */ ptr = efm32x_info->lb_page; for (i = 0; i < data_size; i++, ptr++) { ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+i*4, ptr); if (ERROR_OK != ret) { LOG_ERROR("Failed to read PLW %d", i); return ret; } } /* also, read ULW, DLW and MLW */ /* ULW, word 126 */ ptr = efm32x_info->lb_page + 126; ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+126*4, ptr); if (ERROR_OK != ret) { LOG_ERROR("Failed to read ULW"); return ret; } /* DLW, word 127 */ ptr = efm32x_info->lb_page + 127; ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+127*4, ptr); if (ERROR_OK != ret) { LOG_ERROR("Failed to read DLW"); return ret; } /* MLW, word 125, present in GG and LG */ ptr = efm32x_info->lb_page + 125; ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+125*4, ptr); if (ERROR_OK != ret) { LOG_ERROR("Failed to read MLW"); return ret; } return ERROR_OK; } static int efm32x_write_lock_data(struct flash_bank *bank) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; int ret = 0; ret = efm32x_erase_page(bank, EFM32_MSC_LOCK_BITS); if (ERROR_OK != ret) { LOG_ERROR("Failed to erase LB page"); return ret; } return efm32x_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS, LOCKBITS_PAGE_SZ); } static int efm32x_get_page_lock(struct flash_bank *bank, size_t page) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; uint32_t dw = efm32x_info->lb_page[page >> 5]; uint32_t mask = 0; mask = 1 << (page & 0x1f); return (dw & mask) ? 0 : 1; } static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; uint32_t *dw = &efm32x_info->lb_page[page >> 5]; uint32_t mask = 0; mask = 1 << (page & 0x1f); if (!set) *dw |= mask; else *dw &= ~mask; return ERROR_OK; } static int efm32x_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; int i = 0; int ret = 0; if (!set) { LOG_ERROR("Erase device data to reset page locks"); return ERROR_FAIL; } if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = first; i <= last; i++) { ret = efm32x_set_page_lock(bank, i, set); if (ERROR_OK != ret) { LOG_ERROR("Failed to set lock on page %d", i); return ret; } } ret = efm32x_write_lock_data(bank); if (ERROR_OK != ret) { LOG_ERROR("Failed to write LB page"); return ret; } return ERROR_OK; } static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int ret = ERROR_OK; /* see contrib/loaders/flash/efm32.S for src */ static const uint8_t efm32x_flash_write_code[] = { /* #define EFM32_MSC_WRITECTRL_OFFSET 0x008 */ /* #define EFM32_MSC_WRITECMD_OFFSET 0x00c */ /* #define EFM32_MSC_ADDRB_OFFSET 0x010 */ /* #define EFM32_MSC_WDATA_OFFSET 0x018 */ /* #define EFM32_MSC_STATUS_OFFSET 0x01c */ /* #define EFM32_MSC_LOCK_OFFSET 0x03c */ 0x15, 0x4e, /* ldr r6, =#0x1b71 */ 0xc6, 0x63, /* str r6, [r0, #EFM32_MSC_LOCK_OFFSET] */ 0x01, 0x26, /* movs r6, #1 */ 0x86, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET] */ /* wait_fifo: */ 0x16, 0x68, /* ldr r6, [r2, #0] */ 0x00, 0x2e, /* cmp r6, #0 */ 0x22, 0xd0, /* beq exit */ 0x55, 0x68, /* ldr r5, [r2, #4] */ 0xb5, 0x42, /* cmp r5, r6 */ 0xf9, 0xd0, /* beq wait_fifo */ 0x04, 0x61, /* str r4, [r0, #EFM32_MSC_ADDRB_OFFSET] */ 0x01, 0x26, /* movs r6, #1 */ 0xc6, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] */ 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */ 0x06, 0x27, /* movs r7, #6 */ 0x3e, 0x42, /* tst r6, r7 */ 0x16, 0xd1, /* bne error */ /* wait_wdataready: */ 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */ 0x08, 0x27, /* movs r7, #8 */ 0x3e, 0x42, /* tst r6, r7 */ 0xfb, 0xd0, /* beq wait_wdataready */ 0x2e, 0x68, /* ldr r6, [r5] */ 0x86, 0x61, /* str r6, [r0, #EFM32_MSC_WDATA_OFFSET] */ 0x08, 0x26, /* movs r6, #8 */ 0xc6, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] */ 0x04, 0x35, /* adds r5, #4 */ 0x04, 0x34, /* adds r4, #4 */ /* busy: */ 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */ 0x01, 0x27, /* movs r7, #1 */ 0x3e, 0x42, /* tst r6, r7 */ 0xfb, 0xd1, /* bne busy */ 0x9d, 0x42, /* cmp r5, r3 */ 0x01, 0xd3, /* bcc no_wrap */ 0x15, 0x46, /* mov r5, r2 */ 0x08, 0x35, /* adds r5, #8 */ /* no_wrap: */ 0x55, 0x60, /* str r5, [r2, #4] */ 0x01, 0x39, /* subs r1, r1, #1 */ 0x00, 0x29, /* cmp r1, #0 */ 0x02, 0xd0, /* beq exit */ 0xdb, 0xe7, /* b wait_fifo */ /* error: */ 0x00, 0x20, /* movs r0, #0 */ 0x50, 0x60, /* str r0, [r2, #4] */ /* exit: */ 0x30, 0x46, /* mov r0, r6 */ 0x00, 0xbe, /* bkpt #0 */ /* LOCKKEY */ 0x71, 0x1b, 0x00, 0x00 }; /* flash write code */ if (target_alloc_working_area(target, sizeof(efm32x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; ret = target_write_buffer(target, write_algorithm->address, sizeof(efm32x_flash_write_code), efm32x_flash_write_code); if (ret != ERROR_OK) return ret; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } }; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (word-32bit) */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer start */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[4], "r4", 32, PARAM_IN_OUT); /* target address */ buf_set_u32(reg_params[0].value, 0, 32, EFM32_MSC_REGBASE); buf_set_u32(reg_params[1].value, 0, 32, count); buf_set_u32(reg_params[2].value, 0, 32, source->address); buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[4].value, 0, 32, address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; ret = target_run_flash_async_algorithm(target, buf, count, 4, 0, NULL, 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (ret == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash write failed at address 0x%"PRIx32, buf_get_u32(reg_params[4].value, 0, 32)); if (buf_get_u32(reg_params[0].value, 0, 32) & EFM32_MSC_STATUS_LOCKED_MASK) { LOG_ERROR("flash memory write protected"); } if (buf_get_u32(reg_params[0].value, 0, 32) & EFM32_MSC_STATUS_INVADDR_MASK) { LOG_ERROR("invalid flash memory write address"); } } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return ret; } static int efm32x_write_word(struct flash_bank *bank, uint32_t addr, uint32_t val) { /* this function DOES NOT set WREN; must be set already */ /* 1. write address to ADDRB 2. write LADDRIM 3. check status (INVADDR, LOCKED) 4. wait for WDATAREADY 5. write data to WDATA 6. write WRITECMD_WRITEONCE to WRITECMD 7. wait until !STATUS_BUSY */ /* FIXME: EFM32G ref states (7.3.2) that writes should be * performed twice per dword */ int ret = 0; uint32_t status = 0; /* if not called, GDB errors will be reported during large writes */ keep_alive(); ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr); if (ERROR_OK != ret) return ret; ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_LADDRIM_MASK, 1); if (ERROR_OK != ret) return ret; ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status); if (ERROR_OK != ret) return ret; LOG_DEBUG("status 0x%" PRIx32, status); if (status & EFM32_MSC_STATUS_LOCKED_MASK) { LOG_ERROR("Page is locked"); return ERROR_FAIL; } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) { LOG_ERROR("Invalid address 0x%" PRIx32, addr); return ERROR_FAIL; } ret = efm32x_wait_status(bank, EFM32_FLASH_WDATAREADY_TMO, EFM32_MSC_STATUS_WDATAREADY_MASK, 1); if (ERROR_OK != ret) { LOG_ERROR("Wait for WDATAREADY failed"); return ret; } ret = target_write_u32(bank->target, EFM32_MSC_WDATA, val); if (ERROR_OK != ret) { LOG_ERROR("WDATA write failed"); return ret; } ret = target_write_u32(bank->target, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_WRITEONCE_MASK); if (ERROR_OK != ret) { LOG_ERROR("WRITECMD write failed"); return ret; } ret = efm32x_wait_status(bank, EFM32_FLASH_WRITE_TMO, EFM32_MSC_STATUS_BUSY_MASK, 0); if (ERROR_OK != ret) { LOG_ERROR("Wait for BUSY failed"); return ret; } return ERROR_OK; } static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint8_t *new_buffer = NULL; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x3) { LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte " "alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } if (count & 0x3) { uint32_t old_count = count; count = (old_count | 3) + 1; new_buffer = malloc(count); if (new_buffer == NULL) { LOG_ERROR("odd number of bytes to write and no memory " "for padding buffer"); return ERROR_FAIL; } LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " " "and padding with 0xff", old_count, count); memset(new_buffer, 0xff, count); buffer = memcpy(new_buffer, buffer, old_count); } uint32_t words_remaining = count / 4; int retval, retval2; /* unlock flash registers */ efm32x_msc_lock(bank, 0); retval = efm32x_set_wren(bank, 1); if (retval != ERROR_OK) goto cleanup; /* try using a block write */ retval = efm32x_write_block(bank, buffer, offset, words_remaining); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single word accesses */ LOG_WARNING("couldn't use block writes, falling back to single " "memory accesses"); while (words_remaining > 0) { uint32_t value; memcpy(&value, buffer, sizeof(uint32_t)); retval = efm32x_write_word(bank, offset, value); if (retval != ERROR_OK) goto reset_pg_and_lock; words_remaining--; buffer += 4; offset += 4; } } reset_pg_and_lock: retval2 = efm32x_set_wren(bank, 0); efm32x_msc_lock(bank, 1); if (retval == ERROR_OK) retval = retval2; cleanup: if (new_buffer) free(new_buffer); return retval; } static int efm32x_probe(struct flash_bank *bank) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; struct efm32_info efm32_mcu_info; int ret; int i; uint32_t base_address = 0x00000000; efm32x_info->probed = 0; memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ); ret = efm32x_read_info(bank, &efm32_mcu_info); if (ERROR_OK != ret) return ret; switch (efm32_mcu_info.part_family) { case EFM_FAMILY_ID_GECKO: LOG_INFO("Gecko MCU detected"); break; case EFM_FAMILY_ID_GIANT_GECKO: LOG_INFO("Giant Gecko MCU detected"); break; case EFM_FAMILY_ID_TINY_GECKO: LOG_INFO("Tiny Gecko MCU detected"); break; case EFM_FAMILY_ID_LEOPARD_GECKO: case EZR_FAMILY_ID_LEOPARD_GECKO: LOG_INFO("Leopard Gecko MCU detected"); break; case EFM_FAMILY_ID_WONDER_GECKO: case EZR_FAMILY_ID_WONDER_GECKO: LOG_INFO("Wonder Gecko MCU detected"); break; case EFM_FAMILY_ID_ZERO_GECKO: LOG_INFO("Zero Gecko MCU detected"); break; default: LOG_ERROR("Unsupported MCU family %d", efm32_mcu_info.part_family); return ERROR_FAIL; } LOG_INFO("flash size = %dkbytes", efm32_mcu_info.flash_sz_kib); LOG_INFO("flash page size = %dbytes", efm32_mcu_info.page_size); assert(0 != efm32_mcu_info.page_size); int num_pages = efm32_mcu_info.flash_sz_kib * 1024 / efm32_mcu_info.page_size; assert(num_pages > 0); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->size = (num_pages * efm32_mcu_info.page_size); bank->num_sectors = num_pages; ret = efm32x_read_lock_data(bank); if (ERROR_OK != ret) { LOG_ERROR("Failed to read LB data"); return ret; } bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); for (i = 0; i < num_pages; i++) { bank->sectors[i].offset = i * efm32_mcu_info.page_size; bank->sectors[i].size = efm32_mcu_info.page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } efm32x_info->probed = 1; return ERROR_OK; } static int efm32x_auto_probe(struct flash_bank *bank) { struct efm32x_flash_bank *efm32x_info = bank->driver_priv; if (efm32x_info->probed) return ERROR_OK; return efm32x_probe(bank); } static int efm32x_protect_check(struct flash_bank *bank) { struct target *target = bank->target; int ret = 0; int i = 0; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } ret = efm32x_read_lock_data(bank); if (ERROR_OK != ret) { LOG_ERROR("Failed to read LB data"); return ret; } assert(NULL != bank->sectors); for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = efm32x_get_page_lock(bank, i); return ERROR_OK; } static int get_efm32x_info(struct flash_bank *bank, char *buf, int buf_size) { struct efm32_info info; int ret = 0; int printed = 0; ret = efm32x_read_info(bank, &info); if (ERROR_OK != ret) { LOG_ERROR("Failed to read EFM32 info"); return ret; } switch (info.part_family) { case EZR_FAMILY_ID_WONDER_GECKO: case EZR_FAMILY_ID_LEOPARD_GECKO: printed = snprintf(buf, buf_size, "EZR32 "); break; default: printed = snprintf(buf, buf_size, "EFM32 "); } buf += printed; buf_size -= printed; if (0 >= buf_size) return ERROR_BUF_TOO_SMALL; switch (info.part_family) { case EFM_FAMILY_ID_GECKO: printed = snprintf(buf, buf_size, "Gecko"); break; case EFM_FAMILY_ID_GIANT_GECKO: printed = snprintf(buf, buf_size, "Giant Gecko"); break; case EFM_FAMILY_ID_TINY_GECKO: printed = snprintf(buf, buf_size, "Tiny Gecko"); break; case EFM_FAMILY_ID_LEOPARD_GECKO: case EZR_FAMILY_ID_LEOPARD_GECKO: printed = snprintf(buf, buf_size, "Leopard Gecko"); break; case EFM_FAMILY_ID_WONDER_GECKO: case EZR_FAMILY_ID_WONDER_GECKO: printed = snprintf(buf, buf_size, "Wonder Gecko"); break; case EFM_FAMILY_ID_ZERO_GECKO: printed = snprintf(buf, buf_size, "Zero Gecko"); break; } buf += printed; buf_size -= printed; if (0 >= buf_size) return ERROR_BUF_TOO_SMALL; printed = snprintf(buf, buf_size, " - Rev: %d", info.prod_rev); buf += printed; buf_size -= printed; if (0 >= buf_size) return ERROR_BUF_TOO_SMALL; return ERROR_OK; } static const struct command_registration efm32x_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; static const struct command_registration efm32x_command_handlers[] = { { .name = "efm32", .mode = COMMAND_ANY, .help = "efm32 flash command group", .usage = "", .chain = efm32x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver efm32_flash = { .name = "efm32", .commands = efm32x_command_handlers, .flash_bank_command = efm32x_flash_bank_command, .erase = efm32x_erase, .protect = efm32x_protect, .write = efm32x_write, .read = default_flash_read, .probe = efm32x_probe, .auto_probe = efm32x_auto_probe, .erase_check = default_flash_blank_check, .protect_check = efm32x_protect_check, .info = get_efm32x_info, }; openocd-0.9.0/src/flash/nor/em357.c0000644000175000017500000006241512315575360013575 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * Copyright (C) 2011 by Erik Botö * erik.boto@pelagicore.com * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include /* em357 register locations */ #define EM357_FLASH_ACR 0x40008000 #define EM357_FLASH_KEYR 0x40008004 #define EM357_FLASH_OPTKEYR 0x40008008 #define EM357_FLASH_SR 0x4000800C #define EM357_FLASH_CR 0x40008010 #define EM357_FLASH_AR 0x40008014 #define EM357_FLASH_OBR 0x4000801C #define EM357_FLASH_WRPR 0x40008020 #define EM357_FPEC_CLK 0x4000402c /* option byte location */ #define EM357_OB_RDP 0x08040800 #define EM357_OB_WRP0 0x08040808 #define EM357_OB_WRP1 0x0804080A #define EM357_OB_WRP2 0x0804080C /* FLASH_CR register bits */ #define FLASH_PG (1 << 0) #define FLASH_PER (1 << 1) #define FLASH_MER (1 << 2) #define FLASH_OPTPG (1 << 4) #define FLASH_OPTER (1 << 5) #define FLASH_STRT (1 << 6) #define FLASH_LOCK (1 << 7) #define FLASH_OPTWRE (1 << 9) /* FLASH_SR register bits */ #define FLASH_BSY (1 << 0) #define FLASH_PGERR (1 << 2) #define FLASH_WRPRTERR (1 << 4) #define FLASH_EOP (1 << 5) /* EM357_FLASH_OBR bit definitions (reading) */ #define OPT_ERROR 0 #define OPT_READOUT 1 /* register unlock keys */ #define KEY1 0x45670123 #define KEY2 0xCDEF89AB struct em357_options { uint16_t RDP; uint16_t user_options; uint16_t protection[3]; }; struct em357_flash_bank { struct em357_options option_bytes; int ppage_size; int probed; }; static int em357_mass_erase(struct flash_bank *bank); /* flash bank em357 0 0 */ FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command) { struct em357_flash_bank *em357_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; em357_info = malloc(sizeof(struct em357_flash_bank)); bank->driver_priv = em357_info; em357_info->probed = 0; return ERROR_OK; } static inline int em357_get_flash_status(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; return target_read_u32(target, EM357_FLASH_SR, status); } static int em357_wait_status_busy(struct flash_bank *bank, int timeout) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;; ) { retval = em357_get_flash_status(bank, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if ((status & FLASH_BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_WRPRTERR) { LOG_ERROR("em357 device protected"); retval = ERROR_FAIL; } if (status & FLASH_PGERR) { LOG_ERROR("em357 device programming failed"); retval = ERROR_FAIL; } /* Clear but report errors */ if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { /* If this operation fails, we ignore it and report the original * retval */ target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR | FLASH_PGERR); } return retval; } static int em357_read_options(struct flash_bank *bank) { uint32_t optiondata; struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, EM357_FLASH_OBR, &optiondata); if (retval != ERROR_OK) return retval; em357_info->option_bytes.user_options = (uint16_t)0xFFFC | ((optiondata >> 2) & 0x03); em357_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5; if (optiondata & (1 << OPT_READOUT)) LOG_INFO("Device Security Bit Set"); /* each bit refers to a 4bank protection */ retval = target_read_u32(target, EM357_FLASH_WRPR, &optiondata); if (retval != ERROR_OK) return retval; em357_info->option_bytes.protection[0] = (uint16_t)optiondata; em357_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8); em357_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16); return ERROR_OK; } static int em357_erase_options(struct flash_bank *bank) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* read current options */ em357_read_options(bank); /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* erase option bytes */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* clear readout protection and complementary option bytes * this will also force a device unlock if set */ em357_info->option_bytes.RDP = 0x5AA5; return ERROR_OK; } static int em357_write_options(struct flash_bank *bank) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* program option bytes */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 1 */ retval = target_write_u16(target, EM357_OB_WRP0, em357_info->option_bytes.protection[0]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 2 */ retval = target_write_u16(target, EM357_OB_WRP1, em357_info->option_bytes.protection[1]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 3 */ retval = target_write_u16(target, EM357_OB_WRP2, em357_info->option_bytes.protection[2]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write readout protection bit */ retval = target_write_u16(target, EM357_OB_RDP, em357_info->option_bytes.RDP); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int em357_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct em357_flash_bank *em357_info = bank->driver_priv; uint32_t protection; int i, s; int num_bits; int set; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* each bit refers to a 4bank protection (bit 0-23) */ int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection); if (retval != ERROR_OK) return retval; /* each protection bit is for 4 * 2K pages */ num_bits = (bank->num_sectors / em357_info->ppage_size); for (i = 0; i < num_bits; i++) { set = 1; if (protection & (1 << i)) set = 0; for (s = 0; s < em357_info->ppage_size; s++) bank->sectors[(i * em357_info->ppage_size) + s].is_protected = set; } return ERROR_OK; } static int em357_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first == 0) && (last == (bank->num_sectors - 1))) return em357_mass_erase(bank); /* Enable FPEC clock */ target_write_u32(target, EM357_FPEC_CLK, 0x00000001); /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; for (i = first; i <= last; i++) { retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_AR, bank->base + bank->sectors[i].offset); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 100); if (retval != ERROR_OK) return retval; bank->sectors[i].is_erased = 1; } retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int em357_protect(struct flash_bank *bank, int set, int first, int last) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; int i, reg, bit; int status; uint32_t protection; em357_info = bank->driver_priv; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first % em357_info->ppage_size) != 0) { LOG_WARNING("aligned start protect sector to a %d sector boundary", em357_info->ppage_size); first = first - (first % em357_info->ppage_size); } if (((last + 1) % em357_info->ppage_size) != 0) { LOG_WARNING("aligned end protect sector to a %d sector boundary", em357_info->ppage_size); last++; last = last - (last % em357_info->ppage_size); last--; } /* each bit refers to a 4bank protection */ int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection); if (retval != ERROR_OK) return retval; prot_reg[0] = (uint16_t)protection; prot_reg[1] = (uint16_t)(protection >> 8); prot_reg[2] = (uint16_t)(protection >> 16); for (i = first; i <= last; i++) { reg = (i / em357_info->ppage_size) / 8; bit = (i / em357_info->ppage_size) - (reg * 8); LOG_WARNING("reg, bit: %d, %d", reg, bit); if (set) prot_reg[reg] &= ~(1 << bit); else prot_reg[reg] |= (1 << bit); } status = em357_erase_options(bank); if (retval != ERROR_OK) return status; em357_info->option_bytes.protection[0] = prot_reg[0]; em357_info->option_bytes.protection[1] = prot_reg[1]; em357_info->option_bytes.protection[2] = prot_reg[2]; return em357_write_options(bank); } static int em357_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* see contib/loaders/flash/stm32x.s for src, the same is used here except for * a modified *_FLASH_BASE */ static const uint8_t em357_flash_write_code[] = { /* #define EM357_FLASH_CR_OFFSET 0x10 * #define EM357_FLASH_SR_OFFSET 0x0C * write: */ 0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */ 0x1c, 0x44, /* add r4, r3 */ /* write_half_word: */ 0x01, 0x23, /* movs r3, #0x01 */ 0x23, 0x61, /* str r3, [r4, *#EM357_FLASH_CR_OFFSET] */ 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */ 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */ /* busy: */ 0xe3, 0x68, /* ldr r3, [r4, *#EM357_FLASH_SR_OFFSET] */ 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */ 0xfb, 0xd0, /* beq busy */ 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */ 0x01, 0xd1, /* bne exit */ 0x01, 0x3a, /* subs r2, r2, #0x01 */ 0xf0, 0xd1, /* bne write_half_word */ /* exit: */ 0x00, 0xbe, /* bkpt #0x00 */ 0x00, 0x80, 0x00, 0x40, /* EM357_FLASH_BASE: .word 0x40008000 */ }; /* flash write code */ if (target_alloc_working_area(target, sizeof(em357_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } ; retval = target_write_buffer(target, write_algorithm->address, sizeof(em357_flash_write_code), em357_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING( "no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); while (count > 0) { uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); buf_set_u32(reg_params[3].value, 0, 32, 0); retval = target_run_algorithm(target, 0, NULL, 4, reg_params, write_algorithm->address, 0, 10000, &armv7m_info); if (retval != ERROR_OK) { LOG_ERROR("error executing em357 flash write algorithm"); break; } if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) { LOG_ERROR("flash memory not erased before writing"); /* Clear but report errors */ target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR); retval = ERROR_FAIL; break; } if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) { LOG_ERROR("flash memory write protected"); /* Clear but report errors */ target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR); retval = ERROR_FAIL; break; } buffer += thisrun_count * 2; address += thisrun_count * 2; count -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); return retval; } static int em357_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t words_remaining = (count / 2); uint32_t bytes_remaining = (count & 0x00000001); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* unlock flash registers */ retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; target_write_u32(target, EM357_FPEC_CLK, 0x00000001); /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = em357_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING( "couldn't use block writes, falling back to single memory accesses"); } } else { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) return retval; while (words_remaining > 0) { uint16_t value; memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { uint16_t value = 0xffff; memcpy(&value, buffer + bytes_written, bytes_remaining); retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; } return target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); } static int em357_probe(struct flash_bank *bank) { struct target *target = bank->target; struct em357_flash_bank *em357_info = bank->driver_priv; int i; uint16_t num_pages; int page_size; uint32_t base_address = 0x08000000; em357_info->probed = 0; switch (bank->size) { case 0x10000: /* 64k -- 64 1k pages */ num_pages = 64; page_size = 1024; break; case 0x20000: /* 128k -- 128 1k pages */ num_pages = 128; page_size = 1024; break; case 0x30000: /* 192k -- 96 2k pages */ num_pages = 96; page_size = 2048; break; case 0x40000: /* 256k -- 128 2k pages */ num_pages = 128; page_size = 2048; break; default: LOG_WARNING("No size specified for em357 flash driver, assuming 192k!"); num_pages = 96; page_size = 2048; break; } /* Enable FPEC CLK */ int retval = target_write_u32(target, EM357_FPEC_CLK, 0x00000001); if (retval != ERROR_OK) return retval; em357_info->ppage_size = 4; LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->size = (num_pages * page_size); bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); for (i = 0; i < num_pages; i++) { bank->sectors[i].offset = i * page_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } em357_info->probed = 1; return ERROR_OK; } static int em357_auto_probe(struct flash_bank *bank) { struct em357_flash_bank *em357_info = bank->driver_priv; if (em357_info->probed) return ERROR_OK; return em357_probe(bank); } COMMAND_HANDLER(em357_handle_lock_command) { struct target *target = NULL; struct em357_flash_bank *em357_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; em357_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (em357_erase_options(bank) != ERROR_OK) { command_print(CMD_CTX, "em357 failed to erase options"); return ERROR_OK; } /* set readout protection */ em357_info->option_bytes.RDP = 0; if (em357_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "em357 failed to lock device"); return ERROR_OK; } command_print(CMD_CTX, "em357 locked"); return ERROR_OK; } COMMAND_HANDLER(em357_handle_unlock_command) { struct target *target = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (em357_erase_options(bank) != ERROR_OK) { command_print(CMD_CTX, "em357 failed to unlock device"); return ERROR_OK; } if (em357_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "em357 failed to lock device"); return ERROR_OK; } command_print(CMD_CTX, "em357 unlocked.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } static int em357_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Make sure the flash clock is on */ target_write_u32(target, EM357_FPEC_CLK, 0x00000001); /* unlock option flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 100); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } COMMAND_HANDLER(em357_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = em357_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "em357 mass erase complete"); } else command_print(CMD_CTX, "em357 mass erase failed"); return retval; } static const struct command_registration em357_exec_command_handlers[] = { { .name = "lock", .usage = "", .handler = em357_handle_lock_command, .mode = COMMAND_EXEC, .help = "Lock entire flash device.", }, { .name = "unlock", .usage = "", .handler = em357_handle_unlock_command, .mode = COMMAND_EXEC, .help = "Unlock entire protected flash device.", }, { .name = "mass_erase", .usage = "", .handler = em357_handle_mass_erase_command, .mode = COMMAND_EXEC, .help = "Erase entire flash device.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration em357_command_handlers[] = { { .name = "em357", .mode = COMMAND_ANY, .help = "em357 flash command group", .usage = "", .chain = em357_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver em357_flash = { .name = "em357", .commands = em357_command_handlers, .flash_bank_command = em357_flash_bank_command, .erase = em357_erase, .protect = em357_protect, .write = em357_write, .read = default_flash_read, .probe = em357_probe, .auto_probe = em357_auto_probe, .erase_check = default_flash_blank_check, .protect_check = em357_protect_check, }; openocd-0.9.0/src/flash/nor/sim3x.c0000644000175000017500000007406712516456302014003 00000000000000/*************************************************************************** * Copyright (C) 2014 by Ladislav Bábel * * ladababel@seznam.cz * * * * Copyright (C) 2015 by Andreas Bomholtz * * andreas@seluxit.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /* SI32_DEVICEID0 */ #define DEVICEID0_DEVICEID0 (0x400490C0) #define DEVICEID0_DEVICEID1 (0x400490D0) #define DEVICEID0_DEVICEID2 (0x400490E0) #define DEVICEID0_DEVICEID3 (0x400490F0) /* cortex_m CPUID */ #define CPUID_CHECK_VALUE (0x410FC230) #define CPUID_CHECK_VALUE_MASK (0xFF0FFFF0) /* Flash */ #define FLASH_BASE_ADDRESS (0x00000000) #define LOCK_WORD_ADDRESS (0x0003FFFC) #define LOCK_WORD_MCU_UNLOCKED (0xFFFFFFFF) /* Can't by locked again without erase, because LOCK_WORD is in FLASH */ #define LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE (0x00000000) /* SI32_FLASHCTRL_0 */ #define FLASHCTRL0_CONFIG_ALL (0x4002E000) #define FLASHCTRL0_CONFIG_SET (0x4002E004) #define FLASHCTRL0_CONFIG_CLR (0x4002E008) #define FLASHCTRL0_CONFIG_ERASEEN_MASK (0x00040000) #define FLASHCTRL0_CONFIG_BUSYF_MASK (0x00100000) #define FLASHCTRL0_WRADDR (0x4002E0A0) #define FLASHCTRL0_WRDATA (0x4002E0B0) #define FLASHCTRL0_KEY (0x4002E0C0) #define FLASHCTRL0_KEY_INITIAL_UNLOCK (0x000000A5) #define FLASHCTRL0_KEY_SINGLE_UNLOCK (0x000000F1) #define FLASHCTRL0_KEY_MULTIPLE_UNLOCK (0x000000F2) #define FLASHCTRL0_KEY_MULTIPLE_LOCK (0x0000005A) #define FLASH_BUSY_TIMEOUT (100) /* SI32_RSTSRC_0 */ #define RSTSRC0_RESETEN_ALL (0x4002D060) #define RSTSRC0_RESETEN_SET (0x4002D064) #define RSTSRC0_RESETEN_CLR (0x4002D068) #define RSTSRC0_RESETEN_VMONREN_MASK (0x00000004) #define RSTSRC0_RESETEN_SWREN_MASK (0x00000040) /* SI32_VMON_0 */ #define VMON0_CONTROL_ALL (0x4002F000) #define VMON0_CONTROL_SET (0x4002F004) #define VMON0_CONTROL_CLR (0x4002F008) #define VMON0_CONTROL_VMONEN_MASK (0x80000000) /* SI32_CLKCTRL_0 */ #define CLKCTRL0_APBCLKG0_ALL (0x4002D020) #define CLKCTRL0_APBCLKG0_SET (0x4002D024) #define CLKCTRL0_APBCLKG0_CLR (0x4002D028) #define CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK (0x40000000) /* SI32_WDTIMER_0 */ #define WDTIMER0_CONTROL_ALL (0x40030000) #define WDTIMER0_CONTROL_SET (0x40030004) #define WDTIMER0_CONTROL_CLR (0x40030008) #define WDTIMER0_CONTROL_DBGMD_MASK (0x00000002) #define WDTIMER0_STATUS_ALL (0x40030010) #define WDTIMER0_STATUS_SET (0x40030014) #define WDTIMER0_STATUS_CLR (0x40030018) #define WDTIMER0_STATUS_KEYSTS_MASK (0x00000001) #define WDTIMER0_STATUS_PRIVSTS_MASK (0x00000002) #define WDTIMER0_THRESHOLD (0x40030020) #define WDTIMER0_WDTKEY (0x40030030) #define WDTIMER0_KEY_ATTN (0x000000A5) #define WDTIMER0_KEY_WRITE (0x000000F1) #define WDTIMER0_KEY_RESET (0x000000CC) #define WDTIMER0_KEY_DISABLE (0x000000DD) #define WDTIMER0_KEY_START (0x000000EE) #define WDTIMER0_KEY_LOCK (0x000000FF) /* DAP */ #define SIM3X_AP (0x0A) #define SIM3X_AP_CTRL1 (0x00) #define SIM3X_AP_CTRL2 (0x04) #define SIM3X_AP_LOCK (0x08) #define SIM3X_AP_CRC (0x0C) #define SIM3X_AP_INIT_STAT (0x10) #define SIM3X_AP_DAP_IN (0x14) #define SIM3X_AP_DAP_OUT (0x18) #define SIM3X_AP_ID (0xFC) /* DAP register values */ #define SIM3X_AP_CTRL1_MASS_ERASE_REQ (0x00000001) #define SIM3X_AP_CTRL1_RESET_REQ (0x00000008) /* this bit is set if MCU is locked */ #define SIM3X_AP_INIT_STAT_LOCK (0x00000004) /* expected value inside SIM3X_AP_ID */ #define SIM3X_AP_ID_VALUE (0x2430002) #define SIM3X_FLASH_PAGE_SIZE 1024 struct sim3x_info { uint16_t flash_size_kb; uint16_t part_number; char part_family; uint8_t device_revision; char device_package[4]; bool probed; bool need_init; bool flash_locked; }; /* flash bank sim3x 0 0 0 0 */ FLASH_BANK_COMMAND_HANDLER(sim3x_flash_bank_command) { struct sim3x_info *sim3x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; /* Init sim3x_info struct */ sim3x_info = malloc(sizeof(struct sim3x_info)); sim3x_info->probed = false; sim3x_info->need_init = true; sim3x_info->device_revision = 0; memset(sim3x_info->device_package, 0, 4); bank->driver_priv = sim3x_info; return ERROR_OK; } static int sim3x_init(struct flash_bank *bank) { int ret; struct target *target; struct sim3x_info *sim3x_info; target = bank->target; /* Disable watchdog timer */ ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN); if (ret != ERROR_OK) return ret; ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_DISABLE); if (ret != ERROR_OK) return ret; /* Enable one write command */ ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN); if (ret != ERROR_OK) return ret; ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_WRITE); if (ret != ERROR_OK) return ret; /* Watchdog Timer Debug Mode */ ret = target_write_u32(target, WDTIMER0_CONTROL_SET, WDTIMER0_CONTROL_DBGMD_MASK); if (ret != ERROR_OK) return ret; /* Enable VDD Supply Monitor */ ret = target_write_u32(target, VMON0_CONTROL_SET, VMON0_CONTROL_VMONEN_MASK); if (ret != ERROR_OK) return ret; /* Set VDD Supply Monitor as a reset source */ ret = target_write_u32(target, RSTSRC0_RESETEN_SET, RSTSRC0_RESETEN_VMONREN_MASK); if (ret != ERROR_OK) return ret; /* Flash Controller Clock Enable */ ret = target_write_u32(target, CLKCTRL0_APBCLKG0_SET, CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK); if (ret != ERROR_OK) return ret; /* Disable Flash Erase Mode */ ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR, FLASHCTRL0_CONFIG_ERASEEN_MASK); if (ret != ERROR_OK) return ret; sim3x_info = bank->driver_priv; sim3x_info->need_init = 0; return ERROR_OK; } static int sim3x_erase_page(struct flash_bank *bank, uint32_t addr) { int ret, i; uint32_t temp; struct target *target; target = bank->target; for (i = 0; i < FLASH_BUSY_TIMEOUT; i++) { ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp); if (ret != ERROR_OK) return ret; /* If is not busy */ if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) { /* If erase is not enabled */ if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) == 0) { /* Enter Flash Erase Mode */ ret = target_write_u32(target, FLASHCTRL0_CONFIG_SET, FLASHCTRL0_CONFIG_ERASEEN_MASK); if (ret != ERROR_OK) return ret; } /* Write the address of the Flash page to WRADDR */ ret = target_write_u32(target, FLASHCTRL0_WRADDR, addr); if (ret != ERROR_OK) return ret; /* Write the inital unlock value to KEY */ ret = target_write_u32(target, FLASHCTRL0_KEY, FLASHCTRL0_KEY_INITIAL_UNLOCK); if (ret != ERROR_OK) return ret; /* Write the single unlock value to KEY */ ret = target_write_u32(target, FLASHCTRL0_KEY, FLASHCTRL0_KEY_SINGLE_UNLOCK); if (ret != ERROR_OK) return ret; /* Write any value to WRDATA to initiate the page erase */ ret = target_write_u32(target, FLASHCTRL0_WRDATA, 0); if (ret != ERROR_OK) return ret; return ERROR_OK; } alive_sleep(1); } LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF"); return ERROR_FAIL; } static int sim3x_flash_erase(struct flash_bank *bank, int first, int last) { int ret, i; uint32_t temp; struct sim3x_info *sim3x_info; struct target *target; /* Check if target is halted */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } sim3x_info = bank->driver_priv; /* Init MCU after reset */ if (sim3x_info->need_init) { ret = sim3x_init(bank); if (ret != ERROR_OK) { LOG_ERROR("Failed to init MCU"); return ret; } } /* erase pages */ for (i = first; i <= last; i++) { ret = sim3x_erase_page(bank, bank->sectors[i].offset); if (ret != ERROR_OK) return ret; } target = bank->target; /* Wait until busy */ for (i = 0; i < FLASH_BUSY_TIMEOUT; i++) { ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp); if (ret != ERROR_OK) return ret; if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) { /* If is not busy */ if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) != 0) { /* If erase is enabled */ /* Disable Flash Erase Mode */ ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR, FLASHCTRL0_CONFIG_ERASEEN_MASK); if (ret != ERROR_OK) return ret; } return ERROR_OK; } alive_sleep(1); } LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF"); return ERROR_FAIL; } static int sim3x_write_block(struct flash_bank *bank, const uint8_t *buf, uint32_t offset, uint32_t count) /* count is count of half words (2 bytes)! */ { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int ret = ERROR_OK; /* see contrib/loaders/flash/sim3x.s for src */ static const uint8_t sim3x_flash_write_code[] = { /* Write the initial unlock value to KEY (0xA5) */ 0xA5, 0x26, /* movs r6, #INITIAL_UNLOCK */ 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */ /* Write the multiple unlock value to KEY (0xF2) */ 0xF2, 0x26, /* movs r6, #MULTIPLE_UNLOCK */ 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */ /* wait_fifo: */ 0x16, 0x68, /* ldr r6, [r2, #0] */ 0x00, 0x2E, /* cmp r6, #0 */ 0x16, 0xD0, /* beq exit */ 0x55, 0x68, /* ldr r5, [r2, #4] */ 0xB5, 0x42, /* cmp r5, r6 */ 0xF9, 0xD0, /* beq wait_fifo */ /* wait for BUSYF flag */ /* wait_busy1: */ 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */ 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */ 0xFB, 0xD1, /* bne wait_busy1 */ /* Write the destination address to WRADDR */ 0xC0, 0xF8, 0xA0, 0x40, /* str r4, [r0, #FLASHCTRL_WRADDR] */ /* Write the data half-word to WRDATA in right-justified format */ 0x2E, 0x88, /* ldrh r6, [r5] */ 0xC0, 0xF8, 0xB0, 0x60, /* str r6, [r0, #FLASHCTRL_WRDATA] */ 0x02, 0x35, /* adds r5, #2 */ 0x02, 0x34, /* adds r4, #2 */ /* wrap rp at end of buffer */ 0x9D, 0x42, /* cmp r5, r3 */ 0x01, 0xD3, /* bcc no_wrap */ 0x15, 0x46, /* mov r5, r2 */ 0x08, 0x35, /* adds r5, #8 */ /* no_wrap: */ 0x55, 0x60, /* str r5, [r2, #4] */ 0x49, 0x1E, /* subs r1, r1, #1 */ 0x00, 0x29, /* cmp r1, #0 */ 0x00, 0xD0, /* beq exit */ 0xE5, 0xE7, /* b wait_fifo */ /* exit: */ 0x5A, 0x26, /* movs r6, #MULTIPLE_LOCK */ 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */ /* wait for BUSYF flag */ /* wait_busy2: */ 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */ 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */ 0xFB, 0xD1, /* bne wait_busy2 */ 0x00, 0xBE /* bkpt #0 */ }; /* flash write code */ if (target_alloc_working_area(target, sizeof(sim3x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } ret = target_write_buffer(target, write_algorithm->address, sizeof(sim3x_flash_write_code), sim3x_flash_write_code); if (ret != ERROR_OK) return ret; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; buffer_size &= ~1UL; /* Make sure it's 2 byte aligned */ if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* flash base */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer start */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[4], "r4", 32, PARAM_IN_OUT); /* target address */ buf_set_u32(reg_params[0].value, 0, 32, FLASHCTRL0_CONFIG_ALL); buf_set_u32(reg_params[1].value, 0, 32, count); buf_set_u32(reg_params[2].value, 0, 32, source->address); buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[4].value, 0, 32, address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; ret = target_run_flash_async_algorithm(target, buf, count, 2, 0, NULL, 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (ret == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash write failed at address 0x%"PRIx32, buf_get_u32(reg_params[4].value, 0, 32)); } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return ret; } static int sim3x_flash_write(struct flash_bank *bank, const uint8_t * buffer, uint32_t offset, uint32_t count) { int ret; struct target *target; struct sim3x_info *sim3x_info; uint8_t *new_buffer = NULL; target = bank->target; /* Check if target is halted */ if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } sim3x_info = bank->driver_priv; if (sim3x_info->flash_locked) { LOG_ERROR("Falsh is locked"); return ERROR_FAIL; } /* Init MCU after reset */ if (sim3x_info->need_init) { ret = sim3x_init(bank); if (ret != ERROR_OK) return ret; } if (offset & 0x1) { LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } if (count & 0x1) { uint32_t old_count = count; count++; new_buffer = malloc(count); if (new_buffer == NULL) { LOG_ERROR("odd number of bytes to write and no memory " "for padding buffer"); return ERROR_FAIL; } LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " and padding with 0xff", old_count, count); new_buffer[count - 1] = 0xff; buffer = memcpy(new_buffer, buffer, old_count); } ret = sim3x_write_block(bank, buffer, offset, count / 2); free(new_buffer); return ret; } static int sim3x_flash_lock_check(struct flash_bank *bank) { int ret; uint32_t lock_word; struct sim3x_info *sim3x_info; ret = target_read_u32(bank->target, LOCK_WORD_ADDRESS, &lock_word); if (ret != ERROR_OK) { LOG_ERROR("Can not read Lock Word"); return ret; } sim3x_info = bank->driver_priv; sim3x_info->flash_locked = (lock_word != 0xFFFFFFFF); return ERROR_OK; } static int sim3x_flash_protect_check(struct flash_bank *bank) { int ret, i; struct sim3x_info *sim3x_info; /* Check if target is halted */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } ret = sim3x_flash_lock_check(bank); if (ret != ERROR_OK) return ret; sim3x_info = bank->driver_priv; for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = sim3x_info->flash_locked; return ERROR_OK; } static int sim3x_flash_protect(struct flash_bank *bank, int set, int first, int last) { int ret; uint8_t lock_word[4]; struct sim3x_info *sim3x_info; struct target *target; target = bank->target; /* Check if target is halted */ if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (first != 0 || last != bank->num_sectors - 1) { LOG_ERROR("Flash does not support finer granularity"); return ERROR_FAIL; } sim3x_info = bank->driver_priv; if (set) { if (sim3x_info->flash_locked) { LOG_INFO("Flash is already locked"); return ERROR_OK; } /* Lock Flash */ target_buffer_set_u32(target, lock_word, 0xFFFFFFFE); ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4); if (ret != ERROR_OK) return ret; } else { /* Flash is unlocked by an erase operation */ ret = sim3x_flash_erase(bank, 0, 0); if (ret != ERROR_OK) return ret; } ret = sim3x_flash_protect_check(bank); if (ret != ERROR_OK) return ret; if (set) { if (sim3x_info->flash_locked) { LOG_INFO("Flash locked"); return ERROR_OK; } else { LOG_ERROR("Flash lock error"); return ERROR_FAIL; } } else { if (sim3x_info->flash_locked) { LOG_ERROR("Flash unlock error"); return ERROR_FAIL; } else { LOG_INFO("Flash unlocked"); return ERROR_OK; } } } static int sim3x_read_deviceid(struct flash_bank *bank) { int ret; struct sim3x_info *sim3x_info; uint32_t device_id; int part_number; char part_num_string[4]; sim3x_info = bank->driver_priv; /* MCU check */ ret = target_read_u32(bank->target, DEVICEID0_DEVICEID2, &device_id); if (ret != ERROR_OK) return ret; /* Device ID should be 'M3' */ if (device_id != 0x00004D33) return ERROR_FAIL; /* Family and Part number */ ret = target_read_u32(bank->target, DEVICEID0_DEVICEID1, &device_id); if (ret != ERROR_OK) return ret; part_num_string[0] = device_id >> 16; part_num_string[1] = device_id >> 8; part_num_string[2] = device_id; part_num_string[3] = 0; part_number = atoi(part_num_string); /* Part Number should be between 100 and 999 */ if (!isalpha(device_id >> 24) || part_number < 100 || part_number > 999) return ERROR_FAIL; sim3x_info->part_family = device_id >> 24; sim3x_info->part_number = part_number; /* Package and Revision */ ret = target_read_u32(bank->target, DEVICEID0_DEVICEID0, &device_id); if (ret != ERROR_OK) return ret; sim3x_info->device_package[0] = device_id >> 24; sim3x_info->device_package[1] = device_id >> 16; sim3x_info->device_package[2] = device_id >> 8; sim3x_info->device_package[3] = 0; sim3x_info->device_revision = device_id; return ERROR_OK; } static int sim3x_parse_part_info(struct sim3x_info *sim3x_info) { switch (sim3x_info->part_number) { case 134: case 136: sim3x_info->flash_size_kb = 32; break; case 144: case 146: sim3x_info->flash_size_kb = 64; break; case 154: case 156: case 157: sim3x_info->flash_size_kb = 128; break; case 164: case 166: case 167: sim3x_info->flash_size_kb = 256; break; default: LOG_ERROR("Unknown Part number %d", sim3x_info->part_number); sim3x_info->part_number = 0; return ERROR_FAIL; } switch (sim3x_info->part_family) { case 'c': case 'C': LOG_INFO("SiM3C%d detected", sim3x_info->part_number); break; case 'u': case 'U': LOG_INFO("SiM3U%d detected", sim3x_info->part_number); break; case 'l': case 'L': LOG_INFO("SiM3L%d detected", sim3x_info->part_number); break; default: LOG_ERROR("Unsupported MCU family %c", sim3x_info->part_family); sim3x_info->part_family = 0; return ERROR_FAIL; } return ERROR_OK; } static int sim3x_read_info(struct flash_bank *bank) { int ret; struct sim3x_info *sim3x_info; uint32_t cpuid; sim3x_info = bank->driver_priv; /* Core check */ ret = target_read_u32(bank->target, CPUID, &cpuid); if (ret != ERROR_OK) { LOG_ERROR("Failed to read CPU ID"); return ret; } if (((cpuid >> 4) & 0xfff) != 0xc23) { LOG_ERROR("Target is not CortexM3"); return ERROR_FAIL; } /* Read info from chip */ ret = sim3x_read_deviceid(bank); if (ret == ERROR_OK) { ret = sim3x_parse_part_info(sim3x_info); if (ret != ERROR_OK) { LOG_ERROR("Failed to parse info from MCU"); return ERROR_FAIL; } } else { LOG_WARNING("Failed to read info from MCU, using info from flash bank parameters"); /* Check if flash size is given in flash bank command */ if (!bank->size) { LOG_ERROR("Flash size not set in the flash bank command"); return ERROR_FAIL; } /* Convert bank size to kb */ sim3x_info->flash_size_kb = bank->size / 1024; } LOG_INFO("Flash size = %dKB", sim3x_info->flash_size_kb); return ERROR_OK; } static int sim3x_probe(struct flash_bank *bank) { int ret, i; struct sim3x_info *sim3x_info; sim3x_info = bank->driver_priv; sim3x_info->probed = false; sim3x_info->need_init = true; /* Read info from chip */ ret = sim3x_read_info(bank); if (ret != ERROR_OK) return ret; ret = sim3x_flash_lock_check(bank); if (ret != ERROR_OK) return ret; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = FLASH_BASE_ADDRESS; bank->size = sim3x_info->flash_size_kb * SIM3X_FLASH_PAGE_SIZE; bank->num_sectors = SIM3X_FLASH_PAGE_SIZE; bank->sectors = malloc(sizeof(struct flash_sector) * sim3x_info->flash_size_kb); for (i = 0; i < sim3x_info->flash_size_kb; i++) { bank->sectors[i].offset = i * SIM3X_FLASH_PAGE_SIZE; bank->sectors[i].size = SIM3X_FLASH_PAGE_SIZE; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = sim3x_info->flash_locked; } sim3x_info->probed = true; return ERROR_OK; } static int sim3x_auto_probe(struct flash_bank *bank) { struct sim3x_info *sim3x_info; sim3x_info = bank->driver_priv; if (sim3x_info->probed) { sim3x_info->need_init = true; return ERROR_OK; } else { return sim3x_probe(bank); } } static int sim3x_flash_info(struct flash_bank *bank, char *buf, int buf_size) { int ret; int printed = 0; struct sim3x_info *sim3x_info; sim3x_info = bank->driver_priv; /* Read info about chip */ ret = sim3x_read_info(bank); if (ret != ERROR_OK) return ret; /* Part */ if (sim3x_info->part_family && sim3x_info->part_number) { printed = snprintf(buf, buf_size, "SiM3%c%d", sim3x_info->part_family, sim3x_info->part_number); buf += printed; buf_size -= printed; if (buf_size <= 0) return ERROR_BUF_TOO_SMALL; /* Revision */ if (sim3x_info->device_revision && sim3x_info->device_revision <= 'Z' - 'A') { printed = snprintf(buf, buf_size, "-%c", sim3x_info->device_revision + 'A'); buf += printed; buf_size -= printed; if (buf_size <= 0) return ERROR_BUF_TOO_SMALL; /* Package */ if (sim3x_info->device_package) { printed = snprintf(buf, buf_size, "-G%s", sim3x_info->device_package); buf += printed; buf_size -= printed; if (buf_size <= 0) return ERROR_BUF_TOO_SMALL; } } } /* Print flash size */ printed = snprintf(buf, buf_size, " flash_size = %dKB", sim3x_info->flash_size_kb); buf_size -= printed; if (buf_size <= 0) return ERROR_BUF_TOO_SMALL; return ERROR_OK; } /** * reg 31:8 - no effect * reg 7:4 - bank * reg 3:2 - register * reg 1:0 - no effect */ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { int retval; LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value); retval = dap_queue_ap_write(dap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a write request"); return retval; } retval = dap_run(dap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; } return ERROR_OK; } static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { int retval; retval = dap_queue_ap_read(dap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a read request"); return retval; } retval = dap_run(dap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; } LOG_DEBUG("DAP_REG[0x%02x]: %08" PRIX32, reg, *result); return ERROR_OK; } static int ap_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout) { uint32_t val; int retval; do { retval = ap_read_register(dap, reg, &val); if (retval != ERROR_OK || (val & mask) == value) return retval; alive_sleep(1); } while (timeout--); LOG_DEBUG("DAP: polling timed out"); return ERROR_FAIL; } COMMAND_HANDLER(sim3x_mass_erase) { uint32_t val; int ret; struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; if (dap == NULL) { /* Used debug interface doesn't support direct DAP access */ LOG_ERROR("mass_erase can't be used by this debug interface"); return ERROR_FAIL; } const uint8_t origninal_ap = dap->ap_current >> 24; dap_ap_select(dap, SIM3X_AP); ret = ap_read_register(dap, SIM3X_AP_ID, &val); if (ret != ERROR_OK) return ret; if (val != SIM3X_AP_ID_VALUE) { LOG_ERROR("Wrong SIM3X_AP_ID"); return ERROR_FAIL; } /* Mass erase sequence */ ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ); if (ret != ERROR_OK) return ret; ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ | SIM3X_AP_CTRL1_MASS_ERASE_REQ); if (ret != ERROR_OK) return ret; ret = ap_poll_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_MASS_ERASE_REQ, 0x00000000, FLASH_BUSY_TIMEOUT); if (ret != ERROR_OK) return ret; ret = ap_write_register(dap, SIM3X_AP_CTRL1, 0x00000000); /* clear SIM3X_AP_CTRL1_RESET_REQ */ if (ret != ERROR_OK) return ret; dap_ap_select(dap, origninal_ap); LOG_INFO("Mass erase success"); return ERROR_OK; } COMMAND_HANDLER(sim3x_lock) { uint32_t val; int ret; struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; if (dap == NULL) { /* Used debug interface doesn't support direct DAP access */ LOG_INFO("Target can't by unlocked by this debug interface"); /* Core check */ ret = target_read_u32(target, CPUID, &val); if (ret != ERROR_OK) return ret; if ((val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) { LOG_ERROR("Target is not ARM CortexM3 or is already locked"); return ERROR_FAIL; } } else { const uint8_t origninal_ap = dap->ap_current >> 24; dap_ap_select(dap, SIM3X_AP); /* check SIM3X_AP_ID */ ret = ap_read_register(dap, SIM3X_AP_ID, &val); if (ret != ERROR_OK) return ret; if (val != SIM3X_AP_ID_VALUE) { LOG_ERROR("Wrong SIM3X_AP_ID"); return ERROR_FAIL; } /* check if locked */ ret = target_read_u32(target, CPUID, &val); /* if correct value is read, then it will continue */ if (ret != ERROR_OK || (val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) { /* if correct value is'n read, then it will check SIM3X_AP_INIT_STAT register */ ret = ap_read_register(dap, SIM3X_AP_INIT_STAT, &val); if (ret != ERROR_OK) return ret; dap_ap_select(dap, origninal_ap); if (val & SIM3X_AP_INIT_STAT_LOCK) { LOG_INFO("Target is already locked"); return ERROR_OK; } else { LOG_ERROR("Target doesn't seem to be locked but memory was not read correct"); return ERROR_FAIL; } } dap_ap_select(dap, origninal_ap); } ret = target_read_u32(target, LOCK_WORD_ADDRESS, &val); if (ret != ERROR_OK) return ret; if (val == LOCK_WORD_MCU_UNLOCKED) { /* Lock Flash */ uint8_t lock_word[4]; target_buffer_set_u32(target, lock_word, 0xFFFFFFFE); /* Get Flash Bank */ struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (retval != ERROR_OK) return retval; ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4); if (ERROR_OK != ret) return ret; LOG_INFO("Target is successfully locked"); return ERROR_OK; } else if (val == LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE) { /* Can't by locked again without erase, because LOCK_WORD is in FLASH */ LOG_ERROR("Target is unlocked by firmware and can't by locked again without the lock page erase or mass erase"); return ERROR_FAIL; } else { LOG_ERROR("Unexpected lock word value"); /* SIM3X_AP_ID_VALUE is not checked */ if (dap == NULL) LOG_INFO("Maybe this isn't a SiM3x MCU"); return ERROR_FAIL; } } static const struct command_registration sim3x_exec_command_handlers[] = { { .name = "mass_erase", .mode = COMMAND_EXEC, .help = "Erase the complete flash", .usage = "", .handler = sim3x_mass_erase, }, { .name = "lock", .mode = COMMAND_EXEC, .help = "Locks the flash. Unlock by mass erase", .usage = "", .handler = sim3x_lock, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration sim3x_command_handlers[] = { { .name = "sim3x", .mode = COMMAND_ANY, .help = "sim3x flash command group", .usage = "", .chain = sim3x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver sim3x_flash = { .name = "sim3x", .commands = sim3x_command_handlers, .flash_bank_command = sim3x_flash_bank_command, .erase = sim3x_flash_erase, .protect = sim3x_flash_protect, .write = sim3x_flash_write, .read = default_flash_read, .probe = sim3x_probe, .auto_probe = sim3x_auto_probe, .erase_check = default_flash_blank_check, .protect_check = sim3x_flash_protect_check, .info = sim3x_flash_info }; openocd-0.9.0/src/flash/nor/virtual.c0000644000175000017500000001511512315575360014416 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank) { struct flash_bank *master_bank; master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv); if (master_bank == NULL) LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv); return master_bank; } static void virtual_update_bank_info(struct flash_bank *bank) { struct flash_bank *master_bank = virtual_get_master_bank(bank); if (master_bank == NULL) return; /* update the info we do not have */ bank->size = master_bank->size; bank->chip_width = master_bank->chip_width; bank->bus_width = master_bank->bus_width; bank->default_padded_value = master_bank->default_padded_value; bank->num_sectors = master_bank->num_sectors; bank->sectors = master_bank->sectors; } FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command) { if (CMD_ARGC < 7) return ERROR_COMMAND_SYNTAX_ERROR; /* get the master flash bank */ const char *bank_name = CMD_ARGV[6]; struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name); if (master_bank == NULL) { LOG_ERROR("master flash bank '%s' does not exist", bank_name); return ERROR_FLASH_OPERATION_FAILED; } /* save master bank name - use this to get settings later */ bank->driver_priv = strdup(bank_name); return ERROR_OK; } static int virtual_protect(struct flash_bank *bank, int set, int first, int last) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->protect(master_bank, set, first, last); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int virtual_protect_check(struct flash_bank *bank) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->protect_check(master_bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int virtual_erase(struct flash_bank *bank, int first, int last) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->erase(master_bank, first, last); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int virtual_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->write(master_bank, buffer, offset, count); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int virtual_probe(struct flash_bank *bank) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->probe(master_bank); if (retval != ERROR_OK) return retval; /* update the info we do not have */ virtual_update_bank_info(bank); return ERROR_OK; } static int virtual_auto_probe(struct flash_bank *bank) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->auto_probe(master_bank); if (retval != ERROR_OK) return retval; /* update the info we do not have */ virtual_update_bank_info(bank); return ERROR_OK; } static int virtual_info(struct flash_bank *bank, char *buf, int buf_size) { struct flash_bank *master_bank = virtual_get_master_bank(bank); if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "", bank->driver->name, master_bank->name, master_bank->base); return ERROR_OK; } static int virtual_blank_check(struct flash_bank *bank) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->erase_check(master_bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int virtual_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct flash_bank *master_bank = virtual_get_master_bank(bank); int retval; if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; /* call master handler */ retval = master_bank->driver->read(master_bank, buffer, offset, count); if (retval != ERROR_OK) return retval; return ERROR_OK; } struct flash_driver virtual_flash = { .name = "virtual", .flash_bank_command = virtual_flash_bank_command, .erase = virtual_erase, .protect = virtual_protect, .write = virtual_write, .read = virtual_flash_read, .probe = virtual_probe, .auto_probe = virtual_auto_probe, .erase_check = virtual_blank_check, .protect_check = virtual_protect_check, .info = virtual_info, }; openocd-0.9.0/src/flash/nor/at91sam3.c0000644000175000017500000027044412327155503014276 00000000000000/*************************************************************************** * Copyright (C) 2009 by Duane Ellis * * openocd@duaneellis.com * * * * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) * * olaf@uni-paderborn.de * * * * Copyright (C) 2011 by Olivier Schonken (at91sam3x* support) * * * and Jim Norris * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ****************************************************************************/ /* Some of the the lower level code was based on code supplied by * ATMEL under this copyright. */ /* BEGIN ATMEL COPYRIGHT */ /* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2009, Atmel Corporation * * 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 disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL 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. * ---------------------------------------------------------------------------- */ /* END ATMEL COPYRIGHT */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #define REG_NAME_WIDTH (12) /* at91sam3u series (has one or two flash banks) */ #define FLASH_BANK0_BASE_U 0x00080000 #define FLASH_BANK1_BASE_U 0x00100000 /* at91sam3s series (has always one flash bank) */ #define FLASH_BANK_BASE_S 0x00400000 /* at91sam3sd series (has always two flash banks) */ #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S #define FLASH_BANK1_BASE_512K_SD (FLASH_BANK0_BASE_SD+(512*1024/2)) /* at91sam3n series (has always one flash bank) */ #define FLASH_BANK_BASE_N 0x00400000 /* at91sam3a/x series has two flash banks*/ #define FLASH_BANK0_BASE_AX 0x00080000 /*Bank 1 of the at91sam3a/x series starts at 0x00080000 + half flash size*/ #define FLASH_BANK1_BASE_256K_AX 0x000A0000 #define FLASH_BANK1_BASE_512K_AX 0x000C0000 #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ #define AT91C_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */ #define AT91C_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page and Write Page then Lock */ #define AT91C_EFC_FCMD_EA (0x5) /* (EFC) Erase All */ /* cmd6 is not present in the at91sam3u4/2/1 data sheet table 17-2 */ /* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */ /* cmd7 is not present in the at91sam3u4/2/1 data sheet table 17-2 */ /* #define AT91C_EFC_FCMD_EPA (0x7) // (EFC) Erase pages? */ #define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */ #define AT91C_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */ #define AT91C_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */ #define AT91C_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */ #define AT91C_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */ #define AT91C_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */ #define AT91C_EFC_FCMD_STUI (0xE) /* (EFC) Start Read Unique ID */ #define AT91C_EFC_FCMD_SPUI (0xF) /* (EFC) Stop Read Unique ID */ #define offset_EFC_FMR 0 #define offset_EFC_FCR 4 #define offset_EFC_FSR 8 #define offset_EFC_FRR 12 extern struct flash_driver at91sam3_flash; static float _tomhz(uint32_t freq_hz) { float f; f = ((float)(freq_hz)) / 1000000.0; return f; } /* How the chip is configured. */ struct sam3_cfg { uint32_t unique_id[4]; uint32_t slow_freq; uint32_t rc_freq; uint32_t mainosc_freq; uint32_t plla_freq; uint32_t mclk_freq; uint32_t cpu_freq; uint32_t fclk_freq; uint32_t pclk0_freq; uint32_t pclk1_freq; uint32_t pclk2_freq; #define SAM3_CHIPID_CIDR (0x400E0740) uint32_t CHIPID_CIDR; #define SAM3_CHIPID_CIDR2 (0x400E0940) /*SAM3X and SAM3A cidr at this address*/ uint32_t CHIPID_CIDR2; #define SAM3_CHIPID_EXID (0x400E0744) uint32_t CHIPID_EXID; #define SAM3_CHIPID_EXID2 (0x400E0944) /*SAM3X and SAM3A cidr at this address*/ uint32_t CHIPID_EXID2; #define SAM3_PMC_BASE (0x400E0400) #define SAM3_PMC_SCSR (SAM3_PMC_BASE + 0x0008) uint32_t PMC_SCSR; #define SAM3_PMC_PCSR (SAM3_PMC_BASE + 0x0018) uint32_t PMC_PCSR; #define SAM3_CKGR_UCKR (SAM3_PMC_BASE + 0x001c) uint32_t CKGR_UCKR; #define SAM3_CKGR_MOR (SAM3_PMC_BASE + 0x0020) uint32_t CKGR_MOR; #define SAM3_CKGR_MCFR (SAM3_PMC_BASE + 0x0024) uint32_t CKGR_MCFR; #define SAM3_CKGR_PLLAR (SAM3_PMC_BASE + 0x0028) uint32_t CKGR_PLLAR; #define SAM3_PMC_MCKR (SAM3_PMC_BASE + 0x0030) uint32_t PMC_MCKR; #define SAM3_PMC_PCK0 (SAM3_PMC_BASE + 0x0040) uint32_t PMC_PCK0; #define SAM3_PMC_PCK1 (SAM3_PMC_BASE + 0x0044) uint32_t PMC_PCK1; #define SAM3_PMC_PCK2 (SAM3_PMC_BASE + 0x0048) uint32_t PMC_PCK2; #define SAM3_PMC_SR (SAM3_PMC_BASE + 0x0068) uint32_t PMC_SR; #define SAM3_PMC_IMR (SAM3_PMC_BASE + 0x006c) uint32_t PMC_IMR; #define SAM3_PMC_FSMR (SAM3_PMC_BASE + 0x0070) uint32_t PMC_FSMR; #define SAM3_PMC_FSPR (SAM3_PMC_BASE + 0x0074) uint32_t PMC_FSPR; }; /* * The AT91SAM3N data sheet 04-Oct-2010, AT91SAM3U data sheet 22-Aug-2011 * and AT91SAM3S data sheet 09-Feb-2011 state that for flash writes * the flash wait state (FWS) should be set to 6. It seems like that the * cause of the problem is not the flash itself, but the flash write * buffer. Ie the wait states have to be set before writing into the * buffer. * Tested and confirmed with SAM3N and SAM3U */ struct sam3_bank_private { int probed; /* DANGER: THERE ARE DRAGONS HERE.. */ /* NOTE: If you add more 'ghost' pointers */ /* be aware that you must *manually* update */ /* these pointers in the function sam3_GetDetails() */ /* See the comment "Here there be dragons" */ /* so we can find the chip we belong to */ struct sam3_chip *pChip; /* so we can find the original bank pointer */ struct flash_bank *pBank; unsigned bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; unsigned size_bytes; unsigned nsectors; unsigned sector_size; unsigned page_size; }; struct sam3_chip_details { /* THERE ARE DRAGONS HERE.. */ /* note: If you add pointers here */ /* be careful about them as they */ /* may need to be updated inside */ /* the function: "sam3_GetDetails() */ /* which copy/overwrites the */ /* 'runtime' copy of this structure */ uint32_t chipid_cidr; const char *name; unsigned n_gpnvms; #define SAM3_N_NVM_BITS 3 unsigned gpnvm[SAM3_N_NVM_BITS]; unsigned total_flash_size; unsigned total_sram_size; unsigned n_banks; #define SAM3_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam3_bank_private bank[SAM3_MAX_FLASH_BANKS]; }; struct sam3_chip { struct sam3_chip *next; int probed; /* this is "initialized" from the global const structure */ struct sam3_chip_details details; struct target *target; struct sam3_cfg cfg; }; struct sam3_reg_list { uint32_t address; size_t struct_offset; const char *name; void (*explain_func)(struct sam3_chip *pInfo); }; static struct sam3_chip *all_sam3_chips; static struct sam3_chip *get_current_sam3(struct command_context *cmd_ctx) { struct target *t; static struct sam3_chip *p; t = get_current_target(cmd_ctx); if (!t) { command_print(cmd_ctx, "No current target?"); return NULL; } p = all_sam3_chips; if (!p) { /* this should not happen */ /* the command is not registered until the chip is created? */ command_print(cmd_ctx, "No SAM3 chips exist?"); return NULL; } while (p) { if (p->target == t) return p; p = p->next; } command_print(cmd_ctx, "Cannot find SAM3 chip?"); return NULL; } /* these are used to *initialize* the "pChip->details" structure. */ static const struct sam3_chip_details all_sam3_details[] = { /* Start at91sam3u* series */ { .chipid_cidr = 0x28100960, .name = "at91sam3u4e", .total_flash_size = 256 * 1024, .total_sram_size = 52 * 1024, .n_gpnvms = 3, .n_banks = 2, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_U, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, }, }, { .chipid_cidr = 0x281a0760, .name = "at91sam3u2e", .total_flash_size = 128 * 1024, .total_sram_size = 36 * 1024, .n_gpnvms = 2, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28190560, .name = "at91sam3u1e", .total_flash_size = 64 * 1024, .total_sram_size = 20 * 1024, .n_gpnvms = 2, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 8, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28000960, .name = "at91sam3u4c", .total_flash_size = 256 * 1024, .total_sram_size = 52 * 1024, .n_gpnvms = 3, .n_banks = 2, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ { { /* .bank[0] = { */ .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_U, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, }, }, { .chipid_cidr = 0x280a0760, .name = "at91sam3u2c", .total_flash_size = 128 * 1024, .total_sram_size = 36 * 1024, .n_gpnvms = 2, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 16, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28090560, .name = "at91sam3u1c", .total_flash_size = 64 * 1024, .total_sram_size = 20 * 1024, .n_gpnvms = 2, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_U, .controller_address = 0x400e0800, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 8, .sector_size = 8192, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /* Start at91sam3s* series */ /* Note: The preliminary at91sam3s datasheet says on page 302 */ /* that the flash controller is at address 0x400E0800. */ /* This is _not_ the case, the controller resides at address 0x400e0a00. */ { .chipid_cidr = 0x28A00960, .name = "at91sam3s4c", .total_flash_size = 256 * 1024, .total_sram_size = 48 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28900960, .name = "at91sam3s4b", .total_flash_size = 256 * 1024, .total_sram_size = 48 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28800960, .name = "at91sam3s4a", .total_flash_size = 256 * 1024, .total_sram_size = 48 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28AA0760, .name = "at91sam3s2c", .total_flash_size = 128 * 1024, .total_sram_size = 32 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x289A0760, .name = "at91sam3s2b", .total_flash_size = 128 * 1024, .total_sram_size = 32 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x298B0A60, .name = "at91sam3sd8a", .total_flash_size = 512 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, }, }, { .chipid_cidr = 0x299B0A60, .name = "at91sam3sd8b", .total_flash_size = 512 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, }, }, { .chipid_cidr = 0x29ab0a60, .name = "at91sam3sd8c", .total_flash_size = 512 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, }, }, { .chipid_cidr = 0x288A0760, .name = "at91sam3s2a", .total_flash_size = 128 * 1024, .total_sram_size = 32 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28A90560, .name = "at91sam3s1c", .total_flash_size = 64 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28990560, .name = "at91sam3s1b", .total_flash_size = 64 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28890560, .name = "at91sam3s1a", .total_flash_size = 64 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x288B0A60, .name = "at91sam3s8a", .total_flash_size = 256 * 2048, .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 2048, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x289B0A60, .name = "at91sam3s8b", .total_flash_size = 256 * 2048, .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 2048, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x28AB0A60, .name = "at91sam3s8c", .total_flash_size = 256 * 2048, .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 2048, .nsectors = 16, .sector_size = 32768, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /* Start at91sam3n* series */ { .chipid_cidr = 0x29540960, .name = "at91sam3n4c", .total_flash_size = 256 * 1024, .total_sram_size = 24 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29440960, .name = "at91sam3n4b", .total_flash_size = 256 * 1024, .total_sram_size = 24 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29340960, .name = "at91sam3n4a", .total_flash_size = 256 * 1024, .total_sram_size = 24 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29590760, .name = "at91sam3n2c", .total_flash_size = 128 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29490760, .name = "at91sam3n2b", .total_flash_size = 128 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29390760, .name = "at91sam3n2a", .total_flash_size = 128 * 1024, .total_sram_size = 16 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29580560, .name = "at91sam3n1c", .total_flash_size = 64 * 1024, .total_sram_size = 8 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29480560, .name = "at91sam3n1b", .total_flash_size = 64 * 1024, .total_sram_size = 8 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29380560, .name = "at91sam3n1a", .total_flash_size = 64 * 1024, .total_sram_size = 8 * 1024, .n_gpnvms = 3, .n_banks = 1, /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 64 * 1024, .nsectors = 4, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29480360, .name = "at91sam3n0b", .total_flash_size = 32 * 1024, .total_sram_size = 8 * 1024, .n_gpnvms = 3, .n_banks = 1, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 32 * 1024, .nsectors = 2, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29380360, .name = "at91sam3n0a", .total_flash_size = 32 * 1024, .total_sram_size = 8 * 1024, .n_gpnvms = 3, .n_banks = 1, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 32 * 1024, .nsectors = 2, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29450260, .name = "at91sam3n00b", .total_flash_size = 16 * 1024, .total_sram_size = 4 * 1024, .n_gpnvms = 3, .n_banks = 1, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 16 * 1024, .nsectors = 1, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, { .chipid_cidr = 0x29350260, .name = "at91sam3n00a", .total_flash_size = 16 * 1024, .total_sram_size = 4 * 1024, .n_gpnvms = 3, .n_banks = 1, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_N, .controller_address = 0x400e0A00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 16 * 1024, .nsectors = 1, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /* Start at91sam3a series*/ /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ { .chipid_cidr = 0x283E0A60, .name = "at91sam3a8c", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, }, }, { .chipid_cidr = 0x283B0960, .name = "at91sam3a4c", .total_flash_size = 256 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_256K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, }, }, /* Start at91sam3x* series */ /* System boots at address 0x0 */ /* gpnvm[1] = selects boot code */ /* if gpnvm[1] == 0 */ /* boot is via "SAMBA" (rom) */ /* else */ /* boot is via FLASH */ /* Selection is via gpnvm[2] */ /* endif */ /* */ /* NOTE: banks 0 & 1 switch places */ /* if gpnvm[2] == 0 */ /* Bank0 is the boot rom */ /* else */ /* Bank1 is the boot rom */ /* endif */ /*at91sam3x8h - ES has an incorrect CIDR of 0x286E0A20*/ { .chipid_cidr = 0x286E0A20, .name = "at91sam3x8h - ES", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, }, }, /*at91sam3x8h - ES2 and up uses the correct CIDR of 0x286E0A60*/ { .chipid_cidr = 0x286E0A60, .name = "at91sam3x8h", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, }, }, { .chipid_cidr = 0x285E0A60, .name = "at91sam3x8e", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, }, }, { .chipid_cidr = 0x284E0A60, .name = "at91sam3x8c", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_512K_AX , .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 16, .sector_size = 16384, .page_size = 256, }, }, }, { .chipid_cidr = 0x285B0960, .name = "at91sam3x4e", .total_flash_size = 256 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_256K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, }, }, { .chipid_cidr = 0x284B0960, .name = "at91sam3x4c", .total_flash_size = 256 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 3, .n_banks = 2, { /* .bank[0] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_AX, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_256K_AX, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 128 * 1024, .nsectors = 8, .sector_size = 16384, .page_size = 256, }, }, }, /* terminate */ { .chipid_cidr = 0, .name = NULL, } }; /* Globals above */ /*********************************************************************** ********************************************************************** ********************************************************************** ********************************************************************** ********************************************************************** **********************************************************************/ /* *ATMEL* style code - from the SAM3 driver code */ /** * Get the current status of the EEFC and * the value of some status bits (LOCKE, PROGE). * @param pPrivate - info about the bank * @param v - result goes here */ static int EFC_GetStatus(struct sam3_bank_private *pPrivate, uint32_t *v) { int r; r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address + offset_EFC_FSR, v); LOG_DEBUG("Status: 0x%08x (lockerror: %d, cmderror: %d, ready: %d)", (unsigned int)(*v), ((unsigned int)((*v >> 2) & 1)), ((unsigned int)((*v >> 1) & 1)), ((unsigned int)((*v >> 0) & 1))); return r; } /** * Get the result of the last executed command. * @param pPrivate - info about the bank * @param v - result goes here */ static int EFC_GetResult(struct sam3_bank_private *pPrivate, uint32_t *v) { int r; uint32_t rv; r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address + offset_EFC_FRR, &rv); if (v) *v = rv; LOG_DEBUG("Result: 0x%08x", ((unsigned int)(rv))); return r; } static int EFC_StartCommand(struct sam3_bank_private *pPrivate, unsigned command, unsigned argument) { uint32_t n, v; int r; int retry; retry = 0; do_retry: /* Check command & argument */ switch (command) { case AT91C_EFC_FCMD_WP: case AT91C_EFC_FCMD_WPL: case AT91C_EFC_FCMD_EWP: case AT91C_EFC_FCMD_EWPL: /* case AT91C_EFC_FCMD_EPL: */ /* case AT91C_EFC_FCMD_EPA: */ case AT91C_EFC_FCMD_SLB: case AT91C_EFC_FCMD_CLB: n = (pPrivate->size_bytes / pPrivate->page_size); if (argument >= n) LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); break; case AT91C_EFC_FCMD_SFB: case AT91C_EFC_FCMD_CFB: if (argument >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs", pPrivate->pChip->details.n_gpnvms); } break; case AT91C_EFC_FCMD_GETD: case AT91C_EFC_FCMD_EA: case AT91C_EFC_FCMD_GLB: case AT91C_EFC_FCMD_GFB: case AT91C_EFC_FCMD_STUI: case AT91C_EFC_FCMD_SPUI: if (argument != 0) LOG_ERROR("Argument is meaningless for cmd: %d", command); break; default: LOG_ERROR("Unknown command %d", command); break; } if (command == AT91C_EFC_FCMD_SPUI) { /* this is a very special situation. */ /* Situation (1) - error/retry - see below */ /* And we are being called recursively */ /* Situation (2) - normal, finished reading unique id */ } else { /* it should be "ready" */ EFC_GetStatus(pPrivate, &v); if (v & 1) { /* then it is ready */ /* we go on */ } else { if (retry) { /* we have done this before */ /* the controller is not responding. */ LOG_ERROR("flash controller(%d) is not ready! Error", pPrivate->bank_number); return ERROR_FAIL; } else { retry++; LOG_ERROR("Flash controller(%d) is not ready, attempting reset", pPrivate->bank_number); /* we do that by issuing the *STOP* command */ EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0); /* above is recursive, and further recursion is blocked by */ /* if (command == AT91C_EFC_FCMD_SPUI) above */ goto do_retry; } } } v = (0x5A << 24) | (argument << 8) | command; LOG_DEBUG("Command: 0x%08x", ((unsigned int)(v))); r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address + offset_EFC_FCR, v); if (r != ERROR_OK) LOG_DEBUG("Error Write failed"); return r; } /** * Performs the given command and wait until its completion (or an error). * @param pPrivate - info about the bank * @param command - Command to perform. * @param argument - Optional command argument. * @param status - put command status bits here */ static int EFC_PerformCommand(struct sam3_bank_private *pPrivate, unsigned command, unsigned argument, uint32_t *status) { int r; uint32_t v; long long ms_now, ms_end; /* default */ if (status) *status = 0; r = EFC_StartCommand(pPrivate, command, argument); if (r != ERROR_OK) return r; ms_end = 500 + timeval_ms(); do { r = EFC_GetStatus(pPrivate, &v); if (r != ERROR_OK) return r; ms_now = timeval_ms(); if (ms_now > ms_end) { /* error */ LOG_ERROR("Command timeout"); return ERROR_FAIL; } } while ((v & 1) == 0); /* error bits.. */ if (status) *status = (v & 0x6); return ERROR_OK; } /** * Read the unique ID. * @param pPrivate - info about the bank * The unique ID is stored in the 'pPrivate' structure. */ static int FLASHD_ReadUniqueID(struct sam3_bank_private *pPrivate) { int r; uint32_t v; int x; /* assume 0 */ pPrivate->pChip->cfg.unique_id[0] = 0; pPrivate->pChip->cfg.unique_id[1] = 0; pPrivate->pChip->cfg.unique_id[2] = 0; pPrivate->pChip->cfg.unique_id[3] = 0; LOG_DEBUG("Begin"); r = EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_STUI, 0); if (r < 0) return r; for (x = 0; x < 4; x++) { r = target_read_u32(pPrivate->pChip->target, pPrivate->pBank->base + (x * 4), &v); if (r < 0) return r; pPrivate->pChip->cfg.unique_id[x] = v; } r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0, NULL); LOG_DEBUG("End: R=%d, id = 0x%08x, 0x%08x, 0x%08x, 0x%08x", r, (unsigned int)(pPrivate->pChip->cfg.unique_id[0]), (unsigned int)(pPrivate->pChip->cfg.unique_id[1]), (unsigned int)(pPrivate->pChip->cfg.unique_id[2]), (unsigned int)(pPrivate->pChip->cfg.unique_id[3])); return r; } /** * Erases the entire flash. * @param pPrivate - the info about the bank. */ static int FLASHD_EraseEntireBank(struct sam3_bank_private *pPrivate) { LOG_DEBUG("Here"); return EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_EA, 0, NULL); } /** * Gets current GPNVM state. * @param pPrivate - info about the bank. * @param gpnvm - GPNVM bit index. * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ static int FLASHD_GetGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm, unsigned *puthere) { uint32_t v; int r; LOG_DEBUG("Here"); if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } /* Get GPNVMs status */ r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GFB, 0, NULL); if (r != ERROR_OK) { LOG_ERROR("Failed"); return r; } r = EFC_GetResult(pPrivate, &v); if (puthere) { /* Check if GPNVM is set */ /* get the bit and make it a 0/1 */ *puthere = (v >> gpnvm) & 1; } return r; } /** * Clears the selected GPNVM bit. * @param pPrivate info about the bank * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ static int FLASHD_ClrGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm) { int r; unsigned v; LOG_DEBUG("Here"); if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v); if (r != ERROR_OK) { LOG_DEBUG("Failed: %d", r); return r; } r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CFB, gpnvm, NULL); LOG_DEBUG("End: %d", r); return r; } /** * Sets the selected GPNVM bit. * @param pPrivate info about the bank * @param gpnvm GPNVM index. */ static int FLASHD_SetGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm) { int r; unsigned v; if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v); if (r != ERROR_OK) return r; if (v) { /* already set */ r = ERROR_OK; } else { /* set it */ r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SFB, gpnvm, NULL); } return r; } /** * Returns a bit field (at most 64) of locked regions within a page. * @param pPrivate info about the bank * @param v where to store locked bits */ static int FLASHD_GetLockBits(struct sam3_bank_private *pPrivate, uint32_t *v) { int r; LOG_DEBUG("Here"); r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GLB, 0, NULL); if (r == ERROR_OK) r = EFC_GetResult(pPrivate, v); LOG_DEBUG("End: %d", r); return r; } /** * Unlocks all the regions in the given address range. * @param pPrivate info about the bank * @param start_sector first sector to unlock * @param end_sector last (inclusive) to unlock */ static int FLASHD_Unlock(struct sam3_bank_private *pPrivate, unsigned start_sector, unsigned end_sector) { int r; uint32_t status; uint32_t pg; uint32_t pages_per_sector; pages_per_sector = pPrivate->sector_size / pPrivate->page_size; /* Unlock all pages */ while (start_sector <= end_sector) { pg = start_sector * pages_per_sector; r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CLB, pg, &status); if (r != ERROR_OK) return r; start_sector++; } return ERROR_OK; } /** * Locks regions * @param pPrivate - info about the bank * @param start_sector - first sector to lock * @param end_sector - last sector (inclusive) to lock */ static int FLASHD_Lock(struct sam3_bank_private *pPrivate, unsigned start_sector, unsigned end_sector) { uint32_t status; uint32_t pg; uint32_t pages_per_sector; int r; pages_per_sector = pPrivate->sector_size / pPrivate->page_size; /* Lock all pages */ while (start_sector <= end_sector) { pg = start_sector * pages_per_sector; r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SLB, pg, &status); if (r != ERROR_OK) return r; start_sector++; } return ERROR_OK; } /****** END SAM3 CODE ********/ /* begin helpful debug code */ /* print the fieldname, the field value, in dec & hex, and return field value */ static uint32_t sam3_reg_fieldname(struct sam3_chip *pChip, const char *regname, uint32_t value, unsigned shift, unsigned width) { uint32_t v; int hwidth, dwidth; /* extract the field */ v = value >> shift; v = v & ((1 << width)-1); if (width <= 16) { hwidth = 4; dwidth = 5; } else { hwidth = 8; dwidth = 12; } /* show the basics */ LOG_USER_N("\t%*s: %*" PRIu32 " [0x%0*" PRIx32 "] ", REG_NAME_WIDTH, regname, dwidth, v, hwidth, v); return v; } static const char _unknown[] = "unknown"; static const char *const eproc_names[] = { _unknown, /* 0 */ "arm946es", /* 1 */ "arm7tdmi", /* 2 */ "cortex-m3", /* 3 */ "arm920t", /* 4 */ "arm926ejs", /* 5 */ _unknown, /* 6 */ _unknown, /* 7 */ _unknown, /* 8 */ _unknown, /* 9 */ _unknown, /* 10 */ _unknown, /* 11 */ _unknown, /* 12 */ _unknown, /* 13 */ _unknown, /* 14 */ _unknown, /* 15 */ }; #define nvpsize2 nvpsize /* these two tables are identical */ static const char *const nvpsize[] = { "none", /* 0 */ "8K bytes", /* 1 */ "16K bytes", /* 2 */ "32K bytes", /* 3 */ _unknown, /* 4 */ "64K bytes", /* 5 */ _unknown, /* 6 */ "128K bytes", /* 7 */ _unknown, /* 8 */ "256K bytes", /* 9 */ "512K bytes", /* 10 */ _unknown, /* 11 */ "1024K bytes", /* 12 */ _unknown, /* 13 */ "2048K bytes", /* 14 */ _unknown, /* 15 */ }; static const char *const sramsize[] = { "48K Bytes", /* 0 */ "1K Bytes", /* 1 */ "2K Bytes", /* 2 */ "6K Bytes", /* 3 */ "112K Bytes", /* 4 */ "4K Bytes", /* 5 */ "80K Bytes", /* 6 */ "160K Bytes", /* 7 */ "8K Bytes", /* 8 */ "16K Bytes", /* 9 */ "32K Bytes", /* 10 */ "64K Bytes", /* 11 */ "128K Bytes", /* 12 */ "256K Bytes", /* 13 */ "96K Bytes", /* 14 */ "512K Bytes", /* 15 */ }; static const struct archnames { unsigned value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, { 0x37, "CAP7 Series" }, { 0x39, "CAP9 Series" }, { 0x3B, "CAP11 Series" }, { 0x40, "AT91x40 Series" }, { 0x42, "AT91x42 Series" }, { 0x55, "AT91x55 Series" }, { 0x60, "AT91SAM7Axx Series" }, { 0x61, "AT91SAM7AQxx Series" }, { 0x63, "AT91x63 Series" }, { 0x70, "AT91SAM7Sxx Series" }, { 0x71, "AT91SAM7XCxx Series" }, { 0x72, "AT91SAM7SExx Series" }, { 0x73, "AT91SAM7Lxx Series" }, { 0x75, "AT91SAM7Xxx Series" }, { 0x76, "AT91SAM7SLxx Series" }, { 0x80, "ATSAM3UxC Series (100-pin version)" }, { 0x81, "ATSAM3UxE Series (144-pin version)" }, { 0x83, "ATSAM3AxC Series (100-pin version)" }, { 0x84, "ATSAM3XxC Series (100-pin version)" }, { 0x85, "ATSAM3XxE Series (144-pin version)" }, { 0x86, "ATSAM3XxG Series (208/217-pin version)" }, { 0x88, "ATSAM3SxA Series (48-pin version)" }, { 0x89, "ATSAM3SxB Series (64-pin version)" }, { 0x8A, "ATSAM3SxC Series (100-pin version)" }, { 0x92, "AT91x92 Series" }, { 0x93, "ATSAM3NxA Series (48-pin version)" }, { 0x94, "ATSAM3NxB Series (64-pin version)" }, { 0x95, "ATSAM3NxC Series (100-pin version)" }, { 0x98, "ATSAM3SDxA Series (48-pin version)" }, { 0x99, "ATSAM3SDxB Series (64-pin version)" }, { 0x9A, "ATSAM3SDxC Series (100-pin version)" }, { 0xA5, "ATSAM5A" }, { 0xF0, "AT75Cxx Series" }, { -1, NULL }, }; static const char *const nvptype[] = { "rom", /* 0 */ "romless or onchip flash", /* 1 */ "embedded flash memory",/* 2 */ "rom(nvpsiz) + embedded flash (nvpsiz2)", /* 3 */ "sram emulating flash", /* 4 */ _unknown, /* 5 */ _unknown, /* 6 */ _unknown, /* 7 */ }; static const char *_yes_or_no(uint32_t v) { if (v) return "YES"; else return "NO"; } static const char *const _rc_freq[] = { "4 MHz", "8 MHz", "12 MHz", "reserved" }; static void sam3_explain_ckgr_mor(struct sam3_chip *pChip) { uint32_t v; uint32_t rcen; v = sam3_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1); LOG_USER("(main xtal enabled: %s)", _yes_or_no(v)); v = sam3_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1); LOG_USER("(main osc bypass: %s)", _yes_or_no(v)); rcen = sam3_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 3, 1); LOG_USER("(onchip RC-OSC enabled: %s)", _yes_or_no(rcen)); v = sam3_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3); LOG_USER("(onchip RC-OSC freq: %s)", _rc_freq[v]); pChip->cfg.rc_freq = 0; if (rcen) { switch (v) { default: pChip->cfg.rc_freq = 0; break; case 0: pChip->cfg.rc_freq = 4 * 1000 * 1000; break; case 1: pChip->cfg.rc_freq = 8 * 1000 * 1000; break; case 2: pChip->cfg.rc_freq = 12 * 1000 * 1000; break; } } v = sam3_reg_fieldname(pChip, "MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8); LOG_USER("(startup clks, time= %f uSecs)", ((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq))); v = sam3_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1); LOG_USER("(mainosc source: %s)", v ? "external xtal" : "internal RC"); v = sam3_reg_fieldname(pChip, "CFDEN", pChip->cfg.CKGR_MOR, 25, 1); LOG_USER("(clock failure enabled: %s)", _yes_or_no(v)); } static void sam3_explain_chipid_cidr(struct sam3_chip *pChip) { int x; uint32_t v; const char *cp; sam3_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5); LOG_USER_N("\n"); v = sam3_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3); LOG_USER("%s", eproc_names[v]); v = sam3_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4); LOG_USER("%s", nvpsize[v]); v = sam3_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4); LOG_USER("%s", nvpsize2[v]); v = sam3_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16, 4); LOG_USER("%s", sramsize[v]); v = sam3_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8); cp = _unknown; for (x = 0; archnames[x].name; x++) { if (v == archnames[x].value) { cp = archnames[x].name; break; } } LOG_USER("%s", cp); v = sam3_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3); LOG_USER("%s", nvptype[v]); v = sam3_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1); LOG_USER("(exists: %s)", _yes_or_no(v)); } static void sam3_explain_ckgr_mcfr(struct sam3_chip *pChip) { uint32_t v; v = sam3_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1); LOG_USER("(main ready: %s)", _yes_or_no(v)); v = sam3_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16); v = (v * pChip->cfg.slow_freq) / 16; pChip->cfg.mainosc_freq = v; LOG_USER("(%3.03f Mhz (%" PRIu32 ".%03" PRIu32 "khz slowclk)", _tomhz(v), (uint32_t)(pChip->cfg.slow_freq / 1000), (uint32_t)(pChip->cfg.slow_freq % 1000)); } static void sam3_explain_ckgr_plla(struct sam3_chip *pChip) { uint32_t mula, diva; diva = sam3_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8); LOG_USER_N("\n"); mula = sam3_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11); LOG_USER_N("\n"); pChip->cfg.plla_freq = 0; if (mula == 0) LOG_USER("\tPLLA Freq: (Disabled,mula = 0)"); else if (diva == 0) LOG_USER("\tPLLA Freq: (Disabled,diva = 0)"); else if (diva >= 1) { pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1) / diva); LOG_USER("\tPLLA Freq: %3.03f MHz", _tomhz(pChip->cfg.plla_freq)); } } static void sam3_explain_mckr(struct sam3_chip *pChip) { uint32_t css, pres, fin = 0; int pdiv = 0; const char *cp = NULL; css = sam3_reg_fieldname(pChip, "CSS", pChip->cfg.PMC_MCKR, 0, 2); switch (css & 3) { case 0: fin = pChip->cfg.slow_freq; cp = "slowclk"; break; case 1: fin = pChip->cfg.mainosc_freq; cp = "mainosc"; break; case 2: fin = pChip->cfg.plla_freq; cp = "plla"; break; case 3: if (pChip->cfg.CKGR_UCKR & (1 << 16)) { fin = 480 * 1000 * 1000; cp = "upll"; } else { fin = 0; cp = "upll (*ERROR* UPLL is disabled)"; } break; default: assert(0); break; } LOG_USER("%s (%3.03f Mhz)", cp, _tomhz(fin)); pres = sam3_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3); switch (pres & 0x07) { case 0: pdiv = 1; cp = "selected clock"; break; case 1: pdiv = 2; cp = "clock/2"; break; case 2: pdiv = 4; cp = "clock/4"; break; case 3: pdiv = 8; cp = "clock/8"; break; case 4: pdiv = 16; cp = "clock/16"; break; case 5: pdiv = 32; cp = "clock/32"; break; case 6: pdiv = 64; cp = "clock/64"; break; case 7: pdiv = 6; cp = "clock/6"; break; default: assert(0); break; } LOG_USER("(%s)", cp); fin = fin / pdiv; /* sam3 has a *SINGLE* clock - */ /* other at91 series parts have divisors for these. */ pChip->cfg.cpu_freq = fin; pChip->cfg.mclk_freq = fin; pChip->cfg.fclk_freq = fin; LOG_USER("\t\tResult CPU Freq: %3.03f", _tomhz(fin)); } #if 0 static struct sam3_chip *target2sam3(struct target *pTarget) { struct sam3_chip *pChip; if (pTarget == NULL) return NULL; pChip = all_sam3_chips; while (pChip) { if (pChip->target == pTarget) break; /* return below */ else pChip = pChip->next; } return pChip; } #endif static uint32_t *sam3_get_reg_ptr(struct sam3_cfg *pCfg, const struct sam3_reg_list *pList) { /* this function exists to help */ /* keep funky offsetof() errors */ /* and casting from causing bugs */ /* By using prototypes - we can detect what would */ /* be casting errors. */ return (uint32_t *)(void *)(((char *)(pCfg)) + pList->struct_offset); } #define SAM3_ENTRY(NAME, FUNC) { .address = SAM3_ ## NAME, .struct_offset = offsetof( \ struct sam3_cfg, \ NAME), # NAME, FUNC } static const struct sam3_reg_list sam3_all_regs[] = { SAM3_ENTRY(CKGR_MOR, sam3_explain_ckgr_mor), SAM3_ENTRY(CKGR_MCFR, sam3_explain_ckgr_mcfr), SAM3_ENTRY(CKGR_PLLAR, sam3_explain_ckgr_plla), SAM3_ENTRY(CKGR_UCKR, NULL), SAM3_ENTRY(PMC_FSMR, NULL), SAM3_ENTRY(PMC_FSPR, NULL), SAM3_ENTRY(PMC_IMR, NULL), SAM3_ENTRY(PMC_MCKR, sam3_explain_mckr), SAM3_ENTRY(PMC_PCK0, NULL), SAM3_ENTRY(PMC_PCK1, NULL), SAM3_ENTRY(PMC_PCK2, NULL), SAM3_ENTRY(PMC_PCSR, NULL), SAM3_ENTRY(PMC_SCSR, NULL), SAM3_ENTRY(PMC_SR, NULL), SAM3_ENTRY(CHIPID_CIDR, sam3_explain_chipid_cidr), SAM3_ENTRY(CHIPID_CIDR2, sam3_explain_chipid_cidr), SAM3_ENTRY(CHIPID_EXID, NULL), SAM3_ENTRY(CHIPID_EXID2, NULL), /* TERMINATE THE LIST */ { .name = NULL } }; #undef SAM3_ENTRY static struct sam3_bank_private *get_sam3_bank_private(struct flash_bank *bank) { return bank->driver_priv; } /** * Given a pointer to where it goes in the structure, * determine the register name, address from the all registers table. */ static const struct sam3_reg_list *sam3_GetReg(struct sam3_chip *pChip, uint32_t *goes_here) { const struct sam3_reg_list *pReg; pReg = &(sam3_all_regs[0]); while (pReg->name) { uint32_t *pPossible; /* calculate where this one go.. */ /* it is "possibly" this register. */ pPossible = ((uint32_t *)(void *)(((char *)(&(pChip->cfg))) + pReg->struct_offset)); /* well? Is it this register */ if (pPossible == goes_here) { /* Jump for joy! */ return pReg; } /* next... */ pReg++; } /* This is *TOTAL*PANIC* - we are totally screwed. */ LOG_ERROR("INVALID SAM3 REGISTER"); return NULL; } static int sam3_ReadThisReg(struct sam3_chip *pChip, uint32_t *goes_here) { const struct sam3_reg_list *pReg; int r; pReg = sam3_GetReg(pChip, goes_here); if (!pReg) return ERROR_FAIL; r = target_read_u32(pChip->target, pReg->address, goes_here); if (r != ERROR_OK) { LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d", pReg->name, (unsigned)(pReg->address), r); } return r; } static int sam3_ReadAllRegs(struct sam3_chip *pChip) { int r; const struct sam3_reg_list *pReg; pReg = &(sam3_all_regs[0]); while (pReg->name) { r = sam3_ReadThisReg(pChip, sam3_get_reg_ptr(&(pChip->cfg), pReg)); if (r != ERROR_OK) { LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Error: %d", pReg->name, ((unsigned)(pReg->address)), r); return r; } pReg++; } /* Chip identification register * * Unfortunately, the chip identification register is not at * a constant address across all of the SAM3 series'. As a * consequence, a simple heuristic is used to find where it's * at... * * If the contents at the first address is zero, then we know * that the second address is where the chip id register is. * We can deduce this because for those SAM's that have the * chip id @ 0x400e0940, the first address, 0x400e0740, is * located in the memory map of the Power Management Controller * (PMC). Furthermore, the address is not used by the PMC. * So when read, the memory controller returns zero.*/ if (pChip->cfg.CHIPID_CIDR == 0) { /*Put the correct CIDR and EXID values in the pChip structure */ pChip->cfg.CHIPID_CIDR = pChip->cfg.CHIPID_CIDR2; pChip->cfg.CHIPID_EXID = pChip->cfg.CHIPID_EXID2; } return ERROR_OK; } static int sam3_GetInfo(struct sam3_chip *pChip) { const struct sam3_reg_list *pReg; uint32_t regval; pReg = &(sam3_all_regs[0]); while (pReg->name) { /* display all regs */ LOG_DEBUG("Start: %s", pReg->name); regval = *sam3_get_reg_ptr(&(pChip->cfg), pReg); LOG_USER("%*s: [0x%08" PRIx32 "] -> 0x%08" PRIx32, REG_NAME_WIDTH, pReg->name, pReg->address, regval); if (pReg->explain_func) (*(pReg->explain_func))(pChip); LOG_DEBUG("End: %s", pReg->name); pReg++; } LOG_USER(" rc-osc: %3.03f MHz", _tomhz(pChip->cfg.rc_freq)); LOG_USER(" mainosc: %3.03f MHz", _tomhz(pChip->cfg.mainosc_freq)); LOG_USER(" plla: %3.03f MHz", _tomhz(pChip->cfg.plla_freq)); LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq)); LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq)); LOG_USER(" UniqueId: 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32, pChip->cfg.unique_id[0], pChip->cfg.unique_id[1], pChip->cfg.unique_id[2], pChip->cfg.unique_id[3]); return ERROR_OK; } static int sam3_erase_check(struct flash_bank *bank) { int x; LOG_DEBUG("Here"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (0 == bank->num_sectors) { LOG_ERROR("Target: not supported/not probed"); return ERROR_FAIL; } LOG_INFO("sam3 - supports auto-erase, erase_check ignored"); for (x = 0; x < bank->num_sectors; x++) bank->sectors[x].is_erased = 1; LOG_DEBUG("Done"); return ERROR_OK; } static int sam3_protect_check(struct flash_bank *bank) { int r; uint32_t v = 0; unsigned x; struct sam3_bank_private *pPrivate; LOG_DEBUG("Begin"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam3_bank_private(bank); if (!pPrivate) { LOG_ERROR("no private for this bank?"); return ERROR_FAIL; } if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; r = FLASHD_GetLockBits(pPrivate, &v); if (r != ERROR_OK) { LOG_DEBUG("Failed: %d", r); return r; } for (x = 0; x < pPrivate->nsectors; x++) bank->sectors[x].is_protected = (!!(v & (1 << x))); LOG_DEBUG("Done"); return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command) { struct sam3_chip *pChip; pChip = all_sam3_chips; /* is this an existing chip? */ while (pChip) { if (pChip->target == bank->target) break; pChip = pChip->next; } if (!pChip) { /* this is a *NEW* chip */ pChip = calloc(1, sizeof(struct sam3_chip)); if (!pChip) { LOG_ERROR("NO RAM!"); return ERROR_FAIL; } pChip->target = bank->target; /* insert at head */ pChip->next = all_sam3_chips; all_sam3_chips = pChip; pChip->target = bank->target; /* assumption is this runs at 32khz */ pChip->cfg.slow_freq = 32768; pChip->probed = 0; } switch (bank->base) { default: LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x " "[at91sam3u series] or 0x%08x [at91sam3s series] or " "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )", ((unsigned int)(bank->base)), ((unsigned int)(FLASH_BANK0_BASE_U)), ((unsigned int)(FLASH_BANK1_BASE_U)), ((unsigned int)(FLASH_BANK_BASE_S)), ((unsigned int)(FLASH_BANK_BASE_N)), ((unsigned int)(FLASH_BANK0_BASE_AX)), ((unsigned int)(FLASH_BANK1_BASE_256K_AX)), ((unsigned int)(FLASH_BANK1_BASE_512K_AX))); return ERROR_FAIL; break; /* at91sam3s and at91sam3n series only has bank 0*/ /* at91sam3u and at91sam3ax series has the same address for bank 0*/ case FLASH_BANK_BASE_S: case FLASH_BANK0_BASE_U: bank->driver_priv = &(pChip->details.bank[0]); bank->bank_number = 0; pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pBank = bank; break; /* Bank 1 of at91sam3u or at91sam3ax series */ case FLASH_BANK1_BASE_U: case FLASH_BANK1_BASE_256K_AX: case FLASH_BANK1_BASE_512K_AX: bank->driver_priv = &(pChip->details.bank[1]); bank->bank_number = 1; pChip->details.bank[1].pChip = pChip; pChip->details.bank[1].pBank = bank; break; } /* we initialize after probing. */ return ERROR_OK; } static int sam3_GetDetails(struct sam3_bank_private *pPrivate) { const struct sam3_chip_details *pDetails; struct sam3_chip *pChip; struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS]; unsigned x; LOG_DEBUG("Begin"); pDetails = all_sam3_details; while (pDetails->name) { /* Compare cidr without version bits */ if (((pDetails->chipid_cidr ^ pPrivate->pChip->cfg.CHIPID_CIDR) & 0xFFFFFFE0) == 0) break; else pDetails++; } if (pDetails->name == NULL) { LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can ID this chip?)", (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR)); /* Help the victim, print details about the chip */ LOG_INFO("SAM3 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows", pPrivate->pChip->cfg.CHIPID_CIDR); sam3_explain_chipid_cidr(pPrivate->pChip); return ERROR_FAIL; } /* DANGER: THERE ARE DRAGONS HERE */ /* get our pChip - it is going */ /* to be over-written shortly */ pChip = pPrivate->pChip; /* Note that, in reality: */ /* */ /* pPrivate = &(pChip->details.bank[0]) */ /* or pPrivate = &(pChip->details.bank[1]) */ /* */ /* save the "bank" pointers */ for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++) saved_banks[x] = pChip->details.bank[x].pBank; /* Overwrite the "details" structure. */ memcpy(&(pPrivate->pChip->details), pDetails, sizeof(pPrivate->pChip->details)); /* now fix the ghosted pointers */ for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++) { pChip->details.bank[x].pChip = pChip; pChip->details.bank[x].pBank = saved_banks[x]; } /* update the *BANK*SIZE* */ LOG_DEBUG("End"); return ERROR_OK; } static int _sam3_probe(struct flash_bank *bank, int noise) { unsigned x; int r; struct sam3_bank_private *pPrivate; LOG_DEBUG("Begin: Bank: %d, Noise: %d", bank->bank_number, noise); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam3_bank_private(bank); if (!pPrivate) { LOG_ERROR("Invalid/unknown bank number"); return ERROR_FAIL; } r = sam3_ReadAllRegs(pPrivate->pChip); if (r != ERROR_OK) return r; LOG_DEBUG("Here"); if (pPrivate->pChip->probed) r = sam3_GetInfo(pPrivate->pChip); else r = sam3_GetDetails(pPrivate); if (r != ERROR_OK) return r; /* update the flash bank size */ for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++) { if (bank->base == pPrivate->pChip->details.bank[x].base_address) { bank->size = pPrivate->pChip->details.bank[x].size_bytes; break; } } if (bank->sectors == NULL) { bank->sectors = calloc(pPrivate->nsectors, (sizeof((bank->sectors)[0]))); if (bank->sectors == NULL) { LOG_ERROR("No memory!"); return ERROR_FAIL; } bank->num_sectors = pPrivate->nsectors; for (x = 0; ((int)(x)) < bank->num_sectors; x++) { bank->sectors[x].size = pPrivate->sector_size; bank->sectors[x].offset = x * (pPrivate->sector_size); /* mark as unknown */ bank->sectors[x].is_erased = -1; bank->sectors[x].is_protected = -1; } } pPrivate->probed = 1; r = sam3_protect_check(bank); if (r != ERROR_OK) return r; LOG_DEBUG("Bank = %d, nbanks = %d", pPrivate->bank_number, pPrivate->pChip->details.n_banks); if ((pPrivate->bank_number + 1) == pPrivate->pChip->details.n_banks) { /* read unique id, */ /* it appears to be associated with the *last* flash bank. */ FLASHD_ReadUniqueID(pPrivate); } return r; } static int sam3_probe(struct flash_bank *bank) { return _sam3_probe(bank, 1); } static int sam3_auto_probe(struct flash_bank *bank) { return _sam3_probe(bank, 0); } static int sam3_erase(struct flash_bank *bank, int first, int last) { struct sam3_bank_private *pPrivate; int r; LOG_DEBUG("Here"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } r = sam3_auto_probe(bank); if (r != ERROR_OK) { LOG_DEBUG("Here,r=%d", r); return r; } pPrivate = get_sam3_bank_private(bank); if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; if ((first == 0) && ((last + 1) == ((int)(pPrivate->nsectors)))) { /* whole chip */ LOG_DEBUG("Here"); return FLASHD_EraseEntireBank(pPrivate); } LOG_INFO("sam3 auto-erases while programming (request ignored)"); return ERROR_OK; } static int sam3_protect(struct flash_bank *bank, int set, int first, int last) { struct sam3_bank_private *pPrivate; int r; LOG_DEBUG("Here"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam3_bank_private(bank); if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; if (set) r = FLASHD_Lock(pPrivate, (unsigned)(first), (unsigned)(last)); else r = FLASHD_Unlock(pPrivate, (unsigned)(first), (unsigned)(last)); LOG_DEBUG("End: r=%d", r); return r; } static int sam3_page_read(struct sam3_bank_private *pPrivate, unsigned pagenum, uint8_t *buf) { uint32_t adr; int r; adr = pagenum * pPrivate->page_size; adr += pPrivate->base_address; r = target_read_memory(pPrivate->pChip->target, adr, 4, /* THIS*MUST*BE* in 32bit values */ pPrivate->page_size / 4, buf); if (r != ERROR_OK) LOG_ERROR("SAM3: Flash program failed to read page phys address: 0x%08x", (unsigned int)(adr)); return r; } static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; uint32_t fmr; /* EEFC Flash Mode Register */ int r; adr = pagenum * pPrivate->page_size; adr += pPrivate->base_address; /* Get flash mode register value */ r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr); if (r != ERROR_OK) LOG_DEBUG("Error Read failed: read flash mode register"); /* Clear flash wait state field */ fmr &= 0xfffff0ff; /* set FWS (flash wait states) field in the FMR (flash mode register) */ fmr |= (pPrivate->flash_wait_states << 8); LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr))); r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr); if (r != ERROR_OK) LOG_DEBUG("Error Write failed: set flash mode register"); LOG_DEBUG("Wr Page %u @ phys address: 0x%08x", pagenum, (unsigned int)(adr)); r = target_write_memory(pPrivate->pChip->target, adr, 4, /* THIS*MUST*BE* in 32bit values */ pPrivate->page_size / 4, buf); if (r != ERROR_OK) { LOG_ERROR("SAM3: Failed to write (buffer) page at phys address 0x%08x", (unsigned int)(adr)); return r; } r = EFC_PerformCommand(pPrivate, /* send Erase & Write Page */ AT91C_EFC_FCMD_EWP, pagenum, &status); if (r != ERROR_OK) LOG_ERROR("SAM3: Error performing Erase & Write page @ phys address 0x%08x", (unsigned int)(adr)); if (status & (1 << 2)) { LOG_ERROR("SAM3: Page @ Phys address 0x%08x is locked", (unsigned int)(adr)); return ERROR_FAIL; } if (status & (1 << 1)) { LOG_ERROR("SAM3: Flash Command error @phys address 0x%08x", (unsigned int)(adr)); return ERROR_FAIL; } return ERROR_OK; } static int sam3_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int n; unsigned page_cur; unsigned page_end; int r; unsigned page_offset; struct sam3_bank_private *pPrivate; uint8_t *pagebuffer; /* incase we bail further below, set this to null */ pagebuffer = NULL; /* ignore dumb requests */ if (count == 0) { r = ERROR_OK; goto done; } if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); r = ERROR_TARGET_NOT_HALTED; goto done; } pPrivate = get_sam3_bank_private(bank); if (!(pPrivate->probed)) { r = ERROR_FLASH_BANK_NOT_PROBED; goto done; } if ((offset + count) > pPrivate->size_bytes) { LOG_ERROR("Flash write error - past end of bank"); LOG_ERROR(" offset: 0x%08x, count 0x%08x, BankEnd: 0x%08x", (unsigned int)(offset), (unsigned int)(count), (unsigned int)(pPrivate->size_bytes)); r = ERROR_FAIL; goto done; } pagebuffer = malloc(pPrivate->page_size); if (!pagebuffer) { LOG_ERROR("No memory for %d Byte page buffer", (int)(pPrivate->page_size)); r = ERROR_FAIL; goto done; } /* what page do we start & end in? */ page_cur = offset / pPrivate->page_size; page_end = (offset + count - 1) / pPrivate->page_size; LOG_DEBUG("Offset: 0x%08x, Count: 0x%08x", (unsigned int)(offset), (unsigned int)(count)); LOG_DEBUG("Page start: %d, Page End: %d", (int)(page_cur), (int)(page_end)); /* Special case: all one page */ /* */ /* Otherwise: */ /* (1) non-aligned start */ /* (2) body pages */ /* (3) non-aligned end. */ /* Handle special case - all one page. */ if (page_cur == page_end) { LOG_DEBUG("Special case, all in one page"); r = sam3_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; page_offset = (offset & (pPrivate->page_size-1)); memcpy(pagebuffer + page_offset, buffer, count); r = sam3_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; r = ERROR_OK; goto done; } /* non-aligned start */ page_offset = offset & (pPrivate->page_size - 1); if (page_offset) { LOG_DEBUG("Not-Aligned start"); /* read the partial */ r = sam3_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; /* over-write with new data */ n = (pPrivate->page_size - page_offset); memcpy(pagebuffer + page_offset, buffer, n); r = sam3_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; count -= n; offset += n; buffer += n; page_cur++; } /* By checking that offset is correct here, we also fix a clang warning */ assert(offset % pPrivate->page_size == 0); /* intermediate large pages */ /* also - the final *terminal* */ /* if that terminal page is a full page */ LOG_DEBUG("Full Page Loop: cur=%d, end=%d, count = 0x%08x", (int)page_cur, (int)page_end, (unsigned int)(count)); while ((page_cur < page_end) && (count >= pPrivate->page_size)) { r = sam3_page_write(pPrivate, page_cur, buffer); if (r != ERROR_OK) goto done; count -= pPrivate->page_size; buffer += pPrivate->page_size; page_cur += 1; } /* terminal partial page? */ if (count) { LOG_DEBUG("Terminal partial page, count = 0x%08x", (unsigned int)(count)); /* we have a partial page */ r = sam3_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; /* data goes at start */ memcpy(pagebuffer, buffer, count); r = sam3_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; } LOG_DEBUG("Done!"); r = ERROR_OK; done: if (pagebuffer) free(pagebuffer); return r; } COMMAND_HANDLER(sam3_handle_info_command) { struct sam3_chip *pChip; pChip = get_current_sam3(CMD_CTX); if (!pChip) return ERROR_OK; unsigned x; int r; /* bank0 must exist before we can do anything */ if (pChip->details.bank[0].pBank == NULL) { x = 0; need_define: command_print(CMD_CTX, "Please define bank %d via command: flash bank %s ... ", x, at91sam3_flash.name); return ERROR_FAIL; } /* if bank 0 is not probed, then probe it */ if (!(pChip->details.bank[0].probed)) { r = sam3_auto_probe(pChip->details.bank[0].pBank); if (r != ERROR_OK) return ERROR_FAIL; } /* above guarantees the "chip details" structure is valid */ /* and thus, bank private areas are valid */ /* and we have a SAM3 chip, what a concept! */ /* auto-probe other banks, 0 done above */ for (x = 1; x < SAM3_MAX_FLASH_BANKS; x++) { /* skip banks not present */ if (!(pChip->details.bank[x].present)) continue; if (pChip->details.bank[x].pBank == NULL) goto need_define; if (pChip->details.bank[x].probed) continue; r = sam3_auto_probe(pChip->details.bank[x].pBank); if (r != ERROR_OK) return r; } r = sam3_GetInfo(pChip); if (r != ERROR_OK) { LOG_DEBUG("Sam3Info, Failed %d", r); return r; } return ERROR_OK; } COMMAND_HANDLER(sam3_handle_gpnvm_command) { unsigned x, v; int r, who; struct sam3_chip *pChip; pChip = get_current_sam3(CMD_CTX); if (!pChip) return ERROR_OK; if (pChip->target->state != TARGET_HALTED) { LOG_ERROR("sam3 - target not halted"); return ERROR_TARGET_NOT_HALTED; } if (pChip->details.bank[0].pBank == NULL) { command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...", at91sam3_flash.name); return ERROR_FAIL; } if (!pChip->details.bank[0].probed) { r = sam3_auto_probe(pChip->details.bank[0].pBank); if (r != ERROR_OK) return r; } switch (CMD_ARGC) { default: return ERROR_COMMAND_SYNTAX_ERROR; break; case 0: goto showall; break; case 1: who = -1; break; case 2: if ((0 == strcmp(CMD_ARGV[0], "show")) && (0 == strcmp(CMD_ARGV[1], "all"))) who = -1; else { uint32_t v32; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32); who = v32; } break; } if (0 == strcmp("show", CMD_ARGV[0])) { if (who == -1) { showall: r = ERROR_OK; for (x = 0; x < pChip->details.n_gpnvms; x++) { r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v); if (r != ERROR_OK) break; command_print(CMD_CTX, "sam3-gpnvm%u: %u", x, v); } return r; } if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) { r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v); command_print(CMD_CTX, "sam3-gpnvm%u: %u", who, v); return r; } else { command_print(CMD_CTX, "sam3-gpnvm invalid GPNVM: %u", who); return ERROR_COMMAND_SYNTAX_ERROR; } } if (who == -1) { command_print(CMD_CTX, "Missing GPNVM number"); return ERROR_COMMAND_SYNTAX_ERROR; } if (0 == strcmp("set", CMD_ARGV[0])) r = FLASHD_SetGPNVM(&(pChip->details.bank[0]), who); else if ((0 == strcmp("clr", CMD_ARGV[0])) || (0 == strcmp("clear", CMD_ARGV[0]))) /* quietly accept both */ r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who); else { command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]); r = ERROR_COMMAND_SYNTAX_ERROR; } return r; } COMMAND_HANDLER(sam3_handle_slowclk_command) { struct sam3_chip *pChip; pChip = get_current_sam3(CMD_CTX); if (!pChip) return ERROR_OK; switch (CMD_ARGC) { case 0: /* show */ break; case 1: { /* set */ uint32_t v; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v); if (v > 200000) { /* absurd slow clock of 200Khz? */ command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v)); return ERROR_COMMAND_SYNTAX_ERROR; } pChip->cfg.slow_freq = v; break; } default: /* error */ command_print(CMD_CTX, "Too many parameters"); return ERROR_COMMAND_SYNTAX_ERROR; break; } command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz", (int)(pChip->cfg.slow_freq / 1000), (int)(pChip->cfg.slow_freq % 1000)); return ERROR_OK; } static const struct command_registration at91sam3_exec_command_handlers[] = { { .name = "gpnvm", .handler = sam3_handle_gpnvm_command, .mode = COMMAND_EXEC, .usage = "[('clr'|'set'|'show') bitnum]", .help = "Without arguments, shows all bits in the gpnvm " "register. Otherwise, clears, sets, or shows one " "General Purpose Non-Volatile Memory (gpnvm) bit.", }, { .name = "info", .handler = sam3_handle_info_command, .mode = COMMAND_EXEC, .help = "Print information about the current at91sam3 chip" "and its flash configuration.", }, { .name = "slowclk", .handler = sam3_handle_slowclk_command, .mode = COMMAND_EXEC, .usage = "[clock_hz]", .help = "Display or set the slowclock frequency " "(default 32768 Hz).", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91sam3_command_handlers[] = { { .name = "at91sam3", .mode = COMMAND_ANY, .help = "at91sam3 flash command group", .usage = "", .chain = at91sam3_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver at91sam3_flash = { .name = "at91sam3", .commands = at91sam3_command_handlers, .flash_bank_command = sam3_flash_bank_command, .erase = sam3_erase, .protect = sam3_protect, .write = sam3_write, .read = default_flash_read, .probe = sam3_probe, .auto_probe = sam3_auto_probe, .erase_check = sam3_erase_check, .protect_check = sam3_protect_check, }; openocd-0.9.0/src/flash/nor/at91sam4.c0000644000175000017500000017663112516456302014303 00000000000000/*************************************************************************** * Copyright (C) 2009 by Duane Ellis * * openocd@duaneellis.com * * * * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) * * olaf@uni-paderborn.de * * * * Copyright (C) 2011 by Olivier Schonken, Jim Norris * * (at91sam3x* & at91sam4 support)* * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ****************************************************************************/ /* Some of the the lower level code was based on code supplied by * ATMEL under this copyright. */ /* BEGIN ATMEL COPYRIGHT */ /* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2009, Atmel Corporation * * 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 disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL 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. * ---------------------------------------------------------------------------- */ /* END ATMEL COPYRIGHT */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #define REG_NAME_WIDTH (12) /* at91sam4s/at91sam4e series (has always one flash bank)*/ #define FLASH_BANK_BASE_S 0x00400000 /* at91sam4sd series (two one flash banks), first bank address */ #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S /* at91sam4sd16x, second bank address */ #define FLASH_BANK1_BASE_1024K_SD (FLASH_BANK0_BASE_SD+(1024*1024/2)) /* at91sam4sd32x, second bank address */ #define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2)) #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ #define AT91C_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */ #define AT91C_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page and Write Page then Lock */ #define AT91C_EFC_FCMD_EA (0x5) /* (EFC) Erase All */ /* cmd6 is not present in the at91sam4u4/2/1 data sheet table 19-2 */ /* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */ #define AT91C_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */ #define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */ #define AT91C_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */ #define AT91C_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */ #define AT91C_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */ #define AT91C_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */ #define AT91C_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */ #define AT91C_EFC_FCMD_STUI (0xE) /* (EFC) Start Read Unique ID */ #define AT91C_EFC_FCMD_SPUI (0xF) /* (EFC) Stop Read Unique ID */ #define offset_EFC_FMR 0 #define offset_EFC_FCR 4 #define offset_EFC_FSR 8 #define offset_EFC_FRR 12 extern struct flash_driver at91sam4_flash; static float _tomhz(uint32_t freq_hz) { float f; f = ((float)(freq_hz)) / 1000000.0; return f; } /* How the chip is configured. */ struct sam4_cfg { uint32_t unique_id[4]; uint32_t slow_freq; uint32_t rc_freq; uint32_t mainosc_freq; uint32_t plla_freq; uint32_t mclk_freq; uint32_t cpu_freq; uint32_t fclk_freq; uint32_t pclk0_freq; uint32_t pclk1_freq; uint32_t pclk2_freq; #define SAM4_CHIPID_CIDR (0x400E0740) uint32_t CHIPID_CIDR; #define SAM4_CHIPID_EXID (0x400E0744) uint32_t CHIPID_EXID; #define SAM4_PMC_BASE (0x400E0400) #define SAM4_PMC_SCSR (SAM4_PMC_BASE + 0x0008) uint32_t PMC_SCSR; #define SAM4_PMC_PCSR (SAM4_PMC_BASE + 0x0018) uint32_t PMC_PCSR; #define SAM4_CKGR_UCKR (SAM4_PMC_BASE + 0x001c) uint32_t CKGR_UCKR; #define SAM4_CKGR_MOR (SAM4_PMC_BASE + 0x0020) uint32_t CKGR_MOR; #define SAM4_CKGR_MCFR (SAM4_PMC_BASE + 0x0024) uint32_t CKGR_MCFR; #define SAM4_CKGR_PLLAR (SAM4_PMC_BASE + 0x0028) uint32_t CKGR_PLLAR; #define SAM4_PMC_MCKR (SAM4_PMC_BASE + 0x0030) uint32_t PMC_MCKR; #define SAM4_PMC_PCK0 (SAM4_PMC_BASE + 0x0040) uint32_t PMC_PCK0; #define SAM4_PMC_PCK1 (SAM4_PMC_BASE + 0x0044) uint32_t PMC_PCK1; #define SAM4_PMC_PCK2 (SAM4_PMC_BASE + 0x0048) uint32_t PMC_PCK2; #define SAM4_PMC_SR (SAM4_PMC_BASE + 0x0068) uint32_t PMC_SR; #define SAM4_PMC_IMR (SAM4_PMC_BASE + 0x006c) uint32_t PMC_IMR; #define SAM4_PMC_FSMR (SAM4_PMC_BASE + 0x0070) uint32_t PMC_FSMR; #define SAM4_PMC_FSPR (SAM4_PMC_BASE + 0x0074) uint32_t PMC_FSPR; }; struct sam4_bank_private { int probed; /* DANGER: THERE ARE DRAGONS HERE.. */ /* NOTE: If you add more 'ghost' pointers */ /* be aware that you must *manually* update */ /* these pointers in the function sam4_GetDetails() */ /* See the comment "Here there be dragons" */ /* so we can find the chip we belong to */ struct sam4_chip *pChip; /* so we can find the original bank pointer */ struct flash_bank *pBank; unsigned bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; unsigned size_bytes; unsigned nsectors; unsigned sector_size; unsigned page_size; }; struct sam4_chip_details { /* THERE ARE DRAGONS HERE.. */ /* note: If you add pointers here */ /* be careful about them as they */ /* may need to be updated inside */ /* the function: "sam4_GetDetails() */ /* which copy/overwrites the */ /* 'runtime' copy of this structure */ uint32_t chipid_cidr; const char *name; unsigned n_gpnvms; #define SAM4_N_NVM_BITS 3 unsigned gpnvm[SAM4_N_NVM_BITS]; unsigned total_flash_size; unsigned total_sram_size; unsigned n_banks; #define SAM4_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam4_bank_private bank[SAM4_MAX_FLASH_BANKS]; }; struct sam4_chip { struct sam4_chip *next; int probed; /* this is "initialized" from the global const structure */ struct sam4_chip_details details; struct target *target; struct sam4_cfg cfg; }; struct sam4_reg_list { uint32_t address; size_t struct_offset; const char *name; void (*explain_func)(struct sam4_chip *pInfo); }; static struct sam4_chip *all_sam4_chips; static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx) { struct target *t; static struct sam4_chip *p; t = get_current_target(cmd_ctx); if (!t) { command_print(cmd_ctx, "No current target?"); return NULL; } p = all_sam4_chips; if (!p) { /* this should not happen */ /* the command is not registered until the chip is created? */ command_print(cmd_ctx, "No SAM4 chips exist?"); return NULL; } while (p) { if (p->target == t) return p; p = p->next; } command_print(cmd_ctx, "Cannot find SAM4 chip?"); return NULL; } /*The actual sector size of the SAM4S flash memory is 65536 bytes. 16 sectors for a 1024KB device*/ /*The lockregions are 8KB per lock region, with a 1024KB device having 128 lock regions. */ /*For the best results, nsectors are thus set to the amount of lock regions, and the sector_size*/ /*set to the lock region size. Page erases are used to erase 8KB sections when programming*/ /* these are used to *initialize* the "pChip->details" structure. */ static const struct sam4_chip_details all_sam4_details[] = { /* Start at91sam4e* series */ /*atsam4e16e - LQFP144/LFBGA144*/ { .chipid_cidr = 0xA3CC0CE0, .name = "at91sam4e16e", .total_flash_size = 1024 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /* Start at91sam4s* series */ /*atsam4s16c - LQFP100/BGA100*/ { .chipid_cidr = 0x28AC0CE0, .name = "at91sam4s16c", .total_flash_size = 1024 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s16b - LQFP64/QFN64*/ { .chipid_cidr = 0x289C0CE0, .name = "at91sam4s16b", .total_flash_size = 1024 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s16a - LQFP48/QFN48*/ { .chipid_cidr = 0x288C0CE0, .name = "at91sam4s16a", .total_flash_size = 1024 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s8c - LQFP100/BGA100*/ { .chipid_cidr = 0x28AC0AE0, .name = "at91sam4s8c", .total_flash_size = 512 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s8b - LQFP64/BGA64*/ { .chipid_cidr = 0x289C0AE0, .name = "at91sam4s8b", .total_flash_size = 512 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s8a - LQFP48/BGA48*/ { .chipid_cidr = 0x288C0AE0, .name = "at91sam4s8a", .total_flash_size = 512 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*atsam4s4a - LQFP48/BGA48*/ { .chipid_cidr = 0x288b09e0, .name = "at91sam4s4a", .total_flash_size = 256 * 1024, .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { /* .bank[0] = {*/ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 256 * 1024, .nsectors = 32, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, }, }, /*at91sam4sd32c*/ { .chipid_cidr = 0x29a70ee0, .name = "at91sam4sd32c", .total_flash_size = 2048 * 1024, .total_sram_size = 160 * 1024, .n_gpnvms = 3, .n_banks = 2, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_2048K_SD, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, .sector_size = 8192, .page_size = 512, }, }, }, /*at91sam4sd16c*/ { .chipid_cidr = 0x29a70ce0, .name = "at91sam4sd16c", .total_flash_size = 1024 * 1024, .total_sram_size = 160 * 1024, .n_gpnvms = 3, .n_banks = 2, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_1024K_SD, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, }, }, /*at91sam4sa16c*/ { .chipid_cidr = 0x28a70ce0, .name = "at91sam4sa16c", .total_flash_size = 1024 * 1024, .total_sram_size = 160 * 1024, .n_gpnvms = 3, .n_banks = 2, /* .bank[0] = { */ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = { */ { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 1, .base_address = FLASH_BANK1_BASE_1024K_SD, .controller_address = 0x400e0c00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, }, }, /* at91samg53n19 */ { .chipid_cidr = 0x247e0ae0, .name = "at91samg53n19", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 2, .n_banks = 1, /* .bank[0] = {*/ { { .probed = 0, .pChip = NULL, .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { .present = 0, .probed = 0, .bank_number = 1, }, } }, /* terminate */ { .chipid_cidr = 0, .name = NULL, } }; /* Globals above */ /*********************************************************************** ********************************************************************** ********************************************************************** ********************************************************************** ********************************************************************** **********************************************************************/ /* *ATMEL* style code - from the SAM4 driver code */ /** * Get the current status of the EEFC and * the value of some status bits (LOCKE, PROGE). * @param pPrivate - info about the bank * @param v - result goes here */ static int EFC_GetStatus(struct sam4_bank_private *pPrivate, uint32_t *v) { int r; r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address + offset_EFC_FSR, v); LOG_DEBUG("Status: 0x%08x (lockerror: %d, cmderror: %d, ready: %d)", (unsigned int)(*v), ((unsigned int)((*v >> 2) & 1)), ((unsigned int)((*v >> 1) & 1)), ((unsigned int)((*v >> 0) & 1))); return r; } /** * Get the result of the last executed command. * @param pPrivate - info about the bank * @param v - result goes here */ static int EFC_GetResult(struct sam4_bank_private *pPrivate, uint32_t *v) { int r; uint32_t rv; r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address + offset_EFC_FRR, &rv); if (v) *v = rv; LOG_DEBUG("Result: 0x%08x", ((unsigned int)(rv))); return r; } static int EFC_StartCommand(struct sam4_bank_private *pPrivate, unsigned command, unsigned argument) { uint32_t n, v; int r; int retry; retry = 0; do_retry: /* Check command & argument */ switch (command) { case AT91C_EFC_FCMD_WP: case AT91C_EFC_FCMD_WPL: case AT91C_EFC_FCMD_EWP: case AT91C_EFC_FCMD_EWPL: /* case AT91C_EFC_FCMD_EPL: */ case AT91C_EFC_FCMD_EPA: case AT91C_EFC_FCMD_SLB: case AT91C_EFC_FCMD_CLB: n = (pPrivate->size_bytes / pPrivate->page_size); if (argument >= n) LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); break; case AT91C_EFC_FCMD_SFB: case AT91C_EFC_FCMD_CFB: if (argument >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs", pPrivate->pChip->details.n_gpnvms); } break; case AT91C_EFC_FCMD_GETD: case AT91C_EFC_FCMD_EA: case AT91C_EFC_FCMD_GLB: case AT91C_EFC_FCMD_GFB: case AT91C_EFC_FCMD_STUI: case AT91C_EFC_FCMD_SPUI: if (argument != 0) LOG_ERROR("Argument is meaningless for cmd: %d", command); break; default: LOG_ERROR("Unknown command %d", command); break; } if (command == AT91C_EFC_FCMD_SPUI) { /* this is a very special situation. */ /* Situation (1) - error/retry - see below */ /* And we are being called recursively */ /* Situation (2) - normal, finished reading unique id */ } else { /* it should be "ready" */ EFC_GetStatus(pPrivate, &v); if (v & 1) { /* then it is ready */ /* we go on */ } else { if (retry) { /* we have done this before */ /* the controller is not responding. */ LOG_ERROR("flash controller(%d) is not ready! Error", pPrivate->bank_number); return ERROR_FAIL; } else { retry++; LOG_ERROR("Flash controller(%d) is not ready, attempting reset", pPrivate->bank_number); /* we do that by issuing the *STOP* command */ EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0); /* above is recursive, and further recursion is blocked by */ /* if (command == AT91C_EFC_FCMD_SPUI) above */ goto do_retry; } } } v = (0x5A << 24) | (argument << 8) | command; LOG_DEBUG("Command: 0x%08x", ((unsigned int)(v))); r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address + offset_EFC_FCR, v); if (r != ERROR_OK) LOG_DEBUG("Error Write failed"); return r; } /** * Performs the given command and wait until its completion (or an error). * @param pPrivate - info about the bank * @param command - Command to perform. * @param argument - Optional command argument. * @param status - put command status bits here */ static int EFC_PerformCommand(struct sam4_bank_private *pPrivate, unsigned command, unsigned argument, uint32_t *status) { int r; uint32_t v; long long ms_now, ms_end; /* default */ if (status) *status = 0; r = EFC_StartCommand(pPrivate, command, argument); if (r != ERROR_OK) return r; ms_end = 10000 + timeval_ms(); do { r = EFC_GetStatus(pPrivate, &v); if (r != ERROR_OK) return r; ms_now = timeval_ms(); if (ms_now > ms_end) { /* error */ LOG_ERROR("Command timeout"); return ERROR_FAIL; } } while ((v & 1) == 0); /* error bits.. */ if (status) *status = (v & 0x6); return ERROR_OK; } /** * Read the unique ID. * @param pPrivate - info about the bank * The unique ID is stored in the 'pPrivate' structure. */ static int FLASHD_ReadUniqueID(struct sam4_bank_private *pPrivate) { int r; uint32_t v; int x; /* assume 0 */ pPrivate->pChip->cfg.unique_id[0] = 0; pPrivate->pChip->cfg.unique_id[1] = 0; pPrivate->pChip->cfg.unique_id[2] = 0; pPrivate->pChip->cfg.unique_id[3] = 0; LOG_DEBUG("Begin"); r = EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_STUI, 0); if (r < 0) return r; for (x = 0; x < 4; x++) { r = target_read_u32(pPrivate->pChip->target, pPrivate->pBank->base + (x * 4), &v); if (r < 0) return r; pPrivate->pChip->cfg.unique_id[x] = v; } r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0, NULL); LOG_DEBUG("End: R=%d, id = 0x%08x, 0x%08x, 0x%08x, 0x%08x", r, (unsigned int)(pPrivate->pChip->cfg.unique_id[0]), (unsigned int)(pPrivate->pChip->cfg.unique_id[1]), (unsigned int)(pPrivate->pChip->cfg.unique_id[2]), (unsigned int)(pPrivate->pChip->cfg.unique_id[3])); return r; } /** * Erases the entire flash. * @param pPrivate - the info about the bank. */ static int FLASHD_EraseEntireBank(struct sam4_bank_private *pPrivate) { LOG_DEBUG("Here"); return EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_EA, 0, NULL); } /** * Erases the entire flash. * @param pPrivate - the info about the bank. */ static int FLASHD_ErasePages(struct sam4_bank_private *pPrivate, int firstPage, int numPages, uint32_t *status) { LOG_DEBUG("Here"); uint8_t erasePages; switch (numPages) { case 4: erasePages = 0x00; break; case 8: erasePages = 0x01; break; case 16: erasePages = 0x02; break; case 32: erasePages = 0x03; break; default: erasePages = 0x00; break; } /* AT91C_EFC_FCMD_EPA * According to the datasheet FARG[15:2] defines the page from which * the erase will start.This page must be modulo 4, 8, 16 or 32 * according to the number of pages to erase. FARG[1:0] defines the * number of pages to be erased. Previously (firstpage << 2) was used * to conform to this, seems it should not be shifted... */ return EFC_PerformCommand(pPrivate, /* send Erase Page */ AT91C_EFC_FCMD_EPA, (firstPage) | erasePages, status); } /** * Gets current GPNVM state. * @param pPrivate - info about the bank. * @param gpnvm - GPNVM bit index. * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ static int FLASHD_GetGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm, unsigned *puthere) { uint32_t v; int r; LOG_DEBUG("Here"); if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } /* Get GPNVMs status */ r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GFB, 0, NULL); if (r != ERROR_OK) { LOG_ERROR("Failed"); return r; } r = EFC_GetResult(pPrivate, &v); if (puthere) { /* Check if GPNVM is set */ /* get the bit and make it a 0/1 */ *puthere = (v >> gpnvm) & 1; } return r; } /** * Clears the selected GPNVM bit. * @param pPrivate info about the bank * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ static int FLASHD_ClrGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm) { int r; unsigned v; LOG_DEBUG("Here"); if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v); if (r != ERROR_OK) { LOG_DEBUG("Failed: %d", r); return r; } r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CFB, gpnvm, NULL); LOG_DEBUG("End: %d", r); return r; } /** * Sets the selected GPNVM bit. * @param pPrivate info about the bank * @param gpnvm GPNVM index. */ static int FLASHD_SetGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm) { int r; unsigned v; if (pPrivate->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); return ERROR_FAIL; } if (gpnvm >= pPrivate->pChip->details.n_gpnvms) { LOG_ERROR("Invalid GPNVM %d, max: %d, ignored", gpnvm, pPrivate->pChip->details.n_gpnvms); return ERROR_FAIL; } r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v); if (r != ERROR_OK) return r; if (v) { /* already set */ r = ERROR_OK; } else { /* set it */ r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SFB, gpnvm, NULL); } return r; } /** * Returns a bit field (at most 64) of locked regions within a page. * @param pPrivate info about the bank * @param v where to store locked bits */ static int FLASHD_GetLockBits(struct sam4_bank_private *pPrivate, uint32_t *v) { int r; LOG_DEBUG("Here"); r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GLB, 0, NULL); if (r == ERROR_OK) { EFC_GetResult(pPrivate, v); EFC_GetResult(pPrivate, v); EFC_GetResult(pPrivate, v); r = EFC_GetResult(pPrivate, v); } LOG_DEBUG("End: %d", r); return r; } /** * Unlocks all the regions in the given address range. * @param pPrivate info about the bank * @param start_sector first sector to unlock * @param end_sector last (inclusive) to unlock */ static int FLASHD_Unlock(struct sam4_bank_private *pPrivate, unsigned start_sector, unsigned end_sector) { int r; uint32_t status; uint32_t pg; uint32_t pages_per_sector; pages_per_sector = pPrivate->sector_size / pPrivate->page_size; /* Unlock all pages */ while (start_sector <= end_sector) { pg = start_sector * pages_per_sector; r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CLB, pg, &status); if (r != ERROR_OK) return r; start_sector++; } return ERROR_OK; } /** * Locks regions * @param pPrivate - info about the bank * @param start_sector - first sector to lock * @param end_sector - last sector (inclusive) to lock */ static int FLASHD_Lock(struct sam4_bank_private *pPrivate, unsigned start_sector, unsigned end_sector) { uint32_t status; uint32_t pg; uint32_t pages_per_sector; int r; pages_per_sector = pPrivate->sector_size / pPrivate->page_size; /* Lock all pages */ while (start_sector <= end_sector) { pg = start_sector * pages_per_sector; r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SLB, pg, &status); if (r != ERROR_OK) return r; start_sector++; } return ERROR_OK; } /****** END SAM4 CODE ********/ /* begin helpful debug code */ /* print the fieldname, the field value, in dec & hex, and return field value */ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip, const char *regname, uint32_t value, unsigned shift, unsigned width) { uint32_t v; int hwidth, dwidth; /* extract the field */ v = value >> shift; v = v & ((1 << width)-1); if (width <= 16) { hwidth = 4; dwidth = 5; } else { hwidth = 8; dwidth = 12; } /* show the basics */ LOG_USER_N("\t%*s: %*" PRId32 " [0x%0*" PRIx32 "] ", REG_NAME_WIDTH, regname, dwidth, v, hwidth, v); return v; } static const char _unknown[] = "unknown"; static const char *const eproc_names[] = { _unknown, /* 0 */ "arm946es", /* 1 */ "arm7tdmi", /* 2 */ "cortex-m3", /* 3 */ "arm920t", /* 4 */ "arm926ejs", /* 5 */ "cortex-a5", /* 6 */ "cortex-m4", /* 7 */ _unknown, /* 8 */ _unknown, /* 9 */ _unknown, /* 10 */ _unknown, /* 11 */ _unknown, /* 12 */ _unknown, /* 13 */ _unknown, /* 14 */ _unknown, /* 15 */ }; #define nvpsize2 nvpsize /* these two tables are identical */ static const char *const nvpsize[] = { "none", /* 0 */ "8K bytes", /* 1 */ "16K bytes", /* 2 */ "32K bytes", /* 3 */ _unknown, /* 4 */ "64K bytes", /* 5 */ _unknown, /* 6 */ "128K bytes", /* 7 */ _unknown, /* 8 */ "256K bytes", /* 9 */ "512K bytes", /* 10 */ _unknown, /* 11 */ "1024K bytes", /* 12 */ _unknown, /* 13 */ "2048K bytes", /* 14 */ _unknown, /* 15 */ }; static const char *const sramsize[] = { "48K Bytes", /* 0 */ "1K Bytes", /* 1 */ "2K Bytes", /* 2 */ "6K Bytes", /* 3 */ "112K Bytes", /* 4 */ "4K Bytes", /* 5 */ "80K Bytes", /* 6 */ "160K Bytes", /* 7 */ "8K Bytes", /* 8 */ "16K Bytes", /* 9 */ "32K Bytes", /* 10 */ "64K Bytes", /* 11 */ "128K Bytes", /* 12 */ "256K Bytes", /* 13 */ "96K Bytes", /* 14 */ "512K Bytes", /* 15 */ }; static const struct archnames { unsigned value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, { 0x37, "CAP7 Series" }, { 0x39, "CAP9 Series" }, { 0x3B, "CAP11 Series" }, { 0x3C, "ATSAM4E" }, { 0x40, "AT91x40 Series" }, { 0x42, "AT91x42 Series" }, { 0x43, "SAMG51 Series" }, { 0x47, "SAMG53 Series" }, { 0x55, "AT91x55 Series" }, { 0x60, "AT91SAM7Axx Series" }, { 0x61, "AT91SAM7AQxx Series" }, { 0x63, "AT91x63 Series" }, { 0x70, "AT91SAM7Sxx Series" }, { 0x71, "AT91SAM7XCxx Series" }, { 0x72, "AT91SAM7SExx Series" }, { 0x73, "AT91SAM7Lxx Series" }, { 0x75, "AT91SAM7Xxx Series" }, { 0x76, "AT91SAM7SLxx Series" }, { 0x80, "ATSAM3UxC Series (100-pin version)" }, { 0x81, "ATSAM3UxE Series (144-pin version)" }, { 0x83, "ATSAM3A/SAM4A xC Series (100-pin version)"}, { 0x84, "ATSAM3X/SAM4X xC Series (100-pin version)"}, { 0x85, "ATSAM3X/SAM4X xE Series (144-pin version)"}, { 0x86, "ATSAM3X/SAM4X xG Series (208/217-pin version)" }, { 0x88, "ATSAM3S/SAM4S xA Series (48-pin version)" }, { 0x89, "ATSAM3S/SAM4S xB Series (64-pin version)" }, { 0x8A, "ATSAM3S/SAM4S xC Series (100-pin version)"}, { 0x92, "AT91x92 Series" }, { 0x93, "ATSAM3NxA Series (48-pin version)" }, { 0x94, "ATSAM3NxB Series (64-pin version)" }, { 0x95, "ATSAM3NxC Series (100-pin version)" }, { 0x98, "ATSAM3SDxA Series (48-pin version)" }, { 0x99, "ATSAM3SDxB Series (64-pin version)" }, { 0x9A, "ATSAM3SDxC Series (100-pin version)" }, { 0xA5, "ATSAM5A" }, { 0xF0, "AT75Cxx Series" }, { -1, NULL }, }; static const char *const nvptype[] = { "rom", /* 0 */ "romless or onchip flash", /* 1 */ "embedded flash memory",/* 2 */ "rom(nvpsiz) + embedded flash (nvpsiz2)", /* 3 */ "sram emulating flash", /* 4 */ _unknown, /* 5 */ _unknown, /* 6 */ _unknown, /* 7 */ }; static const char *_yes_or_no(uint32_t v) { if (v) return "YES"; else return "NO"; } static const char *const _rc_freq[] = { "4 MHz", "8 MHz", "12 MHz", "reserved" }; static void sam4_explain_ckgr_mor(struct sam4_chip *pChip) { uint32_t v; uint32_t rcen; v = sam4_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1); LOG_USER("(main xtal enabled: %s)", _yes_or_no(v)); v = sam4_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1); LOG_USER("(main osc bypass: %s)", _yes_or_no(v)); rcen = sam4_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 3, 1); LOG_USER("(onchip RC-OSC enabled: %s)", _yes_or_no(rcen)); v = sam4_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3); LOG_USER("(onchip RC-OSC freq: %s)", _rc_freq[v]); pChip->cfg.rc_freq = 0; if (rcen) { switch (v) { default: pChip->cfg.rc_freq = 0; break; case 0: pChip->cfg.rc_freq = 4 * 1000 * 1000; break; case 1: pChip->cfg.rc_freq = 8 * 1000 * 1000; break; case 2: pChip->cfg.rc_freq = 12 * 1000 * 1000; break; } } v = sam4_reg_fieldname(pChip, "MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8); LOG_USER("(startup clks, time= %f uSecs)", ((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq))); v = sam4_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1); LOG_USER("(mainosc source: %s)", v ? "external xtal" : "internal RC"); v = sam4_reg_fieldname(pChip, "CFDEN", pChip->cfg.CKGR_MOR, 25, 1); LOG_USER("(clock failure enabled: %s)", _yes_or_no(v)); } static void sam4_explain_chipid_cidr(struct sam4_chip *pChip) { int x; uint32_t v; const char *cp; sam4_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5); LOG_USER_N("\n"); v = sam4_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3); LOG_USER("%s", eproc_names[v]); v = sam4_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4); LOG_USER("%s", nvpsize[v]); v = sam4_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4); LOG_USER("%s", nvpsize2[v]); v = sam4_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16, 4); LOG_USER("%s", sramsize[v]); v = sam4_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8); cp = _unknown; for (x = 0; archnames[x].name; x++) { if (v == archnames[x].value) { cp = archnames[x].name; break; } } LOG_USER("%s", cp); v = sam4_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3); LOG_USER("%s", nvptype[v]); v = sam4_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1); LOG_USER("(exists: %s)", _yes_or_no(v)); } static void sam4_explain_ckgr_mcfr(struct sam4_chip *pChip) { uint32_t v; v = sam4_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1); LOG_USER("(main ready: %s)", _yes_or_no(v)); v = sam4_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16); v = (v * pChip->cfg.slow_freq) / 16; pChip->cfg.mainosc_freq = v; LOG_USER("(%3.03f Mhz (%" PRIu32 ".%03" PRIu32 "khz slowclk)", _tomhz(v), (uint32_t)(pChip->cfg.slow_freq / 1000), (uint32_t)(pChip->cfg.slow_freq % 1000)); } static void sam4_explain_ckgr_plla(struct sam4_chip *pChip) { uint32_t mula, diva; diva = sam4_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8); LOG_USER_N("\n"); mula = sam4_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11); LOG_USER_N("\n"); pChip->cfg.plla_freq = 0; if (mula == 0) LOG_USER("\tPLLA Freq: (Disabled,mula = 0)"); else if (diva == 0) LOG_USER("\tPLLA Freq: (Disabled,diva = 0)"); else if (diva >= 1) { pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1) / diva); LOG_USER("\tPLLA Freq: %3.03f MHz", _tomhz(pChip->cfg.plla_freq)); } } static void sam4_explain_mckr(struct sam4_chip *pChip) { uint32_t css, pres, fin = 0; int pdiv = 0; const char *cp = NULL; css = sam4_reg_fieldname(pChip, "CSS", pChip->cfg.PMC_MCKR, 0, 2); switch (css & 3) { case 0: fin = pChip->cfg.slow_freq; cp = "slowclk"; break; case 1: fin = pChip->cfg.mainosc_freq; cp = "mainosc"; break; case 2: fin = pChip->cfg.plla_freq; cp = "plla"; break; case 3: if (pChip->cfg.CKGR_UCKR & (1 << 16)) { fin = 480 * 1000 * 1000; cp = "upll"; } else { fin = 0; cp = "upll (*ERROR* UPLL is disabled)"; } break; default: assert(0); break; } LOG_USER("%s (%3.03f Mhz)", cp, _tomhz(fin)); pres = sam4_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3); switch (pres & 0x07) { case 0: pdiv = 1; cp = "selected clock"; break; case 1: pdiv = 2; cp = "clock/2"; break; case 2: pdiv = 4; cp = "clock/4"; break; case 3: pdiv = 8; cp = "clock/8"; break; case 4: pdiv = 16; cp = "clock/16"; break; case 5: pdiv = 32; cp = "clock/32"; break; case 6: pdiv = 64; cp = "clock/64"; break; case 7: pdiv = 6; cp = "clock/6"; break; default: assert(0); break; } LOG_USER("(%s)", cp); fin = fin / pdiv; /* sam4 has a *SINGLE* clock - */ /* other at91 series parts have divisors for these. */ pChip->cfg.cpu_freq = fin; pChip->cfg.mclk_freq = fin; pChip->cfg.fclk_freq = fin; LOG_USER("\t\tResult CPU Freq: %3.03f", _tomhz(fin)); } #if 0 static struct sam4_chip *target2sam4(struct target *pTarget) { struct sam4_chip *pChip; if (pTarget == NULL) return NULL; pChip = all_sam4_chips; while (pChip) { if (pChip->target == pTarget) break; /* return below */ else pChip = pChip->next; } return pChip; } #endif static uint32_t *sam4_get_reg_ptr(struct sam4_cfg *pCfg, const struct sam4_reg_list *pList) { /* this function exists to help */ /* keep funky offsetof() errors */ /* and casting from causing bugs */ /* By using prototypes - we can detect what would */ /* be casting errors. */ return (uint32_t *)(void *)(((char *)(pCfg)) + pList->struct_offset); } #define SAM4_ENTRY(NAME, FUNC) { .address = SAM4_ ## NAME, .struct_offset = offsetof( \ struct sam4_cfg, \ NAME), # NAME, FUNC } static const struct sam4_reg_list sam4_all_regs[] = { SAM4_ENTRY(CKGR_MOR, sam4_explain_ckgr_mor), SAM4_ENTRY(CKGR_MCFR, sam4_explain_ckgr_mcfr), SAM4_ENTRY(CKGR_PLLAR, sam4_explain_ckgr_plla), SAM4_ENTRY(CKGR_UCKR, NULL), SAM4_ENTRY(PMC_FSMR, NULL), SAM4_ENTRY(PMC_FSPR, NULL), SAM4_ENTRY(PMC_IMR, NULL), SAM4_ENTRY(PMC_MCKR, sam4_explain_mckr), SAM4_ENTRY(PMC_PCK0, NULL), SAM4_ENTRY(PMC_PCK1, NULL), SAM4_ENTRY(PMC_PCK2, NULL), SAM4_ENTRY(PMC_PCSR, NULL), SAM4_ENTRY(PMC_SCSR, NULL), SAM4_ENTRY(PMC_SR, NULL), SAM4_ENTRY(CHIPID_CIDR, sam4_explain_chipid_cidr), SAM4_ENTRY(CHIPID_EXID, NULL), /* TERMINATE THE LIST */ { .name = NULL } }; #undef SAM4_ENTRY static struct sam4_bank_private *get_sam4_bank_private(struct flash_bank *bank) { return bank->driver_priv; } /** * Given a pointer to where it goes in the structure, * determine the register name, address from the all registers table. */ static const struct sam4_reg_list *sam4_GetReg(struct sam4_chip *pChip, uint32_t *goes_here) { const struct sam4_reg_list *pReg; pReg = &(sam4_all_regs[0]); while (pReg->name) { uint32_t *pPossible; /* calculate where this one go.. */ /* it is "possibly" this register. */ pPossible = ((uint32_t *)(void *)(((char *)(&(pChip->cfg))) + pReg->struct_offset)); /* well? Is it this register */ if (pPossible == goes_here) { /* Jump for joy! */ return pReg; } /* next... */ pReg++; } /* This is *TOTAL*PANIC* - we are totally screwed. */ LOG_ERROR("INVALID SAM4 REGISTER"); return NULL; } static int sam4_ReadThisReg(struct sam4_chip *pChip, uint32_t *goes_here) { const struct sam4_reg_list *pReg; int r; pReg = sam4_GetReg(pChip, goes_here); if (!pReg) return ERROR_FAIL; r = target_read_u32(pChip->target, pReg->address, goes_here); if (r != ERROR_OK) { LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Err: %d", pReg->name, (unsigned)(pReg->address), r); } return r; } static int sam4_ReadAllRegs(struct sam4_chip *pChip) { int r; const struct sam4_reg_list *pReg; pReg = &(sam4_all_regs[0]); while (pReg->name) { r = sam4_ReadThisReg(pChip, sam4_get_reg_ptr(&(pChip->cfg), pReg)); if (r != ERROR_OK) { LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Error: %d", pReg->name, ((unsigned)(pReg->address)), r); return r; } pReg++; } return ERROR_OK; } static int sam4_GetInfo(struct sam4_chip *pChip) { const struct sam4_reg_list *pReg; uint32_t regval; pReg = &(sam4_all_regs[0]); while (pReg->name) { /* display all regs */ LOG_DEBUG("Start: %s", pReg->name); regval = *sam4_get_reg_ptr(&(pChip->cfg), pReg); LOG_USER("%*s: [0x%08" PRIx32 "] -> 0x%08" PRIx32, REG_NAME_WIDTH, pReg->name, pReg->address, regval); if (pReg->explain_func) (*(pReg->explain_func))(pChip); LOG_DEBUG("End: %s", pReg->name); pReg++; } LOG_USER(" rc-osc: %3.03f MHz", _tomhz(pChip->cfg.rc_freq)); LOG_USER(" mainosc: %3.03f MHz", _tomhz(pChip->cfg.mainosc_freq)); LOG_USER(" plla: %3.03f MHz", _tomhz(pChip->cfg.plla_freq)); LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq)); LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq)); LOG_USER(" UniqueId: 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08"PRIx32, pChip->cfg.unique_id[0], pChip->cfg.unique_id[1], pChip->cfg.unique_id[2], pChip->cfg.unique_id[3]); return ERROR_OK; } static int sam4_protect_check(struct flash_bank *bank) { int r; uint32_t v[4] = {0}; unsigned x; struct sam4_bank_private *pPrivate; LOG_DEBUG("Begin"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam4_bank_private(bank); if (!pPrivate) { LOG_ERROR("no private for this bank?"); return ERROR_FAIL; } if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; r = FLASHD_GetLockBits(pPrivate, v); if (r != ERROR_OK) { LOG_DEBUG("Failed: %d", r); return r; } for (x = 0; x < pPrivate->nsectors; x++) bank->sectors[x].is_protected = (!!(v[x >> 5] & (1 << (x % 32)))); LOG_DEBUG("Done"); return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command) { struct sam4_chip *pChip; pChip = all_sam4_chips; /* is this an existing chip? */ while (pChip) { if (pChip->target == bank->target) break; pChip = pChip->next; } if (!pChip) { /* this is a *NEW* chip */ pChip = calloc(1, sizeof(struct sam4_chip)); if (!pChip) { LOG_ERROR("NO RAM!"); return ERROR_FAIL; } pChip->target = bank->target; /* insert at head */ pChip->next = all_sam4_chips; all_sam4_chips = pChip; pChip->target = bank->target; /* assumption is this runs at 32khz */ pChip->cfg.slow_freq = 32768; pChip->probed = 0; } switch (bank->base) { default: LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x" "[at91sam4s series] )", ((unsigned int)(bank->base)), ((unsigned int)(FLASH_BANK_BASE_S))); return ERROR_FAIL; break; /* at91sam4s series only has bank 0*/ /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/ case FLASH_BANK_BASE_S: bank->driver_priv = &(pChip->details.bank[0]); bank->bank_number = 0; pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pBank = bank; break; /* Bank 1 of at91sam4sd series */ case FLASH_BANK1_BASE_1024K_SD: case FLASH_BANK1_BASE_2048K_SD: bank->driver_priv = &(pChip->details.bank[1]); bank->bank_number = 1; pChip->details.bank[1].pChip = pChip; pChip->details.bank[1].pBank = bank; break; } /* we initialize after probing. */ return ERROR_OK; } static int sam4_GetDetails(struct sam4_bank_private *pPrivate) { const struct sam4_chip_details *pDetails; struct sam4_chip *pChip; struct flash_bank *saved_banks[SAM4_MAX_FLASH_BANKS]; unsigned x; LOG_DEBUG("Begin"); pDetails = all_sam4_details; while (pDetails->name) { /* Compare cidr without version bits */ if (pDetails->chipid_cidr == (pPrivate->pChip->cfg.CHIPID_CIDR & 0xFFFFFFE0)) break; else pDetails++; } if (pDetails->name == NULL) { LOG_ERROR("SAM4 ChipID 0x%08x not found in table (perhaps you can ID this chip?)", (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR)); /* Help the victim, print details about the chip */ LOG_INFO("SAM4 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows", pPrivate->pChip->cfg.CHIPID_CIDR); sam4_explain_chipid_cidr(pPrivate->pChip); return ERROR_FAIL; } /* DANGER: THERE ARE DRAGONS HERE */ /* get our pChip - it is going */ /* to be over-written shortly */ pChip = pPrivate->pChip; /* Note that, in reality: */ /* */ /* pPrivate = &(pChip->details.bank[0]) */ /* or pPrivate = &(pChip->details.bank[1]) */ /* */ /* save the "bank" pointers */ for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) saved_banks[x] = pChip->details.bank[x].pBank; /* Overwrite the "details" structure. */ memcpy(&(pPrivate->pChip->details), pDetails, sizeof(pPrivate->pChip->details)); /* now fix the ghosted pointers */ for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) { pChip->details.bank[x].pChip = pChip; pChip->details.bank[x].pBank = saved_banks[x]; } /* update the *BANK*SIZE* */ LOG_DEBUG("End"); return ERROR_OK; } static int _sam4_probe(struct flash_bank *bank, int noise) { unsigned x; int r; struct sam4_bank_private *pPrivate; LOG_DEBUG("Begin: Bank: %d, Noise: %d", bank->bank_number, noise); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam4_bank_private(bank); if (!pPrivate) { LOG_ERROR("Invalid/unknown bank number"); return ERROR_FAIL; } r = sam4_ReadAllRegs(pPrivate->pChip); if (r != ERROR_OK) return r; LOG_DEBUG("Here"); if (pPrivate->pChip->probed) r = sam4_GetInfo(pPrivate->pChip); else r = sam4_GetDetails(pPrivate); if (r != ERROR_OK) return r; /* update the flash bank size */ for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) { if (bank->base == pPrivate->pChip->details.bank[x].base_address) { bank->size = pPrivate->pChip->details.bank[x].size_bytes; break; } } if (bank->sectors == NULL) { bank->sectors = calloc(pPrivate->nsectors, (sizeof((bank->sectors)[0]))); if (bank->sectors == NULL) { LOG_ERROR("No memory!"); return ERROR_FAIL; } bank->num_sectors = pPrivate->nsectors; for (x = 0; ((int)(x)) < bank->num_sectors; x++) { bank->sectors[x].size = pPrivate->sector_size; bank->sectors[x].offset = x * (pPrivate->sector_size); /* mark as unknown */ bank->sectors[x].is_erased = -1; bank->sectors[x].is_protected = -1; } } pPrivate->probed = 1; r = sam4_protect_check(bank); if (r != ERROR_OK) return r; LOG_DEBUG("Bank = %d, nbanks = %d", pPrivate->bank_number, pPrivate->pChip->details.n_banks); if ((pPrivate->bank_number + 1) == pPrivate->pChip->details.n_banks) { /* read unique id, */ /* it appears to be associated with the *last* flash bank. */ FLASHD_ReadUniqueID(pPrivate); } return r; } static int sam4_probe(struct flash_bank *bank) { return _sam4_probe(bank, 1); } static int sam4_auto_probe(struct flash_bank *bank) { return _sam4_probe(bank, 0); } static int sam4_erase(struct flash_bank *bank, int first, int last) { struct sam4_bank_private *pPrivate; int r; int i; int pageCount; /*16 pages equals 8KB - Same size as a lock region*/ pageCount = 16; uint32_t status; LOG_DEBUG("Here"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } r = sam4_auto_probe(bank); if (r != ERROR_OK) { LOG_DEBUG("Here,r=%d", r); return r; } pPrivate = get_sam4_bank_private(bank); if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; if ((first == 0) && ((last + 1) == ((int)(pPrivate->nsectors)))) { /* whole chip */ LOG_DEBUG("Here"); return FLASHD_EraseEntireBank(pPrivate); } LOG_INFO("sam4 does not auto-erase while programming (Erasing relevant sectors)"); LOG_INFO("sam4 First: 0x%08x Last: 0x%08x", (unsigned int)(first), (unsigned int)(last)); for (i = first; i <= last; i++) { /*16 pages equals 8KB - Same size as a lock region*/ r = FLASHD_ErasePages(pPrivate, (i * pageCount), pageCount, &status); LOG_INFO("Erasing sector: 0x%08x", (unsigned int)(i)); if (r != ERROR_OK) LOG_ERROR("SAM4: Error performing Erase page @ lock region number %d", (unsigned int)(i)); if (status & (1 << 2)) { LOG_ERROR("SAM4: Lock Region %d is locked", (unsigned int)(i)); return ERROR_FAIL; } if (status & (1 << 1)) { LOG_ERROR("SAM4: Flash Command error @lock region %d", (unsigned int)(i)); return ERROR_FAIL; } } return ERROR_OK; } static int sam4_protect(struct flash_bank *bank, int set, int first, int last) { struct sam4_bank_private *pPrivate; int r; LOG_DEBUG("Here"); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } pPrivate = get_sam4_bank_private(bank); if (!(pPrivate->probed)) return ERROR_FLASH_BANK_NOT_PROBED; if (set) r = FLASHD_Lock(pPrivate, (unsigned)(first), (unsigned)(last)); else r = FLASHD_Unlock(pPrivate, (unsigned)(first), (unsigned)(last)); LOG_DEBUG("End: r=%d", r); return r; } static int sam4_page_read(struct sam4_bank_private *pPrivate, unsigned pagenum, uint8_t *buf) { uint32_t adr; int r; adr = pagenum * pPrivate->page_size; adr = adr + pPrivate->base_address; r = target_read_memory(pPrivate->pChip->target, adr, 4, /* THIS*MUST*BE* in 32bit values */ pPrivate->page_size / 4, buf); if (r != ERROR_OK) LOG_ERROR("SAM4: Flash program failed to read page phys address: 0x%08x", (unsigned int)(adr)); return r; } static int sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; uint32_t fmr; /* EEFC Flash Mode Register */ int r; adr = pagenum * pPrivate->page_size; adr = (adr + pPrivate->base_address); /* Get flash mode register value */ r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr); if (r != ERROR_OK) LOG_DEBUG("Error Read failed: read flash mode register"); /* Clear flash wait state field */ fmr &= 0xfffff0ff; /* set FWS (flash wait states) field in the FMR (flash mode register) */ fmr |= (pPrivate->flash_wait_states << 8); LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr))); r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr); if (r != ERROR_OK) LOG_DEBUG("Error Write failed: set flash mode register"); /* 1st sector 8kBytes - page 0 - 15*/ /* 2nd sector 8kBytes - page 16 - 30*/ /* 3rd sector 48kBytes - page 31 - 127*/ LOG_DEBUG("Wr Page %u @ phys address: 0x%08x", pagenum, (unsigned int)(adr)); r = target_write_memory(pPrivate->pChip->target, adr, 4, /* THIS*MUST*BE* in 32bit values */ pPrivate->page_size / 4, buf); if (r != ERROR_OK) { LOG_ERROR("SAM4: Failed to write (buffer) page at phys address 0x%08x", (unsigned int)(adr)); return r; } r = EFC_PerformCommand(pPrivate, /* send Erase & Write Page */ AT91C_EFC_FCMD_WP, /*AT91C_EFC_FCMD_EWP only works on first two 8kb sectors*/ pagenum, &status); if (r != ERROR_OK) LOG_ERROR("SAM4: Error performing Write page @ phys address 0x%08x", (unsigned int)(adr)); if (status & (1 << 2)) { LOG_ERROR("SAM4: Page @ Phys address 0x%08x is locked", (unsigned int)(adr)); return ERROR_FAIL; } if (status & (1 << 1)) { LOG_ERROR("SAM4: Flash Command error @phys address 0x%08x", (unsigned int)(adr)); return ERROR_FAIL; } return ERROR_OK; } static int sam4_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int n; unsigned page_cur; unsigned page_end; int r; unsigned page_offset; struct sam4_bank_private *pPrivate; uint8_t *pagebuffer; /* incase we bail further below, set this to null */ pagebuffer = NULL; /* ignore dumb requests */ if (count == 0) { r = ERROR_OK; goto done; } if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); r = ERROR_TARGET_NOT_HALTED; goto done; } pPrivate = get_sam4_bank_private(bank); if (!(pPrivate->probed)) { r = ERROR_FLASH_BANK_NOT_PROBED; goto done; } if ((offset + count) > pPrivate->size_bytes) { LOG_ERROR("Flash write error - past end of bank"); LOG_ERROR(" offset: 0x%08x, count 0x%08x, BankEnd: 0x%08x", (unsigned int)(offset), (unsigned int)(count), (unsigned int)(pPrivate->size_bytes)); r = ERROR_FAIL; goto done; } pagebuffer = malloc(pPrivate->page_size); if (!pagebuffer) { LOG_ERROR("No memory for %d Byte page buffer", (int)(pPrivate->page_size)); r = ERROR_FAIL; goto done; } /* what page do we start & end in? */ page_cur = offset / pPrivate->page_size; page_end = (offset + count - 1) / pPrivate->page_size; LOG_DEBUG("Offset: 0x%08x, Count: 0x%08x", (unsigned int)(offset), (unsigned int)(count)); LOG_DEBUG("Page start: %d, Page End: %d", (int)(page_cur), (int)(page_end)); /* Special case: all one page */ /* */ /* Otherwise: */ /* (1) non-aligned start */ /* (2) body pages */ /* (3) non-aligned end. */ /* Handle special case - all one page. */ if (page_cur == page_end) { LOG_DEBUG("Special case, all in one page"); r = sam4_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; page_offset = (offset & (pPrivate->page_size-1)); memcpy(pagebuffer + page_offset, buffer, count); r = sam4_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; r = ERROR_OK; goto done; } /* non-aligned start */ page_offset = offset & (pPrivate->page_size - 1); if (page_offset) { LOG_DEBUG("Not-Aligned start"); /* read the partial */ r = sam4_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; /* over-write with new data */ n = (pPrivate->page_size - page_offset); memcpy(pagebuffer + page_offset, buffer, n); r = sam4_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; count -= n; offset += n; buffer += n; page_cur++; } /* By checking that offset is correct here, we also fix a clang warning */ assert(offset % pPrivate->page_size == 0); /* intermediate large pages */ /* also - the final *terminal* */ /* if that terminal page is a full page */ LOG_DEBUG("Full Page Loop: cur=%d, end=%d, count = 0x%08x", (int)page_cur, (int)page_end, (unsigned int)(count)); while ((page_cur < page_end) && (count >= pPrivate->page_size)) { r = sam4_page_write(pPrivate, page_cur, buffer); if (r != ERROR_OK) goto done; count -= pPrivate->page_size; buffer += pPrivate->page_size; page_cur += 1; } /* terminal partial page? */ if (count) { LOG_DEBUG("Terminal partial page, count = 0x%08x", (unsigned int)(count)); /* we have a partial page */ r = sam4_page_read(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; /* data goes at start */ memcpy(pagebuffer, buffer, count); r = sam4_page_write(pPrivate, page_cur, pagebuffer); if (r != ERROR_OK) goto done; } LOG_DEBUG("Done!"); r = ERROR_OK; done: if (pagebuffer) free(pagebuffer); return r; } COMMAND_HANDLER(sam4_handle_info_command) { struct sam4_chip *pChip; pChip = get_current_sam4(CMD_CTX); if (!pChip) return ERROR_OK; unsigned x; int r; /* bank0 must exist before we can do anything */ if (pChip->details.bank[0].pBank == NULL) { x = 0; need_define: command_print(CMD_CTX, "Please define bank %d via command: flash bank %s ... ", x, at91sam4_flash.name); return ERROR_FAIL; } /* if bank 0 is not probed, then probe it */ if (!(pChip->details.bank[0].probed)) { r = sam4_auto_probe(pChip->details.bank[0].pBank); if (r != ERROR_OK) return ERROR_FAIL; } /* above guarantees the "chip details" structure is valid */ /* and thus, bank private areas are valid */ /* and we have a SAM4 chip, what a concept! */ /* auto-probe other banks, 0 done above */ for (x = 1; x < SAM4_MAX_FLASH_BANKS; x++) { /* skip banks not present */ if (!(pChip->details.bank[x].present)) continue; if (pChip->details.bank[x].pBank == NULL) goto need_define; if (pChip->details.bank[x].probed) continue; r = sam4_auto_probe(pChip->details.bank[x].pBank); if (r != ERROR_OK) return r; } r = sam4_GetInfo(pChip); if (r != ERROR_OK) { LOG_DEBUG("Sam4Info, Failed %d", r); return r; } return ERROR_OK; } COMMAND_HANDLER(sam4_handle_gpnvm_command) { unsigned x, v; int r, who; struct sam4_chip *pChip; pChip = get_current_sam4(CMD_CTX); if (!pChip) return ERROR_OK; if (pChip->target->state != TARGET_HALTED) { LOG_ERROR("sam4 - target not halted"); return ERROR_TARGET_NOT_HALTED; } if (pChip->details.bank[0].pBank == NULL) { command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...", at91sam4_flash.name); return ERROR_FAIL; } if (!pChip->details.bank[0].probed) { r = sam4_auto_probe(pChip->details.bank[0].pBank); if (r != ERROR_OK) return r; } switch (CMD_ARGC) { default: return ERROR_COMMAND_SYNTAX_ERROR; break; case 0: goto showall; break; case 1: who = -1; break; case 2: if ((0 == strcmp(CMD_ARGV[0], "show")) && (0 == strcmp(CMD_ARGV[1], "all"))) who = -1; else { uint32_t v32; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32); who = v32; } break; } if (0 == strcmp("show", CMD_ARGV[0])) { if (who == -1) { showall: r = ERROR_OK; for (x = 0; x < pChip->details.n_gpnvms; x++) { r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v); if (r != ERROR_OK) break; command_print(CMD_CTX, "sam4-gpnvm%u: %u", x, v); } return r; } if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) { r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v); command_print(CMD_CTX, "sam4-gpnvm%u: %u", who, v); return r; } else { command_print(CMD_CTX, "sam4-gpnvm invalid GPNVM: %u", who); return ERROR_COMMAND_SYNTAX_ERROR; } } if (who == -1) { command_print(CMD_CTX, "Missing GPNVM number"); return ERROR_COMMAND_SYNTAX_ERROR; } if (0 == strcmp("set", CMD_ARGV[0])) r = FLASHD_SetGPNVM(&(pChip->details.bank[0]), who); else if ((0 == strcmp("clr", CMD_ARGV[0])) || (0 == strcmp("clear", CMD_ARGV[0]))) /* quietly accept both */ r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who); else { command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]); r = ERROR_COMMAND_SYNTAX_ERROR; } return r; } COMMAND_HANDLER(sam4_handle_slowclk_command) { struct sam4_chip *pChip; pChip = get_current_sam4(CMD_CTX); if (!pChip) return ERROR_OK; switch (CMD_ARGC) { case 0: /* show */ break; case 1: { /* set */ uint32_t v; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v); if (v > 200000) { /* absurd slow clock of 200Khz? */ command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v)); return ERROR_COMMAND_SYNTAX_ERROR; } pChip->cfg.slow_freq = v; break; } default: /* error */ command_print(CMD_CTX, "Too many parameters"); return ERROR_COMMAND_SYNTAX_ERROR; break; } command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz", (int)(pChip->cfg.slow_freq / 1000), (int)(pChip->cfg.slow_freq % 1000)); return ERROR_OK; } static const struct command_registration at91sam4_exec_command_handlers[] = { { .name = "gpnvm", .handler = sam4_handle_gpnvm_command, .mode = COMMAND_EXEC, .usage = "[('clr'|'set'|'show') bitnum]", .help = "Without arguments, shows all bits in the gpnvm " "register. Otherwise, clears, sets, or shows one " "General Purpose Non-Volatile Memory (gpnvm) bit.", }, { .name = "info", .handler = sam4_handle_info_command, .mode = COMMAND_EXEC, .help = "Print information about the current at91sam4 chip" "and its flash configuration.", }, { .name = "slowclk", .handler = sam4_handle_slowclk_command, .mode = COMMAND_EXEC, .usage = "[clock_hz]", .help = "Display or set the slowclock frequency " "(default 32768 Hz).", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91sam4_command_handlers[] = { { .name = "at91sam4", .mode = COMMAND_ANY, .help = "at91sam4 flash command group", .usage = "", .chain = at91sam4_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver at91sam4_flash = { .name = "at91sam4", .commands = at91sam4_command_handlers, .flash_bank_command = sam4_flash_bank_command, .erase = sam4_erase, .protect = sam4_protect, .write = sam4_write, .read = default_flash_read, .probe = sam4_probe, .auto_probe = sam4_auto_probe, .erase_check = default_flash_blank_check, .protect_check = sam4_protect_check, }; openocd-0.9.0/src/flash/nor/at91sam7.c0000644000175000017500000010307212315575360014276 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Gheorghe Guran (atlas) * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ****************************************************************************/ /*************************************************************************** * * New flash setup command: * * flash bank * [ * * * ] * * - MUST be used if clock is from external source, * CAN be used if main oscillator frequency is known (recommended) * Examples: * ==== RECOMMENDED (covers clock speed) ============ * flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 25000 * (if auto-detect fails; provides clock spec) * flash bank at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 25000 * (auto-detect everything except the clock) * ==== NOT RECOMMENDED !!! (clock speed is not configured) ==== * flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 0 * (if auto-detect fails) * flash bank at91sam7 0 0 0 0 $_TARGETNAME * (old style, auto-detect everything) ****************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include /* AT91SAM7 control registers */ #define DBGU_CIDR 0xFFFFF240 #define CKGR_MCFR 0xFFFFFC24 #define CKGR_MOR 0xFFFFFC20 #define CKGR_MCFR_MAINRDY 0x10000 #define CKGR_PLLR 0xFFFFFC2c #define CKGR_PLLR_DIV 0xff #define CKGR_PLLR_MUL 0x07ff0000 #define PMC_MCKR 0xFFFFFC30 #define PMC_MCKR_CSS 0x03 #define PMC_MCKR_PRES 0x1c /* Flash Controller Commands */ #define WP 0x01 #define SLB 0x02 #define WPL 0x03 #define CLB 0x04 #define EA 0x08 #define SGPB 0x0B #define CGPB 0x0D #define SSB 0x0F /* MC_FSR bit definitions */ #define MC_FSR_FRDY 1 #define MC_FSR_EOL 2 /* AT91SAM7 constants */ #define RC_FREQ 32000 /* Flash timing modes */ #define FMR_TIMING_NONE 0 #define FMR_TIMING_NVBITS 1 #define FMR_TIMING_FLASH 2 /* Flash size constants */ #define FLASH_SIZE_8KB 1 #define FLASH_SIZE_16KB 2 #define FLASH_SIZE_32KB 3 #define FLASH_SIZE_64KB 5 #define FLASH_SIZE_128KB 7 #define FLASH_SIZE_256KB 9 #define FLASH_SIZE_512KB 10 #define FLASH_SIZE_1024KB 12 #define FLASH_SIZE_2048KB 14 static int at91sam7_protect_check(struct flash_bank *bank); static int at91sam7_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number); static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode); static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout); static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t pagen); static const uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 }; static const uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 }; static const uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 }; static const char *EPROC[8] = { "Unknown", "ARM946-E", "ARM7TDMI", "Unknown", "ARM920T", "ARM926EJ-S", "Unknown", "Unknown" }; struct at91sam7_flash_bank { /* chip id register */ uint32_t cidr; uint16_t cidr_ext; uint16_t cidr_nvptyp; uint16_t cidr_arch; uint16_t cidr_sramsiz; uint16_t cidr_nvpsiz; uint16_t cidr_nvpsiz2; uint16_t cidr_eproc; uint16_t cidr_version; const char *target_name; /* flash auto-detection */ uint8_t flash_autodetection; /* flash geometry */ uint16_t pages_per_sector; uint16_t pagesize; uint16_t pages_in_lockregion; /* nv memory bits */ uint16_t num_lockbits_on; uint16_t lockbits; uint16_t num_nvmbits; uint16_t num_nvmbits_on; uint16_t nvmbits; uint8_t securitybit; /* 0: not init * 1: fmcn for nvbits (1uS) * 2: fmcn for flash (1.5uS) */ uint8_t flashmode; /* main clock status */ uint8_t mck_valid; uint32_t mck_freq; /* external clock frequency */ uint32_t ext_freq; }; #if 0 static long SRAMSIZ[16] = { -1, 0x0400, /* 1K */ 0x0800, /* 2K */ -1, 0x1c000, /* 112K */ 0x1000, /* 4K */ 0x14000, /* 80K */ 0x28000, /* 160K */ 0x2000, /* 8K */ 0x4000, /* 16K */ 0x8000, /* 32K */ 0x10000, /* 64K */ 0x20000, /* 128K */ 0x40000, /* 256K */ 0x18000, /* 96K */ 0x80000, /* 512K */ }; #endif static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number) { uint32_t fsr; target_read_u32(target, MC_FSR[bank_number], &fsr); return fsr; } /* Read clock configuration and set at91sam7_info->mck_freq */ static void at91sam7_read_clock_info(struct flash_bank *bank) { struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct target *target = bank->target; uint32_t mckr, mcfr, pllr, mor; unsigned long tmp = 0, mainfreq; /* Read Clock Generator Main Oscillator Register */ target_read_u32(target, CKGR_MOR, &mor); /* Read Clock Generator Main Clock Frequency Register */ target_read_u32(target, CKGR_MCFR, &mcfr); /* Read Master Clock Register*/ target_read_u32(target, PMC_MCKR, &mckr); /* Read Clock Generator PLL Register */ target_read_u32(target, CKGR_PLLR, &pllr); at91sam7_info->mck_valid = 0; at91sam7_info->mck_freq = 0; switch (mckr & PMC_MCKR_CSS) { case 0: /* Slow Clock */ at91sam7_info->mck_valid = 1; tmp = RC_FREQ; break; case 1: /* Main Clock */ if ((mcfr & CKGR_MCFR_MAINRDY) && (at91sam7_info->ext_freq == 0)) { at91sam7_info->mck_valid = 1; tmp = RC_FREQ / 16ul * (mcfr & 0xffff); } else if (at91sam7_info->ext_freq != 0) { at91sam7_info->mck_valid = 1; tmp = at91sam7_info->ext_freq; } break; case 2: /* Reserved */ break; case 3: /* PLL Clock */ if ((mcfr & CKGR_MCFR_MAINRDY) && (at91sam7_info->ext_freq == 0)) { target_read_u32(target, CKGR_PLLR, &pllr); if (!(pllr & CKGR_PLLR_DIV)) break; /* 0 Hz */ at91sam7_info->mck_valid = 1; mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff); /* Integer arithmetic should have sufficient precision * as long as PLL is properly configured. */ tmp = mainfreq / (pllr & CKGR_PLLR_DIV)* (((pllr & CKGR_PLLR_MUL) >> 16) + 1); } else if ((at91sam7_info->ext_freq != 0) && ((pllr&CKGR_PLLR_DIV) != 0)) { at91sam7_info->mck_valid = 1; tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)* (((pllr & CKGR_PLLR_MUL) >> 16) + 1); } break; } /* Prescaler adjust */ if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) { at91sam7_info->mck_valid = 0; at91sam7_info->mck_freq = 0; } else if (((mckr & PMC_MCKR_PRES) >> 2) != 0) at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2); else at91sam7_info->mck_freq = tmp; } /* Setup the timimg registers for nvbits or normal flash */ static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode) { uint32_t fmr, fmcn = 0, fws = 0; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct target *target = bank->target; if (mode && (mode != at91sam7_info->flashmode)) { /* Always round up (ceil) */ if (mode == FMR_TIMING_NVBITS) { if (at91sam7_info->cidr_arch == 0x60) { /* AT91SAM7A3 uses master clocks in 100 ns */ fmcn = (at91sam7_info->mck_freq/10000000ul) + 1; } else { /* master clocks in 1uS for ARCH 0x7 types */ fmcn = (at91sam7_info->mck_freq/1000000ul) + 1; } } else if (mode == FMR_TIMING_FLASH) { /* main clocks in 1.5uS */ fmcn = (at91sam7_info->mck_freq/1000000ul)+ (at91sam7_info->mck_freq/2000000ul) + 1; } /* hard overclocking */ if (fmcn > 0xFF) fmcn = 0xFF; /* Only allow fmcn = 0 if clock period is > 30 us = 33kHz. */ if (at91sam7_info->mck_freq <= 33333ul) fmcn = 0; /* Only allow fws = 0 if clock frequency is < 30 MHz. */ if (at91sam7_info->mck_freq > 30000000ul) fws = 1; LOG_DEBUG("fmcn[%i]: %i", bank->bank_number, (int)(fmcn)); fmr = fmcn << 16 | fws << 8; target_write_u32(target, MC_FMR[bank->bank_number], fmr); } at91sam7_info->flashmode = mode; } static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout) { uint32_t status; while ((!((status = at91sam7_get_flash_status(bank->target, bank->bank_number)) & waitbits)) && (timeout-- > 0)) { LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status); alive_sleep(1); } LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status); if (status & 0x0C) { LOG_ERROR("status register: 0x%" PRIx32 "", status); if (status & 0x4) LOG_ERROR("Lock Error Bit Detected, Operation Abort"); if (status & 0x8) LOG_ERROR("Invalid command and/or bad keyword, Operation Abort"); if (status & 0x10) LOG_ERROR("Security Bit Set, Operation Abort"); } return status; } /* Send one command to the AT91SAM flash controller */ static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t pagen) { uint32_t fcr; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct target *target = bank->target; fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd; target_write_u32(target, MC_FCR[bank->bank_number], fcr); LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u", fcr, bank->bank_number + 1, pagen); if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) { /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */ if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } /* Read device id register, main clock frequency register and fill in driver info structure */ static int at91sam7_read_part_info(struct flash_bank *bank) { struct at91sam7_flash_bank *at91sam7_info; struct target *target = bank->target; uint16_t bnk, sec; uint16_t arch; uint32_t cidr; uint8_t banks_num = 0; uint16_t num_nvmbits = 0; uint16_t sectors_num = 0; uint16_t pages_per_sector = 0; uint16_t page_size = 0; uint32_t ext_freq; uint32_t bank_size; uint32_t base_address = 0; char *target_name_t = "Unknown"; at91sam7_info = bank->driver_priv; if (at91sam7_info->cidr != 0) { /* flash already configured, update clock and check for protected sectors */ struct flash_bank *fb = bank; struct flash_bank *t_bank = bank; while (t_bank) { /* re-calculate master clock frequency */ at91sam7_read_clock_info(t_bank); /* no timming */ at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE); /* check protect state */ at91sam7_protect_check(t_bank); t_bank = fb->next; fb = t_bank; } return ERROR_OK; } /* Read and parse chip identification register */ target_read_u32(target, DBGU_CIDR, &cidr); if (cidr == 0) { LOG_WARNING("Cannot identify target as an AT91SAM"); return ERROR_FLASH_OPERATION_FAILED; } if (at91sam7_info->flash_autodetection == 0) { /* banks and sectors are already created, based on data from input file */ struct flash_bank *fb = bank; struct flash_bank *t_bank = bank; while (t_bank) { at91sam7_info = t_bank->driver_priv; at91sam7_info->cidr = cidr; at91sam7_info->cidr_ext = (cidr >> 31)&0x0001; at91sam7_info->cidr_nvptyp = (cidr >> 28)&0x0007; at91sam7_info->cidr_arch = (cidr >> 20)&0x00FF; at91sam7_info->cidr_sramsiz = (cidr >> 16)&0x000F; at91sam7_info->cidr_nvpsiz2 = (cidr >> 12)&0x000F; at91sam7_info->cidr_nvpsiz = (cidr >> 8)&0x000F; at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007; at91sam7_info->cidr_version = cidr&0x001F; /* calculate master clock frequency */ at91sam7_read_clock_info(t_bank); /* no timming */ at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE); /* check protect state */ at91sam7_protect_check(t_bank); t_bank = fb->next; fb = t_bank; } return ERROR_OK; } arch = (cidr >> 20)&0x00FF; /* check flash size */ switch ((cidr >> 8)&0x000F) { case FLASH_SIZE_8KB: break; case FLASH_SIZE_16KB: banks_num = 1; sectors_num = 8; pages_per_sector = 32; page_size = 64; base_address = 0x00100000; if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S161/16"; } break; case FLASH_SIZE_32KB: banks_num = 1; sectors_num = 8; pages_per_sector = 32; page_size = 128; base_address = 0x00100000; if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S321/32"; } if (arch == 0x72) { num_nvmbits = 3; target_name_t = "AT91SAM7SE32"; } break; case FLASH_SIZE_64KB: banks_num = 1; sectors_num = 16; pages_per_sector = 32; page_size = 128; base_address = 0x00100000; if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S64"; } break; case FLASH_SIZE_128KB: banks_num = 1; sectors_num = 8; pages_per_sector = 64; page_size = 256; base_address = 0x00100000; if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S128"; } if (arch == 0x71) { num_nvmbits = 3; target_name_t = "AT91SAM7XC128"; } if (arch == 0x72) { num_nvmbits = 3; target_name_t = "AT91SAM7SE128"; } if (arch == 0x75) { num_nvmbits = 3; target_name_t = "AT91SAM7X128"; } break; case FLASH_SIZE_256KB: banks_num = 1; sectors_num = 16; pages_per_sector = 64; page_size = 256; base_address = 0x00100000; if (arch == 0x60) { num_nvmbits = 3; target_name_t = "AT91SAM7A3"; } if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S256"; } if (arch == 0x71) { num_nvmbits = 3; target_name_t = "AT91SAM7XC256"; } if (arch == 0x72) { num_nvmbits = 3; target_name_t = "AT91SAM7SE256"; } if (arch == 0x75) { num_nvmbits = 3; target_name_t = "AT91SAM7X256"; } break; case FLASH_SIZE_512KB: banks_num = 2; sectors_num = 16; pages_per_sector = 64; page_size = 256; base_address = 0x00100000; if (arch == 0x70) { num_nvmbits = 2; target_name_t = "AT91SAM7S512"; } if (arch == 0x71) { num_nvmbits = 3; target_name_t = "AT91SAM7XC512"; } if (arch == 0x72) { num_nvmbits = 3; target_name_t = "AT91SAM7SE512"; } if (arch == 0x75) { num_nvmbits = 3; target_name_t = "AT91SAM7X512"; } break; case FLASH_SIZE_1024KB: break; case FLASH_SIZE_2048KB: break; } if (strcmp(target_name_t, "Unknown") == 0) { LOG_ERROR( "Target autodetection failed! Please specify target parameters in configuration file"); return ERROR_FLASH_OPERATION_FAILED; } ext_freq = at91sam7_info->ext_freq; /* calculate bank size */ bank_size = sectors_num * pages_per_sector * page_size; for (bnk = 0; bnk < banks_num; bnk++) { struct flash_bank *t_bank = bank; if (bnk > 0) { if (!t_bank->next) { /* create a new flash bank element */ struct flash_bank *fb = malloc(sizeof(struct flash_bank)); fb->target = target; fb->driver = bank->driver; fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank)); fb->name = "sam7_probed"; fb->next = NULL; /* link created bank in 'flash_banks' list */ t_bank->next = fb; } t_bank = t_bank->next; } t_bank->bank_number = bnk; t_bank->base = base_address + bnk * bank_size; t_bank->size = bank_size; t_bank->chip_width = 0; t_bank->bus_width = 4; t_bank->num_sectors = sectors_num; /* allocate sectors */ t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector)); for (sec = 0; sec < sectors_num; sec++) { t_bank->sectors[sec].offset = sec * pages_per_sector * page_size; t_bank->sectors[sec].size = pages_per_sector * page_size; t_bank->sectors[sec].is_erased = -1; t_bank->sectors[sec].is_protected = -1; } at91sam7_info = t_bank->driver_priv; at91sam7_info->cidr = cidr; at91sam7_info->cidr_ext = (cidr >> 31)&0x0001; at91sam7_info->cidr_nvptyp = (cidr >> 28)&0x0007; at91sam7_info->cidr_arch = (cidr >> 20)&0x00FF; at91sam7_info->cidr_sramsiz = (cidr >> 16)&0x000F; at91sam7_info->cidr_nvpsiz2 = (cidr >> 12)&0x000F; at91sam7_info->cidr_nvpsiz = (cidr >> 8)&0x000F; at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007; at91sam7_info->cidr_version = cidr&0x001F; at91sam7_info->target_name = target_name_t; at91sam7_info->flashmode = 0; at91sam7_info->ext_freq = ext_freq; at91sam7_info->num_nvmbits = num_nvmbits; at91sam7_info->num_nvmbits_on = 0; at91sam7_info->pagesize = page_size; at91sam7_info->pages_per_sector = pages_per_sector; /* calculate master clock frequency */ at91sam7_read_clock_info(t_bank); /* no timming */ at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE); /* check protect state */ at91sam7_protect_check(t_bank); } LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch); return ERROR_OK; } static int at91sam7_erase_check(struct flash_bank *bank) { struct target *target = bank->target; uint16_t retval; uint32_t blank; uint16_t fast_check; uint8_t *buffer; uint16_t nSector; uint16_t nByte; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); fast_check = 1; for (nSector = 0; nSector < bank->num_sectors; nSector++) { retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset, bank->sectors[nSector].size, &blank); if (retval != ERROR_OK) { fast_check = 0; break; } if (blank == 0xFF) bank->sectors[nSector].is_erased = 1; else bank->sectors[nSector].is_erased = 0; } if (fast_check) return ERROR_OK; LOG_USER("Running slow fallback erase check - add working memory"); buffer = malloc(bank->sectors[0].size); for (nSector = 0; nSector < bank->num_sectors; nSector++) { bank->sectors[nSector].is_erased = 1; retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4, bank->sectors[nSector].size/4, buffer); if (retval != ERROR_OK) return retval; for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) { if (buffer[nByte] != 0xFF) { bank->sectors[nSector].is_erased = 0; break; } } } free(buffer); return ERROR_OK; } static int at91sam7_protect_check(struct flash_bank *bank) { uint8_t lock_pos, gpnvm_pos; uint32_t status; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; if (at91sam7_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } status = at91sam7_get_flash_status(bank->target, bank->bank_number); at91sam7_info->lockbits = (status >> 16); at91sam7_info->num_lockbits_on = 0; for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) { if (((status >> (16 + lock_pos))&(0x0001)) == 1) { at91sam7_info->num_lockbits_on++; bank->sectors[lock_pos].is_protected = 1; } else bank->sectors[lock_pos].is_protected = 0; } /* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */ status = at91sam7_get_flash_status(bank->target, 0); at91sam7_info->securitybit = (status >> 4)&0x01; at91sam7_info->nvmbits = (status >> 8)&0xFF; at91sam7_info->num_nvmbits_on = 0; for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) { if (((status >> (8 + gpnvm_pos))&(0x01)) == 1) at91sam7_info->num_nvmbits_on++; } return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) { struct flash_bank *t_bank = bank; struct at91sam7_flash_bank *at91sam7_info; struct target *target = t_bank->target; uint32_t base_address; uint32_t bank_size; uint32_t ext_freq = 0; int chip_width; int bus_width; int banks_num; int num_sectors; uint16_t pages_per_sector; uint16_t page_size; uint16_t num_nvmbits; char *target_name_t; int bnk, sec; at91sam7_info = malloc(sizeof(struct at91sam7_flash_bank)); t_bank->driver_priv = at91sam7_info; /* part wasn't probed for info yet */ at91sam7_info->cidr = 0; at91sam7_info->flashmode = 0; at91sam7_info->ext_freq = 0; at91sam7_info->flash_autodetection = 0; if (CMD_ARGC < 13) { at91sam7_info->flash_autodetection = 1; return ERROR_OK; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], base_address); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], bus_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[8], banks_num); COMMAND_PARSE_NUMBER(int, CMD_ARGV[9], num_sectors); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[10], pages_per_sector); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[11], page_size); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[12], num_nvmbits); if (CMD_ARGC == 14) { unsigned long freq; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[13], freq); ext_freq = freq * 1000; at91sam7_info->ext_freq = ext_freq; } if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) || (pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) { at91sam7_info->flash_autodetection = 1; return ERROR_OK; } target_name_t = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char)); strcpy(target_name_t, CMD_ARGV[7]); /* calculate bank size */ bank_size = num_sectors * pages_per_sector * page_size; for (bnk = 0; bnk < banks_num; bnk++) { if (bnk > 0) { if (!t_bank->next) { /* create a new bank element */ struct flash_bank *fb = malloc(sizeof(struct flash_bank)); fb->target = target; fb->driver = bank->driver; fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank)); fb->name = "sam7_probed"; fb->next = NULL; /* link created bank in 'flash_banks' list */ t_bank->next = fb; } t_bank = t_bank->next; } t_bank->bank_number = bnk; t_bank->base = base_address + bnk * bank_size; t_bank->size = bank_size; t_bank->chip_width = chip_width; t_bank->bus_width = bus_width; t_bank->num_sectors = num_sectors; /* allocate sectors */ t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector)); for (sec = 0; sec < num_sectors; sec++) { t_bank->sectors[sec].offset = sec * pages_per_sector * page_size; t_bank->sectors[sec].size = pages_per_sector * page_size; t_bank->sectors[sec].is_erased = -1; t_bank->sectors[sec].is_protected = -1; } at91sam7_info = t_bank->driver_priv; at91sam7_info->target_name = target_name_t; at91sam7_info->flashmode = 0; at91sam7_info->ext_freq = ext_freq; at91sam7_info->num_nvmbits = num_nvmbits; at91sam7_info->num_nvmbits_on = 0; at91sam7_info->pagesize = page_size; at91sam7_info->pages_per_sector = pages_per_sector; } return ERROR_OK; } static int at91sam7_erase(struct flash_bank *bank, int first, int last) { struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; int sec; uint32_t nbytes, pos; uint8_t *buffer; uint8_t erase_all; if (at91sam7_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; erase_all = 0; if ((first == 0) && (last == (bank->num_sectors-1))) erase_all = 1; /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); if (erase_all) { if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; } else { /* allocate and clean buffer */ nbytes = (last - first + 1) * bank->sectors[first].size; buffer = malloc(nbytes * sizeof(uint8_t)); for (pos = 0; pos < nbytes; pos++) buffer[pos] = 0xFF; if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK) { free(buffer); return ERROR_FLASH_OPERATION_FAILED; } free(buffer); } /* mark erased sectors */ for (sec = first; sec <= last; sec++) bank->sectors[sec].is_erased = 1; return ERROR_OK; } static int at91sam7_protect(struct flash_bank *bank, int set, int first, int last) { uint32_t cmd; int sector; uint32_t pagen; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; if (at91sam7_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); for (sector = first; sector <= last; sector++) { if (set) cmd = SLB; else cmd = CLB; /* if we lock a page from one sector then entire sector will be locked, also, * if we unlock a page from a locked sector, entire sector will be unlocked */ pagen = sector * at91sam7_info->pages_per_sector; if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; } at91sam7_protect_check(bank); return ERROR_OK; } static int at91sam7_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int retval; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct target *target = bank->target; uint32_t dst_min_alignment, wcount, bytes_remaining = count; uint32_t first_page, last_page, pagen, buffer_pos; if (at91sam7_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; dst_min_alignment = at91sam7_info->pagesize; if (offset % dst_min_alignment) { LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, dst_min_alignment); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } if (at91sam7_info->cidr_arch == 0) return ERROR_FLASH_BANK_NOT_PROBED; first_page = offset/dst_min_alignment; last_page = DIV_ROUND_UP(offset + count, dst_min_alignment); LOG_DEBUG("first_page: %i, last_page: %i, count %i", (int)first_page, (int)last_page, (int)count); /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); for (pagen = first_page; pagen < last_page; pagen++) { if (bytes_remaining < dst_min_alignment) count = bytes_remaining; else count = dst_min_alignment; bytes_remaining -= count; /* Write one block to the PageWriteBuffer */ buffer_pos = (pagen-first_page)*dst_min_alignment; wcount = DIV_ROUND_UP(count, 4); retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4, wcount, buffer + buffer_pos); if (retval != ERROR_OK) return retval; /* Send Write Page command to Flash Controller */ if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen); } return ERROR_OK; } static int at91sam7_probe(struct flash_bank *bank) { /* we can't probe on an at91sam7 * if this is an at91sam7, it has the configured flash */ int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = at91sam7_read_part_info(bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; if (at91sam7_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; printed = snprintf(buf, buf_size, "\n at91sam7 driver information: Chip is %s\n", at91sam7_info->target_name); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, " Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | " "Flashsize: 0x%8.8" PRIx32 "\n", at91sam7_info->cidr, at91sam7_info->cidr_arch, EPROC[at91sam7_info->cidr_eproc], at91sam7_info->cidr_version, bank->size); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, " Master clock (estimated): %u KHz | External clock: %u KHz\n", (unsigned)(at91sam7_info->mck_freq / 1000), (unsigned)(at91sam7_info->ext_freq / 1000)); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, " Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n", at91sam7_info->pagesize, bank->num_sectors, at91sam7_info->num_lockbits_on, at91sam7_info->lockbits, at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on); buf += printed; buf_size -= printed; snprintf(buf, buf_size, " Securitybit: %i | Nvmbits(%i): %i 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->num_nvmbits, at91sam7_info->num_nvmbits_on, at91sam7_info->nvmbits); return ERROR_OK; } /* * On AT91SAM7S: When the gpnvm bits are set with * > at91sam7 gpnvm bitnr set * the changes are not visible in the flash controller status register MC_FSR * until the processor has been reset. * On the Olimex board this requires a power cycle. * Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3): * The maximum number of write/erase cycles for Non volatile Memory bits is 100. this includes * Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit. */ COMMAND_HANDLER(at91sam7_handle_gpnvm_command) { struct flash_bank *bank; int bit; uint8_t flashcmd; uint32_t status; struct at91sam7_flash_bank *at91sam7_info; int retval; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; bank = get_flash_bank_by_num_noprobe(0); if (bank == NULL) return ERROR_FLASH_BANK_INVALID; if (strcmp(bank->driver->name, "at91sam7")) { command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]); return ERROR_FLASH_BANK_INVALID; } if (bank->target->state != TARGET_HALTED) { LOG_ERROR("target has to be halted to perform flash operation"); return ERROR_TARGET_NOT_HALTED; } if (strcmp(CMD_ARGV[1], "set") == 0) flashcmd = SGPB; else if (strcmp(CMD_ARGV[1], "clear") == 0) flashcmd = CGPB; else return ERROR_COMMAND_SYNTAX_ERROR; at91sam7_info = bank->driver_priv; if (at91sam7_info->cidr == 0) { retval = at91sam7_read_part_info(bank); if (retval != ERROR_OK) return retval; } COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit); if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) { command_print(CMD_CTX, "gpnvm bit '#%s' is out of bounds for target %s", CMD_ARGV[0], at91sam7_info->target_name); return ERROR_OK; } /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; /* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */ status = at91sam7_get_flash_status(bank->target, 0); LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, flashcmd, bit, status); /* check protect state */ at91sam7_protect_check(bank); return ERROR_OK; } static const struct command_registration at91sam7_exec_command_handlers[] = { { .name = "gpnvm", .handler = at91sam7_handle_gpnvm_command, .mode = COMMAND_EXEC, .help = "set or clear one General Purpose Non-Volatile Memory " "(gpnvm) bit", .usage = "bitnum ('set'|'clear')", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91sam7_command_handlers[] = { { .name = "at91sam7", .mode = COMMAND_ANY, .help = "at91sam7 flash command group", .usage = "", .chain = at91sam7_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver at91sam7_flash = { .name = "at91sam7", .usage = "gpnvm ", .commands = at91sam7_command_handlers, .flash_bank_command = at91sam7_flash_bank_command, .erase = at91sam7_erase, .protect = at91sam7_protect, .write = at91sam7_write, .read = default_flash_read, .probe = at91sam7_probe, .auto_probe = at91sam7_probe, .erase_check = at91sam7_erase_check, .protect_check = at91sam7_protect_check, .info = get_at91sam7_info, }; openocd-0.9.0/src/flash/nor/at91samd.c0000644000175000017500000007277312516456302014365 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andrey Yurovsky * * Andrey Yurovsky * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "helper/binarybuffer.h" #define SAMD_NUM_SECTORS 16 #define SAMD_PAGE_SIZE_MAX 1024 #define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */ #define SAMD_USER_ROW ((uint32_t)0x00804000) /* User Row of Flash */ #define SAMD_PAC1 0x41000000 /* Peripheral Access Control 1 */ #define SAMD_DSU 0x41002000 /* Device Service Unit */ #define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */ #define SAMD_DSU_DID 0x18 /* Device ID register */ #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */ #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */ #define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */ #define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */ #define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */ #define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */ #define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */ #define SAMD_CMDEX_KEY 0xA5UL #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F)) /* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */ #define SAMD_NVM_CMD_ER 0x02 /* Erase Row */ #define SAMD_NVM_CMD_WP 0x04 /* Write Page */ #define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */ #define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */ #define SAMD_NVM_CMD_LR 0x40 /* Lock Region */ #define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */ #define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */ #define SAMD_NVM_CMD_CPRM 0x43 /* Clear Power Reduction Mode */ #define SAMD_NVM_CMD_PBC 0x44 /* Page Buffer Clear */ #define SAMD_NVM_CMD_SSB 0x45 /* Set Security Bit */ #define SAMD_NVM_CMD_INVALL 0x46 /* Invalidate all caches */ /* Known identifiers */ #define SAMD_PROCESSOR_M0 0x01 #define SAMD_FAMILY_D 0x00 #define SAMD_FAMILY_L 0x01 #define SAMD_SERIES_20 0x00 #define SAMD_SERIES_21 0x01 #define SAMD_SERIES_10 0x02 #define SAMD_SERIES_11 0x03 struct samd_part { uint8_t id; const char *name; uint32_t flash_kb; uint32_t ram_kb; }; /* Known SAMD10 parts */ static const struct samd_part samd10_parts[] = { { 0x0, "SAMD10D14AMU", 16, 4 }, { 0x1, "SAMD10D13AMU", 8, 4 }, { 0x2, "SAMD10D12AMU", 4, 4 }, { 0x3, "SAMD10D14ASU", 16, 4 }, { 0x4, "SAMD10D13ASU", 8, 4 }, { 0x5, "SAMD10D12ASU", 4, 4 }, { 0x6, "SAMD10C14A", 16, 4 }, { 0x7, "SAMD10C13A", 8, 4 }, { 0x8, "SAMD10C12A", 4, 4 }, }; /* Known SAMD11 parts */ static const struct samd_part samd11_parts[] = { { 0x0, "SAMD11D14AMU", 16, 4 }, { 0x1, "SAMD11D13AMU", 8, 4 }, { 0x2, "SAMD11D12AMU", 4, 4 }, { 0x3, "SAMD11D14ASU", 16, 4 }, { 0x4, "SAMD11D13ASU", 8, 4 }, { 0x5, "SAMD11D12ASU", 4, 4 }, { 0x6, "SAMD11C14A", 16, 4 }, { 0x7, "SAMD11C13A", 8, 4 }, { 0x8, "SAMD11C12A", 4, 4 }, }; /* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */ static const struct samd_part samd20_parts[] = { { 0x0, "SAMD20J18A", 256, 32 }, { 0x1, "SAMD20J17A", 128, 16 }, { 0x2, "SAMD20J16A", 64, 8 }, { 0x3, "SAMD20J15A", 32, 4 }, { 0x4, "SAMD20J14A", 16, 2 }, { 0x5, "SAMD20G18A", 256, 32 }, { 0x6, "SAMD20G17A", 128, 16 }, { 0x7, "SAMD20G16A", 64, 8 }, { 0x8, "SAMD20G15A", 32, 4 }, { 0x9, "SAMD20G14A", 16, 2 }, { 0xA, "SAMD20E18A", 256, 32 }, { 0xB, "SAMD20E17A", 128, 16 }, { 0xC, "SAMD20E16A", 64, 8 }, { 0xD, "SAMD20E15A", 32, 4 }, { 0xE, "SAMD20E14A", 16, 2 }, }; /* Known SAMD21 parts. */ static const struct samd_part samd21_parts[] = { { 0x0, "SAMD21J18A", 256, 32 }, { 0x1, "SAMD21J17A", 128, 16 }, { 0x2, "SAMD21J16A", 64, 8 }, { 0x3, "SAMD21J15A", 32, 4 }, { 0x4, "SAMD21J14A", 16, 2 }, { 0x5, "SAMD21G18A", 256, 32 }, { 0x6, "SAMD21G17A", 128, 16 }, { 0x7, "SAMD21G16A", 64, 8 }, { 0x8, "SAMD21G15A", 32, 4 }, { 0x9, "SAMD21G14A", 16, 2 }, { 0xA, "SAMD21E18A", 256, 32 }, { 0xB, "SAMD21E17A", 128, 16 }, { 0xC, "SAMD21E16A", 64, 8 }, { 0xD, "SAMD21E15A", 32, 4 }, { 0xE, "SAMD21E14A", 16, 2 }, }; /* Known SAMR21 parts. */ static const struct samd_part samr21_parts[] = { { 0x19, "SAMR21G18A", 256, 32 }, { 0x1A, "SAMR21G17A", 128, 32 }, { 0x1B, "SAMR21G16A", 64, 32 }, { 0x1C, "SAMR21E18A", 256, 32 }, { 0x1D, "SAMR21E17A", 128, 32 }, { 0x1E, "SAMR21E16A", 64, 32 }, }; /* Known SAML21 parts. */ static const struct samd_part saml21_parts[] = { { 0x00, "SAML21J18A", 256, 32 }, { 0x01, "SAML21J17A", 128, 16 }, { 0x02, "SAML21J16A", 64, 8 }, { 0x05, "SAML21G18A", 256, 32 }, { 0x06, "SAML21G17A", 128, 16 }, { 0x07, "SAML21G16A", 64, 8 }, { 0x0A, "SAML21E18A", 256, 32 }, { 0x0B, "SAML21E17A", 128, 16 }, { 0x0C, "SAML21E16A", 64, 8 }, { 0x0D, "SAML21E15A", 32, 4 }, }; /* Each family of parts contains a parts table in the DEVSEL field of DID. The * processor ID, family ID, and series ID are used to determine which exact * family this is and then we can use the corresponding table. */ struct samd_family { uint8_t processor; uint8_t family; uint8_t series; const struct samd_part *parts; size_t num_parts; }; /* Known SAMD families */ static const struct samd_family samd_families[] = { { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20, samd20_parts, ARRAY_SIZE(samd20_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21, samd21_parts, ARRAY_SIZE(samd21_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21, samr21_parts, ARRAY_SIZE(samr21_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10, samd10_parts, ARRAY_SIZE(samd10_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11, samd11_parts, ARRAY_SIZE(samd11_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_21, saml21_parts, ARRAY_SIZE(saml21_parts) }, }; struct samd_info { uint32_t page_size; int num_pages; int sector_size; bool probed; struct target *target; struct samd_info *next; }; static struct samd_info *samd_chips; static const struct samd_part *samd_find_part(uint32_t id) { uint8_t processor = (id >> 28); uint8_t family = (id >> 23) & 0x1F; uint8_t series = (id >> 16) & 0x3F; uint8_t devsel = id & 0xFF; for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) { if (samd_families[i].processor == processor && samd_families[i].series == series && samd_families[i].family == family) { for (unsigned j = 0; j < samd_families[i].num_parts; j++) { if (samd_families[i].parts[j].id == devsel) return &samd_families[i].parts[j]; } } } return NULL; } static int samd_protect_check(struct flash_bank *bank) { int res; uint16_t lock; res = target_read_u16(bank->target, SAMD_NVMCTRL + SAMD_NVMCTRL_LOCK, &lock); if (res != ERROR_OK) return res; /* Lock bits are active-low */ for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = !(lock & (1<> 16) & 0x7)); /* The NVMP field (bits 15:0) indicates the total number of pages */ if (nump) *nump = param & 0xFFFF; } else { LOG_ERROR("Couldn't read NVM Parameters register"); } return res; } static int samd_probe(struct flash_bank *bank) { uint32_t id; int res; struct samd_info *chip = (struct samd_info *)bank->driver_priv; const struct samd_part *part; if (chip->probed) return ERROR_OK; res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id); if (res != ERROR_OK) { LOG_ERROR("Couldn't read Device ID register"); return res; } part = samd_find_part(id); if (part == NULL) { LOG_ERROR("Couldn't find part correspoding to DID %08" PRIx32, id); return ERROR_FAIL; } bank->size = part->flash_kb * 1024; chip->sector_size = bank->size / SAMD_NUM_SECTORS; res = samd_get_flash_page_info(bank->target, &chip->page_size, &chip->num_pages); if (res != ERROR_OK) { LOG_ERROR("Couldn't determine Flash page size"); return res; } /* Sanity check: the total flash size in the DSU should match the page size * multiplied by the number of pages. */ if (bank->size != chip->num_pages * chip->page_size) { LOG_WARNING("SAMD: bank size doesn't match NVM parameters. " "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages", part->flash_kb, chip->num_pages, chip->page_size); } /* Allocate the sector table */ bank->num_sectors = SAMD_NUM_SECTORS; bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); if (!bank->sectors) return ERROR_FAIL; /* Fill out the sector information: all SAMD sectors are the same size and * there is always a fixed number of them. */ for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].size = chip->sector_size; bank->sectors[i].offset = i * chip->sector_size; /* mark as unknown */ bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } samd_protect_check(bank); /* Done */ chip->probed = true; LOG_INFO("SAMD MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name, part->flash_kb, part->ram_kb); return ERROR_OK; } static bool samd_check_error(struct target *target) { int ret; bool error; uint16_t status; ret = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status); if (ret != ERROR_OK) { LOG_ERROR("Can't read NVM status"); return true; } if (status & 0x001C) { if (status & (1 << 4)) /* NVME */ LOG_ERROR("SAMD: NVM Error"); if (status & (1 << 3)) /* LOCKE */ LOG_ERROR("SAMD: NVM lock error"); if (status & (1 << 2)) /* PROGE */ LOG_ERROR("SAMD: NVM programming error"); error = true; } else { error = false; } /* Clear the error conditions by writing a one to them */ ret = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status); if (ret != ERROR_OK) LOG_ERROR("Can't clear NVM error conditions"); return error; } static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) { if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Read current configuration. */ uint16_t tmp = 0; int res = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &tmp); if (res != ERROR_OK) return res; /* Set cache disable. */ res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, tmp | (1<<18)); if (res != ERROR_OK) return res; /* Issue the NVM command */ int res_cmd = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd)); /* Try to restore configuration, regardless of NVM command write * status. */ res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, tmp); if (res_cmd != ERROR_OK) return res_cmd; if (res != ERROR_OK) return res; /* Check to see if the NVM command resulted in an error condition. */ if (samd_check_error(target)) return ERROR_FAIL; return ERROR_OK; } static int samd_erase_row(struct target *target, uint32_t address) { int res; /* Set an address contained in the row to be erased */ res = target_write_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, address >> 1); /* Issue the Erase Row command to erase that row. */ if (res == ERROR_OK) res = samd_issue_nvmctrl_command(target, address == SAMD_USER_ROW ? SAMD_NVM_CMD_EAR : SAMD_NVM_CMD_ER); if (res != ERROR_OK) { LOG_ERROR("Failed to erase row containing %08" PRIx32, address); return ERROR_FAIL; } return ERROR_OK; } static bool is_user_row_reserved_bit(uint8_t bit) { /* See Table 9-3 in the SAMD20 datasheet for more information. */ switch (bit) { /* Reserved bits */ case 3: case 7: /* Voltage regulator internal configuration with default value of 0x70, * may not be changed. */ case 17 ... 24: /* 41 is voltage regulator internal configuration and must not be * changed. 42 through 47 are reserved. */ case 41 ... 47: return true; default: break; } return false; } /* Modify the contents of the User Row in Flash. These are described in Table * 9-3 of the SAMD20 datasheet. The User Row itself has a size of one page * and contains a combination of "fuses" and calibration data in bits 24:17. * We therefore try not to erase the row's contents unless we absolutely have * to and we don't permit modifying reserved bits. */ static int samd_modify_user_row(struct target *target, uint32_t value, uint8_t startb, uint8_t endb) { int res; if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) { LOG_ERROR("Can't modify bits in the requested range"); return ERROR_FAIL; } /* Retrieve the MCU's page size, in bytes. This is also the size of the * entire User Row. */ uint32_t page_size; res = samd_get_flash_page_info(target, &page_size, NULL); if (res != ERROR_OK) { LOG_ERROR("Couldn't determine Flash page size"); return res; } /* Make sure the size is sane before we allocate. */ assert(page_size > 0 && page_size <= SAMD_PAGE_SIZE_MAX); /* Make sure we're within the single page that comprises the User Row. */ if (startb >= (page_size * 8) || endb >= (page_size * 8)) { LOG_ERROR("Can't modify bits outside the User Row page range"); return ERROR_FAIL; } uint8_t *buf = malloc(page_size); if (!buf) return ERROR_FAIL; /* Read the user row (comprising one page) by half-words. */ res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf); if (res != ERROR_OK) goto out_user_row; /* We will need to erase before writing if the new value needs a '1' in any * position for which the current value had a '0'. Otherwise we can avoid * erasing. */ uint32_t cur = buf_get_u32(buf, startb, endb - startb + 1); if ((~cur) & value) { res = samd_erase_row(target, SAMD_USER_ROW); if (res != ERROR_OK) { LOG_ERROR("Couldn't erase user row"); goto out_user_row; } } /* Modify */ buf_set_u32(buf, startb, endb - startb + 1, value); /* Write the page buffer back out to the target. A Flash write will be * triggered automatically. */ res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); if (res != ERROR_OK) goto out_user_row; if (samd_check_error(target)) { res = ERROR_FAIL; goto out_user_row; } /* Success */ res = ERROR_OK; out_user_row: free(buf); return res; } static int samd_protect(struct flash_bank *bank, int set, int first, int last) { struct samd_info *chip = (struct samd_info *)bank->driver_priv; /* We can issue lock/unlock region commands with the target running but * the settings won't persist unless we're able to modify the LOCK regions * and that requires the target to be halted. */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int res = ERROR_OK; for (int s = first; s <= last; s++) { if (set != bank->sectors[s].is_protected) { /* Load an address that is within this sector (we use offset 0) */ res = target_write_u32(bank->target, SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, ((s * chip->sector_size) >> 1)); if (res != ERROR_OK) goto exit; /* Tell the controller to lock that sector */ res = samd_issue_nvmctrl_command(bank->target, set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR); if (res != ERROR_OK) goto exit; } } /* We've now applied our changes, however they will be undone by the next * reset unless we also apply them to the LOCK bits in the User Page. The * LOCK bits start at bit 48, correspoding to Sector 0 and end with bit 63, * corresponding to Sector 15. A '1' means unlocked and a '0' means * locked. See Table 9-3 in the SAMD20 datasheet for more details. */ res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF, 48 + first, 48 + last); if (res != ERROR_OK) LOG_WARNING("SAMD: protect settings were not made persistent!"); res = ERROR_OK; exit: samd_protect_check(bank); return res; } static int samd_erase(struct flash_bank *bank, int first, int last) { int res; int rows_in_sector; struct samd_info *chip = (struct samd_info *)bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (samd_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } /* The SAMD NVM has row erase granularity. There are four pages in a row * and the number of rows in a sector depends on the sector size, which in * turn depends on the Flash capacity as there is a fixed number of * sectors. */ rows_in_sector = chip->sector_size / (chip->page_size * 4); /* For each sector to be erased */ for (int s = first; s <= last; s++) { if (bank->sectors[s].is_protected) { LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s); return ERROR_FLASH_OPERATION_FAILED; } if (bank->sectors[s].is_erased != 1) { /* For each row in that sector */ for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) { res = samd_erase_row(bank->target, r * chip->page_size * 4); if (res != ERROR_OK) { LOG_ERROR("SAMD: failed to erase sector %d", s); return res; } } bank->sectors[s].is_erased = 1; } } return ERROR_OK; } static struct flash_sector *samd_find_sector_by_address(struct flash_bank *bank, uint32_t address) { struct samd_info *chip = (struct samd_info *)bank->driver_priv; for (int i = 0; i < bank->num_sectors; i++) { if (bank->sectors[i].offset <= address && address < bank->sectors[i].offset + chip->sector_size) return &bank->sectors[i]; } return NULL; } /* Write an entire row (four pages) from host buffer 'buf' to row-aligned * 'address' in the Flash. */ static int samd_write_row(struct flash_bank *bank, uint32_t address, const uint8_t *buf) { int res; struct samd_info *chip = (struct samd_info *)bank->driver_priv; struct flash_sector *sector = samd_find_sector_by_address(bank, address); if (!sector) { LOG_ERROR("Can't find sector corresponding to address 0x%08" PRIx32, address); return ERROR_FLASH_OPERATION_FAILED; } if (sector->is_protected) { LOG_ERROR("Trying to write to a protected sector at 0x%08" PRIx32, address); return ERROR_FLASH_OPERATION_FAILED; } /* Erase the row that we'll be writing to */ res = samd_erase_row(bank->target, address); if (res != ERROR_OK) return res; /* Now write the pages in this row. */ for (unsigned int i = 0; i < 4; i++) { bool error; /* Write the page contents to the target's page buffer. A page write * is issued automatically once the last location is written in the * page buffer (ie: a complete page has been written out). */ res = target_write_memory(bank->target, address, 4, chip->page_size / 4, buf); if (res != ERROR_OK) { LOG_ERROR("%s: %d", __func__, __LINE__); return res; } /* Access through AHB is stalled while flash is being programmed */ usleep(200); error = samd_check_error(bank->target); if (error) return ERROR_FAIL; /* Next page */ address += chip->page_size; buf += chip->page_size; } sector->is_erased = 0; return res; } /* Write partial contents into row-aligned 'address' on the Flash from host * buffer 'buf' by writing 'nb' of 'buf' at 'row_offset' into the Flash row. */ static int samd_write_row_partial(struct flash_bank *bank, uint32_t address, const uint8_t *buf, uint32_t row_offset, uint32_t nb) { int res; struct samd_info *chip = (struct samd_info *)bank->driver_priv; uint32_t row_size = chip->page_size * 4; uint8_t *rb = malloc(row_size); if (!rb) return ERROR_FAIL; assert(row_offset + nb < row_size); assert((address % row_size) == 0); /* Retrieve the full row contents from Flash */ res = target_read_memory(bank->target, address, 4, row_size / 4, rb); if (res != ERROR_OK) { free(rb); return res; } /* Insert our partial row over the data from Flash */ memcpy(rb + (row_offset % row_size), buf, nb); /* Write the row back out */ res = samd_write_row(bank, address, rb); free(rb); return res; } static int samd_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int res; uint32_t address; uint32_t nb = 0; struct samd_info *chip = (struct samd_info *)bank->driver_priv; uint32_t row_size = chip->page_size * 4; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (samd_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } if (offset % row_size) { /* We're starting at an unaligned offset so we'll write a partial row * comprising that offset and up to the end of that row. */ nb = row_size - (offset % row_size); if (nb > count) nb = count; } else if (count < row_size) { /* We're writing an aligned but partial row. */ nb = count; } address = (offset / row_size) * row_size + bank->base; if (nb > 0) { res = samd_write_row_partial(bank, address, buffer, offset % row_size, nb); if (res != ERROR_OK) return res; /* We're done with the row contents */ count -= nb; offset += nb; buffer += row_size; } /* There's at least one aligned row to write out. */ if (count >= row_size) { int nr = count / row_size + ((count % row_size) ? 1 : 0); unsigned int r = 0; for (unsigned int i = address / row_size; (i < (address / row_size) + nr) && count > 0; i++) { address = (i * row_size) + bank->base; if (count >= row_size) { res = samd_write_row(bank, address, buffer + (r * row_size)); /* Advance one row */ offset += row_size; count -= row_size; } else { res = samd_write_row_partial(bank, address, buffer + (r * row_size), 0, count); /* We're done after this. */ offset += count; count = 0; } r++; if (res != ERROR_OK) return res; } } return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command) { struct samd_info *chip = samd_chips; while (chip) { if (chip->target == bank->target) break; chip = chip->next; } if (!chip) { /* Create a new chip */ chip = calloc(1, sizeof(*chip)); if (!chip) return ERROR_FAIL; chip->target = bank->target; chip->probed = false; bank->driver_priv = chip; /* Insert it into the chips list (at head) */ chip->next = samd_chips; samd_chips = chip; } if (bank->base != SAMD_FLASH) { LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 "[at91samd series] )", bank->base, SAMD_FLASH); return ERROR_FAIL; } return ERROR_OK; } COMMAND_HANDLER(samd_handle_info_command) { return ERROR_OK; } COMMAND_HANDLER(samd_handle_chip_erase_command) { struct target *target = get_current_target(CMD_CTX); if (target) { /* Enable access to the DSU by disabling the write protect bit */ target_write_u32(target, SAMD_PAC1, (1<<1)); /* Tell the DSU to perform a full chip erase. It takes about 240ms to * perform the erase. */ target_write_u8(target, SAMD_DSU, (1<<4)); command_print(CMD_CTX, "chip erased"); } return ERROR_OK; } COMMAND_HANDLER(samd_handle_set_security_command) { int res = ERROR_OK; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) { command_print(CMD_CTX, "supply the \"enable\" argument to proceed."); return ERROR_COMMAND_SYNTAX_ERROR; } if (target) { if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB); /* Check (and clear) error conditions */ if (res == ERROR_OK) command_print(CMD_CTX, "chip secured on next power-cycle"); else command_print(CMD_CTX, "failed to secure chip"); } return res; } COMMAND_HANDLER(samd_handle_eeprom_command) { int res = ERROR_OK; struct target *target = get_current_target(CMD_CTX); if (target) { if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (CMD_ARGC >= 1) { int val = atoi(CMD_ARGV[0]); uint32_t code; if (val == 0) code = 7; else { /* Try to match size in bytes with corresponding size code */ for (code = 0; code <= 6; code++) { if (val == (2 << (13 - code))) break; } if (code > 6) { command_print(CMD_CTX, "Invalid EEPROM size. Please see " "datasheet for a list valid sizes."); return ERROR_COMMAND_SYNTAX_ERROR; } } res = samd_modify_user_row(target, code, 4, 6); } else { uint16_t val; res = target_read_u16(target, SAMD_USER_ROW, &val); if (res == ERROR_OK) { uint32_t size = ((val >> 4) & 0x7); /* grab size code */ if (size == 0x7) command_print(CMD_CTX, "EEPROM is disabled"); else { /* Otherwise, 6 is 256B, 0 is 16KB */ command_print(CMD_CTX, "EEPROM size is %u bytes", (2 << (13 - size))); } } } } return res; } COMMAND_HANDLER(samd_handle_bootloader_command) { int res = ERROR_OK; struct target *target = get_current_target(CMD_CTX); if (target) { if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Retrieve the MCU's page size, in bytes. */ uint32_t page_size; res = samd_get_flash_page_info(target, &page_size, NULL); if (res != ERROR_OK) { LOG_ERROR("Couldn't determine Flash page size"); return res; } if (CMD_ARGC >= 1) { int val = atoi(CMD_ARGV[0]); uint32_t code; if (val == 0) code = 7; else { /* Try to match size in bytes with corresponding size code */ for (code = 0; code <= 6; code++) { if ((unsigned int)val == (2UL << (8UL - code)) * page_size) break; } if (code > 6) { command_print(CMD_CTX, "Invalid bootloader size. Please " "see datasheet for a list valid sizes."); return ERROR_COMMAND_SYNTAX_ERROR; } } res = samd_modify_user_row(target, code, 0, 2); } else { uint16_t val; res = target_read_u16(target, SAMD_USER_ROW, &val); if (res == ERROR_OK) { uint32_t size = (val & 0x7); /* grab size code */ uint32_t nb; if (size == 0x7) nb = 0; else nb = (2 << (8 - size)) * page_size; /* There are 4 pages per row */ command_print(CMD_CTX, "Bootloader size is %" PRIu32 " bytes (%" PRIu32 " rows)", nb, (uint32_t)(nb / (page_size * 4))); } } } return res; } static const struct command_registration at91samd_exec_command_handlers[] = { { .name = "info", .handler = samd_handle_info_command, .mode = COMMAND_EXEC, .help = "Print information about the current at91samd chip" "and its flash configuration.", }, { .name = "chip-erase", .handler = samd_handle_chip_erase_command, .mode = COMMAND_EXEC, .help = "Erase the entire Flash by using the Chip" "Erase feature in the Device Service Unit (DSU).", }, { .name = "set-security", .handler = samd_handle_set_security_command, .mode = COMMAND_EXEC, .help = "Secure the chip's Flash by setting the Security Bit." "This makes it impossible to read the Flash contents." "The only way to undo this is to issue the chip-erase" "command.", }, { .name = "eeprom", .usage = "[size_in_bytes]", .handler = samd_handle_eeprom_command, .mode = COMMAND_EXEC, .help = "Show or set the EEPROM size setting, stored in the User Row." "Please see Table 20-3 of the SAMD20 datasheet for allowed values." "Changes are stored immediately but take affect after the MCU is" "reset.", }, { .name = "bootloader", .usage = "[size_in_bytes]", .handler = samd_handle_bootloader_command, .mode = COMMAND_EXEC, .help = "Show or set the bootloader size, stored in the User Row." "Please see Table 20-2 of the SAMD20 datasheet for allowed values." "Changes are stored immediately but take affect after the MCU is" "reset.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91samd_command_handlers[] = { { .name = "at91samd", .mode = COMMAND_ANY, .help = "at91samd flash command group", .usage = "", .chain = at91samd_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver at91samd_flash = { .name = "at91samd", .commands = at91samd_command_handlers, .flash_bank_command = samd_flash_bank_command, .erase = samd_erase, .protect = samd_protect, .write = samd_write, .read = default_flash_read, .probe = samd_probe, .auto_probe = samd_probe, .erase_check = default_flash_blank_check, .protect_check = samd_protect_check, }; openocd-0.9.0/src/flash/nor/non_cfi.c0000644000175000017500000003626512516456302014351 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2009 Michael Schwingen * * michael@schwingen.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "cfi.h" #include "non_cfi.h" #define KB 1024 #define MB (1024*1024) #define ERASE_REGION(num, size) (((size/256) << 16) | (num-1)) /* non-CFI compatible flashes */ static const struct non_cfi non_cfi_flashes[] = { { .mfr = CFI_MFR_SST, .id = 0xd4, .pri_id = 0x02, .dev_size = 64*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(16, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0xd5, .pri_id = 0x02, .dev_size = 128*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(32, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0xd6, .pri_id = 0x02, .dev_size = 256*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(64, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0xd7, .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(128, 4*KB) } }, { .mfr = CFI_MFR_AMD, /* Spansion AM29LV040B */ .id = 0x4f, .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(8, 64*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x2780, .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(128, 4*KB) } }, { .mfr = CFI_MFR_ST, .id = 0xd6, /* ST29F400BB */ .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(7, 64*KB) } }, { .mfr = CFI_MFR_ST, .id = 0xd5, /* ST29F400BT */ .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(7, 64*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 16*KB) } }, /* SST 39VF* do not support DQ5 status polling - this currently is only supported by the host algorithm, not by the target code using the work area. Only true for 8-bit and 32-bit wide memories. 16-bit wide memories without DQ5 status polling are supported by the target code. */ { .mfr = CFI_MFR_SST, .id = 0x2782, /* SST39xF160 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(512, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x2783, /* SST39VF320 */ .pri_id = 0x02, .dev_size = 4*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(1024, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x234b, /* SST39VF1601 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(512, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x274b, /* SST39WF1601 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(512, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x234a, /* SST39VF1602 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(512, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x235b, /* SST39VF3201 */ .pri_id = 0x02, .dev_size = 4*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(1024, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x235a, /* SST39VF3202 */ .pri_id = 0x02, .dev_size = 4*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(1024, 4*KB) } }, { .mfr = CFI_MFR_SST, .id = 0x236d, /* SST39VF6401B */ .pri_id = 0x02, .dev_size = 8*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { ERASE_REGION(2048, 4*KB) } }, { .mfr = CFI_MFR_AMD, .id = 0x22ab, /* AM29F400BB */ .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(7, 64*KB) } }, { .mfr = CFI_MFR_AMD, .id = 0x2223, /* AM29F400BT */ .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(7, 64*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 16*KB) } }, { .mfr = CFI_MFR_FUJITSU, .id = 0x226b, /* AM29SL800DB */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(15, 64*KB) } }, { .mfr = CFI_MFR_FUJITSU, .id = 0x22ea, /* MBM29SL800TE */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(15, 64*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 16*KB) } }, { .mfr = CFI_MFR_FUJITSU, .id = 0xba, /* 29LV400BC */ .pri_id = 0x02, .dev_size = 512*KB, .interface_desc = 0x1, /* x8 or x16 device w/ nBYTE */ .max_buf_write_size = 0x00, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(7, 64*KB) } }, { .mfr = CFI_MFR_AMIC, .id = 0xb31a, /* A29L800A */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(15, 64*KB) } }, { .mfr = CFI_MFR_MX, .id = 0x225b, /* MX29LV800B */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(15, 64*KB) } }, { .mfr = CFI_MFR_MX, .id = 0x2249, /* MX29LV160AB: 2MB */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(31, 64*KB) } }, { .mfr = CFI_MFR_MX, .id = 0x22C4, /* MX29LV160AT: 2MB */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(31, 64*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 16*KB) } }, { .mfr = CFI_MFR_EON, .id = 0x225b, /* EN29LV800BB */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(15, 64*KB) } }, { .mfr = CFI_MFR_ATMEL, .id = 0x00c0, /* Atmel 49BV1614 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 3, .erase_region_info = { ERASE_REGION(8, 8*KB), ERASE_REGION(2, 32*KB), ERASE_REGION(30, 64*KB) } }, { .mfr = CFI_MFR_ATMEL, .id = 0xC2, /* Atmel 49BV1614T */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 3, .erase_region_info = { ERASE_REGION(30, 64*KB), ERASE_REGION(2, 32*KB), ERASE_REGION(8, 8*KB) } }, { .mfr = CFI_MFR_AMD, .id = 0x225b, /* S29AL008D */ .pri_id = 0x02, .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { ERASE_REGION(1, 16*KB), ERASE_REGION(2, 8*KB), ERASE_REGION(1, 32*KB), ERASE_REGION(15, 64*KB) } }, { .mfr = 0, .id = 0, } }; void cfi_fixup_non_cfi(struct flash_bank *bank) { unsigned int mask; struct cfi_flash_bank *cfi_info = bank->driver_priv; const struct non_cfi *non_cfi = non_cfi_flashes; if (cfi_info->x16_as_x8) mask = 0xFF; else mask = 0xFFFF; for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) { if ((cfi_info->manufacturer == non_cfi->mfr) && (cfi_info->device_id == (non_cfi->id & mask))) break; } /* only fixup jedec flashs found in table */ if (!non_cfi->mfr) return; cfi_info->not_cfi = 1; /* fill in defaults for non-critical data */ cfi_info->vcc_min = 0x0; cfi_info->vcc_max = 0x0; cfi_info->vpp_min = 0x0; cfi_info->vpp_max = 0x0; /* these are used for timeouts - use vales that should be long enough for normal operation. */ cfi_info->word_write_timeout_typ = 0x0a; cfi_info->buf_write_timeout_typ = 0x0d; cfi_info->block_erase_timeout_typ = 0x0d; cfi_info->chip_erase_timeout_typ = 0x10; cfi_info->word_write_timeout_max = 0x0; cfi_info->buf_write_timeout_max = 0x0; cfi_info->block_erase_timeout_max = 0x0; cfi_info->chip_erase_timeout_max = 0x0; cfi_info->qry[0] = 'Q'; cfi_info->qry[1] = 'R'; cfi_info->qry[2] = 'Y'; cfi_info->pri_id = non_cfi->pri_id; cfi_info->pri_addr = 0x0; cfi_info->alt_id = 0x0; cfi_info->alt_addr = 0x0; cfi_info->alt_ext = NULL; cfi_info->interface_desc = non_cfi->interface_desc; cfi_info->max_buf_write_size = non_cfi->max_buf_write_size; cfi_info->status_poll_mask = non_cfi->status_poll_mask; cfi_info->num_erase_regions = non_cfi->num_erase_regions; size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) * cfi_info->num_erase_regions; cfi_info->erase_region_info = malloc(erase_region_info_size); memcpy(cfi_info->erase_region_info, non_cfi->erase_region_info, erase_region_info_size); cfi_info->dev_size = non_cfi->dev_size; if (cfi_info->pri_id == 0x2) { struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext)); pri_ext->pri[0] = 'P'; pri_ext->pri[1] = 'R'; pri_ext->pri[2] = 'I'; pri_ext->major_version = '1'; pri_ext->minor_version = '0'; pri_ext->SiliconRevision = 0x0; pri_ext->EraseSuspend = 0x0; pri_ext->EraseSuspend = 0x0; pri_ext->BlkProt = 0x0; pri_ext->TmpBlkUnprotect = 0x0; pri_ext->BlkProtUnprot = 0x0; pri_ext->SimultaneousOps = 0x0; pri_ext->BurstMode = 0x0; pri_ext->PageMode = 0x0; pri_ext->VppMin = 0x0; pri_ext->VppMax = 0x0; pri_ext->TopBottom = 0x0; pri_ext->_unlock1 = 0x5555; pri_ext->_unlock2 = 0x2AAA; pri_ext->_reversed_geometry = 0; cfi_info->pri_ext = pri_ext; } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) { LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported"); exit(-1); } } openocd-0.9.0/src/flash/nor/non_cfi.h0000644000175000017500000000341712315575360014352 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef NON_CFI_H #define NON_CFI_H struct non_cfi { uint16_t mfr; uint16_t id; uint16_t pri_id; uint32_t dev_size; uint16_t interface_desc; uint16_t max_buf_write_size; uint8_t num_erase_regions; uint32_t erase_region_info[6]; uint8_t status_poll_mask; }; void cfi_fixup_non_cfi(struct flash_bank *bank); #endif /* NON_CFI_H */ openocd-0.9.0/src/flash/nor/tms470.c0000644000175000017500000010575112315575360013774 00000000000000/*************************************************************************** * Copyright (C) 2007,2008 by Christopher Kilgour * * techie |_at_| whiterocker |_dot_| com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" /* ---------------------------------------------------------------------- * Internal Support, Helpers * ---------------------------------------------------------------------- */ struct tms470_flash_bank { unsigned ordinal; /* device identification register */ uint32_t device_ident_reg; uint32_t silicon_version; uint32_t technology_family; uint32_t rom_flash; uint32_t part_number; const char *part_name; }; static const struct flash_sector TMS470R1A256_SECTORS[] = { {0x00000000, 0x00002000, -1, -1}, {0x00002000, 0x00002000, -1, -1}, {0x00004000, 0x00002000, -1, -1}, {0x00006000, 0x00002000, -1, -1}, {0x00008000, 0x00008000, -1, -1}, {0x00010000, 0x00008000, -1, -1}, {0x00018000, 0x00008000, -1, -1}, {0x00020000, 0x00008000, -1, -1}, {0x00028000, 0x00008000, -1, -1}, {0x00030000, 0x00008000, -1, -1}, {0x00038000, 0x00002000, -1, -1}, {0x0003A000, 0x00002000, -1, -1}, {0x0003C000, 0x00002000, -1, -1}, {0x0003E000, 0x00002000, -1, -1}, }; #define TMS470R1A256_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A256_SECTORS) static const struct flash_sector TMS470R1A288_BANK0_SECTORS[] = { {0x00000000, 0x00002000, -1, -1}, {0x00002000, 0x00002000, -1, -1}, {0x00004000, 0x00002000, -1, -1}, {0x00006000, 0x00002000, -1, -1}, }; #define TMS470R1A288_BANK0_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A288_BANK0_SECTORS) static const struct flash_sector TMS470R1A288_BANK1_SECTORS[] = { {0x00040000, 0x00010000, -1, -1}, {0x00050000, 0x00010000, -1, -1}, {0x00060000, 0x00010000, -1, -1}, {0x00070000, 0x00010000, -1, -1}, }; #define TMS470R1A288_BANK1_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A288_BANK1_SECTORS) static const struct flash_sector TMS470R1A384_BANK0_SECTORS[] = { {0x00000000, 0x00002000, -1, -1}, {0x00002000, 0x00002000, -1, -1}, {0x00004000, 0x00004000, -1, -1}, {0x00008000, 0x00004000, -1, -1}, {0x0000C000, 0x00004000, -1, -1}, {0x00010000, 0x00004000, -1, -1}, {0x00014000, 0x00004000, -1, -1}, {0x00018000, 0x00002000, -1, -1}, {0x0001C000, 0x00002000, -1, -1}, {0x0001E000, 0x00002000, -1, -1}, }; #define TMS470R1A384_BANK0_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A384_BANK0_SECTORS) static const struct flash_sector TMS470R1A384_BANK1_SECTORS[] = { {0x00020000, 0x00008000, -1, -1}, {0x00028000, 0x00008000, -1, -1}, {0x00030000, 0x00008000, -1, -1}, {0x00038000, 0x00008000, -1, -1}, }; #define TMS470R1A384_BANK1_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A384_BANK1_SECTORS) static const struct flash_sector TMS470R1A384_BANK2_SECTORS[] = { {0x00040000, 0x00008000, -1, -1}, {0x00048000, 0x00008000, -1, -1}, {0x00050000, 0x00008000, -1, -1}, {0x00058000, 0x00008000, -1, -1}, }; #define TMS470R1A384_BANK2_NUM_SECTORS \ ARRAY_SIZE(TMS470R1A384_BANK2_SECTORS) /* ---------------------------------------------------------------------- */ static int tms470_read_part_info(struct flash_bank *bank) { struct tms470_flash_bank *tms470_info = bank->driver_priv; struct target *target = bank->target; uint32_t device_ident_reg; uint32_t silicon_version; uint32_t technology_family; uint32_t rom_flash; uint32_t part_number; const char *part_name; /* we shall not rely on the caller in this test, this function allocates memory, thus and executing the code more than once may cause memory leak */ if (tms470_info->device_ident_reg) return ERROR_OK; /* read and parse the device identification register */ target_read_u32(target, 0xFFFFFFF0, &device_ident_reg); LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg); if ((device_ident_reg & 7) == 0) { LOG_WARNING("Cannot identify target as a TMS470 family."); return ERROR_FLASH_OPERATION_FAILED; } silicon_version = (device_ident_reg >> 12) & 0xF; technology_family = (device_ident_reg >> 11) & 1; rom_flash = (device_ident_reg >> 10) & 1; part_number = (device_ident_reg >> 3) & 0x7f; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } /* * If the part number is known, determine if the flash bank is valid * based on the base address being within the known flash bank * ranges. Then fixup/complete the remaining fields of the flash * bank structure. */ switch (part_number) { case 0x0a: part_name = "TMS470R1A256"; if (bank->base >= 0x00040000) { LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; } tms470_info->ordinal = 0; bank->base = 0x00000000; bank->size = 256 * 1024; bank->num_sectors = TMS470R1A256_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS)); break; case 0x2b: part_name = "TMS470R1A288"; if (bank->base < 0x00008000) { tms470_info->ordinal = 0; bank->base = 0x00000000; bank->size = 32 * 1024; bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS)); } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) { tms470_info->ordinal = 1; bank->base = 0x00040000; bank->size = 256 * 1024; bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS)); } else { LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; } break; case 0x2d: part_name = "TMS470R1A384"; if (bank->base < 0x00020000) { tms470_info->ordinal = 0; bank->base = 0x00000000; bank->size = 128 * 1024; bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS)); } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) { tms470_info->ordinal = 1; bank->base = 0x00020000; bank->size = 128 * 1024; bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS)); } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) { tms470_info->ordinal = 2; bank->base = 0x00040000; bank->size = 128 * 1024; bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS; bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS)); if (!bank->sectors) return ERROR_FLASH_OPERATION_FAILED; (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS)); } else { LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; } break; default: LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number); return ERROR_FLASH_OPERATION_FAILED; } /* turn off memory selects */ target_write_u32(target, 0xFFFFFFE4, 0x00000000); target_write_u32(target, 0xFFFFFFE0, 0x00000000); bank->chip_width = 32; bank->bus_width = 32; LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.", part_name, (int)(silicon_version), (technology_family ? "1.8v" : "3.3v"), (rom_flash ? "rom" : "flash")); tms470_info->device_ident_reg = device_ident_reg; tms470_info->silicon_version = silicon_version; tms470_info->technology_family = technology_family; tms470_info->rom_flash = rom_flash; tms470_info->part_number = part_number; tms470_info->part_name = part_name; /* * Disable reset on address access violation. */ target_write_u32(target, 0xFFFFFFE0, 0x00004007); return ERROR_OK; } /* ---------------------------------------------------------------------- */ static uint32_t keysSet; static uint32_t flashKeys[4]; COMMAND_HANDLER(tms470_handle_flash_keyset_command) { if (CMD_ARGC > 4) return ERROR_COMMAND_SYNTAX_ERROR; else if (CMD_ARGC == 4) { int i; for (i = 0; i < 4; i++) { int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0; if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) { command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]); LOG_ERROR("could not process flash key %s", CMD_ARGV[i]); return ERROR_COMMAND_SYNTAX_ERROR; } } keysSet = 1; } else if (CMD_ARGC != 0) { command_print(CMD_CTX, "tms470 flash_keyset "); return ERROR_COMMAND_SYNTAX_ERROR; } if (keysSet) { command_print(CMD_CTX, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "", flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]); } else command_print(CMD_CTX, "flash keys not set"); return ERROR_OK; } static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,}; static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,}; static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff, 0xf0fff0ff, 0xf0fff0ff}; static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}; /* ---------------------------------------------------------------------- */ static int oscMHz = 12; COMMAND_HANDLER(tms470_handle_osc_megahertz_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; else if (CMD_ARGC == 1) sscanf(CMD_ARGV[0], "%d", &oscMHz); if (oscMHz <= 0) { LOG_ERROR("osc_megahertz must be positive and non-zero!"); command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!"); oscMHz = 12; return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "osc_megahertz=%d", oscMHz); return ERROR_OK; } /* ---------------------------------------------------------------------- */ static int plldis; COMMAND_HANDLER(tms470_handle_plldis_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; else if (CMD_ARGC == 1) { sscanf(CMD_ARGV[0], "%d", &plldis); plldis = plldis ? 1 : 0; } command_print(CMD_CTX, "plldis=%d", plldis); return ERROR_OK; } /* ---------------------------------------------------------------------- */ static int tms470_check_flash_unlocked(struct target *target) { uint32_t fmbbusy; target_read_u32(target, 0xFFE89C08, &fmbbusy); LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", fmbbusy, fmbbusy & 0x8000 ? "unlocked" : "LOCKED"); return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED; } /* ---------------------------------------------------------------------- */ static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set) { uint32_t glbctrl, fmmstat; int retval = ERROR_FLASH_OPERATION_FAILED; /* set GLBCTRL.4 */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10); /* only perform the key match when 3VSTAT is clear */ target_read_u32(target, 0xFFE8BC0C, &fmmstat); if (!(fmmstat & 0x08)) { unsigned i; uint32_t fmbptr, fmbac2, orig_fmregopt; target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07); /* wait for pump ready */ do { target_read_u32(target, 0xFFE8A814, &fmbptr); alive_sleep(1); } while (!(fmbptr & 0x0200)); /* force max wait states */ target_read_u32(target, 0xFFE88004, &fmbac2); target_write_u32(target, 0xFFE88004, fmbac2 | 0xff); /* save current access mode, force normal read mode */ target_read_u32(target, 0xFFE89C00, &orig_fmregopt); target_write_u32(target, 0xFFE89C00, 0x00); for (i = 0; i < 4; i++) { uint32_t tmp; /* There is no point displaying the value of tmp, it is * filtered by the chip. The purpose of this read is to * prime the unlocking logic rather than read out the value. */ target_read_u32(target, 0x00001FF0 + 4 * i, &tmp); LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]); target_write_u32(target, 0xFFE89C0C, key_set[i]); } if (ERROR_OK == tms470_check_flash_unlocked(target)) { /* * There seems to be a side-effect of reading the FMPKEY * register in that it re-enables the protection. So we * re-enable it. */ for (i = 0; i < 4; i++) { uint32_t tmp; target_read_u32(target, 0x00001FF0 + 4 * i, &tmp); target_write_u32(target, 0xFFE89C0C, key_set[i]); } retval = ERROR_OK; } /* restore settings */ target_write_u32(target, 0xFFE89C00, orig_fmregopt); target_write_u32(target, 0xFFE88004, fmbac2); } /* clear config bit */ target_write_u32(target, 0xFFFFFFDC, glbctrl); return retval; } /* ---------------------------------------------------------------------- */ static int tms470_unlock_flash(struct flash_bank *bank) { struct target *target = bank->target; const uint32_t *p_key_sets[5]; unsigned i, key_set_count; if (keysSet) { key_set_count = 5; p_key_sets[0] = flashKeys; p_key_sets[1] = FLASH_KEYS_ALL_ONES; p_key_sets[2] = FLASH_KEYS_ALL_ZEROS; p_key_sets[3] = FLASH_KEYS_MIX1; p_key_sets[4] = FLASH_KEYS_MIX2; } else { key_set_count = 4; p_key_sets[0] = FLASH_KEYS_ALL_ONES; p_key_sets[1] = FLASH_KEYS_ALL_ZEROS; p_key_sets[2] = FLASH_KEYS_MIX1; p_key_sets[3] = FLASH_KEYS_MIX2; } for (i = 0; i < key_set_count; i++) { if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) { LOG_INFO("tms470 flash is unlocked"); return ERROR_OK; } } LOG_WARNING("tms470 could not unlock flash memory protection level 2"); return ERROR_FLASH_OPERATION_FAILED; } /* ---------------------------------------------------------------------- */ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *bank) { uint32_t fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk; struct target *target = bank->target; struct tms470_flash_bank *tms470_info = bank->driver_priv; int result = ERROR_OK; /* * Select the desired bank to be programmed by writing BANK[2:0] of * FMMAC2. */ target_read_u32(target, 0xFFE8BC04, &fmmac2); fmmac2 &= ~0x0007; fmmac2 |= (tms470_info->ordinal & 7); target_write_u32(target, 0xFFE8BC04, fmmac2); LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2); /* * Disable level 1 sector protection by setting bit 15 of FMMAC1. */ target_read_u32(target, 0xFFE8BC00, &fmmac1); fmmac1 |= 0x8000; target_write_u32(target, 0xFFE8BC00, fmmac1); LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1); /* * FMTCREG = 0x2fc0; */ target_write_u32(target, 0xFFE8BC10, 0x2fc0); LOG_DEBUG("set fmtcreg = 0x2fc0"); /* * MAXPP = 50 */ target_write_u32(target, 0xFFE8A07C, 50); LOG_DEBUG("set fmmaxpp = 50"); /* * MAXCP = 0xf000 + 2000 */ target_write_u32(target, 0xFFE8A084, 0xf000 + 2000); LOG_DEBUG("set fmmaxcp = 0x%04x", 0xf000 + 2000); /* * configure VHV */ target_read_u32(target, 0xFFE8A080, &fmmaxep); if (fmmaxep == 0xf000) { fmmaxep = 0xf000 + 4095; target_write_u32(target, 0xFFE8A80C, 0x9964); LOG_DEBUG("set fmptr3 = 0x9964"); } else { fmmaxep = 0xa000 + 4095; target_write_u32(target, 0xFFE8A80C, 0x9b64); LOG_DEBUG("set fmptr3 = 0x9b64"); } target_write_u32(target, 0xFFE8A080, fmmaxep); LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep); /* * FMPTR4 = 0xa000 */ target_write_u32(target, 0xFFE8A810, 0xa000); LOG_DEBUG("set fmptr4 = 0xa000"); /* * FMPESETUP, delay parameter selected based on clock frequency. * * According to the TI App Note SPNU257 and flashing code, delay is * int((sysclk(MHz) + 1) / 2), with a minimum of 5. The system * clock is usually derived from the ZPLL module, and selected by * the plldis global. */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * oscMHz / (1 + (glbctrl & 7)); delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5; target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8)); LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8)); /* * FMPVEVACCESS, based on delay. */ k = delay | (delay << 8); target_write_u32(target, 0xFFE8A05C, k); LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k); /* * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay. */ k <<= 1; target_write_u32(target, 0xFFE8A034, k); LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k); target_write_u32(target, 0xFFE8A040, k); LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k); target_write_u32(target, 0xFFE8A024, k); LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k); /* * FMCVACCESS, based on delay. */ k = delay * 16; target_write_u32(target, 0xFFE8A060, k); LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k); /* * FMCSETUP, based on delay. */ k = 0x3000 | delay * 20; target_write_u32(target, 0xFFE8A020, k); LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k); /* * FMEHOLD, based on delay. */ k = (delay * 20) << 2; target_write_u32(target, 0xFFE8A038, k); LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k); /* * PWIDTH, CWIDTH, EWIDTH, based on delay. */ target_write_u32(target, 0xFFE8A050, delay * 8); LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8); target_write_u32(target, 0xFFE8A058, delay * 1000); LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000); target_write_u32(target, 0xFFE8A054, delay * 5400); LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400); return result; } /* ---------------------------------------------------------------------- */ static int tms470_flash_status(struct flash_bank *bank) { struct target *target = bank->target; int result = ERROR_OK; uint32_t fmmstat; target_read_u32(target, 0xFFE8BC0C, &fmmstat); LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat); if (fmmstat & 0x0080) { LOG_WARNING("tms470 flash command: erase still active after busy clear."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0040) { LOG_WARNING("tms470 flash command: program still active after busy clear."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0020) { LOG_WARNING("tms470 flash command: invalid data command."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0010) { LOG_WARNING("tms470 flash command: program, erase or validate sector failed."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0008) { LOG_WARNING("tms470 flash command: voltage instability detected."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0006) { LOG_WARNING("tms470 flash command: command suspend detected."); result = ERROR_FLASH_OPERATION_FAILED; } if (fmmstat & 0x0001) { LOG_WARNING("tms470 flash command: sector was locked."); result = ERROR_FLASH_OPERATION_FAILED; } return result; } /* ---------------------------------------------------------------------- */ static int tms470_erase_sector(struct flash_bank *bank, int sector) { uint32_t glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat; struct target *target = bank->target; uint32_t flashAddr = bank->base + bank->sectors[sector].offset; int result = ERROR_OK; /* * Set the bit GLBCTRL4 of the GLBCTRL register (in the System * module) to enable writing to the flash registers }. */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10); LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10); /* Force normal read mode. */ target_read_u32(target, 0xFFE89C00, &orig_fmregopt); target_write_u32(target, 0xFFE89C00, 0); LOG_DEBUG("set fmregopt = 0x%08x", 0); (void)tms470_flash_initialize_internal_state_machine(bank); /* * Select one or more bits in FMBSEA or FMBSEB to disable Level 1 * protection for the particular sector to be erased/written. */ if (sector < 16) { target_read_u32(target, 0xFFE88008, &fmbsea); target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector)); LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector)); } else { target_read_u32(target, 0xFFE8800C, &fmbseb); target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16))); LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16))); } bank->sectors[sector].is_protected = 0; /* * clear status regiser, sent erase command, kickoff erase */ target_write_u16(target, flashAddr, 0x0040); LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr); target_write_u16(target, flashAddr, 0x0020); LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr); target_write_u16(target, flashAddr, 0xffff); LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr); /* * Monitor FMMSTAT, busy until clear, then check and other flags for * ultimate result of the operation. */ do { target_read_u32(target, 0xFFE8BC0C, &fmmstat); if (fmmstat & 0x0100) alive_sleep(1); } while (fmmstat & 0x0100); result = tms470_flash_status(bank); if (sector < 16) { target_write_u32(target, 0xFFE88008, fmbsea); LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea); bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1; } else { target_write_u32(target, 0xFFE8800C, fmbseb); LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb); bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; } target_write_u32(target, 0xFFE89C00, orig_fmregopt); LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt); target_write_u32(target, 0xFFFFFFDC, glbctrl); LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl); if (result == ERROR_OK) bank->sectors[sector].is_erased = 1; return result; } /*---------------------------------------------------------------------- * Implementation of Flash Driver Interfaces *---------------------------------------------------------------------- */ static const struct command_registration tms470_any_command_handlers[] = { { .name = "flash_keyset", .usage = " ", .handler = tms470_handle_flash_keyset_command, .mode = COMMAND_ANY, .help = "tms470 flash_keyset ", }, { .name = "osc_megahertz", .usage = "", .handler = tms470_handle_osc_megahertz_command, .mode = COMMAND_ANY, .help = "tms470 osc_megahertz ", }, { .name = "plldis", .usage = "<0 | 1>", .handler = tms470_handle_plldis_command, .mode = COMMAND_ANY, .help = "tms470 plldis <0/1>", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration tms470_command_handlers[] = { { .name = "tms470", .mode = COMMAND_ANY, .help = "TI tms470 flash command group", .usage = "", .chain = tms470_any_command_handlers, }, COMMAND_REGISTRATION_DONE }; /* ---------------------------------------------------------------------- */ static int tms470_erase(struct flash_bank *bank, int first, int last) { struct tms470_flash_bank *tms470_info = bank->driver_priv; int sector, result = ERROR_OK; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } tms470_read_part_info(bank); if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last)) { LOG_ERROR("Sector range %d to %d invalid.", first, last); return ERROR_FLASH_SECTOR_INVALID; } result = tms470_unlock_flash(bank); if (result != ERROR_OK) return result; for (sector = first; sector <= last; sector++) { LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector); result = tms470_erase_sector(bank, sector); if (result != ERROR_OK) { LOG_ERROR("tms470 could not erase flash sector."); break; } else LOG_INFO("sector erased successfully."); } return result; } /* ---------------------------------------------------------------------- */ static int tms470_protect(struct flash_bank *bank, int set, int first, int last) { struct tms470_flash_bank *tms470_info = bank->driver_priv; struct target *target = bank->target; uint32_t fmmac2, fmbsea, fmbseb; int sector; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } tms470_read_part_info(bank); if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last)) { LOG_ERROR("Sector range %d to %d invalid.", first, last); return ERROR_FLASH_SECTOR_INVALID; } /* enable the appropriate bank */ target_read_u32(target, 0xFFE8BC04, &fmmac2); target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal); /* get the original sector proection flags for this bank */ target_read_u32(target, 0xFFE88008, &fmbsea); target_read_u32(target, 0xFFE8800C, &fmbseb); for (sector = 0; sector < bank->num_sectors; sector++) { if (sector < 16) { fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector); bank->sectors[sector].is_protected = set ? 1 : 0; } else { fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16)); bank->sectors[sector].is_protected = set ? 1 : 0; } } /* update the protection bits */ target_write_u32(target, 0xFFE88008, fmbsea); target_write_u32(target, 0xFFE8800C, fmbseb); return ERROR_OK; } /* ---------------------------------------------------------------------- */ static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat; int result = ERROR_OK; uint32_t i; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } tms470_read_part_info(bank); LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + offset); /* set GLBCTRL.4 */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10); (void)tms470_flash_initialize_internal_state_machine(bank); /* force max wait states */ target_read_u32(target, 0xFFE88004, &fmbac2); target_write_u32(target, 0xFFE88004, fmbac2 | 0xff); /* save current access mode, force normal read mode */ target_read_u32(target, 0xFFE89C00, &orig_fmregopt); target_write_u32(target, 0xFFE89C00, 0x00); /* * Disable Level 1 protection for all sectors to be erased/written. */ target_read_u32(target, 0xFFE88008, &fmbsea); target_write_u32(target, 0xFFE88008, 0xffff); target_read_u32(target, 0xFFE8800C, &fmbseb); target_write_u32(target, 0xFFE8800C, 0xffff); /* read MAXPP */ target_read_u32(target, 0xFFE8A07C, &fmmaxpp); for (i = 0; i < count; i += 2) { uint32_t addr = bank->base + offset + i; uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1]; if (word != 0xffff) { LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr); /* clear status register */ target_write_u16(target, addr, 0x0040); /* program flash command */ target_write_u16(target, addr, 0x0010); /* burn the 16-bit word (big-endian) */ target_write_u16(target, addr, word); /* * Monitor FMMSTAT, busy until clear, then check and other flags * for ultimate result of the operation. */ do { target_read_u32(target, 0xFFE8BC0C, &fmmstat); if (fmmstat & 0x0100) alive_sleep(1); } while (fmmstat & 0x0100); if (fmmstat & 0x3ff) { LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat); LOG_ERROR( "Could not program word 0x%04x at address 0x%08" PRIx32 ".", word, addr); result = ERROR_FLASH_OPERATION_FAILED; break; } } else LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr); } /* restore */ target_write_u32(target, 0xFFE88008, fmbsea); target_write_u32(target, 0xFFE8800C, fmbseb); target_write_u32(target, 0xFFE88004, fmbac2); target_write_u32(target, 0xFFE89C00, orig_fmregopt); target_write_u32(target, 0xFFFFFFDC, glbctrl); return result; } /* ---------------------------------------------------------------------- */ static int tms470_probe(struct flash_bank *bank) { if (bank->target->state != TARGET_HALTED) { LOG_WARNING("Cannot communicate... target not halted."); return ERROR_TARGET_NOT_HALTED; } return tms470_read_part_info(bank); } static int tms470_auto_probe(struct flash_bank *bank) { struct tms470_flash_bank *tms470_info = bank->driver_priv; if (tms470_info->device_ident_reg) return ERROR_OK; return tms470_probe(bank); } /* ---------------------------------------------------------------------- */ static int tms470_erase_check(struct flash_bank *bank) { struct target *target = bank->target; struct tms470_flash_bank *tms470_info = bank->driver_priv; int sector, result = ERROR_OK; uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt; static uint8_t buffer[64 * 1024]; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!tms470_info->device_ident_reg) tms470_read_part_info(bank); /* set GLBCTRL.4 */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10); /* save current access mode, force normal read mode */ target_read_u32(target, 0xFFE89C00, &orig_fmregopt); target_write_u32(target, 0xFFE89C00, 0x00); /* enable the appropriate bank */ target_read_u32(target, 0xFFE8BC04, &fmmac2); target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal); /* TCR = 0 */ target_write_u32(target, 0xFFE8BC10, 0x2fc0); /* clear TEZ in fmbrdy */ target_write_u32(target, 0xFFE88010, 0x0b); /* save current wait states, force max */ target_read_u32(target, 0xFFE88004, &fmbac2); target_write_u32(target, 0xFFE88004, fmbac2 | 0xff); /* * The TI primitives inspect the flash memory by reading one 32-bit * word at a time. Here we read an entire sector and inspect it in * an attempt to reduce the JTAG overhead. */ for (sector = 0; sector < bank->num_sectors; sector++) { if (bank->sectors[sector].is_erased != 1) { uint32_t i, addr = bank->base + bank->sectors[sector].offset; LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector); target_read_buffer(target, addr, bank->sectors[sector].size, buffer); bank->sectors[sector].is_erased = 1; for (i = 0; i < bank->sectors[sector].size; i++) { if (buffer[i] != 0xff) { LOG_WARNING("tms470 bank %d, sector %d, not erased.", tms470_info->ordinal, sector); LOG_WARNING( "at location 0x%08" PRIx32 ": flash data is 0x%02x.", addr + i, buffer[i]); bank->sectors[sector].is_erased = 0; break; } } } if (bank->sectors[sector].is_erased != 1) { result = ERROR_FLASH_SECTOR_NOT_ERASED; break; } else LOG_INFO("sector erased"); } /* reset TEZ, wait states, read mode, GLBCTRL.4 */ target_write_u32(target, 0xFFE88010, 0x0f); target_write_u32(target, 0xFFE88004, fmbac2); target_write_u32(target, 0xFFE89C00, orig_fmregopt); target_write_u32(target, 0xFFFFFFDC, glbctrl); return result; } /* ---------------------------------------------------------------------- */ static int tms470_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct tms470_flash_bank *tms470_info = bank->driver_priv; int sector, result = ERROR_OK; uint32_t fmmac2, fmbsea, fmbseb; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!tms470_info->device_ident_reg) tms470_read_part_info(bank); /* enable the appropriate bank */ target_read_u32(target, 0xFFE8BC04, &fmmac2); target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal); target_read_u32(target, 0xFFE88008, &fmbsea); target_read_u32(target, 0xFFE8800C, &fmbseb); for (sector = 0; sector < bank->num_sectors; sector++) { int protected; if (sector < 16) { protected = fmbsea & (1 << sector) ? 0 : 1; bank->sectors[sector].is_protected = protected; } else { protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; bank->sectors[sector].is_protected = protected; } LOG_DEBUG("bank %d sector %d is %s", tms470_info->ordinal, sector, protected ? "protected" : "not protected"); } return result; } /* ---------------------------------------------------------------------- */ static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size) { int used = 0; struct tms470_flash_bank *tms470_info = bank->driver_priv; if (!tms470_info->device_ident_reg) tms470_read_part_info(bank); if (!tms470_info->device_ident_reg) { (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n"); return ERROR_FLASH_OPERATION_FAILED; } used = snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n", tms470_info->part_name); buf += used; buf_size -= used; snprintf(buf, buf_size, "Flash protection level 2 is %s\n", tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled"); return ERROR_OK; } /* ---------------------------------------------------------------------- */ /* * flash bank tms470 * [options...] */ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command) { bank->driver_priv = malloc(sizeof(struct tms470_flash_bank)); if (!bank->driver_priv) return ERROR_FLASH_OPERATION_FAILED; (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank)); return ERROR_OK; } struct flash_driver tms470_flash = { .name = "tms470", .commands = tms470_command_handlers, .flash_bank_command = tms470_flash_bank_command, .erase = tms470_erase, .protect = tms470_protect, .write = tms470_write, .read = default_flash_read, .probe = tms470_probe, .auto_probe = tms470_auto_probe, .erase_check = tms470_erase_check, .protect_check = tms470_protect_check, .info = get_tms470_info, }; openocd-0.9.0/src/flash/nor/avrf.c0000644000175000017500000003437312516456302013672 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * SimonQian@SimonQian.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include /* AVR_JTAG_Instructions */ #define AVR_JTAG_INS_LEN 4 /* Public Instructions: */ #define AVR_JTAG_INS_EXTEST 0x00 #define AVR_JTAG_INS_IDCODE 0x01 #define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02 #define AVR_JTAG_INS_BYPASS 0x0F /* AVR Specified Public Instructions: */ #define AVR_JTAG_INS_AVR_RESET 0x0C #define AVR_JTAG_INS_PROG_ENABLE 0x04 #define AVR_JTAG_INS_PROG_COMMANDS 0x05 #define AVR_JTAG_INS_PROG_PAGELOAD 0x06 #define AVR_JTAG_INS_PROG_PAGEREAD 0x07 /* Data Registers: */ #define AVR_JTAG_REG_Bypass_Len 1 #define AVR_JTAG_REG_DeviceID_Len 32 #define AVR_JTAG_REG_Reset_Len 1 #define AVR_JTAG_REG_JTAGID_Len 32 #define AVR_JTAG_REG_ProgrammingEnable_Len 16 #define AVR_JTAG_REG_ProgrammingCommand_Len 15 #define AVR_JTAG_REG_FlashDataByte_Len 16 struct avrf_type { char name[15]; uint16_t chip_id; int flash_page_size; int flash_page_num; int eeprom_page_size; int eeprom_page_num; }; struct avrf_flash_bank { int ppage_size; int probed; }; static const struct avrf_type avft_chips_info[] = { /* name, chip_id, flash_page_size, flash_page_num, * eeprom_page_size, eeprom_page_num */ {"atmega128", 0x9702, 256, 512, 8, 512}, {"at90can128", 0x9781, 256, 512, 8, 512}, {"at90usb128", 0x9782, 256, 512, 8, 512}, {"atmega164p", 0x940a, 128, 128, 4, 128}, {"atmega324p", 0x9508, 128, 256, 4, 256}, {"atmega324pa", 0x9511, 128, 256, 4, 256}, {"atmega644p", 0x960a, 256, 256, 8, 256}, {"atmega1284p", 0x9705, 256, 512, 8, 512}, }; /* avr program functions */ static int avr_jtag_reset(struct avr_common *avr, uint32_t reset) { avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_AVR_RESET); avr_jtag_senddat(avr->jtag_info.tap, NULL, reset, AVR_JTAG_REG_Reset_Len); return ERROR_OK; } static int avr_jtag_read_jtagid(struct avr_common *avr, uint32_t *id) { avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_IDCODE); avr_jtag_senddat(avr->jtag_info.tap, id, 0, AVR_JTAG_REG_JTAGID_Len); return ERROR_OK; } static int avr_jtagprg_enterprogmode(struct avr_common *avr) { avr_jtag_reset(avr, 1); avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xA370, AVR_JTAG_REG_ProgrammingEnable_Len); return ERROR_OK; } static int avr_jtagprg_leaveprogmode(struct avr_common *avr) { avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2300, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0, AVR_JTAG_REG_ProgrammingEnable_Len); avr_jtag_reset(avr, 0); return ERROR_OK; } static int avr_jtagprg_chiperase(struct avr_common *avr) { uint32_t poll_value; avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2380, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3180, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len); do { poll_value = 0; avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len); if (ERROR_OK != mcu_execute_queue()) return ERROR_FAIL; LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); } while (!(poll_value & 0x0200)); return ERROR_OK; } static int avr_jtagprg_writeflashpage(struct avr_common *avr, const uint8_t *page_buf, uint32_t buf_size, uint32_t addr, uint32_t page_size) { uint32_t i, poll_value; avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len); /* load addr high byte */ avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0700 | ((addr >> 9) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); /* load addr low byte */ avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0300 | ((addr >> 1) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD); for (i = 0; i < page_size; i++) { if (i < buf_size) avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8); else avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8); } avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3500, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len); do { poll_value = 0; avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len); if (ERROR_OK != mcu_execute_queue()) return ERROR_FAIL; LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); } while (!(poll_value & 0x0200)); return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command) { struct avrf_flash_bank *avrf_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; avrf_info = malloc(sizeof(struct avrf_flash_bank)); bank->driver_priv = avrf_info; avrf_info->probed = 0; return ERROR_OK; } static int avrf_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct avr_common *avr = target->arch_info; int status; LOG_DEBUG("%s", __func__); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } status = avr_jtagprg_enterprogmode(avr); if (status != ERROR_OK) return status; status = avr_jtagprg_chiperase(avr); if (status != ERROR_OK) return status; return avr_jtagprg_leaveprogmode(avr); } static int avrf_protect(struct flash_bank *bank, int set, int first, int last) { LOG_INFO("%s", __func__); return ERROR_OK; } static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct avr_common *avr = target->arch_info; uint32_t cur_size, cur_buffer_size, page_size; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } page_size = bank->sectors[0].size; if ((offset % page_size) != 0) { LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", offset, page_size); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } LOG_DEBUG("offset is 0x%08" PRIx32 "", offset); LOG_DEBUG("count is %" PRId32 "", count); if (ERROR_OK != avr_jtagprg_enterprogmode(avr)) return ERROR_FAIL; cur_size = 0; while (count > 0) { if (count > page_size) cur_buffer_size = page_size; else cur_buffer_size = count; avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size); count -= cur_buffer_size; cur_size += cur_buffer_size; keep_alive(); } return avr_jtagprg_leaveprogmode(avr); } #define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) static int avrf_probe(struct flash_bank *bank) { struct target *target = bank->target; struct avrf_flash_bank *avrf_info = bank->driver_priv; struct avr_common *avr = target->arch_info; const struct avrf_type *avr_info = NULL; int i; uint32_t device_id; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } avrf_info->probed = 0; avr_jtag_read_jtagid(avr, &device_id); if (ERROR_OK != mcu_execute_queue()) return ERROR_FAIL; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); if (EXTRACT_MFG(device_id) != 0x1F) LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { avr_info = &avft_chips_info[i]; LOG_INFO("target device is %s", avr_info->name); break; } } if (avr_info != NULL) { if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } /* chip found */ bank->base = 0x00000000; bank->size = (avr_info->flash_page_size * avr_info->flash_page_num); bank->num_sectors = avr_info->flash_page_num; bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num); for (i = 0; i < avr_info->flash_page_num; i++) { bank->sectors[i].offset = i * avr_info->flash_page_size; bank->sectors[i].size = avr_info->flash_page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } avrf_info->probed = 1; return ERROR_OK; } else { /* chip not supported */ LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id)); avrf_info->probed = 1; return ERROR_FAIL; } } static int avrf_auto_probe(struct flash_bank *bank) { struct avrf_flash_bank *avrf_info = bank->driver_priv; if (avrf_info->probed) return ERROR_OK; return avrf_probe(bank); } static int avrf_protect_check(struct flash_bank *bank) { LOG_INFO("%s", __func__); return ERROR_OK; } static int avrf_info(struct flash_bank *bank, char *buf, int buf_size) { struct target *target = bank->target; struct avr_common *avr = target->arch_info; const struct avrf_type *avr_info = NULL; int i; uint32_t device_id; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } avr_jtag_read_jtagid(avr, &device_id); if (ERROR_OK != mcu_execute_queue()) return ERROR_FAIL; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); if (EXTRACT_MFG(device_id) != 0x1F) LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { avr_info = &avft_chips_info[i]; LOG_INFO("target device is %s", avr_info->name); break; } } if (avr_info != NULL) { /* chip found */ snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, EXTRACT_VER(device_id)); return ERROR_OK; } else { /* chip not supported */ snprintf(buf, buf_size, "Cannot identify target as a avr\n"); return ERROR_FLASH_OPERATION_FAILED; } } static int avrf_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; struct avr_common *avr = target->arch_info; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((ERROR_OK != avr_jtagprg_enterprogmode(avr)) || (ERROR_OK != avr_jtagprg_chiperase(avr)) || (ERROR_OK != avr_jtagprg_leaveprogmode(avr))) return ERROR_FAIL; return ERROR_OK; } COMMAND_HANDLER(avrf_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; if (avrf_mass_erase(bank) == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "avr mass erase complete"); } else command_print(CMD_CTX, "avr mass erase failed"); LOG_DEBUG("%s", __func__); return ERROR_OK; } static const struct command_registration avrf_exec_command_handlers[] = { { .name = "mass_erase", .usage = "", .handler = avrf_handle_mass_erase_command, .mode = COMMAND_EXEC, .help = "erase entire device", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration avrf_command_handlers[] = { { .name = "avrf", .mode = COMMAND_ANY, .help = "AVR flash command group", .usage = "", .chain = avrf_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver avr_flash = { .name = "avr", .commands = avrf_command_handlers, .flash_bank_command = avrf_flash_bank_command, .erase = avrf_erase, .protect = avrf_protect, .write = avrf_write, .read = default_flash_read, .probe = avrf_probe, .auto_probe = avrf_auto_probe, .erase_check = default_flash_blank_check, .protect_check = avrf_protect_check, .info = avrf_info, }; openocd-0.9.0/src/flash/nor/str7x.c0000644000175000017500000005545312315575360014030 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include /* Flash registers */ #define FLASH_CR0 0x00000000 #define FLASH_CR1 0x00000004 #define FLASH_DR0 0x00000008 #define FLASH_DR1 0x0000000C #define FLASH_AR 0x00000010 #define FLASH_ER 0x00000014 #define FLASH_NVWPAR 0x0000DFB0 #define FLASH_NVAPR0 0x0000DFB8 #define FLASH_NVAPR1 0x0000DFBC /* FLASH_CR0 register bits */ #define FLASH_WMS 0x80000000 #define FLASH_SUSP 0x40000000 #define FLASH_WPG 0x20000000 #define FLASH_DWPG 0x10000000 #define FLASH_SER 0x08000000 #define FLASH_SPR 0x01000000 #define FLASH_BER 0x04000000 #define FLASH_MER 0x02000000 #define FLASH_LOCK 0x00000010 #define FLASH_BSYA1 0x00000004 #define FLASH_BSYA0 0x00000002 /* FLASH_CR1 register bits */ #define FLASH_B1S 0x02000000 #define FLASH_B0S 0x01000000 #define FLASH_B1F1 0x00020000 #define FLASH_B1F0 0x00010000 #define FLASH_B0F7 0x00000080 #define FLASH_B0F6 0x00000040 #define FLASH_B0F5 0x00000020 #define FLASH_B0F4 0x00000010 #define FLASH_B0F3 0x00000008 #define FLASH_B0F2 0x00000004 #define FLASH_B0F1 0x00000002 #define FLASH_B0F0 0x00000001 /* FLASH_ER register bits */ #define FLASH_WPF 0x00000100 #define FLASH_RESER 0x00000080 #define FLASH_SEQER 0x00000040 #define FLASH_10ER 0x00000008 #define FLASH_PGER 0x00000004 #define FLASH_ERER 0x00000002 #define FLASH_ERR 0x00000001 struct str7x_flash_bank { uint32_t *sector_bits; uint32_t disable_bit; uint32_t busy_bits; uint32_t register_base; }; struct str7x_mem_layout { uint32_t sector_start; uint32_t sector_size; uint32_t sector_bit; }; enum str7x_status_codes { STR7X_CMD_SUCCESS = 0, STR7X_INVALID_COMMAND = 1, STR7X_SRC_ADDR_ERROR = 2, STR7X_DST_ADDR_ERROR = 3, STR7X_SRC_ADDR_NOT_MAPPED = 4, STR7X_DST_ADDR_NOT_MAPPED = 5, STR7X_COUNT_ERROR = 6, STR7X_INVALID_SECTOR = 7, STR7X_SECTOR_NOT_BLANK = 8, STR7X_SECTOR_NOT_PREPARED = 9, STR7X_COMPARE_ERROR = 10, STR7X_BUSY = 11 }; static const struct str7x_mem_layout mem_layout_str7bank0[] = { {0x00000000, 0x02000, 0x01}, {0x00002000, 0x02000, 0x02}, {0x00004000, 0x02000, 0x04}, {0x00006000, 0x02000, 0x08}, {0x00008000, 0x08000, 0x10}, {0x00010000, 0x10000, 0x20}, {0x00020000, 0x10000, 0x40}, {0x00030000, 0x10000, 0x80} }; static const struct str7x_mem_layout mem_layout_str7bank1[] = { {0x00000000, 0x02000, 0x10000}, {0x00002000, 0x02000, 0x20000} }; static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg) { struct str7x_flash_bank *str7x_info = bank->driver_priv; return str7x_info->register_base | reg; } static int str7x_build_block_list(struct flash_bank *bank) { struct str7x_flash_bank *str7x_info = bank->driver_priv; int i; int num_sectors; int b0_sectors = 0, b1_sectors = 0; switch (bank->size) { case 16 * 1024: b1_sectors = 2; break; case 64 * 1024: b0_sectors = 5; break; case 128 * 1024: b0_sectors = 6; break; case 256 * 1024: b0_sectors = 8; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } num_sectors = b0_sectors + b1_sectors; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); str7x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors); num_sectors = 0; for (i = 0; i < b0_sectors; i++) { bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start; bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size; bank->sectors[num_sectors].is_erased = -1; /* the reset_init handler marks all the sectors unprotected, * matching hardware after reset; keep the driver in sync */ bank->sectors[num_sectors].is_protected = 0; str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit; } for (i = 0; i < b1_sectors; i++) { bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start; bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size; bank->sectors[num_sectors].is_erased = -1; /* the reset_init handler marks all the sectors unprotected, * matching hardware after reset; keep the driver in sync */ bank->sectors[num_sectors].is_protected = 0; str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit; } return ERROR_OK; } /* flash bank str7x 0 0 */ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command) { struct str7x_flash_bank *str7x_info; if (CMD_ARGC < 7) return ERROR_COMMAND_SYNTAX_ERROR; str7x_info = malloc(sizeof(struct str7x_flash_bank)); bank->driver_priv = str7x_info; /* set default bits for str71x flash */ str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA1 | FLASH_BSYA0); str7x_info->disable_bit = (1 << 1); if (strcmp(CMD_ARGV[6], "STR71x") == 0) str7x_info->register_base = 0x40100000; else if (strcmp(CMD_ARGV[6], "STR73x") == 0) { str7x_info->register_base = 0x80100000; str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0); } else if (strcmp(CMD_ARGV[6], "STR75x") == 0) { str7x_info->register_base = 0x20100000; str7x_info->disable_bit = (1 << 0); } else { LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]); free(str7x_info); return ERROR_FLASH_BANK_INVALID; } str7x_build_block_list(bank); return ERROR_OK; } /* wait for flash to become idle or report errors. FIX!!! what's the maximum timeout??? The documentation doesn't state any maximum time.... by inspection it seems > 1000ms is to be expected. 10000ms is long enough that it should cover anything, yet not quite be equivalent to an infinite loop. */ static int str7x_waitbusy(struct flash_bank *bank) { int err; int i; struct target *target = bank->target; struct str7x_flash_bank *str7x_info = bank->driver_priv; for (i = 0 ; i < 10000; i++) { uint32_t retval; err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval); if (err != ERROR_OK) return err; if ((retval & str7x_info->busy_bits) == 0) return ERROR_OK; alive_sleep(1); } LOG_ERROR("Timed out waiting for str7x flash"); return ERROR_FAIL; } static int str7x_result(struct flash_bank *bank) { struct target *target = bank->target; uint32_t flash_flags; int retval; retval = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &flash_flags); if (retval != ERROR_OK) return retval; if (flash_flags & FLASH_WPF) { LOG_ERROR("str7x hw write protection set"); retval = ERROR_FAIL; } if (flash_flags & FLASH_RESER) { LOG_ERROR("str7x suspended program erase not resumed"); retval = ERROR_FAIL; } if (flash_flags & FLASH_10ER) { LOG_ERROR("str7x trying to set bit to 1 when it is already 0"); retval = ERROR_FAIL; } if (flash_flags & FLASH_PGER) { LOG_ERROR("str7x program error"); retval = ERROR_FAIL; } if (flash_flags & FLASH_ERER) { LOG_ERROR("str7x erase error"); retval = ERROR_FAIL; } if (retval == ERROR_OK) { if (flash_flags & FLASH_ERR) { /* this should always be set if one of the others are set... */ LOG_ERROR("str7x write operation failed / bad setup"); retval = ERROR_FAIL; } } return retval; } static int str7x_protect_check(struct flash_bank *bank) { struct str7x_flash_bank *str7x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t flash_flags; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int retval; retval = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &flash_flags); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { if (flash_flags & str7x_info->sector_bits[i]) bank->sectors[i].is_protected = 0; else bank->sectors[i].is_protected = 1; } return ERROR_OK; } static int str7x_erase(struct flash_bank *bank, int first, int last) { struct str7x_flash_bank *str7x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t cmd; uint32_t sectors = 0; int err; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = first; i <= last; i++) sectors |= str7x_info->sector_bits[i]; LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors); /* clear FLASH_ER register */ err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0); if (err != ERROR_OK) return err; cmd = FLASH_SER; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); if (err != ERROR_OK) return err; cmd = sectors; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd); if (err != ERROR_OK) return err; cmd = FLASH_SER | FLASH_WMS; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); if (err != ERROR_OK) return err; err = str7x_waitbusy(bank); if (err != ERROR_OK) return err; err = str7x_result(bank); if (err != ERROR_OK) return err; for (i = first; i <= last; i++) bank->sectors[i].is_erased = 1; return ERROR_OK; } static int str7x_protect(struct flash_bank *bank, int set, int first, int last) { struct str7x_flash_bank *str7x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t cmd; uint32_t protect_blocks; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } protect_blocks = 0xFFFFFFFF; if (set) { for (i = first; i <= last; i++) protect_blocks &= ~(str7x_info->sector_bits[i]); } /* clear FLASH_ER register */ int err; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0); if (err != ERROR_OK) return err; cmd = FLASH_SPR; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); if (err != ERROR_OK) return err; cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR); err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd); if (err != ERROR_OK) return err; cmd = protect_blocks; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd); if (err != ERROR_OK) return err; cmd = FLASH_SPR | FLASH_WMS; err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); if (err != ERROR_OK) return err; err = str7x_waitbusy(bank); if (err != ERROR_OK) return err; err = str7x_result(bank); if (err != ERROR_OK) return err; return ERROR_OK; } static int str7x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct str7x_flash_bank *str7x_info = bank->driver_priv; struct target *target = bank->target; uint32_t buffer_size = 32768; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[6]; struct arm_algorithm arm_algo; int retval = ERROR_OK; /* see contib/loaders/flash/str7x.s for src */ static const uint32_t str7x_flash_write_code[] = { /* write: */ 0xe3a04201, /* mov r4, #0x10000000 */ 0xe5824000, /* str r4, [r2, #0x0] */ 0xe5821010, /* str r1, [r2, #0x10] */ 0xe4904004, /* ldr r4, [r0], #4 */ 0xe5824008, /* str r4, [r2, #0x8] */ 0xe4904004, /* ldr r4, [r0], #4 */ 0xe582400c, /* str r4, [r2, #0xc] */ 0xe3a04209, /* mov r4, #0x90000000 */ 0xe5824000, /* str r4, [r2, #0x0] */ /* busy: */ 0xe5924000, /* ldr r4, [r2, #0x0] */ 0xe1140005, /* tst r4, r5 */ 0x1afffffc, /* bne busy */ 0xe5924014, /* ldr r4, [r2, #0x14] */ 0xe31400ff, /* tst r4, #0xff */ 0x03140c01, /* tsteq r4, #0x100 */ 0x1a000002, /* bne exit */ 0xe2811008, /* add r1, r1, #0x8 */ 0xe2533001, /* subs r3, r3, #1 */ 0x1affffec, /* bne write */ /* exit: */ 0xeafffffe, /* b exit */ }; /* flash write code */ if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code), &write_algorithm) != ERROR_OK) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; uint8_t code[sizeof(str7x_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(str7x_flash_write_code), str7x_flash_write_code); target_write_buffer(target, write_algorithm->address, sizeof(code), code); /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_OUT); init_reg_param(®_params[4], "r4", 32, PARAM_IN); init_reg_param(®_params[5], "r5", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count; target_write_buffer(target, source->address, thisrun_count * 8, buffer); buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0)); buf_set_u32(reg_params[3].value, 0, 32, thisrun_count); buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits); retval = target_run_algorithm(target, 0, NULL, 6, reg_params, write_algorithm->address, write_algorithm->address + (sizeof(str7x_flash_write_code) - 4), 10000, &arm_algo); if (retval != ERROR_OK) break; if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) { retval = str7x_result(bank); break; } buffer += thisrun_count * 8; address += thisrun_count * 8; count -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); return retval; } static int str7x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t dwords_remaining = (count / 8); uint32_t bytes_remaining = (count & 0x00000007); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; uint32_t cmd; int retval; uint32_t check_address = offset; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x7) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } for (i = 0; i < bank->num_sectors; i++) { uint32_t sec_start = bank->sectors[i].offset; uint32_t sec_end = sec_start + bank->sectors[i].size; /* check if destination falls within the current sector */ if ((check_address >= sec_start) && (check_address < sec_end)) { /* check if destination ends in the current sector */ if (offset + count < sec_end) check_address = offset + count; else check_address = sec_end; } } if (check_address != offset + count) return ERROR_FLASH_DST_OUT_OF_BANK; /* clear FLASH_ER register */ target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0); /* multiple dwords (8-byte) to be programmed? */ if (dwords_remaining > 0) { /* try using a block write */ retval = str7x_write_block(bank, buffer, offset, dwords_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); } else { return retval; } } else { buffer += dwords_remaining * 8; address += dwords_remaining * 8; dwords_remaining = 0; } } while (dwords_remaining > 0) { /* command */ cmd = FLASH_DWPG; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); /* address */ target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address); /* data word 1 */ target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written); bytes_written += 4; /* data word 2 */ target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written); bytes_written += 4; /* start programming cycle */ cmd = FLASH_DWPG | FLASH_WMS; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); int err; err = str7x_waitbusy(bank); if (err != ERROR_OK) return err; err = str7x_result(bank); if (err != ERROR_OK) return err; dwords_remaining--; address += 8; } if (bytes_remaining) { uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* copy the last remaining bytes into the write buffer */ memcpy(last_dword, buffer+bytes_written, bytes_remaining); /* command */ cmd = FLASH_DWPG; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); /* address */ target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address); /* data word 1 */ target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword); /* data word 2 */ target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4); /* start programming cycle */ cmd = FLASH_DWPG | FLASH_WMS; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); int err; err = str7x_waitbusy(bank); if (err != ERROR_OK) return err; err = str7x_result(bank); if (err != ERROR_OK) return err; } return ERROR_OK; } static int str7x_probe(struct flash_bank *bank) { return ERROR_OK; } #if 0 COMMAND_HANDLER(str7x_handle_part_id_command) { return ERROR_OK; } #endif static int get_str7x_info(struct flash_bank *bank, char *buf, int buf_size) { /* Setting the write protection on a sector is a permanent change but it * can be disabled temporarily. FLASH_NVWPAR reflects the permanent * protection state of the sectors, not the temporary. */ snprintf(buf, buf_size, "STR7x flash protection info is only valid after a power cycle, " "clearing the protection is only temporary and may not be reflected in the current " "info returned."); return ERROR_OK; } COMMAND_HANDLER(str7x_handle_disable_jtag_command) { struct target *target = NULL; struct str7x_flash_bank *str7x_info = NULL; uint32_t flash_cmd; uint16_t ProtectionLevel = 0; uint16_t ProtectionRegs; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str7x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* first we get protection status */ uint32_t reg; target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), ®); if (!(reg & str7x_info->disable_bit)) ProtectionLevel = 1; target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), ®); ProtectionRegs = ~(reg >> 16); while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) { ProtectionRegs >>= 1; ProtectionLevel++; } if (ProtectionLevel == 0) { flash_cmd = FLASH_SPR; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD); flash_cmd = FLASH_SPR | FLASH_WMS; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); } else { flash_cmd = FLASH_SPR; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), ~(1 << (15 + ProtectionLevel))); flash_cmd = FLASH_SPR | FLASH_WMS; target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); } return ERROR_OK; } static const struct command_registration str7x_exec_command_handlers[] = { { .name = "disable_jtag", .usage = "", .handler = str7x_handle_disable_jtag_command, .mode = COMMAND_EXEC, .help = "disable jtag access", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration str7x_command_handlers[] = { { .name = "str7x", .mode = COMMAND_ANY, .help = "str7x flash command group", .usage = "", .chain = str7x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver str7x_flash = { .name = "str7x", .commands = str7x_command_handlers, .flash_bank_command = str7x_flash_bank_command, .erase = str7x_erase, .protect = str7x_protect, .write = str7x_write, .read = default_flash_read, .probe = str7x_probe, .auto_probe = str7x_probe, .erase_check = default_flash_blank_check, .protect_check = str7x_protect_check, .info = get_str7x_info, }; openocd-0.9.0/src/flash/nor/str9x.c0000644000175000017500000004531512315575360014026 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * Copyright (C) 2008 by Oyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include /* Flash registers */ #define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */ #define FLASH_NBBSR 0x54000004 /* Non-Boot Bank Size Register */ #define FLASH_BBADR 0x5400000C /* Boot Bank Base Address Register */ #define FLASH_NBBADR 0x54000010 /* Non-Boot Bank Base Address Register */ #define FLASH_CR 0x54000018 /* Control Register */ #define FLASH_SR 0x5400001C /* Status Register */ #define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */ struct str9x_flash_bank { uint32_t *sector_bits; int variant; int bank1; }; enum str9x_status_codes { STR9X_CMD_SUCCESS = 0, STR9X_INVALID_COMMAND = 1, STR9X_SRC_ADDR_ERROR = 2, STR9X_DST_ADDR_ERROR = 3, STR9X_SRC_ADDR_NOT_MAPPED = 4, STR9X_DST_ADDR_NOT_MAPPED = 5, STR9X_COUNT_ERROR = 6, STR9X_INVALID_SECTOR = 7, STR9X_SECTOR_NOT_BLANK = 8, STR9X_SECTOR_NOT_PREPARED = 9, STR9X_COMPARE_ERROR = 10, STR9X_BUSY = 11 }; static uint32_t bank1start = 0x00080000; static int str9x_build_block_list(struct flash_bank *bank) { struct str9x_flash_bank *str9x_info = bank->driver_priv; int i; int num_sectors; int b0_sectors = 0, b1_sectors = 0; uint32_t offset = 0; /* set if we have large flash str9 */ str9x_info->variant = 0; str9x_info->bank1 = 0; switch (bank->size) { case (256 * 1024): b0_sectors = 4; break; case (512 * 1024): b0_sectors = 8; break; case (1024 * 1024): bank1start = 0x00100000; str9x_info->variant = 1; b0_sectors = 16; break; case (2048 * 1024): bank1start = 0x00200000; str9x_info->variant = 1; b0_sectors = 32; break; case (128 * 1024): str9x_info->variant = 1; str9x_info->bank1 = 1; b1_sectors = 8; bank1start = bank->base; break; case (32 * 1024): str9x_info->bank1 = 1; b1_sectors = 4; bank1start = bank->base; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } num_sectors = b0_sectors + b1_sectors; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); str9x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors); num_sectors = 0; for (i = 0; i < b0_sectors; i++) { bank->sectors[num_sectors].offset = offset; bank->sectors[num_sectors].size = 0x10000; offset += bank->sectors[i].size; bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_protected = 1; str9x_info->sector_bits[num_sectors++] = (1 << i); } for (i = 0; i < b1_sectors; i++) { bank->sectors[num_sectors].offset = offset; bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000; offset += bank->sectors[i].size; bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_protected = 1; if (str9x_info->variant) str9x_info->sector_bits[num_sectors++] = (1 << i); else str9x_info->sector_bits[num_sectors++] = (1 << (i + 8)); } return ERROR_OK; } /* flash bank str9x 0 0 */ FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command) { struct str9x_flash_bank *str9x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; str9x_info = malloc(sizeof(struct str9x_flash_bank)); bank->driver_priv = str9x_info; str9x_build_block_list(bank); return ERROR_OK; } static int str9x_protect_check(struct flash_bank *bank) { int retval; struct str9x_flash_bank *str9x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t adr; uint32_t status = 0; uint16_t hstatus = 0; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* read level one protection */ if (str9x_info->variant) { if (str9x_info->bank1) { adr = bank1start + 0x18; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, adr, &hstatus); if (retval != ERROR_OK) return retval; status = hstatus; } else { adr = bank1start + 0x14; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, adr, &status); if (retval != ERROR_OK) return retval; } } else { adr = bank1start + 0x10; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, adr, &hstatus); if (retval != ERROR_OK) return retval; status = hstatus; } /* read array command */ retval = target_write_u16(target, adr, 0xFF); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { if (status & str9x_info->sector_bits[i]) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } return ERROR_OK; } static int str9x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; uint32_t adr; uint8_t status; uint8_t erase_cmd; int total_timeout; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Check if we can erase whole bank */ if ((first == 0) && (last == (bank->num_sectors - 1))) { /* Optimize to run erase bank command instead of sector */ erase_cmd = 0x80; /* Add timeout duration since erase bank takes more time */ total_timeout = 1000 * bank->num_sectors; } else { /* Erase sector command */ erase_cmd = 0x20; total_timeout = 1000; } /* this is so the compiler can *know* */ assert(total_timeout > 0); for (i = first; i <= last; i++) { int retval; adr = bank->base + bank->sectors[i].offset; /* erase sectors or block */ retval = target_write_u16(target, adr, erase_cmd); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, adr, 0xD0); if (retval != ERROR_OK) return retval; /* get status */ retval = target_write_u16(target, adr, 0x70); if (retval != ERROR_OK) return retval; int timeout; for (timeout = 0; timeout < total_timeout; timeout++) { retval = target_read_u8(target, adr, &status); if (retval != ERROR_OK) return retval; if (status & 0x80) break; alive_sleep(1); } if (timeout == total_timeout) { LOG_ERROR("erase timed out"); return ERROR_FAIL; } /* clear status, also clear read array */ retval = target_write_u16(target, adr, 0x50); if (retval != ERROR_OK) return retval; /* read array command */ retval = target_write_u16(target, adr, 0xFF); if (retval != ERROR_OK) return retval; if (status & 0x22) { LOG_ERROR("error erasing flash bank, status: 0x%x", status); return ERROR_FLASH_OPERATION_FAILED; } /* If we ran erase bank command, we are finished */ if (erase_cmd == 0x80) break; } for (i = first; i <= last; i++) bank->sectors[i].is_erased = 1; return ERROR_OK; } static int str9x_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; int i; uint32_t adr; uint8_t status; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = first; i <= last; i++) { /* Level One Protection */ adr = bank->base + bank->sectors[i].offset; target_write_u16(target, adr, 0x60); if (set) target_write_u16(target, adr, 0x01); else target_write_u16(target, adr, 0xD0); /* query status */ target_read_u8(target, adr, &status); /* clear status, also clear read array */ target_write_u16(target, adr, 0x50); /* read array command */ target_write_u16(target, adr, 0xFF); } return ERROR_OK; } static int str9x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 32768; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[4]; struct arm_algorithm arm_algo; int retval = ERROR_OK; /* see contib/loaders/flash/str9x.s for src */ static const uint32_t str9x_flash_write_code[] = { /* write: */ 0xe3c14003, /* bic r4, r1, #3 */ 0xe3a03040, /* mov r3, #0x40 */ 0xe1c430b0, /* strh r3, [r4, #0] */ 0xe0d030b2, /* ldrh r3, [r0], #2 */ 0xe0c130b2, /* strh r3, [r1], #2 */ 0xe3a03070, /* mov r3, #0x70 */ 0xe1c430b0, /* strh r3, [r4, #0] */ /* busy: */ 0xe5d43000, /* ldrb r3, [r4, #0] */ 0xe3130080, /* tst r3, #0x80 */ 0x0afffffc, /* beq busy */ 0xe3a05050, /* mov r5, #0x50 */ 0xe1c450b0, /* strh r5, [r4, #0] */ 0xe3a050ff, /* mov r5, #0xFF */ 0xe1c450b0, /* strh r5, [r4, #0] */ 0xe3130012, /* tst r3, #0x12 */ 0x1a000001, /* bne exit */ 0xe2522001, /* subs r2, r2, #1 */ 0x1affffed, /* bne write */ /* exit: */ 0xe1200070, /* bkpt #0 */ }; /* flash write code */ if (target_alloc_working_area(target, sizeof(str9x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; uint8_t code[sizeof(str9x_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(str9x_flash_write_code), str9x_flash_write_code); target_write_buffer(target, write_algorithm->address, sizeof(code), code); /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_IN); while (count > 0) { uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; target_write_buffer(target, source->address, thisrun_count * 2, buffer); buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); retval = target_run_algorithm(target, 0, NULL, 4, reg_params, write_algorithm->address, 0, 10000, &arm_algo); if (retval != ERROR_OK) { LOG_ERROR("error executing str9x flash write algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) { retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count * 2; address += thisrun_count * 2; count -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); return retval; } static int str9x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t words_remaining = (count / 2); uint32_t bytes_remaining = (count & 0x00000001); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; uint8_t status; int retval; uint32_t check_address = offset; uint32_t bank_adr; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } for (i = 0; i < bank->num_sectors; i++) { uint32_t sec_start = bank->sectors[i].offset; uint32_t sec_end = sec_start + bank->sectors[i].size; /* check if destination falls within the current sector */ if ((check_address >= sec_start) && (check_address < sec_end)) { /* check if destination ends in the current sector */ if (offset + count < sec_end) check_address = offset + count; else check_address = sec_end; } } if (check_address != offset + count) return ERROR_FLASH_DST_OUT_OF_BANK; /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = str9x_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); } else if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash writing failed"); return ERROR_FLASH_OPERATION_FAILED; } } else { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } while (words_remaining > 0) { bank_adr = address & ~0x03; /* write data command */ target_write_u16(target, bank_adr, 0x40); target_write_memory(target, address, 2, 1, buffer + bytes_written); /* get status command */ target_write_u16(target, bank_adr, 0x70); int timeout; for (timeout = 0; timeout < 1000; timeout++) { target_read_u8(target, bank_adr, &status); if (status & 0x80) break; alive_sleep(1); } if (timeout == 1000) { LOG_ERROR("write timed out"); return ERROR_FAIL; } /* clear status reg and read array */ target_write_u16(target, bank_adr, 0x50); target_write_u16(target, bank_adr, 0xFF); if (status & 0x10) return ERROR_FLASH_OPERATION_FAILED; else if (status & 0x02) return ERROR_FLASH_OPERATION_FAILED; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { uint8_t last_halfword[2] = {0xff, 0xff}; /* copy the last remaining bytes into the write buffer */ memcpy(last_halfword, buffer+bytes_written, bytes_remaining); bank_adr = address & ~0x03; /* write data command */ target_write_u16(target, bank_adr, 0x40); target_write_memory(target, address, 2, 1, last_halfword); /* query status command */ target_write_u16(target, bank_adr, 0x70); int timeout; for (timeout = 0; timeout < 1000; timeout++) { target_read_u8(target, bank_adr, &status); if (status & 0x80) break; alive_sleep(1); } if (timeout == 1000) { LOG_ERROR("write timed out"); return ERROR_FAIL; } /* clear status reg and read array */ target_write_u16(target, bank_adr, 0x50); target_write_u16(target, bank_adr, 0xFF); if (status & 0x10) return ERROR_FLASH_OPERATION_FAILED; else if (status & 0x02) return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int str9x_probe(struct flash_bank *bank) { return ERROR_OK; } #if 0 COMMAND_HANDLER(str9x_handle_part_id_command) { return ERROR_OK; } #endif COMMAND_HANDLER(str9x_handle_flash_config_command) { struct target *target = NULL; if (CMD_ARGC < 5) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; uint32_t bbsr, nbbsr, bbadr, nbbadr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], bbsr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], nbbsr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], bbadr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], nbbadr); target = bank->target; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* config flash controller */ target_write_u32(target, FLASH_BBSR, bbsr); target_write_u32(target, FLASH_NBBSR, nbbsr); target_write_u32(target, FLASH_BBADR, bbadr >> 2); target_write_u32(target, FLASH_NBBADR, nbbadr >> 2); /* set bit 18 instruction TCM order as per flash programming manual */ arm966e_write_cp15(target, 62, 0x40000); /* enable flash bank 1 */ target_write_u32(target, FLASH_CR, 0x18); return ERROR_OK; } static const struct command_registration str9x_config_command_handlers[] = { { .name = "flash_config", .handler = str9x_handle_flash_config_command, .mode = COMMAND_EXEC, .help = "Configure str9x flash controller, prior to " "programming the flash.", .usage = "bank_id BBSR NBBSR BBADR NBBADR", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration str9x_command_handlers[] = { { .name = "str9x", .mode = COMMAND_ANY, .help = "str9x flash command group", .usage = "", .chain = str9x_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver str9x_flash = { .name = "str9x", .commands = str9x_command_handlers, .flash_bank_command = str9x_flash_bank_command, .erase = str9x_erase, .protect = str9x_protect, .write = str9x_write, .read = default_flash_read, .probe = str9x_probe, .auto_probe = str9x_probe, .erase_check = default_flash_blank_check, .protect_check = str9x_protect_check, }; openocd-0.9.0/src/flash/nor/core.c0000644000175000017500000005017212315575360013662 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007-2010 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * Copyright (C) 2010 by Antonio Borneo * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include /** * @file * Upper level of NOR flash framework. * The lower level interfaces are to drivers. These upper level ones * primarily support access from Tcl scripts or from GDB. */ static struct flash_bank *flash_banks; int flash_driver_erase(struct flash_bank *bank, int first, int last) { int retval; retval = bank->driver->erase(bank, first, last); if (retval != ERROR_OK) LOG_ERROR("failed erasing sectors %d to %d", first, last); return retval; } int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) { int retval; /* callers may not supply illegal parameters ... */ if (first < 0 || first > last || last >= bank->num_sectors) { LOG_ERROR("illegal sector range"); return ERROR_FAIL; } /* force "set" to 0/1 */ set = !!set; /* DANGER! * * We must not use any cached information about protection state!!!! * * There are a million things that could change the protect state: * * the target could have reset, power cycled, been hot plugged, * the application could have run, etc. * * Drivers only receive valid sector range. */ retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) LOG_ERROR("failed setting protection for areas %d to %d", first, last); return retval; } int flash_driver_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { int retval; retval = bank->driver->write(bank, buffer, offset, count); if (retval != ERROR_OK) { LOG_ERROR( "error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, bank->base, offset); } return retval; } int flash_driver_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { int retval; LOG_DEBUG("call flash_driver_read()"); retval = bank->driver->read(bank, buffer, offset, count); if (retval != ERROR_OK) { LOG_ERROR( "error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, bank->base, offset); } return retval; } int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { return target_read_buffer(bank->target, offset + bank->base, count, buffer); } void flash_bank_add(struct flash_bank *bank) { /* put flash bank in linked list */ unsigned bank_num = 0; if (flash_banks) { /* find last flash bank */ struct flash_bank *p = flash_banks; while (NULL != p->next) { bank_num += 1; p = p->next; } p->next = bank; bank_num += 1; } else flash_banks = bank; bank->bank_number = bank_num; } struct flash_bank *flash_bank_list(void) { return flash_banks; } struct flash_bank *get_flash_bank_by_num_noprobe(int num) { struct flash_bank *p; int i = 0; for (p = flash_banks; p; p = p->next) { if (i++ == num) return p; } LOG_ERROR("flash bank %d does not exist", num); return NULL; } int flash_get_bank_count(void) { struct flash_bank *p; int i = 0; for (p = flash_banks; p; p = p->next) i++; return i; } struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) { unsigned requested = get_flash_name_index(name); unsigned found = 0; struct flash_bank *bank; for (bank = flash_banks; NULL != bank; bank = bank->next) { if (strcmp(bank->name, name) == 0) return bank; if (!flash_driver_name_matches(bank->driver->name, name)) continue; if (++found < requested) continue; return bank; } return NULL; } int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result) { struct flash_bank *bank; int retval; bank = get_flash_bank_by_name_noprobe(name); if (bank != NULL) { retval = bank->driver->auto_probe(bank); if (retval != ERROR_OK) { LOG_ERROR("auto_probe failed"); return retval; } } *bank_result = bank; return ERROR_OK; } int get_flash_bank_by_num(int num, struct flash_bank **bank) { struct flash_bank *p = get_flash_bank_by_num_noprobe(num); int retval; if (p == NULL) return ERROR_FAIL; retval = p->driver->auto_probe(p); if (retval != ERROR_OK) { LOG_ERROR("auto_probe failed"); return retval; } *bank = p; return ERROR_OK; } /* lookup flash bank by address, bank not found is success, but * result_bank is set to NULL. */ int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank) { struct flash_bank *c; /* cycle through bank list */ for (c = flash_banks; c; c = c->next) { if (c->target != target) continue; int retval; retval = c->driver->auto_probe(c); if (retval != ERROR_OK) { LOG_ERROR("auto_probe failed"); return retval; } /* check whether address belongs to this flash bank */ if ((addr >= c->base) && (addr <= c->base + (c->size - 1))) { *result_bank = c; return ERROR_OK; } } *result_bank = NULL; if (check) { LOG_ERROR("No flash at address 0x%08" PRIx32, addr); return ERROR_FAIL; } return ERROR_OK; } static int default_flash_mem_blank_check(struct flash_bank *bank) { struct target *target = bank->target; const int buffer_size = 1024; int i; uint32_t nBytes; int retval = ERROR_OK; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } uint8_t *buffer = malloc(buffer_size); for (i = 0; i < bank->num_sectors; i++) { uint32_t j; bank->sectors[i].is_erased = 1; for (j = 0; j < bank->sectors[i].size; j += buffer_size) { uint32_t chunk; chunk = buffer_size; if (chunk > (j - bank->sectors[i].size)) chunk = (j - bank->sectors[i].size); retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer); if (retval != ERROR_OK) goto done; for (nBytes = 0; nBytes < chunk; nBytes++) { if (buffer[nBytes] != 0xFF) { bank->sectors[i].is_erased = 0; break; } } } } done: free(buffer); return retval; } int default_flash_blank_check(struct flash_bank *bank) { struct target *target = bank->target; int i; int retval; int fast_check = 0; uint32_t blank; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = 0; i < bank->num_sectors; i++) { uint32_t address = bank->base + bank->sectors[i].offset; uint32_t size = bank->sectors[i].size; retval = target_blank_check_memory(target, address, size, &blank); if (retval != ERROR_OK) { fast_check = 0; break; } if (blank == 0xFF) bank->sectors[i].is_erased = 1; else bank->sectors[i].is_erased = 0; fast_check = 1; } if (!fast_check) { LOG_USER("Running slow fallback erase check - add working memory"); return default_flash_mem_blank_check(bank); } return ERROR_OK; } /* Manipulate given flash region, selecting the bank according to target * and address. Maps an address range to a set of sectors, and issues * the callback() on that set ... e.g. to erase or unprotect its members. * * (Note a current bad assumption: that protection operates on the same * size sectors as erase operations use.) * * The "pad_reason" parameter is a kind of boolean: when it's NULL, the * range must fit those sectors exactly. This is clearly safe; it can't * erase data which the caller said to leave alone, for example. If it's * non-NULL, rather than failing, extra data in the first and/or last * sectors will be added to the range, and that reason string is used when * warning about those additions. */ static int flash_iterate_address_range_inner(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; uint32_t last_addr = addr + length; /* first address AFTER end */ int first = -1; int last = -1; int i; int retval = get_flash_bank_by_addr(target, addr, true, &c); if (retval != ERROR_OK) return retval; if (c->size == 0 || c->num_sectors == 0) { LOG_ERROR("Bank is invalid"); return ERROR_FLASH_BANK_INVALID; } if (length == 0) { /* special case, erase whole bank when length is zero */ if (addr != c->base) { LOG_ERROR("Whole bank access must start at beginning of bank."); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } return callback(c, 0, c->num_sectors - 1); } /* check whether it all fits in this bank */ if (addr + length - 1 > c->base + c->size - 1) { LOG_ERROR("Flash access does not fit into bank."); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /** @todo: handle erasures that cross into adjacent banks */ addr -= c->base; last_addr -= c->base; for (i = 0; i < c->num_sectors; i++) { struct flash_sector *f = c->sectors + i; uint32_t end = f->offset + f->size; /* start only on a sector boundary */ if (first < 0) { /* scanned past the first sector? */ if (addr < f->offset) break; /* is this the first sector? */ if (addr == f->offset) first = i; /* Does this need head-padding? If so, pad and warn; * or else force an error. * * Such padding can make trouble, since *WE* can't * ever know if that data was in use. The warning * should help users sort out messes later. */ else if (addr < end && pad_reason) { /* FIXME say how many bytes (e.g. 80 KB) */ LOG_WARNING("Adding extra %s range, " "%#8.8x to %#8.8x", pad_reason, (unsigned) f->offset, (unsigned) addr - 1); first = i; } else continue; } /* is this (also?) the last sector? */ if (last_addr == end) { last = i; break; } /* Does this need tail-padding? If so, pad and warn; * or else force an error. */ if (last_addr < end && pad_reason) { /* FIXME say how many bytes (e.g. 80 KB) */ LOG_WARNING("Adding extra %s range, " "%#8.8x to %#8.8x", pad_reason, (unsigned) last_addr, (unsigned) end - 1); last = i; break; } /* MUST finish on a sector boundary */ if (last_addr <= f->offset) break; } /* invalid start or end address? */ if (first == -1 || last == -1) { LOG_ERROR("address range 0x%8.8x .. 0x%8.8x " "is not sector-aligned", (unsigned) (c->base + addr), (unsigned) (c->base + last_addr - 1)); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* The NOR driver may trim this range down, based on what * sectors are already erased/unprotected. GDB currently * blocks such optimizations. */ return callback(c, first, last); } /* The inner fn only handles a single bank, we could be spanning * multiple chips. */ static int flash_iterate_address_range(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; int retval = ERROR_OK; /* Danger! zero-length iterations means entire bank! */ do { retval = get_flash_bank_by_addr(target, addr, true, &c); if (retval != ERROR_OK) return retval; uint32_t cur_length = length; /* check whether it all fits in this bank */ if (addr + length - 1 > c->base + c->size - 1) { LOG_DEBUG("iterating over more than one flash bank."); cur_length = c->base + c->size - addr; } retval = flash_iterate_address_range_inner(target, pad_reason, addr, cur_length, callback); if (retval != ERROR_OK) break; length -= cur_length; addr += cur_length; } while (length > 0); return retval; } int flash_erase_address_range(struct target *target, bool pad, uint32_t addr, uint32_t length) { return flash_iterate_address_range(target, pad ? "erase" : NULL, addr, length, &flash_driver_erase); } static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) { return flash_driver_protect(bank, 0, first, last); } int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length) { /* By default, pad to sector boundaries ... the real issue here * is that our (only) caller *permanently* removes protection, * and doesn't restore it. */ return flash_iterate_address_range(target, "unprotect", addr, length, &flash_driver_unprotect); } static int compare_section(const void *a, const void *b) { struct imagesection *b1, *b2; b1 = *((struct imagesection **)a); b2 = *((struct imagesection **)b); if (b1->base_address == b2->base_address) return 0; else if (b1->base_address > b2->base_address) return 1; else return -1; } int flash_write_unlock(struct target *target, struct image *image, uint32_t *written, int erase, bool unlock) { int retval = ERROR_OK; int section; uint32_t section_offset; struct flash_bank *c; int *padding; section = 0; section_offset = 0; if (written) *written = 0; if (erase) { /* assume all sectors need erasing - stops any problems * when flash_write is called multiple times */ flash_set_dirty(); } /* allocate padding array */ padding = calloc(image->num_sections, sizeof(*padding)); /* This fn requires all sections to be in ascending order of addresses, * whereas an image can have sections out of order. */ struct imagesection **sections = malloc(sizeof(struct imagesection *) * image->num_sections); int i; for (i = 0; i < image->num_sections; i++) sections[i] = &image->sections[i]; qsort(sections, image->num_sections, sizeof(struct imagesection *), compare_section); /* loop until we reach end of the image */ while (section < image->num_sections) { uint32_t buffer_size; uint8_t *buffer; int section_last; uint32_t run_address = sections[section]->base_address + section_offset; uint32_t run_size = sections[section]->size - section_offset; int pad_bytes = 0; if (sections[section]->size == 0) { LOG_WARNING("empty section %d", section); section++; section_offset = 0; continue; } /* find the corresponding flash bank */ retval = get_flash_bank_by_addr(target, run_address, false, &c); if (retval != ERROR_OK) goto done; if (c == NULL) { LOG_WARNING("no flash bank found for address %" PRIx32, run_address); section++; /* and skip it */ section_offset = 0; continue; } /* collect consecutive sections which fall into the same bank */ section_last = section; padding[section] = 0; while ((run_address + run_size - 1 < c->base + c->size - 1) && (section_last + 1 < image->num_sections)) { /* sections are sorted */ assert(sections[section_last + 1]->base_address >= c->base); if (sections[section_last + 1]->base_address >= (c->base + c->size)) { /* Done with this bank */ break; } /* FIXME This needlessly touches sectors BETWEEN the * sections it's writing. Without auto erase, it just * writes ones. That WILL INVALIDATE data in cases * like Stellaris Tempest chips, corrupting internal * ECC codes; and at least FreeScale suggests issues * with that approach (in HC11 documentation). * * With auto erase enabled, data in those sectors will * be needlessly destroyed; and some of the limited * number of flash erase cycles will be wasted... * * In both cases, the extra writes slow things down. */ /* if we have multiple sections within our image, * flash programming could fail due to alignment issues * attempt to rebuild a consecutive buffer for the flash loader */ pad_bytes = (sections[section_last + 1]->base_address) - (run_address + run_size); padding[section_last] = pad_bytes; run_size += sections[++section_last]->size; run_size += pad_bytes; if (pad_bytes > 0) LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes); } if (run_address + run_size - 1 > c->base + c->size - 1) { /* If we have more than one flash chip back to back, then we limit * the current write operation to the current chip. */ LOG_DEBUG("Truncate flash run size to the current flash chip."); run_size = c->base + c->size - run_address; assert(run_size > 0); } /* If we're applying any sector automagic, then pad this * (maybe-combined) segment to the end of its last sector. */ if (unlock || erase) { int sector; uint32_t offset_start = run_address - c->base; uint32_t offset_end = offset_start + run_size; uint32_t end = offset_end, delta; for (sector = 0; sector < c->num_sectors; sector++) { end = c->sectors[sector].offset + c->sectors[sector].size; if (offset_end <= end) break; } delta = end - offset_end; padding[section_last] += delta; run_size += delta; } /* allocate buffer */ buffer = malloc(run_size); if (buffer == NULL) { LOG_ERROR("Out of memory for flash bank buffer"); retval = ERROR_FAIL; goto done; } buffer_size = 0; /* read sections to the buffer */ while (buffer_size < run_size) { size_t size_read; size_read = run_size - buffer_size; if (size_read > sections[section]->size - section_offset) size_read = sections[section]->size - section_offset; /* KLUDGE! * * #¤%#"%¤% we have to figure out the section # from the sorted * list of pointers to sections to invoke image_read_section()... */ intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections; int t_section_num = diff / sizeof(struct imagesection); LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, " "section_offset = %d, buffer_size = %d, size_read = %d", (int)section, (int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read); retval = image_read_section(image, t_section_num, section_offset, size_read, buffer + buffer_size, &size_read); if (retval != ERROR_OK || size_read == 0) { free(buffer); goto done; } /* see if we need to pad the section */ while (padding[section]--) (buffer + buffer_size)[size_read++] = c->default_padded_value; buffer_size += size_read; section_offset += size_read; if (section_offset >= sections[section]->size) { section++; section_offset = 0; } } retval = ERROR_OK; if (unlock) retval = flash_unlock_address_range(target, run_address, run_size); if (retval == ERROR_OK) { if (erase) { /* calculate and erase sectors */ retval = flash_erase_address_range(target, true, run_address, run_size); } } if (retval == ERROR_OK) { /* write flash sectors */ retval = flash_driver_write(c, buffer, run_address - c->base, run_size); } free(buffer); if (retval != ERROR_OK) { /* abort operation */ goto done; } if (written != NULL) *written += run_size; /* add run size to total written counter */ } done: free(sections); free(padding); return retval; } int flash_write(struct target *target, struct image *image, uint32_t *written, int erase) { return flash_write_unlock(target, image, written, erase, false); } openocd-0.9.0/src/flash/nor/core.h0000644000175000017500000002106512315575360013666 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * Copyright (C) 2010 by Antonio Borneo * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NOR_CORE_H #define FLASH_NOR_CORE_H #include /** * @file * Upper level NOR flash interfaces. */ struct image; #define FLASH_MAX_ERROR_STR (128) /** * Describes the geometry and status of a single flash sector * within a flash bank. A single bank typically consists of multiple * sectors, each of which can be erased and protected independently. */ struct flash_sector { /** Bus offset from start of the flash chip (in bytes). */ uint32_t offset; /** Number of bytes in this flash sector. */ uint32_t size; /** * Indication of erasure status: 0 = not erased, 1 = erased, * other = unknown. Set by @c flash_driver_s::erase_check. */ int is_erased; /** * Indication of protection status: 0 = unprotected/unlocked, * 1 = protected/locked, other = unknown. Set by * @c flash_driver_s::protect_check. * * This information must be considered stale immediately. * A million things could make it stale: power cycle, * reset of target, code running on target, etc. */ int is_protected; }; /** * Provides details of a flash bank, available either on-chip or through * a major interface. * * This structure will be passed as a parameter to the callbacks in the * flash_driver_s structure, some of which may modify the contents of * this structure of the area of flash that it defines. Driver writers * may use the @c driver_priv member to store additional data on a * per-bank basis, if required. */ struct flash_bank { const char *name; struct target *target; /**< Target to which this bank belongs. */ struct flash_driver *driver; /**< Driver for this bank. */ void *driver_priv; /**< Private driver storage pointer */ int bank_number; /**< The 'bank' (or chip number) of this instance. */ uint32_t base; /**< The base address of this bank */ uint32_t size; /**< The size of this chip bank, in bytes */ int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ /** Default padded value used, normally this matches the flash * erased value. Defaults to 0xFF. */ uint8_t default_padded_value; /** * The number of sectors on this chip. This value will * be set intially to 0, and the flash driver must set this to * some non-zero value during "probe()" or "auto_probe()". */ int num_sectors; /** Array of sectors, allocated and initilized by the flash driver */ struct flash_sector *sectors; struct flash_bank *next; /**< The next flash bank on this chip */ }; /** Registers the 'flash' subsystem commands */ int flash_register_commands(struct command_context *cmd_ctx); /** * Erases @a length bytes in the @a target flash, starting at @a addr. * The range @a addr to @a addr + @a length - 1 must be strictly * sector aligned, unless @a pad is true. Setting @a pad true extends * the range, at beginning and/or end, if needed for sector alignment. * @returns ERROR_OK if successful; otherwise, an error code. */ int flash_erase_address_range(struct target *target, bool pad, uint32_t addr, uint32_t length); int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length); /** * Writes @a image into the @a target flash. The @a written parameter * will contain the * @param target The target with the flash to be programmed. * @param image The image that will be programmed to flash. * @param written On return, contains the number of bytes written. * @param erase If non-zero, indicates the flash driver should first * erase the corresponding banks or sectors before programming. * @returns ERROR_OK if successful; otherwise, an error code. */ int flash_write(struct target *target, struct image *image, uint32_t *written, int erase); /** * Forces targets to re-examine their erase/protection state. * This routine must be called when the system may modify the status. */ void flash_set_dirty(void); /** @returns The number of flash banks currently defined. */ int flash_get_bank_count(void); /** * Provides default read implementation for flash memory. * @param bank The bank to read. * @param buffer The data bytes read. * @param offset The offset into the chip to read. * @param count The number of bytes to read. * @returns ERROR_OK if successful; otherwise, an error code. */ int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count); /** * Provides default erased-bank check handling. Checks to see if * the flash driver knows they are erased; if things look uncertain, * this routine will call default_flash_mem_blank_check() to confirm. * @returns ERROR_OK if successful; otherwise, an error code. */ int default_flash_blank_check(struct flash_bank *bank); /** * Returns the flash bank specified by @a name, which matches the * driver name and a suffix (option) specify the driver-specific * bank number. The suffix consists of the '.' and the driver-specific * bank number: when two str9x banks are defined, then 'str9x.1' refers * to the second. */ int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result); /** * Returns the flash bank specified by @a name, which matches the * driver name and a suffix (option) specify the driver-specific * bank number. The suffix consists of the '.' and the driver-specific * bank number: when two str9x banks are defined, then 'str9x.1' refers * to the second. */ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name); /** * Returns the flash bank like get_flash_bank_by_name(), without probing. * @param num The flash bank number. * @param bank returned bank if fn returns ERROR_OK * @returns ERROR_OK if successful */ int get_flash_bank_by_num(int num, struct flash_bank **bank); /** * Retreives @a bank from a command argument, reporting errors parsing * the bank identifier or retreiving the specified bank. The bank * may be identified by its bank number or by @c name.instance, where * @a instance is driver-specific. * @param name_index The index to the string in args containing the * bank identifier. * @param bank On output, contians a pointer to the bank or NULL. * @returns ERROR_OK on success, or an error indicating the problem. */ COMMAND_HELPER(flash_command_get_bank, unsigned name_index, struct flash_bank **bank); /** * Returns the flash bank like get_flash_bank_by_num(), without probing. * @param num The flash bank number. * @returns A struct flash_bank for flash bank @a num, or NULL. */ struct flash_bank *get_flash_bank_by_num_noprobe(int num); /** * Returns the flash bank located at a specified address. * @param target The target, presumed to contain one or more banks. * @param addr An address that is within the range of the bank. * @param check return ERROR_OK and result_bank NULL if the bank does not exist * @returns The struct flash_bank located at @a addr, or NULL. */ int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank); #endif /* FLASH_NOR_CORE_H */ openocd-0.9.0/src/flash/nor/driver.h0000644000175000017500000002077112315575360014234 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * Copyright (C) 2010 by Antonio Borneo * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NOR_DRIVER_H #define FLASH_NOR_DRIVER_H struct flash_bank; #define __FLASH_BANK_COMMAND(name) \ COMMAND_HELPER(name, struct flash_bank *bank) /** * @brief Provides the implementation-independent structure that defines * all of the callbacks required by OpenOCD flash drivers. * * Driver authors must implement the routines defined here, providing an * instance with the fields filled out. After that, the instance must * be registered in flash.c, so it can be used by the driver lookup system. * * Specifically, the user can issue the command: @par * @code * flash bank DRIVERNAME ...parameters... * @endcode * * OpenOCD will search for the driver with a @c flash_driver_s::name * that matches @c DRIVERNAME. * * The flash subsystem calls some of the other drivers routines a using * corresponding static flash_driver_callback() * routine in flash.c. */ struct flash_driver { /** * Gives a human-readable name of this flash driver, * This field is used to select and initialize the driver. */ const char *name; /** * Gives a human-readable description of arguments. */ const char *usage; /** * An array of driver-specific commands to register. When called * during the "flash bank" command, the driver can register addition * commands to support new flash chip functions. */ const struct command_registration *commands; /** * Finish the "flash bank" command for @a bank. The * @a bank parameter will have been filled in by the core flash * layer when this routine is called, and the driver can store * additional information in its struct flash_bank::driver_priv field. * * The CMD_ARGV are: @par * @code * CMD_ARGV[0] = bank * CMD_ARGV[1] = drivername {name above} * CMD_ARGV[2] = baseaddress * CMD_ARGV[3] = lengthbytes * CMD_ARGV[4] = chip_width_in bytes * CMD_ARGV[5] = bus_width_in_bytes * CMD_ARGV[6] = driver-specific parameters * @endcode * * For example, CMD_ARGV[4] = 2 (for 16 bit flash), * CMD_ARGV[5] = 4 (for 32 bit bus). * * If extra arguments are provided (@a CMD_ARGC > 6), they will * start in @a CMD_ARGV[6]. These can be used to implement * driver-specific extensions. * * @returns ERROR_OK if successful; otherwise, an error code. */ __FLASH_BANK_COMMAND((*flash_bank_command)); /** * Bank/sector erase routine (target-specific). When * called, the flash driver should erase the specified sectors * using whatever means are at its disposal. * * @param bank The bank of flash to be erased. * @param first The number of the first sector to erase, typically 0. * @param last The number of the last sector to erase, typically N-1. * @returns ERROR_OK if successful; otherwise, an error code. */ int (*erase)(struct flash_bank *bank, int first, int last); /** * Bank/sector protection routine (target-specific). * * When called, the driver should enable/disable protection * for MINIMUM the range covered by first..last sectors * inclusive. Some chips have alignment requirements will * cause the actual range to be protected / unprotected to * be larger than the first..last range. * * @param bank The bank to protect or unprotect. * @param set If non-zero, enable protection; if 0, disable it. * @param first The first sector to (un)protect, typicaly 0. * @param last The last sector to (un)project, typically N-1. * @returns ERROR_OK if successful; otherwise, an error code. */ int (*protect)(struct flash_bank *bank, int set, int first, int last); /** * Program data into the flash. Note CPU address will be * "bank->base + offset", while the physical address is * dependent upon current target MMU mappings. * * @param bank The bank to program * @param buffer The data bytes to write. * @param offset The offset into the chip to program. * @param count The number of bytes to write. * @returns ERROR_OK if successful; otherwise, an error code. */ int (*write)(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); /** * Read data from the flash. Note CPU address will be * "bank->base + offset", while the physical address is * dependent upon current target MMU mappings. * * @param bank The bank to read. * @param buffer The data bytes read. * @param offset The offset into the chip to read. * @param count The number of bytes to read. * @returns ERROR_OK if successful; otherwise, an error code. */ int (*read)(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count); /** * Probe to determine what kind of flash is present. * This is invoked by the "probe" script command. * * @param bank The bank to probe * @returns ERROR_OK if successful; otherwise, an error code. */ int (*probe)(struct flash_bank *bank); /** * Check the erasure status of a flash bank. * When called, the driver routine must perform the required * checks and then set the @c flash_sector_s::is_erased field * for each of the flash banks's sectors. * * @param bank The bank to check * @returns ERROR_OK if successful; otherwise, an error code. */ int (*erase_check)(struct flash_bank *bank); /** * Determine if the specific bank is "protected" or not. * When called, the driver routine must must perform the * required protection check(s) and then set the @c * flash_sector_s::is_protected field for each of the flash * bank's sectors. * * @param bank - the bank to check * @returns ERROR_OK if successful; otherwise, an error code. */ int (*protect_check)(struct flash_bank *bank); /** * Display human-readable information about the flash * bank into the given buffer. Drivers must be careful to avoid * overflowing the buffer. * * @param bank - the bank to get info about * @param char - where to put the text for the human to read * @param buf_size - the size of the human buffer. * @returns ERROR_OK if successful; otherwise, an error code. */ int (*info)(struct flash_bank *bank, char *buf, int buf_size); /** * A more gentle flavor of filash_driver_s::probe, performing * setup with less noise. Generally, driver routines should test * to see if the bank has already been probed; if it has, the * driver probably should not perform its probe a second time. * * This callback is often called from the inside of other * routines (e.g. GDB flash downloads) to autoprobe the flash as * it is programing the flash. * * @param bank - the bank to probe * @returns ERROR_OK if successful; otherwise, an error code. */ int (*auto_probe)(struct flash_bank *bank); }; #define FLASH_BANK_COMMAND_HANDLER(name) \ static __FLASH_BANK_COMMAND(name) /** * Find a NOR flash driver by its name. * @param name The name of the requested driver. * @returns The flash_driver called @c name, or NULL if not found. */ struct flash_driver *flash_driver_find_by_name(const char *name); #endif /* FLASH_NOR_DRIVER_H */ openocd-0.9.0/src/flash/nor/stellaris.c0000644000175000017500000012567412516456302014743 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /*************************************************************************** * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more. ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/interface.h" #include "imp.h" #include #include #define DID0_VER(did0) ((did0 >> 28)&0x07) /* STELLARIS control registers */ #define SCB_BASE 0x400FE000 #define DID0 0x000 #define DID1 0x004 #define DC0 0x008 #define DC1 0x010 #define DC2 0x014 #define DC3 0x018 #define DC4 0x01C #define RIS 0x050 #define RCC 0x060 #define PLLCFG 0x064 #define RCC2 0x070 #define NVMSTAT 0x1a0 /* "legacy" flash memory protection registers (64KB max) */ #define FMPRE 0x130 #define FMPPE 0x134 /* new flash memory protection registers (for more than 64KB) */ #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */ #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */ #define USECRL 0x140 #define FLASH_CONTROL_BASE 0x400FD000 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000) #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004) #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008) #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C) #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010) #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014) #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0) #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4) #define AMISC 1 #define PMISC 2 #define AMASK 1 #define PMASK 2 /* Flash Controller Command bits */ #define FMC_WRKEY (0xA442 << 16) #define FMC_COMT (1 << 3) #define FMC_MERASE (1 << 2) #define FMC_ERASE (1 << 1) #define FMC_WRITE (1 << 0) /* STELLARIS constants */ /* values to write in FMA to commit write-"once" values */ #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */ #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */ static void stellaris_read_clock_info(struct flash_bank *bank); static int stellaris_mass_erase(struct flash_bank *bank); struct stellaris_flash_bank { /* chip id register */ uint32_t did0; uint32_t did1; uint32_t dc0; uint32_t dc1; uint32_t fsize; uint32_t ssize; const char *target_name; uint8_t target_class; uint32_t sramsiz; /* flash geometry */ uint32_t num_pages; uint32_t pagesize; /* main clock status */ uint32_t rcc; uint32_t rcc2; uint8_t mck_valid; uint8_t xtal_mask; uint32_t iosc_freq; uint32_t mck_freq; const char *iosc_desc; const char *mck_desc; }; /* Autogenerated by contrib/gen-stellaris-part-header.pl */ /* From Stellaris Firmware Development Package revision 9453 */ static const struct { uint8_t class; uint8_t partno; const char *partname; } StellarisParts[] = { {0x00, 0x01, "LM3S101"}, {0x00, 0x02, "LM3S102"}, {0x01, 0xBF, "LM3S1110"}, {0x01, 0xC3, "LM3S1133"}, {0x01, 0xC5, "LM3S1138"}, {0x01, 0xC1, "LM3S1150"}, {0x01, 0xC4, "LM3S1162"}, {0x01, 0xC2, "LM3S1165"}, {0x01, 0xEC, "LM3S1166"}, {0x01, 0xC6, "LM3S1332"}, {0x01, 0xBC, "LM3S1435"}, {0x01, 0xBA, "LM3S1439"}, {0x01, 0xBB, "LM3S1512"}, {0x01, 0xC7, "LM3S1538"}, {0x01, 0xDB, "LM3S1601"}, {0x03, 0x06, "LM3S1607"}, {0x01, 0xDA, "LM3S1608"}, {0x01, 0xC0, "LM3S1620"}, {0x04, 0xCD, "LM3S1621"}, {0x03, 0x03, "LM3S1625"}, {0x03, 0x04, "LM3S1626"}, {0x03, 0x05, "LM3S1627"}, {0x01, 0xB3, "LM3S1635"}, {0x01, 0xEB, "LM3S1636"}, {0x01, 0xBD, "LM3S1637"}, {0x04, 0xB1, "LM3S1651"}, {0x01, 0xB9, "LM3S1751"}, {0x03, 0x10, "LM3S1776"}, {0x04, 0x16, "LM3S1811"}, {0x04, 0x3D, "LM3S1816"}, {0x01, 0xB4, "LM3S1850"}, {0x01, 0xDD, "LM3S1911"}, {0x01, 0xDC, "LM3S1918"}, {0x01, 0xB7, "LM3S1937"}, {0x01, 0xBE, "LM3S1958"}, {0x01, 0xB5, "LM3S1960"}, {0x01, 0xB8, "LM3S1968"}, {0x01, 0xEA, "LM3S1969"}, {0x04, 0xCE, "LM3S1B21"}, {0x06, 0xCA, "LM3S1C21"}, {0x06, 0xCB, "LM3S1C26"}, {0x06, 0x98, "LM3S1C58"}, {0x06, 0xB0, "LM3S1D21"}, {0x06, 0xCC, "LM3S1D26"}, {0x06, 0x1D, "LM3S1F11"}, {0x06, 0x1B, "LM3S1F16"}, {0x06, 0xAF, "LM3S1G21"}, {0x06, 0x95, "LM3S1G58"}, {0x06, 0x1E, "LM3S1H11"}, {0x06, 0x1C, "LM3S1H16"}, {0x04, 0x0F, "LM3S1J11"}, {0x04, 0x3C, "LM3S1J16"}, {0x04, 0x0E, "LM3S1N11"}, {0x04, 0x3B, "LM3S1N16"}, {0x04, 0xB2, "LM3S1P51"}, {0x04, 0x9E, "LM3S1R21"}, {0x04, 0xC9, "LM3S1R26"}, {0x04, 0x30, "LM3S1W16"}, {0x04, 0x2F, "LM3S1Z16"}, {0x01, 0x51, "LM3S2110"}, {0x01, 0x84, "LM3S2139"}, {0x03, 0x39, "LM3S2276"}, {0x01, 0xA2, "LM3S2410"}, {0x01, 0x59, "LM3S2412"}, {0x01, 0x56, "LM3S2432"}, {0x01, 0x5A, "LM3S2533"}, {0x01, 0xE1, "LM3S2601"}, {0x01, 0xE0, "LM3S2608"}, {0x03, 0x33, "LM3S2616"}, {0x01, 0x57, "LM3S2620"}, {0x01, 0x85, "LM3S2637"}, {0x01, 0x53, "LM3S2651"}, {0x03, 0x80, "LM3S2671"}, {0x03, 0x50, "LM3S2678"}, {0x01, 0xA4, "LM3S2730"}, {0x01, 0x52, "LM3S2739"}, {0x03, 0x3A, "LM3S2776"}, {0x04, 0x6D, "LM3S2793"}, {0x01, 0xE3, "LM3S2911"}, {0x01, 0xE2, "LM3S2918"}, {0x01, 0xED, "LM3S2919"}, {0x01, 0x54, "LM3S2939"}, {0x01, 0x8F, "LM3S2948"}, {0x01, 0x58, "LM3S2950"}, {0x01, 0x55, "LM3S2965"}, {0x04, 0x6C, "LM3S2B93"}, {0x06, 0x94, "LM3S2D93"}, {0x06, 0x93, "LM3S2U93"}, {0x00, 0x19, "LM3S300"}, {0x00, 0x11, "LM3S301"}, {0x00, 0x1A, "LM3S308"}, {0x00, 0x12, "LM3S310"}, {0x00, 0x13, "LM3S315"}, {0x00, 0x14, "LM3S316"}, {0x00, 0x17, "LM3S317"}, {0x00, 0x15, "LM3S328"}, {0x03, 0x08, "LM3S3634"}, {0x03, 0x43, "LM3S3651"}, {0x04, 0xC8, "LM3S3654"}, {0x03, 0x44, "LM3S3739"}, {0x03, 0x49, "LM3S3748"}, {0x03, 0x45, "LM3S3749"}, {0x04, 0x42, "LM3S3826"}, {0x04, 0x41, "LM3S3J26"}, {0x04, 0x40, "LM3S3N26"}, {0x04, 0x3F, "LM3S3W26"}, {0x04, 0x3E, "LM3S3Z26"}, {0x03, 0x81, "LM3S5632"}, {0x04, 0x0C, "LM3S5651"}, {0x03, 0x8A, "LM3S5652"}, {0x04, 0x4D, "LM3S5656"}, {0x03, 0x91, "LM3S5662"}, {0x03, 0x96, "LM3S5732"}, {0x03, 0x97, "LM3S5737"}, {0x03, 0xA0, "LM3S5739"}, {0x03, 0x99, "LM3S5747"}, {0x03, 0xA7, "LM3S5749"}, {0x03, 0x9A, "LM3S5752"}, {0x03, 0x9C, "LM3S5762"}, {0x04, 0x69, "LM3S5791"}, {0x04, 0x0B, "LM3S5951"}, {0x04, 0x4E, "LM3S5956"}, {0x04, 0x68, "LM3S5B91"}, {0x06, 0x2E, "LM3S5C31"}, {0x06, 0x2C, "LM3S5C36"}, {0x06, 0x5E, "LM3S5C51"}, {0x06, 0x5B, "LM3S5C56"}, {0x06, 0x5F, "LM3S5D51"}, {0x06, 0x5C, "LM3S5D56"}, {0x06, 0x87, "LM3S5D91"}, {0x06, 0x2D, "LM3S5G31"}, {0x06, 0x1F, "LM3S5G36"}, {0x06, 0x5D, "LM3S5G51"}, {0x06, 0x4F, "LM3S5G56"}, {0x04, 0x09, "LM3S5K31"}, {0x04, 0x4A, "LM3S5K36"}, {0x04, 0x0A, "LM3S5P31"}, {0x04, 0x48, "LM3S5P36"}, {0x04, 0xB6, "LM3S5P3B"}, {0x04, 0x0D, "LM3S5P51"}, {0x04, 0x4C, "LM3S5P56"}, {0x04, 0x07, "LM3S5R31"}, {0x04, 0x4B, "LM3S5R36"}, {0x04, 0x47, "LM3S5T36"}, {0x06, 0x7F, "LM3S5U91"}, {0x04, 0x46, "LM3S5Y36"}, {0x00, 0x2A, "LM3S600"}, {0x00, 0x21, "LM3S601"}, {0x00, 0x2B, "LM3S608"}, {0x00, 0x22, "LM3S610"}, {0x01, 0xA1, "LM3S6100"}, {0x00, 0x23, "LM3S611"}, {0x01, 0x74, "LM3S6110"}, {0x00, 0x24, "LM3S612"}, {0x00, 0x25, "LM3S613"}, {0x00, 0x26, "LM3S615"}, {0x00, 0x28, "LM3S617"}, {0x00, 0x29, "LM3S618"}, {0x00, 0x27, "LM3S628"}, {0x01, 0xA5, "LM3S6420"}, {0x01, 0x82, "LM3S6422"}, {0x01, 0x75, "LM3S6432"}, {0x01, 0x76, "LM3S6537"}, {0x01, 0x71, "LM3S6610"}, {0x01, 0xE7, "LM3S6611"}, {0x01, 0xE6, "LM3S6618"}, {0x01, 0x83, "LM3S6633"}, {0x01, 0x8B, "LM3S6637"}, {0x01, 0xA3, "LM3S6730"}, {0x01, 0x77, "LM3S6753"}, {0x01, 0xE9, "LM3S6911"}, {0x01, 0xE8, "LM3S6918"}, {0x01, 0x89, "LM3S6938"}, {0x01, 0x72, "LM3S6950"}, {0x01, 0x78, "LM3S6952"}, {0x01, 0x73, "LM3S6965"}, {0x06, 0xAA, "LM3S6C11"}, {0x06, 0xAC, "LM3S6C65"}, {0x06, 0x9F, "LM3S6G11"}, {0x06, 0xAB, "LM3S6G65"}, {0x00, 0x38, "LM3S800"}, {0x00, 0x31, "LM3S801"}, {0x00, 0x39, "LM3S808"}, {0x00, 0x32, "LM3S811"}, {0x00, 0x33, "LM3S812"}, {0x00, 0x34, "LM3S815"}, {0x00, 0x36, "LM3S817"}, {0x00, 0x37, "LM3S818"}, {0x00, 0x35, "LM3S828"}, {0x01, 0x64, "LM3S8530"}, {0x01, 0x8E, "LM3S8538"}, {0x01, 0x61, "LM3S8630"}, {0x01, 0x63, "LM3S8730"}, {0x01, 0x8D, "LM3S8733"}, {0x01, 0x86, "LM3S8738"}, {0x01, 0x65, "LM3S8930"}, {0x01, 0x8C, "LM3S8933"}, {0x01, 0x88, "LM3S8938"}, {0x01, 0xA6, "LM3S8962"}, {0x01, 0x62, "LM3S8970"}, {0x01, 0xD7, "LM3S8971"}, {0x06, 0xAE, "LM3S8C62"}, {0x06, 0xAD, "LM3S8G62"}, {0x04, 0xCF, "LM3S9781"}, {0x04, 0x67, "LM3S9790"}, {0x04, 0x6B, "LM3S9792"}, {0x04, 0x2D, "LM3S9971"}, {0x04, 0x20, "LM3S9997"}, {0x04, 0xD0, "LM3S9B81"}, {0x04, 0x66, "LM3S9B90"}, {0x04, 0x6A, "LM3S9B92"}, {0x04, 0x6E, "LM3S9B95"}, {0x04, 0x6F, "LM3S9B96"}, {0x04, 0x1D, "LM3S9BN2"}, {0x04, 0x1E, "LM3S9BN5"}, {0x04, 0x1F, "LM3S9BN6"}, {0x06, 0x70, "LM3S9C97"}, {0x06, 0xA9, "LM3S9D81"}, {0x06, 0x7E, "LM3S9D90"}, {0x06, 0x92, "LM3S9D92"}, {0x06, 0x9D, "LM3S9D96"}, {0x06, 0x7B, "LM3S9DN5"}, {0x06, 0x7C, "LM3S9DN6"}, {0x06, 0x60, "LM3S9G97"}, {0x06, 0x79, "LM3S9GN5"}, {0x04, 0x1B, "LM3S9L71"}, {0x04, 0x18, "LM3S9L97"}, {0x06, 0xA8, "LM3S9U81"}, {0x06, 0x7D, "LM3S9U90"}, {0x06, 0x90, "LM3S9U92"}, {0x06, 0x9B, "LM3S9U96"}, {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"}, {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"}, {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"}, {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"}, {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"}, {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"}, {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"}, {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"}, {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"}, {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"}, {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"}, {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"}, {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"}, {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"}, {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"}, {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"}, {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"}, {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"}, {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"}, {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"}, {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"}, {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"}, {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"}, {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"}, {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"}, {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"}, {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"}, {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"}, {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"}, {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"}, {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"}, {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"}, {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"}, {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"}, {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"}, {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"}, {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"}, {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"}, {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"}, {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"}, {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"}, {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"}, {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"}, {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"}, {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"}, {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"}, {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"}, {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"}, {0x05, 0xE1, "LM4FSXLH5BB"}, {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"}, {0x05, 0xE4, "LM4FS99H5BB"}, {0x05, 0xE5, "LM4FS1AH5BB"}, {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"}, {0x05, 0xEA, "LM4FS1GH5BB"}, {0x05, 0xF0, "TM4C123GH6ZXR"}, {0x0A, 0x19, "TM4C1290NCPDT"}, {0x0A, 0x1B, "TM4C1290NCZAD"}, {0x0A, 0x1C, "TM4C1292NCPDT"}, {0x0A, 0x1E, "TM4C1292NCZAD"}, {0x0A, 0x1F, "TM4C1294NCPDT"}, {0x0A, 0x21, "TM4C1294NCZAD"}, {0x0A, 0x22, "TM4C1297NCZAD"}, {0x0A, 0x23, "TM4C1299NCZAD"}, {0x0A, 0x24, "TM4C129CNCPDT"}, {0x0A, 0x26, "TM4C129CNCZAD"}, {0x0A, 0x27, "TM4C129DNCPDT"}, {0x0A, 0x29, "TM4C129DNCZAD"}, {0x0A, 0x2D, "TM4C129ENCPDT"}, {0x0A, 0x2F, "TM4C129ENCZAD"}, {0x0A, 0x30, "TM4C129LNCZAD"}, {0x0A, 0x32, "TM4C129XNCZAD"}, {0x0A, 0x34, "TM4C1294KCPDT"}, {0x0A, 0x35, "TM4C129EKCPDT"}, {0x0A, 0x36, "TM4C1299KCZAD"}, {0x0A, 0x37, "TM4C129XKCZAD"}, {0xFF, 0x00, "Unknown Part"} }; static const char * const StellarisClassname[] = { "Sandstorm", "Fury", "Unknown", "DustDevil", "Tempest", "Blizzard/TM4C123x", "Firestorm", "", "", "", "Snowflake", }; /*************************************************************************** * openocd command interface * ***************************************************************************/ /* flash_bank stellaris 0 0 */ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command) { struct stellaris_flash_bank *stellaris_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1); bank->base = 0x0; bank->driver_priv = stellaris_info; stellaris_info->target_name = "Unknown target"; /* part wasn't probed for info yet */ stellaris_info->did1 = 0; /* TODO Specify the main crystal speed in kHz using an optional * argument; ditto, the speed of an external oscillator used * instead of a crystal. Avoid programming flash using IOSC. */ return ERROR_OK; } static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct stellaris_flash_bank *stellaris_info = bank->driver_priv; if (stellaris_info->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; /* Read main and master clock freqency register */ stellaris_read_clock_info(bank); printed = snprintf(buf, buf_size, "\nTI/LMI Stellaris information: Chip is " "class %i (%s) %s rev %c%i\n", stellaris_info->target_class, StellarisClassname[stellaris_info->target_class], stellaris_info->target_name, (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)), (int)((stellaris_info->did0) & 0xFF)); buf += printed; buf_size -= printed; printed = snprintf(buf, buf_size, "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32 ", eproc: %s, ramsize: %" PRIu32 "k, flashsize: %" PRIu32 "k\n", stellaris_info->did1, stellaris_info->did1, "ARMv7M", stellaris_info->sramsiz, (uint32_t)(stellaris_info->num_pages * stellaris_info->pagesize / 1024)); buf += printed; buf_size -= printed; snprintf(buf, buf_size, "master clock: %ikHz%s, " "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 ", " "pagesize: %" PRIu32 ", pages: %" PRIu32, (int)(stellaris_info->mck_freq / 1000), stellaris_info->mck_desc, stellaris_info->rcc, stellaris_info->rcc2, stellaris_info->pagesize, stellaris_info->num_pages); return ERROR_OK; } /*************************************************************************** * chip identification and status * ***************************************************************************/ /* Set the flash timimg register to match current clocking */ static void stellaris_set_flash_timing(struct flash_bank *bank) { struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1); /* only valid for Sandstorm and Fury class devices */ if (stellaris_info->target_class > 1) return; LOG_DEBUG("usecrl = %i", (int)(usecrl)); target_write_u32(target, SCB_BASE | USECRL, usecrl); } static const unsigned rcc_xtal[32] = { [0x00] = 1000000, /* no pll */ [0x01] = 1843200, /* no pll */ [0x02] = 2000000, /* no pll */ [0x03] = 2457600, /* no pll */ [0x04] = 3579545, [0x05] = 3686400, [0x06] = 4000000, /* usb */ [0x07] = 4096000, [0x08] = 4915200, [0x09] = 5000000, /* usb */ [0x0a] = 5120000, [0x0b] = 6000000, /* (reset) usb */ [0x0c] = 6144000, [0x0d] = 7372800, [0x0e] = 8000000, /* usb */ [0x0f] = 8192000, /* parts before DustDevil use just 4 bits for xtal spec */ [0x10] = 10000000, /* usb */ [0x11] = 12000000, /* usb */ [0x12] = 12288000, [0x13] = 13560000, [0x14] = 14318180, [0x15] = 16000000, /* usb */ [0x16] = 16384000, }; /** Read clock configuration and set stellaris_info->usec_clocks. */ static void stellaris_read_clock_info(struct flash_bank *bank) { struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc; unsigned xtal; unsigned long mainfreq; target_read_u32(target, SCB_BASE | RCC, &rcc); LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc); target_read_u32(target, SCB_BASE | RCC2, &rcc2); LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc); target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg); LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg); stellaris_info->rcc = rcc; stellaris_info->rcc = rcc2; sysdiv = (rcc >> 23) & 0xF; usesysdiv = (rcc >> 22) & 0x1; bypass = (rcc >> 11) & 0x1; oscsrc = (rcc >> 4) & 0x3; xtal = (rcc >> 6) & stellaris_info->xtal_mask; /* NOTE: post-Sandstorm parts have RCC2 which may override * parts of RCC ... with more sysdiv options, option for * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads * as zero, so the "use RCC2" flag is always clear. */ if (rcc2 & (1 << 31)) { sysdiv = (rcc2 >> 23) & 0x3F; bypass = (rcc2 >> 11) & 0x1; oscsrc = (rcc2 >> 4) & 0x7; /* FIXME Tempest parts have an additional lsb for * fractional sysdiv (200 MHz / 2.5 == 80 MHz) */ } stellaris_info->mck_desc = ""; switch (oscsrc) { case 0: /* MOSC */ mainfreq = rcc_xtal[xtal]; break; case 1: /* IOSC */ mainfreq = stellaris_info->iosc_freq; stellaris_info->mck_desc = stellaris_info->iosc_desc; break; case 2: /* IOSC/4 */ mainfreq = stellaris_info->iosc_freq / 4; stellaris_info->mck_desc = stellaris_info->iosc_desc; break; case 3: /* lowspeed */ /* Sandstorm doesn't have this 30K +/- 30% osc */ mainfreq = 30000; stellaris_info->mck_desc = " (±30%)"; break; case 8: /* hibernation osc */ /* not all parts support hibernation */ mainfreq = 32768; break; default: /* NOTREACHED */ mainfreq = 0; break; } /* PLL is used if it's not bypassed; its output is 200 MHz * even when it runs at 400 MHz (adds divide-by-two stage). */ if (!bypass) mainfreq = 200000000; if (usesysdiv) stellaris_info->mck_freq = mainfreq/(1 + sysdiv); else stellaris_info->mck_freq = mainfreq; } /* Read device id register, main clock frequency register and fill in driver info structure */ static int stellaris_read_part_info(struct flash_bank *bank) { struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t did0, did1, ver, fam; int i; /* Read and parse chip identification register */ target_read_u32(target, SCB_BASE | DID0, &did0); target_read_u32(target, SCB_BASE | DID1, &did1); target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0); target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1); LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "", did0, did1, stellaris_info->dc0, stellaris_info->dc1); ver = DID0_VER(did0); if ((ver != 0) && (ver != 1)) { LOG_WARNING("Unknown did0 version, cannot identify target"); return ERROR_FLASH_OPERATION_FAILED; } if (did1 == 0) { LOG_WARNING("Cannot identify target as a Stellaris"); return ERROR_FLASH_OPERATION_FAILED; } ver = did1 >> 28; fam = (did1 >> 24) & 0xF; if (((ver != 0) && (ver != 1)) || (fam != 0)) { LOG_WARNING("Unknown did1 version/family."); return ERROR_FLASH_OPERATION_FAILED; } /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC * is 12 MHz, but some older parts have 15 MHz. A few data sheets * even give _both_ numbers! We'll use current numbers; IOSC is * always approximate. * * For Tempest: IOSC is calibrated, 16 MHz * For Blizzard: IOSC is calibrated, 16 MHz * For Firestorm: IOSC is calibrated, 16 MHz */ stellaris_info->iosc_freq = 12000000; stellaris_info->iosc_desc = " (±30%)"; stellaris_info->xtal_mask = 0x0f; /* get device class */ if (DID0_VER(did0) > 0) { stellaris_info->target_class = (did0 >> 16) & 0xFF; } else { /* Sandstorm class */ stellaris_info->target_class = 0; } switch (stellaris_info->target_class) { case 0: /* Sandstorm */ /* * Current (2009-August) parts seem to be rev C2 and use 12 MHz. * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz * (LM3S618), but some other C0 parts are 12 MHz (LM3S811). */ if (((did0 >> 8) & 0xff) < 2) { stellaris_info->iosc_freq = 15000000; stellaris_info->iosc_desc = " (±50%)"; } break; case 1: /* Fury */ break; case 4: /* Tempest */ case 5: /* Blizzard */ case 6: /* Firestorm */ case 0xa: /* Snowflake */ stellaris_info->iosc_freq = 16000000; /* +/- 1% */ stellaris_info->iosc_desc = " (±1%)"; /* FALL THROUGH */ case 3: /* DustDevil */ stellaris_info->xtal_mask = 0x1f; break; default: LOG_WARNING("Unknown did0 class"); } for (i = 0; StellarisParts[i].partno; i++) { if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) && (StellarisParts[i].class == stellaris_info->target_class)) break; } stellaris_info->target_name = StellarisParts[i].partname; stellaris_info->did0 = did0; stellaris_info->did1 = did1; if (stellaris_info->target_class == 5) { /* Blizzard */ target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize); target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize); stellaris_info->num_pages = 2 * (1 + (stellaris_info->fsize & 0xFFFF)); stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4; stellaris_info->pagesize = 1024; } else if (stellaris_info->target_class == 0xa) { /* Snowflake */ target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize); target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize); stellaris_info->pagesize = (1 << ((stellaris_info->fsize >> 16) & 7)) * 1024; stellaris_info->num_pages = 2048 * (1 + (stellaris_info->fsize & 0xFFFF)) / stellaris_info->pagesize; stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4; } else { stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF)); stellaris_info->sramsiz = (1 + ((stellaris_info->dc0 >> 16) & 0xFFFF)) / 4; stellaris_info->pagesize = 1024; } /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too. * That exposes a 32-word Flash Write Buffer ... enabling * writes of more than one word at a time. */ return ERROR_OK; } /*************************************************************************** * flash operations * ***************************************************************************/ static int stellaris_protect_check(struct flash_bank *bank) { struct stellaris_flash_bank *stellaris = bank->driver_priv; struct target *target = bank->target; uint32_t flash_sizek = stellaris->pagesize / 1024 * stellaris->num_pages; uint32_t fmppe_addr; int status = ERROR_OK; unsigned i; if (stellaris->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; for (i = 0; i < (unsigned) bank->num_sectors; i++) bank->sectors[i].is_protected = -1; /* Read each Flash Memory Protection Program Enable (FMPPE) register * to report any pages that we can't write. Ignore the Read Enable * register (FMPRE). */ if (stellaris->target_class >= 0x0a || flash_sizek > 64) fmppe_addr = SCB_BASE | FMPPE0; else fmppe_addr = SCB_BASE | FMPPE; unsigned int page = 0, lockbitnum, lockbitcnt = flash_sizek / 2; unsigned int bits_per_page = stellaris->pagesize / 2048; /* Every lock bit always corresponds to a 2k region */ for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) { uint32_t fmppe; target_read_u32(target, fmppe_addr, &fmppe); for (i = 0; i < 32 && lockbitnum + i < lockbitcnt; i++) { bool protect = !(fmppe & (1 << i)); if (bits_per_page) { bank->sectors[page++].is_protected = protect; i += bits_per_page - 1; } else { /* 1024k pages, every lockbit covers 2 pages */ bank->sectors[page++].is_protected = protect; bank->sectors[page++].is_protected = protect; } } fmppe_addr += 4; } return status; } static int stellaris_erase(struct flash_bank *bank, int first, int last) { int banknr; uint32_t flash_fmc, flash_cris; struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (stellaris_info->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages)) return ERROR_FLASH_SECTOR_INVALID; if ((first == 0) && (last == ((int)stellaris_info->num_pages-1))) return stellaris_mass_erase(bank); /* Refresh flash controller timing */ stellaris_read_clock_info(bank); stellaris_set_flash_timing(bank); /* Clear and disable flash programming interrupts */ target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); /* REVISIT this clobbers state set by any halted firmware ... * it might want to process those IRQs. */ for (banknr = first; banknr <= last; banknr++) { /* Address is first word in page */ target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize); /* Write erase command */ target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE); /* Wait until erase complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_ERASE); /* Check acess violations */ target_read_u32(target, FLASH_CRIS, &flash_cris); if (flash_cris & (AMASK)) { LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris); target_write_u32(target, FLASH_CRIS, 0); return ERROR_FLASH_OPERATION_FAILED; } bank->sectors[banknr].is_erased = 1; } return ERROR_OK; } static int stellaris_protect(struct flash_bank *bank, int set, int first, int last) { struct stellaris_flash_bank *stellaris = bank->driver_priv; struct target *target = bank->target; uint32_t flash_fmc, flash_cris; unsigned int bits_per_page = stellaris->pagesize / 2048; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!set) { LOG_ERROR("Hardware doesn't support page-level unprotect. " "Try the 'recover' command."); return ERROR_COMMAND_SYNTAX_ERROR; } if (stellaris->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (stellaris->target_class == 0x03 && !((stellaris->did0 >> 8) & 0xFF) && !((stellaris->did0) & 0xFF)) { LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed"); return ERROR_FLASH_OPERATION_FAILED; } if (!bits_per_page && (first % 2 || !(last % 2))) { LOG_ERROR("Can't protect unaligned pages"); return ERROR_FLASH_SECTOR_INVALID; } /* Refresh flash controller timing */ stellaris_read_clock_info(bank); stellaris_set_flash_timing(bank); /* Clear and disable flash programming interrupts */ target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); uint32_t flash_sizek = stellaris->pagesize / 1024 * stellaris->num_pages; uint32_t fmppe_addr; if (stellaris->target_class >= 0x0a || flash_sizek > 64) fmppe_addr = SCB_BASE | FMPPE0; else fmppe_addr = SCB_BASE | FMPPE; int page = 0; unsigned int lockbitnum, lockbitcnt = flash_sizek / 2; /* Every lock bit always corresponds to a 2k region */ for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) { uint32_t fmppe; target_read_u32(target, fmppe_addr, &fmppe); for (unsigned int i = 0; i < 32 && lockbitnum + i < lockbitcnt; i++) { if (page >= first && page <= last) fmppe &= ~(1 << i); if (bits_per_page) { if (!((i + 1) % bits_per_page)) page++; } else { /* 1024k pages, every lockbit covers 2 pages */ page += 2; } } target_write_u32(target, fmppe_addr, fmppe); /* Commit FMPPE* */ target_write_u32(target, FLASH_FMA, 1 + lockbitnum / 16); /* Write commit command */ target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); /* Wait until commit complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_COMT); /* Check access violations */ target_read_u32(target, FLASH_CRIS, &flash_cris); if (flash_cris & (AMASK)) { LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris); target_write_u32(target, FLASH_CRIS, 0); return ERROR_FLASH_OPERATION_FAILED; } fmppe_addr += 4; } return ERROR_OK; } /* see contib/loaders/flash/stellaris.s for src */ static const uint8_t stellaris_write_code[] = { /* write: */ 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */ 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */ /* wait_fifo: */ 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */ 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */ 0x17, 0xD0, /* beq exit */ 0x47, 0x68, /* ldr r7, [r0, #4] */ 0x47, 0x45, /* cmp r7, r8 */ 0xF7, 0xD0, /* beq wait_fifo */ /* mainloop: */ 0x22, 0x60, /* str r2, [r4, #0] */ 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */ 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */ 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */ 0xA5, 0x60, /* str r5, [r4, #8] */ /* busy: */ 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */ 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */ 0xFA, 0xD1, /* bne busy */ 0x8F, 0x42, /* cmp r7, r1 */ 0x28, 0xBF, /* it cs */ 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */ 0x47, 0x60, /* str r7, [r0, #4] */ 0x01, 0x3B, /* subs r3, r3, #1 */ 0x03, 0xB1, /* cbz r3, exit */ 0xE2, 0xE7, /* b wait_fifo */ /* exit: */ 0x00, 0xBE, /* bkpt #0 */ /* pFLASH_CTRL_BASE: */ 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */ /* FLASHWRITECMD: */ 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */ }; static int stellaris_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t wcount) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *source; struct working_area *write_algorithm; uint32_t address = bank->base + offset; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* power of two, and multiple of word size */ static const unsigned buf_min = 128; /* for small buffers it's faster not to download an algorithm */ if (wcount * 4 < buf_min) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "", bank, buffer, offset, wcount); /* flash write code */ if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; /* plus a buffer big enough for this data */ if (wcount * 4 < buffer_size) buffer_size = wcount * 4; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= buf_min) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", target_name(target), (unsigned) buffer_size); }; target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, wcount); retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, 0, NULL, 4, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (retval == ERROR_FLASH_OPERATION_FAILED) LOG_ERROR("error %d executing stellaris flash write algorithm", retval); target_free_working_area(target, write_algorithm); target_free_working_area(target, source); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); return retval; } static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t address = offset; uint32_t flash_cris, flash_fmc; uint32_t words_remaining = (count / 4); uint32_t bytes_remaining = (count & 0x00000003); uint32_t bytes_written = 0; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "", bank, buffer, offset, count); if (stellaris_info->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (offset & 0x3) { LOG_WARNING("offset size must be word aligned"); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; /* Refresh flash controller timing */ stellaris_read_clock_info(bank); stellaris_set_flash_timing(bank); /* Clear and disable flash programming interrupts */ target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); /* REVISIT this clobbers state set by any halted firmware ... * it might want to process those IRQs. */ /* multiple words to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = stellaris_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { LOG_DEBUG("writing flash word-at-a-time"); } else if (retval == ERROR_FLASH_OPERATION_FAILED) { /* if an error occured, we examine the reason, and quit */ target_read_u32(target, FLASH_CRIS, &flash_cris); LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris); return ERROR_FLASH_OPERATION_FAILED; } } else { buffer += words_remaining * 4; address += words_remaining * 4; words_remaining = 0; } } while (words_remaining > 0) { if (!(address & 0xff)) LOG_DEBUG("0x%" PRIx32 "", address); /* Program one word */ target_write_u32(target, FLASH_FMA, address); target_write_buffer(target, FLASH_FMD, 4, buffer); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE); /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */ /* Wait until write complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_WRITE); buffer += 4; address += 4; words_remaining--; } if (bytes_remaining) { uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff}; /* copy the last remaining bytes into the write buffer */ memcpy(last_word, buffer+bytes_written, bytes_remaining); if (!(address & 0xff)) LOG_DEBUG("0x%" PRIx32 "", address); /* Program one word */ target_write_u32(target, FLASH_FMA, address); target_write_buffer(target, FLASH_FMD, 4, last_word); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE); /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */ /* Wait until write complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_WRITE); } /* Check access violations */ target_read_u32(target, FLASH_CRIS, &flash_cris); if (flash_cris & (AMASK)) { LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int stellaris_probe(struct flash_bank *bank) { struct stellaris_flash_bank *stellaris_info = bank->driver_priv; int retval; /* If this is a stellaris chip, it has flash; probe() is just * to figure out how much is present. Only do it once. */ if (stellaris_info->did1 != 0) return ERROR_OK; /* stellaris_read_part_info() already handled error checking and * reporting. Note that it doesn't write, so we don't care about * whether the target is halted or not. */ retval = stellaris_read_part_info(bank); if (retval != ERROR_OK) return retval; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } /* provide this for the benefit of the NOR flash framework */ bank->size = stellaris_info->num_pages * stellaris_info->pagesize; bank->num_sectors = stellaris_info->num_pages; bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = i * stellaris_info->pagesize; bank->sectors[i].size = stellaris_info->pagesize; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } return retval; } static int stellaris_mass_erase(struct flash_bank *bank) { struct target *target = NULL; struct stellaris_flash_bank *stellaris_info = NULL; uint32_t flash_fmc; stellaris_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (stellaris_info->did1 == 0) return ERROR_FLASH_BANK_NOT_PROBED; /* Refresh flash controller timing */ stellaris_read_clock_info(bank); stellaris_set_flash_timing(bank); /* Clear and disable flash programming interrupts */ target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); /* REVISIT this clobbers state set by any halted firmware ... * it might want to process those IRQs. */ target_write_u32(target, FLASH_FMA, 0); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); /* Wait until erase complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_MERASE); /* if device has > 128k, then second erase cycle is needed * this is only valid for older devices, but will not hurt */ if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) { target_write_u32(target, FLASH_FMA, 0x20000); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); /* Wait until erase complete */ do { target_read_u32(target, FLASH_FMC, &flash_fmc); } while (flash_fmc & FMC_MERASE); } return ERROR_OK; } COMMAND_HANDLER(stellaris_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; if (stellaris_mass_erase(bank) == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "stellaris mass erase complete"); } else command_print(CMD_CTX, "stellaris mass erase failed"); return ERROR_OK; } /** * Perform the Stellaris "Recovering a 'Locked' Device procedure. * This performs a mass erase and then restores all nonvolatile registers * (including USER_* registers and flash lock bits) to their defaults. * Accordingly, flash can be reprogrammed, and JTAG can be used. * * NOTE that DustDevil parts (at least rev A0 silicon) have errata which * can affect this operation if flash protection has been enabled. */ COMMAND_HANDLER(stellaris_handle_recover_command) { struct flash_bank *bank; int retval; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; bank = get_flash_bank_by_num_noprobe(0); if (!bank) return ERROR_FAIL; /* REVISIT ... it may be worth sanity checking that the AP is * inactive before we start. ARM documents that switching a DP's * mode while it's active can cause fault modes that need a power * cycle to recover. */ Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0); if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) { retval = ERROR_OK; goto user_action; } /* assert SRST */ if (!(jtag_get_reset_config() & RESET_HAS_SRST)) { LOG_ERROR("Can't recover Stellaris flash without SRST"); return ERROR_FAIL; } adapter_assert_reset(); for (int i = 0; i < 5; i++) { retval = dap_to_swd(bank->target); if (retval != ERROR_OK) goto done; retval = dap_to_jtag(bank->target); if (retval != ERROR_OK) goto done; } /* de-assert SRST */ adapter_deassert_reset(); retval = jtag_execute_queue(); /* wait 400+ msec ... OK, "1+ second" is simpler */ usleep(1000); user_action: /* USER INTERVENTION required for the power cycle * Restarting OpenOCD is likely needed because of mode switching. */ LOG_INFO("USER ACTION: " "power cycle Stellaris chip, then restart OpenOCD."); done: return retval; } static const struct command_registration stellaris_exec_command_handlers[] = { { .name = "mass_erase", .usage = "", .handler = stellaris_handle_mass_erase_command, .mode = COMMAND_EXEC, .help = "erase entire device", }, { .name = "recover", .handler = stellaris_handle_recover_command, .mode = COMMAND_EXEC, .usage = "", .help = "recover (and erase) locked device", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration stellaris_command_handlers[] = { { .name = "stellaris", .mode = COMMAND_EXEC, .help = "Stellaris flash command group", .usage = "", .chain = stellaris_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver stellaris_flash = { .name = "stellaris", .commands = stellaris_command_handlers, .flash_bank_command = stellaris_flash_bank_command, .erase = stellaris_erase, .protect = stellaris_protect, .write = stellaris_write, .read = default_flash_read, .probe = stellaris_probe, .auto_probe = stellaris_probe, .erase_check = default_flash_blank_check, .protect_check = stellaris_protect_check, .info = get_stellaris_info, }; openocd-0.9.0/src/flash/nor/faux.c0000644000175000017500000001046412315575360013675 00000000000000/*************************************************************************** * Copyright (C) 2009 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include "hello.h" struct faux_flash_bank { struct target *target; uint8_t *memory; uint32_t start_address; }; static const int sectorSize = 0x10000; /* flash bank faux */ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command) { struct faux_flash_bank *info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; info = malloc(sizeof(struct faux_flash_bank)); if (info == NULL) { LOG_ERROR("no memory for flash bank info"); return ERROR_FAIL; } info->memory = malloc(bank->size); if (info == NULL) { free(info); LOG_ERROR("no memory for flash bank info"); return ERROR_FAIL; } bank->driver_priv = info; /* Use 0x10000 as a fixed sector size. */ int i = 0; uint32_t offset = 0; bank->num_sectors = bank->size/sectorSize; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = sectorSize; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; } info->target = get_target(CMD_ARGV[5]); if (info->target == NULL) { LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); free(info->memory); free(info); return ERROR_FAIL; } return ERROR_OK; } static int faux_erase(struct flash_bank *bank, int first, int last) { struct faux_flash_bank *info = bank->driver_priv; memset(info->memory + first*sectorSize, 0xff, sectorSize*(last-first + 1)); return ERROR_OK; } static int faux_protect(struct flash_bank *bank, int set, int first, int last) { LOG_USER("set protection sector %d to %d to %s", first, last, set ? "on" : "off"); return ERROR_OK; } static int faux_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct faux_flash_bank *info = bank->driver_priv; memcpy(info->memory + offset, buffer, count); return ERROR_OK; } static int faux_protect_check(struct flash_bank *bank) { return ERROR_OK; } static int faux_info(struct flash_bank *bank, char *buf, int buf_size) { snprintf(buf, buf_size, "faux flash driver"); return ERROR_OK; } static int faux_probe(struct flash_bank *bank) { return ERROR_OK; } static const struct command_registration faux_command_handlers[] = { { .name = "faux", .mode = COMMAND_ANY, .help = "faux flash command group", .chain = hello_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver faux_flash = { .name = "faux", .commands = faux_command_handlers, .flash_bank_command = faux_flash_bank_command, .erase = faux_erase, .protect = faux_protect, .write = faux_write, .read = default_flash_read, .probe = faux_probe, .auto_probe = faux_probe, .erase_check = default_flash_blank_check, .protect_check = faux_protect_check, .info = faux_info }; openocd-0.9.0/src/flash/nor/Makefile.am0000644000175000017500000000142012516456302014607 00000000000000include $(top_srcdir)/common.mk noinst_LTLIBRARIES = libocdflashnor.la libocdflashnor_la_SOURCES = \ core.c \ tcl.c \ $(NOR_DRIVERS) \ drivers.c NOR_DRIVERS = \ aduc702x.c \ at91sam4.c \ at91sam4l.c \ at91samd.c \ at91sam3.c \ at91sam7.c \ avrf.c \ cfi.c \ efm32.c \ em357.c \ faux.c \ lpc2000.c \ lpc288x.c \ lpc2900.c \ lpcspifi.c \ mdr.c \ non_cfi.c \ ocl.c \ pic32mx.c \ spi.c \ stmsmi.c \ stellaris.c \ stm32f1x.c \ stm32f2x.c \ stm32lx.c \ str7x.c \ str9x.c \ str9xpec.c \ tms470.c \ virtual.c \ fm3.c \ dsp5680xx_flash.c \ kinetis.c \ mini51.c \ nuc1x.c \ nrf51.c \ mrvlqspi.c \ psoc4.c \ sim3x.c noinst_HEADERS = \ core.h \ cfi.h \ driver.h \ imp.h \ non_cfi.h \ ocl.h \ spi.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/flash/nor/Makefile.in0000644000175000017500000005355212526201647014636 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/flash/nor ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdflashnor_la_LIBADD = am__objects_1 = aduc702x.lo at91sam4.lo at91sam4l.lo at91samd.lo \ at91sam3.lo at91sam7.lo avrf.lo cfi.lo efm32.lo em357.lo \ faux.lo lpc2000.lo lpc288x.lo lpc2900.lo lpcspifi.lo mdr.lo \ non_cfi.lo ocl.lo pic32mx.lo spi.lo stmsmi.lo stellaris.lo \ stm32f1x.lo stm32f2x.lo stm32lx.lo str7x.lo str9x.lo \ str9xpec.lo tms470.lo virtual.lo fm3.lo dsp5680xx_flash.lo \ kinetis.lo mini51.lo nuc1x.lo nrf51.lo mrvlqspi.lo psoc4.lo \ sim3x.lo am_libocdflashnor_la_OBJECTS = core.lo tcl.lo $(am__objects_1) \ drivers.lo libocdflashnor_la_OBJECTS = $(am_libocdflashnor_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdflashnor_la_SOURCES) DIST_SOURCES = $(libocdflashnor_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) noinst_LTLIBRARIES = libocdflashnor.la libocdflashnor_la_SOURCES = \ core.c \ tcl.c \ $(NOR_DRIVERS) \ drivers.c NOR_DRIVERS = \ aduc702x.c \ at91sam4.c \ at91sam4l.c \ at91samd.c \ at91sam3.c \ at91sam7.c \ avrf.c \ cfi.c \ efm32.c \ em357.c \ faux.c \ lpc2000.c \ lpc288x.c \ lpc2900.c \ lpcspifi.c \ mdr.c \ non_cfi.c \ ocl.c \ pic32mx.c \ spi.c \ stmsmi.c \ stellaris.c \ stm32f1x.c \ stm32f2x.c \ stm32lx.c \ str7x.c \ str9x.c \ str9xpec.c \ tms470.c \ virtual.c \ fm3.c \ dsp5680xx_flash.c \ kinetis.c \ mini51.c \ nuc1x.c \ nrf51.c \ mrvlqspi.c \ psoc4.c \ sim3x.c noinst_HEADERS = \ core.h \ cfi.h \ driver.h \ imp.h \ non_cfi.h \ ocl.h \ spi.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/flash/nor/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/flash/nor/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libocdflashnor.la: $(libocdflashnor_la_OBJECTS) $(libocdflashnor_la_DEPENDENCIES) $(EXTRA_libocdflashnor_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdflashnor_la_OBJECTS) $(libocdflashnor_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aduc702x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91sam3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91sam4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91sam4l.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91sam7.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91samd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avrf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drivers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsp5680xx_flash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/efm32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em357.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fm3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kinetis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc2000.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc288x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc2900.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpcspifi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mini51.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mrvlqspi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/non_cfi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nrf51.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nuc1x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pic32mx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psoc4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim3x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stellaris.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stm32f1x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stm32f2x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stm32lx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stmsmi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str7x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str9x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str9xpec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tms470.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/flash/nor/at91sam4l.c0000644000175000017500000005046212516456302014450 00000000000000/*************************************************************************** * Copyright (C) 2013 by Andrey Yurovsky * * Andrey Yurovsky * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include /* At this time, the SAM4L Flash is available in these capacities: * ATSAM4Lx4xx: 256KB (512 pages) * ATSAM4Lx2xx: 128KB (256 pages) * ATSAM4Lx8xx: 512KB (1024 pages) */ /* There are 16 lockable regions regardless of overall capacity. The number * of pages per sector is therefore dependant on capacity. */ #define SAM4L_NUM_SECTORS 16 /* Locations in memory map */ #define SAM4L_FLASH ((uint32_t)0x00000000) /* Flash region */ #define SAM4L_FLASH_USER 0x00800000 /* Flash user page region */ #define SAM4L_FLASHCALW 0x400A0000 /* Flash controller */ #define SAM4L_CHIPID 0x400E0740 /* Chip Identification */ /* Offsets from SAM4L_FLASHCALW */ #define SAM4L_FCR 0x00 /* Flash Control Register (RW) */ #define SAM4L_FCMD 0x04 /* Flash Command Register (RW) */ #define SAM4L_FSR 0x08 /* Flash Status Register (RO) */ #define SAM4L_FPR 0x0C /* Flash Parameter Register (RO) */ #define SAM4L_FVR 0x10 /* Flash Version Register (RO) */ #define SAM4L_FGPFRHI 0x14 /* Flash General Purpose Register High (RO) */ #define SAM4L_FGPFRLO 0x18 /* Flash General Purpose Register Low (RO) */ /* Offsets from SAM4L_CHIPID */ #define SAM4L_CIDR 0x00 /* Chip ID Register (RO) */ #define SAM4L_EXID 0x04 /* Chip ID Extension Register (RO) */ /* Flash commands (for SAM4L_FCMD), see Table 14-5 */ #define SAM4L_FCMD_NOP 0 /* No Operation */ #define SAM4L_FCMD_WP 1 /* Write Page */ #define SAM4L_FCMD_EP 2 /* Erase Page */ #define SAM4L_FCMD_CPB 3 /* Clear Page Buffer */ #define SAM4L_FCMD_LP 4 /* Lock region containing given page */ #define SAM4L_FCMD_UP 5 /* Unlock region containing given page */ #define SAM4L_FCMD_EA 6 /* Erase All */ #define SAM4L_FCMD_WGPB 7 /* Write general-purpose fuse bit */ #define SAM4L_FCMD_EGPB 8 /* Erase general-purpose fuse bit */ #define SAM4L_FCMD_SSB 9 /* Set security fuses */ #define SAM4L_FCMD_PGPFB 10 /* Program general-purpose fuse byte */ #define SAM4L_FCMD_EAGPF 11 /* Erase all general-purpose fuse bits */ #define SAM4L_FCMD_QPR 12 /* Quick page read */ #define SAM4L_FCMD_WUP 13 /* Write user page */ #define SAM4L_FCMD_EUP 14 /* Erase user page */ #define SAM4L_FCMD_QPRUP 15 /* Quick page read (user page) */ #define SAM4L_FCMD_HSEN 16 /* High speed mode enable */ #define SAM4L_FCMD_HSDIS 17 /* High speed mode disable */ #define SAM4L_FMCD_CMDKEY 0xA5UL /* 'key' to issue commands, see 14.10.2 */ /* SMAP registers and bits */ #define SMAP_BASE 0x400A3000 #define SMAP_SCR (SMAP_BASE + 8) #define SMAP_SCR_HCR (1 << 1) struct sam4l_chip_info { uint32_t id; uint32_t exid; const char *name; }; /* These are taken from Table 9-1 in 42023E-SAM-07/2013 */ static const struct sam4l_chip_info sam4l_known_chips[] = { { 0xAB0B0AE0, 0x1400000F, "ATSAM4LC8C" }, { 0xAB0A09E0, 0x0400000F, "ATSAM4LC4C" }, { 0xAB0A07E0, 0x0400000F, "ATSAM4LC2C" }, { 0xAB0B0AE0, 0x1300000F, "ATSAM4LC8B" }, { 0xAB0A09E0, 0x0300000F, "ATSAM4LC4B" }, { 0xAB0A07E0, 0x0300000F, "ATSAM4LC2B" }, { 0xAB0B0AE0, 0x1200000F, "ATSAM4LC8A" }, { 0xAB0A09E0, 0x0200000F, "ATSAM4LC4A" }, { 0xAB0A07E0, 0x0200000F, "ATSAM4LC2A" }, { 0xAB0B0AE0, 0x14000002, "ATSAM4LS8C" }, { 0xAB0A09E0, 0x04000002, "ATSAM4LS4C" }, { 0xAB0A07E0, 0x04000002, "ATSAM4LS2C" }, { 0xAB0B0AE0, 0x13000002, "ATSAM4LS8B" }, { 0xAB0A09E0, 0x03000002, "ATSAM4LS4B" }, { 0xAB0A07E0, 0x03000002, "ATSAM4LS2B" }, { 0xAB0B0AE0, 0x12000002, "ATSAM4LS8A" }, { 0xAB0A09E0, 0x02000002, "ATSAM4LS4A" }, { 0xAB0A07E0, 0x02000002, "ATSAM4LS2A" }, }; /* Meaning of SRAMSIZ field in CHIPID, see 9.3.1 in 42023E-SAM-07/2013 */ static const uint16_t sam4l_ram_sizes[16] = { 48, 1, 2, 6, 24, 4, 80, 160, 8, 16, 32, 64, 128, 256, 96, 512 }; /* Meaning of PSZ field in FPR, see 14.10.4 in 42023E-SAM-07/2013 */ static const uint16_t sam4l_page_sizes[8] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 }; struct sam4l_info { const struct sam4l_chip_info *details; uint32_t flash_kb; uint32_t ram_kb; uint32_t page_size; int num_pages; int sector_size; int pages_per_sector; bool probed; struct target *target; struct sam4l_info *next; }; static struct sam4l_info *sam4l_chips; static int sam4l_flash_wait_until_ready(struct target *target) { volatile unsigned int t = 0; uint32_t st; int res; /* Poll the status register until the FRDY bit is set */ do { res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FSR, &st); } while (res == ERROR_OK && !(st & (1<<0)) && ++t < 10); return res; } static int sam4l_flash_check_error(struct target *target, uint32_t *err) { uint32_t st; int res; res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FSR, &st); if (res == ERROR_OK) *err = st & ((1<<3) | (1<<2)); /* grab PROGE and LOCKE bits */ return res; } static int sam4l_flash_command(struct target *target, uint8_t cmd, int page) { int res; uint32_t fcmd; uint32_t err; res = sam4l_flash_wait_until_ready(target); if (res != ERROR_OK) return res; if (page >= 0) { /* Set the page number. For some commands, the page number is just an * argument (ex: fuse bit number). */ fcmd = (SAM4L_FMCD_CMDKEY << 24) | ((page & 0xFFFF) << 8) | (cmd & 0x3F); } else { /* Reuse the page number that was read from the flash command register. */ res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FCMD, &fcmd); if (res != ERROR_OK) return res; fcmd &= ~0x3F; /* clear out the command code */ fcmd |= (SAM4L_FMCD_CMDKEY << 24) | (cmd & 0x3F); } /* Send the command */ res = target_write_u32(target, SAM4L_FLASHCALW + SAM4L_FCMD, fcmd); if (res != ERROR_OK) return res; res = sam4l_flash_check_error(target, &err); if (res != ERROR_OK) return res; if (err != 0) LOG_ERROR("%s got error status 0x%08" PRIx32, __func__, err); res = sam4l_flash_wait_until_ready(target); return res; } FLASH_BANK_COMMAND_HANDLER(sam4l_flash_bank_command) { struct sam4l_info *chip = sam4l_chips; while (chip) { if (chip->target == bank->target) break; chip = chip->next; } if (!chip) { /* Create a new chip */ chip = calloc(1, sizeof(*chip)); if (!chip) return ERROR_FAIL; chip->target = bank->target; chip->probed = false; bank->driver_priv = chip; /* Insert it into the chips list (at head) */ chip->next = sam4l_chips; sam4l_chips = chip; } if (bank->base != SAM4L_FLASH) { LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 "[at91sam4l series] )", bank->base, SAM4L_FLASH); return ERROR_FAIL; } return ERROR_OK; } static const struct sam4l_chip_info *sam4l_find_chip_name(uint32_t id, uint32_t exid) { unsigned int i; id &= ~0xF; for (i = 0; i < ARRAY_SIZE(sam4l_known_chips); i++) { if (sam4l_known_chips[i].id == id && sam4l_known_chips[i].exid == exid) return &sam4l_known_chips[i]; } return NULL; } static int sam4l_check_page_erased(struct flash_bank *bank, uint32_t pn, bool *is_erased_p) { int res; uint32_t st; /* Issue a quick page read to verify that we've erased this page */ res = sam4l_flash_command(bank->target, SAM4L_FCMD_QPR, pn); if (res != ERROR_OK) { LOG_ERROR("Quick page read %" PRIu32 " failed", pn); return res; } /* Retrieve the flash status */ res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st); if (res != ERROR_OK) { LOG_ERROR("Couldn't read erase status"); return res; } /* Is the page in question really erased? */ *is_erased_p = !!(st & (1<<5)); return ERROR_OK; } static int sam4l_probe(struct flash_bank *bank) { uint32_t id, exid, param; int res; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; if (chip->probed) return ERROR_OK; res = target_read_u32(bank->target, SAM4L_CHIPID + SAM4L_CIDR, &id); if (res != ERROR_OK) { LOG_ERROR("Couldn't read chip ID"); return res; } res = target_read_u32(bank->target, SAM4L_CHIPID + SAM4L_EXID, &exid); if (res != ERROR_OK) { LOG_ERROR("Couldn't read extended chip ID"); return res; } chip->details = sam4l_find_chip_name(id, exid); /* The RAM capacity is in a lookup table. */ chip->ram_kb = sam4l_ram_sizes[0xF & (id >> 16)]; switch (0xF & (id >> 8)) { case 0x07: chip->flash_kb = 128; break; case 0x09: chip->flash_kb = 256; break; case 0x0A: chip->flash_kb = 512; break; default: LOG_ERROR("Unknown flash size (chip ID is %08" PRIx32 "), assuming 128K", id); chip->flash_kb = 128; break; } /* Retrieve the Flash parameters */ res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FPR, ¶m); if (res != ERROR_OK) { LOG_ERROR("Couldn't read Flash parameters"); return res; } /* Fetch the page size from the parameter register. Technically the flash * capacity is there too though the manual mentions that not all parts will * have it set so we use the Chip ID capacity information instead. */ chip->page_size = sam4l_page_sizes[0x7 & (param >> 8)]; assert(chip->page_size); chip->num_pages = chip->flash_kb * 1024 / chip->page_size; chip->sector_size = (chip->flash_kb * 1024) / SAM4L_NUM_SECTORS; chip->pages_per_sector = chip->sector_size / chip->page_size; /* Make sure the bank size is correct */ bank->size = chip->flash_kb * 1024; /* Allocate the sector table. */ bank->num_sectors = SAM4L_NUM_SECTORS; bank->sectors = calloc(bank->num_sectors, (sizeof((bank->sectors)[0]))); if (!bank->sectors) return ERROR_FAIL; /* Fill out the sector information: all SAM4L sectors are the same size and * there is always a fixed number of them. */ for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].size = chip->sector_size; bank->sectors[i].offset = i * chip->sector_size; /* mark as unknown */ bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } /* Done */ chip->probed = true; LOG_INFO("SAM4L MCU: %s (Rev %c) (%" PRIu32 "KB Flash with %d %" PRId32 "B pages, %" PRIu32 "KB RAM)", chip->details ? chip->details->name : "unknown", (char)('A' + (id & 0xF)), chip->flash_kb, chip->num_pages, chip->page_size, chip->ram_kb); return ERROR_OK; } static int sam4l_protect_check(struct flash_bank *bank) { int res; uint32_t st; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (sam4l_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st); if (res != ERROR_OK) return res; st >>= 16; /* There are 16 lock region bits in the upper half word */ for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = !!(st & (1<target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (sam4l_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } /* Make sure the pages make sense. */ if (first >= bank->num_sectors || last >= bank->num_sectors) { LOG_ERROR("Protect range %d - %d not valid (%d sectors total)", first, last, bank->num_sectors); return ERROR_FAIL; } /* Try to lock or unlock each sector in the range. This is done by locking * a region containing one page in that sector, we arbitrarily choose the 0th * page in the sector. */ for (int i = first; i <= last; i++) { int res; res = sam4l_flash_command(bank->target, set ? SAM4L_FCMD_LP : SAM4L_FCMD_UP, i * chip->pages_per_sector); if (res != ERROR_OK) { LOG_ERROR("Can't %slock region containing page %d", set ? "" : "un", i); return res; } } return ERROR_OK; } static int sam4l_erase(struct flash_bank *bank, int first, int last) { int ret; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (sam4l_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } /* Make sure the pages make sense. */ if (first >= bank->num_sectors || last >= bank->num_sectors) { LOG_ERROR("Erase range %d - %d not valid (%d sectors total)", first, last, bank->num_sectors); return ERROR_FAIL; } /* Erase */ if ((first == 0) && ((last + 1) == bank->num_sectors)) { LOG_DEBUG("Erasing the whole chip"); ret = sam4l_flash_command(bank->target, SAM4L_FCMD_EA, -1); if (ret != ERROR_OK) { LOG_ERROR("Erase All failed"); return ret; } } else { LOG_DEBUG("Erasing sectors %d through %d...\n", first, last); /* For each sector... */ for (int i = first; i <= last; i++) { /* For each page in that sector... */ for (int j = 0; j < chip->pages_per_sector; j++) { int pn = i * chip->pages_per_sector + j; bool is_erased = false; /* Issue the page erase */ ret = sam4l_flash_command(bank->target, SAM4L_FCMD_EP, pn); if (ret != ERROR_OK) { LOG_ERROR("Erasing page %d failed", pn); return ret; } ret = sam4l_check_page_erased(bank, pn, &is_erased); if (ret != ERROR_OK) return ret; if (!is_erased) { LOG_DEBUG("Page %d was not erased.", pn); return ERROR_FAIL; } } /* This sector is definitely erased. */ bank->sectors[i].is_erased = 1; } } return ERROR_OK; } /* Write an entire page from host buffer 'buf' to page-aligned 'address' in the * Flash. */ static int sam4l_write_page(struct sam4l_info *chip, struct target *target, uint32_t address, const uint8_t *buf) { int res; LOG_DEBUG("sam4l_write_page address=%08" PRIx32, address); /* Clear the page buffer before we write to it */ res = sam4l_flash_command(target, SAM4L_FCMD_CPB, -1); if (res != ERROR_OK) { LOG_ERROR("%s: can't clear page buffer", __func__); return res; } /* Write the modified page back to the target's page buffer */ res = target_write_memory(target, address, 4, chip->page_size / 4, buf); if (res != ERROR_OK) { LOG_ERROR("%s: %d", __func__, __LINE__); return res; } /* Commit the page contents to Flash: erase the current page and then * write it out. */ res = sam4l_flash_command(target, SAM4L_FCMD_EP, -1); if (res != ERROR_OK) return res; res = sam4l_flash_command(target, SAM4L_FCMD_WP, -1); return res; } /* Write partial contents into page-aligned 'address' on the Flash from host * buffer 'buf' by writing 'nb' of 'buf' at 'offset' into the Flash page. */ static int sam4l_write_page_partial(struct sam4l_info *chip, struct flash_bank *bank, uint32_t address, const uint8_t *buf, uint32_t page_offset, uint32_t nb) { int res; uint8_t *pg = malloc(chip->page_size); if (!pg) return ERROR_FAIL; LOG_DEBUG("sam4l_write_page_partial address=%08" PRIx32 " nb=%08" PRIx32, address, nb); assert(page_offset + nb < chip->page_size); assert((address % chip->page_size) == 0); /* Retrieve the full page contents from Flash */ res = target_read_memory(bank->target, address, 4, chip->page_size / 4, pg); if (res != ERROR_OK) { free(pg); return res; } /* Insert our partial page over the data from Flash */ memcpy(pg + (page_offset % chip->page_size), buf, nb); /* Write the page back out */ res = sam4l_write_page(chip, bank->target, address, pg); free(pg); return res; } static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int res; uint32_t nb = 0; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; LOG_DEBUG("sam4l_write offset=%08" PRIx32 " count=%08" PRIx32, offset, count); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (sam4l_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } if (offset % chip->page_size) { /* We're starting at an unaligned offset so we'll write a partial page * comprising that offset and up to the end of that page. */ nb = chip->page_size - (offset % chip->page_size); if (nb > count) nb = count; } else if (count < chip->page_size) { /* We're writing an aligned but partial page. */ nb = count; } if (nb > 0) { res = sam4l_write_page_partial(chip, bank, (offset / chip->page_size) * chip->page_size + bank->base, buffer, offset % chip->page_size, nb); if (res != ERROR_OK) return res; /* We're done with the page contents */ count -= nb; offset += nb; } /* There's at least one aligned page to write out. */ if (count >= chip->page_size) { int np = count / chip->page_size + ((count % chip->page_size) ? 1 : 0); for (int i = 0; i < np; i++) { if (count >= chip->page_size) { res = sam4l_write_page(chip, bank->target, bank->base + offset, buffer + (i * chip->page_size)); /* Advance one page */ offset += chip->page_size; count -= chip->page_size; } else { res = sam4l_write_page_partial(chip, bank, bank->base + offset, buffer + (i * chip->page_size), 0, count); /* We're done after this. */ offset += count; count = 0; } if (res != ERROR_OK) return res; } } return ERROR_OK; } COMMAND_HANDLER(sam4l_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by SMAP * * n_RESET (srst) clears the DP, so reenable debug and set vector catch here * * After vectreset SMAP release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { retval = mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) retval = mem_ap_write_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing SMAP reset is more important */ } int retval2 = mem_ap_write_atomic_u32(swjdp, SMAP_SCR, SMAP_SCR_HCR); if (retval2 != ERROR_OK) return retval2; return retval; } static const struct command_registration at91sam4l_exec_command_handlers[] = { { .name = "smap_reset_deassert", .handler = sam4l_handle_reset_deassert, .mode = COMMAND_EXEC, .help = "deasert internal reset held by SMAP" }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91sam4l_command_handlers[] = { { .name = "at91sam4l", .mode = COMMAND_ANY, .help = "at91sam4l flash command group", .usage = "", .chain = at91sam4l_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver at91sam4l_flash = { .name = "at91sam4l", .commands = at91sam4l_command_handlers, .flash_bank_command = sam4l_flash_bank_command, .erase = sam4l_erase, .protect = sam4l_protect, .write = sam4l_write, .read = default_flash_read, .probe = sam4l_probe, .auto_probe = sam4l_probe, .erase_check = default_flash_blank_check, .protect_check = sam4l_protect_check, }; openocd-0.9.0/src/flash/nor/str9xpec.c0000644000175000017500000007341212315575360014515 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include /* ISC commands */ #define ISC_IDCODE 0xFE #define ISC_MFG_READ 0x4C #define ISC_CONFIGURATION 0x07 #define ISC_ENABLE 0x0C #define ISC_DISABLE 0x0F #define ISC_NOOP 0x10 #define ISC_ADDRESS_SHIFT 0x11 #define ISC_CLR_STATUS 0x13 #define ISC_PROGRAM 0x20 #define ISC_PROGRAM_SECURITY 0x22 #define ISC_PROGRAM_UC 0x23 #define ISC_ERASE 0x30 #define ISC_READ 0x50 #define ISC_BLANK_CHECK 0x60 /* ISC_DEFAULT bit definitions */ #define ISC_STATUS_SECURITY 0x40 #define ISC_STATUS_INT_ERROR 0x30 #define ISC_STATUS_MODE 0x08 #define ISC_STATUS_BUSY 0x04 #define ISC_STATUS_ERROR 0x03 /* Option bytes definitions */ #define STR9XPEC_OPT_CSMAPBIT 48 #define STR9XPEC_OPT_LVDTHRESBIT 49 #define STR9XPEC_OPT_LVDSELBIT 50 #define STR9XPEC_OPT_LVDWARNBIT 51 #define STR9XPEC_OPT_OTPBIT 63 enum str9xpec_status_codes { STR9XPEC_INVALID_COMMAND = 1, STR9XPEC_ISC_SUCCESS = 2, STR9XPEC_ISC_DISABLED = 3, STR9XPEC_ISC_INTFAIL = 32, }; struct str9xpec_flash_controller { struct jtag_tap *tap; uint32_t *sector_bits; int chain_pos; int isc_enable; uint8_t options[8]; }; static int str9xpec_erase_area(struct flash_bank *bank, int first, int last); static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector); static int str9xpec_write_options(struct flash_bank *bank); static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) { if (tap == NULL) return ERROR_TARGET_INVALID; if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { struct scan_field field; field.num_bits = tap->ir_length; void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, end_state); free(t); } return ERROR_OK; } static uint8_t str9xpec_isc_status(struct jtag_tap *tap) { struct scan_field field; uint8_t status; if (str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE) != ERROR_OK) return ISC_STATUS_ERROR; field.num_bits = 8; field.out_value = NULL; field.in_value = &status; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); LOG_DEBUG("status: 0x%2.2x", status); if (status & ISC_STATUS_SECURITY) LOG_INFO("Device Security Bit Set"); return status; } static int str9xpec_isc_enable(struct flash_bank *bank) { uint8_t status; struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (str9xpec_info->isc_enable) return ERROR_OK; /* enter isc mode */ if (str9xpec_set_instr(tap, ISC_ENABLE, TAP_IDLE) != ERROR_OK) return ERROR_TARGET_INVALID; /* check ISC status */ status = str9xpec_isc_status(tap); if (status & ISC_STATUS_MODE) { /* we have entered isc mode */ str9xpec_info->isc_enable = 1; LOG_DEBUG("ISC_MODE Enabled"); } return ERROR_OK; } static int str9xpec_isc_disable(struct flash_bank *bank) { uint8_t status; struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) return ERROR_OK; if (str9xpec_set_instr(tap, ISC_DISABLE, TAP_IDLE) != ERROR_OK) return ERROR_TARGET_INVALID; /* delay to handle aborts */ jtag_add_sleep(50); /* check ISC status */ status = str9xpec_isc_status(tap); if (!(status & ISC_STATUS_MODE)) { /* we have left isc mode */ str9xpec_info->isc_enable = 0; LOG_DEBUG("ISC_MODE Disabled"); } return ERROR_OK; } static int str9xpec_read_config(struct flash_bank *bank) { struct scan_field field; uint8_t status; struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; LOG_DEBUG("ISC_CONFIGURATION"); /* execute ISC_CONFIGURATION command */ str9xpec_set_instr(tap, ISC_CONFIGURATION, TAP_IRPAUSE); field.num_bits = 64; field.out_value = NULL; field.in_value = str9xpec_info->options; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); status = str9xpec_isc_status(tap); return status; } static int str9xpec_build_block_list(struct flash_bank *bank) { struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; int i; int num_sectors; int b0_sectors = 0, b1_sectors = 0; uint32_t offset = 0; int b1_size = 0x2000; switch (bank->size) { case (256 * 1024): b0_sectors = 4; break; case (512 * 1024): b0_sectors = 8; break; case (1024 * 1024): b0_sectors = 16; break; case (2048 * 1024): b0_sectors = 32; break; case (128 * 1024): b1_size = 0x4000; b1_sectors = 8; break; case (32 * 1024): b1_sectors = 4; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } num_sectors = b0_sectors + b1_sectors; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); str9xpec_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors); num_sectors = 0; for (i = 0; i < b0_sectors; i++) { bank->sectors[num_sectors].offset = offset; bank->sectors[num_sectors].size = 0x10000; offset += bank->sectors[i].size; bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_protected = 1; str9xpec_info->sector_bits[num_sectors++] = i; } for (i = 0; i < b1_sectors; i++) { bank->sectors[num_sectors].offset = offset; bank->sectors[num_sectors].size = b1_size; offset += bank->sectors[i].size; bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_protected = 1; str9xpec_info->sector_bits[num_sectors++] = i + 32; } return ERROR_OK; } /* flash bank str9x 0 0 */ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command) { struct str9xpec_flash_controller *str9xpec_info; struct arm *arm = NULL; struct arm7_9_common *arm7_9 = NULL; struct arm_jtag *jtag_info = NULL; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller)); bank->driver_priv = str9xpec_info; /* REVISIT verify that the jtag position of flash controller is * right after *THIS* core, which must be a STR9xx core ... */ arm = bank->target->arch_info; arm7_9 = arm->arch_info; jtag_info = &arm7_9->jtag_info; /* The core is the next tap after the flash controller in the chain */ str9xpec_info->tap = jtag_tap_by_position(jtag_info->tap->abs_chain_position - 1); str9xpec_info->isc_enable = 0; str9xpec_build_block_list(bank); /* clear option byte register */ buf_set_u32(str9xpec_info->options, 0, 64, 0); return ERROR_OK; } static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) { struct scan_field field; uint8_t status; struct jtag_tap *tap; int i; uint8_t *buffer = NULL; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ERROR_FLASH_OPERATION_FAILED; buffer = calloc(DIV_ROUND_UP(64, 8), 1); LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last); for (i = first; i <= last; i++) buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); /* execute ISC_BLANK_CHECK command */ str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE); field.num_bits = 64; field.out_value = buffer; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_add_sleep(40000); /* read blank check result */ field.num_bits = 64; field.out_value = NULL; field.in_value = buffer; jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = str9xpec_isc_status(tap); for (i = first; i <= last; i++) { if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1)) bank->sectors[i].is_erased = 0; else bank->sectors[i].is_erased = 1; } free(buffer); str9xpec_isc_disable(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } static int str9xpec_protect_check(struct flash_bank *bank) { uint8_t status; int i; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; status = str9xpec_read_config(bank); for (i = 0; i < bank->num_sectors; i++) { if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1)) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) { struct scan_field field; uint8_t status; struct jtag_tap *tap; int i; uint8_t *buffer = NULL; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ISC_STATUS_ERROR; buffer = calloc(DIV_ROUND_UP(64, 8), 1); LOG_DEBUG("erase: first_bank: %i, last_bank: %i", first, last); /* last bank: 0xFF signals a full erase (unlock complete device) */ /* last bank: 0xFE signals a option byte erase */ if (last == 0xFF) { for (i = 0; i < 64; i++) buf_set_u32(buffer, i, 1, 1); } else if (last == 0xFE) buf_set_u32(buffer, 49, 1, 1); else { for (i = first; i <= last; i++) buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); } LOG_DEBUG("ISC_ERASE"); /* execute ISC_ERASE command */ str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE); field.num_bits = 64; field.out_value = buffer; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); jtag_add_sleep(10); /* wait for erase completion */ while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) alive_sleep(1); free(buffer); str9xpec_isc_disable(bank); return status; } static int str9xpec_erase(struct flash_bank *bank, int first, int last) { int status; status = str9xpec_erase_area(bank, first, last); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } static int str9xpec_lock_device(struct flash_bank *bank) { struct scan_field field; uint8_t status; struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = NULL; str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ISC_STATUS_ERROR; /* set security address */ str9xpec_set_address(bank, 0x80); /* execute ISC_PROGRAM command */ str9xpec_set_instr(tap, ISC_PROGRAM_SECURITY, TAP_IDLE); str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { field.num_bits = 8; field.out_value = NULL; field.in_value = &status; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); str9xpec_isc_disable(bank); return status; } static int str9xpec_unlock_device(struct flash_bank *bank) { uint8_t status; status = str9xpec_erase_area(bank, 0, 255); return status; } static int str9xpec_protect(struct flash_bank *bank, int set, int first, int last) { uint8_t status; int i; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; status = str9xpec_read_config(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last); /* last bank: 0xFF signals a full device protect */ if (last == 0xFF) { if (set) status = str9xpec_lock_device(bank); else { /* perform full erase to unlock device */ status = str9xpec_unlock_device(bank); } } else { for (i = first; i <= last; i++) { if (set) buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1); else buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0); } status = str9xpec_write_options(bank); } if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector) { struct jtag_tap *tap; struct scan_field field; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; /* set flash controller address */ str9xpec_set_instr(tap, ISC_ADDRESS_SHIFT, TAP_IRPAUSE); field.num_bits = 8; field.out_value = §or; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); return ERROR_OK; } static int str9xpec_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; uint32_t dwords_remaining = (count / 8); uint32_t bytes_remaining = (count & 0x00000007); uint32_t bytes_written = 0; uint8_t status; uint32_t check_address = offset; struct jtag_tap *tap; struct scan_field field; uint8_t *scanbuf; int i; int first_sector = 0; int last_sector = 0; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ERROR_FLASH_OPERATION_FAILED; if (offset & 0x7) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } for (i = 0; i < bank->num_sectors; i++) { uint32_t sec_start = bank->sectors[i].offset; uint32_t sec_end = sec_start + bank->sectors[i].size; /* check if destination falls within the current sector */ if ((check_address >= sec_start) && (check_address < sec_end)) { /* check if destination ends in the current sector */ if (offset + count < sec_end) check_address = offset + count; else check_address = sec_end; } if ((offset >= sec_start) && (offset < sec_end)) first_sector = i; if ((offset + count >= sec_start) && (offset + count < sec_end)) last_sector = i; } if (check_address != offset + count) return ERROR_FLASH_DST_OUT_OF_BANK; LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector); scanbuf = calloc(DIV_ROUND_UP(64, 8), 1); LOG_DEBUG("ISC_PROGRAM"); for (i = first_sector; i <= last_sector; i++) { str9xpec_set_address(bank, str9xpec_info->sector_bits[i]); dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8); while (dwords_remaining > 0) { str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); field.num_bits = 64; field.out_value = (buffer + bytes_written); field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { field.num_bits = 8; field.out_value = NULL; field.in_value = scanbuf; jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); } while (!(status & ISC_STATUS_BUSY)); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL) return ERROR_FLASH_OPERATION_FAILED; */ dwords_remaining--; bytes_written += 8; } } if (bytes_remaining) { uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* copy the last remaining bytes into the write buffer */ memcpy(last_dword, buffer+bytes_written, bytes_remaining); str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); field.num_bits = 64; field.out_value = last_dword; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { field.num_bits = 8; field.out_value = NULL; field.in_value = scanbuf; jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); } while (!(status & ISC_STATUS_BUSY)); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL) return ERROR_FLASH_OPERATION_FAILED; */ } free(scanbuf); str9xpec_isc_disable(bank); return ERROR_OK; } static int str9xpec_probe(struct flash_bank *bank) { return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_part_id_command) { struct scan_field field; uint8_t *buffer = NULL; struct jtag_tap *tap; uint32_t idcode; struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; buffer = calloc(DIV_ROUND_UP(32, 8), 1); str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE); field.num_bits = 32; field.out_value = NULL; field.in_value = buffer; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); idcode = buf_get_u32(buffer, 0, 32); command_print(CMD_CTX, "str9xpec part id: 0x%8.8" PRIx32 "", idcode); free(buffer); return ERROR_OK; } static int str9xpec_erase_check(struct flash_bank *bank) { return str9xpec_blank_check(bank, 0, bank->num_sectors - 1); } COMMAND_HANDLER(str9xpec_handle_flash_options_read_command) { uint8_t status; struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; status = str9xpec_read_config(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; /* boot bank */ if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1)) command_print(CMD_CTX, "CS Map: bank1"); else command_print(CMD_CTX, "CS Map: bank0"); /* OTP lock */ if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1)) command_print(CMD_CTX, "OTP Lock: OTP Locked"); else command_print(CMD_CTX, "OTP Lock: OTP Unlocked"); /* LVD Threshold */ if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1)) command_print(CMD_CTX, "LVD Threshold: 2.7v"); else command_print(CMD_CTX, "LVD Threshold: 2.4v"); /* LVD reset warning */ if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1)) command_print(CMD_CTX, "LVD Reset Warning: VDD or VDDQ Inputs"); else command_print(CMD_CTX, "LVD Reset Warning: VDD Input Only"); /* LVD reset select */ if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1)) command_print(CMD_CTX, "LVD Reset Selection: VDD or VDDQ Inputs"); else command_print(CMD_CTX, "LVD Reset Selection: VDD Input Only"); return ERROR_OK; } static int str9xpec_write_options(struct flash_bank *bank) { struct scan_field field; uint8_t status; struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = NULL; str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; /* erase config options first */ status = str9xpec_erase_area(bank, 0xFE, 0xFE); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return status; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ISC_STATUS_ERROR; /* according to data 64th bit has to be set */ buf_set_u32(str9xpec_info->options, 63, 1, 1); /* set option byte address */ str9xpec_set_address(bank, 0x50); /* execute ISC_PROGRAM command */ str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); field.num_bits = 64; field.out_value = str9xpec_info->options; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { field.num_bits = 8; field.out_value = NULL; field.in_value = &status; jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); str9xpec_isc_disable(bank); return status; } COMMAND_HANDLER(str9xpec_handle_flash_options_write_command) { uint8_t status; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; status = str9xpec_write_options(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; command_print(CMD_CTX, "str9xpec write options complete.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command) { struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; if (strcmp(CMD_ARGV[1], "bank1") == 0) buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1); else buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command) { struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; if (strcmp(CMD_ARGV[1], "2.7v") == 0) buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1); else buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command) { struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1); else buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command) { struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1); else buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_lock_command) { uint8_t status; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; status = str9xpec_lock_device(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_unlock_command) { uint8_t status; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; status = str9xpec_unlock_device(bank); if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; command_print(CMD_CTX, "str9xpec unlocked.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command) { struct jtag_tap *tap0; struct jtag_tap *tap1; struct jtag_tap *tap2; struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; /* remove arm core from chain - enter turbo mode */ tap0 = str9xpec_info->tap; if (tap0 == NULL) { /* things are *WRONG* */ command_print(CMD_CTX, "**STR9FLASH** (tap0) invalid chain?"); return ERROR_FAIL; } tap1 = tap0->next_tap; if (tap1 == NULL) { /* things are *WRONG* */ command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?"); return ERROR_FAIL; } tap2 = tap1->next_tap; if (tap2 == NULL) { /* things are *WRONG* */ command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?"); return ERROR_FAIL; } /* enable turbo mode - TURBO-PROG-ENABLE */ str9xpec_set_instr(tap2, 0xD, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* modify scan chain - str9 core has been removed */ tap1->enabled = 0; return ERROR_OK; } COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command) { struct jtag_tap *tap; struct str9xpec_flash_controller *str9xpec_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (tap == NULL) return ERROR_FAIL; /* exit turbo mode via RESET */ str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE); jtag_add_tlr(); jtag_execute_queue(); /* restore previous scan chain */ if (tap->next_tap) tap->next_tap->enabled = 1; return ERROR_OK; } static const struct command_registration str9xpec_config_command_handlers[] = { { .name = "enable_turbo", .usage = "", .handler = str9xpec_handle_flash_enable_turbo_command, .mode = COMMAND_EXEC, .help = "enable str9xpec turbo mode", }, { .name = "disable_turbo", .usage = "", .handler = str9xpec_handle_flash_disable_turbo_command, .mode = COMMAND_EXEC, .help = "disable str9xpec turbo mode", }, { .name = "options_cmap", .usage = " ", .handler = str9xpec_handle_flash_options_cmap_command, .mode = COMMAND_EXEC, .help = "configure str9xpec boot sector", }, { .name = "options_lvdthd", .usage = " <2.4v | 2.7v>", .handler = str9xpec_handle_flash_options_lvdthd_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd threshold", }, { .name = "options_lvdsel", .usage = " ", .handler = str9xpec_handle_flash_options_lvdsel_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd selection", }, { .name = "options_lvdwarn", .usage = " ", .handler = str9xpec_handle_flash_options_lvdwarn_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd warning", }, { .name = "options_read", .usage = "", .handler = str9xpec_handle_flash_options_read_command, .mode = COMMAND_EXEC, .help = "read str9xpec options", }, { .name = "options_write", .usage = "", .handler = str9xpec_handle_flash_options_write_command, .mode = COMMAND_EXEC, .help = "write str9xpec options", }, { .name = "lock", .usage = "", .handler = str9xpec_handle_flash_lock_command, .mode = COMMAND_EXEC, .help = "lock str9xpec device", }, { .name = "unlock", .usage = "", .handler = str9xpec_handle_flash_unlock_command, .mode = COMMAND_EXEC, .help = "unlock str9xpec device", }, { .name = "part_id", .handler = str9xpec_handle_part_id_command, .mode = COMMAND_EXEC, .help = "print part id of str9xpec flash bank ", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration str9xpec_command_handlers[] = { { .name = "str9xpec", .mode = COMMAND_ANY, .help = "str9xpec flash command group", .usage = "", .chain = str9xpec_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver str9xpec_flash = { .name = "str9xpec", .commands = str9xpec_command_handlers, .flash_bank_command = str9xpec_flash_bank_command, .erase = str9xpec_erase, .protect = str9xpec_protect, .write = str9xpec_write, .read = default_flash_read, .probe = str9xpec_probe, .auto_probe = str9xpec_probe, .erase_check = str9xpec_erase_check, .protect_check = str9xpec_protect_check, }; openocd-0.9.0/src/flash/nor/mini51.c0000644000175000017500000004117012516456302014027 00000000000000/*************************************************************************** * Copyright (C) 2013 Cosmin Gorgovan * * cosmin [at] linux-geek [dot] org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* Flash driver for the Nuvoton NuMicro Mini51 and M051 series microcontrollers Part |APROM Size |Part ID (at 0x5000_0000) ---------------------------------------------- MINI51LAN 4 KB 0x00205100 MINI51ZAN 4 KB 0x00205103 MINI51TAN 4 KB 0x00205104 MINI52LAN 8 KB 0x00205200 MINI52ZAN 8 KB 0x00205203 MINI52TAN 8 KB 0x00205204 MINI54LAN 16 KB 0x00205400 MINI54ZAN 16 KB 0x00205403 MINI54TAN 16 KB 0x00205404 M052LBN 8 KB 0x10005200 M054LBN 16 KB 0x10005400 M058LBN 32 KB 0x10005800 M0516LBN 64 KB 0x10005A00 M052ZBN 8 KB 0x10005203 M054ZBN 16 KB 0x10005403 M058ZBN 32 KB 0x10005803 M0516ZBN 64 KB 0x10005A03 M052LDN 8 KB 0x20005200 M054LDN 16 KB 0x20005400 M058LDN 32 KB 0x20005800 M0516LDN 64 KB 0x20005A00 M052ZDN 8 KB 0x20005203 M054ZDN 16 KB 0x20005403 M058ZDN 32 KB 0x20005803 M0516ZDN 64 KB 0x20005A03 M052LDE 8 KB 0x30005200 M054LDE 16 KB 0x30005400 M058LDE 32 KB 0x30005800 M0516LDE 64 KB 0x30005A00 M052ZDE 8 KB 0x30005203 M054ZDE 16 KB 0x30005403 M058ZDE 32 KB 0x30005803 M0516ZDE 64 KB 0x30005A03 Datasheet & TRM --------------- The ISP flash programming procedure is described on pages 130 and 131 of the (not very verbose) TRM. http://www.keil.com/dd/docs/datashts/nuvoton/mini51/da00-mini51_52_54c1.pdf M051 ISP datasheet pages 190-206: http://www.nuvoton.com/hq/resource-download.jsp?tp_GUID=DA05-M052-54-58-516 This driver ----------- * chip_erase, erase, read and write operations have been implemented; * All operations support APROM, LDROM, FLASH DATA and CONFIG; Flash access limitations ------------------------ For implementing the read operation, please note that the APROM isn't memory mapped when booted from LDROM. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #define PART_ID_REG 0x50000000 #define IPRSTC1 0x50000008 #define REGLOCKADDR 0x50000100 #define ISPCON 0x5000C000 #define ISPADR 0x5000C004 #define ISPDAT 0x5000C008 #define ISPCMD 0x5000C00C #define ISPTRG 0x5000C010 /* Undocumented isp register */ #define ISPUNKNOWN 0x5000C01C #define IPRSTC_CPU_RST 0x02 #define ISPCON_ISPFF 0x40 #define ISPCON_LDUEN 0x20 #define ISPCON_CFGUEN 0x10 #define ISPCON_APUEN 0x08 #define ISPCON_BS_LDROM 0x02 #define ISPCON_ISPEN 0x01 #define ISPCMD_READ 0x00 #define ISPCMD_PROGRAM 0x21 #define ISPCMD_ERASE 0x22 #define ISPCMD_CHIP_ERASE 0x26 #define ISPTRG_ISPGO 0x01 #define MINI51_APROM_BASE 0x00000000 #define MINI51_DATA_BASE 0x0001F000 #define MINI51_LDROM_BASE 0x00100000 #define MINI51_CONFIG_BASE 0x00300000 #define MINI51_KB 1024 #define MINI51_PAGE_SIZE 512 #define MINI51_TIMEOUT 1000 #define ENSURE_OK(status) if (status != ERROR_OK) return status #define MINI51_MAX_FLASH_BANKS 4 struct mini51_flash_bank_type { uint32_t base; uint32_t size; }; struct mini51_cpu_type { char *name; uint32_t ppid; unsigned n_banks; struct mini51_flash_bank_type bank[MINI51_MAX_FLASH_BANKS]; }; #define MINI51_BANKS_MINI51(aprom_size) \ .n_banks = 3, \ { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_LDROM_BASE, 2*1024}, {MINI51_CONFIG_BASE, 512} } #define MINI51_BANKS_M051(aprom_size) \ .n_banks = 4, \ { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_DATA_BASE, 4*1024}, {MINI51_LDROM_BASE, 4*1024}, \ {MINI51_CONFIG_BASE, 1024} } static const struct mini51_cpu_type mini51_cpu[] = { { "MINI51LAN", 0x00205100, MINI51_BANKS_MINI51(4*1024) }, { "MINI51ZAN", 0x00205103, MINI51_BANKS_MINI51(4*1024) }, { "MINI51TAN", 0x00205104, MINI51_BANKS_MINI51(4*1024) }, { "MINI52LAN", 0x00205200, MINI51_BANKS_MINI51(8*1024) }, { "MINI52ZAN", 0x00205203, MINI51_BANKS_MINI51(8*1024) }, { "MINI52TAN", 0x00205204, MINI51_BANKS_MINI51(8*1024) }, { "MINI54LAN", 0x00205400, MINI51_BANKS_MINI51(16*1024) }, { "MINI54ZAN", 0x00205403, MINI51_BANKS_MINI51(16*1024) }, { "MINI54TAN", 0x00205404, MINI51_BANKS_MINI51(16*1024) }, { "M052LBN", 0x10005200, MINI51_BANKS_M051(8*1024) }, { "M054LBN", 0x10005400, MINI51_BANKS_M051(16*1024) }, { "M058LBN", 0x10005800, MINI51_BANKS_M051(32*1024) }, { "M0516LBN", 0x10005A00, MINI51_BANKS_M051(64*1024) }, { "M052ZBN", 0x10005203, MINI51_BANKS_M051(8*1024) }, { "M054ZBN", 0x10005403, MINI51_BANKS_M051(16*1024) }, { "M058ZBN", 0x10005803, MINI51_BANKS_M051(32*1024) }, { "M0516ZBN", 0x10005A03, MINI51_BANKS_M051(64*1024) }, { "M052LDN", 0x20005200, MINI51_BANKS_M051(8*1024) }, { "M054LDN", 0x20005400, MINI51_BANKS_M051(16*1024) }, { "M058LDN", 0x20005800, MINI51_BANKS_M051(32*1024) }, { "M0516LDN", 0x20005A00, MINI51_BANKS_M051(64*1024) }, { "M052ZDN", 0x20005203, MINI51_BANKS_M051(8*1024) }, { "M054ZDN", 0x20005403, MINI51_BANKS_M051(16*1024) }, { "M058ZDN", 0x20005803, MINI51_BANKS_M051(32*1024) }, { "M0516ZDN", 0x20005A03, MINI51_BANKS_M051(64*1024) }, { "M052LDE", 0x30005200, MINI51_BANKS_M051(8*1024) }, { "M054LDE", 0x30005400, MINI51_BANKS_M051(16*1024) }, { "M058LDE", 0x30005800, MINI51_BANKS_M051(32*1024) }, { "M0516LDE", 0x30005A00, MINI51_BANKS_M051(64*1024) }, { "M052ZDE", 0x30005203, MINI51_BANKS_M051(8*1024) }, { "M054ZDE", 0x30005403, MINI51_BANKS_M051(16*1024) }, { "M058ZDE", 0x30005803, MINI51_BANKS_M051(32*1024) }, { "M0516ZDE", 0x30005A03, MINI51_BANKS_M051(64*1024) }, }; struct mini51_flash_bank { bool probed; const struct mini51_cpu_type *cpu; }; /* Private methods */ static int mini51_unlock_reg(struct target *target) { int status; status = target_write_u32(target, REGLOCKADDR, 0x59); if (status != ERROR_OK) return status; status = target_write_u32(target, REGLOCKADDR, 0x16); if (status != ERROR_OK) return status; status = target_write_u32(target, REGLOCKADDR, 0x88); if (status != ERROR_OK) return status; return ERROR_OK; } static int mini51_get_part_id(struct target *target, uint32_t *part_id) { int retu = target_read_u32(target, PART_ID_REG, part_id); LOG_INFO("device id = 0x%08" PRIx32 "", *part_id); return retu; } static int mini51_get_cpu_type(struct target *target, const struct mini51_cpu_type** cpu) { uint32_t part_id; int status; status = mini51_get_part_id(target, &part_id); ENSURE_OK(status); for (size_t i = 0; i < sizeof(mini51_cpu)/sizeof(mini51_cpu[0]); i++) { if (part_id == mini51_cpu[i].ppid) { *cpu = &mini51_cpu[i]; LOG_INFO("device name = %s", (*cpu)->name); return ERROR_OK; } } return ERROR_FLASH_OPERATION_FAILED; } static int mini51_get_flash_size(struct flash_bank *bank, const struct mini51_cpu_type *cpu, uint32_t *flash_size) { for (size_t i = 0; i < cpu->n_banks; i++) { if (bank->base == cpu->bank[i].base) { *flash_size = cpu->bank[i].size; LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size); return ERROR_OK; } } return ERROR_FLASH_OPERATION_FAILED; } static int mini51_isp_execute(struct target *target) { int status; uint32_t ispcon; int timeout; uint32_t isptrg; /* start ISP operation */ status = target_write_u32(target, ISPTRG, ISPTRG_ISPGO); ENSURE_OK(status); /* Wait for for command to finish executing */ timeout = MINI51_TIMEOUT; do { target_read_u32(target, ISPTRG, &isptrg); timeout--; } while ((isptrg & ISPTRG_ISPGO) && (timeout > 0)); if (timeout == 0) { LOG_WARNING("Mini51 flash driver: Timeout executing flash command\n"); return ERROR_FLASH_OPERATION_FAILED; } /* Check for errors */ status = target_read_u32(target, ISPCON, &ispcon); ENSURE_OK(status); if (ispcon & ISPCON_ISPFF) { LOG_WARNING("Mini51 flash driver: operation failed\n"); return ERROR_FLASH_OPERATION_FAILED; } return status; } static int mini51_isp_execute_cmd(struct target *target, uint32_t cmd, uint32_t address, uint32_t data) { int status; status = target_write_u32(target, ISPDAT, data); ENSURE_OK(status); status = target_write_u32(target, ISPADR, address); ENSURE_OK(status); status = target_write_u32(target, ISPCMD, cmd); ENSURE_OK(status); status = mini51_isp_execute(target); return status; } static int mini51_isp_execute_cmd_read(struct target *target, uint32_t cmd, uint32_t address, uint32_t *data) { int status; status = target_write_u32(target, ISPADR, address); ENSURE_OK(status); status = target_write_u32(target, ISPCMD, cmd); ENSURE_OK(status); status = mini51_isp_execute(target); ENSURE_OK(status); status = target_read_u32(target, ISPDAT, data); ENSURE_OK(status); return status; } static int mini51_isp_enable(struct target *target) { int status; uint32_t ispcon; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } status = mini51_unlock_reg(target); ENSURE_OK(status); status = target_read_u32(target, ISPCON, &ispcon); ENSURE_OK(status); ispcon |= ISPCON_ISPEN | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN; status = target_write_u32(target, ISPCON, ispcon); return status; } /* Public (API) methods */ FLASH_BANK_COMMAND_HANDLER(mini51_flash_bank_command) { struct mini51_flash_bank *mini51_info; mini51_info = malloc(sizeof(struct mini51_flash_bank)); mini51_info->probed = false; bank->driver_priv = mini51_info; return ERROR_OK; } static int mini51_protect_check(struct flash_bank *bank) { LOG_WARNING("Mini51 flash driver: protect_check not implemented yet\n"); return ERROR_FLASH_OPERATION_FAILED; } static int mini51_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { int status; uint32_t ispdat; struct target *target = bank->target; if ((offset & 0x3) || (count & 0x3)) { LOG_WARNING("Mini51 flash driver: unaligned access not supported\n"); return ERROR_FLASH_OPERATION_FAILED; } status = mini51_isp_enable(target); ENSURE_OK(status); for (uint32_t i = offset; i < offset + count; i += 4) { status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, bank->base + i, &ispdat); memcpy(buffer, &ispdat, sizeof(ispdat)); ENSURE_OK(status); buffer += sizeof(ispdat); } return ERROR_OK; } static int mini51_erase(struct flash_bank *bank, int first, int last) { int status; struct target *target = bank->target; /* Enable ISP */ status = mini51_isp_enable(target); ENSURE_OK(status); for (int page_start = first; page_start <= last; page_start++) { /* Set up erase command */ uint32_t address = bank->base + page_start*MINI51_PAGE_SIZE; status = mini51_isp_execute_cmd(target, ISPCMD_ERASE, address, 0); ENSURE_OK(status); } return ERROR_OK; } static int mini51_protect(struct flash_bank *bank, int set, int first, int last) { LOG_WARNING("Mini51 flash driver: protect operation not implemented yet\n"); return ERROR_FLASH_OPERATION_FAILED; } static int mini51_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int status; uint32_t ispdat; struct target *target = bank->target; if ((offset & 0x3) || (count & 0x3)) { LOG_WARNING("Mini51 flash driver: unaligned access not supported\n"); return ERROR_FLASH_OPERATION_FAILED; } status = mini51_isp_enable(target); ENSURE_OK(status); for (uint32_t i = offset; i < offset + count; i += 4) { memcpy(&ispdat, buffer, sizeof(ispdat)); status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, bank->base + i, ispdat); ENSURE_OK(status); buffer += sizeof(ispdat); } return ERROR_OK; } static int mini51_probe(struct flash_bank *bank) { uint32_t flash_size; int status; int num_pages; uint32_t offset = 0; const struct mini51_cpu_type *cpu; struct target *target = bank->target; status = mini51_get_cpu_type(target, &cpu); if (status != ERROR_OK) { LOG_WARNING("Mini51 flash driver: Failed to detect a known part\n"); return ERROR_FLASH_OPERATION_FAILED; } status = mini51_get_flash_size(bank, cpu, &flash_size); if (status != ERROR_OK) { LOG_WARNING("Mini51 flash driver: Failed to detect flash size\n"); return ERROR_FLASH_OPERATION_FAILED; } num_pages = flash_size / MINI51_PAGE_SIZE; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); bank->size = flash_size; for (int i = 0; i < num_pages; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = MINI51_PAGE_SIZE; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; offset += MINI51_PAGE_SIZE; } struct mini51_flash_bank *mini51_info = bank->driver_priv; mini51_info->probed = true; mini51_info->cpu = cpu; return ERROR_OK; } static int mini51_auto_probe(struct flash_bank *bank) { struct mini51_flash_bank *mini51_info = bank->driver_priv; if (mini51_info->probed) return ERROR_OK; return mini51_probe(bank); } COMMAND_HANDLER(mini51_handle_read_isp_command) { uint32_t address; uint32_t ispdat; int status; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); struct target *target = get_current_target(CMD_CTX); status = mini51_isp_enable(target); ENSURE_OK(status); status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, address, &ispdat); ENSURE_OK(status); LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat); return ERROR_OK; } COMMAND_HANDLER(mini51_handle_write_isp_command) { uint32_t address; uint32_t ispdat; int status; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat); struct target *target = get_current_target(CMD_CTX); status = mini51_isp_enable(target); ENSURE_OK(status); status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, address, ispdat); ENSURE_OK(status); LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat); return ERROR_OK; } COMMAND_HANDLER(mini51_handle_chip_erase_command) { int status; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; struct target *target = get_current_target(CMD_CTX); status = mini51_isp_enable(target); ENSURE_OK(status); /* Write one to undocumented flash control register */ status = target_write_u32(target, ISPUNKNOWN, 1); ENSURE_OK(status); status = mini51_isp_execute_cmd(target, ISPCMD_CHIP_ERASE, 0, 0); ENSURE_OK(status); return ERROR_OK; } static const struct command_registration mini51_exec_command_handlers[] = { { .name = "read_isp", .handler = mini51_handle_read_isp_command, .usage = "address", .mode = COMMAND_EXEC, .help = "read flash through ISP.", }, { .name = "write_isp", .handler = mini51_handle_write_isp_command, .usage = "address value", .mode = COMMAND_EXEC, .help = "write flash through ISP.", }, { .name = "chip_erase", .handler = mini51_handle_chip_erase_command, .mode = COMMAND_EXEC, .help = "chip erase.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration mini51_command_handlers[] = { { .name = "mini51", .mode = COMMAND_ANY, .help = "mini51 flash command group", .usage = "", .chain = mini51_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver mini51_flash = { .name = "mini51", .commands = mini51_command_handlers, .flash_bank_command = mini51_flash_bank_command, .erase = mini51_erase, .protect = mini51_protect, .write = mini51_write, .read = mini51_read, .probe = mini51_probe, .auto_probe = mini51_auto_probe, .erase_check = default_flash_blank_check, .protect_check = mini51_protect_check, }; openocd-0.9.0/src/flash/nor/mrvlqspi.c0000644000175000017500000006365312516456302014614 00000000000000/*************************************************************************** * Copyright (C) 2014 by Mahavir Jain * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * ***************************************************************************/ /* * This is QSPI flash controller driver for Marvell's Wireless * Microcontroller platform. * * For more information please refer, * https://origin-www.marvell.com/microcontrollers/wi-fi-microcontroller-platform/ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "spi.h" #include #include #include #define QSPI_R_EN (0x0) #define QSPI_W_EN (0x1) #define QSPI_SS_DISABLE (0x0) #define QSPI_SS_ENABLE (0x1) #define WRITE_DISBALE (0x0) #define WRITE_ENABLE (0x1) #define QSPI_TIMEOUT (1000) #define FIFO_FLUSH_TIMEOUT (1000) #define BLOCK_ERASE_TIMEOUT (1000) #define CHIP_ERASE_TIMEOUT (10000) #define SS_EN (1 << 0) #define XFER_RDY (1 << 1) #define RFIFO_EMPTY (1 << 4) #define WFIFO_EMPTY (1 << 6) #define WFIFO_FULL (1 << 7) #define FIFO_FLUSH (1 << 9) #define RW_EN (1 << 13) #define XFER_STOP (1 << 14) #define XFER_START (1 << 15) #define CONF_MASK (0x7) #define CONF_OFFSET (10) #define INS_WRITE_ENABLE 0x06 #define INS_WRITE_DISABLE 0x04 #define INS_READ_STATUS 0x05 #define INS_PAGE_PROGRAM 0x02 #define CNTL 0x0 /* QSPI_BASE + 0x0 */ #define CONF 0x4 #define DOUT 0x8 #define DIN 0xc #define INSTR 0x10 #define ADDR 0x14 #define RDMODE 0x18 #define HDRCNT 0x1c #define DINCNT 0x20 struct mrvlqspi_flash_bank { int probed; uint32_t reg_base; uint32_t bank_num; const struct flash_device *dev; }; static inline uint32_t mrvlqspi_get_reg(struct flash_bank *bank, uint32_t reg) { struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; return reg + mrvlqspi_info->reg_base; } static inline int mrvlqspi_set_din_cnt(struct flash_bank *bank, uint32_t count) { struct target *target = bank->target; return target_write_u32(target, mrvlqspi_get_reg(bank, DINCNT), count); } static inline int mrvlqspi_set_addr(struct flash_bank *bank, uint32_t addr) { struct target *target = bank->target; return target_write_u32(target, mrvlqspi_get_reg(bank, ADDR), addr); } static inline int mrvlqspi_set_instr(struct flash_bank *bank, uint32_t instr) { struct target *target = bank->target; return target_write_u32(target, mrvlqspi_get_reg(bank, INSTR), instr); } static inline int mrvlqspi_set_hdr_cnt(struct flash_bank *bank, uint32_t hdr_cnt) { struct target *target = bank->target; return target_write_u32(target, mrvlqspi_get_reg(bank, HDRCNT), hdr_cnt); } static int mrvlqspi_set_conf(struct flash_bank *bank, uint32_t conf_val) { int retval; uint32_t regval; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; regval &= ~(CONF_MASK << CONF_OFFSET); regval |= (conf_val << CONF_OFFSET); return target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); } static int mrvlqspi_set_ss_state(struct flash_bank *bank, bool state, int timeout) { int retval; uint32_t regval; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; if (state) regval |= SS_EN; else regval &= ~(SS_EN); retval = target_write_u32(target, mrvlqspi_get_reg(bank, CNTL), regval); if (retval != ERROR_OK) return retval; /* wait for xfer_ready to set */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_RDY) == XFER_RDY) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return ERROR_OK; } static int mrvlqspi_start_transfer(struct flash_bank *bank, bool rw_mode) { int retval; uint32_t regval; struct target *target = bank->target; retval = mrvlqspi_set_ss_state(bank, QSPI_SS_ENABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; if (rw_mode) regval |= RW_EN; else regval &= ~(RW_EN); regval |= XFER_START; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int mrvlqspi_stop_transfer(struct flash_bank *bank) { int retval; uint32_t regval; struct target *target = bank->target; int timeout = QSPI_TIMEOUT; /* wait for xfer_ready and wfifo_empty to set */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & (XFER_RDY | WFIFO_EMPTY)) == (XFER_RDY | WFIFO_EMPTY)) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; regval |= XFER_STOP; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); if (retval != ERROR_OK) return retval; /* wait for xfer_start to reset */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_START) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout) { int retval; uint32_t val; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; val |= FIFO_FLUSH; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), val); if (retval != ERROR_OK) return retval; /* wait for fifo_flush to clear */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIX32, val); if ((val & FIFO_FLUSH) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return ERROR_OK; } static int mrvlqspi_read_byte(struct flash_bank *bank, uint8_t *data) { int retval; uint32_t val; struct target *target = bank->target; /* wait for rfifo_empty to reset */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), &val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, val); if ((val & RFIFO_EMPTY) == 0) break; usleep(10); } retval = target_read_u32(target, mrvlqspi_get_reg(bank, DIN), &val); if (retval != ERROR_OK) return retval; *data = val & 0xFF; return ERROR_OK; } static int mrvlqspi_flash_busy_status(struct flash_bank *bank, int timeout) { uint8_t val; int retval; /* Flush read/write fifo's */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, 0x1); if (retval != ERROR_OK) return retval; /* Read flash status register in continuous manner */ retval = mrvlqspi_set_din_cnt(bank, 0x0); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, INS_READ_STATUS); if (retval != ERROR_OK) return retval; /* Set data and addr pin length */ retval = mrvlqspi_set_conf(bank, 0x0); if (retval != ERROR_OK) return retval; /* Enable read mode transfer */ retval = mrvlqspi_start_transfer(bank, QSPI_R_EN); if (retval != ERROR_OK) return retval; for (;;) { retval = mrvlqspi_read_byte(bank, &val); if (retval != ERROR_OK) return retval; if (!(val & 0x1)) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return mrvlqspi_stop_transfer(bank); } static int mrvlqspi_set_write_status(struct flash_bank *bank, bool mode) { int retval; uint32_t instr; /* Flush read/write fifo's */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, 0x1); if (retval != ERROR_OK) return retval; if (mode) instr = INS_WRITE_ENABLE; else instr = INS_WRITE_DISABLE; /* Set instruction */ retval = mrvlqspi_set_instr(bank, instr); if (retval != ERROR_OK) return retval; retval = mrvlqspi_start_transfer(bank, QSPI_W_EN); if (retval != ERROR_OK) return retval; retval = mrvlqspi_stop_transfer(bank); if (retval != ERROR_OK) return retval; return retval; } static int mrvlqspi_read_id(struct flash_bank *bank, uint32_t *id) { uint8_t id_buf[3] = {0, 0, 0}; int retval, i; LOG_DEBUG("Getting ID"); /* Flush read/write fifo's */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, 0x1); if (retval != ERROR_OK) return retval; /* Set count for number of bytes to read */ retval = mrvlqspi_set_din_cnt(bank, 0x3); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, SPIFLASH_READ_ID); if (retval != ERROR_OK) return retval; /* Set data and addr pin length */ retval = mrvlqspi_set_conf(bank, 0x0); if (retval != ERROR_OK) return retval; retval = mrvlqspi_start_transfer(bank, QSPI_R_EN); if (retval != ERROR_OK) return retval; for (i = 0; i < 3; i++) { retval = mrvlqspi_read_byte(bank, &id_buf[i]); if (retval != ERROR_OK) return retval; } LOG_DEBUG("ID is 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8, id_buf[0], id_buf[1], id_buf[2]); retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0]; return ERROR_OK; } static int mrvlqspi_block_erase(struct flash_bank *bank, uint32_t offset) { int retval; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; /* Set flash write enable */ retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, (0x1 | (0x3 << 4))); if (retval != ERROR_OK) return retval; /* Set read offset address */ retval = mrvlqspi_set_addr(bank, offset); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, mrvlqspi_info->dev->erase_cmd); if (retval != ERROR_OK) return retval; retval = mrvlqspi_start_transfer(bank, QSPI_W_EN); if (retval != ERROR_OK) return retval; retval = mrvlqspi_stop_transfer(bank); if (retval != ERROR_OK) return retval; return mrvlqspi_flash_busy_status(bank, BLOCK_ERASE_TIMEOUT); } static int mrvlqspi_bulk_erase(struct flash_bank *bank) { int retval; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; /* Set flash write enable */ retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, mrvlqspi_info->dev->chip_erase_cmd); if (retval != ERROR_OK) return retval; retval = mrvlqspi_start_transfer(bank, QSPI_W_EN); if (retval != ERROR_OK) return retval; retval = mrvlqspi_stop_transfer(bank); if (retval != ERROR_OK) return retval; return mrvlqspi_flash_busy_status(bank, CHIP_ERASE_TIMEOUT); } static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; int retval = ERROR_OK; int sector; LOG_DEBUG("erase from sector %d to sector %d", first, last); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Flash sector invalid"); return ERROR_FLASH_SECTOR_INVALID; } if (!(mrvlqspi_info->probed)) { LOG_ERROR("Flash bank not probed"); return ERROR_FLASH_BANK_NOT_PROBED; } for (sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } /* If we're erasing the entire chip and the flash supports * it, use a bulk erase instead of going sector-by-sector. */ if (first == 0 && last == (bank->num_sectors - 1) && mrvlqspi_info->dev->chip_erase_cmd != mrvlqspi_info->dev->erase_cmd) { LOG_DEBUG("Chip supports the bulk erase command."\ " Will use bulk erase instead of sector-by-sector erase."); retval = mrvlqspi_bulk_erase(bank); if (retval == ERROR_OK) { return retval; } else LOG_WARNING("Bulk flash erase failed." " Falling back to sector-by-sector erase."); } for (sector = first; sector <= last; sector++) { retval = mrvlqspi_block_erase(bank, sector * mrvlqspi_info->dev->sectorsize); if (retval != ERROR_OK) return retval; } return retval; } static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; int retval = ERROR_OK; uint32_t page_size, fifo_size; struct working_area *fifo; struct reg_param reg_params[6]; struct armv7m_algorithm armv7m_info; struct working_area *write_algorithm; int sector; LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > mrvlqspi_info->dev->size_in_bytes) { LOG_WARNING("Writes past end of flash. Extra data discarded."); count = mrvlqspi_info->dev->size_in_bytes - offset; } /* Check sector protection */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } page_size = mrvlqspi_info->dev->pagesize; /* See contrib/loaders/flash/mrvlqspi.S for src */ static const uint8_t mrvlqspi_flash_write_code[] = { 0x4f, 0xf0, 0x00, 0x0a, 0xa2, 0x44, 0x92, 0x45, 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6b, 0xf8, 0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x06, 0x08, 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x6b, 0xf8, 0x00, 0xf0, 0x7d, 0xf8, 0x5f, 0xf0, 0x31, 0x08, 0xc5, 0xf8, 0x1c, 0x80, 0x90, 0x46, 0xc5, 0xf8, 0x14, 0x80, 0x5f, 0xf0, 0x02, 0x08, 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x5a, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x00, 0xf0, 0x8b, 0x80, 0x47, 0x68, 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b, 0x00, 0xf0, 0x30, 0xf8, 0x8f, 0x42, 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b, 0x00, 0x2b, 0x00, 0xf0, 0x05, 0x80, 0x02, 0xf1, 0x01, 0x02, 0x92, 0x45, 0x7f, 0xf4, 0xe4, 0xaf, 0x00, 0xf0, 0x50, 0xf8, 0xa2, 0x44, 0x00, 0xf0, 0x2d, 0xf8, 0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x00, 0x08, 0xc5, 0xf8, 0x20, 0x80, 0x5f, 0xf0, 0x05, 0x08, 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x29, 0xf8, 0x00, 0xf0, 0x13, 0xf8, 0x09, 0xf0, 0x01, 0x09, 0xb9, 0xf1, 0x00, 0x0f, 0xf8, 0xd1, 0x00, 0xf0, 0x34, 0xf8, 0x00, 0x2b, 0xa4, 0xd1, 0x00, 0xf0, 0x53, 0xb8, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x08, 0x68, 0xfa, 0xd4, 0xc5, 0xf8, 0x08, 0x90, 0x70, 0x47, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0xc8, 0x68, 0xfa, 0xd4, 0xd5, 0xf8, 0x0c, 0x90, 0x70, 0x47, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4, 0x00, 0x78, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea, 0x88, 0x58, 0xfa, 0xd4, 0x70, 0x47, 0xd5, 0xf8, 0x00, 0x80, 0x48, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x69, 0xf3, 0x4d, 0x38, 0x48, 0xf4, 0x00, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0x70, 0x47, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x48, 0x68, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4, 0x80, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea, 0x08, 0x48, 0xfa, 0xd4, 0xd5, 0xf8, 0x00, 0x80, 0x28, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0x70, 0x47, 0x00, 0x20, 0x50, 0x60, 0x30, 0x46, 0x00, 0xbe }; if (target_alloc_working_area(target, sizeof(mrvlqspi_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_ERROR("Insufficient working area. You must configure"\ " a working area > %zdB in order to write to SPIFI flash.", sizeof(mrvlqspi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; retval = target_write_buffer(target, write_algorithm->address, sizeof(mrvlqspi_flash_write_code), mrvlqspi_flash_write_code); if (retval != ERROR_OK) { target_free_working_area(target, write_algorithm); return retval; } /* FIFO allocation */ fifo_size = target_get_working_area_avail(target); if (fifo_size == 0) { /* if we already allocated the writing code but failed to get fifo * space, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_ERROR("Insufficient working area. Please allocate at least"\ " %zdB of working area to enable flash writes.", sizeof(mrvlqspi_flash_write_code) + 1 ); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } else if (fifo_size < page_size) LOG_WARNING("Working area size is limited; flash writes may be"\ " slow. Increase working area size to at least %zdB"\ " to reduce write times.", (size_t)(sizeof(mrvlqspi_flash_write_code) + page_size) ); if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* page size */ init_reg_param(®_params[5], "r5", 32, PARAM_OUT); /* qspi base address */ buf_set_u32(reg_params[0].value, 0, 32, fifo->address); buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size); buf_set_u32(reg_params[2].value, 0, 32, offset); buf_set_u32(reg_params[3].value, 0, 32, count); buf_set_u32(reg_params[4].value, 0, 32, page_size); buf_set_u32(reg_params[5].value, 0, 32, (uint32_t) mrvlqspi_info->reg_base); retval = target_run_flash_async_algorithm(target, buffer, count, 1, 0, NULL, 6, reg_params, fifo->address, fifo->size, write_algorithm->address, 0, &armv7m_info ); if (retval != ERROR_OK) LOG_ERROR("Error executing flash write algorithm"); target_free_working_area(target, fifo); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); destroy_reg_param(®_params[5]); return retval; } int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; int retval; uint32_t i; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!(mrvlqspi_info->probed)) { LOG_ERROR("Flash bank not probed"); return ERROR_FLASH_BANK_NOT_PROBED; } /* Flush read/write fifo's */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, (0x1 | (0x3 << 4))); if (retval != ERROR_OK) return retval; /* Set count for number of bytes to read */ retval = mrvlqspi_set_din_cnt(bank, count); if (retval != ERROR_OK) return retval; /* Set read address */ retval = mrvlqspi_set_addr(bank, offset); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, SPIFLASH_READ); if (retval != ERROR_OK) return retval; /* Set data and addr pin length */ retval = mrvlqspi_set_conf(bank, 0x0); if (retval != ERROR_OK) return retval; retval = mrvlqspi_start_transfer(bank, QSPI_R_EN); if (retval != ERROR_OK) return retval; for (i = 0; i < count; i++) { retval = mrvlqspi_read_byte(bank, &buffer[i]); if (retval != ERROR_OK) return retval; } retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int mrvlqspi_probe(struct flash_bank *bank) { struct target *target = bank->target; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; uint32_t id = 0; int retval; struct flash_sector *sectors; /* If we've already probed, we should be fine to skip this time. */ if (mrvlqspi_info->probed) return ERROR_OK; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } mrvlqspi_info->probed = 0; mrvlqspi_info->bank_num = bank->bank_number; /* Read flash JEDEC ID */ retval = mrvlqspi_read_id(bank, &id); if (retval != ERROR_OK) return retval; mrvlqspi_info->dev = NULL; for (const struct flash_device *p = flash_devices; p->name ; p++) if (p->device_id == id) { mrvlqspi_info->dev = p; break; } if (!mrvlqspi_info->dev) { LOG_ERROR("Unknown flash device ID 0x%08" PRIx32, id); return ERROR_FAIL; } LOG_INFO("Found flash device \'%s\' ID 0x%08" PRIx32, mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id); /* Set correct size value */ bank->size = mrvlqspi_info->dev->size_in_bytes; /* create and fill sectors array */ bank->num_sectors = mrvlqspi_info->dev->size_in_bytes / mrvlqspi_info->dev->sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); if (sectors == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } for (int sector = 0; sector < bank->num_sectors; sector++) { sectors[sector].offset = sector * mrvlqspi_info->dev->sectorsize; sectors[sector].size = mrvlqspi_info->dev->sectorsize; sectors[sector].is_erased = -1; sectors[sector].is_protected = 0; } bank->sectors = sectors; mrvlqspi_info->probed = 1; return ERROR_OK; } static int mrvlqspi_auto_probe(struct flash_bank *bank) { struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; if (mrvlqspi_info->probed) return ERROR_OK; return mrvlqspi_probe(bank); } static int mrvlqspi_flash_erase_check(struct flash_bank *bank) { /* Not implemented yet */ return ERROR_OK; } static int mrvlqspi_protect_check(struct flash_bank *bank) { /* Not implemented yet */ return ERROR_OK; } int mrvlqspi_get_info(struct flash_bank *bank, char *buf, int buf_size) { struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; if (!(mrvlqspi_info->probed)) { snprintf(buf, buf_size, "\nQSPI flash bank not probed yet\n"); return ERROR_OK; } snprintf(buf, buf_size, "\nQSPI flash information:\n" " Device \'%s\' ID 0x%08" PRIx32 "\n", mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id); return ERROR_OK; } FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command) { struct mrvlqspi_flash_bank *mrvlqspi_info; if (CMD_ARGC < 7) return ERROR_COMMAND_SYNTAX_ERROR; mrvlqspi_info = malloc(sizeof(struct mrvlqspi_flash_bank)); if (mrvlqspi_info == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } /* Get QSPI controller register map base address */ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], mrvlqspi_info->reg_base); bank->driver_priv = mrvlqspi_info; mrvlqspi_info->probed = 0; return ERROR_OK; } struct flash_driver mrvlqspi_flash = { .name = "mrvlqspi", .flash_bank_command = mrvlqspi_flash_bank_command, .erase = mrvlqspi_flash_erase, .protect = NULL, .write = mrvlqspi_flash_write, .read = mrvlqspi_flash_read, .probe = mrvlqspi_probe, .auto_probe = mrvlqspi_auto_probe, .erase_check = mrvlqspi_flash_erase_check, .protect_check = mrvlqspi_protect_check, .info = mrvlqspi_get_info, }; openocd-0.9.0/src/flash/nor/stm32lx.c0000644000175000017500000010723712516456302014250 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Clement Burin des Roziers * * clement.burin-des-roziers@hikob.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /* stm32lx flash register locations */ #define FLASH_ACR 0x00 #define FLASH_PECR 0x04 #define FLASH_PDKEYR 0x08 #define FLASH_PEKEYR 0x0C #define FLASH_PRGKEYR 0x10 #define FLASH_OPTKEYR 0x14 #define FLASH_SR 0x18 #define FLASH_OBR 0x1C #define FLASH_WRPR 0x20 /* FLASH_ACR bites */ #define FLASH_ACR__LATENCY (1<<0) #define FLASH_ACR__PRFTEN (1<<1) #define FLASH_ACR__ACC64 (1<<2) #define FLASH_ACR__SLEEP_PD (1<<3) #define FLASH_ACR__RUN_PD (1<<4) /* FLASH_PECR bits */ #define FLASH_PECR__PELOCK (1<<0) #define FLASH_PECR__PRGLOCK (1<<1) #define FLASH_PECR__OPTLOCK (1<<2) #define FLASH_PECR__PROG (1<<3) #define FLASH_PECR__DATA (1<<4) #define FLASH_PECR__FTDW (1<<8) #define FLASH_PECR__ERASE (1<<9) #define FLASH_PECR__FPRG (1<<10) #define FLASH_PECR__EOPIE (1<<16) #define FLASH_PECR__ERRIE (1<<17) #define FLASH_PECR__OBL_LAUNCH (1<<18) /* FLASH_SR bits */ #define FLASH_SR__BSY (1<<0) #define FLASH_SR__EOP (1<<1) #define FLASH_SR__ENDHV (1<<2) #define FLASH_SR__READY (1<<3) #define FLASH_SR__WRPERR (1<<8) #define FLASH_SR__PGAERR (1<<9) #define FLASH_SR__SIZERR (1<<10) #define FLASH_SR__OPTVERR (1<<11) /* Unlock keys */ #define PEKEY1 0x89ABCDEF #define PEKEY2 0x02030405 #define PRGKEY1 0x8C9DAEBF #define PRGKEY2 0x13141516 #define OPTKEY1 0xFBEAD9C8 #define OPTKEY2 0x24252627 /* other registers */ #define DBGMCU_IDCODE 0xE0042000 #define DBGMCU_IDCODE_L0 0x40015800 /* Constants */ #define FLASH_SECTOR_SIZE 4096 #define FLASH_BANK0_ADDRESS 0x08000000 /* option bytes */ #define OPTION_BYTES_ADDRESS 0x1FF80000 #define OPTION_BYTE_0_PR1 0xFFFF0000 #define OPTION_BYTE_0_PR0 0xFF5500AA static int stm32lx_unlock_program_memory(struct flash_bank *bank); static int stm32lx_lock_program_memory(struct flash_bank *bank); static int stm32lx_enable_write_half_page(struct flash_bank *bank); static int stm32lx_erase_sector(struct flash_bank *bank, int sector); static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank); static int stm32lx_mass_erase(struct flash_bank *bank); static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout); struct stm32lx_rev { uint16_t rev; const char *str; }; struct stm32lx_part_info { uint16_t id; const char *device_str; const struct stm32lx_rev *revs; size_t num_revs; unsigned int page_size; unsigned int pages_per_sector; uint16_t max_flash_size_kb; uint16_t first_bank_size_kb; /* used when has_dual_banks is true */ bool has_dual_banks; uint32_t flash_base; /* Flash controller registers location */ uint32_t fsize_base; /* Location of FSIZE register */ }; struct stm32lx_flash_bank { int probed; uint32_t idcode; uint32_t user_bank_size; uint32_t flash_base; const struct stm32lx_part_info *part_info; }; static const struct stm32lx_rev stm32_416_revs[] = { { 0x1000, "A" }, { 0x1008, "Y" }, { 0x1038, "W" }, { 0x1078, "V" }, }; static const struct stm32lx_rev stm32_417_revs[] = { { 0x1000, "A" }, { 0x1008, "Z" }, }; static const struct stm32lx_rev stm32_427_revs[] = { { 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" }, }; static const struct stm32lx_rev stm32_429_revs[] = { { 0x1000, "A" }, { 0x1018, "Z" }, }; static const struct stm32lx_rev stm32_436_revs[] = { { 0x1000, "A" }, { 0x1008, "Z" }, { 0x1018, "Y" }, }; static const struct stm32lx_rev stm32_437_revs[] = { { 0x1000, "A" }, }; static const struct stm32lx_part_info stm32lx_parts[] = { { .id = 0x416, .revs = stm32_416_revs, .num_revs = ARRAY_SIZE(stm32_416_revs), .device_str = "STM32L1xx (Cat.1 - Low/Medium Density)", .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 128, .has_dual_banks = false, .flash_base = 0x40023C00, .fsize_base = 0x1FF8004C, }, { .id = 0x417, .revs = stm32_417_revs, .num_revs = ARRAY_SIZE(stm32_417_revs), .device_str = "STM32L0xx", .page_size = 128, .pages_per_sector = 32, .max_flash_size_kb = 64, .has_dual_banks = false, .flash_base = 0x40022000, .fsize_base = 0x1FF8007C, }, { .id = 0x427, .revs = stm32_427_revs, .num_revs = ARRAY_SIZE(stm32_427_revs), .device_str = "STM32L1xx (Cat.3 - Medium+ Density)", .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 256, .first_bank_size_kb = 192, .has_dual_banks = true, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, }, { .id = 0x429, .revs = stm32_429_revs, .num_revs = ARRAY_SIZE(stm32_429_revs), .device_str = "STM32L1xx (Cat.2)", .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 128, .has_dual_banks = false, .flash_base = 0x40023C00, .fsize_base = 0x1FF8004C, }, { .id = 0x436, .revs = stm32_436_revs, .num_revs = ARRAY_SIZE(stm32_436_revs), .device_str = "STM32L1xx (Cat.4/Cat.3 - Medium+/High Density)", .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 384, .first_bank_size_kb = 192, .has_dual_banks = true, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, }, { .id = 0x437, .revs = stm32_437_revs, .num_revs = ARRAY_SIZE(stm32_437_revs), .device_str = "STM32L1xx (Cat.5/Cat.6)", .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 512, .first_bank_size_kb = 256, .has_dual_banks = true, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, }, }; /* flash bank stm32lx 0 0 */ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command) { struct stm32lx_flash_bank *stm32lx_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; /* Create the bank structure */ stm32lx_info = calloc(1, sizeof(*stm32lx_info)); /* Check allocation */ if (stm32lx_info == NULL) { LOG_ERROR("failed to allocate bank structure"); return ERROR_FAIL; } bank->driver_priv = stm32lx_info; stm32lx_info->probed = 0; stm32lx_info->user_bank_size = bank->size; /* the stm32l erased value is 0x00 */ bank->default_padded_value = 0x00; return ERROR_OK; } COMMAND_HANDLER(stm32lx_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = stm32lx_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "stm32lx mass erase complete"); } else { command_print(CMD_CTX, "stm32lx mass erase failed"); } return retval; } static int stm32lx_protect_check(struct flash_bank *bank) { int retval; struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; uint32_t wrpr; /* * Read the WRPR word, and check each bit (corresponding to each * flash sector */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_WRPR, &wrpr); if (retval != ERROR_OK) return retval; for (int i = 0; i < bank->num_sectors; i++) { if (wrpr & (1 << i)) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } return ERROR_OK; } static int stm32lx_erase(struct flash_bank *bank, int first, int last) { int retval; /* * It could be possible to do a mass erase if all sectors must be * erased, but it is not implemented yet. */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* * Loop over the selected sectors and erase them */ for (int i = first; i <= last; i++) { retval = stm32lx_erase_sector(bank, i); if (retval != ERROR_OK) return retval; bank->sectors[i].is_erased = 1; } return ERROR_OK; } static int stm32lx_protect(struct flash_bank *bank, int set, int first, int last) { LOG_WARNING("protection of the STM32L flash is not implemented"); return ERROR_OK; } static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* see contib/loaders/flash/stm32lx.S for src */ static const uint8_t stm32lx_flash_write_code[] = { /* write_word: */ 0x00, 0x23, /* movs r3, #0 */ 0x04, 0xe0, /* b test_done */ /* write_word: */ 0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */ 0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */ 0x01, 0x33, /* adds r3, #1 */ /* test_done: */ 0x93, 0x42, /* cmp r3, r2 */ 0xf8, 0xd3, /* bcc write_word */ 0x00, 0xbe, /* bkpt 0 */ }; /* Make sure we're performing a half-page aligned write. */ if (count % hp_nb) { LOG_ERROR("The byte count must be %" PRIu32 "B-aligned but count is %" PRIi32 "B)", hp_nb, count); return ERROR_FAIL; } /* flash write code */ if (target_alloc_working_area(target, sizeof(stm32lx_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; /* Write the flashing code */ retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32lx_flash_write_code), stm32lx_flash_write_code); if (retval != ERROR_OK) { target_free_working_area(target, write_algorithm); return retval; } /* Allocate half pages memory */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { if (buffer_size > 1024) buffer_size -= 1024; else buffer_size /= 2; if (buffer_size <= stm32lx_info->part_info->page_size) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* Enable half-page write */ retval = stm32lx_enable_write_half_page(bank); if (retval != ERROR_OK) { target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); return retval; } struct armv7m_common *armv7m = target_to_armv7m(target); if (armv7m == NULL) { /* something is very wrong if armv7m is NULL */ LOG_ERROR("unable to get armv7m target"); return retval; } /* save any DEMCR flags and configure target to catch any Hard Faults */ uint32_t demcr_save = armv7m->demcr; armv7m->demcr = VC_HARDERR; /* Loop while there are bytes to write */ while (count > 0) { uint32_t this_count; this_count = (count > buffer_size) ? buffer_size : count; /* Write the next half pages */ retval = target_write_buffer(target, source->address, this_count, buffer); if (retval != ERROR_OK) break; /* 4: Store useful information in the registers */ /* the destination address of the copy (R0) */ buf_set_u32(reg_params[0].value, 0, 32, address); /* The source address of the copy (R1) */ buf_set_u32(reg_params[1].value, 0, 32, source->address); /* The length of the copy (R2) */ buf_set_u32(reg_params[2].value, 0, 32, this_count / 4); /* 5: Execute the bunch of code */ retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params) / sizeof(*reg_params), reg_params, write_algorithm->address, 0, 10000, &armv7m_info); if (retval != ERROR_OK) break; /* check for Hard Fault */ if (armv7m->exception_number == 3) break; /* 6: Wait while busy */ retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) break; buffer += this_count; address += this_count; count -= this_count; } /* restore previous flags */ armv7m->demcr = demcr_save; if (armv7m->exception_number == 3) { /* the stm32l15x devices seem to have an issue when blank. * if a ram loader is executed on a blank device it will * Hard Fault, this issue does not happen for a already programmed device. * A related issue is described in the stm32l151xx errata (Doc ID 17721 Rev 6 - 2.1.3). * The workaround of handling the Hard Fault exception does work, but makes the * loader more complicated, as a compromise we manually write the pages, programming time * is reduced by 50% using this slower method. */ LOG_WARNING("couldn't use loader, falling back to page memory writes"); while (count > 0) { uint32_t this_count; this_count = (count > hp_nb) ? hp_nb : count; /* Write the next half pages */ retval = target_write_buffer(target, address, this_count, buffer); if (retval != ERROR_OK) break; /* Wait while busy */ retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) break; buffer += this_count; address += this_count; count -= this_count; } } if (retval == ERROR_OK) retval = stm32lx_lock_program_memory(bank); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); return retval; } static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; uint32_t halfpages_number; uint32_t bytes_remaining = 0; uint32_t address = bank->base + offset; uint32_t bytes_written = 0; int retval, retval2; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x3) { LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) return retval; /* first we need to write any unaligned head bytes upto * the next 128 byte page */ if (offset % hp_nb) bytes_remaining = MIN(count, hp_nb - (offset % hp_nb)); while (bytes_remaining > 0) { uint8_t value[4] = {0xff, 0xff, 0xff, 0xff}; /* copy remaining bytes into the write buffer */ uint32_t bytes_to_write = MIN(4, bytes_remaining); memcpy(value, buffer + bytes_written, bytes_to_write); retval = target_write_buffer(target, address, 4, value); if (retval != ERROR_OK) goto reset_pg_and_lock; bytes_written += bytes_to_write; bytes_remaining -= bytes_to_write; address += 4; retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) goto reset_pg_and_lock; } offset += bytes_written; count -= bytes_written; /* this should always pass this check here */ assert((offset % hp_nb) == 0); /* calculate half pages */ halfpages_number = count / hp_nb; if (halfpages_number) { retval = stm32lx_write_half_pages(bank, buffer + bytes_written, offset, hp_nb * halfpages_number); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* attempt slow memory writes */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); halfpages_number = 0; } else { if (retval != ERROR_OK) return ERROR_FAIL; } } /* write any remaining bytes */ uint32_t page_bytes_written = hp_nb * halfpages_number; bytes_written += page_bytes_written; address += page_bytes_written; bytes_remaining = count - page_bytes_written; retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) return retval; while (bytes_remaining > 0) { uint8_t value[4] = {0xff, 0xff, 0xff, 0xff}; /* copy remaining bytes into the write buffer */ uint32_t bytes_to_write = MIN(4, bytes_remaining); memcpy(value, buffer + bytes_written, bytes_to_write); retval = target_write_buffer(target, address, 4, value); if (retval != ERROR_OK) goto reset_pg_and_lock; bytes_written += bytes_to_write; bytes_remaining -= bytes_to_write; address += 4; retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) goto reset_pg_and_lock; } reset_pg_and_lock: retval2 = stm32lx_lock_program_memory(bank); if (retval == ERROR_OK) retval = retval2; return retval; } static int stm32lx_read_id_code(struct target *target, uint32_t *id) { /* read stm32 device id register */ int retval = target_read_u32(target, DBGMCU_IDCODE, id); if (retval != ERROR_OK) return retval; /* STM32L0 parts will have 0 there, try reading the L0's location for * DBG_IDCODE in case this is an L0 part. */ if (*id == 0) retval = target_read_u32(target, DBGMCU_IDCODE_L0, id); return retval; } static int stm32lx_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int i; uint16_t flash_size_in_kb; uint32_t device_id; uint32_t base_address = FLASH_BANK0_ADDRESS; uint32_t second_bank_base; stm32lx_info->probed = 0; stm32lx_info->part_info = NULL; int retval = stm32lx_read_id_code(bank->target, &device_id); if (retval != ERROR_OK) return retval; stm32lx_info->idcode = device_id; LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id); for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { if ((device_id & 0xfff) == stm32lx_parts[n].id) stm32lx_info->part_info = &stm32lx_parts[n]; } if (!stm32lx_info->part_info) { LOG_WARNING("Cannot identify target as a STM32L family."); return ERROR_FAIL; } stm32lx_info->flash_base = stm32lx_info->part_info->flash_base; /* Get the flash size from target. */ retval = target_read_u16(target, stm32lx_info->part_info->fsize_base, &flash_size_in_kb); /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K * or 256K, respectively. Please see RM0038 r8 or newer and refer to * section 30.1.1. */ if (retval == ERROR_OK && (device_id & 0xfff) == 0x436) { if (flash_size_in_kb == 0) flash_size_in_kb = 384; else if (flash_size_in_kb == 1) flash_size_in_kb = 256; } /* Failed reading flash size or flash size invalid (early silicon), * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash", stm32lx_info->part_info->max_flash_size_kb); flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; } else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) { LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash", flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb, stm32lx_info->part_info->max_flash_size_kb); flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; } if (stm32lx_info->part_info->has_dual_banks) { /* Use the configured base address to determine if this is the first or second flash bank. * Verify that the base address is reasonably correct and determine the flash bank size */ second_bank_base = base_address + stm32lx_info->part_info->first_bank_size_kb * 1024; if (bank->base == second_bank_base || !bank->base) { /* This is the second bank */ base_address = second_bank_base; flash_size_in_kb = flash_size_in_kb - stm32lx_info->part_info->first_bank_size_kb; } else if (bank->base == base_address) { /* This is the first bank */ flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb; } else { LOG_WARNING("STM32L flash bank base address config is incorrect." " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, bank->base, base_address, second_bank_base); return ERROR_FAIL; } LOG_INFO("STM32L flash has dual banks. Bank (%d) size is %dkb, base address is 0x%" PRIx32, bank->bank_number, flash_size_in_kb, base_address); } else { LOG_INFO("STM32L flash size is %dkb, base address is 0x%" PRIx32, flash_size_in_kb, base_address); } /* if the user sets the size manually then ignore the probed value * this allows us to work around devices that have a invalid flash size register value */ if (stm32lx_info->user_bank_size) { flash_size_in_kb = stm32lx_info->user_bank_size / 1024; LOG_INFO("ignoring flash probed value, using configured bank size: %dkbytes", flash_size_in_kb); } /* calculate numbers of sectors (4kB per sector) */ int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE; if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->size = flash_size_in_kb * 1024; bank->base = base_address; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); if (bank->sectors == NULL) { LOG_ERROR("failed to allocate bank sectors"); return ERROR_FAIL; } for (i = 0; i < num_sectors; i++) { bank->sectors[i].offset = i * FLASH_SECTOR_SIZE; bank->sectors[i].size = FLASH_SECTOR_SIZE; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } stm32lx_info->probed = 1; return ERROR_OK; } static int stm32lx_auto_probe(struct flash_bank *bank) { struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; if (stm32lx_info->probed) return ERROR_OK; return stm32lx_probe(bank); } static int stm32lx_erase_check(struct flash_bank *bank) { struct target *target = bank->target; const int buffer_size = 4096; int i; uint32_t nBytes; int retval = ERROR_OK; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } uint8_t *buffer = malloc(buffer_size); if (buffer == NULL) { LOG_ERROR("failed to allocate read buffer"); return ERROR_FAIL; } for (i = 0; i < bank->num_sectors; i++) { uint32_t j; bank->sectors[i].is_erased = 1; /* Loop chunk by chunk over the sector */ for (j = 0; j < bank->sectors[i].size; j += buffer_size) { uint32_t chunk; chunk = buffer_size; if (chunk > (j - bank->sectors[i].size)) chunk = (j - bank->sectors[i].size); retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk / 4, buffer); if (retval != ERROR_OK) break; for (nBytes = 0; nBytes < chunk; nBytes++) { if (buffer[nBytes] != 0x00) { bank->sectors[i].is_erased = 0; break; } } } if (retval != ERROR_OK) break; } free(buffer); return retval; } /* This method must return a string displaying information about the bank */ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) { struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; if (!stm32lx_info->probed) { int retval = stm32lx_probe(bank); if (retval != ERROR_OK) { snprintf(buf, buf_size, "Unable to find bank information."); return retval; } } const struct stm32lx_part_info *info = stm32lx_info->part_info; if (info) { const char *rev_str = NULL; uint16_t rev_id = stm32lx_info->idcode >> 16; for (unsigned int i = 0; i < info->num_revs; i++) if (rev_id == info->revs[i].rev) rev_str = info->revs[i].str; if (rev_str != NULL) { snprintf(buf, buf_size, "%s - Rev: %s", stm32lx_info->part_info->device_str, rev_str); } else { snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", stm32lx_info->part_info->device_str, rev_id); } return ERROR_OK; } else { snprintf(buf, buf_size, "Cannot identify target as a STM32Lx"); return ERROR_FAIL; } } static const struct command_registration stm32lx_exec_command_handlers[] = { { .name = "mass_erase", .handler = stm32lx_handle_mass_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Erase entire flash device. including available EEPROM", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration stm32lx_command_handlers[] = { { .name = "stm32lx", .mode = COMMAND_ANY, .help = "stm32lx flash command group", .usage = "", .chain = stm32lx_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver stm32lx_flash = { .name = "stm32lx", .commands = stm32lx_command_handlers, .flash_bank_command = stm32lx_flash_bank_command, .erase = stm32lx_erase, .protect = stm32lx_protect, .write = stm32lx_write, .read = default_flash_read, .probe = stm32lx_probe, .auto_probe = stm32lx_auto_probe, .erase_check = stm32lx_erase_check, .protect_check = stm32lx_protect_check, .info = stm32lx_get_info, }; /* Static methods implementation */ static int stm32lx_unlock_program_memory(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; uint32_t reg32; /* * Unlocking the program memory is done by unlocking the PECR, * then by writing the 2 PRGKEY to the PRGKEYR register */ /* check flash is not already unlocked */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if ((reg32 & FLASH_PECR__PRGLOCK) == 0) return ERROR_OK; /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */ retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY2); if (retval != ERROR_OK) return retval; /* Make sure it worked */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if (reg32 & FLASH_PECR__PELOCK) { LOG_ERROR("PELOCK is not cleared :("); return ERROR_FLASH_OPERATION_FAILED; } retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PRGKEYR, PRGKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PRGKEYR, PRGKEY2); if (retval != ERROR_OK) return retval; /* Make sure it worked */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if (reg32 & FLASH_PECR__PRGLOCK) { LOG_ERROR("PRGLOCK is not cleared :("); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int stm32lx_enable_write_half_page(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; uint32_t reg32; /** * Unlock the program memory, then set the FPRG bit in the PECR register. */ retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__FPRG; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PROG; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32); return retval; } static int stm32lx_lock_program_memory(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; uint32_t reg32; /* To lock the program memory, simply set the lock bit and lock PECR */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PRGLOCK; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PELOCK; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32lx_erase_sector(struct flash_bank *bank, int sector) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; uint32_t reg32; /* * To erase a sector (i.e. stm32lx_info->part_info.pages_per_sector pages), * first unlock the memory, loop over the pages of this sector * and write 0x0 to its first word. */ retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) return retval; for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector; page++) { reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) return retval; uint32_t addr = bank->base + bank->sectors[sector].offset + (page * stm32lx_info->part_info->page_size); retval = target_write_u32(target, addr, 0x0); if (retval != ERROR_OK) return retval; retval = stm32lx_wait_until_bsy_clear(bank); if (retval != ERROR_OK) return retval; } retval = stm32lx_lock_program_memory(bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static inline int stm32lx_get_flash_status(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; return target_read_u32(target, stm32lx_info->flash_base + FLASH_SR, status); } static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank) { return stm32lx_wait_until_bsy_clear_timeout(bank, 100); } static int stm32lx_unlock_options_bytes(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; uint32_t reg32; /* * Unlocking the options bytes is done by unlocking the PECR, * then by writing the 2 FLASH_PEKEYR to the FLASH_OPTKEYR register */ /* check flash is not already unlocked */ retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if ((reg32 & FLASH_PECR__OPTLOCK) == 0) return ERROR_OK; if ((reg32 & FLASH_PECR__PELOCK) != 0) { retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY2); if (retval != ERROR_OK) return retval; } /* To unlock the PECR write the 2 OPTKEY to the FLASH_OPTKEYR register */ retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_OPTKEYR, OPTKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_OPTKEYR, OPTKEY2); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;;) { retval = stm32lx_get_flash_status(bank, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if ((status & FLASH_SR__BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_SR__WRPERR) { LOG_ERROR("access denied / write protected"); retval = ERROR_FAIL; } if (status & FLASH_SR__PGAERR) { LOG_ERROR("invalid program address"); retval = ERROR_FAIL; } /* Clear but report errors */ if (status & FLASH_SR__OPTVERR) { /* If this operation fails, we ignore it and report the original retval */ target_write_u32(target, stm32lx_info->flash_base + FLASH_SR, status & FLASH_SR__OPTVERR); } return retval; } static int stm32lx_obl_launch(struct flash_bank *bank) { struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int retval; /* This will fail as the target gets immediately rebooted */ target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, FLASH_PECR__OBL_LAUNCH); size_t tries = 10; do { target_halt(target); retval = target_poll(target); } while (--tries > 0 && (retval != ERROR_OK || target->state != TARGET_HALTED)); return tries ? ERROR_OK : ERROR_FAIL; } static int stm32lx_mass_erase(struct flash_bank *bank) { int retval; struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = NULL; uint32_t reg32; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } stm32lx_info = bank->driver_priv; retval = stm32lx_unlock_options_bytes(bank); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ /* set the RDP protection level to 1 */ retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR1); if (retval != ERROR_OK) return retval; retval = stm32lx_obl_launch(bank); if (retval != ERROR_OK) return retval; retval = stm32lx_unlock_options_bytes(bank); if (retval != ERROR_OK) return retval; /* set the RDP protection level to 0 */ retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR0); if (retval != ERROR_OK) return retval; retval = stm32lx_wait_until_bsy_clear_timeout(bank, 30000); if (retval != ERROR_OK) return retval; retval = stm32lx_obl_launch(bank); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32 | FLASH_PECR__OPTLOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } openocd-0.9.0/src/flash/nor/stm32f1x.c0000644000175000017500000012646612516456302014330 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include /* stm32x register locations */ #define FLASH_REG_BASE_B0 0x40022000 #define FLASH_REG_BASE_B1 0x40022040 #define STM32_FLASH_ACR 0x00 #define STM32_FLASH_KEYR 0x04 #define STM32_FLASH_OPTKEYR 0x08 #define STM32_FLASH_SR 0x0C #define STM32_FLASH_CR 0x10 #define STM32_FLASH_AR 0x14 #define STM32_FLASH_OBR 0x1C #define STM32_FLASH_WRPR 0x20 /* TODO: Check if code using these really should be hard coded to bank 0. * There are valid cases, on dual flash devices the protection of the * second bank is done on the bank0 reg's. */ #define STM32_FLASH_ACR_B0 0x40022000 #define STM32_FLASH_KEYR_B0 0x40022004 #define STM32_FLASH_OPTKEYR_B0 0x40022008 #define STM32_FLASH_SR_B0 0x4002200C #define STM32_FLASH_CR_B0 0x40022010 #define STM32_FLASH_AR_B0 0x40022014 #define STM32_FLASH_OBR_B0 0x4002201C #define STM32_FLASH_WRPR_B0 0x40022020 /* option byte location */ #define STM32_OB_RDP 0x1FFFF800 #define STM32_OB_USER 0x1FFFF802 #define STM32_OB_DATA0 0x1FFFF804 #define STM32_OB_DATA1 0x1FFFF806 #define STM32_OB_WRP0 0x1FFFF808 #define STM32_OB_WRP1 0x1FFFF80A #define STM32_OB_WRP2 0x1FFFF80C #define STM32_OB_WRP3 0x1FFFF80E /* FLASH_CR register bits */ #define FLASH_PG (1 << 0) #define FLASH_PER (1 << 1) #define FLASH_MER (1 << 2) #define FLASH_OPTPG (1 << 4) #define FLASH_OPTER (1 << 5) #define FLASH_STRT (1 << 6) #define FLASH_LOCK (1 << 7) #define FLASH_OPTWRE (1 << 9) /* FLASH_SR register bits */ #define FLASH_BSY (1 << 0) #define FLASH_PGERR (1 << 2) #define FLASH_WRPRTERR (1 << 4) #define FLASH_EOP (1 << 5) /* STM32_FLASH_OBR bit definitions (reading) */ #define OPT_ERROR 0 #define OPT_READOUT 1 #define OPT_RDWDGSW 2 #define OPT_RDRSTSTOP 3 #define OPT_RDRSTSTDBY 4 #define OPT_BFB2 5 /* dual flash bank only */ /* register unlock keys */ #define KEY1 0x45670123 #define KEY2 0xCDEF89AB /* timeout values */ #define FLASH_WRITE_TIMEOUT 10 #define FLASH_ERASE_TIMEOUT 100 struct stm32x_options { uint16_t RDP; uint16_t user_options; uint16_t user_data; uint16_t protection[4]; }; struct stm32x_flash_bank { struct stm32x_options option_bytes; int ppage_size; int probed; bool has_dual_banks; /* used to access dual flash bank stm32xl */ uint32_t register_base; uint16_t default_rdp; int user_data_offset; int option_offset; uint32_t user_bank_size; }; static int stm32x_mass_erase(struct flash_bank *bank); static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id); static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); /* flash bank stm32x 0 0 */ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) { struct stm32x_flash_bank *stm32x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); bank->driver_priv = stm32x_info; stm32x_info->probed = 0; stm32x_info->has_dual_banks = false; stm32x_info->register_base = FLASH_REG_BASE_B0; stm32x_info->user_bank_size = bank->size; return ERROR_OK; } static inline int stm32x_get_flash_reg(struct flash_bank *bank, uint32_t reg) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; return reg + stm32x_info->register_base; } static inline int stm32x_get_flash_status(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; return target_read_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), status); } static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;;) { retval = stm32x_get_flash_status(bank, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if ((status & FLASH_BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_WRPRTERR) { LOG_ERROR("stm32x device protected"); retval = ERROR_FAIL; } if (status & FLASH_PGERR) { LOG_ERROR("stm32x device programming failed"); retval = ERROR_FAIL; } /* Clear but report errors */ if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { /* If this operation fails, we ignore it and report the original * retval */ target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_WRPRTERR | FLASH_PGERR); } return retval; } static int stm32x_check_operation_supported(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; /* if we have a dual flash bank device then * we need to perform option byte stuff on bank0 only */ if (stm32x_info->register_base != FLASH_REG_BASE_B0) { LOG_ERROR("Option Byte Operation's must use bank0"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } static int stm32x_read_options(struct flash_bank *bank) { uint32_t optiondata; struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, STM32_FLASH_OBR_B0, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.user_options = (optiondata >> stm32x_info->option_offset >> 2) & 0xffff; stm32x_info->option_bytes.user_data = (optiondata >> stm32x_info->user_data_offset) & 0xffff; stm32x_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5; if (optiondata & (1 << OPT_READOUT)) LOG_INFO("Device Security Bit Set"); /* each bit refers to a 4bank protection */ retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.protection[0] = (uint16_t)optiondata; stm32x_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8); stm32x_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16); stm32x_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24); return ERROR_OK; } static int stm32x_erase_options(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current options */ stm32x_read_options(bank); /* unlock flash registers */ int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2); if (retval != ERROR_OK) return retval; /* erase option bytes */ retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; /* clear readout protection and complementary option bytes * this will also force a device unlock if set */ stm32x_info->option_bytes.RDP = stm32x_info->default_rdp; return ERROR_OK; } static int stm32x_write_options(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* unlock flash registers */ int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2); if (retval != ERROR_OK) return retval; /* program option bytes */ retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTPG | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; uint8_t opt_bytes[16]; target_buffer_set_u16(target, opt_bytes, stm32x_info->option_bytes.RDP); target_buffer_set_u16(target, opt_bytes + 2, stm32x_info->option_bytes.user_options); target_buffer_set_u16(target, opt_bytes + 4, stm32x_info->option_bytes.user_data & 0xff); target_buffer_set_u16(target, opt_bytes + 6, (stm32x_info->option_bytes.user_data >> 8) & 0xff); target_buffer_set_u16(target, opt_bytes + 8, stm32x_info->option_bytes.protection[0]); target_buffer_set_u16(target, opt_bytes + 10, stm32x_info->option_bytes.protection[1]); target_buffer_set_u16(target, opt_bytes + 12, stm32x_info->option_bytes.protection[2]); target_buffer_set_u16(target, opt_bytes + 14, stm32x_info->option_bytes.protection[3]); uint32_t offset = STM32_OB_RDP - bank->base; retval = stm32x_write_block(bank, opt_bytes, offset, sizeof(opt_bytes) / 2); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) LOG_ERROR("working area required to erase options bytes"); return retval; } retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32x_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; uint32_t protection; int i, s; int num_bits; int set; int retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; /* medium density - each bit refers to a 4bank protection * high density - each bit refers to a 2bank protection */ retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &protection); if (retval != ERROR_OK) return retval; /* medium density - each protection bit is for 4 * 1K pages * high density - each protection bit is for 2 * 2K pages */ num_bits = (bank->num_sectors / stm32x_info->ppage_size); if (stm32x_info->ppage_size == 2) { /* high density flash/connectivity line protection */ set = 1; if (protection & (1 << 31)) set = 0; /* bit 31 controls sector 62 - 255 protection for high density * bit 31 controls sector 62 - 127 protection for connectivity line */ for (s = 62; s < bank->num_sectors; s++) bank->sectors[s].is_protected = set; if (bank->num_sectors > 61) num_bits = 31; for (i = 0; i < num_bits; i++) { set = 1; if (protection & (1 << i)) set = 0; for (s = 0; s < stm32x_info->ppage_size; s++) bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set; } } else { /* low/medium density flash protection */ for (i = 0; i < num_bits; i++) { set = 1; if (protection & (1 << i)) set = 0; for (s = 0; s < stm32x_info->ppage_size; s++) bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set; } } return ERROR_OK; } static int stm32x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first == 0) && (last == (bank->num_sectors - 1))) return stm32x_mass_erase(bank); /* unlock flash registers */ int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2); if (retval != ERROR_OK) return retval; for (i = first; i <= last; i++) { retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_AR), bank->base + bank->sectors[i].offset); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; bank->sectors[i].is_erased = 1; } retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; int i, reg, bit; int status; uint32_t protection; stm32x_info = bank->driver_priv; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; if ((first % stm32x_info->ppage_size) != 0) { LOG_WARNING("aligned start protect sector to a %d sector boundary", stm32x_info->ppage_size); first = first - (first % stm32x_info->ppage_size); } if (((last + 1) % stm32x_info->ppage_size) != 0) { LOG_WARNING("aligned end protect sector to a %d sector boundary", stm32x_info->ppage_size); last++; last = last - (last % stm32x_info->ppage_size); last--; } /* medium density - each bit refers to a 4bank protection * high density - each bit refers to a 2bank protection */ retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &protection); if (retval != ERROR_OK) return retval; prot_reg[0] = (uint16_t)protection; prot_reg[1] = (uint16_t)(protection >> 8); prot_reg[2] = (uint16_t)(protection >> 16); prot_reg[3] = (uint16_t)(protection >> 24); if (stm32x_info->ppage_size == 2) { /* high density flash */ /* bit 7 controls sector 62 - 255 protection */ if (last > 61) { if (set) prot_reg[3] &= ~(1 << 7); else prot_reg[3] |= (1 << 7); } if (first > 61) first = 62; if (last > 61) last = 61; for (i = first; i <= last; i++) { reg = (i / stm32x_info->ppage_size) / 8; bit = (i / stm32x_info->ppage_size) - (reg * 8); if (set) prot_reg[reg] &= ~(1 << bit); else prot_reg[reg] |= (1 << bit); } } else { /* medium density flash */ for (i = first; i <= last; i++) { reg = (i / stm32x_info->ppage_size) / 8; bit = (i / stm32x_info->ppage_size) - (reg * 8); if (set) prot_reg[reg] &= ~(1 << bit); else prot_reg[reg] |= (1 << bit); } } status = stm32x_erase_options(bank); if (status != ERROR_OK) return status; stm32x_info->option_bytes.protection[0] = prot_reg[0]; stm32x_info->option_bytes.protection[1] = prot_reg[1]; stm32x_info->option_bytes.protection[2] = prot_reg[2]; stm32x_info->option_bytes.protection[3] = prot_reg[3]; return stm32x_write_options(bank); } static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* see contrib/loaders/flash/stm32f1x.S for src */ static const uint8_t stm32x_flash_write_code[] = { /* #define STM32_FLASH_SR_OFFSET 0x0C */ /* wait_fifo: */ 0x16, 0x68, /* ldr r6, [r2, #0] */ 0x00, 0x2e, /* cmp r6, #0 */ 0x18, 0xd0, /* beq exit */ 0x55, 0x68, /* ldr r5, [r2, #4] */ 0xb5, 0x42, /* cmp r5, r6 */ 0xf9, 0xd0, /* beq wait_fifo */ 0x2e, 0x88, /* ldrh r6, [r5, #0] */ 0x26, 0x80, /* strh r6, [r4, #0] */ 0x02, 0x35, /* adds r5, #2 */ 0x02, 0x34, /* adds r4, #2 */ /* busy: */ 0xc6, 0x68, /* ldr r6, [r0, #STM32_FLASH_SR_OFFSET] */ 0x01, 0x27, /* movs r7, #1 */ 0x3e, 0x42, /* tst r6, r7 */ 0xfb, 0xd1, /* bne busy */ 0x14, 0x27, /* movs r7, #0x14 */ 0x3e, 0x42, /* tst r6, r7 */ 0x08, 0xd1, /* bne error */ 0x9d, 0x42, /* cmp r5, r3 */ 0x01, 0xd3, /* bcc no_wrap */ 0x15, 0x46, /* mov r5, r2 */ 0x08, 0x35, /* adds r5, #8 */ /* no_wrap: */ 0x55, 0x60, /* str r5, [r2, #4] */ 0x01, 0x39, /* subs r1, r1, #1 */ 0x00, 0x29, /* cmp r1, #0 */ 0x02, 0xd0, /* beq exit */ 0xe5, 0xe7, /* b wait_fifo */ /* error: */ 0x00, 0x20, /* movs r0, #0 */ 0x50, 0x60, /* str r0, [r2, #4] */ /* exit: */ 0x30, 0x46, /* mov r0, r6 */ 0x00, 0xbe, /* bkpt #0 */ }; /* flash write code */ if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } }; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (halfword-16bit) */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer start */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[4], "r4", 32, PARAM_IN_OUT); /* target address */ buf_set_u32(reg_params[0].value, 0, 32, stm32x_info->register_base); buf_set_u32(reg_params[1].value, 0, 32, count); buf_set_u32(reg_params[2].value, 0, 32, source->address); buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[4].value, 0, 32, address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; retval = target_run_flash_async_algorithm(target, buffer, count, 2, 0, NULL, 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash write failed at address 0x%"PRIx32, buf_get_u32(reg_params[4].value, 0, 32)); if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) { LOG_ERROR("flash memory not erased before writing"); /* Clear but report errors */ target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_PGERR); } if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) { LOG_ERROR("flash memory write protected"); /* Clear but report errors */ target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_WRPRTERR); } } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return retval; } static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint8_t *new_buffer = NULL; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* If there's an odd number of bytes, the data has to be padded. Duplicate * the buffer and use the normal code path with a single block write since * it's probably cheaper than to special case the last odd write using * discrete accesses. */ if (count & 1) { new_buffer = malloc(count + 1); if (new_buffer == NULL) { LOG_ERROR("odd number of bytes to write and no memory for padding buffer"); return ERROR_FAIL; } LOG_INFO("odd number of bytes to write, padding with 0xff"); buffer = memcpy(new_buffer, buffer, count); new_buffer[count++] = 0xff; } uint32_t words_remaining = count / 2; int retval, retval2; /* unlock flash registers */ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); if (retval != ERROR_OK) goto cleanup; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2); if (retval != ERROR_OK) goto cleanup; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG); if (retval != ERROR_OK) goto cleanup; /* try using a block write */ retval = stm32x_write_block(bank, buffer, offset, words_remaining); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single halfword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); while (words_remaining > 0) { uint16_t value; memcpy(&value, buffer, sizeof(uint16_t)); retval = target_write_u16(target, bank->base + offset, value); if (retval != ERROR_OK) goto reset_pg_and_lock; retval = stm32x_wait_status_busy(bank, 5); if (retval != ERROR_OK) goto reset_pg_and_lock; words_remaining--; buffer += 2; offset += 2; } } reset_pg_and_lock: retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); if (retval == ERROR_OK) retval = retval2; cleanup: if (new_buffer) free(new_buffer); return retval; } static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) { /* This check the device CPUID core register to detect * the M0 from the M3 devices. */ struct target *target = bank->target; uint32_t cpuid, device_id_register = 0; /* Get the CPUID from the ARM Core * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */ int retval = target_read_u32(target, 0xE000ED00, &cpuid); if (retval != ERROR_OK) return retval; if (((cpuid >> 4) & 0xFFF) == 0xC20) { /* 0xC20 is M0 devices */ device_id_register = 0x40015800; } else if (((cpuid >> 4) & 0xFFF) == 0xC23) { /* 0xC23 is M3 devices */ device_id_register = 0xE0042000; } else if (((cpuid >> 4) & 0xFFF) == 0xC24) { /* 0xC24 is M4 devices */ device_id_register = 0xE0042000; } else { LOG_ERROR("Cannot identify target as a stm32x"); return ERROR_FAIL; } /* read stm32 device id register */ retval = target_read_u32(target, device_id_register, device_id); if (retval != ERROR_OK) return retval; return retval; } static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb) { struct target *target = bank->target; uint32_t cpuid, flash_size_reg; int retval = target_read_u32(target, 0xE000ED00, &cpuid); if (retval != ERROR_OK) return retval; if (((cpuid >> 4) & 0xFFF) == 0xC20) { /* 0xC20 is M0 devices */ flash_size_reg = 0x1FFFF7CC; } else if (((cpuid >> 4) & 0xFFF) == 0xC23) { /* 0xC23 is M3 devices */ flash_size_reg = 0x1FFFF7E0; } else if (((cpuid >> 4) & 0xFFF) == 0xC24) { /* 0xC24 is M4 devices */ flash_size_reg = 0x1FFFF7CC; } else { LOG_ERROR("Cannot identify target as a stm32x"); return ERROR_FAIL; } retval = target_read_u16(target, flash_size_reg, flash_size_in_kb); if (retval != ERROR_OK) return retval; return retval; } static int stm32x_probe(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; int i; uint16_t flash_size_in_kb; uint16_t max_flash_size_in_kb; uint32_t device_id; int page_size; uint32_t base_address = 0x08000000; stm32x_info->probed = 0; stm32x_info->register_base = FLASH_REG_BASE_B0; stm32x_info->user_data_offset = 10; stm32x_info->option_offset = 0; /* default factory protection level */ stm32x_info->default_rdp = 0x5AA5; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); if (retval != ERROR_OK) return retval; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); /* set page size, protection granularity and max flash size depending on family */ switch (device_id & 0xfff) { case 0x410: /* medium density */ page_size = 1024; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 128; break; case 0x412: /* low density */ page_size = 1024; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 32; break; case 0x414: /* high density */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 512; break; case 0x418: /* connectivity line density */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 256; break; case 0x420: /* value line density */ page_size = 1024; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 128; break; case 0x422: /* stm32f302/3xb/c */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 256; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; case 0x446: /* stm32f303xD/E */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 512; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; case 0x428: /* value line High density */ page_size = 2048; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 128; break; case 0x430: /* xl line density (dual flash banks) */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 1024; stm32x_info->has_dual_banks = true; break; case 0x432: /* stm32f37x */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 256; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; case 0x438: /* stm32f33x */ case 0x439: /* stm32f302x6/8 */ page_size = 2048; stm32x_info->ppage_size = 2; max_flash_size_in_kb = 64; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; case 0x440: /* stm32f05x */ case 0x444: /* stm32f03x */ case 0x445: /* stm32f04x */ page_size = 1024; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 64; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; case 0x448: /* stm32f07x */ case 0x442: /* stm32f09x */ page_size = 2048; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 256; stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; stm32x_info->default_rdp = 0x55AA; break; default: LOG_WARNING("Cannot identify target as a STM32 family."); return ERROR_FAIL; } /* get flash size from target. */ retval = stm32x_get_flash_size(bank, &flash_size_in_kb); /* failed reading flash size or flash size invalid (early silicon), * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash", max_flash_size_in_kb); flash_size_in_kb = max_flash_size_in_kb; } if (stm32x_info->has_dual_banks) { /* split reported size into matching bank */ if (bank->base != 0x08080000) { /* bank 0 will be fixed 512k */ flash_size_in_kb = 512; } else { flash_size_in_kb -= 512; /* bank1 also uses a register offset */ stm32x_info->register_base = FLASH_REG_BASE_B1; base_address = 0x08080000; } } /* if the user sets the size manually then ignore the probed value * this allows us to work around devices that have a invalid flash size register value */ if (stm32x_info->user_bank_size) { LOG_INFO("ignoring flash probed value, using configured bank size"); flash_size_in_kb = stm32x_info->user_bank_size / 1024; } LOG_INFO("flash size = %dkbytes", flash_size_in_kb); /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); /* calculate numbers of pages */ int num_pages = flash_size_in_kb * 1024 / page_size; /* check that calculation result makes sense */ assert(num_pages > 0); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->size = (num_pages * page_size); bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); for (i = 0; i < num_pages; i++) { bank->sectors[i].offset = i * page_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } stm32x_info->probed = 1; return ERROR_OK; } static int stm32x_auto_probe(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; if (stm32x_info->probed) return ERROR_OK; return stm32x_probe(bank); } #if 0 COMMAND_HANDLER(stm32x_handle_part_id_command) { return ERROR_OK; } #endif static const char *get_stm32f0_revision(uint16_t rev_id) { const char *rev_str = NULL; switch (rev_id) { case 0x1000: rev_str = "1.0"; break; case 0x2000: rev_str = "2.0"; break; } return rev_str; } static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) { uint32_t dbgmcu_idcode; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &dbgmcu_idcode); if (retval != ERROR_OK) return retval; uint16_t device_id = dbgmcu_idcode & 0xfff; uint16_t rev_id = dbgmcu_idcode >> 16; const char *device_str; const char *rev_str = NULL; switch (device_id) { case 0x410: device_str = "STM32F10x (Medium Density)"; switch (rev_id) { case 0x0000: rev_str = "A"; break; case 0x2000: rev_str = "B"; break; case 0x2001: rev_str = "Z"; break; case 0x2003: rev_str = "Y"; break; } break; case 0x412: device_str = "STM32F10x (Low Density)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; } break; case 0x414: device_str = "STM32F10x (High Density)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; case 0x1003: rev_str = "Y"; break; } break; case 0x418: device_str = "STM32F10x (Connectivity)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; } break; case 0x420: device_str = "STM32F100 (Low/Medium Density)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; } break; case 0x422: device_str = "STM32F302xB/C"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; case 0x1003: rev_str = "Y"; break; case 0x2000: rev_str = "B"; break; } break; case 0x428: device_str = "STM32F100 (High Density)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; } break; case 0x430: device_str = "STM32F10x (XL Density)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; } break; case 0x432: device_str = "STM32F37x"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x2000: rev_str = "B"; break; } break; case 0x438: device_str = "STM32F33x"; switch (rev_id) { case 0x1000: rev_str = "A"; break; } break; case 0x439: device_str = "STM32F302x6/8"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; } break; case 0x444: device_str = "STM32F03x"; rev_str = get_stm32f0_revision(rev_id); break; case 0x440: device_str = "STM32F05x"; rev_str = get_stm32f0_revision(rev_id); break; case 0x445: device_str = "STM32F04x"; rev_str = get_stm32f0_revision(rev_id); break; case 0x446: device_str = "STM32F303xD/E"; switch (rev_id) { case 0x1000: rev_str = "A"; break; } break; case 0x448: device_str = "STM32F07x"; rev_str = get_stm32f0_revision(rev_id); break; case 0x442: device_str = "STM32F09x"; rev_str = get_stm32f0_revision(rev_id); break; default: snprintf(buf, buf_size, "Cannot identify target as a STM32F0/1/3\n"); return ERROR_FAIL; } if (rev_str != NULL) snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str); else snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_lock_command) { struct target *target = NULL; struct stm32x_flash_bank *stm32x_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; stm32x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; if (stm32x_erase_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to erase options"); return ERROR_OK; } /* set readout protection */ stm32x_info->option_bytes.RDP = 0; if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to lock device"); return ERROR_OK; } command_print(CMD_CTX, "stm32x locked"); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_unlock_command) { struct target *target = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; if (stm32x_erase_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to unlock device"); return ERROR_OK; } if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to lock device"); return ERROR_OK; } command_print(CMD_CTX, "stm32x unlocked.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_options_read_command) { uint32_t optionbyte; struct target *target = NULL; struct stm32x_flash_bank *stm32x_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; stm32x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; retval = target_read_u32(target, STM32_FLASH_OBR_B0, &optionbyte); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte); int user_data = optionbyte; if (optionbyte >> OPT_ERROR & 1) command_print(CMD_CTX, "Option Byte Complement Error"); if (optionbyte >> OPT_READOUT & 1) command_print(CMD_CTX, "Readout Protection On"); else command_print(CMD_CTX, "Readout Protection Off"); /* user option bytes are offset depending on variant */ optionbyte >>= stm32x_info->option_offset; if (optionbyte >> OPT_RDWDGSW & 1) command_print(CMD_CTX, "Software Watchdog"); else command_print(CMD_CTX, "Hardware Watchdog"); if (optionbyte >> OPT_RDRSTSTOP & 1) command_print(CMD_CTX, "Stop: No reset generated"); else command_print(CMD_CTX, "Stop: Reset generated"); if (optionbyte >> OPT_RDRSTSTDBY & 1) command_print(CMD_CTX, "Standby: No reset generated"); else command_print(CMD_CTX, "Standby: Reset generated"); if (stm32x_info->has_dual_banks) { if (optionbyte >> OPT_BFB2 & 1) command_print(CMD_CTX, "Boot: Bank 0"); else command_print(CMD_CTX, "Boot: Bank 1"); } command_print(CMD_CTX, "User Option0: 0x%02" PRIx8, (uint8_t)((user_data >> stm32x_info->user_data_offset) & 0xff)); command_print(CMD_CTX, "User Option1: 0x%02" PRIx8, (uint8_t)((user_data >> (stm32x_info->user_data_offset + 8)) & 0xff)); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_options_write_command) { struct target *target = NULL; struct stm32x_flash_bank *stm32x_info = NULL; uint16_t optionbyte; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; stm32x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = stm32x_check_operation_supported(bank); if (ERROR_OK != retval) return retval; retval = stm32x_read_options(bank); if (ERROR_OK != retval) return retval; /* start with current options */ optionbyte = stm32x_info->option_bytes.user_options; /* skip over flash bank */ CMD_ARGC--; CMD_ARGV++; while (CMD_ARGC) { if (strcmp("SWWDG", CMD_ARGV[0]) == 0) optionbyte |= (1 << 0); else if (strcmp("HWWDG", CMD_ARGV[0]) == 0) optionbyte &= ~(1 << 0); else if (strcmp("NORSTSTOP", CMD_ARGV[0]) == 0) optionbyte |= (1 << 1); else if (strcmp("RSTSTOP", CMD_ARGV[0]) == 0) optionbyte &= ~(1 << 1); else if (strcmp("NORSTSTNDBY", CMD_ARGV[0]) == 0) optionbyte |= (1 << 2); else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0) optionbyte &= ~(1 << 2); else if (stm32x_info->has_dual_banks) { if (strcmp("BOOT0", CMD_ARGV[0]) == 0) optionbyte |= (1 << 3); else if (strcmp("BOOT1", CMD_ARGV[0]) == 0) optionbyte &= ~(1 << 3); else return ERROR_COMMAND_SYNTAX_ERROR; } else return ERROR_COMMAND_SYNTAX_ERROR; CMD_ARGC--; CMD_ARGV++; } if (stm32x_erase_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to erase options"); return ERROR_OK; } stm32x_info->option_bytes.user_options = optionbyte; if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "stm32x failed to write options"); return ERROR_OK; } command_print(CMD_CTX, "stm32x write options complete.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } static int stm32x_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* unlock option flash registers */ int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = stm32x_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "stm32x mass erase complete"); } else command_print(CMD_CTX, "stm32x mass erase failed"); return retval; } static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", .handler = stm32x_handle_lock_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Lock entire flash device.", }, { .name = "unlock", .handler = stm32x_handle_unlock_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Unlock entire protected flash device.", }, { .name = "mass_erase", .handler = stm32x_handle_mass_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Erase entire flash device.", }, { .name = "options_read", .handler = stm32x_handle_options_read_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Read and display device option byte.", }, { .name = "options_write", .handler = stm32x_handle_options_write_command, .mode = COMMAND_EXEC, .usage = "bank_id ('SWWDG'|'HWWDG') " "('RSTSTNDBY'|'NORSTSTNDBY') " "('RSTSTOP'|'NORSTSTOP')", .help = "Replace bits in device option byte.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration stm32x_command_handlers[] = { { .name = "stm32f1x", .mode = COMMAND_ANY, .help = "stm32f1x flash command group", .usage = "", .chain = stm32x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver stm32f1x_flash = { .name = "stm32f1x", .commands = stm32x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, .erase = stm32x_erase, .protect = stm32x_protect, .write = stm32x_write, .read = default_flash_read, .probe = stm32x_probe, .auto_probe = stm32x_auto_probe, .erase_check = default_flash_blank_check, .protect_check = stm32x_protect_check, .info = get_stm32x_info, }; openocd-0.9.0/src/flash/nor/stm32f2x.c0000644000175000017500000007665712516456302014337 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include /* Regarding performance: * * Short story - it might be best to leave the performance at * current levels. * * You may see a jump in speed if you change to using * 32bit words for the block programming. * * Its a shame you cannot use the double word as its * even faster - but you require external VPP for that mode. * * Having said all that 16bit writes give us the widest vdd * operating range, so may be worth adding a note to that effect. * */ /* Danger!!!! The STM32F1x and STM32F2x series actually have * quite different flash controllers. * * What's more scary is that the names of the registers and their * addresses are the same, but the actual bits and what they do are * can be very different. * * To reduce testing complexity and dangers of regressions, * a seperate file is used for stm32fx2x. * * 1mByte part with 4 x 16, 1 x 64, 7 x 128kBytes sectors * * What's the protection page size??? * * Tested with STM3220F-EVAL board. * * STM32F21xx series for reference. * * RM0033 * http://www.st.com/internet/mcu/product/250192.jsp * * PM0059 * www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/ * PROGRAMMING_MANUAL/CD00233952.pdf * * STM32F1x series - notice that this code was copy, pasted and knocked * into a stm32f2x driver, so in case something has been converted or * bugs haven't been fixed, here are the original manuals: * * RM0008 - Reference manual * * RM0042, the Flash programming manual for low-, medium- high-density and * connectivity line STM32F10x devices * * PM0068, the Flash programming manual for XL-density STM32F10x devices. * */ /* Erase time can be as high as 1000ms, 10x this and it's toast... */ #define FLASH_ERASE_TIMEOUT 10000 #define FLASH_WRITE_TIMEOUT 5 #define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_KEYR 0x40023c04 #define STM32_FLASH_OPTKEYR 0x40023c08 #define STM32_FLASH_SR 0x40023c0C #define STM32_FLASH_CR 0x40023c10 #define STM32_FLASH_OPTCR 0x40023c14 #define STM32_FLASH_OPTCR1 0x40023c18 /* FLASH_CR register bits */ #define FLASH_PG (1 << 0) #define FLASH_SER (1 << 1) #define FLASH_MER (1 << 2) #define FLASH_MER1 (1 << 15) #define FLASH_STRT (1 << 16) #define FLASH_PSIZE_8 (0 << 8) #define FLASH_PSIZE_16 (1 << 8) #define FLASH_PSIZE_32 (2 << 8) #define FLASH_PSIZE_64 (3 << 8) /* The sector number encoding is not straight binary for dual bank flash. * Warning: evaluates the argument multiple times */ #define FLASH_SNB(a) ((((a) >= 12) ? 0x10 | ((a) - 12) : (a)) << 3) #define FLASH_LOCK (1 << 31) /* FLASH_SR register bits */ #define FLASH_BSY (1 << 16) #define FLASH_PGSERR (1 << 7) /* Programming sequence error */ #define FLASH_PGPERR (1 << 6) /* Programming parallelism error */ #define FLASH_PGAERR (1 << 5) /* Programming alignment error */ #define FLASH_WRPERR (1 << 4) /* Write protection error */ #define FLASH_OPERR (1 << 1) /* Operation error */ #define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR) /* STM32_FLASH_OPTCR register bits */ #define OPT_LOCK (1 << 0) #define OPT_START (1 << 1) /* STM32_FLASH_OBR bit definitions (reading) */ #define OPT_ERROR 0 #define OPT_READOUT 1 #define OPT_RDWDGSW 2 #define OPT_RDRSTSTOP 3 #define OPT_RDRSTSTDBY 4 #define OPT_BFB2 5 /* dual flash bank only */ /* register unlock keys */ #define KEY1 0x45670123 #define KEY2 0xCDEF89AB /* option register unlock key */ #define OPTKEY1 0x08192A3B #define OPTKEY2 0x4C5D6E7F struct stm32x_options { uint8_t RDP; uint8_t user_options; uint32_t protection; }; struct stm32x_flash_bank { struct stm32x_options option_bytes; int probed; bool has_large_mem; /* stm32f42x/stm32f43x family */ uint32_t user_bank_size; }; /* flash bank stm32x 0 0 */ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) { struct stm32x_flash_bank *stm32x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); bank->driver_priv = stm32x_info; stm32x_info->probed = 0; stm32x_info->user_bank_size = bank->size; return ERROR_OK; } static inline int stm32x_get_flash_reg(struct flash_bank *bank, uint32_t reg) { return reg; } static inline int stm32x_get_flash_status(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; return target_read_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), status); } static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;;) { retval = stm32x_get_flash_status(bank, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if ((status & FLASH_BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_WRPERR) { LOG_ERROR("stm32x device protected"); retval = ERROR_FAIL; } /* Clear but report errors */ if (status & FLASH_ERROR) { /* If this operation fails, we ignore it and report the original * retval */ target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), status & FLASH_ERROR); } return retval; } static int stm32x_unlock_reg(struct target *target) { uint32_t ctrl; /* first check if not already unlocked * otherwise writing on STM32_FLASH_KEYR will fail */ int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; if ((ctrl & FLASH_LOCK) == 0) return ERROR_OK; /* unlock flash registers */ retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; if (ctrl & FLASH_LOCK) { LOG_ERROR("flash not unlocked STM32_FLASH_CR: %" PRIx32, ctrl); return ERROR_TARGET_FAILURE; } return ERROR_OK; } static int stm32x_unlock_option_reg(struct target *target) { uint32_t ctrl; int retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl); if (retval != ERROR_OK) return retval; if ((ctrl & OPT_LOCK) == 0) return ERROR_OK; /* unlock option registers */ retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl); if (retval != ERROR_OK) return retval; if (ctrl & OPT_LOCK) { LOG_ERROR("options not unlocked STM32_FLASH_OPTCR: %" PRIx32, ctrl); return ERROR_TARGET_FAILURE; } return ERROR_OK; } static int stm32x_read_options(struct flash_bank *bank) { uint32_t optiondata; struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.user_options = optiondata & 0xec; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff; if (stm32x_info->has_large_mem) { retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata); if (retval != ERROR_OK) return retval; /* append protection bits */ stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000; } if (stm32x_info->option_bytes.RDP != 0xAA) LOG_INFO("Device Security Bit Set"); return ERROR_OK; } static int stm32x_write_options(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; uint32_t optiondata; stm32x_info = bank->driver_priv; int retval = stm32x_unlock_option_reg(target); if (retval != ERROR_OK) return retval; /* rebuild option data */ optiondata = stm32x_info->option_bytes.user_options; optiondata |= stm32x_info->option_bytes.RDP << 8; optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16; /* program options */ retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata); if (retval != ERROR_OK) return retval; if (stm32x_info->has_large_mem) { uint32_t optiondata2 = 0; optiondata2 |= (stm32x_info->option_bytes.protection & 0x00fff000) << 4; retval = target_write_u32(target, STM32_FLASH_OPTCR1, optiondata2); if (retval != ERROR_OK) return retval; } /* start programming cycle */ retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPT_START); if (retval != ERROR_OK) return retval; /* wait for completion */ retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; /* relock registers */ retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPT_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32x_protect_check(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; /* read write protection settings */ int retval = stm32x_read_options(bank); if (retval != ERROR_OK) { LOG_DEBUG("unable to read option bytes"); return retval; } for (int i = 0; i < bank->num_sectors; i++) { if (stm32x_info->option_bytes.protection & (1 << i)) bank->sectors[i].is_protected = 0; else bank->sectors[i].is_protected = 1; } return ERROR_OK; } static int stm32x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; assert(first < bank->num_sectors); assert(last < bank->num_sectors); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int retval; retval = stm32x_unlock_reg(target); if (retval != ERROR_OK) return retval; /* Sector Erase To erase a sector, follow the procedure below: 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the FLASH_SR register 2. Set the SER bit and select the sector you wish to erase (SNB) in the FLASH_CR register 3. Set the STRT bit in the FLASH_CR register 4. Wait for the BSY bit to be cleared */ for (i = first; i <= last; i++) { retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; bank->sectors[i].is_erased = 1; } retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* read protection settings */ int retval = stm32x_read_options(bank); if (retval != ERROR_OK) { LOG_DEBUG("unable to read option bytes"); return retval; } for (int i = first; i <= last; i++) { if (set) stm32x_info->option_bytes.protection &= ~(1 << i); else stm32x_info->option_bytes.protection |= (1 << i); } retval = stm32x_write_options(bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* see contrib/loaders/flash/stm32f2x.S for src */ static const uint8_t stm32x_flash_write_code[] = { /* wait_fifo: */ 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */ 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */ 0x1A, 0xD0, /* beq exit */ 0x47, 0x68, /* ldr r7, [r0, #4] */ 0x47, 0x45, /* cmp r7, r8 */ 0xF7, 0xD0, /* beq wait_fifo */ 0xDF, 0xF8, 0x30, 0x60, /* ldr r6, STM32_PROG16 */ 0x26, 0x61, /* str r6, [r4, #STM32_FLASH_CR_OFFSET] */ 0x37, 0xF8, 0x02, 0x6B, /* ldrh r6, [r7], #0x02 */ 0x22, 0xF8, 0x02, 0x6B, /* strh r6, [r2], #0x02 */ /* busy: */ 0xE6, 0x68, /* ldr r6, [r4, #STM32_FLASH_SR_OFFSET] */ 0x16, 0xF4, 0x80, 0x3F, /* tst r6, #0x10000 */ 0xFB, 0xD1, /* bne busy */ 0x16, 0xF0, 0xF0, 0x0F, /* tst r6, #0xf0 */ 0x07, 0xD1, /* bne error */ 0x8F, 0x42, /* cmp r7, r1 */ 0x28, 0xBF, /* it cs */ 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */ 0x47, 0x60, /* str r7, [r0, #4] */ 0x01, 0x3B, /* subs r3, r3, #1 */ 0x13, 0xB1, /* cbz r3, exit */ 0xE1, 0xE7, /* b wait_fifo */ /* error: */ 0x00, 0x21, /* movs r1, #0 */ 0x41, 0x60, /* str r1, [r0, #4] */ /* exit: */ 0x30, 0x46, /* mov r0, r6 */ 0x00, 0xBE, /* bkpt #0x00 */ /* : */ 0x01, 0x01, 0x00, 0x00, /* .word 0x00000101 */ }; if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* flash base */ buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, count); buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE); retval = target_run_flash_async_algorithm(target, buffer, count, 2, 0, NULL, 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("error executing stm32x flash write algorithm"); uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & FLASH_ERROR; if (error & FLASH_WRPERR) LOG_ERROR("flash memory write protected"); if (error != 0) { LOG_ERROR("flash write failed = %08" PRIx32, error); /* Clear but report errors */ target_write_u32(target, STM32_FLASH_SR, error); retval = ERROR_FAIL; } } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return retval; } static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t words_remaining = (count / 2); uint32_t bytes_remaining = (count & 0x00000001); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } retval = stm32x_unlock_reg(target); if (retval != ERROR_OK) return retval; /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = stm32x_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); } } else { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) return retval; /* Standard programming The Flash memory programming sequence is as follows: 1. Check that no main Flash memory operation is ongoing by checking the BSY bit in the FLASH_SR register. 2. Set the PG bit in the FLASH_CR register 3. Perform the data write operation(s) to the desired memory address (inside main memory block or OTP area): – – Half-word access in case of x16 parallelism – Word access in case of x32 parallelism – 4. Byte access in case of x8 parallelism Double word access in case of x64 parallelism Wait for the BSY bit to be cleared */ while (words_remaining > 0) { uint16_t value; memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG | FLASH_PSIZE_16); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT); if (retval != ERROR_OK) return retval; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG | FLASH_PSIZE_8); if (retval != ERROR_OK) return retval; retval = target_write_u8(target, address, buffer[bytes_written]); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT); if (retval != ERROR_OK) return retval; } return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); } static void setup_sector(struct flash_bank *bank, int start, int num, int size) { for (int i = start; i < (start + num) ; i++) { assert(i < bank->num_sectors); bank->sectors[i].offset = bank->size; bank->sectors[i].size = size; bank->size += bank->sectors[i].size; } } static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) { /* this checks for a stm32f4x errata issue where a * stm32f2x DBGMCU_IDCODE is incorrectly returned. * If the issue is detected target is forced to stm32f4x Rev A. * Only effects Rev A silicon */ struct target *target = bank->target; uint32_t cpuid; /* read stm32 device id register */ int retval = target_read_u32(target, 0xE0042000, device_id); if (retval != ERROR_OK) return retval; if ((*device_id & 0xfff) == 0x411) { /* read CPUID reg to check core type */ retval = target_read_u32(target, 0xE000ED00, &cpuid); if (retval != ERROR_OK) return retval; /* check for cortex_m4 */ if (((cpuid >> 4) & 0xFFF) == 0xC24) { *device_id &= ~((0xFFFF << 16) | 0xfff); *device_id |= (0x1000 << 16) | 0x413; LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE"); } } return retval; } static int stm32x_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; int i; uint16_t flash_size_in_kb; uint16_t max_flash_size_in_kb; uint32_t device_id; uint32_t base_address = 0x08000000; stm32x_info->probed = 0; stm32x_info->has_large_mem = false; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); if (retval != ERROR_OK) return retval; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); /* set max flash size depending on family */ switch (device_id & 0xfff) { case 0x411: case 0x413: max_flash_size_in_kb = 1024; break; case 0x419: max_flash_size_in_kb = 2048; break; case 0x423: max_flash_size_in_kb = 256; break; case 0x431: case 0x433: case 0x421: max_flash_size_in_kb = 512; break; default: LOG_WARNING("Cannot identify target as a STM32 family."); return ERROR_FAIL; } /* get flash size from target. */ retval = target_read_u16(target, 0x1FFF7A22, &flash_size_in_kb); /* failed reading flash size or flash size invalid (early silicon), * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash", max_flash_size_in_kb); flash_size_in_kb = max_flash_size_in_kb; } /* if the user sets the size manually then ignore the probed value * this allows us to work around devices that have a invalid flash size register value */ if (stm32x_info->user_bank_size) { LOG_INFO("ignoring flash probed value, using configured bank size"); flash_size_in_kb = stm32x_info->user_bank_size / 1024; } /* only devices with > 1024kB have dual banks */ if (flash_size_in_kb > 1024) stm32x_info->has_large_mem = true; LOG_INFO("flash size = %dkbytes", flash_size_in_kb); /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); /* calculate numbers of pages */ int num_pages = (flash_size_in_kb / 128) + 4; /* check for larger 2048 bytes devices */ if (stm32x_info->has_large_mem) num_pages += 4; /* check that calculation result makes sense */ assert(num_pages > 0); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); bank->size = 0; /* fixed memory */ setup_sector(bank, 0, 4, 16 * 1024); setup_sector(bank, 4, 1, 64 * 1024); /* dynamic memory */ setup_sector(bank, 4 + 1, MIN(12, num_pages) - 5, 128 * 1024); if (stm32x_info->has_large_mem) { /* fixed memory for larger devices */ setup_sector(bank, 12, 4, 16 * 1024); setup_sector(bank, 16, 1, 64 * 1024); /* dynamic memory for larger devices */ setup_sector(bank, 16 + 1, num_pages - 5 - 12, 128 * 1024); } for (i = 0; i < num_pages; i++) { bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; } stm32x_info->probed = 1; return ERROR_OK; } static int stm32x_auto_probe(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; if (stm32x_info->probed) return ERROR_OK; return stm32x_probe(bank); } static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) { uint32_t dbgmcu_idcode; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &dbgmcu_idcode); if (retval != ERROR_OK) return retval; uint16_t device_id = dbgmcu_idcode & 0xfff; uint16_t rev_id = dbgmcu_idcode >> 16; const char *device_str; const char *rev_str = NULL; switch (device_id) { case 0x411: device_str = "STM32F2xx"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x2000: rev_str = "B"; break; case 0x1001: rev_str = "Z"; break; case 0x2001: rev_str = "Y"; break; case 0x2003: rev_str = "X"; break; } break; case 0x413: case 0x419: device_str = "STM32F4xx"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; case 0x1003: rev_str = "Y"; break; case 0x1007: rev_str = "1"; break; case 0x2001: rev_str = "3"; break; } break; case 0x421: device_str = "STM32F446"; switch (rev_id) { case 0x1000: rev_str = "A"; break; } break; case 0x423: case 0x431: case 0x433: device_str = "STM32F4xx (Low Power)"; switch (rev_id) { case 0x1000: rev_str = "A"; break; case 0x1001: rev_str = "Z"; break; } break; default: snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4\n"); return ERROR_FAIL; } if (rev_str != NULL) snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str); else snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_lock_command) { struct target *target = NULL; struct stm32x_flash_bank *stm32x_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; stm32x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (stm32x_read_options(bank) != ERROR_OK) { command_print(CMD_CTX, "%s failed to read options", bank->driver->name); return ERROR_OK; } /* set readout protection */ stm32x_info->option_bytes.RDP = 0; if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "%s failed to lock device", bank->driver->name); return ERROR_OK; } command_print(CMD_CTX, "%s locked", bank->driver->name); return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_unlock_command) { struct target *target = NULL; struct stm32x_flash_bank *stm32x_info = NULL; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; stm32x_info = bank->driver_priv; target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (stm32x_read_options(bank) != ERROR_OK) { command_print(CMD_CTX, "%s failed to read options", bank->driver->name); return ERROR_OK; } /* clear readout protection and complementary option bytes * this will also force a device unlock if set */ stm32x_info->option_bytes.RDP = 0xAA; if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "%s failed to unlock device", bank->driver->name); return ERROR_OK; } command_print(CMD_CTX, "%s unlocked.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect.", bank->driver->name); return ERROR_OK; } static int stm32x_mass_erase(struct flash_bank *bank) { int retval; struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = NULL; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } stm32x_info = bank->driver_priv; retval = stm32x_unlock_reg(target); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ if (stm32x_info->has_large_mem) retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_MER1); else retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 30000); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; } COMMAND_HANDLER(stm32x_handle_mass_erase_command) { int i; if (CMD_ARGC < 1) { command_print(CMD_CTX, "stm32x mass_erase "); return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = stm32x_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "stm32x mass erase complete"); } else { command_print(CMD_CTX, "stm32x mass erase failed"); } return retval; } static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", .handler = stm32x_handle_lock_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Lock entire flash device.", }, { .name = "unlock", .handler = stm32x_handle_unlock_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Unlock entire protected flash device.", }, { .name = "mass_erase", .handler = stm32x_handle_mass_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Erase entire flash device.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration stm32x_command_handlers[] = { { .name = "stm32f2x", .mode = COMMAND_ANY, .help = "stm32f2x flash command group", .usage = "", .chain = stm32x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver stm32f2x_flash = { .name = "stm32f2x", .commands = stm32x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, .erase = stm32x_erase, .protect = stm32x_protect, .write = stm32x_write, .read = default_flash_read, .probe = stm32x_probe, .auto_probe = stm32x_auto_probe, .erase_check = default_flash_blank_check, .protect_check = stm32x_protect_check, .info = get_stm32x_info, }; openocd-0.9.0/src/flash/nor/nrf51.c0000644000175000017500000010327312526201107013653 00000000000000/*************************************************************************** * Copyright (C) 2013 Synapse Product Development * * Andrey Smirnov * * Angus Gratton * * Erdem U. Altunyurt * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include enum { NRF51_FLASH_BASE = 0x00000000, }; enum nrf51_ficr_registers { NRF51_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */ #define NRF51_FICR_REG(offset) (NRF51_FICR_BASE + offset) NRF51_FICR_CODEPAGESIZE = NRF51_FICR_REG(0x010), NRF51_FICR_CODESIZE = NRF51_FICR_REG(0x014), NRF51_FICR_CLENR0 = NRF51_FICR_REG(0x028), NRF51_FICR_PPFC = NRF51_FICR_REG(0x02C), NRF51_FICR_NUMRAMBLOCK = NRF51_FICR_REG(0x034), NRF51_FICR_SIZERAMBLOCK0 = NRF51_FICR_REG(0x038), NRF51_FICR_SIZERAMBLOCK1 = NRF51_FICR_REG(0x03C), NRF51_FICR_SIZERAMBLOCK2 = NRF51_FICR_REG(0x040), NRF51_FICR_SIZERAMBLOCK3 = NRF51_FICR_REG(0x044), NRF51_FICR_CONFIGID = NRF51_FICR_REG(0x05C), NRF51_FICR_DEVICEID0 = NRF51_FICR_REG(0x060), NRF51_FICR_DEVICEID1 = NRF51_FICR_REG(0x064), NRF51_FICR_ER0 = NRF51_FICR_REG(0x080), NRF51_FICR_ER1 = NRF51_FICR_REG(0x084), NRF51_FICR_ER2 = NRF51_FICR_REG(0x088), NRF51_FICR_ER3 = NRF51_FICR_REG(0x08C), NRF51_FICR_IR0 = NRF51_FICR_REG(0x090), NRF51_FICR_IR1 = NRF51_FICR_REG(0x094), NRF51_FICR_IR2 = NRF51_FICR_REG(0x098), NRF51_FICR_IR3 = NRF51_FICR_REG(0x09C), NRF51_FICR_DEVICEADDRTYPE = NRF51_FICR_REG(0x0A0), NRF51_FICR_DEVICEADDR0 = NRF51_FICR_REG(0x0A4), NRF51_FICR_DEVICEADDR1 = NRF51_FICR_REG(0x0A8), NRF51_FICR_OVERRIDEN = NRF51_FICR_REG(0x0AC), NRF51_FICR_NRF_1MBIT0 = NRF51_FICR_REG(0x0B0), NRF51_FICR_NRF_1MBIT1 = NRF51_FICR_REG(0x0B4), NRF51_FICR_NRF_1MBIT2 = NRF51_FICR_REG(0x0B8), NRF51_FICR_NRF_1MBIT3 = NRF51_FICR_REG(0x0BC), NRF51_FICR_NRF_1MBIT4 = NRF51_FICR_REG(0x0C0), NRF51_FICR_BLE_1MBIT0 = NRF51_FICR_REG(0x0EC), NRF51_FICR_BLE_1MBIT1 = NRF51_FICR_REG(0x0F0), NRF51_FICR_BLE_1MBIT2 = NRF51_FICR_REG(0x0F4), NRF51_FICR_BLE_1MBIT3 = NRF51_FICR_REG(0x0F8), NRF51_FICR_BLE_1MBIT4 = NRF51_FICR_REG(0x0FC), }; enum nrf51_uicr_registers { NRF51_UICR_BASE = 0x10001000, /* User Information * Configuration Regsters */ NRF51_UICR_SIZE = 0x100, #define NRF51_UICR_REG(offset) (NRF51_UICR_BASE + offset) NRF51_UICR_CLENR0 = NRF51_UICR_REG(0x000), NRF51_UICR_RBPCONF = NRF51_UICR_REG(0x004), NRF51_UICR_XTALFREQ = NRF51_UICR_REG(0x008), NRF51_UICR_FWID = NRF51_UICR_REG(0x010), }; enum nrf51_nvmc_registers { NRF51_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory * Controller Regsters */ #define NRF51_NVMC_REG(offset) (NRF51_NVMC_BASE + offset) NRF51_NVMC_READY = NRF51_NVMC_REG(0x400), NRF51_NVMC_CONFIG = NRF51_NVMC_REG(0x504), NRF51_NVMC_ERASEPAGE = NRF51_NVMC_REG(0x508), NRF51_NVMC_ERASEALL = NRF51_NVMC_REG(0x50C), NRF51_NVMC_ERASEUICR = NRF51_NVMC_REG(0x514), }; enum nrf51_nvmc_config_bits { NRF51_NVMC_CONFIG_REN = 0x00, NRF51_NVMC_CONFIG_WEN = 0x01, NRF51_NVMC_CONFIG_EEN = 0x02, }; struct nrf51_info { uint32_t code_page_size; uint32_t code_memory_size; struct { bool probed; int (*write) (struct flash_bank *bank, struct nrf51_info *chip, const uint8_t *buffer, uint32_t offset, uint32_t count); } bank[2]; struct target *target; }; struct nrf51_device_spec { uint16_t hwid; const char *variant; const char *build_code; unsigned int flash_size_kb; }; /* The known devices table below is derived from the "nRF51 Series * Compatibility Matrix" document, which can be found by searching for * ATTN-51 on the Nordic Semi website: * * http://www.nordicsemi.com/eng/content/search?SearchText=ATTN-51 * * Up to date with Matrix v2.0, plus some additional HWIDs. * * The additional HWIDs apply where the build code in the matrix is * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is * for x==0, x!=0 means different (unspecified) HWIDs. */ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 1). */ { .hwid = 0x001D, .variant = "QFAA", .build_code = "CA/C0", .flash_size_kb = 256, }, { .hwid = 0x0026, .variant = "QFAB", .build_code = "AA", .flash_size_kb = 128, }, { .hwid = 0x0027, .variant = "QFAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0020, .variant = "CEAA", .build_code = "BA", .flash_size_kb = 256, }, { .hwid = 0x002F, .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, }, /* nRF51822 Devices (IC rev 2). */ { .hwid = 0x002A, .variant = "QFAA", .build_code = "FA0", .flash_size_kb = 256, }, { .hwid = 0x0044, .variant = "QFAA", .build_code = "GC0", .flash_size_kb = 256, }, { .hwid = 0x003C, .variant = "QFAA", .build_code = "G0", .flash_size_kb = 256, }, { .hwid = 0x004C, .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, { .hwid = 0x0040, .variant = "CEAA", .build_code = "CA0", .flash_size_kb = 256, }, { .hwid = 0x0047, .variant = "CEAA", .build_code = "DA0", .flash_size_kb = 256, }, { .hwid = 0x004D, .variant = "CEAA", .build_code = "D00", .flash_size_kb = 256, }, /* nRF51822 Devices (IC rev 3). */ { .hwid = 0x0072, .variant = "QFAA", .build_code = "H0", .flash_size_kb = 256, }, { .hwid = 0x007B, .variant = "QFAB", .build_code = "C0", .flash_size_kb = 128, }, { .hwid = 0x0083, .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, { .hwid = 0x007D, .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0079, .variant = "CEAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0087, .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, }, /* nRF51422 Devices (IC rev 1). */ { .hwid = 0x001E, .variant = "QFAA", .build_code = "CA", .flash_size_kb = 256, }, { .hwid = 0x0024, .variant = "QFAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0031, .variant = "CEAA", .build_code = "A0A", .flash_size_kb = 256, }, /* nRF51422 Devices (IC rev 2). */ { .hwid = 0x002D, .variant = "QFAA", .build_code = "DAA", .flash_size_kb = 256, }, { .hwid = 0x002E, .variant = "QFAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0061, .variant = "QFAB", .build_code = "A00", .flash_size_kb = 128, }, { .hwid = 0x0050, .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, }, /* nRF51422 Devices (IC rev 3). */ { .hwid = 0x0073, .variant = "QFAA", .build_code = "F0", .flash_size_kb = 256, }, { .hwid = 0x007C, .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, { .hwid = 0x0085, .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, { .hwid = 0x0086, .variant = "QFAC", .build_code = "A1", .flash_size_kb = 256, }, { .hwid = 0x007E, .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x007A, .variant = "CEAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0088, .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, }, /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards with built-in jlink seem to use engineering samples not listed in the nRF51 Series Compatibility Matrix V1.0. */ { .hwid = 0x0071, .variant = "QFAC", .build_code = "AB", .flash_size_kb = 256, }, }; static int nrf51_bank_is_probed(struct flash_bank *bank) { struct nrf51_info *chip = bank->driver_priv; assert(chip != NULL); return chip->bank[bank->bank_number].probed; } static int nrf51_probe(struct flash_bank *bank); static int nrf51_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf51_info **chip) { if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } *chip = bank->driver_priv; int probed = nrf51_bank_is_probed(bank); if (probed < 0) return probed; else if (!probed) return nrf51_probe(bank); else return ERROR_OK; } static int nrf51_wait_for_nvmc(struct nrf51_info *chip) { uint32_t ready; int res; int timeout = 100; do { res = target_read_u32(chip->target, NRF51_NVMC_READY, &ready); if (res != ERROR_OK) { LOG_ERROR("Couldn't read NVMC_READY register"); return res; } if (ready == 0x00000001) return ERROR_OK; alive_sleep(1); } while (timeout--); LOG_DEBUG("Timed out waiting for NVMC_READY"); return ERROR_FLASH_BUSY; } static int nrf51_nvmc_erase_enable(struct nrf51_info *chip) { int res; res = target_write_u32(chip->target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); if (res != ERROR_OK) { LOG_ERROR("Failed to enable erase operation"); return res; } /* According to NVMC examples in Nordic SDK busy status must be checked after writing to NVMC_CONFIG */ res = nrf51_wait_for_nvmc(chip); if (res != ERROR_OK) LOG_ERROR("Erase enable did not complete"); return res; } static int nrf51_nvmc_write_enable(struct nrf51_info *chip) { int res; res = target_write_u32(chip->target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); if (res != ERROR_OK) { LOG_ERROR("Failed to enable write operation"); return res; } /* According to NVMC examples in Nordic SDK busy status must be checked after writing to NVMC_CONFIG */ res = nrf51_wait_for_nvmc(chip); if (res != ERROR_OK) LOG_ERROR("Write enable did not complete"); return res; } static int nrf51_nvmc_read_only(struct nrf51_info *chip) { int res; res = target_write_u32(chip->target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); if (res != ERROR_OK) { LOG_ERROR("Failed to enable read-only operation"); return res; } /* According to NVMC examples in Nordic SDK busy status must be checked after writing to NVMC_CONFIG */ res = nrf51_wait_for_nvmc(chip); if (res != ERROR_OK) LOG_ERROR("Read only enable did not complete"); return res; } static int nrf51_nvmc_generic_erase(struct nrf51_info *chip, uint32_t erase_register, uint32_t erase_value) { int res; res = nrf51_nvmc_erase_enable(chip); if (res != ERROR_OK) goto error; res = target_write_u32(chip->target, erase_register, erase_value); if (res != ERROR_OK) goto set_read_only; res = nrf51_wait_for_nvmc(chip); if (res != ERROR_OK) goto set_read_only; return nrf51_nvmc_read_only(chip); set_read_only: nrf51_nvmc_read_only(chip); error: LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32, erase_register, erase_value); return ERROR_FAIL; } static int nrf51_protect_check(struct flash_bank *bank) { int res; uint32_t clenr0; /* UICR cannot be write protected so just return early */ if (bank->base == NRF51_UICR_BASE) return ERROR_OK; struct nrf51_info *chip = bank->driver_priv; assert(chip != NULL); res = target_read_u32(chip->target, NRF51_FICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[FICR]"); return res; } if (clenr0 == 0xFFFFFFFF) { res = target_read_u32(chip->target, NRF51_UICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[UICR]"); return res; } } for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = clenr0 != 0xFFFFFFFF && bank->sectors[i].offset < clenr0; return ERROR_OK; } static int nrf51_protect(struct flash_bank *bank, int set, int first, int last) { int res; uint32_t clenr0, ppfc; struct nrf51_info *chip; /* UICR cannot be write protected so just bail out early */ if (bank->base == NRF51_UICR_BASE) return ERROR_FAIL; res = nrf51_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; if (first != 0) { LOG_ERROR("Code region 0 must start at the begining of the bank"); return ERROR_FAIL; } res = target_read_u32(chip->target, NRF51_FICR_PPFC, &ppfc); if (res != ERROR_OK) { LOG_ERROR("Couldn't read PPFC register"); return res; } if ((ppfc & 0xFF) == 0x00) { LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings"); return ERROR_FAIL; }; res = target_read_u32(chip->target, NRF51_UICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[UICR]"); return res; } if (clenr0 == 0xFFFFFFFF) { res = target_write_u32(chip->target, NRF51_UICR_CLENR0, clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't write code region 0 size[UICR]"); return res; } } else { LOG_ERROR("You need to perform chip erase before changing the protection settings"); } nrf51_protect_check(bank); return ERROR_OK; } static int nrf51_probe(struct flash_bank *bank) { uint32_t hwid; int res; struct nrf51_info *chip = bank->driver_priv; res = target_read_u32(chip->target, NRF51_FICR_CONFIGID, &hwid); if (res != ERROR_OK) { LOG_ERROR("Couldn't read CONFIGID register"); return res; } hwid &= 0xFFFF; /* HWID is stored in the lower two * bytes of the CONFIGID register */ const struct nrf51_device_spec *spec = NULL; for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) if (hwid == nrf51_known_devices_table[i].hwid) { spec = &nrf51_known_devices_table[i]; break; } if (!chip->bank[0].probed && !chip->bank[1].probed) { if (spec) LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash", spec->variant, spec->build_code, spec->flash_size_kb); else LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid); } if (bank->base == NRF51_FLASH_BASE) { res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE, &chip->code_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; } res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, &chip->code_memory_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } if (spec && chip->code_memory_size != spec->flash_size_kb) { LOG_ERROR("Chip's reported Flash capacity does not match expected one"); return ERROR_FAIL; } bank->size = chip->code_memory_size * 1024; bank->num_sectors = bank->size / chip->code_page_size; bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); if (!bank->sectors) return ERROR_FLASH_BANK_NOT_PROBED; /* Fill out the sector information: all NRF51 sectors are the same size and * there is always a fixed number of them. */ for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].size = chip->code_page_size; bank->sectors[i].offset = i * chip->code_page_size; /* mark as unknown */ bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } nrf51_protect_check(bank); chip->bank[0].probed = true; } else { bank->size = NRF51_UICR_SIZE; bank->num_sectors = 1; bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); if (!bank->sectors) return ERROR_FLASH_BANK_NOT_PROBED; bank->sectors[0].size = bank->size; bank->sectors[0].offset = 0; /* mark as unknown */ bank->sectors[0].is_erased = 0; bank->sectors[0].is_protected = 0; chip->bank[1].probed = true; } return ERROR_OK; } static int nrf51_auto_probe(struct flash_bank *bank) { int probed = nrf51_bank_is_probed(bank); if (probed < 0) return probed; else if (probed) return ERROR_OK; else return nrf51_probe(bank); } static struct flash_sector *nrf51_find_sector_by_address(struct flash_bank *bank, uint32_t address) { struct nrf51_info *chip = bank->driver_priv; for (int i = 0; i < bank->num_sectors; i++) if (bank->sectors[i].offset <= address && address < (bank->sectors[i].offset + chip->code_page_size)) return &bank->sectors[i]; return NULL; } static int nrf51_erase_all(struct nrf51_info *chip) { LOG_DEBUG("Erasing all non-volatile memory"); return nrf51_nvmc_generic_erase(chip, NRF51_NVMC_ERASEALL, 0x00000001); } static int nrf51_erase_page(struct flash_bank *bank, struct nrf51_info *chip, struct flash_sector *sector) { int res; LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset); if (sector->is_protected) { LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, sector->offset); return ERROR_FAIL; } if (bank->base == NRF51_UICR_BASE) { uint32_t ppfc; res = target_read_u32(chip->target, NRF51_FICR_PPFC, &ppfc); if (res != ERROR_OK) { LOG_ERROR("Couldn't read PPFC register"); return res; } if ((ppfc & 0xFF) == 0xFF) { /* We can't erase the UICR. Double-check to see if it's already erased before complaining. */ default_flash_blank_check(bank); if (sector->is_erased == 1) return ERROR_OK; LOG_ERROR("The chip was not pre-programmed with SoftDevice stack and UICR cannot be erased separately. Please issue mass erase before trying to write to this region"); return ERROR_FAIL; }; res = nrf51_nvmc_generic_erase(chip, NRF51_NVMC_ERASEUICR, 0x00000001); } else { res = nrf51_nvmc_generic_erase(chip, NRF51_NVMC_ERASEPAGE, sector->offset); } if (res == ERROR_OK) sector->is_erased = 1; return res; } static const uint8_t nrf51_flash_write_code[] = { /* See contrib/loaders/flash/cortex-m0.S */ /* : */ 0x0d, 0x68, /* ldr r5, [r1, #0] */ 0x00, 0x2d, /* cmp r5, #0 */ 0x0b, 0xd0, /* beq.n 1e */ 0x4c, 0x68, /* ldr r4, [r1, #4] */ 0xac, 0x42, /* cmp r4, r5 */ 0xf9, 0xd0, /* beq.n 0 */ 0x20, 0xcc, /* ldmia r4!, {r5} */ 0x20, 0xc3, /* stmia r3!, {r5} */ 0x94, 0x42, /* cmp r4, r2 */ 0x01, 0xd3, /* bcc.n 18 */ 0x0c, 0x46, /* mov r4, r1 */ 0x08, 0x34, /* adds r4, #8 */ /* : */ 0x4c, 0x60, /* str r4, [r1, #4] */ 0x04, 0x38, /* subs r0, #4 */ 0xf0, 0xd1, /* bne.n 0 */ /* : */ 0x00, 0xbe /* bkpt 0x0000 */ }; /* Start a low level flash write for the specified region */ static int nrf51_ll_flash_write(struct nrf51_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes) { struct target *target = chip->target; uint32_t buffer_size = 8192; struct working_area *write_algorithm; struct working_area *source; uint32_t address = NRF51_FLASH_BASE + offset; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes); assert(bytes % 4 == 0); /* allocate working area with flash programming code */ if (target_alloc_working_area(target, sizeof(nrf51_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, falling back to slow memory writes"); for (; bytes > 0; bytes -= 4) { retval = target_write_memory(chip->target, offset, 4, 1, buffer); if (retval != ERROR_OK) return retval; retval = nrf51_wait_for_nvmc(chip); if (retval != ERROR_OK) return retval; offset += 4; buffer += 4; } return ERROR_OK; } LOG_WARNING("using fast async flash loader. This is currently supported"); LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add"); LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf51.cfg to disable it"); retval = target_write_buffer(target, write_algorithm->address, sizeof(nrf51_flash_write_code), nrf51_flash_write_code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ if (buffer_size <= 256) { /* free working area, write algorithm already allocated */ target_free_working_area(target, write_algorithm); LOG_WARNING("No large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* byte count */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer start */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); /* target address */ buf_set_u32(reg_params[0].value, 0, 32, bytes); buf_set_u32(reg_params[1].value, 0, 32, source->address); buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[3].value, 0, 32, address); retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4, 0, NULL, 4, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); return retval; } /* Check and erase flash sectors in specified range then start a low level page write. start/end must be sector aligned. */ static int nrf51_write_pages(struct flash_bank *bank, uint32_t start, uint32_t end, const uint8_t *buffer) { int res = ERROR_FAIL; struct nrf51_info *chip = bank->driver_priv; struct flash_sector *sector; uint32_t offset; assert(start % chip->code_page_size == 0); assert(end % chip->code_page_size == 0); /* Erase all sectors */ for (offset = start; offset < end; offset += chip->code_page_size) { sector = nrf51_find_sector_by_address(bank, offset); if (!sector) { LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset); return ERROR_FLASH_SECTOR_INVALID; } if (sector->is_protected) { LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset); goto error; } if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */ res = nrf51_erase_page(bank, chip, sector); if (res != ERROR_OK) { LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset); goto error; } } sector->is_erased = 0; } res = nrf51_nvmc_write_enable(chip); if (res != ERROR_OK) goto error; res = nrf51_ll_flash_write(chip, start, buffer, (end - start)); if (res != ERROR_OK) goto set_read_only; return nrf51_nvmc_read_only(chip); set_read_only: nrf51_nvmc_read_only(chip); error: LOG_ERROR("Failed to write to nrf51 flash"); return res; } static int nrf51_erase(struct flash_bank *bank, int first, int last) { int res; struct nrf51_info *chip; res = nrf51_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; /* For each sector to be erased */ for (int s = first; s <= last && res == ERROR_OK; s++) res = nrf51_erase_page(bank, chip, &bank->sectors[s]); return res; } static int nrf51_code_flash_write(struct flash_bank *bank, struct nrf51_info *chip, const uint8_t *buffer, uint32_t offset, uint32_t count) { int res; /* Need to perform reads to fill any gaps we need to preserve in the first page, before the start of buffer, or in the last page, after the end of buffer */ uint32_t first_page = offset/chip->code_page_size; uint32_t last_page = DIV_ROUND_UP(offset+count, chip->code_page_size); uint32_t first_page_offset = first_page * chip->code_page_size; uint32_t last_page_offset = last_page * chip->code_page_size; LOG_DEBUG("Padding write from 0x%08"PRIx32"-0x%08"PRIx32" as 0x%08"PRIx32"-0x%08"PRIx32, offset, offset+count, first_page_offset, last_page_offset); uint32_t page_cnt = last_page - first_page; uint8_t buffer_to_flash[page_cnt*chip->code_page_size]; /* Fill in any space between start of first page and start of buffer */ uint32_t pre = offset - first_page_offset; if (pre > 0) { res = target_read_memory(bank->target, first_page_offset, 1, pre, buffer_to_flash); if (res != ERROR_OK) return res; } /* Fill in main contents of buffer */ memcpy(buffer_to_flash+pre, buffer, count); /* Fill in any space between end of buffer and end of last page */ uint32_t post = last_page_offset - (offset+count); if (post > 0) { /* Retrieve the full row contents from Flash */ res = target_read_memory(bank->target, offset + count, 1, post, buffer_to_flash+pre+count); if (res != ERROR_OK) return res; } return nrf51_write_pages(bank, first_page_offset, last_page_offset, buffer_to_flash); } static int nrf51_uicr_flash_write(struct flash_bank *bank, struct nrf51_info *chip, const uint8_t *buffer, uint32_t offset, uint32_t count) { int res; uint8_t uicr[NRF51_UICR_SIZE]; struct flash_sector *sector = &bank->sectors[0]; if ((offset + count) > NRF51_UICR_SIZE) return ERROR_FAIL; res = target_read_memory(bank->target, NRF51_UICR_BASE, 1, NRF51_UICR_SIZE, uicr); if (res != ERROR_OK) return res; if (sector->is_erased != 1) { res = nrf51_erase_page(bank, chip, sector); if (res != ERROR_OK) return res; } res = nrf51_nvmc_write_enable(chip); if (res != ERROR_OK) return res; memcpy(&uicr[offset], buffer, count); res = nrf51_ll_flash_write(chip, NRF51_UICR_BASE, uicr, NRF51_UICR_SIZE); if (res != ERROR_OK) { nrf51_nvmc_read_only(chip); return res; } return nrf51_nvmc_read_only(chip); } static int nrf51_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int res; struct nrf51_info *chip; res = nrf51_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count); } FLASH_BANK_COMMAND_HANDLER(nrf51_flash_bank_command) { static struct nrf51_info *chip; switch (bank->base) { case NRF51_FLASH_BASE: bank->bank_number = 0; break; case NRF51_UICR_BASE: bank->bank_number = 1; break; default: LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base); return ERROR_FAIL; } if (!chip) { /* Create a new chip */ chip = calloc(1, sizeof(*chip)); if (!chip) return ERROR_FAIL; chip->target = bank->target; } switch (bank->base) { case NRF51_FLASH_BASE: chip->bank[bank->bank_number].write = nrf51_code_flash_write; break; case NRF51_UICR_BASE: chip->bank[bank->bank_number].write = nrf51_uicr_flash_write; break; } chip->bank[bank->bank_number].probed = false; bank->driver_priv = chip; return ERROR_OK; } COMMAND_HANDLER(nrf51_handle_mass_erase_command) { int res; struct flash_bank *bank = NULL; struct target *target = get_current_target(CMD_CTX); res = get_flash_bank_by_addr(target, NRF51_FLASH_BASE, true, &bank); if (res != ERROR_OK) return res; assert(bank != NULL); struct nrf51_info *chip; res = nrf51_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; uint32_t ppfc; res = target_read_u32(target, NRF51_FICR_PPFC, &ppfc); if (res != ERROR_OK) { LOG_ERROR("Couldn't read PPFC register"); return res; } if ((ppfc & 0xFF) == 0x00) { LOG_ERROR("Code region 0 size was pre-programmed at the factory, " "mass erase command won't work."); return ERROR_FAIL; }; res = nrf51_erase_all(chip); if (res != ERROR_OK) { LOG_ERROR("Failed to erase the chip"); nrf51_protect_check(bank); return res; } for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; res = nrf51_protect_check(bank); if (res != ERROR_OK) { LOG_ERROR("Failed to check chip's write protection"); return res; } res = get_flash_bank_by_addr(target, NRF51_UICR_BASE, true, &bank); if (res != ERROR_OK) return res; bank->sectors[0].is_erased = 1; return ERROR_OK; } static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size) { int res; struct nrf51_info *chip; res = nrf51_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; static struct { const uint32_t address; uint32_t value; } ficr[] = { { .address = NRF51_FICR_CODEPAGESIZE }, { .address = NRF51_FICR_CODESIZE }, { .address = NRF51_FICR_CLENR0 }, { .address = NRF51_FICR_PPFC }, { .address = NRF51_FICR_NUMRAMBLOCK }, { .address = NRF51_FICR_SIZERAMBLOCK0 }, { .address = NRF51_FICR_SIZERAMBLOCK1 }, { .address = NRF51_FICR_SIZERAMBLOCK2 }, { .address = NRF51_FICR_SIZERAMBLOCK3 }, { .address = NRF51_FICR_CONFIGID }, { .address = NRF51_FICR_DEVICEID0 }, { .address = NRF51_FICR_DEVICEID1 }, { .address = NRF51_FICR_ER0 }, { .address = NRF51_FICR_ER1 }, { .address = NRF51_FICR_ER2 }, { .address = NRF51_FICR_ER3 }, { .address = NRF51_FICR_IR0 }, { .address = NRF51_FICR_IR1 }, { .address = NRF51_FICR_IR2 }, { .address = NRF51_FICR_IR3 }, { .address = NRF51_FICR_DEVICEADDRTYPE }, { .address = NRF51_FICR_DEVICEADDR0 }, { .address = NRF51_FICR_DEVICEADDR1 }, { .address = NRF51_FICR_OVERRIDEN }, { .address = NRF51_FICR_NRF_1MBIT0 }, { .address = NRF51_FICR_NRF_1MBIT1 }, { .address = NRF51_FICR_NRF_1MBIT2 }, { .address = NRF51_FICR_NRF_1MBIT3 }, { .address = NRF51_FICR_NRF_1MBIT4 }, { .address = NRF51_FICR_BLE_1MBIT0 }, { .address = NRF51_FICR_BLE_1MBIT1 }, { .address = NRF51_FICR_BLE_1MBIT2 }, { .address = NRF51_FICR_BLE_1MBIT3 }, { .address = NRF51_FICR_BLE_1MBIT4 }, }, uicr[] = { { .address = NRF51_UICR_CLENR0, }, { .address = NRF51_UICR_RBPCONF }, { .address = NRF51_UICR_XTALFREQ }, { .address = NRF51_UICR_FWID }, }; for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) { res = target_read_u32(chip->target, ficr[i].address, &ficr[i].value); if (res != ERROR_OK) { LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address); return res; } } for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) { res = target_read_u32(chip->target, uicr[i].address, &uicr[i].value); if (res != ERROR_OK) { LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address); return res; } } snprintf(buf, buf_size, "\n[factory information control block]\n\n" "code page size: %"PRIu32"B\n" "code memory size: %"PRIu32"kB\n" "code region 0 size: %"PRIu32"kB\n" "pre-programmed code: %s\n" "number of ram blocks: %"PRIu32"\n" "ram block 0 size: %"PRIu32"B\n" "ram block 1 size: %"PRIu32"B\n" "ram block 2 size: %"PRIu32"B\n" "ram block 3 size: %"PRIu32 "B\n" "config id: %" PRIx32 "\n" "device id: 0x%"PRIx32"%08"PRIx32"\n" "encryption root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n" "identity root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n" "device address type: 0x%"PRIx32"\n" "device address: 0x%"PRIx32"%08"PRIx32"\n" "override enable: %"PRIx32"\n" "NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n" "BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n" "\n[user information control block]\n\n" "code region 0 size: %"PRIu32"kB\n" "read back protection configuration: %"PRIx32"\n" "reset value for XTALFREQ: %"PRIx32"\n" "firmware id: 0x%04"PRIx32, ficr[0].value, ficr[1].value, (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024, ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present", ficr[4].value, ficr[5].value, (ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value, (ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value, (ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value, ficr[9].value, ficr[10].value, ficr[11].value, ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value, ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value, ficr[20].value, ficr[21].value, ficr[22].value, ficr[23].value, ficr[24].value, ficr[25].value, ficr[26].value, ficr[27].value, ficr[28].value, ficr[29].value, ficr[30].value, ficr[31].value, ficr[32].value, ficr[33].value, (uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024, uicr[1].value & 0xFFFF, uicr[2].value & 0xFF, uicr[3].value & 0xFFFF); return ERROR_OK; } static const struct command_registration nrf51_exec_command_handlers[] = { { .name = "mass_erase", .handler = nrf51_handle_mass_erase_command, .mode = COMMAND_EXEC, .help = "Erase all flash contents of the chip.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration nrf51_command_handlers[] = { { .name = "nrf51", .mode = COMMAND_ANY, .help = "nrf51 flash command group", .usage = "", .chain = nrf51_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver nrf51_flash = { .name = "nrf51", .commands = nrf51_command_handlers, .flash_bank_command = nrf51_flash_bank_command, .info = nrf51_info, .erase = nrf51_erase, .protect = nrf51_protect, .write = nrf51_write, .read = default_flash_read, .probe = nrf51_probe, .auto_probe = nrf51_auto_probe, .erase_check = default_flash_blank_check, .protect_check = nrf51_protect_check, }; openocd-0.9.0/src/flash/nor/lpc2000.c0000644000175000017500000013026512516456302014011 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius * * didele.deze@gmail.com * * * * LPC1100 variant and auto-probing support Copyright (C) 2014 * * by Cosmin Gorgovan cosmin [at] linux-geek [dot] org * * * * LPC800/LPC1500/LPC54100 support Copyright (C) 2013/2014 * * by Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /** * @file * flash programming support for NXP LPC8xx,LPC1xxx,LPC4xxx,LP5410x and LPC2xxx devices. * * @todo Provide a way to update CCLK after declaring the flash bank. The value which is correct after chip reset will * rarely still work right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz). */ /* * currently supported devices: * variant 1 (lpc2000_v1): * - 2104 | 5 | 6 * - 2114 | 9 * - 2124 | 9 * - 2194 * - 2212 | 4 * - 2292 | 4 * * variant 2 (lpc2000_v2): * - 213x * - 214x * - 2101 | 2 | 3 * - 2364 | 6 | 8 * - 2378 * * lpc1700: * - 175x * - 176x (tested with LPC1768) * - 177x * - 178x (tested with LPC1788) * * lpc4000: (lpc1700's alias) * - 407x * - 408x (tested with LPC4088) * * lpc4300: (also available as lpc1800 - alias) * - 43x2 | 3 | 5 | 7 (tested with LPC4337/LPC4357) * - 18x2 | 3 | 5 | 7 * * lpc800: * - 810 | 1 | 2 (tested with LPC810/LPC811/LPC812) * - 822 | 4 (tested with LPC824) * * lpc1100: * - 11xx * - 11Axx * - 11Cxx * - 11Dxx * - 11Exx * - 11Uxx (tested with LPC11U34) * - 131x * - 134x * * lpc1500: * - 15x7 | 8 | 9 (tested with LPC1549) * * lpc54100: * - 54101 | 2 (tested with LPC54102) * * The auto variant auto-detects parts from the following series: * - 11xx * - 11Axx * - 11Cxx * - 11Dxx * - 11Exx * - 11Uxx * - 131x * - 134x * - 175x * - 176x * - 177x * - 178x * - 407x * - 408x * - 81x * - 82x */ /* Part IDs for autodetection */ /* A script which can automatically extract part ids from user manuals is available here: * https://github.com/lgeek/lpc_part_ids */ #define LPC1110_1 0x0A07102B #define LPC1110_2 0x1A07102B #define LPC1111_002_1 0x0A16D02B #define LPC1111_002_2 0x1A16D02B #define LPC1111_101_1 0x041E502B #define LPC1111_101_2 0x2516D02B #define LPC1111_103_1 0x00010013 #define LPC1111_201_1 0x0416502B #define LPC1111_201_2 0x2516902B #define LPC1111_203_1 0x00010012 #define LPC1112_101_1 0x042D502B #define LPC1112_101_2 0x2524D02B #define LPC1112_102_1 0x0A24902B #define LPC1112_102_2 0x1A24902B #define LPC1112_103_1 0x00020023 #define LPC1112_201_1 0x0425502B #define LPC1112_201_2 0x2524902B #define LPC1112_203_1 0x00020022 #define LPC1113_201_1 0x0434502B #define LPC1113_201_2 0x2532902B #define LPC1113_203_1 0x00030032 #define LPC1113_301_1 0x0434102B #define LPC1113_301_2 0x2532102B #define LPC1113_303_1 0x00030030 #define LPC1114_102_1 0x0A40902B #define LPC1114_102_2 0x1A40902B #define LPC1114_201_1 0x0444502B #define LPC1114_201_2 0x2540902B #define LPC1114_203_1 0x00040042 #define LPC1114_301_1 0x0444102B #define LPC1114_301_2 0x2540102B #define LPC1114_303_1 0x00040040 #define LPC1114_323_1 0x00040060 #define LPC1114_333_1 0x00040070 #define LPC1115_303_1 0x00050080 #define LPC11A02_1 0x4D4C802B #define LPC11A04_1 0x4D80002B #define LPC11A11_001_1 0x455EC02B #define LPC11A12_101_1 0x4574802B #define LPC11A13_201_1 0x458A402B #define LPC11A14_301_1 0x35A0002B #define LPC11A14_301_2 0x45A0002B #define LPC11C12_301_1 0x1421102B #define LPC11C14_301_1 0x1440102B #define LPC11C22_301_1 0x1431102B #define LPC11C24_301_1 0x1430102B #define LPC11E11_101 0x293E902B #define LPC11E12_201 0x2954502B #define LPC11E13_301 0x296A102B #define LPC11E14_401 0x2980102B #define LPC11E36_501 0x00009C41 #define LPC11E37_401 0x00007C45 #define LPC11E37_501 0x00007C41 #define LPC11U12_201_1 0x095C802B #define LPC11U12_201_2 0x295C802B #define LPC11U13_201_1 0x097A802B #define LPC11U13_201_2 0x297A802B #define LPC11U14_201_1 0x0998802B #define LPC11U14_201_2 0x2998802B #define LPC11U23_301 0x2972402B #define LPC11U24_301 0x2988402B #define LPC11U24_401 0x2980002B #define LPC11U34_311 0x0003D440 #define LPC11U34_421 0x0001CC40 #define LPC11U35_401 0x0001BC40 #define LPC11U35_501 0x0000BC40 #define LPC11U36_401 0x00019C40 #define LPC11U37_401 0x00017C40 #define LPC11U37H_401 0x00007C44 #define LPC11U37_501 0x00007C40 #define LPC11E66 0x0000DCC1 #define LPC11E67 0x0000BC81 #define LPC11E68 0x00007C01 #define LPC11U66 0x0000DCC8 #define LPC11U67_1 0x0000BC88 #define LPC11U67_2 0x0000BC80 #define LPC11U68_1 0x00007C08 #define LPC11U68_2 0x00007C00 #define LPC1311 0x2C42502B #define LPC1311_1 0x1816902B #define LPC1313 0x2C40102B #define LPC1313_1 0x1830102B #define LPC1315 0x3A010523 #define LPC1316 0x1A018524 #define LPC1317 0x1A020525 #define LPC1342 0x3D01402B #define LPC1343 0x3D00002B #define LPC1345 0x28010541 #define LPC1346 0x08018542 #define LPC1347 0x08020543 #define LPC1751_1 0x25001110 #define LPC1751_2 0x25001118 #define LPC1752 0x25001121 #define LPC1754 0x25011722 #define LPC1756 0x25011723 #define LPC1758 0x25013F37 #define LPC1759 0x25113737 #define LPC1763 0x26012033 #define LPC1764 0x26011922 #define LPC1765 0x26013733 #define LPC1766 0x26013F33 #define LPC1767 0x26012837 #define LPC1768 0x26013F37 #define LPC1769 0x26113F37 #define LPC1774 0x27011132 #define LPC1776 0x27191F43 #define LPC1777 0x27193747 #define LPC1778 0x27193F47 #define LPC1785 0x281D1743 #define LPC1786 0x281D1F43 #define LPC1787 0x281D3747 #define LPC1788 0x281D3F47 #define LPC4072 0x47011121 #define LPC4074 0x47011132 #define LPC4076 0x47191F43 #define LPC4078 0x47193F47 #define LPC4088 0x481D3F47 #define LPC810_021 0x00008100 #define LPC811_001 0x00008110 #define LPC812_101 0x00008120 #define LPC812_101_1 0x00008121 #define LPC812_101_2 0x00008122 #define LPC812_101_3 0x00008123 #define LPC822_101 0x00008221 #define LPC822_101_1 0x00008222 #define LPC824_201 0x00008241 #define LPC824_201_1 0x00008242 #define IAP_CODE_LEN 0x34 typedef enum { lpc2000_v1, lpc2000_v2, lpc1700, lpc4300, lpc800, lpc1100, lpc1500, lpc54100, lpc_auto, } lpc2000_variant; struct lpc2000_flash_bank { lpc2000_variant variant; uint32_t cclk; int cmd51_dst_boundary; int calc_checksum; uint32_t cmd51_max_buffer; int checksum_vector; uint32_t iap_max_stack; uint32_t lpc4300_bank; bool probed; }; enum lpc2000_status_codes { LPC2000_CMD_SUCCESS = 0, LPC2000_INVALID_COMMAND = 1, LPC2000_SRC_ADDR_ERROR = 2, LPC2000_DST_ADDR_ERROR = 3, LPC2000_SRC_ADDR_NOT_MAPPED = 4, LPC2000_DST_ADDR_NOT_MAPPED = 5, LPC2000_COUNT_ERROR = 6, LPC2000_INVALID_SECTOR = 7, LPC2000_SECTOR_NOT_BLANK = 8, LPC2000_SECTOR_NOT_PREPARED = 9, LPC2000_COMPARE_ERROR = 10, LPC2000_BUSY = 11, LPC2000_PARAM_ERROR = 12, LPC2000_ADDR_ERROR = 13, LPC2000_ADDR_NOT_MAPPED = 14, LPC2000_CMD_NOT_LOCKED = 15, LPC2000_INVALID_CODE = 16, LPC2000_INVALID_BAUD_RATE = 17, LPC2000_INVALID_STOP_BIT = 18, LPC2000_CRP_ENABLED = 19, LPC2000_INVALID_FLASH_UNIT = 20, LPC2000_USER_CODE_CHECKSUM = 21, LCP2000_ERROR_SETTING_ACTIVE_PARTITION = 22, }; static int lpc2000_build_sector_list(struct flash_bank *bank) { struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; uint32_t offset = 0; /* default to a 4096 write buffer */ lpc2000_info->cmd51_max_buffer = 4096; if (lpc2000_info->variant == lpc2000_v1) { lpc2000_info->cmd51_dst_boundary = 512; lpc2000_info->checksum_vector = 5; lpc2000_info->iap_max_stack = 128; /* variant 1 has different layout for 128kb and 256kb flashes */ if (bank->size == 128 * 1024) { bank->num_sectors = 16; bank->sectors = malloc(sizeof(struct flash_sector) * 16); for (int i = 0; i < 16; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 8 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (bank->size == 256 * 1024) { bank->num_sectors = 18; bank->sectors = malloc(sizeof(struct flash_sector) * 18); for (int i = 0; i < 8; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 8 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } for (int i = 8; i < 10; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 64 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } for (int i = 10; i < 18; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 8 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else { LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } } else if (lpc2000_info->variant == lpc2000_v2) { lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->checksum_vector = 5; lpc2000_info->iap_max_stack = 128; /* variant 2 has a uniform layout, only number of sectors differs */ switch (bank->size) { case 4 * 1024: lpc2000_info->cmd51_max_buffer = 1024; bank->num_sectors = 1; break; case 8 * 1024: lpc2000_info->cmd51_max_buffer = 1024; bank->num_sectors = 2; break; case 16 * 1024: bank->num_sectors = 4; break; case 32 * 1024: bank->num_sectors = 8; break; case 64 * 1024: bank->num_sectors = 9; break; case 128 * 1024: bank->num_sectors = 11; break; case 256 * 1024: bank->num_sectors = 15; break; case 500 * 1024: bank->num_sectors = 27; break; case 512 * 1024: case 504 * 1024: bank->num_sectors = 28; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); break; } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { if (i < 8) { bank->sectors[i].offset = offset; bank->sectors[i].size = 4 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } else if (i < 22) { bank->sectors[i].offset = offset; bank->sectors[i].size = 32 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } else if (i < 28) { bank->sectors[i].offset = offset; bank->sectors[i].size = 4 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } } else if (lpc2000_info->variant == lpc1700) { lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 128; switch (bank->size) { case 4 * 1024: lpc2000_info->cmd51_max_buffer = 256; bank->num_sectors = 1; break; case 8 * 1024: lpc2000_info->cmd51_max_buffer = 512; bank->num_sectors = 2; break; case 16 * 1024: lpc2000_info->cmd51_max_buffer = 512; bank->num_sectors = 4; break; case 32 * 1024: lpc2000_info->cmd51_max_buffer = 1024; bank->num_sectors = 8; break; case 64 * 1024: bank->num_sectors = 16; break; case 128 * 1024: bank->num_sectors = 18; break; case 256 * 1024: bank->num_sectors = 22; break; case 512 * 1024: bank->num_sectors = 30; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx/LPC40xx devices */ bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (lpc2000_info->variant == lpc4300) { lpc2000_info->cmd51_dst_boundary = 512; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 208; switch (bank->size) { case 256 * 1024: bank->num_sectors = 11; break; case 384 * 1024: bank->num_sectors = 13; break; case 512 * 1024: bank->num_sectors = 15; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* sectors 0-7 are 8kB-sized, 8 and above are 64kB-sized for LPC43xx devices */ bank->sectors[i].size = (i < 8) ? 8 * 1024 : 64 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (lpc2000_info->variant == lpc800) { lpc2000_info->cmd51_dst_boundary = 64; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 208; /* 148byte for LPC81x,208byte for LPC82x. */ lpc2000_info->cmd51_max_buffer = 256; /* smallest MCU in the series, LPC810, has 1 kB of SRAM */ switch (bank->size) { case 4 * 1024: bank->num_sectors = 4; break; case 8 * 1024: bank->num_sectors = 8; break; case 16 * 1024: bank->num_sectors = 16; break; case 32 * 1024: lpc2000_info->cmd51_max_buffer = 1024; /* For LPC824, has 8kB of SRAM */ bank->num_sectors = 32; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* all sectors are 1kB-sized for LPC8xx devices */ bank->sectors[i].size = 1 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (lpc2000_info->variant == lpc1100) { lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 128; if ((bank->size % (4 * 1024)) != 0) { LOG_ERROR("BUG: unknown bank->size encountered,\nLPC1100 flash size must be a multiple of 4096"); exit(-1); } lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */ bank->num_sectors = bank->size / 4096; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* all sectors are 4kB-sized */ bank->sectors[i].size = 4 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (lpc2000_info->variant == lpc1500) { lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 128; switch (bank->size) { case 64 * 1024: bank->num_sectors = 16; break; case 128 * 1024: bank->num_sectors = 32; break; case 256 * 1024: bank->num_sectors = 64; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* all sectors are 4kB-sized */ bank->sectors[i].size = 4 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else if (lpc2000_info->variant == lpc54100) { lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->checksum_vector = 7; lpc2000_info->iap_max_stack = 128; switch (bank->size) { case 256 * 1024: bank->num_sectors = 8; break; case 512 * 1024: bank->num_sectors = 16; break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); } bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; /* all sectors are 32kB-sized */ bank->sectors[i].size = 32 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } } else { LOG_ERROR("BUG: unknown lpc2000_info->variant encountered"); exit(-1); } return ERROR_OK; } /* this function allocates and initializes working area used for IAP algorithm * uses 52 + max IAP stack bytes working area * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait) * 0x8 to 0x1f: command parameter table (1+5 words) * 0x20 to 0x33: command result table (1+4 words) * 0x34 to 0xb3|0x104: stack * (128b needed for lpc1xxx/2000/5410x, 208b for lpc43xx/lpc82x and 148b for lpc81x) */ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working_area **iap_working_area) { struct target *target = bank->target; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; if (target_alloc_working_area(target, IAP_CODE_LEN + lpc2000_info->iap_max_stack, iap_working_area) != ERROR_OK) { LOG_ERROR("no working area specified, can't write LPC2000 internal flash"); return ERROR_FLASH_OPERATION_FAILED; } uint8_t jump_gate[8]; /* write IAP code to working area */ switch (lpc2000_info->variant) { case lpc800: case lpc1100: case lpc1500: case lpc1700: case lpc4300: case lpc54100: case lpc_auto: target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12)); target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0)); break; case lpc2000_v1: case lpc2000_v2: target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12)); target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0)); break; default: LOG_ERROR("BUG: unknown lpc2000_info->variant encountered"); exit(-1); } int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate); if (retval != ERROR_OK) { LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", (*iap_working_area)->address); target_free_working_area(target, *iap_working_area); } return retval; } /* call LPC8xx/LPC1xxx/LPC4xxx/LPC5410x/LPC2000 IAP function */ static int lpc2000_iap_call(struct flash_bank *bank, struct working_area *iap_working_area, int code, uint32_t param_table[5], uint32_t result_table[4]) { struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; struct target *target = bank->target; struct arm_algorithm arm_algo; /* for LPC2000 */ struct armv7m_algorithm armv7m_info; /* for LPC8xx/LPC1xxx/LPC4xxx/LPC5410x */ uint32_t iap_entry_point = 0; /* to make compiler happier */ switch (lpc2000_info->variant) { case lpc800: case lpc1100: case lpc1700: case lpc_auto: armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; iap_entry_point = 0x1fff1ff1; break; case lpc1500: case lpc54100: armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; iap_entry_point = 0x03000205; break; case lpc2000_v1: case lpc2000_v2: arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; iap_entry_point = 0x7ffffff1; break; case lpc4300: armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; /* read out IAP entry point from ROM driver table at 0x10400100 */ target_read_u32(target, 0x10400100, &iap_entry_point); break; default: LOG_ERROR("BUG: unknown lpc2000->variant encountered"); exit(-1); } struct mem_param mem_params[2]; /* command parameter table */ init_mem_param(&mem_params[0], iap_working_area->address + 8, 6 * 4, PARAM_OUT); target_buffer_set_u32(target, mem_params[0].value, code); target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]); target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]); target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]); target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]); target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]); struct reg_param reg_params[5]; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, iap_working_area->address + 0x08); /* command result table */ init_mem_param(&mem_params[1], iap_working_area->address + 0x20, 5 * 4, PARAM_IN); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, iap_working_area->address + 0x20); /* IAP entry point */ init_reg_param(®_params[2], "r12", 32, PARAM_OUT); buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point); switch (lpc2000_info->variant) { case lpc800: case lpc1100: case lpc1500: case lpc1700: case lpc4300: case lpc54100: case lpc_auto: /* IAP stack */ init_reg_param(®_params[3], "sp", 32, PARAM_OUT); buf_set_u32(reg_params[3].value, 0, 32, iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack); /* return address */ init_reg_param(®_params[4], "lr", 32, PARAM_OUT); buf_set_u32(reg_params[4].value, 0, 32, (iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */ target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address, 0, 10000, &armv7m_info); break; case lpc2000_v1: case lpc2000_v2: /* IAP stack */ init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT); buf_set_u32(reg_params[3].value, 0, 32, iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack); /* return address */ init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT); buf_set_u32(reg_params[4].value, 0, 32, iap_working_area->address + 0x04); target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address, iap_working_area->address + 0x4, 10000, &arm_algo); break; default: LOG_ERROR("BUG: unknown lpc2000->variant encountered"); exit(-1); } int status_code = target_buffer_get_u32(target, mem_params[1].value); result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04); result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08); result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c); result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10); LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ") completed with result = %8.8x", code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code); destroy_mem_param(&mem_params[0]); destroy_mem_param(&mem_params[1]); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return status_code; } static int lpc2000_iap_blank_check(struct flash_bank *bank, int first, int last) { if ((first < 0) || (last >= bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; uint32_t param_table[5] = {0}; uint32_t result_table[4]; struct working_area *iap_working_area; int retval = lpc2000_iap_working_area_init(bank, &iap_working_area); if (retval != ERROR_OK) return retval; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; if (lpc2000_info->variant == lpc4300) param_table[2] = lpc2000_info->lpc4300_bank; for (int i = first; i <= last && retval == ERROR_OK; i++) { /* check single sector */ param_table[0] = param_table[1] = i; int status_code = lpc2000_iap_call(bank, iap_working_area, 53, param_table, result_table); switch (status_code) { case ERROR_FLASH_OPERATION_FAILED: retval = ERROR_FLASH_OPERATION_FAILED; break; case LPC2000_CMD_SUCCESS: bank->sectors[i].is_erased = 1; break; case LPC2000_SECTOR_NOT_BLANK: bank->sectors[i].is_erased = 0; break; case LPC2000_INVALID_SECTOR: bank->sectors[i].is_erased = 0; break; case LPC2000_BUSY: retval = ERROR_FLASH_BUSY; break; default: LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code); exit(-1); } } struct target *target = bank->target; target_free_working_area(target, iap_working_area); return retval; } /* * flash bank lpc2000 0 0 [calc_checksum] */ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command) { if (CMD_ARGC < 8) return ERROR_COMMAND_SYNTAX_ERROR; struct lpc2000_flash_bank *lpc2000_info = calloc(1, sizeof(*lpc2000_info)); lpc2000_info->probed = false; bank->driver_priv = lpc2000_info; if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) { lpc2000_info->variant = lpc2000_v1; } else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) { lpc2000_info->variant = lpc2000_v2; } else if (strcmp(CMD_ARGV[6], "lpc1700") == 0 || strcmp(CMD_ARGV[6], "lpc4000") == 0) { lpc2000_info->variant = lpc1700; } else if (strcmp(CMD_ARGV[6], "lpc1800") == 0 || strcmp(CMD_ARGV[6], "lpc4300") == 0) { lpc2000_info->variant = lpc4300; } else if (strcmp(CMD_ARGV[6], "lpc800") == 0) { lpc2000_info->variant = lpc800; } else if (strcmp(CMD_ARGV[6], "lpc1100") == 0) { lpc2000_info->variant = lpc1100; } else if (strcmp(CMD_ARGV[6], "lpc1500") == 0) { lpc2000_info->variant = lpc1500; } else if (strcmp(CMD_ARGV[6], "lpc54100") == 0) { lpc2000_info->variant = lpc54100; } else if (strcmp(CMD_ARGV[6], "auto") == 0) { lpc2000_info->variant = lpc_auto; } else { LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]); free(lpc2000_info); return ERROR_FLASH_BANK_INVALID; } /* Maximum size required for the IAP stack. This value only gets used when probing, only for auto, lpc1100 and lpc1700. We use the maximum size for any part supported by the driver(!) to be safe in case the auto variant is mistakenly used on a MCU from one of the series for which we don't support auto-probing. */ lpc2000_info->iap_max_stack = 208; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], lpc2000_info->cclk); lpc2000_info->calc_checksum = 0; uint32_t temp_base = 0; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], temp_base); if (temp_base >= 0x1B000000) lpc2000_info->lpc4300_bank = 1; /* bank B */ else lpc2000_info->lpc4300_bank = 0; /* bank A */ if (CMD_ARGC >= 9) { if (strcmp(CMD_ARGV[8], "calc_checksum") == 0) lpc2000_info->calc_checksum = 1; } return ERROR_OK; } static int lpc2000_erase(struct flash_bank *bank, int first, int last) { if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; uint32_t param_table[5] = {0}; param_table[0] = first; param_table[1] = last; if (lpc2000_info->variant == lpc4300) param_table[2] = lpc2000_info->lpc4300_bank; else param_table[2] = lpc2000_info->cclk; uint32_t result_table[4]; struct working_area *iap_working_area; int retval = lpc2000_iap_working_area_init(bank, &iap_working_area); if (retval != ERROR_OK) return retval; if (lpc2000_info->variant == lpc4300) /* Init IAP Anyway */ lpc2000_iap_call(bank, iap_working_area, 49, param_table, result_table); /* Prepare sectors */ int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table); switch (status_code) { case ERROR_FLASH_OPERATION_FAILED: retval = ERROR_FLASH_OPERATION_FAILED; break; case LPC2000_CMD_SUCCESS: break; case LPC2000_INVALID_SECTOR: retval = ERROR_FLASH_SECTOR_INVALID; break; default: LOG_WARNING("lpc2000 prepare sectors returned %i", status_code); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (retval == ERROR_OK) { /* Erase sectors */ param_table[2] = lpc2000_info->cclk; if (lpc2000_info->variant == lpc4300) param_table[3] = lpc2000_info->lpc4300_bank; status_code = lpc2000_iap_call(bank, iap_working_area, 52, param_table, result_table); switch (status_code) { case ERROR_FLASH_OPERATION_FAILED: retval = ERROR_FLASH_OPERATION_FAILED; break; case LPC2000_CMD_SUCCESS: break; case LPC2000_INVALID_SECTOR: retval = ERROR_FLASH_SECTOR_INVALID; break; default: LOG_WARNING("lpc2000 erase sectors returned %i", status_code); retval = ERROR_FLASH_OPERATION_FAILED; break; } } struct target *target = bank->target; target_free_working_area(target, iap_working_area); return retval; } static int lpc2000_protect(struct flash_bank *bank, int set, int first, int last) { /* can't protect/unprotect on the lpc2000 */ return ERROR_OK; } static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; uint32_t dst_min_alignment = lpc2000_info->cmd51_dst_boundary; if (offset % dst_min_alignment) { LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } int first_sector = 0; int last_sector = 0; for (int i = 0; i < bank->num_sectors; i++) { if (offset >= bank->sectors[i].offset) first_sector = i; if (offset + DIV_ROUND_UP(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset) last_sector = i; } LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector); /* check if exception vectors should be flashed */ if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) { assert(lpc2000_info->checksum_vector < 8); uint32_t checksum = 0; for (int i = 0; i < 8; i++) { LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32)); if (i != lpc2000_info->checksum_vector) checksum += buf_get_u32(buffer + (i * 4), 0, 32); } checksum = 0 - checksum; LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum); uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32); if (original_value != checksum) { LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is " "different from calculated vector checksum (0x%8.8" PRIx32 ").", original_value, checksum); LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector " "checksum."); } /* FIXME: WARNING! This code is broken because it modifies the callers buffer in place. */ buf_set_u32((uint8_t *)buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum); } struct working_area *iap_working_area; int retval = lpc2000_iap_working_area_init(bank, &iap_working_area); if (retval != ERROR_OK) return retval; struct working_area *download_area; /* allocate a working area */ if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK) { LOG_ERROR("no working area specified, can't write LPC2000 internal flash"); target_free_working_area(target, iap_working_area); return ERROR_FLASH_OPERATION_FAILED; } uint32_t bytes_remaining = count; uint32_t bytes_written = 0; uint32_t param_table[5] = {0}; uint32_t result_table[4]; if (lpc2000_info->variant == lpc4300) /* Init IAP Anyway */ lpc2000_iap_call(bank, iap_working_area, 49, param_table, result_table); while (bytes_remaining > 0) { uint32_t thisrun_bytes; if (bytes_remaining >= lpc2000_info->cmd51_max_buffer) thisrun_bytes = lpc2000_info->cmd51_max_buffer; else thisrun_bytes = lpc2000_info->cmd51_dst_boundary; /* Prepare sectors */ param_table[0] = first_sector; param_table[1] = last_sector; if (lpc2000_info->variant == lpc4300) param_table[2] = lpc2000_info->lpc4300_bank; else param_table[2] = lpc2000_info->cclk; int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table); switch (status_code) { case ERROR_FLASH_OPERATION_FAILED: retval = ERROR_FLASH_OPERATION_FAILED; break; case LPC2000_CMD_SUCCESS: break; case LPC2000_INVALID_SECTOR: retval = ERROR_FLASH_SECTOR_INVALID; break; default: LOG_WARNING("lpc2000 prepare sectors returned %i", status_code); retval = ERROR_FLASH_OPERATION_FAILED; break; } /* Exit if error occured */ if (retval != ERROR_OK) break; if (bytes_remaining >= thisrun_bytes) { retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written); if (retval != ERROR_OK) { retval = ERROR_FLASH_OPERATION_FAILED; break; } } else { uint8_t *last_buffer = malloc(thisrun_bytes); memcpy(last_buffer, buffer + bytes_written, bytes_remaining); memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining); target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer); free(last_buffer); } LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32, thisrun_bytes, bank->base + offset + bytes_written); /* Write data */ param_table[0] = bank->base + offset + bytes_written; param_table[1] = download_area->address; param_table[2] = thisrun_bytes; param_table[3] = lpc2000_info->cclk; status_code = lpc2000_iap_call(bank, iap_working_area, 51, param_table, result_table); switch (status_code) { case ERROR_FLASH_OPERATION_FAILED: retval = ERROR_FLASH_OPERATION_FAILED; break; case LPC2000_CMD_SUCCESS: break; case LPC2000_INVALID_SECTOR: retval = ERROR_FLASH_SECTOR_INVALID; break; default: LOG_WARNING("lpc2000 returned %i", status_code); retval = ERROR_FLASH_OPERATION_FAILED; break; } /* Exit if error occured */ if (retval != ERROR_OK) break; if (bytes_remaining > thisrun_bytes) bytes_remaining -= thisrun_bytes; else bytes_remaining = 0; bytes_written += thisrun_bytes; } target_free_working_area(target, iap_working_area); target_free_working_area(target, download_area); return retval; } static int get_lpc2000_part_id(struct flash_bank *bank, uint32_t *part_id) { if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t param_table[5] = {0}; uint32_t result_table[4]; struct working_area *iap_working_area; int retval = lpc2000_iap_working_area_init(bank, &iap_working_area); if (retval != ERROR_OK) return retval; /* The status seems to be bogus with the part ID command on some IAP firmwares, so ignore it. */ lpc2000_iap_call(bank, iap_working_area, 54, param_table, result_table); struct target *target = bank->target; target_free_working_area(target, iap_working_area); /* If the result is zero, the command probably didn't work out. */ if (result_table[0] == 0) return LPC2000_INVALID_COMMAND; *part_id = result_table[0]; return LPC2000_CMD_SUCCESS; } static int lpc2000_auto_probe_flash(struct flash_bank *bank) { uint32_t part_id; int retval; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = get_lpc2000_part_id(bank, &part_id); if (retval != LPC2000_CMD_SUCCESS) { LOG_ERROR("Could not get part ID"); return retval; } switch (part_id) { case LPC1110_1: case LPC1110_2: lpc2000_info->variant = lpc1100; bank->size = 4 * 1024; break; case LPC1111_002_1: case LPC1111_002_2: case LPC1111_101_1: case LPC1111_101_2: case LPC1111_103_1: case LPC1111_201_1: case LPC1111_201_2: case LPC1111_203_1: case LPC11A11_001_1: case LPC11E11_101: case LPC1311: case LPC1311_1: lpc2000_info->variant = lpc1100; bank->size = 8 * 1024; break; case LPC1112_101_1: case LPC1112_101_2: case LPC1112_102_1: case LPC1112_102_2: case LPC1112_103_1: case LPC1112_201_1: case LPC1112_201_2: case LPC1112_203_1: case LPC11A02_1: case LPC11C12_301_1: case LPC11C22_301_1: case LPC11A12_101_1: case LPC11E12_201: case LPC11U12_201_1: case LPC11U12_201_2: case LPC1342: lpc2000_info->variant = lpc1100; bank->size = 16 * 1024; break; case LPC1113_201_1: case LPC1113_201_2: case LPC1113_203_1: case LPC1113_301_1: case LPC1113_301_2: case LPC1113_303_1: case LPC11A13_201_1: case LPC11E13_301: case LPC11U13_201_1: case LPC11U13_201_2: case LPC11U23_301: lpc2000_info->variant = lpc1100; bank->size = 24 * 1024; break; case LPC1114_102_1: case LPC1114_102_2: case LPC1114_201_1: case LPC1114_201_2: case LPC1114_203_1: case LPC1114_301_1: case LPC1114_301_2: case LPC1114_303_1: case LPC11A04_1: case LPC11A14_301_1: case LPC11A14_301_2: case LPC11C14_301_1: case LPC11C24_301_1: case LPC11E14_401: case LPC11U14_201_1: case LPC11U14_201_2: case LPC11U24_301: case LPC11U24_401: case LPC1313: case LPC1313_1: case LPC1315: case LPC1343: case LPC1345: lpc2000_info->variant = lpc1100; bank->size = 32 * 1024; break; case LPC1751_1: case LPC1751_2: lpc2000_info->variant = lpc1700; bank->size = 32 * 1024; break; case LPC11U34_311: lpc2000_info->variant = lpc1100; bank->size = 40 * 1024; break; case LPC1114_323_1: case LPC11U34_421: case LPC1316: case LPC1346: lpc2000_info->variant = lpc1100; bank->size = 48 * 1024; break; case LPC1114_333_1: lpc2000_info->variant = lpc1100; bank->size = 56 * 1024; break; case LPC1115_303_1: case LPC11U35_401: case LPC11U35_501: case LPC11E66: case LPC11U66: case LPC1317: case LPC1347: lpc2000_info->variant = lpc1100; bank->size = 64 * 1024; break; case LPC1752: case LPC4072: lpc2000_info->variant = lpc1700; bank->size = 64 * 1024; break; case LPC11E36_501: case LPC11U36_401: lpc2000_info->variant = lpc1100; bank->size = 96 * 1024; break; case LPC11E37_401: case LPC11E37_501: case LPC11U37_401: case LPC11U37H_401: case LPC11U37_501: case LPC11E67: case LPC11E68: case LPC11U67_1: case LPC11U67_2: lpc2000_info->variant = lpc1100; bank->size = 128 * 1024; break; case LPC1754: case LPC1764: case LPC1774: case LPC4074: lpc2000_info->variant = lpc1700; bank->size = 128 * 1024; break; case LPC11U68_1: case LPC11U68_2: lpc2000_info->variant = lpc1100; bank->size = 256 * 1024; break; case LPC1756: case LPC1763: case LPC1765: case LPC1766: case LPC1776: case LPC1785: case LPC1786: case LPC4076: lpc2000_info->variant = lpc1700; bank->size = 256 * 1024; break; case LPC1758: case LPC1759: case LPC1767: case LPC1768: case LPC1769: case LPC1777: case LPC1778: case LPC1787: case LPC1788: case LPC4078: case LPC4088: lpc2000_info->variant = lpc1700; bank->size = 512 * 1024; break; case LPC810_021: lpc2000_info->variant = lpc800; bank->size = 4 * 1024; break; case LPC811_001: lpc2000_info->variant = lpc800; bank->size = 8 * 1024; break; case LPC812_101: case LPC812_101_1: case LPC812_101_2: case LPC812_101_3: case LPC822_101: case LPC822_101_1: lpc2000_info->variant = lpc800; bank->size = 16 * 1024; break; case LPC824_201: case LPC824_201_1: lpc2000_info->variant = lpc800; bank->size = 32 * 1024; break; default: LOG_ERROR("BUG: unknown Part ID encountered: 0x%" PRIx32, part_id); exit(-1); } return ERROR_OK; } static int lpc2000_probe(struct flash_bank *bank) { int status; uint32_t part_id; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; if (!lpc2000_info->probed) { if (lpc2000_info->variant == lpc_auto) { status = lpc2000_auto_probe_flash(bank); if (status != ERROR_OK) return status; } else if (lpc2000_info->variant == lpc1100 || lpc2000_info->variant == lpc1700) { status = get_lpc2000_part_id(bank, &part_id); if (status == LPC2000_CMD_SUCCESS) LOG_INFO("If auto-detection fails for this part, please email " "openocd-devel@lists.sourceforge.net, citing part id 0x%" PRIx32 ".\n", part_id); } lpc2000_build_sector_list(bank); lpc2000_info->probed = true; } return ERROR_OK; } static int lpc2000_erase_check(struct flash_bank *bank) { if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1); } static int lpc2000_protect_check(struct flash_bank *bank) { /* sectors are always protected */ return ERROR_OK; } static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size) { struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz", lpc2000_info->variant, lpc2000_info->cclk); return ERROR_OK; } COMMAND_HANDLER(lpc2000_handle_part_id_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t part_id; int status_code = get_lpc2000_part_id(bank, &part_id); if (status_code != 0x0) { if (status_code == ERROR_FLASH_OPERATION_FAILED) { command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface"); } else command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code); } else command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, part_id); return retval; } static const struct command_registration lpc2000_exec_command_handlers[] = { { .name = "part_id", .handler = lpc2000_handle_part_id_command, .mode = COMMAND_EXEC, .help = "print part id of lpc2000 flash bank ", .usage = "", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration lpc2000_command_handlers[] = { { .name = "lpc2000", .mode = COMMAND_ANY, .help = "lpc2000 flash command group", .usage = "", .chain = lpc2000_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver lpc2000_flash = { .name = "lpc2000", .commands = lpc2000_command_handlers, .flash_bank_command = lpc2000_flash_bank_command, .erase = lpc2000_erase, .protect = lpc2000_protect, .write = lpc2000_write, .read = default_flash_read, .probe = lpc2000_probe, .auto_probe = lpc2000_probe, .erase_check = lpc2000_erase_check, .protect_check = lpc2000_protect_check, .info = get_lpc2000_info, }; openocd-0.9.0/src/flash/nor/lpc2900.c0000644000175000017500000014070412315575360014024 00000000000000/*************************************************************************** * Copyright (C) 2009 by * * Rolf Meeser * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /* 1024 bytes */ #define KiB 1024 /* Some flash constants */ #define FLASH_PAGE_SIZE 512 /* bytes */ #define FLASH_ERASE_TIME 100000 /* microseconds */ #define FLASH_PROGRAM_TIME 1000 /* microseconds */ /* Chip ID / Feature Registers */ #define CHIPID 0xE0000000 /* Chip ID */ #define FEAT0 0xE0000100 /* Chip feature 0 */ #define FEAT1 0xE0000104 /* Chip feature 1 */ #define FEAT2 0xE0000108 /* Chip feature 2 (contains flash size indicator) */ #define FEAT3 0xE000010C /* Chip feature 3 */ #define EXPECTED_CHIPID 0x209CE02B /* Chip ID of all LPC2900 devices */ /* Flash/EEPROM Control Registers */ #define FCTR 0x20200000 /* Flash control */ #define FPTR 0x20200008 /* Flash program-time */ #define FTCTR 0x2020000C /* Flash test control */ #define FBWST 0x20200010 /* Flash bridge wait-state */ #define FCRA 0x2020001C /* Flash clock divider */ #define FMSSTART 0x20200020 /* Flash Built-In Selft Test start address */ #define FMSSTOP 0x20200024 /* Flash Built-In Selft Test stop address */ #define FMS16 0x20200028 /* Flash 16-bit signature */ #define FMSW0 0x2020002C /* Flash 128-bit signature Word 0 */ #define FMSW1 0x20200030 /* Flash 128-bit signature Word 1 */ #define FMSW2 0x20200034 /* Flash 128-bit signature Word 2 */ #define FMSW3 0x20200038 /* Flash 128-bit signature Word 3 */ #define EECMD 0x20200080 /* EEPROM command */ #define EEADDR 0x20200084 /* EEPROM address */ #define EEWDATA 0x20200088 /* EEPROM write data */ #define EERDATA 0x2020008C /* EEPROM read data */ #define EEWSTATE 0x20200090 /* EEPROM wait state */ #define EECLKDIV 0x20200094 /* EEPROM clock divider */ #define EEPWRDWN 0x20200098 /* EEPROM power-down/start */ #define EEMSSTART 0x2020009C /* EEPROM BIST start address */ #define EEMSSTOP 0x202000A0 /* EEPROM BIST stop address */ #define EEMSSIG 0x202000A4 /* EEPROM 24-bit BIST signature */ #define INT_CLR_ENABLE 0x20200FD8 /* Flash/EEPROM interrupt clear enable */ #define INT_SET_ENABLE 0x20200FDC /* Flash/EEPROM interrupt set enable */ #define INT_STATUS 0x20200FE0 /* Flash/EEPROM interrupt status */ #define INT_ENABLE 0x20200FE4 /* Flash/EEPROM interrupt enable */ #define INT_CLR_STATUS 0x20200FE8 /* Flash/EEPROM interrupt clear status */ #define INT_SET_STATUS 0x20200FEC /* Flash/EEPROM interrupt set status */ /* Interrupt sources */ #define INTSRC_END_OF_PROG (1 << 28) #define INTSRC_END_OF_BIST (1 << 27) #define INTSRC_END_OF_RDWR (1 << 26) #define INTSRC_END_OF_MISR (1 << 2) #define INTSRC_END_OF_BURN (1 << 1) #define INTSRC_END_OF_ERASE (1 << 0) /* FCTR bits */ #define FCTR_FS_LOADREQ (1 << 15) #define FCTR_FS_CACHECLR (1 << 14) #define FCTR_FS_CACHEBYP (1 << 13) #define FCTR_FS_PROGREQ (1 << 12) #define FCTR_FS_RLS (1 << 11) #define FCTR_FS_PDL (1 << 10) #define FCTR_FS_PD (1 << 9) #define FCTR_FS_WPB (1 << 7) #define FCTR_FS_ISS (1 << 6) #define FCTR_FS_RLD (1 << 5) #define FCTR_FS_DCR (1 << 4) #define FCTR_FS_WEB (1 << 2) #define FCTR_FS_WRE (1 << 1) #define FCTR_FS_CS (1 << 0) /* FPTR bits */ #define FPTR_EN_T (1 << 15) /* FTCTR bits */ #define FTCTR_FS_BYPASS_R (1 << 29) #define FTCTR_FS_BYPASS_W (1 << 28) /* FMSSTOP bits */ #define FMSSTOP_MISR_START (1 << 17) /* EEMSSTOP bits */ #define EEMSSTOP_STRTBIST (1 << 31) /* Index sector */ #define ISS_CUSTOMER_START1 (0x830) #define ISS_CUSTOMER_END1 (0xA00) #define ISS_CUSTOMER_SIZE1 (ISS_CUSTOMER_END1 - ISS_CUSTOMER_START1) #define ISS_CUSTOMER_NWORDS1 (ISS_CUSTOMER_SIZE1 / 4) #define ISS_CUSTOMER_START2 (0xA40) #define ISS_CUSTOMER_END2 (0xC00) #define ISS_CUSTOMER_SIZE2 (ISS_CUSTOMER_END2 - ISS_CUSTOMER_START2) #define ISS_CUSTOMER_NWORDS2 (ISS_CUSTOMER_SIZE2 / 4) #define ISS_CUSTOMER_SIZE (ISS_CUSTOMER_SIZE1 + ISS_CUSTOMER_SIZE2) /** * Private data for \c lpc2900 flash driver. */ struct lpc2900_flash_bank { /** * This flag is set when the device has been successfully probed. */ bool is_probed; /** * Holds the value read from CHIPID register. * The driver will not load if the chipid doesn't match the expected * value of 0x209CE02B of the LPC2900 family. A probe will only be done * if the chipid does not yet contain the expected value. */ uint32_t chipid; /** * String holding device name. * This string is set by the probe function to the type number of the * device. It takes the form "LPC29xx". */ char *target_name; /** * System clock frequency. * Holds the clock frequency in Hz, as passed by the configuration file * to the flash bank command. */ uint32_t clk_sys_fmc; /** * Flag to indicate that dangerous operations are possible. * This flag can be set by passing the correct password to the * lpc2900 password command. If set, other dangerous commands, * which operate on the index sector, can be executed. */ uint32_t risky; /** * Maximum contiguous block of internal SRAM (bytes). * Autodetected by the driver. Not the total amount of SRAM, only the * the largest \em contiguous block! */ uint32_t max_ram_block; }; static uint32_t lpc2900_wait_status(struct flash_bank *bank, uint32_t mask, int timeout); static void lpc2900_setup(struct flash_bank *bank); static uint32_t lpc2900_is_ready(struct flash_bank *bank); static uint32_t lpc2900_read_security_status(struct flash_bank *bank); static uint32_t lpc2900_run_bist128(struct flash_bank *bank, uint32_t addr_from, uint32_t addr_to, uint32_t signature[4]); static uint32_t lpc2900_address2sector(struct flash_bank *bank, uint32_t offset); static uint32_t lpc2900_calc_tr(uint32_t clock_var, uint32_t time_var); /*********************** Helper functions **************************/ /** * Wait for an event in mask to occur in INT_STATUS. * * Return when an event occurs, or after a timeout. * * @param[in] bank Pointer to the flash bank descriptor * @param[in] mask Mask to be used for INT_STATUS * @param[in] timeout Timeout in ms */ static uint32_t lpc2900_wait_status(struct flash_bank *bank, uint32_t mask, int timeout) { uint32_t int_status; struct target *target = bank->target; do { alive_sleep(1); timeout--; target_read_u32(target, INT_STATUS, &int_status); } while (((int_status & mask) == 0) && (timeout != 0)); if (timeout == 0) { LOG_DEBUG("Timeout!"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } /** * Set up the flash for erase/program operations. * * Enable the flash, and set the correct CRA clock of 66 kHz. * * @param bank Pointer to the flash bank descriptor */ static void lpc2900_setup(struct flash_bank *bank) { uint32_t fcra; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; /* Power up the flash block */ target_write_u32(bank->target, FCTR, FCTR_FS_WEB | FCTR_FS_CS); fcra = (lpc2900_info->clk_sys_fmc / (3 * 66000)) - 1; target_write_u32(bank->target, FCRA, fcra); } /** * Check if device is ready. * * Check if device is ready for flash operation: * Must have been successfully probed. * Must be halted. */ static uint32_t lpc2900_is_ready(struct flash_bank *bank) { struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; if (!lpc2900_info->is_probed) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return ERROR_OK; } /** * Read the status of sector security from the index sector. * * @param bank Pointer to the flash bank descriptor */ static uint32_t lpc2900_read_security_status(struct flash_bank *bank) { uint32_t status = lpc2900_is_ready(bank); if (status != ERROR_OK) return status; struct target *target = bank->target; /* Enable ISS access */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB | FCTR_FS_ISS); /* Read the relevant block of memory from the ISS sector */ uint32_t iss_secured_field[0x230/16][4]; target_read_memory(target, bank->base + 0xC00, 4, 0x230/4, (uint8_t *)iss_secured_field); /* Disable ISS access */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); /* Check status of each sector. Note that the sector numbering in the LPC2900 * is different from the logical sector numbers used in OpenOCD! * Refer to the user manual for details. * * All zeros (16x 0x00) are treated as a secured sector (is_protected = 1) * All ones (16x 0xFF) are treated as a non-secured sector (is_protected = 0) * Anything else is undefined (is_protected = -1). This is treated as * a protected sector! */ int sector; int index_t; for (sector = 0; sector < bank->num_sectors; sector++) { /* Convert logical sector number to physical sector number */ if (sector <= 4) index_t = sector + 11; else if (sector <= 7) index_t = sector + 27; else index_t = sector - 8; bank->sectors[sector].is_protected = -1; if ((iss_secured_field[index_t][0] == 0x00000000) && (iss_secured_field[index_t][1] == 0x00000000) && (iss_secured_field[index_t][2] == 0x00000000) && (iss_secured_field[index_t][3] == 0x00000000)) bank->sectors[sector].is_protected = 1; if ((iss_secured_field[index_t][0] == 0xFFFFFFFF) && (iss_secured_field[index_t][1] == 0xFFFFFFFF) && (iss_secured_field[index_t][2] == 0xFFFFFFFF) && (iss_secured_field[index_t][3] == 0xFFFFFFFF)) bank->sectors[sector].is_protected = 0; } return ERROR_OK; } /** * Use BIST to calculate a 128-bit hash value over a range of flash. * * @param bank Pointer to the flash bank descriptor * @param addr_from * @param addr_to * @param signature */ static uint32_t lpc2900_run_bist128(struct flash_bank *bank, uint32_t addr_from, uint32_t addr_to, uint32_t signature[4]) { struct target *target = bank->target; /* Clear END_OF_MISR interrupt status */ target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_MISR); /* Start address */ target_write_u32(target, FMSSTART, addr_from >> 4); /* End address, and issue start command */ target_write_u32(target, FMSSTOP, (addr_to >> 4) | FMSSTOP_MISR_START); /* Poll for end of operation. Calculate a reasonable timeout. */ if (lpc2900_wait_status(bank, INTSRC_END_OF_MISR, 1000) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; /* Return the signature */ uint8_t sig_buf[4 * 4]; target_read_memory(target, FMSW0, 4, 4, sig_buf); target_buffer_get_u32_array(target, sig_buf, 4, signature); return ERROR_OK; } /** * Return sector number for given address. * * Return the (logical) sector number for a given relative address. * No sanity check is done. It assumed that the address is valid. * * @param bank Pointer to the flash bank descriptor * @param offset Offset address relative to bank start */ static uint32_t lpc2900_address2sector(struct flash_bank *bank, uint32_t offset) { uint32_t address = bank->base + offset; /* Run through all sectors of this bank */ int sector; for (sector = 0; sector < bank->num_sectors; sector++) { /* Return immediately if address is within the current sector */ if (address < (bank->sectors[sector].offset + bank->sectors[sector].size)) return sector; } /* We should never come here. If we do, return an arbitrary sector number. */ return 0; } /** * Write one page to the index sector. * * @param bank Pointer to the flash bank descriptor * @param pagenum Page number (0...7) * @param page Page array (FLASH_PAGE_SIZE bytes) */ static int lpc2900_write_index_page(struct flash_bank *bank, int pagenum, uint8_t page[FLASH_PAGE_SIZE]) { /* Only pages 4...7 are user writable */ if ((pagenum < 4) || (pagenum > 7)) { LOG_ERROR("Refuse to burn index sector page %d", pagenum); return ERROR_COMMAND_ARGUMENT_INVALID; } /* Get target, and check if it's halted */ struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Private info */ struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; /* Enable flash block and set the correct CRA clock of 66 kHz */ lpc2900_setup(bank); /* Un-protect the index sector */ target_write_u32(target, bank->base, 0); target_write_u32(target, FCTR, FCTR_FS_LOADREQ | FCTR_FS_WPB | FCTR_FS_ISS | FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS); /* Set latch load mode */ target_write_u32(target, FCTR, FCTR_FS_ISS | FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS); /* Write whole page to flash data latches */ if (target_write_memory(target, bank->base + pagenum * FLASH_PAGE_SIZE, 4, FLASH_PAGE_SIZE / 4, page) != ERROR_OK) { LOG_ERROR("Index sector write failed @ page %d", pagenum); target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_FLASH_OPERATION_FAILED; } /* Clear END_OF_BURN interrupt status */ target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_BURN); /* Set the program/erase time to FLASH_PROGRAM_TIME */ target_write_u32(target, FPTR, FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc, FLASH_PROGRAM_TIME)); /* Trigger flash write */ target_write_u32(target, FCTR, FCTR_FS_PROGREQ | FCTR_FS_ISS | FCTR_FS_WPB | FCTR_FS_WRE | FCTR_FS_CS); /* Wait for the end of the write operation. If it's not over after one * second, something went dreadfully wrong... :-( */ if (lpc2900_wait_status(bank, INTSRC_END_OF_BURN, 1000) != ERROR_OK) { LOG_ERROR("Index sector write failed @ page %d", pagenum); target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_FLASH_OPERATION_FAILED; } target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_OK; } /** * Calculate FPTR.TR register value for desired program/erase time. * * @param clock System clock in Hz * @param time Program/erase time in µs */ static uint32_t lpc2900_calc_tr(uint32_t clock_var, uint32_t time_var) { /* ((time[µs]/1e6) * f[Hz]) + 511 * FPTR.TR = ------------------------------- * 512 */ uint32_t tr_val = (uint32_t)((((time_var / 1e6) * clock_var) + 511.0) / 512.0); return tr_val; } /*********************** Private flash commands **************************/ /** * Command to determine the signature of the whole flash. * * Uses the Built-In-Self-Test (BIST) to generate a 128-bit hash value * of the flash content. */ COMMAND_HANDLER(lpc2900_handle_signature_command) { uint32_t status; uint32_t signature[4]; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Run BIST over whole flash range */ status = lpc2900_run_bist128(bank, bank->base, bank->base + (bank->size - 1), signature); if (status != ERROR_OK) return status; command_print(CMD_CTX, "signature: 0x%8.8" PRIx32 ":0x%8.8" PRIx32 ":0x%8.8" PRIx32 ":0x%8.8" PRIx32, signature[3], signature[2], signature[1], signature[0]); return ERROR_OK; } /** * Store customer info in file. * * Read customer info from index sector, and store that block of data into * a disk file. The format is binary. */ COMMAND_HANDLER(lpc2900_handle_read_custom_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; lpc2900_info->risky = 0; /* Get target, and check if it's halted */ struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Storage for customer info. Read in two parts */ uint8_t customer[4 * (ISS_CUSTOMER_NWORDS1 + ISS_CUSTOMER_NWORDS2)]; /* Enable access to index sector */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB | FCTR_FS_ISS); /* Read two parts */ target_read_memory(target, bank->base+ISS_CUSTOMER_START1, 4, ISS_CUSTOMER_NWORDS1, &customer[0]); target_read_memory(target, bank->base+ISS_CUSTOMER_START2, 4, ISS_CUSTOMER_NWORDS2, &customer[4 * ISS_CUSTOMER_NWORDS1]); /* Deactivate access to index sector */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); /* Try and open the file */ struct fileio fileio; const char *filename = CMD_ARGV[1]; int ret = fileio_open(&fileio, filename, FILEIO_WRITE, FILEIO_BINARY); if (ret != ERROR_OK) { LOG_WARNING("Could not open file %s", filename); return ret; } size_t nwritten; ret = fileio_write(&fileio, sizeof(customer), customer, &nwritten); if (ret != ERROR_OK) { LOG_ERROR("Write operation to file %s failed", filename); fileio_close(&fileio); return ret; } fileio_close(&fileio); return ERROR_OK; } /** * Enter password to enable potentially dangerous options. */ COMMAND_HANDLER(lpc2900_handle_password_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; #define ISS_PASSWORD "I_know_what_I_am_doing" lpc2900_info->risky = !strcmp(CMD_ARGV[1], ISS_PASSWORD); if (!lpc2900_info->risky) { command_print(CMD_CTX, "Wrong password (use '%s')", ISS_PASSWORD); return ERROR_COMMAND_ARGUMENT_INVALID; } command_print(CMD_CTX, "Potentially dangerous operation allowed in next command!"); return ERROR_OK; } /** * Write customer info from file to the index sector. */ COMMAND_HANDLER(lpc2900_handle_write_custom_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; /* Check if command execution is allowed. */ if (!lpc2900_info->risky) { command_print(CMD_CTX, "Command execution not allowed!"); return ERROR_COMMAND_ARGUMENT_INVALID; } lpc2900_info->risky = 0; /* Get target, and check if it's halted */ struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* The image will always start at offset 0 */ struct image image; image.base_address_set = 1; image.base_address = 0; image.start_address_set = 0; const char *filename = CMD_ARGV[1]; const char *type = (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL; retval = image_open(&image, filename, type); if (retval != ERROR_OK) return retval; /* Do a sanity check: The image must be exactly the size of the customer programmable area. Any other size is rejected. */ if (image.num_sections != 1) { LOG_ERROR("Only one section allowed in image file."); return ERROR_COMMAND_SYNTAX_ERROR; } if ((image.sections[0].base_address != 0) || (image.sections[0].size != ISS_CUSTOMER_SIZE)) { LOG_ERROR("Incorrect image file size. Expected %d, " "got %" PRIu32, ISS_CUSTOMER_SIZE, image.sections[0].size); return ERROR_COMMAND_SYNTAX_ERROR; } /* Well boys, I reckon this is it... */ /* Customer info is split into two blocks in pages 4 and 5. */ uint8_t page[FLASH_PAGE_SIZE]; /* Page 4 */ uint32_t offset = ISS_CUSTOMER_START1 % FLASH_PAGE_SIZE; memset(page, 0xff, FLASH_PAGE_SIZE); size_t size_read; retval = image_read_section(&image, 0, 0, ISS_CUSTOMER_SIZE1, &page[offset], &size_read); if (retval != ERROR_OK) { LOG_ERROR("couldn't read from file '%s'", filename); image_close(&image); return retval; } retval = lpc2900_write_index_page(bank, 4, page); if (retval != ERROR_OK) { image_close(&image); return retval; } /* Page 5 */ offset = ISS_CUSTOMER_START2 % FLASH_PAGE_SIZE; memset(page, 0xff, FLASH_PAGE_SIZE); retval = image_read_section(&image, 0, ISS_CUSTOMER_SIZE1, ISS_CUSTOMER_SIZE2, &page[offset], &size_read); if (retval != ERROR_OK) { LOG_ERROR("couldn't read from file '%s'", filename); image_close(&image); return retval; } retval = lpc2900_write_index_page(bank, 5, page); if (retval != ERROR_OK) { image_close(&image); return retval; } image_close(&image); return ERROR_OK; } /** * Activate 'sector security' for a range of sectors. */ COMMAND_HANDLER(lpc2900_handle_secure_sector_command) { if (CMD_ARGC < 3) return ERROR_COMMAND_SYNTAX_ERROR; /* Get the bank descriptor */ struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; /* Check if command execution is allowed. */ if (!lpc2900_info->risky) { command_print(CMD_CTX, "Command execution not allowed! " "(use 'password' command first)"); return ERROR_COMMAND_ARGUMENT_INVALID; } lpc2900_info->risky = 0; /* Read sector range, and do a sanity check. */ int first, last; COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last); if ((first >= bank->num_sectors) || (last >= bank->num_sectors) || (first > last)) { command_print(CMD_CTX, "Illegal sector range"); return ERROR_COMMAND_ARGUMENT_INVALID; } uint8_t page[FLASH_PAGE_SIZE]; int sector; /* Sectors in page 6 */ if ((first <= 4) || (last >= 8)) { memset(&page, 0xff, FLASH_PAGE_SIZE); for (sector = first; sector <= last; sector++) { if (sector <= 4) memset(&page[0xB0 + 16*sector], 0, 16); else if (sector >= 8) memset(&page[0x00 + 16*(sector - 8)], 0, 16); } retval = lpc2900_write_index_page(bank, 6, page); if (retval != ERROR_OK) { LOG_ERROR("failed to update index sector page 6"); return retval; } } /* Sectors in page 7 */ if ((first <= 7) && (last >= 5)) { memset(&page, 0xff, FLASH_PAGE_SIZE); for (sector = first; sector <= last; sector++) { if ((sector >= 5) && (sector <= 7)) memset(&page[0x00 + 16*(sector - 5)], 0, 16); } retval = lpc2900_write_index_page(bank, 7, page); if (retval != ERROR_OK) { LOG_ERROR("failed to update index sector page 7"); return retval; } } command_print(CMD_CTX, "Sectors security will become effective after next power cycle"); /* Update the sector security status */ if (lpc2900_read_security_status(bank) != ERROR_OK) { LOG_ERROR("Cannot determine sector security status"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } /** * Activate JTAG protection. */ COMMAND_HANDLER(lpc2900_handle_secure_jtag_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; /* Get the bank descriptor */ struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; /* Check if command execution is allowed. */ if (!lpc2900_info->risky) { command_print(CMD_CTX, "Command execution not allowed! " "(use 'password' command first)"); return ERROR_COMMAND_ARGUMENT_INVALID; } lpc2900_info->risky = 0; /* Prepare page */ uint8_t page[FLASH_PAGE_SIZE]; memset(&page, 0xff, FLASH_PAGE_SIZE); /* Insert "soft" protection word */ page[0x30 + 15] = 0x7F; page[0x30 + 11] = 0x7F; page[0x30 + 7] = 0x7F; page[0x30 + 3] = 0x7F; /* Write to page 5 */ retval = lpc2900_write_index_page(bank, 5, page); if (retval != ERROR_OK) { LOG_ERROR("failed to update index sector page 5"); return retval; } LOG_INFO("JTAG security set. Good bye!"); return ERROR_OK; } /*********************** Flash interface functions **************************/ static const struct command_registration lpc2900_exec_command_handlers[] = { { .name = "signature", .usage = "", .handler = lpc2900_handle_signature_command, .mode = COMMAND_EXEC, .help = "Calculate and display signature of flash bank.", }, { .name = "read_custom", .handler = lpc2900_handle_read_custom_command, .mode = COMMAND_EXEC, .usage = "bank_id filename", .help = "Copies 912 bytes of customer information " "from index sector into file.", }, { .name = "password", .handler = lpc2900_handle_password_command, .mode = COMMAND_EXEC, .usage = "bank_id password", .help = "Enter fixed password to enable 'dangerous' options.", }, { .name = "write_custom", .handler = lpc2900_handle_write_custom_command, .mode = COMMAND_EXEC, .usage = "bank_id filename ('bin'|'ihex'|'elf'|'s19')", .help = "Copies 912 bytes of customer info from file " "to index sector.", }, { .name = "secure_sector", .handler = lpc2900_handle_secure_sector_command, .mode = COMMAND_EXEC, .usage = "bank_id first_sector last_sector", .help = "Activate sector security for a range of sectors. " "It will be effective after a power cycle.", }, { .name = "secure_jtag", .handler = lpc2900_handle_secure_jtag_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Disable the JTAG port. " "It will be effective after a power cycle.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration lpc2900_command_handlers[] = { { .name = "lpc2900", .mode = COMMAND_ANY, .help = "LPC2900 flash command group", .usage = "", .chain = lpc2900_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Evaluate flash bank command. */ FLASH_BANK_COMMAND_HANDLER(lpc2900_flash_bank_command) { struct lpc2900_flash_bank *lpc2900_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; lpc2900_info = malloc(sizeof(struct lpc2900_flash_bank)); bank->driver_priv = lpc2900_info; /* Get flash clock. * Reject it if we can't meet the requirements for program time * (if clock too slow), or for erase time (clock too fast). */ uint32_t clk_sys_fmc; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], clk_sys_fmc); lpc2900_info->clk_sys_fmc = clk_sys_fmc * 1000; uint32_t clock_limit; /* Check program time limit */ clock_limit = 512000000l / FLASH_PROGRAM_TIME; if (lpc2900_info->clk_sys_fmc < clock_limit) { LOG_WARNING("flash clock must be at least %" PRIu32 " kHz", (clock_limit / 1000)); return ERROR_FLASH_BANK_INVALID; } /* Check erase time limit */ clock_limit = (uint32_t)((32767.0 * 512.0 * 1e6) / FLASH_ERASE_TIME); if (lpc2900_info->clk_sys_fmc > clock_limit) { LOG_WARNING("flash clock must be a maximum of %" PRIu32 " kHz", (clock_limit / 1000)); return ERROR_FLASH_BANK_INVALID; } /* Chip ID will be obtained by probing the device later */ lpc2900_info->chipid = 0; lpc2900_info->is_probed = false; return ERROR_OK; } /** * Erase sector(s). * * @param bank Pointer to the flash bank descriptor * @param first First sector to be erased * @param last Last sector (including) to be erased */ static int lpc2900_erase(struct flash_bank *bank, int first, int last) { uint32_t status; int sector; int last_unsecured_sector; struct target *target = bank->target; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; status = lpc2900_is_ready(bank); if (status != ERROR_OK) return status; /* Sanity check on sector range */ if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_INFO("Bad sector range"); return ERROR_FLASH_SECTOR_INVALID; } /* Update the info about secured sectors */ lpc2900_read_security_status(bank); /* The selected sector range might include secured sectors. An attempt * to erase such a sector will cause the erase to fail also for unsecured * sectors. It is necessary to determine the last unsecured sector now, * because we have to treat the last relevant sector in the list in * a special way. */ last_unsecured_sector = -1; for (sector = first; sector <= last; sector++) { if (!bank->sectors[sector].is_protected) last_unsecured_sector = sector; } /* Exit now, in case of the rare constellation where all sectors in range * are secured. This is regarded a success, since erasing/programming of * secured sectors shall be handled transparently. */ if (last_unsecured_sector == -1) return ERROR_OK; /* Enable flash block and set the correct CRA clock of 66 kHz */ lpc2900_setup(bank); /* Clear END_OF_ERASE interrupt status */ target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_ERASE); /* Set the program/erase timer to FLASH_ERASE_TIME */ target_write_u32(target, FPTR, FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc, FLASH_ERASE_TIME)); /* Sectors are marked for erasure, then erased all together */ for (sector = first; sector <= last_unsecured_sector; sector++) { /* Only mark sectors that aren't secured. Any attempt to erase a group * of sectors will fail if any single one of them is secured! */ if (!bank->sectors[sector].is_protected) { /* Unprotect the sector */ target_write_u32(target, bank->sectors[sector].offset, 0); target_write_u32(target, FCTR, FCTR_FS_LOADREQ | FCTR_FS_WPB | FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS); /* Mark the sector for erasure. The last sector in the list triggers the erasure. */ target_write_u32(target, bank->sectors[sector].offset, 0); if (sector == last_unsecured_sector) { target_write_u32(target, FCTR, FCTR_FS_PROGREQ | FCTR_FS_WPB | FCTR_FS_CS); } else { target_write_u32(target, FCTR, FCTR_FS_LOADREQ | FCTR_FS_WPB | FCTR_FS_WEB | FCTR_FS_CS); } } } /* Wait for the end of the erase operation. If it's not over after two seconds, * something went dreadfully wrong... :-( */ if (lpc2900_wait_status(bank, INTSRC_END_OF_ERASE, 2000) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; /* Normal flash operating mode */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_OK; } static int lpc2900_protect(struct flash_bank *bank, int set, int first, int last) { /* This command is not supported. * "Protection" in LPC2900 terms is handled transparently. Sectors will * automatically be unprotected as needed. * Instead we use the concept of sector security. A secured sector is shown * as "protected" in OpenOCD. Sector security is a permanent feature, and * cannot be disabled once activated. */ return ERROR_OK; } /** * Write data to flash. * * @param bank Pointer to the flash bank descriptor * @param buffer Buffer with data * @param offset Start address (relative to bank start) * @param count Number of bytes to be programmed */ static int lpc2900_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint8_t page[FLASH_PAGE_SIZE]; uint32_t status; uint32_t num_bytes; struct target *target = bank->target; struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; int sector; int retval; static const uint32_t write_target_code[] = { /* Set auto latch mode: FCTR=CS|WRE|WEB */ 0xe3a0a007, /* loop mov r10, #0x007 */ 0xe583a000, /* str r10,[r3,#0] */ /* Load complete page into latches */ 0xe3a06020, /* mov r6,#(512/16) */ 0xe8b00f00, /* next ldmia r0!,{r8-r11} */ 0xe8a10f00, /* stmia r1!,{r8-r11} */ 0xe2566001, /* subs r6,#1 */ 0x1afffffb, /* bne next */ /* Clear END_OF_BURN interrupt status */ 0xe3a0a002, /* mov r10,#(1 << 1) */ 0xe583afe8, /* str r10,[r3,#0xfe8] */ /* Set the erase time to FLASH_PROGRAM_TIME */ 0xe5834008, /* str r4,[r3,#8] */ /* Trigger flash write * FCTR = CS | WRE | WPB | PROGREQ */ 0xe3a0a083, /* mov r10,#0x83 */ 0xe38aaa01, /* orr r10,#0x1000 */ 0xe583a000, /* str r10,[r3,#0] */ /* Wait for end of burn */ 0xe593afe0, /* wait ldr r10,[r3,#0xfe0] */ 0xe21aa002, /* ands r10,#(1 << 1) */ 0x0afffffc, /* beq wait */ /* End? */ 0xe2522001, /* subs r2,#1 */ 0x1affffed, /* bne loop */ 0xeafffffe /* done b done */ }; status = lpc2900_is_ready(bank); if (status != ERROR_OK) return status; /* Enable flash block and set the correct CRA clock of 66 kHz */ lpc2900_setup(bank); /* Update the info about secured sectors */ lpc2900_read_security_status(bank); /* Unprotect all involved sectors */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start address in or before this sector? * End address in or behind this sector? */ if (((bank->base + offset) < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((bank->base + (offset + count - 1)) >= bank->sectors[sector].offset)) { /* This sector is involved and needs to be unprotected. * Don't do it for secured sectors. */ if (!bank->sectors[sector].is_protected) { target_write_u32(target, bank->sectors[sector].offset, 0); target_write_u32(target, FCTR, FCTR_FS_LOADREQ | FCTR_FS_WPB | FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS); } } } /* Set the program/erase time to FLASH_PROGRAM_TIME */ uint32_t prog_time = FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc, FLASH_PROGRAM_TIME); /* If there is a working area of reasonable size, use it to program via * a target algorithm. If not, fall back to host programming. */ /* We need some room for target code. */ const uint32_t target_code_size = sizeof(write_target_code); /* Try working area allocation. Start with a large buffer, and try with * reduced size if that fails. */ struct working_area *warea; uint32_t buffer_size = lpc2900_info->max_ram_block - 1 * KiB; while ((retval = target_alloc_working_area_try(target, buffer_size + target_code_size, &warea)) != ERROR_OK) { /* Try a smaller buffer now, and stop if it's too small. */ buffer_size -= 1 * KiB; if (buffer_size < 2 * KiB) { LOG_INFO("no (large enough) working area, falling back to host mode"); warea = NULL; break; } } ; if (warea) { struct reg_param reg_params[5]; struct arm_algorithm arm_algo; /* We can use target mode. Download the algorithm. */ uint8_t code[sizeof(write_target_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(write_target_code), write_target_code); retval = target_write_buffer(target, (warea->address) + buffer_size, sizeof(code), code); if (retval != ERROR_OK) { LOG_ERROR("Unable to write block write code to target"); target_free_all_working_areas(target); return ERROR_FLASH_OPERATION_FAILED; } init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_OUT); init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* Write to flash in large blocks */ while (count != 0) { uint32_t this_npages; const uint8_t *this_buffer; int start_sector = lpc2900_address2sector(bank, offset); /* First page / last page / rest */ if (offset % FLASH_PAGE_SIZE) { /* Block doesn't start on page boundary. * Burn first partial page separately. */ memset(&page, 0xff, sizeof(page)); memcpy(&page[offset % FLASH_PAGE_SIZE], buffer, FLASH_PAGE_SIZE - (offset % FLASH_PAGE_SIZE)); this_npages = 1; this_buffer = &page[0]; count = count + (offset % FLASH_PAGE_SIZE); offset = offset - (offset % FLASH_PAGE_SIZE); } else if (count < FLASH_PAGE_SIZE) { /* Download last incomplete page separately. */ memset(&page, 0xff, sizeof(page)); memcpy(&page, buffer, count); this_npages = 1; this_buffer = &page[0]; count = FLASH_PAGE_SIZE; } else { /* Download as many full pages as possible */ this_npages = (count < buffer_size) ? count / FLASH_PAGE_SIZE : buffer_size / FLASH_PAGE_SIZE; this_buffer = buffer; /* Make sure we stop at the next secured sector */ sector = start_sector + 1; while (sector < bank->num_sectors) { /* Secured? */ if (bank->sectors[sector].is_protected) { /* Is that next sector within the current block? */ if ((bank->sectors[sector].offset - bank->base) < (offset + (this_npages * FLASH_PAGE_SIZE))) { /* Yes! Split the block */ this_npages = (bank->sectors[sector].offset - bank->base - offset) / FLASH_PAGE_SIZE; break; } } sector++; } } /* Skip the current sector if it is secured */ if (bank->sectors[start_sector].is_protected) { LOG_DEBUG("Skip secured sector %d", start_sector); /* Stop if this is the last sector */ if (start_sector == bank->num_sectors - 1) break; /* Skip */ uint32_t nskip = bank->sectors[start_sector].size - (offset % bank->sectors[start_sector].size); offset += nskip; buffer += nskip; count = (count >= nskip) ? (count - nskip) : 0; continue; } /* Execute buffer download */ retval = target_write_buffer(target, warea->address, this_npages * FLASH_PAGE_SIZE, this_buffer); if (retval != ERROR_OK) { LOG_ERROR("Unable to write data to target"); target_free_all_working_areas(target); return ERROR_FLASH_OPERATION_FAILED; } /* Prepare registers */ buf_set_u32(reg_params[0].value, 0, 32, warea->address); buf_set_u32(reg_params[1].value, 0, 32, offset); buf_set_u32(reg_params[2].value, 0, 32, this_npages); buf_set_u32(reg_params[3].value, 0, 32, FCTR); buf_set_u32(reg_params[4].value, 0, 32, FPTR_EN_T | prog_time); /* Execute algorithm, assume breakpoint for last instruction */ arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; retval = target_run_algorithm(target, 0, NULL, 5, reg_params, (warea->address) + buffer_size, (warea->address) + buffer_size + target_code_size - 4, 10000, /* 10s should be enough for max. 16 KiB of data */ &arm_algo); if (retval != ERROR_OK) { LOG_ERROR("Execution of flash algorithm failed."); target_free_all_working_areas(target); retval = ERROR_FLASH_OPERATION_FAILED; break; } count -= this_npages * FLASH_PAGE_SIZE; buffer += this_npages * FLASH_PAGE_SIZE; offset += this_npages * FLASH_PAGE_SIZE; } /* Free all resources */ destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); target_free_all_working_areas(target); } else { /* Write to flash memory page-wise */ while (count != 0) { /* How many bytes do we copy this time? */ num_bytes = (count >= FLASH_PAGE_SIZE) ? FLASH_PAGE_SIZE - (offset % FLASH_PAGE_SIZE) : count; /* Don't do anything with it if the page is in a secured sector. */ if (!bank->sectors[lpc2900_address2sector(bank, offset)].is_protected) { /* Set latch load mode */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WRE | FCTR_FS_WEB); /* Always clear the buffer (a little overhead, but who cares) */ memset(page, 0xFF, FLASH_PAGE_SIZE); /* Copy them to the buffer */ memcpy(&page[offset % FLASH_PAGE_SIZE], &buffer[offset % FLASH_PAGE_SIZE], num_bytes); /* Write whole page to flash data latches */ if (target_write_memory(target, bank->base + (offset - (offset % FLASH_PAGE_SIZE)), 4, FLASH_PAGE_SIZE / 4, page) != ERROR_OK) { LOG_ERROR("Write failed @ 0x%8.8" PRIx32, offset); target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_FLASH_OPERATION_FAILED; } /* Clear END_OF_BURN interrupt status */ target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_BURN); /* Set the programming time */ target_write_u32(target, FPTR, FPTR_EN_T | prog_time); /* Trigger flash write */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WRE | FCTR_FS_WPB | FCTR_FS_PROGREQ); /* Wait for the end of the write operation. If it's not over * after one second, something went dreadfully wrong... :-( */ if (lpc2900_wait_status(bank, INTSRC_END_OF_BURN, 1000) != ERROR_OK) { LOG_ERROR("Write failed @ 0x%8.8" PRIx32, offset); target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return ERROR_FLASH_OPERATION_FAILED; } } /* Update pointers and counters */ offset += num_bytes; buffer += num_bytes; count -= num_bytes; } retval = ERROR_OK; } /* Normal flash operating mode */ target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); return retval; } /** * Try and identify the device. * * Determine type number and its memory layout. * * @param bank Pointer to the flash bank descriptor */ static int lpc2900_probe(struct flash_bank *bank) { struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv; struct target *target = bank->target; int i = 0; uint32_t offset; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* We want to do this only once. */ if (lpc2900_info->is_probed) return ERROR_OK; /* Probing starts with reading the CHIPID register. We will continue only * if this identifies as an LPC2900 device. */ target_read_u32(target, CHIPID, &lpc2900_info->chipid); if (lpc2900_info->chipid != EXPECTED_CHIPID) { LOG_WARNING("Device is not an LPC29xx"); return ERROR_FLASH_OPERATION_FAILED; } /* It's an LPC29xx device. Now read the feature register FEAT0...FEAT3. */ uint32_t feat0, feat1, feat2, feat3; target_read_u32(target, FEAT0, &feat0); target_read_u32(target, FEAT1, &feat1); target_read_u32(target, FEAT2, &feat2); target_read_u32(target, FEAT3, &feat3); /* Base address */ bank->base = 0x20000000; /* Determine flash layout from FEAT2 register */ uint32_t num_64k_sectors = (feat2 >> 16) & 0xFF; uint32_t num_8k_sectors = (feat2 >> 0) & 0xFF; bank->num_sectors = num_64k_sectors + num_8k_sectors; bank->size = KiB * (64 * num_64k_sectors + 8 * num_8k_sectors); /* Determine maximum contiguous RAM block */ lpc2900_info->max_ram_block = 16 * KiB; if ((feat1 & 0x30) == 0x30) { lpc2900_info->max_ram_block = 32 * KiB; if ((feat1 & 0x0C) == 0x0C) lpc2900_info->max_ram_block = 48 * KiB; } /* Determine package code and ITCM size */ uint32_t package_code = feat0 & 0x0F; uint32_t itcm_code = (feat1 >> 16) & 0x1F; /* Determine the exact type number. */ uint32_t found = 1; if ((package_code == 4) && (itcm_code == 5)) { /* Old LPC2917 or LPC2919 (non-/01 devices) */ lpc2900_info->target_name = (bank->size == 768*KiB) ? "LPC2919" : "LPC2917"; } else { if (package_code == 2) { /* 100-pin package */ if (bank->size == 128*KiB) lpc2900_info->target_name = "LPC2921"; else if (bank->size == 256*KiB) lpc2900_info->target_name = "LPC2923"; else if (bank->size == 512*KiB) lpc2900_info->target_name = "LPC2925"; else found = 0; } else if (package_code == 4) { /* 144-pin package */ if ((bank->size == 256*KiB) && (feat3 == 0xFFFFFFE9)) lpc2900_info->target_name = "LPC2926"; else if ((bank->size == 512*KiB) && (feat3 == 0xFFFFFCF0)) lpc2900_info->target_name = "LPC2917/01"; else if ((bank->size == 512*KiB) && (feat3 == 0xFFFFFFF1)) lpc2900_info->target_name = "LPC2927"; else if ((bank->size == 768*KiB) && (feat3 == 0xFFFFFCF8)) lpc2900_info->target_name = "LPC2919/01"; else if ((bank->size == 768*KiB) && (feat3 == 0xFFFFFFF9)) lpc2900_info->target_name = "LPC2929"; else found = 0; } else if (package_code == 5) { /* 208-pin package */ lpc2900_info->target_name = (bank->size == 0) ? "LPC2930" : "LPC2939"; } else found = 0; } if (!found) { LOG_WARNING("Unknown LPC29xx derivative (FEATx=" "%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ")", feat0, feat1, feat2, feat3); return ERROR_FLASH_OPERATION_FAILED; } /* Show detected device */ LOG_INFO("Flash bank %d: Device %s, %" PRIu32 " KiB in %d sectors", bank->bank_number, lpc2900_info->target_name, bank->size / KiB, bank->num_sectors); /* Flashless devices cannot be handled */ if (bank->num_sectors == 0) { LOG_WARNING("Flashless device cannot be handled"); return ERROR_FLASH_OPERATION_FAILED; } /* Sector layout. * These are logical sector numbers. When doing real flash operations, * the logical flash number are translated into the physical flash numbers * of the device. */ bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); offset = 0; for (i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; if (i <= 7) bank->sectors[i].size = 8 * KiB; else if (i <= 18) bank->sectors[i].size = 64 * KiB; else { /* We shouldn't come here. But there might be a new part out there * that has more than 19 sectors. Politely ask for a fix then. */ bank->sectors[i].size = 0; LOG_ERROR("Never heard about sector %d", i); } offset += bank->sectors[i].size; } lpc2900_info->is_probed = true; /* Read sector security status */ if (lpc2900_read_security_status(bank) != ERROR_OK) { LOG_ERROR("Cannot determine sector security status"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } /** * Run a blank check for each sector. * * For speed reasons, the device isn't read word by word. * A hash value is calculated by the hardware ("BIST") for each sector. * This value is then compared against the known hash of an empty sector. * * @param bank Pointer to the flash bank descriptor */ static int lpc2900_erase_check(struct flash_bank *bank) { uint32_t status = lpc2900_is_ready(bank); if (status != ERROR_OK) { LOG_INFO("Processor not halted/not probed"); return status; } /* Use the BIST (Built-In Selft Test) to generate a signature of each flash * sector. Compare against the expected signature of an empty sector. */ int sector; for (sector = 0; sector < bank->num_sectors; sector++) { uint32_t signature[4]; status = lpc2900_run_bist128(bank, bank->sectors[sector].offset, bank->sectors[sector].offset + (bank->sectors[sector].size - 1), signature); if (status != ERROR_OK) return status; /* The expected signatures for an empty sector are different * for 8 KiB and 64 KiB sectors. */ if (bank->sectors[sector].size == 8*KiB) { bank->sectors[sector].is_erased = (signature[3] == 0x01ABAAAA) && (signature[2] == 0xAAAAAAAA) && (signature[1] == 0xAAAAAAAA) && (signature[0] == 0xAAA00AAA); } if (bank->sectors[sector].size == 64*KiB) { bank->sectors[sector].is_erased = (signature[3] == 0x11801222) && (signature[2] == 0xB88844FF) && (signature[1] == 0x11A22008) && (signature[0] == 0x2B1BFE44); } } return ERROR_OK; } /** * Get protection (sector security) status. * * Determine the status of "sector security" for each sector. * A secured sector is one that can never be erased/programmed again. * * @param bank Pointer to the flash bank descriptor */ static int lpc2900_protect_check(struct flash_bank *bank) { return lpc2900_read_security_status(bank); } struct flash_driver lpc2900_flash = { .name = "lpc2900", .commands = lpc2900_command_handlers, .flash_bank_command = lpc2900_flash_bank_command, .erase = lpc2900_erase, .protect = lpc2900_protect, .write = lpc2900_write, .read = default_flash_read, .probe = lpc2900_probe, .auto_probe = lpc2900_probe, .erase_check = lpc2900_erase_check, .protect_check = lpc2900_protect_check, }; openocd-0.9.0/src/flash/nor/lpc288x.c0000644000175000017500000003327512315575360014147 00000000000000/*************************************************************************** * Copyright (C) 2008 by * * Karl RobinSod * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /*************************************************************************** * There are some things to notice * * You need to unprotect flash sectors each time you connect the OpenOCD * Dumping 1MB takes about 60 Seconds * Full erase (sectors 0-22 inclusive) takes 2-4 seconds * Writing 1MB takes 88 seconds * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #define LOAD_TIMER_ERASE 0 #define LOAD_TIMER_WRITE 1 #define FLASH_PAGE_SIZE 512 /* LPC288X control registers */ #define DBGU_CIDR 0x8000507C /* LPC288X flash registers */ #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */ #define F_STAT 0x80102004 /* Flash status register RO 0x45 */ #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */ #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */ #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 **/ #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */ #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */ #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */ #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */ #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */ #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */ #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power *savings. R/W 1*/ #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from *Power Down mode. R/W -*/ /* F_CTRL bits */ #define FC_CS 0x0001 #define FC_FUNC 0x0002 #define FC_WEN 0x0004 #define FC_RD_LATCH 0x0020 #define FC_PROTECT 0x0080 #define FC_SET_DATA 0x0400 #define FC_RSSL 0x0800 #define FC_PROG_REQ 0x1000 #define FC_CLR_BUF 0x4000 #define FC_LOAD_REQ 0x8000 /* F_STAT bits */ #define FS_DONE 0x0001 #define FS_PROGGNT 0x0002 #define FS_RDY 0x0004 #define FS_ERR 0x0020 /* F_PROG_TIME */ #define FPT_TIME_MASK 0x7FFF #define FPT_ENABLE 0x8000 /* F_WAIT */ #define FW_WAIT_STATES_MASK 0x00FF #define FW_SET_MASK 0xC000 /* F_CLK_TIME */ #define FCT_CLK_DIV_MASK 0x0FFF struct lpc288x_flash_bank { uint32_t working_area; uint32_t working_area_size; /* chip id register */ uint32_t cidr; const char *target_name; uint32_t cclk; uint32_t sector_size_break; }; static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout); static void lpc288x_load_timer(int erase, struct target *target); static void lpc288x_set_flash_clk(struct flash_bank *bank); static uint32_t lpc288x_system_ready(struct flash_bank *bank); static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout) { uint32_t status; struct target *target = bank->target; do { alive_sleep(1); timeout--; target_read_u32(target, F_STAT, &status); } while (((status & FS_DONE) == 0) && timeout); if (timeout == 0) { LOG_DEBUG("Timedout!"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } /* Read device id register and fill in driver info structure */ static int lpc288x_read_part_info(struct flash_bank *bank) { struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; struct target *target = bank->target; uint32_t cidr; int i = 0; uint32_t offset; if (lpc288x_info->cidr == 0x0102100A) return ERROR_OK;/* already probed, multiple probes may cause memory leak, not *allowed */ /* Read and parse chip identification register */ target_read_u32(target, DBGU_CIDR, &cidr); if (cidr != 0x0102100A) { LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr); return ERROR_FLASH_OPERATION_FAILED; } lpc288x_info->cidr = cidr; lpc288x_info->sector_size_break = 0x000F0000; lpc288x_info->target_name = "LPC288x"; /* setup the sector info... */ offset = bank->base; bank->num_sectors = 23; bank->sectors = malloc(sizeof(struct flash_sector) * 23); for (i = 0; i < 15; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 64 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } for (i = 15; i < 23; i++) { bank->sectors[i].offset = offset; bank->sectors[i].size = 8 * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } return ERROR_OK; } static int lpc288x_protect_check(struct flash_bank *bank) { return ERROR_OK; } /* flash_bank LPC288x 0 0 0 0 */ FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command) { struct lpc288x_flash_bank *lpc288x_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank)); bank->driver_priv = lpc288x_info; /* part wasn't probed for info yet */ lpc288x_info->cidr = 0; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], lpc288x_info->cclk); return ERROR_OK; } /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1. * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%. * AHB = 12 MHz ? * 12000000/66000 = 182 * CLK_DIV = 60 ? */ static void lpc288x_set_flash_clk(struct flash_bank *bank) { uint32_t clk_time; struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; clk_time = (lpc288x_info->cclk / 66000) / 3; target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN); target_write_u32(bank->target, F_CLK_TIME, clk_time); } /* AHB tcyc (in ns) 83 ns * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512 * = 9412 (9500) (AN10548 9375) * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512 * = 23 (75) (AN10548 72 - is this wrong?) * TODO: Sort out timing calcs ;) */ static void lpc288x_load_timer(int erase, struct target *target) { if (erase == LOAD_TIMER_ERASE) target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500); else target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75); } static uint32_t lpc288x_system_ready(struct flash_bank *bank) { struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; if (lpc288x_info->cidr == 0) return ERROR_FLASH_BANK_NOT_PROBED; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return ERROR_OK; } static int lpc288x_erase_check(struct flash_bank *bank) { uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */ if (status != ERROR_OK) { LOG_INFO("Processor not halted/not probed"); return status; } return ERROR_OK; } static int lpc288x_erase(struct flash_bank *bank, int first, int last) { uint32_t status; int sector; struct target *target = bank->target; status = lpc288x_system_ready(bank); /* probed? halted? */ if (status != ERROR_OK) return status; if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_INFO("Bad sector range"); return ERROR_FLASH_SECTOR_INVALID; } /* Configure the flash controller timing */ lpc288x_set_flash_clk(bank); for (sector = first; sector <= last; sector++) { if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; lpc288x_load_timer(LOAD_TIMER_ERASE, target); target_write_u32(target, bank->sectors[sector].offset, 0x00); target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS); } if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } static int lpc288x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint8_t page_buffer[FLASH_PAGE_SIZE]; uint32_t status, source_offset, dest_offset; struct target *target = bank->target; uint32_t bytes_remaining = count; uint32_t first_sector, last_sector, sector, page; int i; /* probed? halted? */ status = lpc288x_system_ready(bank); if (status != ERROR_OK) return status; /* Initialise search indices */ first_sector = last_sector = 0xffffffff; /* validate the write range... */ for (i = 0; i < bank->num_sectors; i++) { if ((offset >= bank->sectors[i].offset) && (offset < (bank->sectors[i].offset + bank->sectors[i].size)) && (first_sector == 0xffffffff)) { first_sector = i; /* all writes must start on a sector boundary... */ if (offset % bank->sectors[i].size) { LOG_INFO( "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } } if (((offset + count) > bank->sectors[i].offset) && ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) && (last_sector == 0xffffffff)) last_sector = i; } /* Range check... */ if (first_sector == 0xffffffff || last_sector == 0xffffffff) { LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count); return ERROR_FLASH_DST_OUT_OF_BANK; } /* Configure the flash controller timing */ lpc288x_set_flash_clk(bank); /* initialise the offsets */ source_offset = 0; dest_offset = 0; for (sector = first_sector; sector <= last_sector; sector++) { for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) { if (bytes_remaining == 0) { count = 0; memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); } else if (bytes_remaining < FLASH_PAGE_SIZE) { count = bytes_remaining; memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); memcpy(page_buffer, &buffer[source_offset], count); } else { count = FLASH_PAGE_SIZE; memcpy(page_buffer, &buffer[source_offset], count); } /* Wait for flash to become ready */ if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) return ERROR_FLASH_OPERATION_FAILED; /* fill flash data latches with 1's */ target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC); target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC); if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK) { LOG_INFO("Write to flash buffer failed"); return ERROR_FLASH_OPERATION_FAILED; } dest_offset += FLASH_PAGE_SIZE; source_offset += count; bytes_remaining -= count; lpc288x_load_timer(LOAD_TIMER_WRITE, target); target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS); } } return ERROR_OK; } static int lpc288x_probe(struct flash_bank *bank) { /* we only deal with LPC2888 so flash config is fixed */ struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; int retval; if (lpc288x_info->cidr != 0) return ERROR_OK;/* already probed */ if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = lpc288x_read_part_info(bank); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last) { int lockregion, status; uint32_t value; struct target *target = bank->target; /* probed? halted? */ status = lpc288x_system_ready(bank); if (status != ERROR_OK) return status; if ((first < 0) || (last < first) || (last >= bank->num_sectors)) return ERROR_FLASH_SECTOR_INVALID; /* Configure the flash controller timing */ lpc288x_set_flash_clk(bank); for (lockregion = first; lockregion <= last; lockregion++) { if (set) { /* write an odd value to base addy to protect... */ value = 0x01; } else { /* write an even value to base addy to unprotect... */ value = 0x00; } target_write_u32(target, bank->sectors[lockregion].offset, value); target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS); } return ERROR_OK; } struct flash_driver lpc288x_flash = { .name = "lpc288x", .flash_bank_command = lpc288x_flash_bank_command, .erase = lpc288x_erase, .protect = lpc288x_protect, .write = lpc288x_write, .read = default_flash_read, .probe = lpc288x_probe, .auto_probe = lpc288x_probe, .erase_check = lpc288x_erase_check, .protect_check = lpc288x_protect_check, }; openocd-0.9.0/src/flash/nor/nuc1x.c0000644000175000017500000004266112516456302013771 00000000000000/*************************************************************************** * Copyright (C) 2011 by James K. Larson * * jlarson@pacifier.com * * * * Copyright (C) 2013 Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "imp.h" /* nuc1x register locations */ #define NUC1X_SYS_BASE 0x50000000 #define NUC1X_SYS_WRPROT 0x50000100 #define NUC1X_SYS_IPRSTC1 0x50000008 #define NUC1X_SYSCLK_BASE 0x50000200 #define NUC1X_SYSCLK_PWRCON 0x50000200 #define NUC1X_SYSCLK_CLKSEL0 0x50000210 #define NUC1X_SYSCLK_CLKDIV 0x50000218 #define NUC1X_SYSCLK_AHBCLK 0x50000204 #define NUC1X_FLASH_BASE 0x5000C000 #define NUC1X_FLASH_ISPCON 0x5000C000 #define NUC1X_FLASH_ISPCMD 0x5000C00C #define NUC1X_FLASH_ISPADR 0x5000C004 #define NUC1X_FLASH_ISPDAT 0x5000C008 #define NUC1X_FLASH_ISPTRG 0x5000C010 /* Command register bits */ #define PWRCON_OSC22M (1 << 2) #define PWRCON_XTL12M (1 << 0) #define IPRSTC1_CPU_RST (1<<1) #define IPRSTC1_CHIP_RST (1<<0) #define AHBCLK_ISP_EN (1 << 2) #define ISPCON_ISPEN (1 << 0) #define ISPCON_BS_AP (0 << 1) #define ISPCON_BS_LP (1 << 1) #define ISPCON_CFGUEN (1 << 4) #define ISPCON_LDUEN (1 << 5) #define ISPCON_ISPFF (1 << 6) /* isp commands */ #define ISPCMD_FCTRL (0x2) #define ISPCMD_FCEN (1 << 4) #define ISPCMD_FOEN (1 << 5) #define ISPCMD_ERASE (0x2 | ISPCMD_FOEN) #define ISPCMD_WRITE (0x1 | ISPCMD_FOEN) #define ISPTRG_ISPGO (1 << 0) /* access unlock keys */ #define KEY1 0x59 #define KEY2 0x16 #define KEY3 0x88 #define LOCK 0x00 /* part structs */ static const struct { const char *partname; uint32_t partno; uint16_t num_page; } NuMicroParts[] = { /*PART NO*/ /*PART ID*/ /*NUM PAGE*/ {"NUC100LC1", 0x00010008, 64}, {"NUC100LD1", 0x00010005, 128}, {"NUC100LD2", 0x00010004, 128}, {"NUC100RC1", 0x00010017, 64}, {"NUC100RD1", 0x00010014, 128}, {"NUC100RD2", 0x00010013, 128}, {"NUC100LD3", 0x00010003, 128}, {"NUC100LE3", 0x00010000, 256}, {"NUC100RD3", 0x00010012, 128}, {"NUC100RE3", 0x00010009, 256}, {"NUC100VD2", 0x00010022, 128}, {"NUC100VD3", 0x00010021, 128}, {"NUC100VE3", 0x00010018, 256}, {"NUC120LC1", 0x00012008, 64}, {"NUC120LD1", 0x00012005, 128}, {"NUC120LD2", 0x00012004, 128}, {"NUC120RC1", 0x00012017, 64}, {"NUC120RD1", 0x00012014, 128}, {"NUC120RD2", 0x00012013, 128}, {"NUC120LD3", 0x00012003, 128}, {"NUC120LE3", 0x00012000, 256}, {"NUC120RD3", 0x00012012, 128}, {"NUC120RE3", 0x00012009, 256}, {"NUC120VD2", 0x00012022, 128}, {"NUC120VD3", 0x00012021, 128}, {"NUC120VE3", 0x00012018, 256}, {"NUC122ZD2", 0x00012231, 128}, {"NUC122ZC1", 0x00012235, 64}, {"NUC122LD2", 0x00012204, 128}, {"NUC122LC1", 0x00012208, 64}, {"NUC122RD2", 0x00012213, 128}, {"NUC122RC1", 0x00012217, 64}, {"NUC123ZD4", 0x00012255, 136}, {"NUC123ZC2", 0x00012245, 68}, {"NUC123LD4", 0x00012235, 136}, {"NUC123LC2", 0x00012225, 68}, {"NUC123SD4", 0x00012215, 136}, {"NUC123SC2", 0x00012205, 68}, {"NUC130LC1", 0x00013008, 64}, {"NUC130LD2", 0x00013004, 128}, {"NUC130LE3", 0x00013000, 256}, {"NUC130RC1", 0x00013017, 64}, {"NUC130RD2", 0x00013013, 128}, {"NUC130RE3", 0x00013009, 256}, {"NUC130VE3", 0x00013018, 256}, {"M052L", 0x00005200, 16}, {"M052Z", 0x00005203, 16}, {"M054L", 0x00005400, 32}, {"M054Z", 0x00005403, 32}, {"M058L", 0x00005800, 64}, {"M058Z", 0x00005803, 64}, {"M0516L", 0x00005A00, 128}, {"M0516Z", 0x00005A03, 128}, {"MINI51L", 0x00205100, 8}, {"MINI51Z", 0x00205103, 8}, {"MINI52L", 0x00205200, 16}, {"MINI52Z", 0x00205203, 16}, {"MINI54L", 0x00205400, 32}, {"MINI54Z", 0x00205403, 32}, {"UNKNOWN", 0x00000000, 256}, }; static int nuc1x_unlock(struct flash_bank *bank) { uint32_t is_protected; struct target *target = bank->target; /* Check to see if Nuc is unlocked or not */ int retval = target_read_u32(target, NUC1X_SYS_WRPROT, &is_protected); if (retval != ERROR_OK) return retval; LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected); if (is_protected == 0) { /* means protected - so unlock it */ /* unlock flash registers */ retval = target_write_u32(target, NUC1X_SYS_WRPROT, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_SYS_WRPROT, KEY2); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_SYS_WRPROT, KEY3); if (retval != ERROR_OK) return retval; } /* Check that unlock worked */ retval = target_read_u32(target, NUC1X_SYS_WRPROT, &is_protected); if (retval != ERROR_OK) return retval; if (is_protected == 1) { /* means unprotected */ LOG_DEBUG("protection removed"); } else { LOG_DEBUG("still protected!!"); } return ERROR_OK; } static int nuc1x_reset(struct flash_bank *bank) { struct target *target = bank->target; nuc1x_unlock(bank); int retval = target_write_u32(target, NUC1X_SYS_IPRSTC1, IPRSTC1_CPU_RST); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int nuc1x_reset2lprom(struct flash_bank *bank) { struct target *target = bank->target; nuc1x_unlock(bank); int retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_BS_LP); if (retval != ERROR_OK) return retval; nuc1x_reset(bank); return ERROR_OK; } static int nuc1x_init_iap(struct flash_bank *bank) { struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int retval = nuc1x_unlock(bank); if (retval != ERROR_OK) return retval; /* enable isp clock and ispen bit */ retval = target_write_u32(target, NUC1X_SYSCLK_AHBCLK, AHBCLK_ISP_EN); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_CFGUEN | ISPCON_ISPEN); if (retval != ERROR_OK) return retval; return ERROR_OK; } /* Private bank information for nuc1x. */ struct nuc1x_flash_bank { struct working_area *write_algorithm; int probed; }; /* This is the function called in the config file. */ FLASH_BANK_COMMAND_HANDLER(nuc1x_flash_bank_command) { struct nuc1x_flash_bank *bank_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; LOG_INFO("add flash_bank nuc1x %s", bank->name); bank_info = malloc(sizeof(struct nuc1x_flash_bank)); memset(bank_info, 0, sizeof(struct nuc1x_flash_bank)); bank->driver_priv = bank_info; return ERROR_OK; } /* Protection checking - examines the lock bit. */ static int nuc1x_protect_check(struct flash_bank *bank) { uint32_t is_protected, set; struct target *target = bank->target; int i; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Check to see if Nuc is unlocked or not */ int retval = target_read_u32(target, NUC1X_SYS_WRPROT, &is_protected); if (retval != ERROR_OK) return retval; LOG_INFO("is_protected = 0x%08" PRIx32 "", is_protected); if (is_protected == 0) { /* means protected */ set = 1; } else { set = 0; } for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = set; return ERROR_OK; } static int nuc1x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; uint32_t timeout, status; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_INFO("Nuvoton NUC: Sector Erase ... (%d to %d)", first, last); int retval = nuc1x_reset2lprom(bank); if (retval != ERROR_OK) return retval; retval = nuc1x_init_iap(bank); if (retval != ERROR_OK) return retval; retval = nuc1x_unlock(bank); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_FLASH_ISPCMD, ISPCMD_ERASE); if (retval != ERROR_OK) return retval; for (i = first; i <= last; i++) { LOG_DEBUG("erasing sector %d at address 0x%" PRIx32 "", i, bank->base + bank->sectors[i].offset); retval = target_write_u32(target, NUC1X_FLASH_ISPADR, bank->base + bank->sectors[i].offset); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_FLASH_ISPTRG, ISPTRG_ISPGO); /* This is the only bit available */ if (retval != ERROR_OK) return retval; /* wait for busy to clear - check the GO flag */ timeout = 100; for (;;) { retval = target_read_u32(target, NUC1X_FLASH_ISPTRG, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if (status == 0) break; if (timeout-- <= 0) { LOG_DEBUG("timed out waiting for flash"); return ERROR_FAIL; } busy_sleep(1); /* can use busy sleep for short times. */ } /* check for failure */ retval = target_read_u32(target, NUC1X_FLASH_ISPCON, &status); if (retval != ERROR_OK) return retval; if ((status & ISPCON_ISPFF) != 0) { LOG_DEBUG("failure: 0x%" PRIx32 "", status); /* if bit is set, then must write to it to clear it. */ retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_ISPFF); if (retval != ERROR_OK) return retval; } else { bank->sectors[i].is_erased = 1; } } retval = nuc1x_reset(bank); if (retval != ERROR_OK) return retval; /* done, */ LOG_DEBUG("Erase done."); return ERROR_OK; } /* The write routine stub. */ static int nuc1x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t i, timeout, status; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_INFO("Nuvoton NUC: FLASH Write ..."); int retval = nuc1x_reset2lprom(bank); if (retval != ERROR_OK) return retval; retval = nuc1x_init_iap(bank); if (retval != ERROR_OK) return retval; retval = nuc1x_unlock(bank); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_FLASH_ISPCMD, ISPCMD_WRITE); if (retval != ERROR_OK) return retval; /* program command */ for (i = 0; i < count; i += 4) { LOG_DEBUG("write longword @ %08" PRIX32, (uint32_t)(offset + i)); uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff}; memcpy(padding, buffer + i, MIN(4, count-i)); retval = target_write_u32(target, NUC1X_FLASH_ISPADR, bank->base + offset + i); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, NUC1X_FLASH_ISPDAT, 4, 1, padding); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, NUC1X_FLASH_ISPTRG, ISPTRG_ISPGO); if (retval != ERROR_OK) return retval; /* wait for busy to clear - check the GO flag */ timeout = 100; for (;;) { retval = target_read_u32(target, NUC1X_FLASH_ISPTRG, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if (status == 0) break; if (timeout-- <= 0) { LOG_DEBUG("timed out waiting for flash"); return ERROR_FAIL; } busy_sleep(1); /* can use busy sleep for short times. */ } /* check for failure */ retval = target_read_u32(target, NUC1X_FLASH_ISPCON, &status); if (retval != ERROR_OK) return retval; if ((status & ISPCON_ISPFF) != 0) { LOG_DEBUG("failure: 0x%" PRIx32 "", status); /* if bit is set, then must write to it to clear it. */ retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_ISPFF); if (retval != ERROR_OK) return retval; } else { LOG_DEBUG("Write OK"); } } retval = nuc1x_reset(bank); if (retval != ERROR_OK) return retval; /* done, */ LOG_DEBUG("Write done."); return ERROR_OK; } /* The probe routine for the nuc. Only recognizes the nuc120 right now. */ static int nuc1x_probe(struct flash_bank *bank) { struct target *target = bank->target; struct nuc1x_flash_bank *nuc1x_info = bank->driver_priv; int i; uint16_t num_pages; uint32_t device_id; int page_size; uint32_t base_address = 0x00000000; nuc1x_info->probed = 0; /* read nuc1x device id register */ int retval = target_read_u32(target, 0x50000000, &device_id); if (retval != ERROR_OK) return retval; page_size = 512; /* all nuc parts has 512 byte per sector */ /* search part numbers */ for (i = 0; NuMicroParts[i].partno; i++) { if (NuMicroParts[i].partno == (device_id & 0x0FFFFFFF)) { num_pages = NuMicroParts[i].num_page; break; } } if (!(NuMicroParts[i].partno == 0x00000000)) { LOG_INFO("DeviceID : 0x%08" PRIx32 "", device_id); LOG_INFO("Detect %s%cN!", NuMicroParts[i].partname, (char)('A'+(device_id>>28))); } else { LOG_INFO("No NUC Device Detected..."); return ERROR_FAIL; } if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->size = (num_pages * page_size); bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); for (i = 0; i < num_pages; i++) { bank->sectors[i].offset = i * page_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } nuc1x_info->probed = 1; LOG_DEBUG("Nuvoton NUC: Probed ..."); return ERROR_OK; } /* Standard approach to autoprobing. */ static int nuc1x_auto_probe(struct flash_bank *bank) { struct nuc1x_flash_bank *nuc1x_info = bank->driver_priv; if (nuc1x_info->probed) return ERROR_OK; return nuc1x_probe(bank); } /* Info doesn't really add much, but works correctly. */ static int get_nuc1x_info(struct flash_bank *bank, char *buf, int buf_size) { struct target *target = bank->target; uint32_t i, device_id; /* read nuc1x device id register */ int retval = target_read_u32(target, 0x50000000, &device_id); if (retval != ERROR_OK) return retval; /* search part numbers */ for (i = 0; NuMicroParts[i].partno; i++) { if (NuMicroParts[i].partno == (device_id & 0x0FFFFFFF)) break; } if (!(NuMicroParts[i].partno == 0x00000000)) { LOG_INFO("DeviceID : 0x%08" PRIx32 "", device_id); LOG_INFO("Detect %s%cN!", NuMicroParts[i].partname, (char)('A'+(device_id>>28))); } else { LOG_INFO("No NUC Device Detected..."); return ERROR_FAIL; } return ERROR_OK; } /* The nuc120 doesn't support mass erase, so this will probably be removed soon. * The structure is left for now until I am sure I don't want to add any custom * commands. */ static int nuc1x_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; int retval = ERROR_OK; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_INFO("Nuvoton NUC: Chip Erase ... (may take several seconds)"); return retval; } COMMAND_HANDLER(nuc1x_handle_mass_erase_command) { int i; /* for erasing sectors */ if (CMD_ARGC < 1) { command_print(CMD_CTX, "nuc1x mass_erase "); return ERROR_OK; } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = nuc1x_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; command_print(CMD_CTX, "nuc1x mass erase complete"); } else command_print(CMD_CTX, "nuc1x mass erase failed"); return retval; } static const struct command_registration nuc1x_exec_command_handlers[] = { { .name = "mass_erase", .handler = nuc1x_handle_mass_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Erase entire Flash device.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration nuc1x_command_handlers[] = { { .name = "nuc1x", .mode = COMMAND_ANY, .help = "nuc1x Flash command group", .chain = nuc1x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver nuc1x_flash = { .name = "nuc1x", .commands = nuc1x_command_handlers, .flash_bank_command = nuc1x_flash_bank_command, .erase = nuc1x_erase, .write = nuc1x_write, .read = default_flash_read, .probe = nuc1x_probe, .auto_probe = nuc1x_auto_probe, .erase_check = default_flash_blank_check, .protect_check = nuc1x_protect_check, .info = get_nuc1x_info, }; openocd-0.9.0/src/flash/nor/dsp5680xx_flash.c0000644000175000017500000002052612315575360015600 00000000000000/*************************************************************************** * Copyright (C) 2011 by Rodrigo L. Rosa * * rodrigorosa.LG@gmail.com * * * * Based on a file written by: * * Kevin McGuire * * Marcel Wijlaars * * Michael Ashton * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file dsp5680xx_flash.c * @author Rodrigo L. Rosa * @date Thu Jun 9 18:21:58 2011 * * @brief This file implements the basic functions to run flashing commands * from the TCL interface. * It allows the user to flash the Freescale 5680xx DSP. * * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include static int dsp5680xx_build_sector_list(struct flash_bank *bank) { uint32_t offset = HFM_FLASH_BASE_ADDR; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); int i; for (i = 0; i < bank->num_sectors; ++i) { bank->sectors[i].offset = i * HFM_SECTOR_SIZE; bank->sectors[i].size = HFM_SECTOR_SIZE; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = -1; } LOG_USER("%s not tested yet.", __func__); return ERROR_OK; } /* flash bank dsp5680xx 0 0 0 0 */ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command) { bank->base = HFM_FLASH_BASE_ADDR; bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */ bank->num_sectors = HFM_SECTOR_COUNT; dsp5680xx_build_sector_list(bank); return ERROR_OK; } /** * A memory mapped register (PROT) holds information regarding sector protection. * Protection refers to undesired core access. * The value in this register is loaded from flash upon reset. * * @param bank * * @return */ static int dsp5680xx_flash_protect_check(struct flash_bank *bank) { int retval = ERROR_OK; uint16_t protected = 0; retval = dsp5680xx_f_protect_check(bank->target, &protected); if (retval != ERROR_OK) { for (int i = 0; i < HFM_SECTOR_COUNT; i++) bank->sectors[i].is_protected = -1; return ERROR_OK; } for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) { if (protected & 1) { bank->sectors[2 * i].is_protected = 1; bank->sectors[2 * i + 1].is_protected = 1; } else { bank->sectors[2 * i].is_protected = 0; bank->sectors[2 * i + 1].is_protected = 0; } protected = (protected >> 1); } return retval; } /** * Protection funcionality is not implemented. * The current implementation applies/removes security on the chip. * The chip is effectively secured/unsecured after the first reset * following the execution of this function. * * @param bank * @param set Apply or remove security on the chip. * @param first This parameter is ignored. * @param last This parameter is ignored. * * @return */ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, int last) { /** * This applies security to flash module after next reset, it does * not actually apply protection (protection refers to undesired access from the core) */ int retval; if (set) retval = dsp5680xx_f_lock(bank->target); else { retval = dsp5680xx_f_unlock(bank->target); if (retval == ERROR_OK) { /* mark all as erased */ for (int i = 0; i <= (HFM_SECTOR_COUNT - 1); i++) /* FM does not recognize it as erased if erased via JTAG. */ bank->sectors[i].is_erased = 1; } } return retval; } /** * The dsp5680xx use word addressing. The "/2" that appear in the following code * are a workaround for the fact that OpenOCD uses byte addressing. * * @param bank * @param buffer Data to write to flash. * @param offset * @param count In bytes (2 bytes per address). * * @return */ static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t* buffer, uint32_t offset, uint32_t count) { int retval; if ((offset + count / 2) > bank->size) { LOG_ERROR("%s: Flash bank cannot fit data.", __func__); return ERROR_FAIL; } if (offset % 2) { /** * Writing to odd addresses not supported. * This chip uses word addressing, Openocd only supports byte addressing. * The workaround results in disabling writing to odd byte addresses */ LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__); return ERROR_FAIL; } retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0); uint32_t addr_word; for (addr_word = bank->base + offset / 2; addr_word < count / 2; addr_word += (HFM_SECTOR_SIZE / 2)) { if (retval == ERROR_OK) bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0; else bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1; } return retval; } static int dsp5680xx_probe(struct flash_bank *bank) { LOG_DEBUG("%s not implemented", __func__); return ERROR_OK; } /** * The flash module (FM) on the dsp5680xx supports both individual sector * and mass erase of the flash memory. * If this function is called with @first == @last == 0 or if @first is the * first sector (#0) and @last is the last sector then the mass erase command * is executed (much faster than erasing each sector individually). * * @param bank * @param first * @param last * * @return */ static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last) { int retval; retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1)))) last = HFM_SECTOR_COUNT - 1; if (retval == ERROR_OK) for (int i = first; i <= last; i++) bank->sectors[i].is_erased = 1; else /** * If an error occurred unknown status *is set even though some sector could have been correctly erased. */ for (int i = first; i <= last; i++) bank->sectors[i].is_erased = -1; return retval; } /** * The flash module (FM) on the dsp5680xx support a blank check function. * This function executes the FM's blank check functionality on each and every sector. * * @param bank * * @return */ static int dsp5680xx_flash_erase_check(struct flash_bank *bank) { int retval = ERROR_OK; uint8_t erased = 0; uint32_t i; for (i = 0; i < HFM_SECTOR_COUNT; i++) { if (bank->sectors[i].is_erased == -1) { retval = dsp5680xx_f_erase_check(bank->target, &erased, i); if (retval != ERROR_OK) { bank->sectors[i].is_erased = -1; } else { if (erased) bank->sectors[i].is_erased = 1; else bank->sectors[i].is_erased = 0; } } } return retval; } struct flash_driver dsp5680xx_flash = { .name = "dsp5680xx_flash", .flash_bank_command = dsp5680xx_flash_bank_command, .erase = dsp5680xx_flash_erase, .protect = dsp5680xx_flash_protect, .write = dsp5680xx_flash_write, /* .read = default_flash_read, */ .probe = dsp5680xx_probe, .auto_probe = dsp5680xx_probe, .erase_check = dsp5680xx_flash_erase_check, .protect_check = dsp5680xx_flash_protect_check, }; openocd-0.9.0/src/flash/nor/lpcspifi.c0000644000175000017500000010114512516456302014535 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "spi.h" #include #include #include #include /* Offsets from ssp_base into config & data registers */ #define SSP_CR0 (0x00) /* Control register 0 */ #define SSP_CR1 (0x04) /* Control register 1 */ #define SSP_DATA (0x08) /* Data register (TX and RX) */ #define SSP_SR (0x0C) /* Status register */ #define SSP_CPSR (0x10) /* Clock prescale register */ /* Status register fields */ #define SSP_BSY (0x00000010) /* Timeout in ms */ #define SSP_CMD_TIMEOUT (100) #define SSP_PROBE_TIMEOUT (100) #define SSP_MAX_TIMEOUT (3000) /* Size of the stack to alloc in the working area for the execution of * the ROM spifi_init() function */ #define SPIFI_INIT_STACK_SIZE 512 struct lpcspifi_flash_bank { int probed; uint32_t ssp_base; uint32_t io_base; uint32_t ioconfig_base; uint32_t bank_num; uint32_t max_spi_clock_mhz; const struct flash_device *dev; }; struct lpcspifi_target { char *name; uint32_t tap_idcode; uint32_t spifi_base; uint32_t ssp_base; uint32_t io_base; uint32_t ioconfig_base; /* base address for the port word pin registers */ }; static const struct lpcspifi_target target_devices[] = { /* name, tap_idcode, spifi_base, ssp_base, io_base, ioconfig_base */ { "LPC43xx/18xx", 0x4ba00477, 0x14000000, 0x40083000, 0x400F4000, 0x40086000 }, { NULL, 0, 0, 0, 0, 0 } }; /* flash_bank lpcspifi */ FLASH_BANK_COMMAND_HANDLER(lpcspifi_flash_bank_command) { struct lpcspifi_flash_bank *lpcspifi_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; lpcspifi_info = malloc(sizeof(struct lpcspifi_flash_bank)); if (lpcspifi_info == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } bank->driver_priv = lpcspifi_info; lpcspifi_info->probed = 0; return ERROR_OK; } static inline int ioconfig_write_reg(struct target *target, uint32_t ioconfig_base, uint32_t offset, uint32_t value) { return target_write_u32(target, ioconfig_base + offset, value); } static inline int ssp_write_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t value) { return target_write_u32(target, ssp_base + offset, value); } static inline int io_write_reg(struct target *target, uint32_t io_base, uint32_t offset, uint32_t value) { return target_write_u32(target, io_base + offset, value); } static inline int ssp_read_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t *value) { return target_read_u32(target, ssp_base + offset, value); } static int ssp_setcs(struct target *target, uint32_t io_base, unsigned int value) { return io_write_reg(target, io_base, 0x12ac, value ? 0xffffffff : 0x00000000); } /* Poll the SSP busy flag. When this comes back as 0, the transfer is complete * and the controller is idle. */ static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout) { long long endtime; uint32_t value; int retval; retval = ssp_read_reg(target, ssp_base, SSP_SR, &value); if ((retval == ERROR_OK) && (value & SSP_BSY) == 0) return ERROR_OK; else if (retval != ERROR_OK) return retval; endtime = timeval_ms() + timeout; do { alive_sleep(1); retval = ssp_read_reg(target, ssp_base, SSP_SR, &value); if ((retval == ERROR_OK) && (value & SSP_BSY) == 0) return ERROR_OK; else if (retval != ERROR_OK) return retval; } while (timeval_ms() < endtime); LOG_ERROR("Timeout while polling BSY"); return ERROR_FLASH_OPERATION_FAILED; } /* Un-initialize the ssp module and initialize the SPIFI module */ static int lpcspifi_set_hw_mode(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; struct armv7m_algorithm armv7m_info; struct working_area *spifi_init_algorithm; struct reg_param reg_params[2]; int retval = ERROR_OK; LOG_DEBUG("Uninitializing LPC43xx SSP"); /* Turn off the SSP module */ retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_init.S for src */ static const uint8_t spifi_init_code[] = { 0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02, 0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01, 0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00, 0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41, 0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46, 0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21, 0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03, 0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30, 0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01, 0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03, 0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; LOG_DEBUG("Allocating working area for SPIFI init algorithm"); /* Get memory for spifi initialization algorithm */ retval = target_alloc_working_area(target, sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE, &spifi_init_algorithm); if (retval != ERROR_OK) { LOG_ERROR("Insufficient working area to initialize SPIFI "\ "module. You must allocate at least %zdB of working "\ "area in order to use this driver.", sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE ); return retval; } LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32, spifi_init_algorithm->address); /* Write algorithm to working area */ retval = target_write_buffer(target, spifi_init_algorithm->address, sizeof(spifi_init_code), spifi_init_code ); if (retval != ERROR_OK) { target_free_working_area(target, spifi_init_algorithm); return retval; } init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* spifi clk speed */ /* the spifi_init() rom API makes use of the stack */ init_reg_param(®_params[1], "sp", 32, PARAM_OUT); /* For now, the algorithm will set up the SPIFI module * @ the IRC clock speed. In the future, it could be made * a bit smarter to use other clock sources if the user has * already configured them in order to speed up memory- * mapped reads. */ buf_set_u32(reg_params[0].value, 0, 32, 12); /* valid stack pointer */ buf_set_u32(reg_params[1].value, 0, 32, (spifi_init_algorithm->address + sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE) & ~7UL); /* Run the algorithm */ LOG_DEBUG("Running SPIFI init algorithm"); retval = target_run_algorithm(target, 0 , NULL, 2, reg_params, spifi_init_algorithm->address, spifi_init_algorithm->address + sizeof(spifi_init_code) - 2, 1000, &armv7m_info); if (retval != ERROR_OK) LOG_ERROR("Error executing SPIFI init algorithm"); target_free_working_area(target, spifi_init_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); return retval; } /* Initialize the ssp module */ static int lpcspifi_set_sw_mode(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t ioconfig_base = lpcspifi_info->ioconfig_base; int retval = ERROR_OK; /* Re-initialize SPIFI. There are a couple of errata on this, so this makes sure that nothing's in an unhappy state. */ retval = lpcspifi_set_hw_mode(bank); /* If we couldn't initialize hardware mode, don't even bother continuing */ if (retval != ERROR_OK) return retval; /* Initialize the pins */ retval = ioconfig_write_reg(target, ioconfig_base, 0x194, 0x00000040); if (retval == ERROR_OK) retval = ioconfig_write_reg(target, ioconfig_base, 0x1a0, 0x00000044); if (retval == ERROR_OK) retval = ioconfig_write_reg(target, ioconfig_base, 0x190, 0x00000040); if (retval == ERROR_OK) retval = ioconfig_write_reg(target, ioconfig_base, 0x19c, 0x000000ed); if (retval == ERROR_OK) retval = ioconfig_write_reg(target, ioconfig_base, 0x198, 0x000000ed); if (retval == ERROR_OK) retval = ioconfig_write_reg(target, ioconfig_base, 0x18c, 0x000000ea); /* Set CS high & as an output */ if (retval == ERROR_OK) retval = io_write_reg(target, io_base, 0x12ac, 0xffffffff); if (retval == ERROR_OK) retval = io_write_reg(target, io_base, 0x2014, 0x00000800); /* Initialize the module */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_CR0, 0x00000007); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_CPSR, 0x00000008); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000002); /* If something didn't work out, attempt to return SPIFI to HW mode */ if (retval != ERROR_OK) lpcspifi_set_hw_mode(bank); return retval; } /* Read the status register of the external SPI flash chip. */ static int read_status_reg(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t value; int retval = ERROR_OK; retval = ssp_setcs(target, io_base, 0); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_STATUS); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); /* Dummy write to clock in the register */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 1); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) *status = value; return retval; } /* check for BSY bit in flash status register */ /* timeout in ms */ static int wait_till_ready(struct flash_bank *bank, int timeout) { uint32_t status; int retval; long long endtime; endtime = timeval_ms() + timeout; do { /* read flash status register */ retval = read_status_reg(bank, &status); if (retval != ERROR_OK) return retval; if ((status & SPIFLASH_BSY_BIT) == 0) return ERROR_OK; alive_sleep(1); } while (timeval_ms() < endtime); LOG_ERROR("timeout waiting for flash to finish write/erase operation"); return ERROR_FAIL; } /* Send "write enable" command to SPI flash chip. */ static int lpcspifi_write_enable(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t status, value; int retval = ERROR_OK; retval = ssp_setcs(target, io_base, 0); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_WRITE_ENABLE); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 1); /* read flash status register */ if (retval == ERROR_OK) retval = read_status_reg(bank, &status); if (retval != ERROR_OK) return retval; /* Check write enabled */ if ((status & SPIFLASH_WE_BIT) == 0) { LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status); return ERROR_FAIL; } return retval; } static int lpcspifi_bulk_erase(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t value; int retval = ERROR_OK; retval = lpcspifi_set_sw_mode(bank); if (retval == ERROR_OK) retval = lpcspifi_write_enable(bank); /* send SPI command "bulk erase" */ if (retval == ERROR_OK) ssp_setcs(target, io_base, 0); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, lpcspifi_info->dev->chip_erase_cmd); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 1); /* poll flash BSY for self-timed bulk erase */ if (retval == ERROR_OK) retval = wait_till_ready(bank, bank->num_sectors*SSP_MAX_TIMEOUT); return retval; } static int lpcspifi_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_info; struct working_area *erase_algorithm; int retval = ERROR_OK; int sector; LOG_DEBUG("erase from sector %d to sector %d", first, last); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Flash sector invalid"); return ERROR_FLASH_SECTOR_INVALID; } if (!(lpcspifi_info->probed)) { LOG_ERROR("Flash bank not probed"); return ERROR_FLASH_BANK_NOT_PROBED; } for (sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } /* If we're erasing the entire chip and the flash supports * it, use a bulk erase instead of going sector-by-sector. */ if (first == 0 && last == (bank->num_sectors - 1) && lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) { LOG_DEBUG("Chip supports the bulk erase command."\ " Will use bulk erase instead of sector-by-sector erase."); retval = lpcspifi_bulk_erase(bank); if (retval == ERROR_OK) { retval = lpcspifi_set_hw_mode(bank); return retval; } else LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase."); } retval = lpcspifi_set_hw_mode(bank); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_erase.S for src */ static const uint8_t lpcspifi_flash_erase_code[] = { 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81, 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81, 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80, 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18, 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08, 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08, 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08, 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80, 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8, 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80, 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49, 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29, 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8, 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf, 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7, 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; /* Get memory for spifi initialization algorithm */ retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code), &erase_algorithm); if (retval != ERROR_OK) { LOG_ERROR("Insufficient working area. You must configure a working"\ " area of at least %zdB in order to erase SPIFI flash.", sizeof(lpcspifi_flash_erase_code)); return retval; } /* Write algorithm to working area */ retval = target_write_buffer(target, erase_algorithm->address, sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code); if (retval != ERROR_OK) { target_free_working_area(target, erase_algorithm); return retval; } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* Start address */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* Sector count */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* Erase command */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* Sector size */ buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset); buf_set_u32(reg_params[1].value, 0, 32, last - first + 1); buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd); buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size); /* Run the algorithm */ retval = target_run_algorithm(target, 0 , NULL, 4, reg_params, erase_algorithm->address, erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4, 3000*(last - first + 1), &armv7m_info); if (retval != ERROR_OK) LOG_ERROR("Error executing flash erase algorithm"); target_free_working_area(target, erase_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); retval = lpcspifi_set_hw_mode(bank); return retval; } static int lpcspifi_protect(struct flash_bank *bank, int set, int first, int last) { int sector; for (sector = first; sector <= last; sector++) bank->sectors[sector].is_protected = set; return ERROR_OK; } static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t page_size, fifo_size; struct working_area *fifo; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; struct working_area *write_algorithm; int sector; int retval = ERROR_OK; LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > lpcspifi_info->dev->size_in_bytes) { LOG_WARNING("Writes past end of flash. Extra data discarded."); count = lpcspifi_info->dev->size_in_bytes - offset; } /* Check sector protection */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } page_size = lpcspifi_info->dev->pagesize; retval = lpcspifi_set_hw_mode(bank); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_write.S for src */ static const uint8_t lpcspifi_flash_write_code[] = { 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81, 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81, 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80, 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18, 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08, 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08, 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08, 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80, 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45, 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8, 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8, 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8, 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8, 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8, 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b, 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b, 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45, 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8, 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0, 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20, 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46, 0x00, 0xbe, 0xff, 0xff }; if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_ERROR("Insufficient working area. You must configure"\ " a working area > %zdB in order to write to SPIFI flash.", sizeof(lpcspifi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; retval = target_write_buffer(target, write_algorithm->address, sizeof(lpcspifi_flash_write_code), lpcspifi_flash_write_code); if (retval != ERROR_OK) { target_free_working_area(target, write_algorithm); return retval; } /* FIFO allocation */ fifo_size = target_get_working_area_avail(target); if (fifo_size == 0) { /* if we already allocated the writing code but failed to get fifo * space, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_ERROR("Insufficient working area. Please allocate at least"\ " %zdB of working area to enable flash writes.", sizeof(lpcspifi_flash_write_code) + 1 ); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } else if (fifo_size < page_size) LOG_WARNING("Working area size is limited; flash writes may be"\ " slow. Increase working area size to at least %zdB"\ " to reduce write times.", (size_t)(sizeof(lpcspifi_flash_write_code) + page_size) ); else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */ fifo_size = 0x2000; if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* page size */ buf_set_u32(reg_params[0].value, 0, 32, fifo->address); buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size); buf_set_u32(reg_params[2].value, 0, 32, offset); buf_set_u32(reg_params[3].value, 0, 32, count); buf_set_u32(reg_params[4].value, 0, 32, page_size); retval = target_run_flash_async_algorithm(target, buffer, count, 1, 0, NULL, 5, reg_params, fifo->address, fifo->size, write_algorithm->address, 0, &armv7m_info ); if (retval != ERROR_OK) LOG_ERROR("Error executing flash write algorithm"); target_free_working_area(target, fifo); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); /* Switch to HW mode before return to prompt */ retval = lpcspifi_set_hw_mode(bank); return retval; } /* Return ID of flash device */ /* On exit, SW mode is kept */ static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t value; uint8_t id_buf[3] = {0, 0, 0}; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("Getting ID"); retval = lpcspifi_set_sw_mode(bank); if (retval != ERROR_OK) return retval; /* poll WIP */ if (retval == ERROR_OK) retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT); /* Send SPI command "read ID" */ if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 0); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[0] = value; /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[1] = value; /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[2] = value; if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 1); if (retval == ERROR_OK) *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0]; return retval; } static int lpcspifi_probe(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base; uint32_t io_base; uint32_t ioconfig_base; struct flash_sector *sectors; uint32_t id = 0; /* silence uninitialized warning */ const struct lpcspifi_target *target_device; int retval; /* If we've already probed, we should be fine to skip this time. */ if (lpcspifi_info->probed) return ERROR_OK; lpcspifi_info->probed = 0; for (target_device = target_devices ; target_device->name ; ++target_device) if (target_device->tap_idcode == target->tap->idcode) break; if (!target_device->name) { LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SPIFI capable", target->tap->idcode); return ERROR_FAIL; } ssp_base = target_device->ssp_base; io_base = target_device->io_base; ioconfig_base = target_device->ioconfig_base; lpcspifi_info->ssp_base = ssp_base; lpcspifi_info->io_base = io_base; lpcspifi_info->ioconfig_base = ioconfig_base; lpcspifi_info->bank_num = bank->bank_number; LOG_DEBUG("Valid SPIFI on device %s at address 0x%" PRIx32, target_device->name, bank->base); /* read and decode flash ID; returns in SW mode */ retval = lpcspifi_read_flash_id(bank, &id); if (retval != ERROR_OK) return retval; retval = lpcspifi_set_hw_mode(bank); if (retval != ERROR_OK) return retval; lpcspifi_info->dev = NULL; for (const struct flash_device *p = flash_devices; p->name ; p++) if (p->device_id == id) { lpcspifi_info->dev = p; break; } if (!lpcspifi_info->dev) { LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); return ERROR_FAIL; } LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", lpcspifi_info->dev->name, lpcspifi_info->dev->device_id); /* Set correct size value */ bank->size = lpcspifi_info->dev->size_in_bytes; /* create and fill sectors array */ bank->num_sectors = lpcspifi_info->dev->size_in_bytes / lpcspifi_info->dev->sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); if (sectors == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } for (int sector = 0; sector < bank->num_sectors; sector++) { sectors[sector].offset = sector * lpcspifi_info->dev->sectorsize; sectors[sector].size = lpcspifi_info->dev->sectorsize; sectors[sector].is_erased = -1; sectors[sector].is_protected = 0; } bank->sectors = sectors; lpcspifi_info->probed = 1; return ERROR_OK; } static int lpcspifi_auto_probe(struct flash_bank *bank) { struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; if (lpcspifi_info->probed) return ERROR_OK; return lpcspifi_probe(bank); } static int lpcspifi_protect_check(struct flash_bank *bank) { /* Nothing to do. Protection is only handled in SW. */ return ERROR_OK; } static int get_lpcspifi_info(struct flash_bank *bank, char *buf, int buf_size) { struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; if (!(lpcspifi_info->probed)) { snprintf(buf, buf_size, "\nSPIFI flash bank not probed yet\n"); return ERROR_OK; } snprintf(buf, buf_size, "\nSPIFI flash information:\n" " Device \'%s\' (ID 0x%08" PRIx32 ")\n", lpcspifi_info->dev->name, lpcspifi_info->dev->device_id); return ERROR_OK; } struct flash_driver lpcspifi_flash = { .name = "lpcspifi", .flash_bank_command = lpcspifi_flash_bank_command, .erase = lpcspifi_erase, .protect = lpcspifi_protect, .write = lpcspifi_write, .read = default_flash_read, .probe = lpcspifi_probe, .auto_probe = lpcspifi_auto_probe, .erase_check = default_flash_blank_check, .protect_check = lpcspifi_protect_check, .info = get_lpcspifi_info, }; openocd-0.9.0/src/flash/nor/pic32mx.c0000644000175000017500000006524212315575360014223 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by John McCarthy * * jgmcc@magma.ca * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "imp.h" #include #include #include #define PIC32MX_MANUF_ID 0x029 /* pic32mx memory locations */ #define PIC32MX_PHYS_RAM 0x00000000 #define PIC32MX_PHYS_PGM_FLASH 0x1D000000 #define PIC32MX_PHYS_PERIPHERALS 0x1F800000 #define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000 /* * Translate Virtual and Physical addresses. * Note: These macros only work for KSEG0/KSEG1 addresses. */ #define Virt2Phys(v) ((v) & 0x1FFFFFFF) /* pic32mx configuration register locations */ #define PIC32MX_DEVCFG0_1_2 0xBFC00BFC #define PIC32MX_DEVCFG0 0xBFC02FFC #define PIC32MX_DEVCFG1 0xBFC02FF8 #define PIC32MX_DEVCFG2 0xBFC02FF4 #define PIC32MX_DEVCFG3 0xBFC02FF0 #define PIC32MX_DEVID 0xBF80F220 #define PIC32MX_BMXPFMSZ 0xBF882060 #define PIC32MX_BMXBOOTSZ 0xBF882070 #define PIC32MX_BMXDRMSZ 0xBF882040 /* pic32mx flash controller register locations */ #define PIC32MX_NVMCON 0xBF80F400 #define PIC32MX_NVMCONCLR 0xBF80F404 #define PIC32MX_NVMCONSET 0xBF80F408 #define PIC32MX_NVMCONINV 0xBF80F40C #define NVMCON_NVMWR (1 << 15) #define NVMCON_NVMWREN (1 << 14) #define NVMCON_NVMERR (1 << 13) #define NVMCON_LVDERR (1 << 12) #define NVMCON_LVDSTAT (1 << 11) #define NVMCON_OP_PFM_ERASE 0x5 #define NVMCON_OP_PAGE_ERASE 0x4 #define NVMCON_OP_ROW_PROG 0x3 #define NVMCON_OP_WORD_PROG 0x1 #define NVMCON_OP_NOP 0x0 #define PIC32MX_NVMKEY 0xBF80F410 #define PIC32MX_NVMADDR 0xBF80F420 #define PIC32MX_NVMADDRCLR 0xBF80F424 #define PIC32MX_NVMADDRSET 0xBF80F428 #define PIC32MX_NVMADDRINV 0xBF80F42C #define PIC32MX_NVMDATA 0xBF80F430 #define PIC32MX_NVMSRCADDR 0xBF80F440 /* flash unlock keys */ #define NVMKEY1 0xAA996655 #define NVMKEY2 0x556699AA #define MX_1_2 1 /* PIC32mx1xx/2xx */ struct pic32mx_flash_bank { int probed; int dev_type; /* Default 0. 1 for Pic32MX1XX/2XX variant */ }; /* * DEVID values as per PIC32MX Flash Programming Specification Rev J */ static const struct pic32mx_devs_s { uint32_t devid; const char *name; } pic32mx_devs[] = { {0x04A07053, "110F016B"}, {0x04A09053, "110F016C"}, {0x04A0B053, "110F016D"}, {0x04A06053, "120F032B"}, {0x04A08053, "120F032C"}, {0x04A0A053, "120F032D"}, {0x04D07053, "130F064B"}, {0x04D09053, "130F064C"}, {0x04D0B053, "130F064D"}, {0x04D06053, "150F128B"}, {0x04D08053, "150F128C"}, {0x04D0A053, "150F128D"}, {0x04A01053, "210F016B"}, {0x04A03053, "210F016C"}, {0x04A05053, "210F016D"}, {0x04A00053, "220F032B"}, {0x04A02053, "220F032C"}, {0x04A04053, "220F032D"}, {0x04D01053, "230F064B"}, {0x04D03053, "230F064C"}, {0x04D05053, "230F064D"}, {0x04D00053, "250F128B"}, {0x04D02053, "250F128C"}, {0x04D04053, "250F128D"}, {0x00938053, "360F512L"}, {0x00934053, "360F256L"}, {0x0092D053, "340F128L"}, {0x0092A053, "320F128L"}, {0x00916053, "340F512H"}, {0x00912053, "340F256H"}, {0x0090D053, "340F128H"}, {0x0090A053, "320F128H"}, {0x00906053, "320F064H"}, {0x00902053, "320F032H"}, {0x00978053, "460F512L"}, {0x00974053, "460F256L"}, {0x0096D053, "440F128L"}, {0x00952053, "440F256H"}, {0x00956053, "440F512H"}, {0x0094D053, "440F128H"}, {0x00942053, "420F032H"}, {0x04307053, "795F512L"}, {0x0430E053, "795F512H"}, {0x04306053, "775F512L"}, {0x0430D053, "775F512H"}, {0x04312053, "775F256L"}, {0x04303053, "775F256H"}, {0x04417053, "764F128L"}, {0x0440B053, "764F128H"}, {0x04341053, "695F512L"}, {0x04325053, "695F512H"}, {0x04311053, "675F512L"}, {0x0430C053, "675F512H"}, {0x04305053, "675F256L"}, {0x0430B053, "675F256H"}, {0x04413053, "664F128L"}, {0x04407053, "664F128H"}, {0x04411053, "664F064L"}, {0x04405053, "664F064H"}, {0x0430F053, "575F512L"}, {0x04309053, "575F512H"}, {0x04333053, "575F256L"}, {0x04317053, "575F256H"}, {0x0440F053, "564F128L"}, {0x04403053, "564F128H"}, {0x0440D053, "564F064L"}, {0x04401053, "564F064H"}, {0x04400053, "534F064H"}, {0x0440C053, "534F064L"}, {0x00000000, NULL} }; /* flash bank pic32mx 0 0 */ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command) { struct pic32mx_flash_bank *pic32mx_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank)); bank->driver_priv = pic32mx_info; pic32mx_info->probed = 0; pic32mx_info->dev_type = 0; return ERROR_OK; } static uint32_t pic32mx_get_flash_status(struct flash_bank *bank) { struct target *target = bank->target; uint32_t status; target_read_u32(target, PIC32MX_NVMCON, &status); return status; } static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout) { uint32_t status; /* wait for busy to clear */ while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) { LOG_DEBUG("status: 0x%" PRIx32, status); alive_sleep(1); } if (timeout <= 0) LOG_DEBUG("timeout: status: 0x%" PRIx32, status); return status; } static int pic32mx_nvm_exec(struct flash_bank *bank, uint32_t op, uint32_t timeout) { struct target *target = bank->target; uint32_t status; target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op); /* unlock flash registers */ target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1); target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2); /* start operation */ target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR); status = pic32mx_wait_status_busy(bank, timeout); /* lock flash registers */ target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN); return status; } static int pic32mx_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv; uint32_t config0_address; uint32_t devcfg0; int s; int num_pages; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (pic32mx_info->dev_type == MX_1_2) config0_address = PIC32MX_DEVCFG0_1_2; else config0_address = PIC32MX_DEVCFG0; target_read_u32(target, config0_address, &devcfg0); if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */ num_pages = 0xffff; /* All pages protected */ else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { if (devcfg0 & (1 << 24)) num_pages = 0; /* All pages unprotected */ else num_pages = 0xffff; /* All pages protected */ } else { /* pgm flash */ if (pic32mx_info->dev_type == MX_1_2) num_pages = (~devcfg0 >> 10) & 0x3f; else num_pages = (~devcfg0 >> 12) & 0xff; } for (s = 0; s < bank->num_sectors && s < num_pages; s++) bank->sectors[s].is_protected = 1; for (; s < bank->num_sectors; s++) bank->sectors[s].is_protected = 0; return ERROR_OK; } static int pic32mx_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; uint32_t status; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first == 0) && (last == (bank->num_sectors - 1)) && (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) { /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM) * we need to use the MTAP to perform a full erase */ LOG_DEBUG("Erasing entire program flash"); status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50); if (status & NVMCON_NVMERR) return ERROR_FLASH_OPERATION_FAILED; if (status & NVMCON_LVDERR) return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } for (i = first; i <= last; i++) { target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset)); status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); if (status & NVMCON_NVMERR) return ERROR_FLASH_OPERATION_FAILED; if (status & NVMCON_LVDERR) return ERROR_FLASH_OPERATION_FAILED; bank->sectors[i].is_erased = 1; } return ERROR_OK; } static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } return ERROR_OK; } /* see contib/loaders/flash/pic32mx.s for src */ static uint32_t pic32mx_flash_write_code[] = { /* write: */ 0x3C08AA99, /* lui $t0, 0xaa99 */ 0x35086655, /* ori $t0, 0x6655 */ 0x3C095566, /* lui $t1, 0x5566 */ 0x352999AA, /* ori $t1, 0x99aa */ 0x3C0ABF80, /* lui $t2, 0xbf80 */ 0x354AF400, /* ori $t2, 0xf400 */ 0x340B4003, /* ori $t3, $zero, 0x4003 */ 0x340C8000, /* ori $t4, $zero, 0x8000 */ /* write_row: */ 0x2CD30080, /* sltiu $s3, $a2, 128 */ 0x16600008, /* bne $s3, $zero, write_word */ 0x340D4000, /* ori $t5, $zero, 0x4000 */ 0xAD450020, /* sw $a1, 32($t2) */ 0xAD440040, /* sw $a0, 64($t2) */ 0x04110016, /* bal progflash */ 0x24840200, /* addiu $a0, $a0, 512 */ 0x24A50200, /* addiu $a1, $a1, 512 */ 0x1000FFF7, /* beq $zero, $zero, write_row */ 0x24C6FF80, /* addiu $a2, $a2, -128 */ /* write_word: */ 0x3C15A000, /* lui $s5, 0xa000 */ 0x36B50000, /* ori $s5, $s5, 0x0 */ 0x00952025, /* or $a0, $a0, $s5 */ 0x10000008, /* beq $zero, $zero, next_word */ 0x340B4001, /* ori $t3, $zero, 0x4001 */ /* prog_word: */ 0x8C940000, /* lw $s4, 0($a0) */ 0xAD540030, /* sw $s4, 48($t2) */ 0xAD450020, /* sw $a1, 32($t2) */ 0x04110009, /* bal progflash */ 0x24840004, /* addiu $a0, $a0, 4 */ 0x24A50004, /* addiu $a1, $a1, 4 */ 0x24C6FFFF, /* addiu $a2, $a2, -1 */ /* next_word: */ 0x14C0FFF8, /* bne $a2, $zero, prog_word */ 0x00000000, /* nop */ /* done: */ 0x10000002, /* beq $zero, $zero, exit */ 0x24040000, /* addiu $a0, $zero, 0 */ /* error: */ 0x26240000, /* addiu $a0, $s1, 0 */ /* exit: */ 0x7000003F, /* sdbbp */ /* progflash: */ 0xAD4B0000, /* sw $t3, 0($t2) */ 0xAD480010, /* sw $t0, 16($t2) */ 0xAD490010, /* sw $t1, 16($t2) */ 0xAD4C0008, /* sw $t4, 8($t2) */ /* waitflash: */ 0x8D500000, /* lw $s0, 0($t2) */ 0x020C8024, /* and $s0, $s0, $t4 */ 0x1600FFFD, /* bne $s0, $zero, waitflash */ 0x00000000, /* nop */ 0x00000000, /* nop */ 0x00000000, /* nop */ 0x00000000, /* nop */ 0x00000000, /* nop */ 0x8D510000, /* lw $s1, 0($t2) */ 0x30113000, /* andi $s1, $zero, 0x3000 */ 0x1620FFEF, /* bne $s1, $zero, error */ 0xAD4D0004, /* sw $t5, 4($t2) */ 0x03E00008, /* jr $ra */ 0x00000000 /* nop */ }; static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[3]; uint32_t row_size; int retval = ERROR_OK; struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv; struct mips32_algorithm mips32_info; /* flash write code */ if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; /* Change values for counters and row size, depending on variant */ if (pic32mx_info->dev_type == MX_1_2) { /* 128 byte row */ pic32mx_flash_write_code[8] = 0x2CD30020; pic32mx_flash_write_code[14] = 0x24840080; pic32mx_flash_write_code[15] = 0x24A50080; pic32mx_flash_write_code[17] = 0x24C6FFE0; row_size = 128; } else { /* 512 byte row */ pic32mx_flash_write_code[8] = 0x2CD30080; pic32mx_flash_write_code[14] = 0x24840200; pic32mx_flash_write_code[15] = 0x24A50200; pic32mx_flash_write_code[17] = 0x24C6FF80; row_size = 512; } uint8_t code[sizeof(pic32mx_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(pic32mx_flash_write_code), pic32mx_flash_write_code); retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; init_reg_param(®_params[0], "a0", 32, PARAM_IN_OUT); init_reg_param(®_params[1], "a1", 32, PARAM_OUT); init_reg_param(®_params[2], "a2", 32, PARAM_OUT); int row_offset = offset % row_size; uint8_t *new_buffer = NULL; if (row_offset && (count >= (row_size / 4))) { new_buffer = malloc(buffer_size); if (new_buffer == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } memset(new_buffer, 0xff, row_offset); address -= row_offset; } else row_offset = 0; while (count > 0) { uint32_t status; uint32_t thisrun_count; if (row_offset) { thisrun_count = (count > ((buffer_size - row_offset) / 4)) ? ((buffer_size - row_offset) / 4) : count; memcpy(new_buffer + row_offset, buffer, thisrun_count * 4); retval = target_write_buffer(target, source->address, row_offset + thisrun_count * 4, new_buffer); if (retval != ERROR_OK) break; } else { thisrun_count = (count > (buffer_size / 4)) ? (buffer_size / 4) : count; retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); if (retval != ERROR_OK) break; } buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address)); buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address)); buf_set_u32(reg_params[2].value, 0, 32, thisrun_count + row_offset / 4); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, 0, 10000, &mips32_info); if (retval != ERROR_OK) { LOG_ERROR("error executing pic32mx flash write algorithm"); retval = ERROR_FLASH_OPERATION_FAILED; break; } status = buf_get_u32(reg_params[0].value, 0, 32); if (status & NVMCON_NVMERR) { LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (status & NVMCON_LVDERR) { LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); retval = ERROR_FLASH_OPERATION_FAILED; break; } buffer += thisrun_count * 4; address += thisrun_count * 4; count -= thisrun_count; if (row_offset) { address += row_offset; row_offset = 0; } } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); if (new_buffer != NULL) free(new_buffer); return retval; } static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word) { struct target *target = bank->target; target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(address)); target_write_u32(target, PIC32MX_NVMDATA, word); return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); } static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint32_t words_remaining = (count / 4); uint32_t bytes_remaining = (count & 0x00000003); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; uint32_t status; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " count: 0x%8.8" PRIx32 "", bank->base, offset, count); if (offset & 0x3) { LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* multiple words (4-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = pic32mx_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); } else if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash writing failed"); return retval; } } else { buffer += words_remaining * 4; address += words_remaining * 4; words_remaining = 0; } } while (words_remaining > 0) { uint32_t value; memcpy(&value, buffer + bytes_written, sizeof(uint32_t)); status = pic32mx_write_word(bank, address, value); if (status & NVMCON_NVMERR) { LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); return ERROR_FLASH_OPERATION_FAILED; } if (status & NVMCON_LVDERR) { LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); return ERROR_FLASH_OPERATION_FAILED; } bytes_written += 4; words_remaining--; address += 4; } if (bytes_remaining) { uint32_t value = 0xffffffff; memcpy(&value, buffer + bytes_written, bytes_remaining); status = pic32mx_write_word(bank, address, value); if (status & NVMCON_NVMERR) { LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); return ERROR_FLASH_OPERATION_FAILED; } if (status & NVMCON_LVDERR) { LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); return ERROR_FLASH_OPERATION_FAILED; } } return ERROR_OK; } static int pic32mx_probe(struct flash_bank *bank) { struct target *target = bank->target; struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv; struct mips32_common *mips32 = target->arch_info; struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int i; uint32_t num_pages = 0; uint32_t device_id; int page_size; pic32mx_info->probed = 0; device_id = ejtag_info->idcode; LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%04x, ver 0x%02x)", device_id, (unsigned)((device_id >> 1) & 0x7ff), (unsigned)((device_id >> 12) & 0xffff), (unsigned)((device_id >> 28) & 0xf)); if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) { LOG_WARNING("Cannot identify target as a PIC32MX family."); return ERROR_FLASH_OPERATION_FAILED; } /* Check for PIC32mx1xx/2xx */ for (i = 0; pic32mx_devs[i].name != NULL; i++) { if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) { if ((*(pic32mx_devs[i].name) == '1') || (*(pic32mx_devs[i].name) == '2')) pic32mx_info->dev_type = MX_1_2; break; } } if (pic32mx_info->dev_type == MX_1_2) page_size = 1024; else page_size = 4096; if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { /* 0x1FC00000: Boot flash size */ #if 0 /* for some reason this register returns 8k for the boot bank size * this does not match the docs, so for now set the boot bank at a * fixed 12k */ if (target_read_u32(target, PIC32MX_BMXBOOTSZ, &num_pages) != ERROR_OK) { LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash"); num_pages = (12 * 1024); } #else /* fixed 12k boot bank - see comments above */ if (pic32mx_info->dev_type == MX_1_2) num_pages = (3 * 1024); else num_pages = (12 * 1024); #endif } else { /* read the flash size from the device */ if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) { if (pic32mx_info->dev_type == MX_1_2) { LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash"); num_pages = (32 * 1024); } else { LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash"); num_pages = (512 * 1024); } } } LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } /* calculate numbers of pages */ num_pages /= page_size; bank->size = (num_pages * page_size); bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); for (i = 0; i < (int)num_pages; i++) { bank->sectors[i].offset = i * page_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } pic32mx_info->probed = 1; return ERROR_OK; } static int pic32mx_auto_probe(struct flash_bank *bank) { struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv; if (pic32mx_info->probed) return ERROR_OK; return pic32mx_probe(bank); } static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size) { struct target *target = bank->target; struct mips32_common *mips32 = target->arch_info; struct mips_ejtag *ejtag_info = &mips32->ejtag_info; uint32_t device_id; int printed = 0, i; device_id = ejtag_info->idcode; if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) { snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (unsigned)((device_id >> 1) & 0x7ff), PIC32MX_MANUF_ID); return ERROR_FLASH_OPERATION_FAILED; } for (i = 0; pic32mx_devs[i].name != NULL; i++) { if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) { printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); break; } } if (pic32mx_devs[i].name == NULL) printed = snprintf(buf, buf_size, "Unknown"); buf += printed; buf_size -= printed; snprintf(buf, buf_size, " Ver: 0x%02x", (unsigned)((device_id >> 28) & 0xf)); return ERROR_OK; } COMMAND_HANDLER(pic32mx_handle_pgm_word_command) { uint32_t address, value; int status, res; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank); if (ERROR_OK != retval) return retval; if (address < bank->base || address >= (bank->base + bank->size)) { command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]); return ERROR_OK; } res = ERROR_OK; status = pic32mx_write_word(bank, address, value); if (status & NVMCON_NVMERR) res = ERROR_FLASH_OPERATION_FAILED; if (status & NVMCON_LVDERR) res = ERROR_FLASH_OPERATION_FAILED; if (res == ERROR_OK) command_print(CMD_CTX, "pic32mx pgm word complete"); else command_print(CMD_CTX, "pic32mx pgm word failed (status = 0x%x)", status); return ERROR_OK; } COMMAND_HANDLER(pic32mx_handle_unlock_command) { uint32_t mchip_cmd; struct target *target = NULL; struct mips_m4k_common *mips_m4k; struct mips_ejtag *ejtag_info; int timeout = 10; if (CMD_ARGC < 1) { command_print(CMD_CTX, "pic32mx unlock "); return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; target = bank->target; mips_m4k = target_to_m4k(target); ejtag_info = &mips_m4k->mips32.ejtag_info; /* we have to use the MTAP to perform a full erase */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP); mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); /* first check status of device */ mchip_cmd = MCHP_STATUS; mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); if (mchip_cmd & (1 << 7)) { /* device is not locked */ command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway"); } /* unlock/erase device */ mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST); jtag_add_sleep(200); mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE); do { mchip_cmd = MCHP_STATUS; mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); if (timeout-- == 0) { LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd); break; } alive_sleep(1); } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3)))); mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST); /* select ejtag tap */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); command_print(CMD_CTX, "pic32mx unlocked.\n" "INFO: a reset or power cycle is required " "for the new settings to take effect."); return ERROR_OK; } static const struct command_registration pic32mx_exec_command_handlers[] = { { .name = "pgm_word", .usage = " ", .handler = pic32mx_handle_pgm_word_command, .mode = COMMAND_EXEC, .help = "program a word", }, { .name = "unlock", .handler = pic32mx_handle_unlock_command, .mode = COMMAND_EXEC, .usage = "[bank_id]", .help = "Unlock/Erase entire device.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration pic32mx_command_handlers[] = { { .name = "pic32mx", .mode = COMMAND_ANY, .help = "pic32mx flash command group", .usage = "", .chain = pic32mx_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver pic32mx_flash = { .name = "pic32mx", .commands = pic32mx_command_handlers, .flash_bank_command = pic32mx_flash_bank_command, .erase = pic32mx_erase, .protect = pic32mx_protect, .write = pic32mx_write, .read = default_flash_read, .probe = pic32mx_probe, .auto_probe = pic32mx_auto_probe, .erase_check = default_flash_blank_check, .protect_check = pic32mx_protect_check, .info = pic32mx_info, }; openocd-0.9.0/src/flash/nor/aduc702x.c0000644000175000017500000003121612315575360014265 00000000000000/*************************************************************************** * Copyright (C) 2008 by Kevin McGuire * * Copyright (C) 2008 by Marcel Wijlaars * * Copyright (C) 2009 by Michael Ashton * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include static int aduc702x_build_sector_list(struct flash_bank *bank); static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms); static int aduc702x_set_write_enable(struct target *target, int enable); #define ADUC702x_FLASH 0xfffff800 #define ADUC702x_FLASH_FEESTA (0*4) #define ADUC702x_FLASH_FEEMOD (1*4) #define ADUC702x_FLASH_FEECON (2*4) #define ADUC702x_FLASH_FEEDAT (3*4) #define ADUC702x_FLASH_FEEADR (4*4) #define ADUC702x_FLASH_FEESIGN (5*4) #define ADUC702x_FLASH_FEEPRO (6*4) #define ADUC702x_FLASH_FEEHIDE (7*4) /* flash bank aduc702x 0 0 0 0 * The ADC7019-28 devices all have the same flash layout */ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command) { bank->base = 0x80000; bank->size = 0xF800; /* top 4k not accessible */ aduc702x_build_sector_list(bank); return ERROR_OK; } static int aduc702x_build_sector_list(struct flash_bank *bank) { /* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */ int i = 0; uint32_t offset = 0; /* sector size is 512 */ bank->num_sectors = bank->size / 512; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (i = 0; i < bank->num_sectors; ++i) { bank->sectors[i].offset = offset; bank->sectors[i].size = 512; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; } return ERROR_OK; } static int aduc702x_protect_check(struct flash_bank *bank) { printf("aduc702x_protect_check not implemented yet.\n"); return ERROR_OK; } static int aduc702x_erase(struct flash_bank *bank, int first, int last) { /* int res; */ int x; int count; /* uint32_t v; */ struct target *target = bank->target; aduc702x_set_write_enable(target, 1); /* mass erase */ if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) { LOG_DEBUG("performing mass erase."); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06); if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) { LOG_ERROR("mass erase failed"); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_OPERATION_FAILED; } LOG_DEBUG("mass erase successful."); return ERROR_OK; } else { unsigned long adr; count = last - first + 1; for (x = 0; x < count; ++x) { adr = bank->base + ((first + x) * 512); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05); if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) { LOG_ERROR("failed to erase sector at address 0x%08lX", adr); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_SECTOR_NOT_ERASED; } LOG_DEBUG("erased sector at address 0x%08lX", adr); } } aduc702x_set_write_enable(target, 0); return ERROR_OK; } static int aduc702x_protect(struct flash_bank *bank, int set, int first, int last) { printf("aduc702x_protect not implemented yet.\n"); return ERROR_FLASH_OPERATION_FAILED; } /* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall * back to another mechanism that does not require onboard RAM * * Caller should not check for other return values specifically */ static int aduc702x_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 7000; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; struct reg_param reg_params[6]; struct arm_algorithm arm_algo; int retval = ERROR_OK; if (((count%2) != 0) || ((offset%2) != 0)) { LOG_ERROR("write block must be multiple of two bytes in offset & length"); return ERROR_FAIL; } /* parameters: r0 - address of source data (absolute) r1 - number of halfwords to be copied r2 - start address in flash (offset from beginning of flash memory) r3 - exit code r4 - base address of flash controller (0xFFFFF800) registers: r5 - scratch r6 - set to 2, used to write flash command */ static const uint32_t aduc702x_flash_write_code[] = { /* <_start>: */ 0xe3a05008, /* mov r5, #8 ; 0x8 */ 0xe5845004, /* str r5, [r4, #4] */ 0xe3a06002, /* mov r6, #2 ; 0x2 */ /* : */ 0xe1c421b0, /* strh r2, [r4, #16] */ 0xe0d050b2, /* ldrh r5, [r0], #2 */ 0xe1c450bc, /* strh r5, [r4, #12] */ 0xe5c46008, /* strb r6, [r4, #8] */ /* : */ 0xe1d430b0, /* ldrh r3, [r4] */ 0xe3130004, /* tst r3, #4 ; 0x4 */ 0x1afffffc, /* bne 1001c */ 0xe2822002, /* add r2, r2, #2 ; 0x2 */ 0xe2511001, /* subs r1, r1, #1 ; 0x1 */ 0x0a000001, /* beq 1003c */ 0xe3130001, /* tst r3, #1 ; 0x1 */ 0x1afffff3, /* bne 1000c */ /* : */ 0xeafffffe /* b 1003c */ }; /* flash write code */ if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } uint8_t code[sizeof(aduc702x_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code), aduc702x_flash_write_code); retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code); if (retval != ERROR_OK) return retval; /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { /* we already allocated the writing code, but failed to get a buffer, *free the algorithm */ target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); init_reg_param(®_params[3], "r3", 32, PARAM_IN); init_reg_param(®_params[4], "r4", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; retval = target_write_buffer(target, source->address, thisrun_count, buffer); if (retval != ERROR_OK) break; buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800); retval = target_run_algorithm(target, 0, NULL, 5, reg_params, write_algorithm->address, write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4, 10000, &arm_algo); if (retval != ERROR_OK) { LOG_ERROR("error executing aduc702x flash write algorithm"); break; } if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) { /* FIX!!!! what does this mean??? replace w/sensible error message */ LOG_ERROR("aduc702x detected error writing flash"); retval = ERROR_FAIL; break; } buffer += thisrun_count; address += thisrun_count; count -= thisrun_count; } target_free_working_area(target, source); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); return retval; } /* All-JTAG, single-access method. Very slow. Used only if there is no * working area available. */ static int aduc702x_write_single(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint32_t x; uint8_t b; struct target *target = bank->target; aduc702x_set_write_enable(target, 1); for (x = 0; x < count; x += 2) { /* FEEADR = address */ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x); /* set up data */ if ((x + 1) == count) { /* last byte */ target_read_u8(target, offset + x + 1, &b); } else b = buffer[x + 1]; target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8)); /* do single-write command */ target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02); if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) { LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x)); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_OPERATION_FAILED; } } LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x)); aduc702x_set_write_enable(target, 0); return ERROR_OK; } static int aduc702x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int retval; /* try using a block write */ retval = aduc702x_write_block(bank, buffer, offset, count); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * use normal (slow) JTAG method */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); retval = aduc702x_write_single(bank, buffer, offset, count); if (retval != ERROR_OK) { LOG_ERROR("slow write failed"); return ERROR_FLASH_OPERATION_FAILED; } } } return retval; } static int aduc702x_probe(struct flash_bank *bank) { return ERROR_OK; } /* sets FEEMOD bit 3 * enable = 1 enables writes & erases, 0 disables them */ static int aduc702x_set_write_enable(struct target *target, int enable) { /* don't bother to preserve int enable bit here */ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0); return ERROR_OK; } /* wait up to timeout_ms for controller to not be busy, * then check whether the command passed or failed. * * this function sleeps 1ms between checks (after the first one), * so in some cases may slow things down without a usleep after the first read */ static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms) { uint8_t v = 4; long long endtime = timeval_ms() + timeout_ms; while (1) { target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); if ((v & 4) == 0) break; alive_sleep(1); if (timeval_ms() >= endtime) break; } if (v & 2) return ERROR_FAIL; /* if a command is ignored, both the success and fail bits may be 0 */ else if ((v & 3) == 0) return ERROR_FAIL; else return ERROR_OK; } struct flash_driver aduc702x_flash = { .name = "aduc702x", .flash_bank_command = aduc702x_flash_bank_command, .erase = aduc702x_erase, .protect = aduc702x_protect, .write = aduc702x_write, .read = default_flash_read, .probe = aduc702x_probe, .auto_probe = aduc702x_probe, .erase_check = default_flash_blank_check, .protect_check = aduc702x_protect_check, }; openocd-0.9.0/src/flash/nor/stmsmi.c0000644000175000017500000004335312315575360014251 00000000000000/*************************************************************************** * Copyright (C) 2010 by Antonio Borneo * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* STM Serial Memory Interface (SMI) controller is a SPI bus controller * specifically designed for SPI memories. * Only SPI "mode 3" (CPOL=1 and CPHA=1) is supported. * Two working modes are available: * - SW mode: the SPI is controlled by SW. Any custom commands can be sent * on the bus. * - HW mode: the SPI but is under SMI control. Memory content is directly * accessible in CPU memory space. CPU can read, write and execute memory * content. */ /* ATTENTION: * To have flash memory mapped in CPU memory space, the SMI controller * have to be in "HW mode". This requires following constraints: * 1) The command "reset init" have to initialize SMI controller and put * it in HW mode; * 2) every command in this file have to return to prompt in HW mode. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "spi.h" #include #include #define SMI_READ_REG(a) (_SMI_READ_REG(a)) #define _SMI_READ_REG(a) \ { \ int __a; \ uint32_t __v; \ \ __a = target_read_u32(target, io_base + (a), &__v); \ if (__a != ERROR_OK) \ return __a; \ __v; \ } #define SMI_WRITE_REG(a, v) \ { \ int __r; \ \ __r = target_write_u32(target, io_base + (a), (v)); \ if (__r != ERROR_OK) \ return __r; \ } #define SMI_POLL_TFF(timeout) \ { \ int __r; \ \ __r = poll_tff(target, io_base, timeout); \ if (__r != ERROR_OK) \ return __r; \ } #define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \ SMI_READ_REG(SMI_CR1) | SMI_SW_MODE) #define SMI_SET_HWWB_MODE() SMI_WRITE_REG(SMI_CR1, \ (SMI_READ_REG(SMI_CR1) | SMI_WB_MODE) & ~SMI_SW_MODE) #define SMI_SET_HW_MODE() SMI_WRITE_REG(SMI_CR1, \ SMI_READ_REG(SMI_CR1) & ~(SMI_SW_MODE | SMI_WB_MODE)) #define SMI_CLEAR_TFF() SMI_WRITE_REG(SMI_SR, ~SMI_TFF) #define SMI_BANK_SIZE (0x01000000) #define SMI_CR1 (0x00) /* Control register 1 */ #define SMI_CR2 (0x04) /* Control register 2 */ #define SMI_SR (0x08) /* Status register */ #define SMI_TR (0x0c) /* TX */ #define SMI_RR (0x10) /* RX */ /* fields in SMI_CR1 */ #define SMI_SW_MODE 0x10000000 /* set to enable SW Mode */ #define SMI_WB_MODE 0x20000000 /* Write Burst Mode */ /* fields in SMI_CR2 */ #define SMI_TX_LEN_1 0x00000001 /* data length = 1 byte */ #define SMI_TX_LEN_4 0x00000004 /* data length = 4 byte */ #define SMI_RX_LEN_3 0x00000030 /* data length = 3 byte */ #define SMI_SEND 0x00000080 /* Send data */ #define SMI_RSR 0x00000400 /* reads status reg */ #define SMI_WE 0x00000800 /* Write Enable */ #define SMI_SEL_BANK0 0x00000000 /* Select Bank0 */ #define SMI_SEL_BANK1 0x00001000 /* Select Bank1 */ #define SMI_SEL_BANK2 0x00002000 /* Select Bank2 */ #define SMI_SEL_BANK3 0x00003000 /* Select Bank3 */ /* fields in SMI_SR */ #define SMI_TFF 0x00000100 /* Transfer Finished Flag */ /* Commands */ #define SMI_READ_ID 0x0000009F /* Read Flash Identification */ /* Timeout in ms */ #define SMI_CMD_TIMEOUT (100) #define SMI_PROBE_TIMEOUT (100) #define SMI_MAX_TIMEOUT (3000) struct stmsmi_flash_bank { int probed; uint32_t io_base; uint32_t bank_num; const struct flash_device *dev; }; struct stmsmi_target { char *name; uint32_t tap_idcode; uint32_t smi_base; uint32_t io_base; }; static const struct stmsmi_target target_devices[] = { /* name, tap_idcode, smi_base, io_base */ { "SPEAr3xx/6xx", 0x07926041, 0xf8000000, 0xfc000000 }, { "STR75x", 0x4f1f0041, 0x80000000, 0x90000000 }, { NULL, 0, 0, 0 } }; FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command) { struct stmsmi_flash_bank *stmsmi_info; LOG_DEBUG("%s", __func__); if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank)); if (stmsmi_info == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } bank->driver_priv = stmsmi_info; stmsmi_info->probed = 0; return ERROR_OK; } /* Poll transmit finished flag */ /* timeout in ms */ static int poll_tff(struct target *target, uint32_t io_base, int timeout) { long long endtime; if (SMI_READ_REG(SMI_SR) & SMI_TFF) return ERROR_OK; endtime = timeval_ms() + timeout; do { alive_sleep(1); if (SMI_READ_REG(SMI_SR) & SMI_TFF) return ERROR_OK; } while (timeval_ms() < endtime); LOG_ERROR("Timeout while polling TFF"); return ERROR_FLASH_OPERATION_FAILED; } /* Read the status register of the external SPI flash chip. * The operation is triggered by setting SMI_RSR bit. * SMI sends the proper SPI command (0x05) and returns value in SMI_SR */ static int read_status_reg(struct flash_bank *bank, uint32_t *status) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; /* clear transmit finished flag */ SMI_CLEAR_TFF(); /* Read status */ SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_RSR); /* Poll transmit finished flag */ SMI_POLL_TFF(SMI_CMD_TIMEOUT); /* clear transmit finished flag */ SMI_CLEAR_TFF(); *status = SMI_READ_REG(SMI_SR) & 0x0000ffff; /* clean-up SMI_CR2 */ SMI_WRITE_REG(SMI_CR2, 0); /* AB: Required ? */ return ERROR_OK; } /* check for WIP (write in progress) bit in status register */ /* timeout in ms */ static int wait_till_ready(struct flash_bank *bank, int timeout) { uint32_t status; int retval; long long endtime; endtime = timeval_ms() + timeout; do { /* read flash status register */ retval = read_status_reg(bank, &status); if (retval != ERROR_OK) return retval; if ((status & SPIFLASH_BSY_BIT) == 0) return ERROR_OK; alive_sleep(1); } while (timeval_ms() < endtime); LOG_ERROR("timeout"); return ERROR_FAIL; } /* Send "write enable" command to SPI flash chip. * The operation is triggered by setting SMI_WE bit, and SMI sends * the proper SPI command (0x06) */ static int smi_write_enable(struct flash_bank *bank) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; uint32_t status; int retval; /* Enter in HW mode */ SMI_SET_HW_MODE(); /* AB: is this correct ?*/ /* clear transmit finished flag */ SMI_CLEAR_TFF(); /* Send write enable command */ SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_WE); /* Poll transmit finished flag */ SMI_POLL_TFF(SMI_CMD_TIMEOUT); /* read flash status register */ retval = read_status_reg(bank, &status); if (retval != ERROR_OK) return retval; /* Check write enabled */ if ((status & SPIFLASH_WE_BIT) == 0) { LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status); return ERROR_FAIL; } return ERROR_OK; } static uint32_t erase_command(struct stmsmi_flash_bank *stmsmi_info, uint32_t offset) { union { uint32_t command; uint8_t x[4]; } cmd; cmd.x[0] = stmsmi_info->dev->erase_cmd; cmd.x[1] = offset >> 16; cmd.x[2] = offset >> 8; cmd.x[3] = offset; return cmd.command; } static int smi_erase_sector(struct flash_bank *bank, int sector) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; uint32_t cmd; int retval; retval = smi_write_enable(bank); if (retval != ERROR_OK) return retval; /* Switch to SW mode to send sector erase command */ SMI_SET_SW_MODE(); /* clear transmit finished flag */ SMI_CLEAR_TFF(); /* send SPI command "block erase" */ cmd = erase_command(stmsmi_info, bank->sectors[sector].offset); SMI_WRITE_REG(SMI_TR, cmd); SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4); /* Poll transmit finished flag */ SMI_POLL_TFF(SMI_CMD_TIMEOUT); /* poll WIP for end of self timed Sector Erase cycle */ retval = wait_till_ready(bank, SMI_MAX_TIMEOUT); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stmsmi_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; int retval = ERROR_OK; int sector; LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Flash sector invalid"); return ERROR_FLASH_SECTOR_INVALID; } if (!(stmsmi_info->probed)) { LOG_ERROR("Flash bank not probed"); return ERROR_FLASH_BANK_NOT_PROBED; } for (sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } for (sector = first; sector <= last; sector++) { retval = smi_erase_sector(bank, sector); if (retval != ERROR_OK) break; keep_alive(); } /* Switch to HW mode before return to prompt */ SMI_SET_HW_MODE(); return retval; } static int stmsmi_protect(struct flash_bank *bank, int set, int first, int last) { int sector; for (sector = first; sector <= last; sector++) bank->sectors[sector].is_protected = set; return ERROR_OK; } static int smi_write_buffer(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t len) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; int retval; LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, __func__, address, len); retval = smi_write_enable(bank); if (retval != ERROR_OK) return retval; /* HW mode, write burst mode */ SMI_SET_HWWB_MODE(); retval = target_write_buffer(target, address, len, buffer); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int stmsmi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; uint32_t cur_count, page_size, page_offset; int sector; int retval = ERROR_OK; LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, __func__, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > stmsmi_info->dev->size_in_bytes) { LOG_WARNING("Write pasts end of flash. Extra data discarded."); count = stmsmi_info->dev->size_in_bytes - offset; } /* Check sector protection */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } page_size = stmsmi_info->dev->pagesize; /* unaligned buffer head */ if (count > 0 && (offset & 3) != 0) { cur_count = 4 - (offset & 3); if (cur_count > count) cur_count = count; retval = smi_write_buffer(bank, buffer, bank->base + offset, cur_count); if (retval != ERROR_OK) goto err; offset += cur_count; buffer += cur_count; count -= cur_count; } page_offset = offset % page_size; /* central part, aligned words */ while (count >= 4) { /* clip block at page boundary */ if (page_offset + count > page_size) cur_count = page_size - page_offset; else cur_count = count & ~3; retval = smi_write_buffer(bank, buffer, bank->base + offset, cur_count); if (retval != ERROR_OK) goto err; page_offset = 0; buffer += cur_count; offset += cur_count; count -= cur_count; keep_alive(); } /* buffer tail */ if (count > 0) retval = smi_write_buffer(bank, buffer, bank->base + offset, count); err: /* Switch to HW mode before return to prompt */ SMI_SET_HW_MODE(); return retval; } /* Return ID of flash device */ /* On exit, SW mode is kept */ static int read_flash_id(struct flash_bank *bank, uint32_t *id) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* poll WIP */ retval = wait_till_ready(bank, SMI_PROBE_TIMEOUT); if (retval != ERROR_OK) return retval; /* enter in SW mode */ SMI_SET_SW_MODE(); /* clear transmit finished flag */ SMI_CLEAR_TFF(); /* Send SPI command "read ID" */ SMI_WRITE_REG(SMI_TR, SMI_READ_ID); SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1); /* Poll transmit finished flag */ SMI_POLL_TFF(SMI_CMD_TIMEOUT); /* clear transmit finished flag */ SMI_CLEAR_TFF(); /* read ID from Receive Register */ *id = SMI_READ_REG(SMI_RR) & 0x00ffffff; return ERROR_OK; } static int stmsmi_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base; struct flash_sector *sectors; uint32_t id = 0; /* silence uninitialized warning */ const struct stmsmi_target *target_device; int retval; if (stmsmi_info->probed) free(bank->sectors); stmsmi_info->probed = 0; for (target_device = target_devices ; target_device->name ; ++target_device) if (target_device->tap_idcode == target->tap->idcode) break; if (!target_device->name) { LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable", target->tap->idcode); return ERROR_FAIL; } switch (bank->base - target_device->smi_base) { case 0: stmsmi_info->bank_num = SMI_SEL_BANK0; break; case SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK1; break; case 2*SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK2; break; case 3*SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK3; break; default: LOG_ERROR("Invalid SMI base address 0x%" PRIx32, bank->base); return ERROR_FAIL; } io_base = target_device->io_base; stmsmi_info->io_base = io_base; LOG_DEBUG("Valid SMI on device %s at address 0x%" PRIx32, target_device->name, bank->base); /* read and decode flash ID; returns in SW mode */ retval = read_flash_id(bank, &id); SMI_SET_HW_MODE(); if (retval != ERROR_OK) return retval; stmsmi_info->dev = NULL; for (const struct flash_device *p = flash_devices; p->name ; p++) if (p->device_id == id) { stmsmi_info->dev = p; break; } if (!stmsmi_info->dev) { LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); return ERROR_FAIL; } LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", stmsmi_info->dev->name, stmsmi_info->dev->device_id); /* Set correct size value */ bank->size = stmsmi_info->dev->size_in_bytes; /* create and fill sectors array */ bank->num_sectors = stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); if (sectors == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } for (int sector = 0; sector < bank->num_sectors; sector++) { sectors[sector].offset = sector * stmsmi_info->dev->sectorsize; sectors[sector].size = stmsmi_info->dev->sectorsize; sectors[sector].is_erased = -1; sectors[sector].is_protected = 1; } bank->sectors = sectors; stmsmi_info->probed = 1; return ERROR_OK; } static int stmsmi_auto_probe(struct flash_bank *bank) { struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; if (stmsmi_info->probed) return ERROR_OK; return stmsmi_probe(bank); } static int stmsmi_protect_check(struct flash_bank *bank) { /* Nothing to do. Protection is only handled in SW. */ return ERROR_OK; } static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size) { struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; if (!(stmsmi_info->probed)) { snprintf(buf, buf_size, "\nSMI flash bank not probed yet\n"); return ERROR_OK; } snprintf(buf, buf_size, "\nSMI flash information:\n" " Device \'%s\' (ID 0x%08" PRIx32 ")\n", stmsmi_info->dev->name, stmsmi_info->dev->device_id); return ERROR_OK; } struct flash_driver stmsmi_flash = { .name = "stmsmi", .flash_bank_command = stmsmi_flash_bank_command, .erase = stmsmi_erase, .protect = stmsmi_protect, .write = stmsmi_write, .read = default_flash_read, .probe = stmsmi_probe, .auto_probe = stmsmi_auto_probe, .erase_check = default_flash_blank_check, .protect_check = stmsmi_protect_check, .info = get_stmsmi_info, }; openocd-0.9.0/src/flash/nor/psoc4.c0000644000175000017500000005651312526201107013754 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * Copyright (C) 2014 by Tomas Vanek (PSoC 4 support derived from STM32) * * vanekt@fbl.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include #include #include #include /* device documets: PSoC(R) 4: PSoC 4200 Family Datasheet Document Number: 001-87197 Rev. *B Revised August 29, 2013 PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM Document No. 001-85634 Rev. *C March 25, 2014 PSoC(R) 4 Registers TRM Spec. Document No. 001-85847 Rev. *A June 25, 2013 CY8C41xx, CY8C42xx Programming Specifications Document No. 001-81799 Rev. *C March 4, 2014 */ /* register locations */ #define PSOC4_CPUSS_SYSREQ 0x40000004 #define PSOC4_CPUSS_SYSARG 0x40000008 #define PSOC4_TEST_MODE 0x40030014 #define PSOC4_SPCIF_GEOMETRY 0x400E0000 #define PSOC4_SFLASH_MACRO 0x0ffff000 /* constants */ #define PSOC4_SROM_KEY1 0xb6 #define PSOC4_SROM_KEY2 0xd3 #define PSOC4_SROM_SYSREQ_BIT (1<<31) #define PSOC4_SROM_HMASTER_BIT (1<<30) #define PSOC4_SROM_PRIVILEGED_BIT (1<<28) #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000 #define PSOC4_SROM_STATUS_FAILED 0xf0000000 #define PSOC4_CMD_GET_SILICON_ID 0 #define PSOC4_CMD_LOAD_LATCH 4 #define PSOC4_CMD_WRITE_ROW 5 #define PSOC4_CMD_PROGRAM_ROW 6 #define PSOC4_CMD_ERASE_ALL 0xa #define PSOC4_CMD_CHECKSUM 0xb #define PSOC4_CMD_WRITE_PROTECTION 0xd #define PSOC4_CHIP_PROT_VIRGIN 0x0 #define PSOC4_CHIP_PROT_OPEN 0x1 #define PSOC4_CHIP_PROT_PROTECTED 0x2 #define PSOC4_CHIP_PROT_KILL 0x4 struct psoc4_chip_details { uint16_t id; const char *type; const char *package; uint32_t flash_size_in_kb; }; /* list of PSoC 4 chips * flash_size_in_kb is not necessary as it can be decoded from SPCIF_GEOMETRY */ const struct psoc4_chip_details psoc4_devices[] = { /* 4200 series */ { 0x04A6, "CY8C4245PVI-482", "SSOP-28", .flash_size_in_kb = 32 }, { 0x04B6, "CY8C4245LQI-483", "QFN-40", .flash_size_in_kb = 32 }, { 0x04C8, "CY8C4245AXI-483", "TQFP-44", .flash_size_in_kb = 32 }, { 0x04FB, "CY8C4245AXI-473", "TQFP-44", .flash_size_in_kb = 32 }, { 0x04F0, "CY8C4244PVI-432", "SSOP-28", .flash_size_in_kb = 16 }, { 0x04F1, "CY8C4244PVI-442", "SSOP-28", .flash_size_in_kb = 16 }, { 0x04F6, "CY8C4244LQI-443", "QFN-40", .flash_size_in_kb = 16 }, { 0x04FA, "CY8C4244AXI-443", "TQFP-44", .flash_size_in_kb = 16 }, /* 4100 series */ { 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 }, { 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 }, { 0x0416, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 }, { 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 }, { 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 }, { 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 }, { 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 }, { 0x041C, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 }, /* CCG1 series */ { 0x0490, "CYPD1103-35FNXI", "CSP-35", .flash_size_in_kb = 32 }, { 0x0489, "CYPD1121-40LQXI", "QFN-40", .flash_size_in_kb = 32 }, { 0x048A, "CYPD1122-40LQXI", "QFN-40", .flash_size_in_kb = 32 }, { 0x0491, "CYPD1131-35FNXI", "CSP-35", .flash_size_in_kb = 32 }, { 0x0498, "CYPD1132-16SXI", "SOIC-16", .flash_size_in_kb = 32 }, { 0x0481, "CYPD1134-28PVXI", "SSOP-28", .flash_size_in_kb = 32 }, { 0x048B, "CYPD1134-40LQXI", "QFN-40", .flash_size_in_kb = 32 }, }; struct psoc4_flash_bank { uint32_t row_size; uint32_t user_bank_size; int probed; uint32_t silicon_id; uint8_t chip_protection; uint8_t cmd_program_row; }; static const struct psoc4_chip_details *psoc4_details_by_id(uint32_t silicon_id) { const struct psoc4_chip_details *p = psoc4_devices; unsigned int i; uint16_t id = silicon_id >> 16; /* ignore die revision */ for (i = 0; i < sizeof(psoc4_devices)/sizeof(psoc4_devices[0]); i++, p++) { if (p->id == id) return p; } LOG_DEBUG("Unknown PSoC 4 device silicon id 0x%08" PRIx32 ".", silicon_id); return NULL; } static const char *psoc4_decode_chip_protection(uint8_t protection) { switch (protection) { case PSOC4_CHIP_PROT_VIRGIN: return "protection VIRGIN"; case PSOC4_CHIP_PROT_OPEN: return "protection open"; case PSOC4_CHIP_PROT_PROTECTED: return "PROTECTED"; case PSOC4_CHIP_PROT_KILL: return "protection KILL"; default: LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection); return ""; } } /* flash bank psoc 0 0 */ FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command) { struct psoc4_flash_bank *psoc4_info; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank)); bank->driver_priv = psoc4_info; psoc4_info->user_bank_size = bank->size; return ERROR_OK; } /* PSoC 4 system ROM request * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service * in sysrem ROM. Algorithm just waits for NMI to finish. * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register. * Otherwise address of memory parameter block is set in CPUSS_SYSARG * and the first parameter is written to the first word of parameter block */ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param, uint32_t *sysreq_params, uint32_t sysreq_params_size) { struct working_area *sysreq_wait_algorithm; struct working_area *sysreq_mem; struct reg_param reg_params[1]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; uint32_t param1 = PSOC4_SROM_KEY1 | ((PSOC4_SROM_KEY2 + cmd) << 8) | (cmd_param << 16); static uint8_t psoc4_sysreq_wait_code[] = { /* system request NMI is served immediately after algo run now we are done: break */ 0x00, 0xbe, /* bkpt 0 */ }; const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4; /* stack must be aligned */ const int stack_size = 196; /* tested stack sizes on PSoC 4: ERASE_ALL 144 PROGRAM_ROW 112 other sysreq 68 */ /* allocate area for sysreq wait code and stack */ if (target_alloc_working_area(target, code_words * 4 + stack_size, &sysreq_wait_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for sysreq code"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; /* Write the code */ retval = target_write_buffer(target, sysreq_wait_algorithm->address, sizeof(psoc4_sysreq_wait_code), psoc4_sysreq_wait_code); if (retval != ERROR_OK) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ goto cleanup_algo; } if (sysreq_params_size) { /* Allocate memory for sysreq_params */ retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem); if (retval != ERROR_OK) { LOG_WARNING("no working area for sysreq parameters"); /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; goto cleanup_algo; } /* Write sysreq_params */ sysreq_params[0] = param1; retval = target_write_buffer(target, sysreq_mem->address, sysreq_params_size, (uint8_t *)sysreq_params); if (retval != ERROR_OK) goto cleanup_mem; /* Set address of sysreq parameters block */ retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, sysreq_mem->address); if (retval != ERROR_OK) goto cleanup_mem; } else { /* Sysreq without memory block of parameters */ /* Set register parameter */ retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, param1); if (retval != ERROR_OK) goto cleanup_mem; } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; /* sysreq stack */ init_reg_param(®_params[0], "sp", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, sysreq_wait_algorithm->address + sysreq_wait_algorithm->size); struct armv7m_common *armv7m = target_to_armv7m(target); if (armv7m == NULL) { /* something is very wrong if armv7m is NULL */ LOG_ERROR("unable to get armv7m target"); goto cleanup; } /* Set SROM request */ retval = target_write_u32(target, PSOC4_CPUSS_SYSREQ, PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd); if (retval != ERROR_OK) goto cleanup; /* Execute wait code */ retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params) / sizeof(*reg_params), reg_params, sysreq_wait_algorithm->address, 0, 1000, &armv7m_info); if (retval != ERROR_OK) LOG_ERROR("sysreq wait code execution failed"); cleanup: destroy_reg_param(®_params[0]); cleanup_mem: if (sysreq_params_size) target_free_working_area(target, sysreq_mem); cleanup_algo: target_free_working_area(target, sysreq_wait_algorithm); return retval; } /* helper routine to get silicon ID from a PSoC 4 chip */ static int psoc4_get_silicon_id(struct target *target, uint32_t *silicon_id, uint8_t *protection) { uint32_t params = PSOC4_SROM_KEY1 | ((PSOC4_SROM_KEY2 + PSOC4_CMD_GET_SILICON_ID) << 8); uint32_t part0, part1; int retval = psoc4_sysreq(target, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, PSOC4_CPUSS_SYSARG, &part0); if (retval != ERROR_OK) return retval; if (part0 == params) { LOG_ERROR("sysreq silicon id request not served"); return ERROR_FAIL; } retval = target_read_u32(target, PSOC4_CPUSS_SYSREQ, &part1); if (retval != ERROR_OK) return retval; uint32_t silicon = ((part0 & 0xffff) << 16) | (((part0 >> 16) & 0xff) << 8) | (part1 & 0xff); uint8_t prot = (part1 >> 12) & 0xff; if (silicon_id) *silicon_id = silicon; if (protection) *protection = prot; LOG_DEBUG("silicon id: 0x%08" PRIx32 "", silicon); LOG_DEBUG("protection: 0x%02" PRIx8 "", prot); return retval; } static int psoc4_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct psoc4_flash_bank *psoc4_info = bank->driver_priv; uint32_t prot_addr = PSOC4_SFLASH_MACRO; uint32_t protection; int i, s; int num_bits; int retval = ERROR_OK; num_bits = bank->num_sectors; for (i = 0; i < num_bits; i += 32) { retval = target_read_u32(target, prot_addr, &protection); if (retval != ERROR_OK) return retval; prot_addr += 4; for (s = 0; s < 32; s++) { if (i + s >= num_bits) break; bank->sectors[i + s].is_protected = (protection & (1 << s)) ? 1 : 0; } } retval = psoc4_get_silicon_id(target, NULL, &(psoc4_info->chip_protection)); return retval; } static int psoc4_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Call "Erase All" system ROM API */ uint32_t param; int retval = psoc4_sysreq(target, PSOC4_CMD_ERASE_ALL, 0, ¶m, sizeof(param)); if (retval == ERROR_OK) /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_erased = 1; return retval; } static int psoc4_erase(struct flash_bank *bank, int first, int last) { struct psoc4_flash_bank *psoc4_info = bank->driver_priv; if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) { LOG_INFO("Autoerase enabled, erase command ignored"); return ERROR_OK; } if ((first == 0) && (last == (bank->num_sectors - 1))) return psoc4_mass_erase(bank); LOG_ERROR("Only mass erase available"); return ERROR_FAIL; } static int psoc4_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; struct psoc4_flash_bank *psoc4_info = bank->driver_priv; if (psoc4_info->probed == 0) return ERROR_FAIL; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t *sysrq_buffer = NULL; int retval; int num_bits = bank->num_sectors; const int param_sz = 8; int prot_sz = num_bits / 8; int chip_prot = PSOC4_CHIP_PROT_OPEN; int flash_macro = 0; /* PSoC 42xx has only macro 0 */ int i; sysrq_buffer = calloc(1, param_sz + prot_sz); if (sysrq_buffer == NULL) { LOG_ERROR("no memory for row buffer"); return ERROR_FAIL; } for (i = first; i < num_bits && i <= last; i++) bank->sectors[i].is_protected = set; uint32_t *p = sysrq_buffer + 2; for (i = 0; i < num_bits; i++) { if (bank->sectors[i].is_protected) p[i / 32] |= 1 << (i % 32); } /* Call "Load Latch" system ROM API */ sysrq_buffer[1] = prot_sz - 1; retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH, 0, /* Byte number in latch from what to write */ sysrq_buffer, param_sz + psoc4_info->row_size); if (retval != ERROR_OK) goto cleanup; /* Call "Write Protection" system ROM API */ retval = psoc4_sysreq(target, PSOC4_CMD_WRITE_PROTECTION, chip_prot | (flash_macro << 8), NULL, 0); cleanup: if (retval != ERROR_OK) psoc4_protect_check(bank); if (sysrq_buffer) free(sysrq_buffer); return retval; } COMMAND_HANDLER(psoc4_handle_flash_autoerase_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; struct psoc4_flash_bank *psoc4_info = bank->driver_priv; bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW; if (CMD_ARGC >= 2) COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable); if (enable) { psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW; LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored."); } else { psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW; LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming."); } return retval; } static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct target *target = bank->target; uint32_t *sysrq_buffer = NULL; int retval = ERROR_OK; const int param_sz = 8; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_ERROR("offset 0x%08" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } sysrq_buffer = malloc(param_sz + psoc4_info->row_size); if (sysrq_buffer == NULL) { LOG_ERROR("no memory for row buffer"); return ERROR_FAIL; } uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz; uint32_t row_num = offset / psoc4_info->row_size; uint32_t row_offset = offset - row_num * psoc4_info->row_size; if (row_offset) memset(row_buffer, 0, row_offset); bool save_poll = jtag_poll_get_enabled(); jtag_poll_set_enabled(false); while (count) { uint32_t chunk_size = psoc4_info->row_size - row_offset; if (chunk_size > count) { chunk_size = count; memset(row_buffer + chunk_size, 0, psoc4_info->row_size - chunk_size); } memcpy(row_buffer + row_offset, buffer, chunk_size); LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "", offset, row_offset, chunk_size); /* Call "Load Latch" system ROM API */ sysrq_buffer[1] = psoc4_info->row_size - 1; retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH, 0, /* Byte number in latch from what to write */ sysrq_buffer, param_sz + psoc4_info->row_size); if (retval != ERROR_OK) goto cleanup; /* Call "Program Row" or "Write Row" system ROM API */ uint32_t sysrq_param; retval = psoc4_sysreq(target, psoc4_info->cmd_program_row, row_num & 0xffff, &sysrq_param, sizeof(sysrq_param)); if (retval != ERROR_OK) goto cleanup; buffer += chunk_size; row_num++; row_offset = 0; count -= chunk_size; } cleanup: jtag_poll_set_enabled(save_poll); if (sysrq_buffer) free(sysrq_buffer); return retval; } static int psoc4_probe(struct flash_bank *bank) { struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct target *target = bank->target; uint32_t flash_size_in_kb = 0; uint32_t max_flash_size_in_kb; uint32_t cpu_id; uint32_t silicon_id; uint32_t row_size; uint32_t base_address = 0x00000000; uint8_t protection; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } psoc4_info->probed = 0; psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW; /* Get the CPUID from the ARM Core * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */ int retval = target_read_u32(target, 0xE000ED00, &cpu_id); if (retval != ERROR_OK) return retval; LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id); /* set page size, protection granularity and max flash size depending on family */ switch ((cpu_id >> 4) & 0xFFF) { case 0xc20: /* M0 -> PSoC4 */ row_size = 128; max_flash_size_in_kb = 32; break; default: LOG_WARNING("Cannot identify target as a PSoC 4 family."); return ERROR_FAIL; } uint32_t spcif_geometry; retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry); if (retval == ERROR_OK) { row_size = 128 * ((spcif_geometry >> 22) & 3); flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024; LOG_INFO("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.", flash_size_in_kb, row_size); } /* Early revisions of ST-Link v2 have some problem reading PSOC4_SPCIF_GEOMETRY and an error is reported late. Dummy read gets this error. */ uint32_t dummy; target_read_u32(target, PSOC4_CPUSS_SYSREQ, &dummy); /* get silicon ID from target. */ retval = psoc4_get_silicon_id(target, &silicon_id, &protection); if (retval != ERROR_OK) return retval; const struct psoc4_chip_details *details = psoc4_details_by_id(silicon_id); if (details) { LOG_INFO("%s device detected.", details->type); if (flash_size_in_kb == 0) flash_size_in_kb = details->flash_size_in_kb; else if (flash_size_in_kb != details->flash_size_in_kb) LOG_ERROR("Flash size mismatch"); } psoc4_info->row_size = row_size; psoc4_info->silicon_id = silicon_id; psoc4_info->chip_protection = protection; /* failed reading flash size or flash size invalid (early silicon), * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("PSoC 4 flash size failed, probe inaccurate - assuming %" PRIu32 " k flash", max_flash_size_in_kb); flash_size_in_kb = max_flash_size_in_kb; } /* if the user sets the size manually then ignore the probed value * this allows us to work around devices that have a invalid flash size register value */ if (psoc4_info->user_bank_size) { LOG_INFO("ignoring flash probed value, using configured bank size"); flash_size_in_kb = psoc4_info->user_bank_size / 1024; } LOG_INFO("flash size = %" PRIu32 " kbytes", flash_size_in_kb); /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); /* calculate numbers of pages */ uint32_t num_rows = flash_size_in_kb * 1024 / row_size; /* check that calculation result makes sense */ assert(num_rows > 0); if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } bank->base = base_address; bank->size = num_rows * row_size; bank->num_sectors = num_rows; bank->sectors = malloc(sizeof(struct flash_sector) * num_rows); uint32_t i; for (i = 0; i < num_rows; i++) { bank->sectors[i].offset = i * row_size; bank->sectors[i].size = row_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } LOG_INFO("flash bank set %" PRIu32 " rows", num_rows); psoc4_info->probed = 1; return ERROR_OK; } static int psoc4_auto_probe(struct flash_bank *bank) { struct psoc4_flash_bank *psoc4_info = bank->driver_priv; if (psoc4_info->probed) return ERROR_OK; return psoc4_probe(bank); } static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size) { struct psoc4_flash_bank *psoc4_info = bank->driver_priv; int printed = 0; if (psoc4_info->probed == 0) return ERROR_FAIL; const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id); if (details) { uint32_t chip_revision = psoc4_info->silicon_id & 0xffff; printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx32 " package %s", details->type, chip_revision, details->package); } else printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "", psoc4_info->silicon_id); buf += printed; buf_size -= printed; const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection); uint32_t size_in_kb = bank->size / 1024; snprintf(buf, buf_size, " flash %" PRIu32 " kb %s", size_in_kb, prot_txt); return ERROR_OK; } COMMAND_HANDLER(psoc4_handle_mass_erase_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (ERROR_OK != retval) return retval; retval = psoc4_mass_erase(bank); if (retval == ERROR_OK) command_print(CMD_CTX, "psoc mass erase complete"); else command_print(CMD_CTX, "psoc mass erase failed"); return retval; } static const struct command_registration psoc4_exec_command_handlers[] = { { .name = "mass_erase", .handler = psoc4_handle_mass_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "Erase entire flash device.", }, { .name = "flash_autoerase", .handler = psoc4_handle_flash_autoerase_command, .mode = COMMAND_EXEC, .usage = "bank_id on|off", .help = "Set autoerase mode for flash bank.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration psoc4_command_handlers[] = { { .name = "psoc4", .mode = COMMAND_ANY, .help = "PSoC 4 flash command group", .usage = "", .chain = psoc4_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct flash_driver psoc4_flash = { .name = "psoc4", .commands = psoc4_command_handlers, .flash_bank_command = psoc4_flash_bank_command, .erase = psoc4_erase, .protect = psoc4_protect, .write = psoc4_write, .read = default_flash_read, .probe = psoc4_probe, .auto_probe = psoc4_auto_probe, .erase_check = default_flash_blank_check, .protect_check = psoc4_protect_check, .info = get_psoc4_info, }; openocd-0.9.0/src/flash/nand/0000755000175000017500000000000012526202226012753 500000000000000openocd-0.9.0/src/flash/nand/ecc.c0000644000175000017500000001437412315575360013612 00000000000000/* * This file contains an ECC algorithm from Toshiba that allows for detection * and correction of 1-bit errors in a 256 byte block of data. * * [ Extracted from the initial code found in some early Linux versions. * The current Linux code is bigger while being faster, but this is of * no real benefit when the bottleneck largely remains the JTAG link. ] * * Copyright (C) 2000-2004 Steven J. Hill (sjhill at realitydiluted.com) * Toshiba America Electronics Components, Inc. * * Copyright (C) 2006 Thomas Gleixner * * This 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 2 or (at your option) any * later version. * * This 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 file; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * As a special exception, if other files instantiate templates or use * macros or inline functions from these files, or you compile these * files and link them with other works to produce a work based on these * files, these files do not by themselves cause the resulting work to be * covered by the GNU General Public License. However the source code for * these files must still be made available in accordance with section (3) * of the GNU General Public License. * * This exception does not invalidate any other reasons why a work based on * this file might be covered by the GNU General Public License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "core.h" /* * Pre-calculated 256-way 1 byte column parity */ static const uint8_t nand_ecc_precalc_table[] = { 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 }; /* * nand_calculate_ecc - Calculate 3-byte ECC for 256-byte block */ int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code) { uint8_t idx, reg1, reg2, reg3, tmp1, tmp2; int i; /* Initialize variables */ reg1 = reg2 = reg3 = 0; /* Build up column parity */ for (i = 0; i < 256; i++) { /* Get CP0 - CP5 from table */ idx = nand_ecc_precalc_table[*dat++]; reg1 ^= (idx & 0x3f); /* All bit XOR = 1 ? */ if (idx & 0x40) { reg3 ^= (uint8_t) i; reg2 ^= ~((uint8_t) i); } } /* Create non-inverted ECC code from line parity */ tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */ tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */ tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */ tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */ tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */ tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */ tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */ tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */ tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */ tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */ tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */ tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */ tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */ tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */ tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */ tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ /* Calculate final ECC code */ #ifdef NAND_ECC_SMC ecc_code[0] = ~tmp2; ecc_code[1] = ~tmp1; #else ecc_code[0] = ~tmp1; ecc_code[1] = ~tmp2; #endif ecc_code[2] = ((~reg1) << 2) | 0x03; return 0; } static inline int countbits(uint32_t b) { int res = 0; for (; b; b >>= 1) res += b & 0x01; return res; } /** * nand_correct_data - Detect and correct a 1 bit error for 256 byte block */ int nand_correct_data(struct nand_device *nand, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { uint8_t s0, s1, s2; #ifdef NAND_ECC_SMC s0 = calc_ecc[0] ^ read_ecc[0]; s1 = calc_ecc[1] ^ read_ecc[1]; s2 = calc_ecc[2] ^ read_ecc[2]; #else s1 = calc_ecc[0] ^ read_ecc[0]; s0 = calc_ecc[1] ^ read_ecc[1]; s2 = calc_ecc[2] ^ read_ecc[2]; #endif if ((s0 | s1 | s2) == 0) return 0; /* Check for a single bit error */ if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { uint32_t byteoffs, bitnum; byteoffs = (s1 << 0) & 0x80; byteoffs |= (s1 << 1) & 0x40; byteoffs |= (s1 << 2) & 0x20; byteoffs |= (s1 << 3) & 0x10; byteoffs |= (s0 >> 4) & 0x08; byteoffs |= (s0 >> 3) & 0x04; byteoffs |= (s0 >> 2) & 0x02; byteoffs |= (s0 >> 1) & 0x01; bitnum = (s2 >> 5) & 0x04; bitnum |= (s2 >> 4) & 0x02; bitnum |= (s2 >> 3) & 0x01; dat[byteoffs] ^= (1 << bitnum); return 1; } if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1) return 1; return -1; } openocd-0.9.0/src/flash/nand/imp.h0000644000175000017500000000373012315575360013644 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NAND_IMP_H #define FLASH_NAND_IMP_H #include "core.h" #include "driver.h" void nand_device_add(struct nand_device *c); int nand_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int nand_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int nand_probe(struct nand_device *nand); int nand_erase(struct nand_device *nand, int first_block, int last_block); int nand_build_bbt(struct nand_device *nand, int first, int last); #endif /* FLASH_NAND_IMP_H */ openocd-0.9.0/src/flash/nand/mx3.c0000644000175000017500000005014412315575360013562 00000000000000 /*************************************************************************** * Copyright (C) 2009 by Alexei Babich * * Rezonans plc., Chelyabinsk, Russia * * impatt@mail.ru * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Freescale iMX3* OpenOCD NAND Flash controller support. * * Many thanks to Ben Dooks for writing s3c24xx driver. */ /* driver tested with STMicro NAND512W3A @imx31 tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", "nand write # file 0" get_next_halfword_from_sram_buffer() not tested */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "mx3.h" #include static const char target_not_halted_err_msg[] = "target must be halted to use mx3 NAND flash controller"; static const char data_block_size_err_msg[] = "minimal granularity is one half-word, %" PRId32 " is incorrect"; static const char sram_buffer_bounds_err_msg[] = "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")"; static const char get_status_register_err_msg[] = "can't get NAND status"; static uint32_t in_sram_address; static unsigned char sign_of_sequental_byte_read; static int test_iomux_settings(struct target *target, uint32_t value, uint32_t mask, const char *text); static int initialize_nf_controller(struct nand_device *nand); static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value); static int get_next_halfword_from_sram_buffer(struct target *target, uint16_t *value); static int poll_for_complete_op(struct target *target, const char *text); static int validate_target_state(struct nand_device *nand); static int do_data_output(struct nand_device *nand); static int imx31_command(struct nand_device *nand, uint8_t command); static int imx31_address(struct nand_device *nand, uint8_t address); NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command) { struct mx3_nf_controller *mx3_nf_info; mx3_nf_info = malloc(sizeof(struct mx3_nf_controller)); if (mx3_nf_info == NULL) { LOG_ERROR("no memory for nand controller"); return ERROR_FAIL; } nand->controller_priv = mx3_nf_info; if (CMD_ARGC < 3) return ERROR_COMMAND_SYNTAX_ERROR; /* * check hwecc requirements */ { int hwecc_needed; hwecc_needed = strcmp(CMD_ARGV[2], "hwecc"); if (hwecc_needed == 0) mx3_nf_info->flags.hw_ecc_enabled = 1; else mx3_nf_info->flags.hw_ecc_enabled = 0; } mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE; mx3_nf_info->fin = MX3_NF_FIN_NONE; mx3_nf_info->flags.target_little_endian = (nand->target->endianness == TARGET_LITTLE_ENDIAN); return ERROR_OK; } static int imx31_init(struct nand_device *nand) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; } { uint16_t buffsize_register_content; target_read_u16(target, MX3_NF_BUFSIZ, &buffsize_register_content); mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f); } { uint32_t pcsr_register_content; target_read_u32(target, MX3_PCSR, &pcsr_register_content); if (!nand->bus_width) { nand->bus_width = (pcsr_register_content & 0x80000000) ? 16 : 8; } else { pcsr_register_content |= ((nand->bus_width == 16) ? 0x80000000 : 0x00000000); target_write_u32(target, MX3_PCSR, pcsr_register_content); } if (!nand->page_size) { nand->page_size = (pcsr_register_content & 0x40000000) ? 2048 : 512; } else { pcsr_register_content |= ((nand->page_size == 2048) ? 0x40000000 : 0x00000000); target_write_u32(target, MX3_PCSR, pcsr_register_content); } if (mx3_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) { LOG_ERROR("NAND controller have only 1 kb SRAM, " "so pagesize 2048 is incompatible with it"); } } { uint32_t cgr_register_content; target_read_u32(target, MX3_CCM_CGR2, &cgr_register_content); if (!(cgr_register_content & 0x00000300)) { LOG_ERROR("clock gating to EMI disabled"); return ERROR_FAIL; } } { uint32_t gpr_register_content; target_read_u32(target, MX3_GPR, &gpr_register_content); if (gpr_register_content & 0x00000060) { LOG_ERROR("pins mode overrided by GPR"); return ERROR_FAIL; } } { /* * testing IOMUX settings; must be in "functional-mode output and * functional-mode input" mode */ int test_iomux; test_iomux = ERROR_OK; test_iomux |= test_iomux_settings(target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2"); test_iomux |= test_iomux_settings(target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6"); test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x0000007f, "d7"); if (nand->bus_width == 16) { test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x7f7f7f00, "d8,d9,d10"); test_iomux |= test_iomux_settings(target, 0x43fac0cc, 0x7f7f7f7f, "d11,d12,d13,d14"); test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x0000007f, "d15"); } test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x7f7f7f00, "nfwp,nfce,nfrb"); test_iomux |= test_iomux_settings(target, 0x43fac0d4, 0x7f7f7f7f, "nfwe,nfre,nfale,nfcle"); if (test_iomux != ERROR_OK) return ERROR_FAIL; } initialize_nf_controller(nand); { int retval; uint16_t nand_status_content; retval = ERROR_OK; retval |= imx31_command(nand, NAND_CMD_STATUS); retval |= imx31_address(nand, 0x00); retval |= do_data_output(nand); if (retval != ERROR_OK) { LOG_ERROR(get_status_register_err_msg); return ERROR_FAIL; } target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content); if (!(nand_status_content & 0x0080)) { /* * is host-big-endian correctly ?? */ LOG_INFO("NAND read-only"); mx3_nf_info->flags.nand_readonly = 1; } else mx3_nf_info->flags.nand_readonly = 0; } return ERROR_OK; } static int imx31_read_data(struct nand_device *nand, void *data) { struct target *target = nand->target; { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; } { /* * get data from nand chip */ int try_data_output_from_nand_chip; try_data_output_from_nand_chip = do_data_output(nand); if (try_data_output_from_nand_chip != ERROR_OK) return try_data_output_from_nand_chip; } if (nand->bus_width == 16) get_next_halfword_from_sram_buffer(target, data); else get_next_byte_from_sram_buffer(target, data); return ERROR_OK; } static int imx31_write_data(struct nand_device *nand, uint16_t data) { LOG_ERROR("write_data() not implemented"); return ERROR_NAND_OPERATION_FAILED; } static int imx31_reset(struct nand_device *nand) { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; initialize_nf_controller(nand); return ERROR_OK; } static int imx31_command(struct nand_device *nand, uint8_t command) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; } switch (command) { case NAND_CMD_READOOB: command = NAND_CMD_READ0; in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for * data_read() and * read_block_data() to * spare area in SRAM * buffer */ break; case NAND_CMD_READ1: command = NAND_CMD_READ0; /* * offset == one half of page size */ in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1); default: in_sram_address = MX3_NF_MAIN_BUFFER0; } target_write_u16(target, MX3_NF_FCMD, command); /* * start command input operation (set MX3_NF_BIT_OP_DONE==0) */ target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI); { int poll_result; poll_result = poll_for_complete_op(target, "command"); if (poll_result != ERROR_OK) return poll_result; } /* * reset cursor to begin of the buffer */ sign_of_sequental_byte_read = 0; switch (command) { case NAND_CMD_READID: mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID; mx3_nf_info->fin = MX3_NF_FIN_DATAOUT; break; case NAND_CMD_STATUS: mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS; mx3_nf_info->fin = MX3_NF_FIN_DATAOUT; break; case NAND_CMD_READ0: mx3_nf_info->fin = MX3_NF_FIN_DATAOUT; mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE; break; default: mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE; } return ERROR_OK; } static int imx31_address(struct nand_device *nand, uint8_t address) { struct target *target = nand->target; { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; } target_write_u16(target, MX3_NF_FADDR, address); /* * start address input operation (set MX3_NF_BIT_OP_DONE==0) */ target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI); { int poll_result; poll_result = poll_for_complete_op(target, "address"); if (poll_result != ERROR_OK) return poll_result; } return ERROR_OK; } static int imx31_nand_ready(struct nand_device *nand, int tout) { uint16_t poll_complete_status; struct target *target = nand->target; { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; } do { target_read_u16(target, MX3_NF_CFG2, &poll_complete_status); if (poll_complete_status & MX3_NF_BIT_OP_DONE) return tout; alive_sleep(1); } while (tout-- > 0); return tout; } static int imx31_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; if (data_size % 2) { LOG_ERROR(data_block_size_err_msg, data_size); return ERROR_NAND_OPERATION_FAILED; } if (oob_size % 2) { LOG_ERROR(data_block_size_err_msg, oob_size); return ERROR_NAND_OPERATION_FAILED; } if (!data) { LOG_ERROR("nothing to program"); return ERROR_NAND_OPERATION_FAILED; } { /* * validate target state */ int retval; retval = validate_target_state(nand); if (retval != ERROR_OK) return retval; } { int retval = ERROR_OK; retval |= imx31_command(nand, NAND_CMD_SEQIN); retval |= imx31_address(nand, 0x00); retval |= imx31_address(nand, page & 0xff); retval |= imx31_address(nand, (page >> 8) & 0xff); if (nand->address_cycles >= 4) { retval |= imx31_address(nand, (page >> 16) & 0xff); if (nand->address_cycles >= 5) retval |= imx31_address(nand, (page >> 24) & 0xff); } target_write_buffer(target, MX3_NF_MAIN_BUFFER0, data_size, data); if (oob) { if (mx3_nf_info->flags.hw_ecc_enabled) { /* * part of spare block will be overrided by hardware * ECC generator */ LOG_DEBUG("part of spare block will be overrided by hardware ECC generator"); } target_write_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size, oob); } /* * start data input operation (set MX3_NF_BIT_OP_DONE==0) */ target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI); { int poll_result; poll_result = poll_for_complete_op(target, "data input"); if (poll_result != ERROR_OK) return poll_result; } retval |= imx31_command(nand, NAND_CMD_PAGEPROG); if (retval != ERROR_OK) return retval; /* * check status register */ { uint16_t nand_status_content; retval = ERROR_OK; retval |= imx31_command(nand, NAND_CMD_STATUS); retval |= imx31_address(nand, 0x00); retval |= do_data_output(nand); if (retval != ERROR_OK) { LOG_ERROR(get_status_register_err_msg); return retval; } target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content); if (nand_status_content & 0x0001) { /* * is host-big-endian correctly ?? */ return ERROR_NAND_OPERATION_FAILED; } } } return ERROR_OK; } static int imx31_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct target *target = nand->target; if (data_size % 2) { LOG_ERROR(data_block_size_err_msg, data_size); return ERROR_NAND_OPERATION_FAILED; } if (oob_size % 2) { LOG_ERROR(data_block_size_err_msg, oob_size); return ERROR_NAND_OPERATION_FAILED; } { /* * validate target state */ int retval; retval = validate_target_state(nand); if (retval != ERROR_OK) return retval; } { int retval = ERROR_OK; retval |= imx31_command(nand, NAND_CMD_READ0); retval |= imx31_address(nand, 0x00); retval |= imx31_address(nand, page & 0xff); retval |= imx31_address(nand, (page >> 8) & 0xff); if (nand->address_cycles >= 4) { retval |= imx31_address(nand, (page >> 16) & 0xff); if (nand->address_cycles >= 5) { retval |= imx31_address(nand, (page >> 24) & 0xff); retval |= imx31_command(nand, NAND_CMD_READSTART); } } retval |= do_data_output(nand); if (retval != ERROR_OK) return retval; if (data) { target_read_buffer(target, MX3_NF_MAIN_BUFFER0, data_size, data); } if (oob) { target_read_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size, oob); } } return ERROR_OK; } static int test_iomux_settings(struct target *target, uint32_t address, uint32_t mask, const char *text) { uint32_t register_content; target_read_u32(target, address, ®ister_content); if ((register_content & mask) != (0x12121212 & mask)) { LOG_ERROR("IOMUX for {%s} is bad", text); return ERROR_FAIL; } return ERROR_OK; } static int initialize_nf_controller(struct nand_device *nand) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; /* * resets NAND flash controller in zero time ? I dont know. */ target_write_u16(target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN); { uint16_t work_mode; work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */ if (target->endianness == TARGET_BIG_ENDIAN) work_mode |= MX3_NF_BIT_BE_EN; if (mx3_nf_info->flags.hw_ecc_enabled) work_mode |= MX3_NF_BIT_ECC_EN; target_write_u16(target, MX3_NF_CFG1, work_mode); } /* * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock" */ target_write_u16(target, MX3_NF_BUFCFG, 2); { uint16_t temp; target_read_u16(target, MX3_NF_FWP, &temp); if ((temp & 0x0007) == 1) { LOG_ERROR("NAND flash is tight-locked, reset needed"); return ERROR_FAIL; } } /* * unlock NAND flash for write */ target_write_u16(target, MX3_NF_FWP, 4); target_write_u16(target, MX3_NF_LOCKSTART, 0x0000); target_write_u16(target, MX3_NF_LOCKEND, 0xFFFF); /* * 0x0000 means that first SRAM buffer @0xB800_0000 will be used */ target_write_u16(target, MX3_NF_BUFADDR, 0x0000); /* * address of SRAM buffer */ in_sram_address = MX3_NF_MAIN_BUFFER0; sign_of_sequental_byte_read = 0; return ERROR_OK; } static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value) { static uint8_t even_byte; /* * host-big_endian ?? */ if (sign_of_sequental_byte_read == 0) even_byte = 0; if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) { LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); *value = 0; sign_of_sequental_byte_read = 0; even_byte = 0; return ERROR_NAND_OPERATION_FAILED; } else { uint16_t temp; target_read_u16(target, in_sram_address, &temp); if (even_byte) { *value = temp >> 8; even_byte = 0; in_sram_address += 2; } else { *value = temp & 0xff; even_byte = 1; } } sign_of_sequental_byte_read = 1; return ERROR_OK; } static int get_next_halfword_from_sram_buffer(struct target *target, uint16_t *value) { if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) { LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); *value = 0; return ERROR_NAND_OPERATION_FAILED; } else { target_read_u16(target, in_sram_address, value); in_sram_address += 2; } return ERROR_OK; } static int poll_for_complete_op(struct target *target, const char *text) { uint16_t poll_complete_status; for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) { usleep(25); target_read_u16(target, MX3_NF_CFG2, &poll_complete_status); if (poll_complete_status & MX3_NF_BIT_OP_DONE) break; } if (!(poll_complete_status & MX3_NF_BIT_OP_DONE)) { LOG_ERROR("%s sending timeout", text); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } static int validate_target_state(struct nand_device *nand) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR(target_not_halted_err_msg); return ERROR_NAND_OPERATION_FAILED; } if (mx3_nf_info->flags.target_little_endian != (target->endianness == TARGET_LITTLE_ENDIAN)) { /* * endianness changed after NAND controller probed */ return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } static int do_data_output(struct nand_device *nand) { struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct target *target = nand->target; switch (mx3_nf_info->fin) { case MX3_NF_FIN_DATAOUT: /* * start data output operation (set MX3_NF_BIT_OP_DONE==0) */ target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype)); { int poll_result; poll_result = poll_for_complete_op(target, "data output"); if (poll_result != ERROR_OK) return poll_result; } mx3_nf_info->fin = MX3_NF_FIN_NONE; /* * ECC stuff */ if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE) && mx3_nf_info->flags.hw_ecc_enabled) { uint16_t ecc_status; target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status); switch (ecc_status & 0x000c) { case 1 << 2: LOG_DEBUG("main area readed with 1 (correctable) error"); break; case 2 << 2: LOG_DEBUG("main area readed with more than 1 (incorrectable) error"); return ERROR_NAND_OPERATION_FAILED; break; } switch (ecc_status & 0x0003) { case 1: LOG_DEBUG("spare area readed with 1 (correctable) error"); break; case 2: LOG_DEBUG("main area readed with more than 1 (incorrectable) error"); return ERROR_NAND_OPERATION_FAILED; break; } } break; case MX3_NF_FIN_NONE: break; } return ERROR_OK; } struct nand_flash_controller imx31_nand_flash_controller = { .name = "imx31", .usage = "nand device imx31 target noecc|hwecc", .nand_device_command = &imx31_nand_device_command, .init = &imx31_init, .reset = &imx31_reset, .command = &imx31_command, .address = &imx31_address, .write_data = &imx31_write_data, .read_data = &imx31_read_data, .write_page = &imx31_write_page, .read_page = &imx31_read_page, .nand_ready = &imx31_nand_ready, }; openocd-0.9.0/src/flash/nand/mx3.h0000644000175000017500000001031712315575360013565 00000000000000/*************************************************************************** * Copyright (C) 2009 by Alexei Babich * * Rezonans plc., Chelyabinsk, Russia * * impatt@mail.ru * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Freescale iMX3* OpenOCD NAND Flash controller support. * * Many thanks to Ben Dooks for writing s3c24xx driver. */ #define MX3_NF_BASE_ADDR 0xb8000000 #define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00) #define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04) #define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06) #define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08) #define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a) #define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c) #define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e) #define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10) #define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12) #define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14) #define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16) #define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18) /* * all bits not marked as self-clearing bit */ #define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a) #define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c) #define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000) #define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200) #define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400) #define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600) #define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800) #define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810) #define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820) #define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830) #define MX3_NF_MAIN_BUFFER_LEN 512 #define MX3_NF_SPARE_BUFFER_LEN 16 #define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2) /* bits in MX3_NF_CFG1 register */ #define MX3_NF_BIT_SPARE_ONLY_EN (1<<2) #define MX3_NF_BIT_ECC_EN (1<<3) #define MX3_NF_BIT_INT_DIS (1<<4) #define MX3_NF_BIT_BE_EN (1<<5) #define MX3_NF_BIT_RESET_EN (1<<6) #define MX3_NF_BIT_FORCE_CE (1<<7) /* bits in MX3_NF_CFG2 register */ /*Flash Command Input*/ #define MX3_NF_BIT_OP_FCI (1<<0) /* * Flash Address Input */ #define MX3_NF_BIT_OP_FAI (1<<1) /* * Flash Data Input */ #define MX3_NF_BIT_OP_FDI (1<<2) /* see "enum mx_dataout_type" below */ #define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3) #define MX3_NF_BIT_OP_DONE (1<<15) #define MX3_CCM_CGR2 0x53f80028 #define MX3_GPR 0x43fac008 #define MX3_PCSR 0x53f8000c enum mx_dataout_type { MX3_NF_DATAOUT_PAGE = 1, MX3_NF_DATAOUT_NANDID = 2, MX3_NF_DATAOUT_NANDSTATUS = 4, }; enum mx_nf_finalize_action { MX3_NF_FIN_NONE, MX3_NF_FIN_DATAOUT, }; struct mx3_nf_flags { unsigned target_little_endian:1; unsigned nand_readonly:1; unsigned one_kb_sram:1; unsigned hw_ecc_enabled:1; }; struct mx3_nf_controller { enum mx_dataout_type optype; enum mx_nf_finalize_action fin; struct mx3_nf_flags flags; }; openocd-0.9.0/src/flash/nand/mxc.c0000644000175000017500000007137112315575360013647 00000000000000/*************************************************************************** * Copyright (C) 2009 by Alexei Babich * * Rezonans plc., Chelyabinsk, Russia * * impatt@mail.ru * * * * Copyright (C) 2010 by Gaetan CARLIER * * Trump s.a., Belgium * * * * Copyright (C) 2011 by Erik Ahlen * * Avalon Innovation, Sweden * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Freescale iMX OpenOCD NAND Flash controller support. * based on Freescale iMX2* and iMX3* OpenOCD NAND Flash controller support. */ /* * driver tested with Samsung K9F2G08UXA and Numonyx/ST NAND02G-B2D @mxc * tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", * "nand write # file 0", "nand verify" * * get_next_halfword_from_sram_buffer() not tested * !! all function only tested with 2k page nand device; mxc_write_page * writes the 4 MAIN_BUFFER's and is not compatible with < 2k page * !! oob must be be used due to NFS bug * !! oob must be 64 bytes per 2KiB page */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "mxc.h" #include #define OOB_SIZE 64 #define nfc_is_v1() (mxc_nf_info->mxc_version == MXC_VERSION_MX27 || \ mxc_nf_info->mxc_version == MXC_VERSION_MX31) #define nfc_is_v2() (mxc_nf_info->mxc_version == MXC_VERSION_MX25 || \ mxc_nf_info->mxc_version == MXC_VERSION_MX35) /* This permits to print (in LOG_INFO) how much bytes * has been written after a page read or write. * This is useful when OpenOCD is used with a graphical * front-end to estimate progression of the global read/write */ #undef _MXC_PRINT_STAT /* #define _MXC_PRINT_STAT */ static const char target_not_halted_err_msg[] = "target must be halted to use mxc NAND flash controller"; static const char data_block_size_err_msg[] = "minimal granularity is one half-word, %" PRId32 " is incorrect"; static const char sram_buffer_bounds_err_msg[] = "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")"; static const char get_status_register_err_msg[] = "can't get NAND status"; static uint32_t in_sram_address; static unsigned char sign_of_sequental_byte_read; static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr); static int initialize_nf_controller(struct nand_device *nand); static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *value); static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t *value); static int poll_for_complete_op(struct nand_device *nand, const char *text); static int validate_target_state(struct nand_device *nand); static int do_data_output(struct nand_device *nand); static int mxc_command(struct nand_device *nand, uint8_t command); static int mxc_address(struct nand_device *nand, uint8_t address); NAND_DEVICE_COMMAND_HANDLER(mxc_nand_device_command) { struct mxc_nf_controller *mxc_nf_info; int hwecc_needed; mxc_nf_info = malloc(sizeof(struct mxc_nf_controller)); if (mxc_nf_info == NULL) { LOG_ERROR("no memory for nand controller"); return ERROR_FAIL; } nand->controller_priv = mxc_nf_info; if (CMD_ARGC < 4) { LOG_ERROR("use \"nand device mxc target mx25|mx27|mx31|mx35 noecc|hwecc [biswap]\""); return ERROR_FAIL; } /* * check board type */ if (strcmp(CMD_ARGV[2], "mx25") == 0) { mxc_nf_info->mxc_version = MXC_VERSION_MX25; mxc_nf_info->mxc_base_addr = 0xBB000000; mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x1E00; } else if (strcmp(CMD_ARGV[2], "mx27") == 0) { mxc_nf_info->mxc_version = MXC_VERSION_MX27; mxc_nf_info->mxc_base_addr = 0xD8000000; mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x0E00; } else if (strcmp(CMD_ARGV[2], "mx31") == 0) { mxc_nf_info->mxc_version = MXC_VERSION_MX31; mxc_nf_info->mxc_base_addr = 0xB8000000; mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x0E00; } else if (strcmp(CMD_ARGV[2], "mx35") == 0) { mxc_nf_info->mxc_version = MXC_VERSION_MX35; mxc_nf_info->mxc_base_addr = 0xBB000000; mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x1E00; } /* * check hwecc requirements */ hwecc_needed = strcmp(CMD_ARGV[3], "hwecc"); if (hwecc_needed == 0) mxc_nf_info->flags.hw_ecc_enabled = 1; else mxc_nf_info->flags.hw_ecc_enabled = 0; mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; mxc_nf_info->fin = MXC_NF_FIN_NONE; mxc_nf_info->flags.target_little_endian = (nand->target->endianness == TARGET_LITTLE_ENDIAN); /* * should factory bad block indicator be swaped * as a workaround for how the nfc handles pages. */ if (CMD_ARGC > 4 && strcmp(CMD_ARGV[4], "biswap") == 0) { LOG_DEBUG("BI-swap enabled"); mxc_nf_info->flags.biswap_enabled = 1; } return ERROR_OK; } COMMAND_HANDLER(handle_mxc_biswap_command) { struct nand_device *nand = NULL; struct mxc_nf_controller *mxc_nf_info = NULL; if (CMD_ARGC < 1 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &nand); if (retval != ERROR_OK) { command_print(CMD_CTX, "invalid nand device number or name: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } mxc_nf_info = nand->controller_priv; if (CMD_ARGC == 2) { if (strcmp(CMD_ARGV[1], "enable") == 0) mxc_nf_info->flags.biswap_enabled = true; else mxc_nf_info->flags.biswap_enabled = false; } if (mxc_nf_info->flags.biswap_enabled) command_print(CMD_CTX, "BI-swapping enabled on %s", nand->name); else command_print(CMD_CTX, "BI-swapping disabled on %s", nand->name); return ERROR_OK; } static const struct command_registration mxc_sub_command_handlers[] = { { .name = "biswap", .handler = handle_mxc_biswap_command, .help = "Turns on/off bad block information swaping from main area, " "without parameter query status.", .usage = "bank_id ['enable'|'disable']", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration mxc_nand_command_handler[] = { { .name = "mxc", .mode = COMMAND_ANY, .help = "MXC NAND flash controller commands", .chain = mxc_sub_command_handlers }, COMMAND_REGISTRATION_DONE }; static int mxc_init(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int validate_target_result; uint16_t buffsize_register_content; uint32_t sreg_content; uint32_t SREG = MX2_FMCR; uint32_t SEL_16BIT = MX2_FMCR_NF_16BIT_SEL; uint32_t SEL_FMS = MX2_FMCR_NF_FMS; int retval; uint16_t nand_status_content; /* * validate target state */ validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; if (nfc_is_v1()) { target_read_u16(target, MXC_NF_BUFSIZ, &buffsize_register_content); mxc_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f); } else mxc_nf_info->flags.one_kb_sram = 0; if (mxc_nf_info->mxc_version == MXC_VERSION_MX31) { SREG = MX3_PCSR; SEL_16BIT = MX3_PCSR_NF_16BIT_SEL; SEL_FMS = MX3_PCSR_NF_FMS; } else if (mxc_nf_info->mxc_version == MXC_VERSION_MX25) { SREG = MX25_RCSR; SEL_16BIT = MX25_RCSR_NF_16BIT_SEL; SEL_FMS = MX25_RCSR_NF_FMS; } else if (mxc_nf_info->mxc_version == MXC_VERSION_MX35) { SREG = MX35_RCSR; SEL_16BIT = MX35_RCSR_NF_16BIT_SEL; SEL_FMS = MX35_RCSR_NF_FMS; } target_read_u32(target, SREG, &sreg_content); if (!nand->bus_width) { /* bus_width not yet defined. Read it from MXC_FMCR */ nand->bus_width = (sreg_content & SEL_16BIT) ? 16 : 8; } else { /* bus_width forced in soft. Sync it to MXC_FMCR */ sreg_content |= ((nand->bus_width == 16) ? SEL_16BIT : 0x00000000); target_write_u32(target, SREG, sreg_content); } if (nand->bus_width == 16) LOG_DEBUG("MXC_NF : bus is 16-bit width"); else LOG_DEBUG("MXC_NF : bus is 8-bit width"); if (!nand->page_size) nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512; else { sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000); target_write_u32(target, SREG, sreg_content); } if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) { LOG_ERROR("NAND controller have only 1 kb SRAM, so " "pagesize 2048 is incompatible with it"); } else LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048"); if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K) LOG_ERROR("MXC driver does not have support for 4k pagesize."); initialize_nf_controller(nand); retval = ERROR_OK; retval |= mxc_command(nand, NAND_CMD_STATUS); retval |= mxc_address(nand, 0x00); retval |= do_data_output(nand); if (retval != ERROR_OK) { LOG_ERROR(get_status_register_err_msg); return ERROR_FAIL; } target_read_u16(target, MXC_NF_MAIN_BUFFER0, &nand_status_content); if (!(nand_status_content & 0x0080)) { LOG_INFO("NAND read-only"); mxc_nf_info->flags.nand_readonly = 1; } else mxc_nf_info->flags.nand_readonly = 0; return ERROR_OK; } static int mxc_read_data(struct nand_device *nand, void *data) { int validate_target_result; int try_data_output_from_nand_chip; /* * validate target state */ validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; /* * get data from nand chip */ try_data_output_from_nand_chip = do_data_output(nand); if (try_data_output_from_nand_chip != ERROR_OK) { LOG_ERROR("mxc_read_data : read data failed : '%x'", try_data_output_from_nand_chip); return try_data_output_from_nand_chip; } if (nand->bus_width == 16) get_next_halfword_from_sram_buffer(nand, data); else get_next_byte_from_sram_buffer(nand, data); return ERROR_OK; } static int mxc_write_data(struct nand_device *nand, uint16_t data) { LOG_ERROR("write_data() not implemented"); return ERROR_NAND_OPERATION_FAILED; } static int mxc_reset(struct nand_device *nand) { /* * validate target state */ int validate_target_result; validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; initialize_nf_controller(nand); return ERROR_OK; } static int mxc_command(struct nand_device *nand, uint8_t command) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int validate_target_result; int poll_result; /* * validate target state */ validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; switch (command) { case NAND_CMD_READOOB: command = NAND_CMD_READ0; /* set read point for data_read() and read_block_data() to * spare area in SRAM buffer */ if (nfc_is_v1()) in_sram_address = MXC_NF_V1_SPARE_BUFFER0; else in_sram_address = MXC_NF_V2_SPARE_BUFFER0; break; case NAND_CMD_READ1: command = NAND_CMD_READ0; /* * offset == one half of page size */ in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1); break; default: in_sram_address = MXC_NF_MAIN_BUFFER0; break; } target_write_u16(target, MXC_NF_FCMD, command); /* * start command input operation (set MXC_NF_BIT_OP_DONE==0) */ target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FCI); poll_result = poll_for_complete_op(nand, "command"); if (poll_result != ERROR_OK) return poll_result; /* * reset cursor to begin of the buffer */ sign_of_sequental_byte_read = 0; /* Handle special read command and adjust NF_CFG2(FDO) */ switch (command) { case NAND_CMD_READID: mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; break; case NAND_CMD_STATUS: mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; target_write_u16 (target, MXC_NF_BUFADDR, 0); in_sram_address = 0; break; case NAND_CMD_READ0: mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; break; default: /* Ohter command use the default 'One page data out' FDO */ mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; break; } return ERROR_OK; } static int mxc_address(struct nand_device *nand, uint8_t address) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int validate_target_result; int poll_result; /* * validate target state */ validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; target_write_u16(target, MXC_NF_FADDR, address); /* * start address input operation (set MXC_NF_BIT_OP_DONE==0) */ target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FAI); poll_result = poll_for_complete_op(nand, "address"); if (poll_result != ERROR_OK) return poll_result; return ERROR_OK; } static int mxc_nand_ready(struct nand_device *nand, int tout) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; uint16_t poll_complete_status; int validate_target_result; /* * validate target state */ validate_target_result = validate_target_state(nand); if (validate_target_result != ERROR_OK) return validate_target_result; do { target_read_u16(target, MXC_NF_CFG2, &poll_complete_status); if (poll_complete_status & MXC_NF_BIT_OP_DONE) return tout; alive_sleep(1); } while (tout-- > 0); return tout; } static int mxc_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int retval; uint16_t nand_status_content; uint16_t swap1, swap2, new_swap1; uint8_t bufs; int poll_result; if (data_size % 2) { LOG_ERROR(data_block_size_err_msg, data_size); return ERROR_NAND_OPERATION_FAILED; } if (oob_size % 2) { LOG_ERROR(data_block_size_err_msg, oob_size); return ERROR_NAND_OPERATION_FAILED; } if (!data) { LOG_ERROR("nothing to program"); return ERROR_NAND_OPERATION_FAILED; } /* * validate target state */ retval = validate_target_state(nand); if (retval != ERROR_OK) return retval; in_sram_address = MXC_NF_MAIN_BUFFER0; sign_of_sequental_byte_read = 0; retval = ERROR_OK; retval |= mxc_command(nand, NAND_CMD_SEQIN); retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, page & 0xff); /* page address */ retval |= mxc_address(nand, (page >> 8) & 0xff);/* page address */ retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */ target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data); if (oob) { if (mxc_nf_info->flags.hw_ecc_enabled) { /* * part of spare block will be overrided by hardware * ECC generator */ LOG_DEBUG("part of spare block will be overrided " "by hardware ECC generator"); } if (nfc_is_v1()) target_write_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob); else { uint32_t addr = MXC_NF_V2_SPARE_BUFFER0; while (oob_size > 0) { uint8_t len = MIN(oob_size, MXC_NF_SPARE_BUFFER_LEN); target_write_buffer(target, addr, len, oob); addr = align_address_v2(nand, addr + len); oob += len; oob_size -= len; } } } if (nand->page_size > 512 && mxc_nf_info->flags.biswap_enabled) { /* BI-swap - work-around of i.MX NFC for NAND device with page == 2kb*/ target_read_u16(target, MXC_NF_MAIN_BUFFER3 + 464, &swap1); if (oob) { LOG_ERROR("Due to NFC Bug, oob is not correctly implemented in mxc driver"); return ERROR_NAND_OPERATION_FAILED; } swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */ new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8); swap2 = (swap1 << 8) | (swap2 & 0xFF); target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1); if (nfc_is_v1()) target_write_u16(target, MXC_NF_V1_SPARE_BUFFER3 + 4, swap2); else target_write_u16(target, MXC_NF_V2_SPARE_BUFFER3, swap2); } /* * start data input operation (set MXC_NF_BIT_OP_DONE==0) */ if (nfc_is_v1() && nand->page_size > 512) bufs = 4; else bufs = 1; for (uint8_t i = 0; i < bufs; ++i) { target_write_u16(target, MXC_NF_BUFADDR, i); target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI); poll_result = poll_for_complete_op(nand, "data input"); if (poll_result != ERROR_OK) return poll_result; } retval |= mxc_command(nand, NAND_CMD_PAGEPROG); if (retval != ERROR_OK) return retval; /* * check status register */ retval = ERROR_OK; retval |= mxc_command(nand, NAND_CMD_STATUS); target_write_u16 (target, MXC_NF_BUFADDR, 0); mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; retval |= do_data_output(nand); if (retval != ERROR_OK) { LOG_ERROR(get_status_register_err_msg); return retval; } target_read_u16(target, MXC_NF_MAIN_BUFFER0, &nand_status_content); if (nand_status_content & 0x0001) { /* * page not correctly written */ return ERROR_NAND_OPERATION_FAILED; } #ifdef _MXC_PRINT_STAT LOG_INFO("%d bytes newly written", data_size); #endif return ERROR_OK; } static int mxc_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int retval; uint8_t bufs; uint16_t swap1, swap2, new_swap1; if (data_size % 2) { LOG_ERROR(data_block_size_err_msg, data_size); return ERROR_NAND_OPERATION_FAILED; } if (oob_size % 2) { LOG_ERROR(data_block_size_err_msg, oob_size); return ERROR_NAND_OPERATION_FAILED; } /* * validate target state */ retval = validate_target_state(nand); if (retval != ERROR_OK) return retval; /* Reset address_cycles before mxc_command ?? */ retval = mxc_command(nand, NAND_CMD_READ0); if (retval != ERROR_OK) return retval; retval = mxc_address(nand, 0); /* col */ if (retval != ERROR_OK) return retval; retval = mxc_address(nand, 0); /* col */ if (retval != ERROR_OK) return retval; retval = mxc_address(nand, page & 0xff);/* page address */ if (retval != ERROR_OK) return retval; retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */ if (retval != ERROR_OK) return retval; retval = mxc_address(nand, (page >> 16) & 0xff);/* page address */ if (retval != ERROR_OK) return retval; retval = mxc_command(nand, NAND_CMD_READSTART); if (retval != ERROR_OK) return retval; if (nfc_is_v1() && nand->page_size > 512) bufs = 4; else bufs = 1; for (uint8_t i = 0; i < bufs; ++i) { target_write_u16(target, MXC_NF_BUFADDR, i); mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; retval = do_data_output(nand); if (retval != ERROR_OK) { LOG_ERROR("MXC_NF : Error reading page %d", i); return retval; } } if (nand->page_size > 512 && mxc_nf_info->flags.biswap_enabled) { uint32_t SPARE_BUFFER3; /* BI-swap - work-around of mxc NFC for NAND device with page == 2k */ target_read_u16(target, MXC_NF_MAIN_BUFFER3 + 464, &swap1); if (nfc_is_v1()) SPARE_BUFFER3 = MXC_NF_V1_SPARE_BUFFER3 + 4; else SPARE_BUFFER3 = MXC_NF_V2_SPARE_BUFFER3; target_read_u16(target, SPARE_BUFFER3, &swap2); new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8); swap2 = (swap1 << 8) | (swap2 & 0xFF); target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1); target_write_u16(target, SPARE_BUFFER3, swap2); } if (data) target_read_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data); if (oob) { if (nfc_is_v1()) target_read_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob); else { uint32_t addr = MXC_NF_V2_SPARE_BUFFER0; while (oob_size > 0) { uint8_t len = MIN(oob_size, MXC_NF_SPARE_BUFFER_LEN); target_read_buffer(target, addr, len, oob); addr = align_address_v2(nand, addr + len); oob += len; oob_size -= len; } } } #ifdef _MXC_PRINT_STAT if (data_size > 0) { /* When Operation Status is read (when page is erased), * this function is used but data_size is null. */ LOG_INFO("%d bytes newly read", data_size); } #endif return ERROR_OK; } static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; uint32_t ret = addr; if (addr > MXC_NF_V2_SPARE_BUFFER0 && (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN) ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN; else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size)) ret = MXC_NF_V2_SPARE_BUFFER0; return ret; } static int initialize_nf_controller(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; uint16_t work_mode = 0; uint16_t temp; /* * resets NAND flash controller in zero time ? I dont know. */ target_write_u16(target, MXC_NF_CFG1, MXC_NF_BIT_RESET_EN); if (mxc_nf_info->mxc_version == MXC_VERSION_MX27) work_mode = MXC_NF_BIT_INT_DIS; /* disable interrupt */ if (target->endianness == TARGET_BIG_ENDIAN) { LOG_DEBUG("MXC_NF : work in Big Endian mode"); work_mode |= MXC_NF_BIT_BE_EN; } else LOG_DEBUG("MXC_NF : work in Little Endian mode"); if (mxc_nf_info->flags.hw_ecc_enabled) { LOG_DEBUG("MXC_NF : work with ECC mode"); work_mode |= MXC_NF_BIT_ECC_EN; } else LOG_DEBUG("MXC_NF : work without ECC mode"); if (nfc_is_v2()) { target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2); if (nand->page_size) { uint16_t pages_per_block = nand->erase_size / nand->page_size; work_mode |= MXC_NF_V2_CFG1_PPB(ffs(pages_per_block) - 6); } work_mode |= MXC_NF_BIT_ECC_4BIT; } target_write_u16(target, MXC_NF_CFG1, work_mode); /* * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock" */ target_write_u16(target, MXC_NF_BUFCFG, 2); target_read_u16(target, MXC_NF_FWP, &temp); if ((temp & 0x0007) == 1) { LOG_ERROR("NAND flash is tight-locked, reset needed"); return ERROR_FAIL; } /* * unlock NAND flash for write */ if (nfc_is_v1()) { target_write_u16(target, MXC_NF_V1_UNLOCKSTART, 0x0000); target_write_u16(target, MXC_NF_V1_UNLOCKEND, 0xFFFF); } else { target_write_u16(target, MXC_NF_V2_UNLOCKSTART0, 0x0000); target_write_u16(target, MXC_NF_V2_UNLOCKSTART1, 0x0000); target_write_u16(target, MXC_NF_V2_UNLOCKSTART2, 0x0000); target_write_u16(target, MXC_NF_V2_UNLOCKSTART3, 0x0000); target_write_u16(target, MXC_NF_V2_UNLOCKEND0, 0xFFFF); target_write_u16(target, MXC_NF_V2_UNLOCKEND1, 0xFFFF); target_write_u16(target, MXC_NF_V2_UNLOCKEND2, 0xFFFF); target_write_u16(target, MXC_NF_V2_UNLOCKEND3, 0xFFFF); } target_write_u16(target, MXC_NF_FWP, 4); /* * 0x0000 means that first SRAM buffer @base_addr will be used */ target_write_u16(target, MXC_NF_BUFADDR, 0x0000); /* * address of SRAM buffer */ in_sram_address = MXC_NF_MAIN_BUFFER0; sign_of_sequental_byte_read = 0; return ERROR_OK; } static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *value) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; static uint8_t even_byte; uint16_t temp; /* * host-big_endian ?? */ if (sign_of_sequental_byte_read == 0) even_byte = 0; if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) { LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); *value = 0; sign_of_sequental_byte_read = 0; even_byte = 0; return ERROR_NAND_OPERATION_FAILED; } else { if (nfc_is_v2()) in_sram_address = align_address_v2(nand, in_sram_address); target_read_u16(target, in_sram_address, &temp); if (even_byte) { *value = temp >> 8; even_byte = 0; in_sram_address += 2; } else { *value = temp & 0xff; even_byte = 1; } } sign_of_sequental_byte_read = 1; return ERROR_OK; } static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t *value) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) { LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); *value = 0; return ERROR_NAND_OPERATION_FAILED; } else { if (nfc_is_v2()) in_sram_address = align_address_v2(nand, in_sram_address); target_read_u16(target, in_sram_address, value); in_sram_address += 2; } return ERROR_OK; } static int poll_for_complete_op(struct nand_device *nand, const char *text) { if (mxc_nand_ready(nand, 1000) == -1) { LOG_ERROR("%s sending timeout", text); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } static int validate_target_state(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR(target_not_halted_err_msg); return ERROR_NAND_OPERATION_FAILED; } if (mxc_nf_info->flags.target_little_endian != (target->endianness == TARGET_LITTLE_ENDIAN)) { /* * endianness changed after NAND controller probed */ return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } int ecc_status_v1(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; uint16_t ecc_status; target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status); switch (ecc_status & 0x000c) { case 1 << 2: LOG_INFO("main area read with 1 (correctable) error"); break; case 2 << 2: LOG_INFO("main area read with more than 1 (incorrectable) error"); return ERROR_NAND_OPERATION_FAILED; break; } switch (ecc_status & 0x0003) { case 1: LOG_INFO("spare area read with 1 (correctable) error"); break; case 2: LOG_INFO("main area read with more than 1 (incorrectable) error"); return ERROR_NAND_OPERATION_FAILED; break; } return ERROR_OK; } int ecc_status_v2(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; uint16_t ecc_status; uint8_t no_subpages; uint8_t err; no_subpages = nand->page_size >> 9; target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status); do { err = ecc_status & 0xF; if (err > 4) { LOG_INFO("UnCorrectable RS-ECC Error"); return ERROR_NAND_OPERATION_FAILED; } else if (err > 0) LOG_INFO("%d Symbol Correctable RS-ECC Error", err); ecc_status >>= 4; } while (--no_subpages); return ERROR_OK; } static int do_data_output(struct nand_device *nand) { struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct target *target = nand->target; int poll_result; switch (mxc_nf_info->fin) { case MXC_NF_FIN_DATAOUT: /* * start data output operation (set MXC_NF_BIT_OP_DONE==0) */ target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype)); poll_result = poll_for_complete_op(nand, "data output"); if (poll_result != ERROR_OK) return poll_result; mxc_nf_info->fin = MXC_NF_FIN_NONE; /* * ECC stuff */ if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) { int ecc_status; if (nfc_is_v1()) ecc_status = ecc_status_v1(nand); else ecc_status = ecc_status_v2(nand); if (ecc_status != ERROR_OK) return ecc_status; } break; case MXC_NF_FIN_NONE: break; } return ERROR_OK; } struct nand_flash_controller mxc_nand_flash_controller = { .name = "mxc", .nand_device_command = &mxc_nand_device_command, .commands = mxc_nand_command_handler, .init = &mxc_init, .reset = &mxc_reset, .command = &mxc_command, .address = &mxc_address, .write_data = &mxc_write_data, .read_data = &mxc_read_data, .write_page = &mxc_write_page, .read_page = &mxc_read_page, .nand_ready = &mxc_nand_ready, }; openocd-0.9.0/src/flash/nand/mxc.h0000644000175000017500000001607212315575360013651 00000000000000 /*************************************************************************** * Copyright (C) 2009 by Alexei Babich * * Rezonans plc., Chelyabinsk, Russia * * impatt@mail.ru * * * * Copyright (C) 2011 by Erik Ahlen * * Avalon Innovation, Sweden * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Freescale iMX OpenOCD NAND Flash controller support. * based on Freescale iMX2* and iMX3* OpenOCD NAND Flash controller support. * * Many thanks to Ben Dooks for writing s3c24xx driver. */ #define MXC_NF_BUFSIZ (mxc_nf_info->mxc_regs_addr + 0x00) #define MXC_NF_BUFADDR (mxc_nf_info->mxc_regs_addr + 0x04) #define MXC_NF_FADDR (mxc_nf_info->mxc_regs_addr + 0x06) #define MXC_NF_FCMD (mxc_nf_info->mxc_regs_addr + 0x08) #define MXC_NF_BUFCFG (mxc_nf_info->mxc_regs_addr + 0x0a) #define MXC_NF_ECCSTATUS (mxc_nf_info->mxc_regs_addr + 0x0c) #define MXC_NF_ECCMAINPOS (mxc_nf_info->mxc_regs_addr + 0x0e) #define MXC_NF_V1_ECCSPAREPOS (mxc_nf_info->mxc_regs_addr + 0x10) #define MXC_NF_V2_SPAS (mxc_nf_info->mxc_regs_addr + 0x10) #define MXC_NF_FWP (mxc_nf_info->mxc_regs_addr + 0x12) #define MXC_NF_V1_UNLOCKSTART (mxc_nf_info->mxc_regs_addr + 0x14) #define MXC_NF_V1_UNLOCKEND (mxc_nf_info->mxc_regs_addr + 0x16) #define MXC_NF_V2_UNLOCKSTART0 (mxc_nf_info->mxc_regs_addr + 0x20) #define MXC_NF_V2_UNLOCKSTART1 (mxc_nf_info->mxc_regs_addr + 0x24) #define MXC_NF_V2_UNLOCKSTART2 (mxc_nf_info->mxc_regs_addr + 0x28) #define MXC_NF_V2_UNLOCKSTART3 (mxc_nf_info->mxc_regs_addr + 0x2c) #define MXC_NF_V2_UNLOCKEND0 (mxc_nf_info->mxc_regs_addr + 0x22) #define MXC_NF_V2_UNLOCKEND1 (mxc_nf_info->mxc_regs_addr + 0x26) #define MXC_NF_V2_UNLOCKEND2 (mxc_nf_info->mxc_regs_addr + 0x2a) #define MXC_NF_V2_UNLOCKEND3 (mxc_nf_info->mxc_regs_addr + 0x2e) #define MXC_NF_FWPSTATUS (mxc_nf_info->mxc_regs_addr + 0x18) /* * all bits not marked as self-clearing bit */ #define MXC_NF_CFG1 (mxc_nf_info->mxc_regs_addr + 0x1a) #define MXC_NF_CFG2 (mxc_nf_info->mxc_regs_addr + 0x1c) #define MXC_NF_MAIN_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x0000) #define MXC_NF_MAIN_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x0200) #define MXC_NF_MAIN_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x0400) #define MXC_NF_MAIN_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x0600) #define MXC_NF_V1_SPARE_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x0800) #define MXC_NF_V1_SPARE_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x0810) #define MXC_NF_V1_SPARE_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x0820) #define MXC_NF_V1_SPARE_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x0830) #define MXC_NF_V2_MAIN_BUFFER4 (mxc_nf_info->mxc_base_addr + 0x0800) #define MXC_NF_V2_MAIN_BUFFER5 (mxc_nf_info->mxc_base_addr + 0x0a00) #define MXC_NF_V2_MAIN_BUFFER6 (mxc_nf_info->mxc_base_addr + 0x0c00) #define MXC_NF_V2_MAIN_BUFFER7 (mxc_nf_info->mxc_base_addr + 0x0e00) #define MXC_NF_V2_SPARE_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x1000) #define MXC_NF_V2_SPARE_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x1040) #define MXC_NF_V2_SPARE_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x1080) #define MXC_NF_V2_SPARE_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x10c0) #define MXC_NF_V2_SPARE_BUFFER4 (mxc_nf_info->mxc_base_addr + 0x1100) #define MXC_NF_V2_SPARE_BUFFER5 (mxc_nf_info->mxc_base_addr + 0x1140) #define MXC_NF_V2_SPARE_BUFFER6 (mxc_nf_info->mxc_base_addr + 0x1180) #define MXC_NF_V2_SPARE_BUFFER7 (mxc_nf_info->mxc_base_addr + 0x11c0) #define MXC_NF_MAIN_BUFFER_LEN 512 #define MXC_NF_SPARE_BUFFER_LEN 16 #define MXC_NF_SPARE_BUFFER_MAX 64 #define MXC_NF_V1_LAST_BUFFADDR ((MXC_NF_V1_SPARE_BUFFER3) + \ MXC_NF_SPARE_BUFFER_LEN - 2) #define MXC_NF_V2_LAST_BUFFADDR ((MXC_NF_V2_SPARE_BUFFER7) + \ MXC_NF_SPARE_BUFFER_LEN - 2) /* bits in MXC_NF_CFG1 register */ #define MXC_NF_BIT_ECC_4BIT (1<<0) #define MXC_NF_BIT_SPARE_ONLY_EN (1<<2) #define MXC_NF_BIT_ECC_EN (1<<3) #define MXC_NF_BIT_INT_DIS (1<<4) #define MXC_NF_BIT_BE_EN (1<<5) #define MXC_NF_BIT_RESET_EN (1<<6) #define MXC_NF_BIT_FORCE_CE (1<<7) #define MXC_NF_V2_CFG1_PPB(x) (((x) & 0x3) << 9) /* bits in MXC_NF_CFG2 register */ /*Flash Command Input*/ #define MXC_NF_BIT_OP_FCI (1<<0) /* * Flash Address Input */ #define MXC_NF_BIT_OP_FAI (1<<1) /* * Flash Data Input */ #define MXC_NF_BIT_OP_FDI (1<<2) /* see "enum mx_dataout_type" below */ #define MXC_NF_BIT_DATAOUT_TYPE(x) ((x)<<3) #define MXC_NF_BIT_OP_DONE (1<<15) #define MXC_CCM_CGR2 0x53f80028 #define MXC_GPR 0x43fac008 #define MX2_FMCR 0x10027814 #define MX2_FMCR_NF_16BIT_SEL (1<<4) #define MX2_FMCR_NF_FMS (1<<5) #define MX25_RCSR 0x53f80018 #define MX25_RCSR_NF_16BIT_SEL (1<<14) #define MX25_RCSR_NF_FMS (1<<8) #define MX25_RCSR_NF_4K (1<<9) #define MX3_PCSR 0x53f8000c #define MX3_PCSR_NF_16BIT_SEL (1<<31) #define MX3_PCSR_NF_FMS (1<<30) #define MX35_RCSR 0x53f80018 #define MX35_RCSR_NF_16BIT_SEL (1<<14) #define MX35_RCSR_NF_FMS (1<<8) #define MX35_RCSR_NF_4K (1<<9) enum mxc_version { MXC_VERSION_UKWN = 0, MXC_VERSION_MX25 = 1, MXC_VERSION_MX27 = 2, MXC_VERSION_MX31 = 3, MXC_VERSION_MX35 = 4 }; enum mxc_dataout_type { MXC_NF_DATAOUT_PAGE = 1, MXC_NF_DATAOUT_NANDID = 2, MXC_NF_DATAOUT_NANDSTATUS = 4, }; enum mxc_nf_finalize_action { MXC_NF_FIN_NONE, MXC_NF_FIN_DATAOUT, }; struct mxc_nf_flags { unsigned target_little_endian:1; unsigned nand_readonly:1; unsigned one_kb_sram:1; unsigned hw_ecc_enabled:1; unsigned biswap_enabled:1; }; struct mxc_nf_controller { enum mxc_version mxc_version; uint32_t mxc_base_addr; uint32_t mxc_regs_addr; enum mxc_dataout_type optype; enum mxc_nf_finalize_action fin; struct mxc_nf_flags flags; }; openocd-0.9.0/src/flash/nand/tcl.c0000644000175000017500000004045012315575360013634 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Copyright (C) 2002 Thomas Gleixner * * Copyright (C) 2009 Zachary T Welch * * * * Partially based on drivers/mtd/nand_ids.c from Linux. * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "core.h" #include "imp.h" #include "fileio.h" #include /* to be removed */ extern struct nand_device *nand_devices; COMMAND_HANDLER(handle_nand_list_command) { struct nand_device *p; int i; if (!nand_devices) { command_print(CMD_CTX, "no NAND flash devices configured"); return ERROR_OK; } for (p = nand_devices, i = 0; p; p = p->next, i++) { if (p->device) command_print(CMD_CTX, "#%i: %s (%s) " "pagesize: %i, buswidth: %i,\n\t" "blocksize: %i, blocks: %i", i, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size, p->num_blocks); else command_print(CMD_CTX, "#%i: not probed", i); } return ERROR_OK; } COMMAND_HANDLER(handle_nand_info_command) { int i = 0; int j = 0; int first = -1; int last = -1; switch (CMD_ARGC) { default: return ERROR_COMMAND_SYNTAX_ERROR; case 1: first = 0; last = INT32_MAX; break; case 2: COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i); first = last = i; i = 0; break; case 3: COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last); break; } struct nand_device *p; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); if (ERROR_OK != retval) return retval; if (NULL == p->device) { command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); return ERROR_OK; } if (first >= p->num_blocks) first = p->num_blocks - 1; if (last >= p->num_blocks) last = p->num_blocks - 1; command_print(CMD_CTX, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i", i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size); for (j = first; j <= last; j++) { char *erase_state, *bad_state; if (p->blocks[j].is_erased == 0) erase_state = "not erased"; else if (p->blocks[j].is_erased == 1) erase_state = "erased"; else erase_state = "erase state unknown"; if (p->blocks[j].is_bad == 0) bad_state = ""; else if (p->blocks[j].is_bad == 1) bad_state = " (marked bad)"; else bad_state = " (block condition unknown)"; command_print(CMD_CTX, "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s", j, p->blocks[j].offset, p->blocks[j].size / 1024, erase_state, bad_state); } return ERROR_OK; } COMMAND_HANDLER(handle_nand_probe_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct nand_device *p; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); if (ERROR_OK != retval) return retval; retval = nand_probe(p); if (retval == ERROR_OK) { command_print(CMD_CTX, "NAND flash device '%s (%s)' found", p->device->name, p->manufacturer->name); } return retval; } COMMAND_HANDLER(handle_nand_erase_command) { if (CMD_ARGC != 1 && CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; struct nand_device *p; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); if (ERROR_OK != retval) return retval; unsigned long offset; unsigned long length; /* erase specified part of the chip; or else everything */ if (CMD_ARGC == 3) { unsigned long size = p->erase_size * p->num_blocks; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset); if ((offset % p->erase_size) != 0 || offset >= size) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length); if ((length == 0) || (length % p->erase_size) != 0 || (length + offset) > size) return ERROR_COMMAND_SYNTAX_ERROR; offset /= p->erase_size; length /= p->erase_size; } else { offset = 0; length = p->num_blocks; } retval = nand_erase(p, offset, offset + length - 1); if (retval == ERROR_OK) { command_print(CMD_CTX, "erased blocks %lu to %lu " "on NAND flash device #%s '%s'", offset, offset + length - 1, CMD_ARGV[0], p->device->name); } return retval; } COMMAND_HANDLER(handle_nand_check_bad_blocks_command) { int first = -1; int last = -1; if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2)) return ERROR_COMMAND_SYNTAX_ERROR; struct nand_device *p; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); if (ERROR_OK != retval) return retval; if (CMD_ARGC == 3) { unsigned long offset; unsigned long length; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset); if (offset % p->erase_size) return ERROR_COMMAND_SYNTAX_ERROR; offset /= p->erase_size; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length); if (length % p->erase_size) return ERROR_COMMAND_SYNTAX_ERROR; length -= 1; length /= p->erase_size; first = offset; last = offset + length; } retval = nand_build_bbt(p, first, last); if (retval == ERROR_OK) { command_print(CMD_CTX, "checked NAND flash device for bad blocks, " "use \"nand info\" command to list blocks"); } return retval; } COMMAND_HANDLER(handle_nand_write_command) { struct nand_device *nand = NULL; struct nand_fileio_state s; int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args, &s, &nand, FILEIO_READ, false, true); if (ERROR_OK != retval) return retval; uint32_t total_bytes = s.size; while (s.size > 0) { int bytes_read = nand_fileio_read(nand, &s); if (bytes_read <= 0) { command_print(CMD_CTX, "error while reading file"); return nand_fileio_cleanup(&s); } s.size -= bytes_read; retval = nand_write_page(nand, s.address / nand->page_size, s.page, s.page_size, s.oob, s.oob_size); if (ERROR_OK != retval) { command_print(CMD_CTX, "failed writing file %s " "to NAND flash %s at offset 0x%8.8" PRIx32, CMD_ARGV[1], CMD_ARGV[0], s.address); return nand_fileio_cleanup(&s); } s.address += s.page_size; } if (nand_fileio_finish(&s) == ERROR_OK) { command_print(CMD_CTX, "wrote file %s to NAND flash %s up to " "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench), duration_kbps(&s.bench, total_bytes)); } return ERROR_OK; } COMMAND_HANDLER(handle_nand_verify_command) { struct nand_device *nand = NULL; struct nand_fileio_state file; int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args, &file, &nand, FILEIO_READ, false, true); if (ERROR_OK != retval) return retval; struct nand_fileio_state dev; nand_fileio_init(&dev); dev.address = file.address; dev.size = file.size; dev.oob_format = file.oob_format; retval = nand_fileio_start(CMD_CTX, nand, NULL, FILEIO_NONE, &dev); if (ERROR_OK != retval) return retval; while (file.size > 0) { retval = nand_read_page(nand, dev.address / dev.page_size, dev.page, dev.page_size, dev.oob, dev.oob_size); if (ERROR_OK != retval) { command_print(CMD_CTX, "reading NAND flash page failed"); nand_fileio_cleanup(&dev); nand_fileio_cleanup(&file); return retval; } int bytes_read = nand_fileio_read(nand, &file); if (bytes_read <= 0) { command_print(CMD_CTX, "error while reading file"); nand_fileio_cleanup(&dev); nand_fileio_cleanup(&file); return ERROR_FAIL; } if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) || (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) { command_print(CMD_CTX, "NAND flash contents differ " "at 0x%8.8" PRIx32, dev.address); nand_fileio_cleanup(&dev); nand_fileio_cleanup(&file); return ERROR_FAIL; } file.size -= bytes_read; dev.address += nand->page_size; } if (nand_fileio_finish(&file) == ERROR_OK) { command_print(CMD_CTX, "verified file %s in NAND flash %s " "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench), duration_kbps(&file.bench, dev.size)); } return nand_fileio_cleanup(&dev); } COMMAND_HANDLER(handle_nand_dump_command) { int filesize; struct nand_device *nand = NULL; struct nand_fileio_state s; int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args, &s, &nand, FILEIO_WRITE, true, false); if (ERROR_OK != retval) return retval; while (s.size > 0) { size_t size_written; retval = nand_read_page(nand, s.address / nand->page_size, s.page, s.page_size, s.oob, s.oob_size); if (ERROR_OK != retval) { command_print(CMD_CTX, "reading NAND flash page failed"); nand_fileio_cleanup(&s); return retval; } if (NULL != s.page) fileio_write(&s.fileio, s.page_size, s.page, &size_written); if (NULL != s.oob) fileio_write(&s.fileio, s.oob_size, s.oob, &size_written); s.size -= nand->page_size; s.address += nand->page_size; } retval = fileio_size(&s.fileio, &filesize); if (retval != ERROR_OK) return retval; if (nand_fileio_finish(&s) == ERROR_OK) { command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)", (long)filesize, duration_elapsed(&s.bench), duration_kbps(&s.bench, filesize)); } return ERROR_OK; } COMMAND_HANDLER(handle_nand_raw_access_command) { if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) return ERROR_COMMAND_SYNTAX_ERROR; struct nand_device *p; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); if (ERROR_OK != retval) return retval; if (NULL == p->device) { command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); return ERROR_OK; } if (CMD_ARGC == 2) COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw); const char *msg = p->use_raw ? "enabled" : "disabled"; command_print(CMD_CTX, "raw access is %s", msg); return ERROR_OK; } static const struct command_registration nand_exec_command_handlers[] = { { .name = "list", .handler = handle_nand_list_command, .mode = COMMAND_EXEC, .help = "list configured NAND flash devices", }, { .name = "info", .handler = handle_nand_info_command, .mode = COMMAND_EXEC, .usage = "[banknum | first_bank_num last_bank_num]", .help = "print info about one or more NAND flash devices", }, { .name = "probe", .handler = handle_nand_probe_command, .mode = COMMAND_EXEC, .usage = "bank_id", .help = "identify NAND flash device", }, { .name = "check_bad_blocks", .handler = handle_nand_check_bad_blocks_command, .mode = COMMAND_EXEC, .usage = "bank_id [offset length]", .help = "check all or part of NAND flash device for bad blocks", }, { .name = "erase", .handler = handle_nand_erase_command, .mode = COMMAND_EXEC, .usage = "bank_id [offset length]", .help = "erase all or subset of blocks on NAND flash device", }, { .name = "dump", .handler = handle_nand_dump_command, .mode = COMMAND_EXEC, .usage = "bank_id filename offset length " "['oob_raw'|'oob_only']", .help = "dump from NAND flash device", }, { .name = "verify", .handler = handle_nand_verify_command, .mode = COMMAND_EXEC, .usage = "bank_id filename offset " "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']", .help = "verify NAND flash device", }, { .name = "write", .handler = handle_nand_write_command, .mode = COMMAND_EXEC, .usage = "bank_id filename offset " "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']", .help = "write to NAND flash device", }, { .name = "raw_access", .handler = handle_nand_raw_access_command, .mode = COMMAND_EXEC, .usage = "bank_id ['enable'|'disable']", .help = "raw access to NAND flash device", }, COMMAND_REGISTRATION_DONE }; static int nand_init(struct command_context *cmd_ctx) { if (!nand_devices) return ERROR_OK; struct command *parent = command_find_in_context(cmd_ctx, "nand"); return register_commands(cmd_ctx, parent, nand_exec_command_handlers); } COMMAND_HANDLER(handle_nand_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool nand_initialized; if (nand_initialized) { LOG_INFO("'nand init' has already been called"); return ERROR_OK; } nand_initialized = true; LOG_DEBUG("Initializing NAND devices..."); return nand_init(CMD_CTX); } static int nand_list_walker(struct nand_flash_controller *c, void *x) { struct command_context *cmd_ctx = x; command_print(cmd_ctx, " %s", c->name); return ERROR_OK; } COMMAND_HANDLER(handle_nand_list_drivers) { command_print(CMD_CTX, "Available NAND flash controller drivers:"); return nand_driver_walk(&nand_list_walker, CMD_CTX); } static COMMAND_HELPER(create_nand_device, const char *bank_name, struct nand_flash_controller *controller) { struct nand_device *c; struct target *target; int retval; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[1]); if (!target) { LOG_ERROR("invalid target %s", CMD_ARGV[1]); return ERROR_COMMAND_ARGUMENT_INVALID; } if (NULL != controller->commands) { retval = register_commands(CMD_CTX, NULL, controller->commands); if (ERROR_OK != retval) return retval; } c = malloc(sizeof(struct nand_device)); if (c == NULL) { LOG_ERROR("End of memory"); return ERROR_FAIL; } c->name = strdup(bank_name); c->target = target; c->controller = controller; c->controller_priv = NULL; c->manufacturer = NULL; c->device = NULL; c->bus_width = 0; c->address_cycles = 0; c->page_size = 0; c->use_raw = 0; c->next = NULL; retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c); if (ERROR_OK != retval) { LOG_ERROR("'%s' driver rejected nand flash. Usage: %s", controller->name, controller->usage); free(c); return retval; } if (controller->usage == NULL) LOG_DEBUG("'%s' driver usage field missing", controller->name); nand_device_add(c); return ERROR_OK; } COMMAND_HANDLER(handle_nand_device_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* save name and increment (for compatibility) with drivers */ const char *bank_name = *CMD_ARGV++; CMD_ARGC--; const char *driver_name = CMD_ARGV[0]; struct nand_flash_controller *controller; controller = nand_driver_find_by_name(CMD_ARGV[0]); if (NULL == controller) { LOG_ERROR("No valid NAND flash driver found (%s)", driver_name); return CALL_COMMAND_HANDLER(handle_nand_list_drivers); } return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller); } static const struct command_registration nand_config_command_handlers[] = { { .name = "device", .handler = &handle_nand_device_command, .mode = COMMAND_CONFIG, .help = "defines a new NAND bank", .usage = "bank_id driver target [driver_options ...]", }, { .name = "drivers", .handler = &handle_nand_list_drivers, .mode = COMMAND_ANY, .help = "lists available NAND drivers", .usage = "" }, { .name = "init", .mode = COMMAND_CONFIG, .handler = &handle_nand_init_command, .help = "initialize NAND devices", .usage = "" }, COMMAND_REGISTRATION_DONE }; static const struct command_registration nand_command_handlers[] = { { .name = "nand", .mode = COMMAND_ANY, .help = "NAND flash command group", .usage = "", .chain = nand_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; int nand_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, nand_command_handlers); } openocd-0.9.0/src/flash/nand/at91sam9.c0000644000175000017500000004625612315575360014434 00000000000000/* * Copyright (C) 2009 by Dean Glazeski * dnglaze@gmail.com * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "imp.h" #include "arm_io.h" #define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */ #define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */ #define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ #define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ #define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ #define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ #define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */ /** * Representation of a pin on an AT91SAM9 chip. */ struct at91sam9_pin { /** Address of the PIO controller. */ uint32_t pioc; /** Pin number. */ uint32_t num; }; /** * Private data for the controller that is stored in the NAND device structure. */ struct at91sam9_nand { /** Address of the ECC controller for NAND. */ uint32_t ecc; /** Address data is written to. */ uint32_t data; /** Address commands are written to. */ uint32_t cmd; /** Address addresses are written to. */ uint32_t addr; /** I/O structure for hosted reads/writes. */ struct arm_nand_data io; /** Pin representing the ready/~busy line. */ struct at91sam9_pin busy; /** Pin representing the chip enable. */ struct at91sam9_pin ce; }; /** * Checks if the target is halted and prints an error message if it isn't. * * @param target Target to be checked. * @param label String label for where function is called from. * @return True if the target is halted. */ static int at91sam9_halted(struct target *target, const char *label) { if (target->state == TARGET_HALTED) return true; LOG_ERROR("Target must be halted to use NAND controller (%s)", label); return false; } /** * Initialize the AT91SAM9 NAND controller. * * @param nand NAND device the controller is attached to. * @return Success or failure of initialization. */ static int at91sam9_init(struct nand_device *nand) { struct target *target = nand->target; if (!at91sam9_halted(target, "init")) return ERROR_NAND_OPERATION_FAILED; return ERROR_OK; } /** * Enable NAND device attached to a controller. * * @param info NAND controller information for controlling NAND device. * @return Success or failure of the enabling. */ static int at91sam9_enable(struct nand_device *nand) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; return target_write_u32(target, info->ce.pioc + AT91C_PIOx_CODR, 1 << info->ce.num); } /** * Disable NAND device attached to a controller. * * @param info NAND controller information for controlling NAND device. * @return Success or failure of the disabling. */ static int at91sam9_disable(struct nand_device *nand) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; return target_write_u32(target, info->ce.pioc + AT91C_PIOx_SODR, 1 << info->ce.num); } /** * Send a command to the NAND device. * * @param nand NAND device to write the command to. * @param command Command to be written. * @return Success or failure of writing the command. */ static int at91sam9_command(struct nand_device *nand, uint8_t command) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; if (!at91sam9_halted(target, "command")) return ERROR_NAND_OPERATION_FAILED; at91sam9_enable(nand); return target_write_u8(target, info->cmd, command); } /** * Reset the AT91SAM9 NAND controller. * * @param nand NAND device to be reset. * @return Success or failure of reset. */ static int at91sam9_reset(struct nand_device *nand) { if (!at91sam9_halted(nand->target, "reset")) return ERROR_NAND_OPERATION_FAILED; return at91sam9_disable(nand); } /** * Send an address to the NAND device attached to an AT91SAM9 NAND controller. * * @param nand NAND device to send the address to. * @param address Address to be sent. * @return Success or failure of sending the address. */ static int at91sam9_address(struct nand_device *nand, uint8_t address) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; if (!at91sam9_halted(nand->target, "address")) return ERROR_NAND_OPERATION_FAILED; return target_write_u8(target, info->addr, address); } /** * Read data directly from the NAND device attached to an AT91SAM9 NAND * controller. * * @param nand NAND device to read from. * @param data Pointer to where the data should be put. * @return Success or failure of reading the data. */ static int at91sam9_read_data(struct nand_device *nand, void *data) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; if (!at91sam9_halted(nand->target, "read data")) return ERROR_NAND_OPERATION_FAILED; return target_read_u8(target, info->data, data); } /** * Write data directly to the NAND device attached to an AT91SAM9 NAND * controller. * * @param nand NAND device to be written to. * @param data Data to be written. * @return Success or failure of the data write. */ static int at91sam9_write_data(struct nand_device *nand, uint16_t data) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; if (!at91sam9_halted(target, "write data")) return ERROR_NAND_OPERATION_FAILED; return target_write_u8(target, info->data, data); } /** * Determine if the NAND device is ready by looking at the ready/~busy pin. * * @param nand NAND device to check. * @param timeout Time in milliseconds to wait for NAND to be ready. * @return True if the NAND is ready in the timeout period. */ static int at91sam9_nand_ready(struct nand_device *nand, int timeout) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t status; if (!at91sam9_halted(target, "nand ready")) return 0; do { target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status); if (status & (1 << info->busy.num)) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; } /** * Read a block of data from the NAND device attached to an AT91SAM9. This * utilizes the ARM hosted NAND read function. * * @param nand NAND device to read from. * @param data Pointer to where the read data should be placed. * @param size Size of the data being read. * @return Success or failure of the hosted read. */ static int at91sam9_read_block_data(struct nand_device *nand, uint8_t *data, int size) { struct at91sam9_nand *info = nand->controller_priv; struct arm_nand_data *io = &info->io; int status; if (!at91sam9_halted(nand->target, "read block")) return ERROR_NAND_OPERATION_FAILED; io->chunk_size = nand->page_size; status = arm_nandread(io, data, size); return status; } /** * Write a block of data to a NAND device attached to an AT91SAM9. This uses * the ARM hosted write function to write the data. * * @param nand NAND device to write to. * @param data Data to be written to device. * @param size Size of the data being written. * @return Success or failure of the hosted write. */ static int at91sam9_write_block_data(struct nand_device *nand, uint8_t *data, int size) { struct at91sam9_nand *info = nand->controller_priv; struct arm_nand_data *io = &info->io; int status; if (!at91sam9_halted(nand->target, "write block")) return ERROR_NAND_OPERATION_FAILED; io->chunk_size = nand->page_size; status = arm_nandwrite(io, data, size); return status; } /** * Initialize the ECC controller on the AT91SAM9. * * @param target Target to configure ECC on. * @param info NAND controller information for where the ECC is. * @return Success or failure of initialization. */ static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info) { if (!info->ecc) { LOG_ERROR("ECC controller address must be set when not reading raw NAND data"); return ERROR_NAND_OPERATION_FAILED; } /* reset ECC parity registers */ return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1); } /** * Initialize an area for the OOB based on whether a user is requesting the OOB * data. This determines the size of the OOB and allocates the space in case * the user has not requested the OOB data. * * @param nand NAND device we are creating an OOB for. * @param oob Pointer to the user supplied OOB area. * @param size Size of the OOB. * @return Pointer to an area to store OOB data. */ static uint8_t *at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size) { if (!oob) { /* user doesn't want OOB, allocate it */ if (nand->page_size == 512) *size = 16; else if (nand->page_size == 2048) *size = 64; oob = malloc(*size); if (!oob) { LOG_ERROR("Unable to allocate space for OOB"); return NULL; } memset(oob, 0xFF, *size); } return oob; } /** * Reads a page from an AT91SAM9 NAND controller and verifies using 1-bit ECC * controller on chip. This makes an attempt to correct any errors that are * encountered while reading the page of data. * * @param nand NAND device to read from * @param page Page to be read. * @param data Pointer to where data should be read to. * @param data_size Size of the data to be read. * @param oob Pointer to where OOB data should be read to. * @param oob_size Size of the OOB data to be read. * @return Success or failure of reading the NAND page. */ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int retval; struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; uint8_t *oob_data; uint32_t status; retval = at91sam9_ecc_init(target, info); if (ERROR_OK != retval) return retval; retval = nand_page_command(nand, page, NAND_CMD_READ0, !data); if (ERROR_OK != retval) return retval; if (data) { retval = nand_read_data_page(nand, data, data_size); if (ERROR_OK != retval) return retval; } oob_data = at91sam9_oob_init(nand, oob, &oob_size); retval = nand_read_data_page(nand, oob_data, oob_size); if (ERROR_OK == retval && data) { target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status); if (status & 1) { LOG_ERROR("Error detected!"); if (status & 4) LOG_ERROR("Multiple errors encountered; unrecoverable!"); else { /* attempt recovery */ uint32_t parity; target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity); uint32_t word = (parity & 0x0000FFF0) >> 4; uint32_t bit = parity & 0x0F; data[word] ^= (0x1) << bit; LOG_INFO("Data word %d, bit %d corrected.", (unsigned) word, (unsigned) bit); } } if (status & 2) { /* we could write back correct ECC data */ LOG_ERROR("Error in ECC bytes detected"); } } if (!oob) { /* if it wasn't asked for, free it */ free(oob_data); } return retval; } /** * Write a page of data including 1-bit ECC information to a NAND device * attached to an AT91SAM9 controller. If there is OOB data to be written, * this will ignore the computed ECC from the ECC controller. * * @param nand NAND device to write to. * @param page Page to write. * @param data Pointer to data being written. * @param data_size Size of the data being written. * @param oob Pointer to OOB data being written. * @param oob_size Size of the OOB data. * @return Success or failure of the page write. */ static int at91sam9_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; int retval; uint8_t *oob_data = oob; uint32_t parity, nparity; retval = at91sam9_ecc_init(target, info); if (ERROR_OK != retval) return retval; retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); if (ERROR_OK != retval) return retval; if (data) { retval = nand_write_data_page(nand, data, data_size); if (ERROR_OK != retval) { LOG_ERROR("Unable to write data to NAND device"); return retval; } } oob_data = at91sam9_oob_init(nand, oob, &oob_size); if (!oob) { /* no OOB given, so read in the ECC parity from the ECC controller */ target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity); target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity); oob_data[0] = (uint8_t) parity; oob_data[1] = (uint8_t) (parity >> 8); oob_data[2] = (uint8_t) nparity; oob_data[3] = (uint8_t) (nparity >> 8); } retval = nand_write_data_page(nand, oob_data, oob_size); if (!oob) free(oob_data); if (ERROR_OK != retval) { LOG_ERROR("Unable to write OOB data to NAND"); return retval; } retval = nand_write_finish(nand); return retval; } /** * Handle the initial NAND device command for AT91SAM9 controllers. This * initializes much of the controller information struct to be ready for future * reads and writes. */ NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command) { unsigned long chip = 0, ecc = 0; struct at91sam9_nand *info = NULL; LOG_DEBUG("AT91SAM9 NAND Device Command"); if (CMD_ARGC < 3 || CMD_ARGC > 4) { LOG_ERROR("parameters: %s target chip_addr", CMD_ARGV[0]); return ERROR_NAND_OPERATION_FAILED; } COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); if (chip == 0) { LOG_ERROR("invalid NAND chip address: %s", CMD_ARGV[2]); return ERROR_NAND_OPERATION_FAILED; } if (CMD_ARGC == 4) { COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[3], ecc); if (ecc == 0) { LOG_ERROR("invalid ECC controller address: %s", CMD_ARGV[3]); return ERROR_NAND_OPERATION_FAILED; } } info = calloc(1, sizeof(*info)); if (!info) { LOG_ERROR("unable to allocate space for controller private data"); return ERROR_NAND_OPERATION_FAILED; } info->data = chip; info->cmd = chip | (1 << 22); info->addr = chip | (1 << 21); info->ecc = ecc; nand->controller_priv = info; info->io.target = nand->target; info->io.data = info->data; info->io.op = ARM_NAND_NONE; return ERROR_OK; } /** * Handle the AT91SAM9 CLE command for specifying the address line to use for * writing commands to a NAND device. */ COMMAND_HANDLER(handle_at91sam9_cle_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; unsigned num, address_line; if (CMD_ARGC != 2) { command_print(CMD_CTX, "incorrect number of arguments for 'at91sam9 cle' command"); return ERROR_OK; } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_OK; } info = nand->controller_priv; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], address_line); info->cmd = info->data | (1 << address_line); return ERROR_OK; } /** * Handle the AT91SAM9 ALE command for specifying the address line to use for * writing addresses to the NAND device. */ COMMAND_HANDLER(handle_at91sam9_ale_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; unsigned num, address_line; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } info = nand->controller_priv; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], address_line); info->addr = info->data | (1 << address_line); return ERROR_OK; } /** * Handle the AT91SAM9 RDY/~BUSY command for specifying the pin that watches the * RDY/~BUSY line from the NAND device. */ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; unsigned num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } info = nand->controller_priv; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], base_pioc); info->busy.pioc = base_pioc; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], pin_num); info->busy.num = pin_num; return ERROR_OK; } /** * Handle the AT91SAM9 CE command for specifying the pin that is used to enable * or disable the NAND device. */ COMMAND_HANDLER(handle_at91sam9_ce_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; unsigned num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } info = nand->controller_priv; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], base_pioc); info->ce.pioc = base_pioc; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], pin_num); info->ce.num = pin_num; return ERROR_OK; } static const struct command_registration at91sam9_sub_command_handlers[] = { { .name = "cle", .handler = handle_at91sam9_cle_command, .mode = COMMAND_CONFIG, .help = "set command latch enable address line (default is 22)", .usage = "bank_id address_line", }, { .name = "ale", .handler = handle_at91sam9_ale_command, .mode = COMMAND_CONFIG, .help = "set address latch enable address line (default is 21)", .usage = "bank_id address_line", }, { .name = "rdy_busy", .handler = handle_at91sam9_rdy_busy_command, .mode = COMMAND_CONFIG, .help = "set the GPIO input pin connected to " "the RDY/~BUSY signal (no default)", .usage = "bank_id pio_base_addr pin_num", }, { .name = "ce", .handler = handle_at91sam9_ce_command, .mode = COMMAND_CONFIG, .help = "set the GPIO output pin connected to " "the chip enable signal (no default)", .usage = "bank_id pio_base_addr pin_num", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration at91sam9_command_handler[] = { { .name = "at91sam9", .mode = COMMAND_ANY, .help = "AT91SAM9 NAND flash controller commands", .usage = "", .chain = at91sam9_sub_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** * Structure representing the AT91SAM9 NAND controller. */ struct nand_flash_controller at91sam9_nand_controller = { .name = "at91sam9", .nand_device_command = at91sam9_nand_device_command, .commands = at91sam9_command_handler, .init = at91sam9_init, .command = at91sam9_command, .reset = at91sam9_reset, .address = at91sam9_address, .read_data = at91sam9_read_data, .write_data = at91sam9_write_data, .nand_ready = at91sam9_nand_ready, .read_block_data = at91sam9_read_block_data, .write_block_data = at91sam9_write_block_data, .read_page = at91sam9_read_page, .write_page = at91sam9_write_page, }; openocd-0.9.0/src/flash/nand/fileio.c0000644000175000017500000001557012315575360014326 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Copyright (C) 2002 Thomas Gleixner * * Copyright (C) 2009 Zachary T Welch * * * * Partially based on drivers/mtd/nand_ids.c from Linux. * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "core.h" #include "fileio.h" static struct nand_ecclayout nand_oob_16 = { .eccbytes = 6, .eccpos = {0, 1, 2, 3, 6, 7}, .oobfree = { {.offset = 8, .length = 8} } }; static struct nand_ecclayout nand_oob_64 = { .eccbytes = 24, .eccpos = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, .oobfree = { {.offset = 2, .length = 38} } }; void nand_fileio_init(struct nand_fileio_state *state) { memset(state, 0, sizeof(*state)); state->oob_format = NAND_OOB_NONE; } int nand_fileio_start(struct command_context *cmd_ctx, struct nand_device *nand, const char *filename, int filemode, struct nand_fileio_state *state) { if (state->address % nand->page_size) { command_print(cmd_ctx, "only page-aligned addresses are supported"); return ERROR_COMMAND_SYNTAX_ERROR; } duration_start(&state->bench); if (NULL != filename) { int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY); if (ERROR_OK != retval) { const char *msg = (FILEIO_READ == filemode) ? "read" : "write"; command_print(cmd_ctx, "failed to open '%s' for %s access", filename, msg); return retval; } state->file_opened = true; } if (!(state->oob_format & NAND_OOB_ONLY)) { state->page_size = nand->page_size; state->page = malloc(nand->page_size); } if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) { if (nand->page_size == 512) { state->oob_size = 16; state->eccpos = nand_oob_16.eccpos; } else if (nand->page_size == 2048) { state->oob_size = 64; state->eccpos = nand_oob_64.eccpos; } state->oob = malloc(state->oob_size); } return ERROR_OK; } int nand_fileio_cleanup(struct nand_fileio_state *state) { if (state->file_opened) fileio_close(&state->fileio); if (state->oob) { free(state->oob); state->oob = NULL; } if (state->page) { free(state->page); state->page = NULL; } return ERROR_OK; } int nand_fileio_finish(struct nand_fileio_state *state) { nand_fileio_cleanup(state); return duration_measure(&state->bench); } COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, struct nand_device **dev, enum fileio_access filemode, bool need_size, bool sw_ecc) { nand_fileio_init(state); unsigned minargs = need_size ? 4 : 3; if (CMD_ARGC < minargs) return ERROR_COMMAND_SYNTAX_ERROR; struct nand_device *nand; int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &nand); if (ERROR_OK != retval) return retval; if (NULL == nand->device) { command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); return ERROR_OK; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address); if (need_size) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size); if (state->size % nand->page_size) { command_print(CMD_CTX, "only page-aligned sizes are supported"); return ERROR_COMMAND_SYNTAX_ERROR; } } if (CMD_ARGC > minargs) { for (unsigned i = minargs; i < CMD_ARGC; i++) { if (!strcmp(CMD_ARGV[i], "oob_raw")) state->oob_format |= NAND_OOB_RAW; else if (!strcmp(CMD_ARGV[i], "oob_only")) state->oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc")) state->oob_format |= NAND_OOB_SW_ECC; else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw")) state->oob_format |= NAND_OOB_SW_ECC_KW; else { command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]); return ERROR_COMMAND_SYNTAX_ERROR; } } } retval = nand_fileio_start(CMD_CTX, nand, CMD_ARGV[1], filemode, state); if (ERROR_OK != retval) return retval; if (!need_size) { int filesize; retval = fileio_size(&state->fileio, &filesize); if (retval != ERROR_OK) return retval; state->size = filesize; } *dev = nand; return ERROR_OK; } /** * @returns If no error occurred, returns number of bytes consumed; * otherwise, returns a negative error code.) */ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s) { size_t total_read = 0; size_t one_read; if (NULL != s->page) { fileio_read(&s->fileio, s->page_size, s->page, &one_read); if (one_read < s->page_size) memset(s->page + one_read, 0xff, s->page_size - one_read); total_read += one_read; } if (s->oob_format & NAND_OOB_SW_ECC) { uint8_t ecc[3]; memset(s->oob, 0xff, s->oob_size); for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) { nand_calculate_ecc(nand, s->page + i, ecc); s->oob[s->eccpos[j++]] = ecc[0]; s->oob[s->eccpos[j++]] = ecc[1]; s->oob[s->eccpos[j++]] = ecc[2]; } } else if (s->oob_format & NAND_OOB_SW_ECC_KW) { /* * In this case eccpos is not used as * the ECC data is always stored contigously * at the end of the OOB area. It consists * of 10 bytes per 512-byte data block. */ uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10; memset(s->oob, 0xff, s->oob_size); for (uint32_t i = 0; i < s->page_size; i += 512) { nand_calculate_ecc_kw(nand, s->page + i, ecc); ecc += 10; } } else if (NULL != s->oob) { fileio_read(&s->fileio, s->oob_size, s->oob, &one_read); if (one_read < s->oob_size) memset(s->oob + one_read, 0xff, s->oob_size - one_read); total_read += one_read; } return total_read; } openocd-0.9.0/src/flash/nand/fileio.h0000644000175000017500000000447312315575360014333 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NAND_FILEIO_H #define FLASH_NAND_FILEIO_H #include #include struct nand_fileio_state { uint32_t address; uint32_t size; uint8_t *page; uint32_t page_size; enum oob_formats oob_format; uint8_t *oob; uint32_t oob_size; const int *eccpos; bool file_opened; struct fileio fileio; struct duration bench; }; void nand_fileio_init(struct nand_fileio_state *state); int nand_fileio_start(struct command_context *cmd_ctx, struct nand_device *nand, const char *filename, int filemode, struct nand_fileio_state *state); int nand_fileio_cleanup(struct nand_fileio_state *state); int nand_fileio_finish(struct nand_fileio_state *state); COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, struct nand_device **dev, enum fileio_access filemode, bool need_size, bool sw_ecc); int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s); #endif /* FLASH_NAND_FILEIO_H */ openocd-0.9.0/src/flash/nand/core.c0000644000175000017500000006400612315575360014005 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Copyright (C) 2002 Thomas Gleixner * * Copyright (C) 2009 Zachary T Welch * * * * Partially based on drivers/mtd/nand_ids.c from Linux. * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" /* configured NAND devices and NAND Flash command handler */ struct nand_device *nand_devices; void nand_device_add(struct nand_device *c) { if (nand_devices) { struct nand_device *p = nand_devices; while (p && p->next) p = p->next; p->next = c; } else nand_devices = c; } /* Chip ID list * * Manufacturer, ID code, pagesize, chipsize in MegaByte, eraseblock size, * options, name * * Pagesize; 0, 256, 512 * 0 get this information from the extended chip ID * 256 256 Byte page size * 512 512 Byte page size */ static struct nand_info nand_flash_ids[] = { /* Vendor Specific Entries */ { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"}, { NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"}, /* start "museum" IDs */ { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"}, { 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"}, { 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"}, { 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"}, { 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"}, { 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"}, { 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"}, { 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"}, { 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"}, { 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"}, { 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"}, /* end "museum" IDs */ { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"}, { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"}, { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 1.8V 16-bit"}, { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 3.3V 16-bit"}, { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"}, { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"}, { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 1.8V 16-bit"}, { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 3.3V 16-bit"}, { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"}, { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"}, { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 1.8V 16-bit"}, { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 3.3V 16-bit"}, { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"}, { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"}, { 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"}, { 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"}, { 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"}, { 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"}, { 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"}, { 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"}, { 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"}, { 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"}, { 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"}, { 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"}, { 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"}, { 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"}, { 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"}, { 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"}, { 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"}, { 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"}, { 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"}, { 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"}, { 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"}, { 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"}, { 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"}, { 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"}, { 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"}, { 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"}, {0, 0, 0, 0, 0, 0, NULL} }; /* Manufacturer ID list */ static struct nand_manufacturer nand_manuf_ids[] = { {0x0, "unknown"}, {NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_SAMSUNG, "Samsung"}, {NAND_MFR_FUJITSU, "Fujitsu"}, {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_MICRON, "Micron"}, {0x0, NULL}, }; /* * Define default oob placement schemes for large and small page devices */ #if 0 static struct nand_ecclayout nand_oob_8 = { .eccbytes = 3, .eccpos = {0, 1, 2}, .oobfree = { {.offset = 3, .length = 2}, {.offset = 6, .length = 2} } }; #endif /** * Returns the flash bank specified by @a name, which matches the * driver name and a suffix (option) specify the driver-specific * bank number. The suffix consists of the '.' and the driver-specific * bank number: when two davinci banks are defined, then 'davinci.1' refers * to the second (e.g. DM355EVM). */ static struct nand_device *get_nand_device_by_name(const char *name) { unsigned requested = get_flash_name_index(name); unsigned found = 0; struct nand_device *nand; for (nand = nand_devices; NULL != nand; nand = nand->next) { if (strcmp(nand->name, name) == 0) return nand; if (!flash_driver_name_matches(nand->controller->name, name)) continue; if (++found < requested) continue; return nand; } return NULL; } struct nand_device *get_nand_device_by_num(int num) { struct nand_device *p; int i = 0; for (p = nand_devices; p; p = p->next) { if (i++ == num) return p; } return NULL; } COMMAND_HELPER(nand_command_get_device, unsigned name_index, struct nand_device **nand) { const char *str = CMD_ARGV[name_index]; *nand = get_nand_device_by_name(str); if (*nand) return ERROR_OK; unsigned num; COMMAND_PARSE_NUMBER(uint, str, num); *nand = get_nand_device_by_num(num); if (!*nand) { command_print(CMD_CTX, "NAND flash device '%s' not found", str); return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } int nand_build_bbt(struct nand_device *nand, int first, int last) { uint32_t page; int i; int pages_per_block = (nand->erase_size / nand->page_size); uint8_t oob[6]; int ret; if ((first < 0) || (first >= nand->num_blocks)) first = 0; if ((last >= nand->num_blocks) || (last == -1)) last = nand->num_blocks - 1; page = first * pages_per_block; for (i = first; i <= last; i++) { ret = nand_read_page(nand, page, NULL, 0, oob, 6); if (ret != ERROR_OK) return ret; if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff)) || (((nand->page_size == 512) && (oob[5] != 0xff)) || ((nand->page_size == 2048) && (oob[0] != 0xff)))) { LOG_WARNING("bad block: %i", i); nand->blocks[i].is_bad = 1; } else nand->blocks[i].is_bad = 0; page += pages_per_block; } return ERROR_OK; } int nand_read_status(struct nand_device *nand, uint8_t *status) { if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; /* Send read status command */ nand->controller->command(nand, NAND_CMD_STATUS); alive_sleep(1); /* read status */ if (nand->device->options & NAND_BUSWIDTH_16) { uint16_t data; nand->controller->read_data(nand, &data); *status = data & 0xff; } else nand->controller->read_data(nand, status); return ERROR_OK; } static int nand_poll_ready(struct nand_device *nand, int timeout) { uint8_t status; nand->controller->command(nand, NAND_CMD_STATUS); do { if (nand->device->options & NAND_BUSWIDTH_16) { uint16_t data; nand->controller->read_data(nand, &data); status = data & 0xff; } else nand->controller->read_data(nand, &status); if (status & NAND_STATUS_READY) break; alive_sleep(1); } while (timeout--); return (status & NAND_STATUS_READY) != 0; } int nand_probe(struct nand_device *nand) { uint8_t manufacturer_id, device_id; uint8_t id_buff[6]; int retval; int i; /* clear device data */ nand->device = NULL; nand->manufacturer = NULL; /* clear device parameters */ nand->bus_width = 0; nand->address_cycles = 0; nand->page_size = 0; nand->erase_size = 0; /* initialize controller (device parameters are zero, use controller default) */ retval = nand->controller->init(nand); if (retval != ERROR_OK) { switch (retval) { case ERROR_NAND_OPERATION_FAILED: LOG_DEBUG("controller initialization failed"); return ERROR_NAND_OPERATION_FAILED; case ERROR_NAND_OPERATION_NOT_SUPPORTED: LOG_ERROR( "BUG: controller reported that it doesn't support default parameters"); return ERROR_NAND_OPERATION_FAILED; default: LOG_ERROR("BUG: unknown controller initialization failure"); return ERROR_NAND_OPERATION_FAILED; } } nand->controller->command(nand, NAND_CMD_RESET); nand->controller->reset(nand); nand->controller->command(nand, NAND_CMD_READID); nand->controller->address(nand, 0x0); if (nand->bus_width == 8) { nand->controller->read_data(nand, &manufacturer_id); nand->controller->read_data(nand, &device_id); } else { uint16_t data_buf; nand->controller->read_data(nand, &data_buf); manufacturer_id = data_buf & 0xff; nand->controller->read_data(nand, &data_buf); device_id = data_buf & 0xff; } for (i = 0; nand_flash_ids[i].name; i++) { if (nand_flash_ids[i].id == device_id && (nand_flash_ids[i].mfr_id == manufacturer_id || nand_flash_ids[i].mfr_id == 0)) { nand->device = &nand_flash_ids[i]; break; } } for (i = 0; nand_manuf_ids[i].name; i++) { if (nand_manuf_ids[i].id == manufacturer_id) { nand->manufacturer = &nand_manuf_ids[i]; break; } } if (!nand->manufacturer) { nand->manufacturer = &nand_manuf_ids[0]; nand->manufacturer->id = manufacturer_id; } if (!nand->device) { LOG_ERROR( "unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x", manufacturer_id, device_id); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("found %s (%s)", nand->device->name, nand->manufacturer->name); /* initialize device parameters */ /* bus width */ if (nand->device->options & NAND_BUSWIDTH_16) nand->bus_width = 16; else nand->bus_width = 8; /* Do we need extended device probe information? */ if (nand->device->page_size == 0 || nand->device->erase_size == 0) { if (nand->bus_width == 8) { nand->controller->read_data(nand, id_buff + 3); nand->controller->read_data(nand, id_buff + 4); nand->controller->read_data(nand, id_buff + 5); } else { uint16_t data_buf; nand->controller->read_data(nand, &data_buf); id_buff[3] = data_buf; nand->controller->read_data(nand, &data_buf); id_buff[4] = data_buf; nand->controller->read_data(nand, &data_buf); id_buff[5] = data_buf >> 8; } } /* page size */ if (nand->device->page_size == 0) nand->page_size = 1 << (10 + (id_buff[4] & 3)); else if (nand->device->page_size == 256) { LOG_ERROR("NAND flashes with 256 byte pagesize are not supported"); return ERROR_NAND_OPERATION_FAILED; } else nand->page_size = nand->device->page_size; /* number of address cycles */ if (nand->page_size <= 512) { /* small page devices */ if (nand->device->chip_size <= 32) nand->address_cycles = 3; else if (nand->device->chip_size <= 8*1024) nand->address_cycles = 4; else { LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered"); nand->address_cycles = 5; } } else { /* large page devices */ if (nand->device->chip_size <= 128) nand->address_cycles = 4; else if (nand->device->chip_size <= 32*1024) nand->address_cycles = 5; else { LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered"); nand->address_cycles = 6; } } /* erase size */ if (nand->device->erase_size == 0) { switch ((id_buff[4] >> 4) & 3) { case 0: nand->erase_size = 64 << 10; break; case 1: nand->erase_size = 128 << 10; break; case 2: nand->erase_size = 256 << 10; break; case 3: nand->erase_size = 512 << 10; break; } } else nand->erase_size = nand->device->erase_size; /* initialize controller, but leave parameters at the controllers default */ retval = nand->controller->init(nand); if (retval != ERROR_OK) { switch (retval) { case ERROR_NAND_OPERATION_FAILED: LOG_DEBUG("controller initialization failed"); return ERROR_NAND_OPERATION_FAILED; case ERROR_NAND_OPERATION_NOT_SUPPORTED: LOG_ERROR( "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)", nand->bus_width, nand->address_cycles, nand->page_size); return ERROR_NAND_OPERATION_FAILED; default: LOG_ERROR("BUG: unknown controller initialization failure"); return ERROR_NAND_OPERATION_FAILED; } } nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024); nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks); for (i = 0; i < nand->num_blocks; i++) { nand->blocks[i].size = nand->erase_size; nand->blocks[i].offset = i * nand->erase_size; nand->blocks[i].is_erased = -1; nand->blocks[i].is_bad = -1; } return ERROR_OK; } int nand_erase(struct nand_device *nand, int first_block, int last_block) { int i; uint32_t page; uint8_t status; int retval; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if ((first_block < 0) || (last_block >= nand->num_blocks)) return ERROR_COMMAND_SYNTAX_ERROR; /* make sure we know if a block is bad before erasing it */ for (i = first_block; i <= last_block; i++) { if (nand->blocks[i].is_bad == -1) { nand_build_bbt(nand, i, last_block); break; } } for (i = first_block; i <= last_block; i++) { /* Send erase setup command */ nand->controller->command(nand, NAND_CMD_ERASE1); page = i * (nand->erase_size / nand->page_size); /* Send page address */ if (nand->page_size <= 512) { /* row */ nand->controller->address(nand, page & 0xff); nand->controller->address(nand, (page >> 8) & 0xff); /* 3rd cycle only on devices with more than 32 MiB */ if (nand->address_cycles >= 4) nand->controller->address(nand, (page >> 16) & 0xff); /* 4th cycle only on devices with more than 8 GiB */ if (nand->address_cycles >= 5) nand->controller->address(nand, (page >> 24) & 0xff); } else { /* row */ nand->controller->address(nand, page & 0xff); nand->controller->address(nand, (page >> 8) & 0xff); /* 3rd cycle only on devices with more than 128 MiB */ if (nand->address_cycles >= 5) nand->controller->address(nand, (page >> 16) & 0xff); } /* Send erase confirm command */ nand->controller->command(nand, NAND_CMD_ERASE2); retval = nand->controller->nand_ready ? nand->controller->nand_ready(nand, 1000) : nand_poll_ready(nand, 1000); if (!retval) { LOG_ERROR("timeout waiting for NAND flash block erase to complete"); return ERROR_NAND_OPERATION_TIMEOUT; } retval = nand_read_status(nand, &status); if (retval != ERROR_OK) { LOG_ERROR("couldn't read status"); return ERROR_NAND_OPERATION_FAILED; } if (status & 0x1) { LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x", (nand->blocks[i].is_bad == 1) ? "bad " : "", i, status); /* continue; other blocks might still be erasable */ } nand->blocks[i].is_erased = 1; } return ERROR_OK; } #if 0 static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) { uint8_t *page; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (address % nand->page_size) { LOG_ERROR("reads need to be page aligned"); return ERROR_NAND_OPERATION_FAILED; } page = malloc(nand->page_size); while (data_size > 0) { uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t page_address; page_address = address / nand->page_size; nand_read_page(nand, page_address, page, nand->page_size, NULL, 0); memcpy(data, page, thisrun_size); address += thisrun_size; data += thisrun_size; data_size -= thisrun_size; } free(page); return ERROR_OK; } static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) { uint8_t *page; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (address % nand->page_size) { LOG_ERROR("writes need to be page aligned"); return ERROR_NAND_OPERATION_FAILED; } page = malloc(nand->page_size); while (data_size > 0) { uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t page_address; memset(page, 0xff, nand->page_size); memcpy(page, data, thisrun_size); page_address = address / nand->page_size; nand_write_page(nand, page_address, page, nand->page_size, NULL, 0); address += thisrun_size; data += thisrun_size; data_size -= thisrun_size; } free(page); return ERROR_OK; } #endif int nand_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { uint32_t block; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; block = page / (nand->erase_size / nand->page_size); if (nand->blocks[block].is_erased == 1) nand->blocks[block].is_erased = 0; if (nand->use_raw || nand->controller->write_page == NULL) return nand_write_page_raw(nand, page, data, data_size, oob, oob_size); else return nand->controller->write_page(nand, page, data, data_size, oob, oob_size); } int nand_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (nand->use_raw || nand->controller->read_page == NULL) return nand_read_page_raw(nand, page, data, data_size, oob, oob_size); else return nand->controller->read_page(nand, page, data, data_size, oob, oob_size); } int nand_page_command(struct nand_device *nand, uint32_t page, uint8_t cmd, bool oob_only) { if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (oob_only && NAND_CMD_READ0 == cmd && nand->page_size <= 512) cmd = NAND_CMD_READOOB; nand->controller->command(nand, cmd); if (nand->page_size <= 512) { /* small page device */ /* column (always 0, we start at the beginning of a page/OOB area) */ nand->controller->address(nand, 0x0); /* row */ nand->controller->address(nand, page & 0xff); nand->controller->address(nand, (page >> 8) & 0xff); /* 4th cycle only on devices with more than 32 MiB */ if (nand->address_cycles >= 4) nand->controller->address(nand, (page >> 16) & 0xff); /* 5th cycle only on devices with more than 8 GiB */ if (nand->address_cycles >= 5) nand->controller->address(nand, (page >> 24) & 0xff); } else { /* large page device */ /* column (0 when we start at the beginning of a page, * or 2048 for the beginning of OOB area) */ nand->controller->address(nand, 0x0); if (oob_only) nand->controller->address(nand, 0x8); else nand->controller->address(nand, 0x0); /* row */ nand->controller->address(nand, page & 0xff); nand->controller->address(nand, (page >> 8) & 0xff); /* 5th cycle only on devices with more than 128 MiB */ if (nand->address_cycles >= 5) nand->controller->address(nand, (page >> 16) & 0xff); /* large page devices need a start command if reading */ if (NAND_CMD_READ0 == cmd) nand->controller->command(nand, NAND_CMD_READSTART); } if (nand->controller->nand_ready) { if (!nand->controller->nand_ready(nand, 100)) return ERROR_NAND_OPERATION_TIMEOUT; } else { /* nand_poll_read() cannot be used during nand read */ alive_sleep(1); } return ERROR_OK; } int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size) { int retval = ERROR_NAND_NO_BUFFER; if (nand->controller->read_block_data != NULL) retval = (nand->controller->read_block_data)(nand, data, size); if (ERROR_NAND_NO_BUFFER == retval) { uint32_t i; int incr = (nand->device->options & NAND_BUSWIDTH_16) ? 2 : 1; retval = ERROR_OK; for (i = 0; retval == ERROR_OK && i < size; i += incr) { retval = nand->controller->read_data(nand, data); data += incr; } } return retval; } int nand_read_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int retval; retval = nand_page_command(nand, page, NAND_CMD_READ0, !data); if (ERROR_OK != retval) return retval; if (data) nand_read_data_page(nand, data, data_size); if (oob) nand_read_data_page(nand, oob, oob_size); return ERROR_OK; } int nand_write_data_page(struct nand_device *nand, uint8_t *data, uint32_t size) { int retval = ERROR_NAND_NO_BUFFER; if (nand->controller->write_block_data != NULL) retval = (nand->controller->write_block_data)(nand, data, size); if (ERROR_NAND_NO_BUFFER == retval) { bool is16bit = nand->device->options & NAND_BUSWIDTH_16; uint32_t incr = is16bit ? 2 : 1; uint16_t write_data; uint32_t i; for (i = 0; i < size; i += incr) { if (is16bit) write_data = le_to_h_u16(data); else write_data = *data; retval = nand->controller->write_data(nand, write_data); if (ERROR_OK != retval) break; data += incr; } } return retval; } int nand_write_finish(struct nand_device *nand) { int retval; uint8_t status; nand->controller->command(nand, NAND_CMD_PAGEPROG); retval = nand->controller->nand_ready ? nand->controller->nand_ready(nand, 100) : nand_poll_ready(nand, 100); if (!retval) return ERROR_NAND_OPERATION_TIMEOUT; retval = nand_read_status(nand, &status); if (ERROR_OK != retval) { LOG_ERROR("couldn't read status"); return ERROR_NAND_OPERATION_FAILED; } if (status & NAND_STATUS_FAIL) { LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } int nand_write_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int retval; retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); if (ERROR_OK != retval) return retval; if (data) { retval = nand_write_data_page(nand, data, data_size); if (ERROR_OK != retval) { LOG_ERROR("Unable to write data to NAND device"); return retval; } } if (oob) { retval = nand_write_data_page(nand, oob, oob_size); if (ERROR_OK != retval) { LOG_ERROR("Unable to write OOB data to NAND device"); return retval; } } return nand_write_finish(nand); } openocd-0.9.0/src/flash/nand/core.h0000644000175000017500000001663612315575360014020 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Copyright (C) 2009 Zachary T Welch * * * * Partially based on linux/include/linux/mtd/nand.h * * Copyright (C) 2000 David Woodhouse * * Copyright (C) 2000 Steven J. Hill * * Copyright (C) 2000 Thomas Gleixner * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NAND_CORE_H #define FLASH_NAND_CORE_H #include /** * Representation of a single NAND block in a NAND device. */ struct nand_block { /** Offset to the block. */ uint32_t offset; /** Size of the block. */ uint32_t size; /** True if the block has been erased. */ int is_erased; /** True if the block is bad. */ int is_bad; }; struct nand_oobfree { int offset; int length; }; struct nand_ecclayout { int eccbytes; int eccpos[64]; int oobavail; struct nand_oobfree oobfree[2]; }; struct nand_device { const char *name; struct target *target; struct nand_flash_controller *controller; void *controller_priv; struct nand_manufacturer *manufacturer; struct nand_info *device; int bus_width; int address_cycles; int page_size; int erase_size; int use_raw; int num_blocks; struct nand_block *blocks; struct nand_device *next; }; /* NAND Flash Manufacturer ID Codes */ enum { NAND_MFR_TOSHIBA = 0x98, NAND_MFR_SAMSUNG = 0xec, NAND_MFR_FUJITSU = 0x04, NAND_MFR_NATIONAL = 0x8f, NAND_MFR_RENESAS = 0x07, NAND_MFR_STMICRO = 0x20, NAND_MFR_HYNIX = 0xad, NAND_MFR_MICRON = 0x2c, }; struct nand_manufacturer { int id; const char *name; }; struct nand_info { int mfr_id; int id; int page_size; int chip_size; int erase_size; int options; const char *name; }; /* Option constants for bizarre disfunctionality and real features */ enum { /* Chip can not auto increment pages */ NAND_NO_AUTOINCR = 0x00000001, /* Buswitdh is 16 bit */ NAND_BUSWIDTH_16 = 0x00000002, /* Device supports partial programming without padding */ NAND_NO_PADDING = 0x00000004, /* Chip has cache program function */ NAND_CACHEPRG = 0x00000008, /* Chip has copy back function */ NAND_COPYBACK = 0x00000010, /* AND Chip which has 4 banks and a confusing page / block * assignment. See Renesas datasheet for further information */ NAND_IS_AND = 0x00000020, /* Chip has a array of 4 pages which can be read without * additional ready /busy waits */ NAND_4PAGE_ARRAY = 0x00000040, /* Chip requires that BBT is periodically rewritten to prevent * bits from adjacent blocks from 'leaking' in altering data. * This happens with the Renesas AG-AND chips, possibly others. */ BBT_AUTO_REFRESH = 0x00000080, /* Chip does not require ready check on read. True * for all large page devices, as they do not support * autoincrement.*/ NAND_NO_READRDY = 0x00000100, /* Options valid for Samsung large page devices */ NAND_SAMSUNG_LP_OPTIONS = (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK), /* Options for new chips with large page size. The pagesize and the * erasesize is determined from the extended id bytes */ LP_OPTIONS = (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR), LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16), }; enum { /* Standard NAND flash commands */ NAND_CMD_READ0 = 0x0, NAND_CMD_READ1 = 0x1, NAND_CMD_RNDOUT = 0x5, NAND_CMD_PAGEPROG = 0x10, NAND_CMD_READOOB = 0x50, NAND_CMD_ERASE1 = 0x60, NAND_CMD_STATUS = 0x70, NAND_CMD_STATUS_MULTI = 0x71, NAND_CMD_SEQIN = 0x80, NAND_CMD_RNDIN = 0x85, NAND_CMD_READID = 0x90, NAND_CMD_ERASE2 = 0xd0, NAND_CMD_RESET = 0xff, /* Extended commands for large page devices */ NAND_CMD_READSTART = 0x30, NAND_CMD_RNDOUTSTART = 0xE0, NAND_CMD_CACHEDPROG = 0x15, }; /* Status bits */ enum { NAND_STATUS_FAIL = 0x01, NAND_STATUS_FAIL_N1 = 0x02, NAND_STATUS_TRUE_READY = 0x20, NAND_STATUS_READY = 0x40, NAND_STATUS_WP = 0x80, }; /* OOB (spare) data formats */ enum oob_formats { NAND_OOB_NONE = 0x0, /* no OOB data at all */ NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for *2048b page sizes) */ NAND_OOB_ONLY = 0x2, /* only OOB data */ NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */ NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */ NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */ NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */ NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */ }; struct nand_device *get_nand_device_by_num(int num); int nand_page_command(struct nand_device *nand, uint32_t page, uint8_t cmd, bool oob_only); int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size); int nand_write_data_page(struct nand_device *nand, uint8_t *data, uint32_t size); int nand_write_finish(struct nand_device *nand); int nand_read_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int nand_write_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int nand_read_status(struct nand_device *nand, uint8_t *status); int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code); int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code); int nand_register_commands(struct command_context *cmd_ctx); /** helper for parsing a nand device command argument string */ COMMAND_HELPER(nand_command_get_device, unsigned name_index, struct nand_device **nand); #define ERROR_NAND_DEVICE_INVALID (-1100) #define ERROR_NAND_OPERATION_FAILED (-1101) #define ERROR_NAND_OPERATION_TIMEOUT (-1102) #define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103) #define ERROR_NAND_DEVICE_NOT_PROBED (-1104) #define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) #define ERROR_NAND_NO_BUFFER (-1106) #endif /* FLASH_NAND_CORE_H */ openocd-0.9.0/src/flash/nand/driver.c0000644000175000017500000000713612315575360014351 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "core.h" #include "driver.h" /* NAND flash controller */ extern struct nand_flash_controller nonce_nand_controller; extern struct nand_flash_controller davinci_nand_controller; extern struct nand_flash_controller lpc3180_nand_controller; extern struct nand_flash_controller lpc32xx_nand_controller; extern struct nand_flash_controller orion_nand_controller; extern struct nand_flash_controller s3c2410_nand_controller; extern struct nand_flash_controller s3c2412_nand_controller; extern struct nand_flash_controller s3c2440_nand_controller; extern struct nand_flash_controller s3c2443_nand_controller; extern struct nand_flash_controller s3c6400_nand_controller; extern struct nand_flash_controller mxc_nand_flash_controller; extern struct nand_flash_controller imx31_nand_flash_controller; extern struct nand_flash_controller at91sam9_nand_controller; extern struct nand_flash_controller nuc910_nand_controller; /* extern struct nand_flash_controller boundary_scan_nand_controller; */ static struct nand_flash_controller *nand_flash_controllers[] = { &nonce_nand_controller, &davinci_nand_controller, &lpc3180_nand_controller, &lpc32xx_nand_controller, &orion_nand_controller, &s3c2410_nand_controller, &s3c2412_nand_controller, &s3c2440_nand_controller, &s3c2443_nand_controller, &s3c6400_nand_controller, &mxc_nand_flash_controller, &imx31_nand_flash_controller, &at91sam9_nand_controller, &nuc910_nand_controller, /* &boundary_scan_nand_controller, */ NULL }; struct nand_flash_controller *nand_driver_find_by_name(const char *name) { for (unsigned i = 0; nand_flash_controllers[i]; i++) { struct nand_flash_controller *controller = nand_flash_controllers[i]; if (strcmp(name, controller->name) == 0) return controller; } return NULL; } int nand_driver_walk(nand_driver_walker_t f, void *x) { for (unsigned i = 0; nand_flash_controllers[i]; i++) { int retval = (*f)(nand_flash_controllers[i], x); if (ERROR_OK != retval) return retval; } return ERROR_OK; } openocd-0.9.0/src/flash/nand/driver.h0000644000175000017500000001106312315575360014350 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_NAND_DRIVER_H #define FLASH_NAND_DRIVER_H struct nand_device; #define __NAND_DEVICE_COMMAND(name) \ COMMAND_HELPER(name, struct nand_device *nand) /** * Interface for NAND flash controllers. Not all of these functions are * required for full functionality of the NAND driver, but better performance * can be achieved by implementing each function. */ struct nand_flash_controller { /** Driver name that is used to select it from configuration files. */ const char *name; /** Usage of flash command registration. */ const char *usage; const struct command_registration *commands; /** NAND device command called when driver is instantiated during configuration. */ __NAND_DEVICE_COMMAND((*nand_device_command)); /** Initialize the NAND device. */ int (*init)(struct nand_device *nand); /** Reset the NAND device. */ int (*reset)(struct nand_device *nand); /** Issue a command to the NAND device. */ int (*command)(struct nand_device *nand, uint8_t command); /** Write an address to the NAND device. */ int (*address)(struct nand_device *nand, uint8_t address); /** Write word of data to the NAND device. */ int (*write_data)(struct nand_device *nand, uint16_t data); /** Read word of data from the NAND device. */ int (*read_data)(struct nand_device *nand, void *data); /** Write a block of data to the NAND device. */ int (*write_block_data)(struct nand_device *nand, uint8_t *data, int size); /** Read a block of data from the NAND device. */ int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size); /** Write a page to the NAND device. */ int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); /** Read a page from the NAND device. */ int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); /** Check if the NAND device is ready for more instructions with timeout. */ int (*nand_ready)(struct nand_device *nand, int timeout); }; #define NAND_DEVICE_COMMAND_HANDLER(name) static __NAND_DEVICE_COMMAND(name) /** * Find a NAND flash controller by name. * @param name Identifies the NAND controller to find. * @returns The nand_flash_controller named @c name, or NULL if not found. */ struct nand_flash_controller *nand_driver_find_by_name(const char *name); /** Signature for callback functions passed to nand_driver_walk */ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *); /** * Walk the list of drivers, encapsulating the data structure type. * Application state/context can be passed through the @c x pointer. * @param f The callback function to invoke for each function. * @param x For use as private data storate, passed directly to @c f. * @returns ERROR_OK if successful, or the non-zero return value of @c f. * This allows a walker to terminate the loop early. */ int nand_driver_walk(nand_driver_walker_t f, void *x); #endif /* FLASH_NAND_DRIVER_H */ openocd-0.9.0/src/flash/nand/s3c24xx_regs.h0000644000175000017500000001276212315575360015322 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Simtec Electronics * * linux@simtec.co.uk * * http://www.simtec.co.uk/products/SWLINUX/ * * * * This program 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; version 2 of the License. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C2410 NAND register definitions */ #ifndef __ASM_ARM_REGS_NAND #define __ASM_ARM_REGS_NAND #define S3C2410_NFREG(x) (x) #define S3C2410_NFCONF S3C2410_NFREG(0x00) #define S3C2410_NFCMD S3C2410_NFREG(0x04) #define S3C2410_NFADDR S3C2410_NFREG(0x08) #define S3C2410_NFDATA S3C2410_NFREG(0x0C) #define S3C2410_NFSTAT S3C2410_NFREG(0x10) #define S3C2410_NFECC S3C2410_NFREG(0x14) #define S3C2440_NFCONT S3C2410_NFREG(0x04) #define S3C2440_NFCMD S3C2410_NFREG(0x08) #define S3C2440_NFADDR S3C2410_NFREG(0x0C) #define S3C2440_NFDATA S3C2410_NFREG(0x10) #define S3C2440_NFECCD0 S3C2410_NFREG(0x14) #define S3C2440_NFECCD1 S3C2410_NFREG(0x18) #define S3C2440_NFECCD S3C2410_NFREG(0x1C) #define S3C2440_NFSTAT S3C2410_NFREG(0x20) #define S3C2440_NFESTAT0 S3C2410_NFREG(0x24) #define S3C2440_NFESTAT1 S3C2410_NFREG(0x28) #define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) #define S3C2440_NFMECC1 S3C2410_NFREG(0x30) #define S3C2440_NFSECC S3C2410_NFREG(0x34) #define S3C2440_NFSBLK S3C2410_NFREG(0x38) #define S3C2440_NFEBLK S3C2410_NFREG(0x3C) #define S3C2412_NFSBLK S3C2410_NFREG(0x20) #define S3C2412_NFEBLK S3C2410_NFREG(0x24) #define S3C2412_NFSTAT S3C2410_NFREG(0x28) #define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C) #define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30) #define S3C2412_NFMECC0 S3C2410_NFREG(0x34) #define S3C2412_NFMECC1 S3C2410_NFREG(0x38) #define S3C2412_NFSECC S3C2410_NFREG(0x3C) #define S3C2410_NFCONF_EN (1 << 15) #define S3C2410_NFCONF_512BYTE (1 << 14) #define S3C2410_NFCONF_4STEP (1 << 13) #define S3C2410_NFCONF_INITECC (1 << 12) #define S3C2410_NFCONF_nFCE (1 << 11) #define S3C2410_NFCONF_TACLS(x) ((x) << 8) #define S3C2410_NFCONF_TWRPH0(x) ((x) << 4) #define S3C2410_NFCONF_TWRPH1(x) ((x) << 0) #define S3C2410_NFSTAT_BUSY (1 << 0) #define S3C2440_NFCONF_BUSWIDTH_8 (0 << 0) #define S3C2440_NFCONF_BUSWIDTH_16 (1 << 0) #define S3C2440_NFCONF_ADVFLASH (1 << 3) #define S3C2440_NFCONF_TACLS(x) ((x) << 12) #define S3C2440_NFCONF_TWRPH0(x) ((x) << 8) #define S3C2440_NFCONF_TWRPH1(x) ((x) << 4) #define S3C2440_NFCONT_LOCKTIGHT (1 << 13) #define S3C2440_NFCONT_SOFTLOCK (1 << 12) #define S3C2440_NFCONT_ILLEGALACC_EN (1 << 10) #define S3C2440_NFCONT_RNBINT_EN (1 << 9) #define S3C2440_NFCONT_RN_FALLING (1 << 8) #define S3C2440_NFCONT_SPARE_ECCLOCK (1 << 6) #define S3C2440_NFCONT_MAIN_ECCLOCK (1 << 5) #define S3C2440_NFCONT_INITECC (1 << 4) #define S3C2440_NFCONT_nFCE (1 << 1) #define S3C2440_NFCONT_ENABLE (1 << 0) #define S3C2440_NFSTAT_READY (1 << 0) #define S3C2440_NFSTAT_nCE (1 << 1) #define S3C2440_NFSTAT_RnB_CHANGE (1 << 2) #define S3C2440_NFSTAT_ILLEGAL_ACCESS (1 << 3) #define S3C2412_NFCONF_NANDBOOT (1 << 31) #define S3C2412_NFCONF_ECCCLKCON (1 << 30) #define S3C2412_NFCONF_ECC_MLC (1 << 24) #define S3C2412_NFCONF_TACLS_MASK (7 << 12) /* 1 extra bit of Tacls */ #define S3C2412_NFCONT_ECC4_DIRWR (1 << 18) #define S3C2412_NFCONT_LOCKTIGHT (1 << 17) #define S3C2412_NFCONT_SOFTLOCK (1 << 16) #define S3C2412_NFCONT_ECC4_ENCINT (1 << 13) #define S3C2412_NFCONT_ECC4_DECINT (1 << 12) #define S3C2412_NFCONT_MAIN_ECC_LOCK (1 << 7) #define S3C2412_NFCONT_INIT_MAIN_ECC (1 << 5) #define S3C2412_NFCONT_nFCE1 (1 << 2) #define S3C2412_NFCONT_nFCE0 (1 << 1) #define S3C2412_NFSTAT_ECC_ENCDONE (1 << 7) #define S3C2412_NFSTAT_ECC_DECDONE (1 << 6) #define S3C2412_NFSTAT_ILLEGAL_ACCESS (1 << 5) #define S3C2412_NFSTAT_RnB_CHANGE (1 << 4) #define S3C2412_NFSTAT_nFCE1 (1 << 3) #define S3C2412_NFSTAT_nFCE0 (1 << 2) #define S3C2412_NFSTAT_Res1 (1 << 1) #define S3C2412_NFSTAT_READY (1 << 0) #define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf) #define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7) #define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff) #define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7) #define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3) #define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3) #define S3C2412_NFECCERR_NONE (0) #define S3C2412_NFECCERR_1BIT (1) #define S3C2412_NFECCERR_MULTIBIT (2) #define S3C2412_NFECCERR_ECCAREA (3) #endif /* __ASM_ARM_REGS_NAND */ openocd-0.9.0/src/flash/nand/Makefile.am0000644000175000017500000000113312315575360014735 00000000000000include $(top_srcdir)/common.mk noinst_LTLIBRARIES = libocdflashnand.la libocdflashnand_la_SOURCES = \ ecc.c \ ecc_kw.c \ core.c \ fileio.c \ tcl.c \ arm_io.c \ $(NAND_DRIVERS) \ driver.c NAND_DRIVERS = \ nonce.c \ davinci.c \ lpc3180.c \ lpc32xx.c \ mxc.c \ mx3.c \ orion.c \ s3c24xx.c \ s3c2410.c \ s3c2412.c \ s3c2440.c \ s3c2443.c \ s3c6400.c \ at91sam9.c \ nuc910.c noinst_HEADERS = \ arm_io.h \ core.h \ driver.h \ fileio.h \ imp.h \ lpc3180.h \ lpc32xx.h \ mxc.h \ mx3.h \ s3c24xx.h \ s3c24xx_regs.h \ nuc910.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/flash/nand/Makefile.in0000644000175000017500000005007612526201647014756 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/flash/nand ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libocdflashnand_la_LIBADD = am__objects_1 = nonce.lo davinci.lo lpc3180.lo lpc32xx.lo mxc.lo \ mx3.lo orion.lo s3c24xx.lo s3c2410.lo s3c2412.lo s3c2440.lo \ s3c2443.lo s3c6400.lo at91sam9.lo nuc910.lo am_libocdflashnand_la_OBJECTS = ecc.lo ecc_kw.lo core.lo fileio.lo \ tcl.lo arm_io.lo $(am__objects_1) driver.lo libocdflashnand_la_OBJECTS = $(am_libocdflashnand_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libocdflashnand_la_SOURCES) DIST_SOURCES = $(libocdflashnand_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) noinst_LTLIBRARIES = libocdflashnand.la libocdflashnand_la_SOURCES = \ ecc.c \ ecc_kw.c \ core.c \ fileio.c \ tcl.c \ arm_io.c \ $(NAND_DRIVERS) \ driver.c NAND_DRIVERS = \ nonce.c \ davinci.c \ lpc3180.c \ lpc32xx.c \ mxc.c \ mx3.c \ orion.c \ s3c24xx.c \ s3c2410.c \ s3c2412.c \ s3c2440.c \ s3c2443.c \ s3c6400.c \ at91sam9.c \ nuc910.c noinst_HEADERS = \ arm_io.h \ core.h \ driver.h \ fileio.h \ imp.h \ lpc3180.h \ lpc32xx.h \ mxc.h \ mx3.h \ s3c24xx.h \ s3c24xx_regs.h \ nuc910.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/flash/nand/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/flash/nand/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libocdflashnand.la: $(libocdflashnand_la_OBJECTS) $(libocdflashnand_la_DEPENDENCIES) $(EXTRA_libocdflashnand_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libocdflashnand_la_OBJECTS) $(libocdflashnand_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at91sam9.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/davinci.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc_kw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc3180.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc32xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mx3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mxc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nuc910.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c2410.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c2412.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c2440.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c2443.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c24xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3c6400.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcl.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/flash/nand/nonce.c0000644000175000017500000000510012315575360014145 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "hello.h" static int nonce_nand_command(struct nand_device *nand, uint8_t command) { return ERROR_OK; } static int nonce_nand_address(struct nand_device *nand, uint8_t address) { return ERROR_OK; } static int nonce_nand_read(struct nand_device *nand, void *data) { return ERROR_OK; } static int nonce_nand_write(struct nand_device *nand, uint16_t data) { return ERROR_OK; } static int nonce_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size) { return ERROR_OK; } static int nonce_nand_reset(struct nand_device *nand) { return nonce_nand_command(nand, NAND_CMD_RESET); } NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command) { return ERROR_OK; } static int nonce_nand_init(struct nand_device *nand) { return ERROR_OK; } struct nand_flash_controller nonce_nand_controller = { .name = "nonce", .commands = hello_command_handlers, .nand_device_command = &nonce_nand_device_command, .init = &nonce_nand_init, .reset = &nonce_nand_reset, .command = &nonce_nand_command, .address = &nonce_nand_address, .read_data = &nonce_nand_read, .write_data = &nonce_nand_write, .write_block_data = &nonce_nand_fast_block_write, }; openocd-0.9.0/src/flash/nand/davinci.c0000644000175000017500000005415212315575360014473 00000000000000/*************************************************************************** * Copyright (C) 2009 by David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * DaVinci family NAND controller support for OpenOCD. * * This driver uses hardware ECC (1-bit or 4-bit) unless * the chip is accessed in "raw" mode. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "arm_io.h" #include enum ecc { HWECC1, /* all controllers support 1-bit ECC */ HWECC4, /* newer chips also have 4-bit ECC hardware */ HWECC4_INFIX, /* avoid this layout, except maybe for boot code */ }; struct davinci_nand { uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */ uint8_t eccmode; /* Async EMIF controller base */ uint32_t aemif; /* NAND chip addresses */ uint32_t data; /* without CLE or ALE */ uint32_t cmd; /* with CLE */ uint32_t addr; /* with ALE */ /* write acceleration */ struct arm_nand_data io; /* page i/o for the relevant flavor of hardware ECC */ int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); }; #define NANDFCR 0x60 /* flash control register */ #define NANDFSR 0x64 /* flash status register */ #define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */ #define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */ #define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */ #define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */ #define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */ static int halted(struct target *target, const char *label) { if (target->state == TARGET_HALTED) return true; LOG_ERROR("Target must be halted to use NAND controller (%s)", label); return false; } static int davinci_init(struct nand_device *nand) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t nandfcr; if (!halted(target, "init")) return ERROR_NAND_OPERATION_FAILED; /* We require something else to have configured AEMIF to talk * to NAND chip in this range (including timings and width). */ target_read_u32(target, info->aemif + NANDFCR, &nandfcr); if (!(nandfcr & (1 << info->chipsel))) { LOG_ERROR("chip address %08" PRIx32 " not NAND-enabled?", info->data); return ERROR_NAND_OPERATION_FAILED; } /* REVISIT verify: AxCR must be in 8-bit mode, since that's all we * tested. 16 bit support should work too; but not with 4-bit ECC. */ return ERROR_OK; } static int davinci_reset(struct nand_device *nand) { return ERROR_OK; } static int davinci_nand_ready(struct nand_device *nand, int timeout) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t nandfsr; /* NOTE: return code is zero/error, else success; not ERROR_* */ if (!halted(target, "ready")) return 0; do { target_read_u32(target, info->aemif + NANDFSR, &nandfsr); if (nandfsr & 0x01) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; } static int davinci_command(struct nand_device *nand, uint8_t command) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; if (!halted(target, "command")) return ERROR_NAND_OPERATION_FAILED; target_write_u8(target, info->cmd, command); return ERROR_OK; } static int davinci_address(struct nand_device *nand, uint8_t address) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; if (!halted(target, "address")) return ERROR_NAND_OPERATION_FAILED; target_write_u8(target, info->addr, address); return ERROR_OK; } static int davinci_write_data(struct nand_device *nand, uint16_t data) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; if (!halted(target, "write_data")) return ERROR_NAND_OPERATION_FAILED; target_write_u8(target, info->data, data); return ERROR_OK; } static int davinci_read_data(struct nand_device *nand, void *data) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; if (!halted(target, "read_data")) return ERROR_NAND_OPERATION_FAILED; target_read_u8(target, info->data, data); return ERROR_OK; } /* REVISIT a bit of native code should let block reads be MUCH faster */ static int davinci_read_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t nfdata = info->data; uint32_t tmp; if (!halted(target, "read_block")) return ERROR_NAND_OPERATION_FAILED; while (data_size >= 4) { target_read_u32(target, nfdata, &tmp); data[0] = tmp; data[1] = tmp >> 8; data[2] = tmp >> 16; data[3] = tmp >> 24; data_size -= 4; data += 4; } while (data_size > 0) { target_read_u8(target, nfdata, data); data_size -= 1; data += 1; } return ERROR_OK; } static int davinci_write_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t nfdata = info->data; uint32_t tmp; int status; if (!halted(target, "write_block")) return ERROR_NAND_OPERATION_FAILED; /* try the fast way first */ status = arm_nandwrite(&info->io, data, data_size); if (status != ERROR_NAND_NO_BUFFER) return status; /* else do it slowly */ while (data_size >= 4) { tmp = le_to_h_u32(data); target_write_u32(target, nfdata, tmp); data_size -= 4; data += 4; } while (data_size > 0) { target_write_u8(target, nfdata, *data); data_size -= 1; data += 1; } return ERROR_OK; } static int davinci_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; uint8_t *ooballoc = NULL; int status; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (!halted(nand->target, "write_page")) return ERROR_NAND_OPERATION_FAILED; /* Always write both data and OOB ... we are not "raw" I/O! */ if (!data) { LOG_ERROR("Missing NAND data; try 'nand raw_access enable'"); return ERROR_NAND_OPERATION_FAILED; } /* If we're not given OOB, write 0xff where we don't write ECC codes. */ switch (nand->page_size) { case 512: oob_size = 16; break; case 2048: oob_size = 64; break; case 4096: oob_size = 128; break; default: return ERROR_NAND_OPERATION_FAILED; } if (!oob) { ooballoc = malloc(oob_size); if (!ooballoc) return ERROR_NAND_OPERATION_FAILED; oob = ooballoc; memset(oob, 0x0ff, oob_size); } /* REVISIT avoid wasting SRAM: unless nand->use_raw is set, * use 512 byte chunks. Read side support will often want * to include oob_size ... */ info->io.chunk_size = nand->page_size; status = info->write_page(nand, page, data, data_size, oob, oob_size); free(ooballoc); return status; } static int davinci_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; if (!halted(nand->target, "read_page")) return ERROR_NAND_OPERATION_FAILED; return info->read_page(nand, page, data, data_size, oob, oob_size); } static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; int page3 = nand->address_cycles - (nand->page_size == 512); /* write command ({page,otp}x{read,program} */ target_write_u8(target, info->cmd, cmd); /* column address (beginning-of-page) */ target_write_u8(target, info->addr, 0); if (nand->page_size > 512) target_write_u8(target, info->addr, 0); /* page address */ target_write_u8(target, info->addr, page); target_write_u8(target, info->addr, page >> 8); if (page3) target_write_u8(target, info->addr, page >> 16); if (page3 == 2) target_write_u8(target, info->addr, page >> 24); } static int davinci_seek_column(struct nand_device *nand, uint16_t column) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; /* Random read, we must have issued a page read already */ target_write_u8(target, info->cmd, NAND_CMD_RNDOUT); target_write_u8(target, info->addr, column); if (nand->page_size > 512) { target_write_u8(target, info->addr, column >> 8); target_write_u8(target, info->cmd, NAND_CMD_RNDOUTSTART); } if (!davinci_nand_ready(nand, 100)) return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_OK; } static int davinci_writepage_tail(struct nand_device *nand, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; uint8_t status; if (oob_size) davinci_write_block_data(nand, oob, oob_size); /* non-cachemode page program */ target_write_u8(target, info->cmd, NAND_CMD_PAGEPROG); if (!davinci_nand_ready(nand, 100)) return ERROR_NAND_OPERATION_TIMEOUT; if (nand_read_status(nand, &status) != ERROR_OK) { LOG_ERROR("couldn't read status"); return ERROR_NAND_OPERATION_FAILED; } if (status & NAND_STATUS_FAIL) { LOG_ERROR("write operation failed, status: 0x%02x", status); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } /* * All DaVinci family chips support 1-bit ECC on a per-chipselect basis. */ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { unsigned oob_offset; struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel); uint32_t fcr, ecc1; /* Write contiguous ECC bytes starting at specified offset. * NOTE: Linux reserves twice as many bytes as we need; and * for 16-bit OOB, those extra bytes are discontiguous. */ switch (nand->page_size) { case 512: oob_offset = 0; break; case 2048: oob_offset = 40; break; default: oob_offset = 80; break; } davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page); /* scrub any old ECC state */ target_read_u32(target, ecc1_addr, &ecc1); target_read_u32(target, fcr_addr, &fcr); fcr |= 1 << (8 + info->chipsel); do { /* set "start csX 1bit ecc" bit */ target_write_u32(target, fcr_addr, fcr); /* write 512 bytes */ davinci_write_block_data(nand, data, 512); data += 512; data_size -= 512; /* read the ecc, pack to 3 bytes, and invert so the ecc * in an erased block is correct */ target_read_u32(target, ecc1_addr, &ecc1); ecc1 = (ecc1 & 0x0fff) | ((ecc1 & 0x0fff0000) >> 4); ecc1 = ~ecc1; /* save correct ECC code into oob data */ oob[oob_offset++] = (uint8_t)(ecc1); oob[oob_offset++] = (uint8_t)(ecc1 >> 8); oob[oob_offset++] = (uint8_t)(ecc1 >> 16); } while (data_size); /* write OOB into spare area */ return davinci_writepage_tail(nand, oob, oob_size); } /* * Preferred "new style" ECC layout for use with 4-bit ECC. This somewhat * slows down large page reads done with error correction (since the OOB * is read first, so its ECC data can be used incrementally), but the * manufacturer bad block markers are safe. Contrast: old "infix" style. */ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { static const uint8_t ecc512[] = { 0, 1, 2, 3, 4, /* 5== mfr badblock */ 6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15, }; static const uint8_t ecc2048[] = { 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }; static const uint8_t ecc4096[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, }; struct davinci_nand *info = nand->controller_priv; const uint8_t *l; struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc4_addr = info->aemif + NAND4BITECC; uint32_t fcr, ecc4; /* Use the same ECC layout Linux uses. For small page chips * it's a bit cramped. * * NOTE: at this writing, 4KB pages have issues in Linux * because they need more than 64 bytes of ECC data, which * the standard ECC logic can't handle. */ switch (nand->page_size) { case 512: l = ecc512; break; case 2048: l = ecc2048; break; default: l = ecc4096; break; } davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page); /* scrub any old ECC state */ target_read_u32(target, info->aemif + NANDERRVAL, &ecc4); target_read_u32(target, fcr_addr, &fcr); fcr &= ~(0x03 << 4); fcr |= (1 << 12) | (info->chipsel << 4); do { uint32_t raw_ecc[4], *p; int i; /* start 4bit ecc on csX */ target_write_u32(target, fcr_addr, fcr); /* write 512 bytes */ davinci_write_block_data(nand, data, 512); data += 512; data_size -= 512; /* read the ecc, then save it into 10 bytes in the oob */ for (i = 0; i < 4; i++) { target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]); raw_ecc[i] &= 0x03ff03ff; } for (i = 0, p = raw_ecc; i < 2; i++, p += 2) { oob[*l++] = p[0] & 0xff; oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc); oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0); oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0); oob[*l++] = (p[1] >> 18) & 0xff; } } while (data_size); /* write OOB into spare area */ return davinci_writepage_tail(nand, oob, oob_size); } /* * "Infix" OOB ... like Linux ECC_HW_SYNDROME. Avoided because it trashes * manufacturer bad block markers, except on small page chips. Once you * write to a page using this scheme, you need specialized code to update * it (code which ignores now-invalid bad block markers). * * This is needed *only* to support older firmware. Older ROM Boot Loaders * need it to read their second stage loader (UBL) into SRAM, but from then * on the whole system can use the cleaner non-infix layouts. Systems with * older second stage loaders (ABL/U-Boot, etc) or other system software * (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally. */ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc4_addr = info->aemif + NAND4BITECC; uint32_t fcr, ecc4; davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page); /* scrub any old ECC state */ target_read_u32(target, info->aemif + NANDERRVAL, &ecc4); target_read_u32(target, fcr_addr, &fcr); fcr &= ~(0x03 << 4); fcr |= (1 << 12) | (info->chipsel << 4); do { uint32_t raw_ecc[4], *p; uint8_t *l; int i; /* start 4bit ecc on csX */ target_write_u32(target, fcr_addr, fcr); /* write 512 bytes */ davinci_write_block_data(nand, data, 512); data += 512; data_size -= 512; /* read the ecc */ for (i = 0; i < 4; i++) { target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]); raw_ecc[i] &= 0x03ff03ff; } /* skip 6 bytes of prepad, then pack 10 packed ecc bytes */ for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) { *l++ = p[0] & 0xff; *l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc); *l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0); *l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0); *l++ = (p[1] >> 18) & 0xff; } /* write this "out-of-band" data -- infix */ davinci_write_block_data(nand, oob, 16); oob += 16; oob_size -= 16; } while (data_size); /* the last data and OOB writes included the spare area */ return davinci_writepage_tail(nand, NULL, 0); } static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int read_size; int want_col, at_col; int ret; davinci_write_pagecmd(nand, NAND_CMD_READ0, page); /* large page devices need a start command */ if (nand->page_size > 512) davinci_command(nand, NAND_CMD_READSTART); if (!davinci_nand_ready(nand, 100)) return ERROR_NAND_OPERATION_TIMEOUT; /* NOTE: not bothering to compute and use ECC data for now */ want_col = 0; at_col = 0; while ((data && data_size) || (oob && oob_size)) { if (data && data_size) { if (want_col != at_col) { /* Reads are slow, so seek past them when we can */ ret = davinci_seek_column(nand, want_col); if (ret != ERROR_OK) return ret; at_col = want_col; } /* read 512 bytes or data_size, whichever is smaller*/ read_size = data_size > 512 ? 512 : data_size; davinci_read_block_data(nand, data, read_size); data += read_size; data_size -= read_size; at_col += read_size; } want_col += 512; if (oob && oob_size) { if (want_col != at_col) { ret = davinci_seek_column(nand, want_col); if (ret != ERROR_OK) return ret; at_col = want_col; } /* read this "out-of-band" data -- infix */ read_size = oob_size > 16 ? 16 : oob_size; davinci_read_block_data(nand, oob, read_size); oob += read_size; oob_size -= read_size; at_col += read_size; } want_col += 16; } return ERROR_OK; } NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command) { struct davinci_nand *info; unsigned long chip, aemif; enum ecc eccmode; int chipsel; /* arguments: * - "davinci" * - target * - nand chip address * - ecc mode * - aemif address * Plus someday, optionally, ALE and CLE masks. */ if (CMD_ARGC < 5) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); if (chip == 0) { LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]); goto fail; } if (strcmp(CMD_ARGV[3], "hwecc1") == 0) eccmode = HWECC1; else if (strcmp(CMD_ARGV[3], "hwecc4") == 0) eccmode = HWECC4; else if (strcmp(CMD_ARGV[3], "hwecc4_infix") == 0) eccmode = HWECC4_INFIX; else { LOG_ERROR("Invalid ecc mode %s", CMD_ARGV[3]); goto fail; } COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[4], aemif); if (aemif == 0) { LOG_ERROR("Invalid AEMIF controller address %s", CMD_ARGV[4]); goto fail; } /* REVISIT what we'd *like* to do is look up valid ranges using * target-specific declarations, and not even need to pass the * AEMIF controller address. */ if (aemif == 0x01e00000 /* dm6446, dm357 */ || aemif == 0x01e10000 /* dm335, dm355 */ || aemif == 0x01d10000 /* dm365 */ ) { if (chip < 0x02000000 || chip >= 0x0a000000) { LOG_ERROR("NAND address %08lx out of range?", chip); goto fail; } chipsel = (chip - 0x02000000) >> 25; } else { LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif); goto fail; } info = calloc(1, sizeof *info); if (info == NULL) goto fail; info->eccmode = eccmode; info->chipsel = chipsel; info->aemif = aemif; info->data = chip; info->cmd = chip | 0x10; info->addr = chip | 0x08; nand->controller_priv = info; info->io.target = nand->target; info->io.data = info->data; info->io.op = ARM_NAND_NONE; /* NOTE: for now we don't do any error correction on read. * Nothing else in OpenOCD currently corrects read errors, * and in any case it's *writing* that we care most about. */ info->read_page = nand_read_page_raw; switch (eccmode) { case HWECC1: /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */ info->write_page = davinci_write_page_ecc1; break; case HWECC4: /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */ info->write_page = davinci_write_page_ecc4; break; case HWECC4_INFIX: /* Same 4-bit ECC HW, with problematic page/ecc layout */ info->read_page = davinci_read_page_ecc4infix; info->write_page = davinci_write_page_ecc4infix; break; } return ERROR_OK; fail: return ERROR_NAND_OPERATION_FAILED; } struct nand_flash_controller davinci_nand_controller = { .name = "davinci", .usage = "chip_addr hwecc_mode aemif_addr", .nand_device_command = davinci_nand_device_command, .init = davinci_init, .reset = davinci_reset, .command = davinci_command, .address = davinci_address, .write_data = davinci_write_data, .read_data = davinci_read_data, .write_page = davinci_write_page, .read_page = davinci_read_page, .write_block_data = davinci_write_block_data, .read_block_data = davinci_read_block_data, .nand_ready = davinci_nand_ready, }; openocd-0.9.0/src/flash/nand/lpc3180.c0000644000175000017500000012710412315575360014146 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * Copyright (C) 2010 richard vegh * * Copyright (C) 2010 Oyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "lpc3180.h" #include static int lpc3180_reset(struct nand_device *nand); static int lpc3180_controller_ready(struct nand_device *nand, int timeout); static int lpc3180_tc_ready(struct nand_device *nand, int timeout); #define ECC_OFFS 0x120 #define SPARE_OFFS 0x140 #define DATA_OFFS 0x200 /* nand device lpc3180 */ NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command) { if (CMD_ARGC < 3) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t osc_freq; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq); struct lpc3180_nand_controller *lpc3180_info; lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller)); nand->controller_priv = lpc3180_info; lpc3180_info->osc_freq = osc_freq; if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000)) LOG_WARNING( "LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i", lpc3180_info->osc_freq); lpc3180_info->selected_controller = LPC3180_NO_CONTROLLER; lpc3180_info->sw_write_protection = 0; lpc3180_info->sw_wp_lower_bound = 0x0; lpc3180_info->sw_wp_upper_bound = 0x0; return ERROR_OK; } static int lpc3180_pll(int fclkin, uint32_t pll_ctrl) { int bypass = (pll_ctrl & 0x8000) >> 15; int direct = (pll_ctrl & 0x4000) >> 14; int feedback = (pll_ctrl & 0x2000) >> 13; int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2); int n = ((pll_ctrl & 0x0600) >> 9) + 1; int m = ((pll_ctrl & 0x01fe) >> 1) + 1; int lock = (pll_ctrl & 0x1); if (!lock) LOG_WARNING("PLL is not locked"); if (!bypass && direct) /* direct mode */ return (m * fclkin) / n; if (bypass && !direct) /* bypass mode */ return fclkin / (2 * p); if (bypass & direct) /* direct bypass mode */ return fclkin; if (feedback) /* integer mode */ return m * (fclkin / n); else /* non-integer mode */ return (m / (2 * p)) * (fclkin / n); } static float lpc3180_cycle_time(struct nand_device *nand) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl; int sysclk; int hclk; int hclk_pll; float cycle; /* calculate timings */ /* determine current SYSCLK (13'MHz or main oscillator) */ target_read_u32(target, 0x40004050, &sysclk_ctrl); if ((sysclk_ctrl & 1) == 0) sysclk = lpc3180_info->osc_freq; else sysclk = 13000; /* determine selected HCLK source */ target_read_u32(target, 0x40004044, &pwr_ctrl); if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */ hclk = sysclk; else { target_read_u32(target, 0x40004058, &hclkpll_ctrl); hclk_pll = lpc3180_pll(sysclk, hclkpll_ctrl); target_read_u32(target, 0x40004040, &hclkdiv_ctrl); if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */ hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1); else /* HCLK uses HCLK_PLL */ hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3)); } LOG_DEBUG("LPC3180 HCLK currently clocked at %i kHz", hclk); cycle = (1.0 / hclk) * 1000000.0; return cycle; } static int lpc3180_init(struct nand_device *nand) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; int bus_width = nand->bus_width ? : 8; int address_cycles = nand->address_cycles ? : 3; int page_size = nand->page_size ? : 512; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } /* sanitize arguments */ if ((bus_width != 8) && (bus_width != 16)) { LOG_ERROR("LPC3180 only supports 8 or 16 bit bus width, not %i", bus_width); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* The LPC3180 only brings out 8 bit NAND data bus, but the controller * would support 16 bit, too, so we just warn about this for now */ if (bus_width == 16) LOG_WARNING("LPC3180 only supports 8 bit bus width"); /* inform calling code about selected bus width */ nand->bus_width = bus_width; if ((address_cycles != 3) && (address_cycles != 4)) { LOG_ERROR("LPC3180 only supports 3 or 4 address cycles, not %i", address_cycles); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if ((page_size != 512) && (page_size != 2048)) { LOG_ERROR("LPC3180 only supports 512 or 2048 byte pages, not %i", page_size); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* select MLC controller if none is currently selected */ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_DEBUG("no LPC3180 NAND flash controller selected, using default 'mlc'"); lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER; } if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { uint32_t mlc_icr_value = 0x0; float cycle; int twp, twh, trp, treh, trhz, trbwb, tcea; /* FLASHCLK_CTRL = 0x22 (enable clock for MLC flash controller) */ target_write_u32(target, 0x400040c8, 0x22); /* MLC_CEH = 0x0 (Force nCE assert) */ target_write_u32(target, 0x200b804c, 0x0); /* MLC_LOCK = 0xa25e (unlock protected registers) */ target_write_u32(target, 0x200b8044, 0xa25e); /* MLC_ICR = configuration */ if (lpc3180_info->sw_write_protection) mlc_icr_value |= 0x8; if (page_size == 2048) mlc_icr_value |= 0x4; if (address_cycles == 4) mlc_icr_value |= 0x2; if (bus_width == 16) mlc_icr_value |= 0x1; target_write_u32(target, 0x200b8030, mlc_icr_value); /* calculate NAND controller timings */ cycle = lpc3180_cycle_time(nand); twp = ((40 / cycle) + 1); twh = ((20 / cycle) + 1); trp = ((30 / cycle) + 1); treh = ((15 / cycle) + 1); trhz = ((30 / cycle) + 1); trbwb = ((100 / cycle) + 1); tcea = ((45 / cycle) + 1); /* MLC_LOCK = 0xa25e (unlock protected registers) */ target_write_u32(target, 0x200b8044, 0xa25e); /* MLC_TIME_REG */ target_write_u32(target, 0x200b8034, (twp & 0xf) | ((twh & 0xf) << 4) | ((trp & 0xf) << 8) | ((treh & 0xf) << 12) | ((trhz & 0x7) << 16) | ((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24)); lpc3180_reset(nand); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { float cycle; int r_setup, r_hold, r_width, r_rdy; int w_setup, w_hold, w_width, w_rdy; /* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */ target_write_u32(target, 0x400040c8, 0x05); /* after reset set other registers of SLC so reset calling is here at the begining*/ lpc3180_reset(nand); /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, *DMA read from SLC, WIDTH = bus_width) */ target_write_u32(target, 0x20020014, 0x3e | (bus_width == 16) ? 1 : 0); /* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */ target_write_u32(target, 0x20020020, 0x03); /* DMA configuration * DMACLK_CTRL = 0x01 (enable clock for DMA controller) */ target_write_u32(target, 0x400040e8, 0x01); /* DMACConfig = DMA enabled*/ target_write_u32(target, 0x31000030, 0x01); /* calculate NAND controller timings */ cycle = lpc3180_cycle_time(nand); r_setup = w_setup = 0; r_hold = w_hold = 10 / cycle; r_width = 30 / cycle; w_width = 40 / cycle; r_rdy = w_rdy = 100 / cycle; /* SLC_TAC: SLC timing arcs register */ target_write_u32(target, 0x2002002c, (r_setup & 0xf) | ((r_hold & 0xf) << 4) | ((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) | ((w_setup & 0xf) << 16) | ((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28)); } return ERROR_OK; } static int lpc3180_reset(struct nand_device *nand) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { /* MLC_CMD = 0xff (reset controller and NAND device) */ target_write_u32(target, 0x200b8000, 0xff); if (!lpc3180_controller_ready(nand, 100)) { LOG_ERROR("LPC3180 NAND controller timed out after reset"); return ERROR_NAND_OPERATION_TIMEOUT; } } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */ target_write_u32(target, 0x20020010, 0x6); if (!lpc3180_controller_ready(nand, 100)) { LOG_ERROR("LPC3180 NAND controller timed out after reset"); return ERROR_NAND_OPERATION_TIMEOUT; } } return ERROR_OK; } static int lpc3180_command(struct nand_device *nand, uint8_t command) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { /* MLC_CMD = command */ target_write_u32(target, 0x200b8000, command); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /* SLC_CMD = command */ target_write_u32(target, 0x20020008, command); } return ERROR_OK; } static int lpc3180_address(struct nand_device *nand, uint8_t address) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { /* MLC_ADDR = address */ target_write_u32(target, 0x200b8004, address); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /* SLC_ADDR = address */ target_write_u32(target, 0x20020004, address); } return ERROR_OK; } static int lpc3180_write_data(struct nand_device *nand, uint16_t data) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { /* MLC_DATA = data */ target_write_u32(target, 0x200b0000, data); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /* SLC_DATA = data */ target_write_u32(target, 0x20020000, data); } return ERROR_OK; } static int lpc3180_read_data(struct nand_device *nand, void *data) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { /* data = MLC_DATA, use sized access */ if (nand->bus_width == 8) { uint8_t *data8 = data; target_read_u8(target, 0x200b0000, data8); } else if (nand->bus_width == 16) { uint16_t *data16 = data; target_read_u16(target, 0x200b0000, data16); } else { LOG_ERROR("BUG: bus_width neither 8 nor 16 bit"); return ERROR_NAND_OPERATION_FAILED; } } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { uint32_t data32; /* data = SLC_DATA, must use 32-bit access */ target_read_u32(target, 0x20020000, &data32); if (nand->bus_width == 8) { uint8_t *data8 = data; *data8 = data32 & 0xff; } else if (nand->bus_width == 16) { uint16_t *data16 = data; *data16 = data32 & 0xffff; } else { LOG_ERROR("BUG: bus_width neither 8 nor 16 bit"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; int retval; uint8_t status; uint8_t *page_buffer; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { uint8_t *oob_buffer; int quarter, num_quarters; if (!data && oob) { LOG_ERROR("LPC3180 MLC controller can't write OOB data only"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if (oob && (oob_size > 24)) { LOG_ERROR("LPC3180 MLC controller can't write more " "than 6 bytes for each quarter's OOB data"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if (data_size > (uint32_t)nand->page_size) { LOG_ERROR("data size exceeds page size"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* MLC_CMD = sequential input */ target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN); page_buffer = malloc(512); oob_buffer = malloc(6); if (nand->page_size == 512) { /* MLC_ADDR = 0x0 (one column cycle) */ target_write_u32(target, 0x200b8004, 0x0); /* MLC_ADDR = row */ target_write_u32(target, 0x200b8004, page & 0xff); target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (nand->address_cycles == 4) target_write_u32(target, 0x200b8004, (page >> 16) & 0xff); } else { /* MLC_ADDR = 0x0 (two column cycles) */ target_write_u32(target, 0x200b8004, 0x0); target_write_u32(target, 0x200b8004, 0x0); /* MLC_ADDR = row */ target_write_u32(target, 0x200b8004, page & 0xff); target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); } /* when using the MLC controller, we have to treat a large page device * as being made out of four quarters, each the size of a small page device */ num_quarters = (nand->page_size == 2048) ? 4 : 1; for (quarter = 0; quarter < num_quarters; quarter++) { int thisrun_data_size = (data_size > 512) ? 512 : data_size; int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size; memset(page_buffer, 0xff, 512); if (data) { memcpy(page_buffer, data, thisrun_data_size); data_size -= thisrun_data_size; data += thisrun_data_size; } memset(oob_buffer, 0xff, 6); if (oob) { memcpy(oob_buffer, oob, thisrun_oob_size); oob_size -= thisrun_oob_size; oob += thisrun_oob_size; } /* write MLC_ECC_ENC_REG to start encode cycle */ target_write_u32(target, 0x200b8008, 0x0); target_write_memory(target, 0x200a8000, 4, 128, page_buffer); target_write_memory(target, 0x200a8000, 1, 6, oob_buffer); /* write MLC_ECC_AUTO_ENC_REG to start auto encode */ target_write_u32(target, 0x200b8010, 0x0); if (!lpc3180_controller_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for completion of auto encode cycle"); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; } } /* MLC_CMD = auto program command */ target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG); retval = nand_read_status(nand, &status); if (retval != ERROR_OK) { LOG_ERROR("couldn't read status"); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; } if (status & NAND_STATUS_FAIL) { LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; } free(page_buffer); free(oob_buffer); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /********************************************************************** * Write both SLC NAND flash page main area and spare area. * Small page - * ------------------------------------------ * | 512 bytes main | 16 bytes spare | * ------------------------------------------ * Large page - * ------------------------------------------ * | 2048 bytes main | 64 bytes spare | * ------------------------------------------ * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte * data is written to the 3rd word of the spare area. The ECC * generated for the 2nd 256-byte data is written to the 4th word * of the spare area. The ECC generated for the 3rd 256-byte data is * written to the 7th word of the spare area. The ECC generated * for the 4th 256-byte data is written to the 8th word of the * spare area and so on. * **********************************************************************/ int i = 0, target_mem_base; uint8_t *ecc_flash_buffer; struct working_area *pworking_area; if (lpc3180_info->is_bulk) { if (!data && oob) { /*if oob only mode is active original method is used as SLC *controller hangs during DMA interworking. Anyway the code supports *the oob only mode below. */ return nand_write_page_raw(nand, page, data, data_size, oob, oob_size); } retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); if (ERROR_OK != retval) return retval; /* allocate a working area */ if (target->working_area_size < (uint32_t) nand->page_size + 0x200) { LOG_ERROR("Reserve at least 0x%x physical target working area", nand->page_size + 0x200); return ERROR_FLASH_OPERATION_FAILED; } if (target->working_area_phys%4) { LOG_ERROR( "Reserve the physical target working area at word boundary"); return ERROR_FLASH_OPERATION_FAILED; } if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK) { LOG_ERROR("no working area specified, can't read LPC internal flash"); return ERROR_FLASH_OPERATION_FAILED; } target_mem_base = target->working_area_phys; if (nand->page_size == 2048) page_buffer = malloc(2048); else page_buffer = malloc(512); ecc_flash_buffer = malloc(64); /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst *enabled, DMA write to SLC, WIDTH = bus_width) */ target_write_u32(target, 0x20020014, 0x3c); if (data && !oob) { /* set DMA LLI-s in target memory and in DMA*/ for (i = 0; i < nand->page_size/0x100; i++) { int tmp; /* -------LLI for 256 byte block--------- * DMACC0SrcAddr = SRAM */ target_write_u32(target, target_mem_base+0+i*32, target_mem_base+DATA_OFFS+i*256); if (i == 0) target_write_u32(target, 0x31000100, target_mem_base+DATA_OFFS); /* DMACCxDestAddr = SLC_DMA_DATA */ target_write_u32(target, target_mem_base+4+i*32, 0x20020038); if (i == 0) target_write_u32(target, 0x31000104, 0x20020038); /* DMACCxLLI = next element */ tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc; target_write_u32(target, target_mem_base+8+i*32, tmp); if (i == 0) target_write_u32(target, 0x31000108, tmp); /* DMACCxControl = TransferSize =64, Source burst size =16, * Destination burst size = 16, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 1, * Destination increment = 0, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+12+i*32, 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); if (i == 0) target_write_u32(target, 0x3100010c, 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); /* -------LLI for 3 byte ECC--------- * DMACC0SrcAddr = SLC_ECC*/ target_write_u32(target, target_mem_base+16+i*32, 0x20020034); /* DMACCxDestAddr = SRAM */ target_write_u32(target, target_mem_base+20+i*32, target_mem_base+SPARE_OFFS+8+16*(i>>1)+(i%2)*4); /* DMACCxLLI = next element */ tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc; target_write_u32(target, target_mem_base+24+i*32, tmp); /* DMACCxControl = TransferSize =1, Source burst size =4, * Destination burst size = 4, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 0, * Destination increment = 1, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+28+i*32, 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<< 31); } } else if (data && oob) { /* -------LLI for 512 or 2048 bytes page--------- * DMACC0SrcAddr = SRAM */ target_write_u32(target, target_mem_base, target_mem_base+DATA_OFFS); target_write_u32(target, 0x31000100, target_mem_base+DATA_OFFS); /* DMACCxDestAddr = SLC_DMA_DATA */ target_write_u32(target, target_mem_base+4, 0x20020038); target_write_u32(target, 0x31000104, 0x20020038); /* DMACCxLLI = next element */ target_write_u32(target, target_mem_base+8, (target_mem_base+32)&0xfffffffc); target_write_u32(target, 0x31000108, (target_mem_base+32)&0xfffffffc); /* DMACCxControl = TransferSize =512 or 128, Source burst size =16, * Destination burst size = 16, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 1, * Destination increment = 0, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+12, (nand->page_size == 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); target_write_u32(target, 0x3100010c, (nand->page_size == 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); i = 1; } else if (!data && oob) i = 0; /* -------LLI for spare area--------- * DMACC0SrcAddr = SRAM*/ target_write_u32(target, target_mem_base+0+i*32, target_mem_base+SPARE_OFFS); if (i == 0) target_write_u32(target, 0x31000100, target_mem_base+SPARE_OFFS); /* DMACCxDestAddr = SLC_DMA_DATA */ target_write_u32(target, target_mem_base+4+i*32, 0x20020038); if (i == 0) target_write_u32(target, 0x31000104, 0x20020038); /* DMACCxLLI = next element = NULL */ target_write_u32(target, target_mem_base+8+i*32, 0); if (i == 0) target_write_u32(target, 0x31000108, 0); /* DMACCxControl = TransferSize =16 for large page or 4 for small page, * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 1, * Destination increment = 0, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+12+i*32, (nand->page_size == 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); if (i == 0) target_write_u32(target, 0x3100010c, (nand->page_size == 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27 | 0<<31); memset(ecc_flash_buffer, 0xff, 64); if (oob) memcpy(ecc_flash_buffer, oob, oob_size); target_write_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer); if (data) { memset(page_buffer, 0xff, nand->page_size == 2048 ? 2048 : 512); memcpy(page_buffer, data, data_size); target_write_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048 ? 512 : 128, page_buffer); } free(page_buffer); free(ecc_flash_buffer); /* Enable DMA after channel set up ! LLI only works when DMA is the flow controller! */ /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), *FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/ target_write_u32(target, 0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18); /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */ target_write_u32(target, 0x20020010, 0x3); /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/ target_write_u32(target, 0x20020028, 2); /* SLC_TC */ if (!data && oob) target_write_u32(target, 0x20020030, (nand->page_size == 2048 ? 0x10 : 0x04)); else target_write_u32(target, 0x20020030, (nand->page_size == 2048 ? 0x840 : 0x210)); nand_write_finish(nand); if (!lpc3180_tc_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for completion of DMA"); return ERROR_NAND_OPERATION_FAILED; } target_free_working_area(target, pworking_area); LOG_INFO("Page = 0x%" PRIx32 " was written.", page); } else return nand_write_page_raw(nand, page, data, data_size, oob, oob_size); } return ERROR_OK; } static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; uint8_t *page_buffer; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC3180 NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { uint8_t *oob_buffer; uint32_t page_bytes_done = 0; uint32_t oob_bytes_done = 0; uint32_t mlc_isr; #if 0 if (oob && (oob_size > 6)) { LOG_ERROR("LPC3180 MLC controller can't read more than 6 bytes of OOB data"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } #endif if (data_size > (uint32_t)nand->page_size) { LOG_ERROR("data size exceeds page size"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if (nand->page_size == 2048) { page_buffer = malloc(2048); oob_buffer = malloc(64); } else { page_buffer = malloc(512); oob_buffer = malloc(16); } if (!data && oob) { /* MLC_CMD = Read OOB * we can use the READOOB command on both small and large page devices, * as the controller translates the 0x50 command to a 0x0 with appropriate * positioning of the serial buffer read pointer */ target_write_u32(target, 0x200b8000, NAND_CMD_READOOB); } else { /* MLC_CMD = Read0 */ target_write_u32(target, 0x200b8000, NAND_CMD_READ0); } if (nand->page_size == 512) { /* small page device * MLC_ADDR = 0x0 (one column cycle) */ target_write_u32(target, 0x200b8004, 0x0); /* MLC_ADDR = row */ target_write_u32(target, 0x200b8004, page & 0xff); target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (nand->address_cycles == 4) target_write_u32(target, 0x200b8004, (page >> 16) & 0xff); } else { /* large page device * MLC_ADDR = 0x0 (two column cycles) */ target_write_u32(target, 0x200b8004, 0x0); target_write_u32(target, 0x200b8004, 0x0); /* MLC_ADDR = row */ target_write_u32(target, 0x200b8004, page & 0xff); target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); /* MLC_CMD = Read Start */ target_write_u32(target, 0x200b8000, NAND_CMD_READSTART); } while (page_bytes_done < (uint32_t)nand->page_size) { /* MLC_ECC_AUTO_DEC_REG = dummy */ target_write_u32(target, 0x200b8014, 0xaa55aa55); if (!lpc3180_controller_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for completion of auto decode cycle"); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; } target_read_u32(target, 0x200b8048, &mlc_isr); if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { LOG_ERROR("uncorrectable error detected: 0x%2.2x", (unsigned)mlc_isr); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; } LOG_WARNING("%i symbol error detected and corrected", ((int)(((mlc_isr & 0x30) >> 4) + 1))); } if (data) target_read_memory(target, 0x200a8000, 4, 128, page_buffer + page_bytes_done); if (oob) target_read_memory(target, 0x200a8000, 4, 4, oob_buffer + oob_bytes_done); page_bytes_done += 512; oob_bytes_done += 16; } if (data) memcpy(data, page_buffer, data_size); if (oob) memcpy(oob, oob_buffer, oob_size); free(page_buffer); free(oob_buffer); } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { /********************************************************************** * Read both SLC NAND flash page main area and spare area. * Small page - * ------------------------------------------ * | 512 bytes main | 16 bytes spare | * ------------------------------------------ * Large page - * ------------------------------------------ * | 2048 bytes main | 64 bytes spare | * ------------------------------------------ * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte * data is compared with the 3rd word of the spare area. The ECC * generated for the 2nd 256-byte data is compared with the 4th word * of the spare area. The ECC generated for the 3rd 256-byte data is * compared with the 7th word of the spare area. The ECC generated * for the 4th 256-byte data is compared with the 8th word of the * spare area and so on. * **********************************************************************/ int retval, i, target_mem_base; uint8_t *ecc_hw_buffer; uint8_t *ecc_flash_buffer; struct working_area *pworking_area; if (lpc3180_info->is_bulk) { /* read always the data and also oob areas*/ retval = nand_page_command(nand, page, NAND_CMD_READ0, 0); if (ERROR_OK != retval) return retval; /* allocate a working area */ if (target->working_area_size < (uint32_t) nand->page_size + 0x200) { LOG_ERROR("Reserve at least 0x%x physical target working area", nand->page_size + 0x200); return ERROR_FLASH_OPERATION_FAILED; } if (target->working_area_phys%4) { LOG_ERROR( "Reserve the physical target working area at word boundary"); return ERROR_FLASH_OPERATION_FAILED; } if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK) { LOG_ERROR("no working area specified, can't read LPC internal flash"); return ERROR_FLASH_OPERATION_FAILED; } target_mem_base = target->working_area_phys; if (nand->page_size == 2048) page_buffer = malloc(2048); else page_buffer = malloc(512); ecc_hw_buffer = malloc(32); ecc_flash_buffer = malloc(64); /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst *enabled, DMA read from SLC, WIDTH = bus_width) */ target_write_u32(target, 0x20020014, 0x3e); /* set DMA LLI-s in target memory and in DMA*/ for (i = 0; i < nand->page_size/0x100; i++) { int tmp; /* -------LLI for 256 byte block--------- * DMACC0SrcAddr = SLC_DMA_DATA*/ target_write_u32(target, target_mem_base+0+i*32, 0x20020038); if (i == 0) target_write_u32(target, 0x31000100, 0x20020038); /* DMACCxDestAddr = SRAM */ target_write_u32(target, target_mem_base+4+i*32, target_mem_base+DATA_OFFS+i*256); if (i == 0) target_write_u32(target, 0x31000104, target_mem_base+DATA_OFFS); /* DMACCxLLI = next element */ tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc; target_write_u32(target, target_mem_base+8+i*32, tmp); if (i == 0) target_write_u32(target, 0x31000108, tmp); /* DMACCxControl = TransferSize =64, Source burst size =16, * Destination burst size = 16, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 0, * Destination increment = 1, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+12+i*32, 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<< 31); if (i == 0) target_write_u32(target, 0x3100010c, 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<< 31); /* -------LLI for 3 byte ECC--------- * DMACC0SrcAddr = SLC_ECC*/ target_write_u32(target, target_mem_base+16+i*32, 0x20020034); /* DMACCxDestAddr = SRAM */ target_write_u32(target, target_mem_base+20+i*32, target_mem_base+ECC_OFFS+i*4); /* DMACCxLLI = next element */ tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc; target_write_u32(target, target_mem_base+24+i*32, tmp); /* DMACCxControl = TransferSize =1, Source burst size =4, * Destination burst size = 4, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 0, * Destination increment = 1, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base+28+i*32, 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<< 31); } /* -------LLI for spare area--------- * DMACC0SrcAddr = SLC_DMA_DATA*/ target_write_u32(target, target_mem_base+0+i*32, 0x20020038); /* DMACCxDestAddr = SRAM */ target_write_u32(target, target_mem_base+4+i*32, target_mem_base+SPARE_OFFS); /* DMACCxLLI = next element = NULL */ target_write_u32(target, target_mem_base+8+i*32, 0); /* DMACCxControl = TransferSize =16 for large page or 4 for small page, * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit, * Destination transfer width = 32 bit, Source AHB master select = M0, * Destination AHB master select = M0, Source increment = 0, * Destination increment = 1, Terminal count interrupt enable bit = 0*/ target_write_u32(target, target_mem_base + 12 + i * 32, (nand->page_size == 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<31); /* Enable DMA after channel set up ! LLI only works when DMA is the flow controller! */ /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), *FlowCntrl = 2 (Pher-> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/ target_write_u32(target, 0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18); /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */ target_write_u32(target, 0x20020010, 0x3); /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/ target_write_u32(target, 0x20020028, 2); /* SLC_TC */ target_write_u32(target, 0x20020030, (nand->page_size == 2048 ? 0x840 : 0x210)); if (!lpc3180_tc_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for completion of DMA"); free(page_buffer); free(ecc_hw_buffer); free(ecc_flash_buffer); target_free_working_area(target, pworking_area); return ERROR_NAND_OPERATION_FAILED; } if (data) { target_read_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048 ? 512 : 128, page_buffer); memcpy(data, page_buffer, data_size); LOG_INFO("Page = 0x%" PRIx32 " was read.", page); /* check hw generated ECC for each 256 bytes block with the saved *ECC in flash spare area*/ int idx = nand->page_size/0x200; target_read_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer); target_read_memory(target, target_mem_base+ECC_OFFS, 4, 8, ecc_hw_buffer); for (i = 0; i < idx; i++) { if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+i*8)) != (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+8+i*16))) LOG_WARNING( "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32, i * 2 + 1, page); if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+4+i*8)) != (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+12+i*16))) LOG_WARNING( "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32, i * 2 + 2, page); } } if (oob) memcpy(oob, ecc_flash_buffer, oob_size); free(page_buffer); free(ecc_hw_buffer); free(ecc_flash_buffer); target_free_working_area(target, pworking_area); } else return nand_read_page_raw(nand, page, data, data_size, oob, oob_size); } return ERROR_OK; } static int lpc3180_controller_ready(struct nand_device *nand, int timeout) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("lpc3180_controller_ready count start=%d", timeout); do { if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { uint8_t status; /* Read MLC_ISR, wait for controller to become ready */ target_read_u8(target, 0x200b8048, &status); if (status & 2) { LOG_DEBUG("lpc3180_controller_ready count=%d", timeout); return 1; } } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { uint32_t status; /* Read SLC_STAT and check READY bit */ target_read_u32(target, 0x20020018, &status); if (status & 1) { LOG_DEBUG("lpc3180_controller_ready count=%d", timeout); return 1; } } alive_sleep(1); } while (timeout-- > 0); return 0; } static int lpc3180_nand_ready(struct nand_device *nand, int timeout) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("lpc3180_nand_ready count start=%d", timeout); do { if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) { uint8_t status = 0x0; /* Read MLC_ISR, wait for NAND flash device to become ready */ target_read_u8(target, 0x200b8048, &status); if (status & 1) { LOG_DEBUG("lpc3180_nand_ready count end=%d", timeout); return 1; } } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { uint32_t status = 0x0; /* Read SLC_STAT and check READY bit */ target_read_u32(target, 0x20020018, &status); if (status & 1) { LOG_DEBUG("lpc3180_nand_ready count end=%d", timeout); return 1; } } alive_sleep(1); } while (timeout-- > 0); return 0; } static int lpc3180_tc_ready(struct nand_device *nand, int timeout) { struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC3180 NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("lpc3180_tc_ready count start=%d", timeout); do { if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) { uint32_t status = 0x0; /* Read SLC_INT_STAT and check INT_TC_STAT bit */ target_read_u32(target, 0x2002001c, &status); if (status & 2) { LOG_DEBUG("lpc3180_tc_ready count=%d", timeout); return 1; } } alive_sleep(1); } while (timeout-- > 0); return 0; } COMMAND_HANDLER(handle_lpc3180_select_command) { struct lpc3180_nand_controller *lpc3180_info = NULL; char *selected[] = { "no", "mlc", "slc" }; if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; unsigned num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]); return ERROR_OK; } lpc3180_info = nand->controller_priv; if (CMD_ARGC >= 2) { if (strcmp(CMD_ARGV[1], "mlc") == 0) lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER; else if (strcmp(CMD_ARGV[1], "slc") == 0) { lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER; if (CMD_ARGC == 3 && strcmp(CMD_ARGV[2], "bulk") == 0) lpc3180_info->is_bulk = 1; else lpc3180_info->is_bulk = 0; } else return ERROR_COMMAND_SYNTAX_ERROR; } if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]); else command_print(CMD_CTX, lpc3180_info->is_bulk ? "%s controller selected bulk mode is available" : "%s controller selected bulk mode is not available", selected[lpc3180_info->selected_controller]); return ERROR_OK; } static const struct command_registration lpc3180_exec_command_handlers[] = { { .name = "select", .handler = handle_lpc3180_select_command, .mode = COMMAND_EXEC, .help = "select MLC or SLC controller (default is MLC), SLC can be set to bulk mode", .usage = "bank_id ['mlc'|'slc' ['bulk'] ]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration lpc3180_command_handler[] = { { .name = "lpc3180", .mode = COMMAND_ANY, .help = "LPC3180 NAND flash controller commands", .usage = "", .chain = lpc3180_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct nand_flash_controller lpc3180_nand_controller = { .name = "lpc3180", .commands = lpc3180_command_handler, .nand_device_command = lpc3180_nand_device_command, .init = lpc3180_init, .reset = lpc3180_reset, .command = lpc3180_command, .address = lpc3180_address, .write_data = lpc3180_write_data, .read_data = lpc3180_read_data, .write_page = lpc3180_write_page, .read_page = lpc3180_read_page, .nand_ready = lpc3180_nand_ready, }; openocd-0.9.0/src/flash/nand/lpc3180.h0000644000175000017500000000354212315575360014152 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef LPC3180_NAND_CONTROLLER_H #define LPC3180_NAND_CONTROLLER_H enum lpc3180_selected_controller { LPC3180_NO_CONTROLLER, LPC3180_MLC_CONTROLLER, LPC3180_SLC_CONTROLLER, }; struct lpc3180_nand_controller { int osc_freq; enum lpc3180_selected_controller selected_controller; int is_bulk; int sw_write_protection; uint32_t sw_wp_lower_bound; uint32_t sw_wp_upper_bound; }; #endif /*LPC3180_NAND_CONTROLLER_H */ openocd-0.9.0/src/flash/nand/lpc32xx.c0000644000175000017500000015205212315575360014357 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2011 Bjarne Steinsbo * * Copyright (C) 2010 richard vegh * * Copyright (C) 2010 Oyvind Harboe * * * * Based on a combination of the lpc3180 driver and code from * * uboot-2009.03-lpc32xx by Kevin Wells. * * Any bugs are mine. --BSt * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "lpc32xx.h" #include static int lpc32xx_reset(struct nand_device *nand); static int lpc32xx_controller_ready(struct nand_device *nand, int timeout); static int lpc32xx_tc_ready(struct nand_device *nand, int timeout); extern int nand_correct_data(struct nand_device *nand, u_char *dat, u_char *read_ecc, u_char *calc_ecc); /* These are offset with the working area in IRAM when using DMA to * read/write data to the SLC controller. * - DMA descriptors will be put at start of working area, * - Hardware generated ECC will be stored at ECC_OFFS * - OOB wil be read/written from/to SPARE_OFFS * - Actual page data will be read from/to DATA_OFFS * There are unused holes between the used areas. */ #define ECC_OFFS 0x120 #define SPARE_OFFS 0x140 #define DATA_OFFS 0x200 static const int sp_ooblayout[] = { 10, 11, 12, 13, 14, 15 }; static const int lp_ooblayout[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }; typedef struct { volatile uint32_t dma_src; volatile uint32_t dma_dest; volatile uint32_t next_lli; volatile uint32_t next_ctrl; } dmac_ll_t; static dmac_ll_t dmalist[(2048/256) * 2 + 1]; /* nand device lpc32xx */ NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command) { if (CMD_ARGC < 3) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t osc_freq; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq); struct lpc32xx_nand_controller *lpc32xx_info; lpc32xx_info = malloc(sizeof(struct lpc32xx_nand_controller)); nand->controller_priv = lpc32xx_info; lpc32xx_info->osc_freq = osc_freq; if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000)) LOG_WARNING("LPC32xx oscillator frequency should be between " "1000 and 20000 kHz, was %i", lpc32xx_info->osc_freq); lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER; lpc32xx_info->sw_write_protection = 0; lpc32xx_info->sw_wp_lower_bound = 0x0; lpc32xx_info->sw_wp_upper_bound = 0x0; return ERROR_OK; } static int lpc32xx_pll(int fclkin, uint32_t pll_ctrl) { int bypass = (pll_ctrl & 0x8000) >> 15; int direct = (pll_ctrl & 0x4000) >> 14; int feedback = (pll_ctrl & 0x2000) >> 13; int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2); int n = ((pll_ctrl & 0x0600) >> 9) + 1; int m = ((pll_ctrl & 0x01fe) >> 1) + 1; int lock = (pll_ctrl & 0x1); if (!lock) LOG_WARNING("PLL is not locked"); if (!bypass && direct) /* direct mode */ return (m * fclkin) / n; if (bypass && !direct) /* bypass mode */ return fclkin / (2 * p); if (bypass & direct) /* direct bypass mode */ return fclkin; if (feedback) /* integer mode */ return m * (fclkin / n); else /* non-integer mode */ return (m / (2 * p)) * (fclkin / n); } static float lpc32xx_cycle_time(struct nand_device *nand) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl; int sysclk; int hclk; int hclk_pll; float cycle; int retval; /* calculate timings */ /* determine current SYSCLK (13'MHz or main oscillator) */ retval = target_read_u32(target, 0x40004050, &sysclk_ctrl); if (ERROR_OK != retval) { LOG_ERROR("could not read SYSCLK_CTRL"); return ERROR_NAND_OPERATION_FAILED; } if ((sysclk_ctrl & 1) == 0) sysclk = lpc32xx_info->osc_freq; else sysclk = 13000; /* determine selected HCLK source */ retval = target_read_u32(target, 0x40004044, &pwr_ctrl); if (ERROR_OK != retval) { LOG_ERROR("could not read HCLK_CTRL"); return ERROR_NAND_OPERATION_FAILED; } if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */ hclk = sysclk; else { retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl); if (ERROR_OK != retval) { LOG_ERROR("could not read HCLKPLL_CTRL"); return ERROR_NAND_OPERATION_FAILED; } hclk_pll = lpc32xx_pll(sysclk, hclkpll_ctrl); retval = target_read_u32(target, 0x40004040, &hclkdiv_ctrl); if (ERROR_OK != retval) { LOG_ERROR("could not read CLKDIV_CTRL"); return ERROR_NAND_OPERATION_FAILED; } if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */ hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1); else /* HCLK uses HCLK_PLL */ hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3)); } LOG_DEBUG("LPC32xx HCLK currently clocked at %i kHz", hclk); cycle = (1.0 / hclk) * 1000000.0; return cycle; } static int lpc32xx_init(struct nand_device *nand) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int bus_width = nand->bus_width ? : 8; int address_cycles = nand->address_cycles ? : 3; int page_size = nand->page_size ? : 512; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } /* sanitize arguments */ if (bus_width != 8) { LOG_ERROR("LPC32xx doesn't support %i", bus_width); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* inform calling code about selected bus width */ nand->bus_width = bus_width; if ((address_cycles < 3) || (address_cycles > 5)) { LOG_ERROR("LPC32xx driver doesn't support %i address cycles", address_cycles); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if ((page_size != 512) && (page_size != 2048)) { LOG_ERROR("LPC32xx doesn't support page size %i", page_size); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* select MLC controller if none is currently selected */ if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_DEBUG("no LPC32xx NAND flash controller selected, " "using default 'slc'"); lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER; } if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { uint32_t mlc_icr_value = 0x0; float cycle; int twp, twh, trp, treh, trhz, trbwb, tcea; /* FLASHCLK_CTRL = 0x22 (enable clk for MLC) */ retval = target_write_u32(target, 0x400040c8, 0x22); if (ERROR_OK != retval) { LOG_ERROR("could not set FLASHCLK_CTRL"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_CEH = 0x0 (Force nCE assert) */ retval = target_write_u32(target, 0x200b804c, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CEH"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_LOCK = 0xa25e (unlock protected registers) */ retval = target_write_u32(target, 0x200b8044, 0xa25e); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_LOCK"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_ICR = configuration */ if (lpc32xx_info->sw_write_protection) mlc_icr_value |= 0x8; if (page_size == 2048) mlc_icr_value |= 0x4; if (address_cycles == 4) mlc_icr_value |= 0x2; if (bus_width == 16) mlc_icr_value |= 0x1; retval = target_write_u32(target, 0x200b8030, mlc_icr_value); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ICR"); return ERROR_NAND_OPERATION_FAILED; } /* calculate NAND controller timings */ cycle = lpc32xx_cycle_time(nand); twp = ((40 / cycle) + 1); twh = ((20 / cycle) + 1); trp = ((30 / cycle) + 1); treh = ((15 / cycle) + 1); trhz = ((30 / cycle) + 1); trbwb = ((100 / cycle) + 1); tcea = ((45 / cycle) + 1); /* MLC_LOCK = 0xa25e (unlock protected registers) */ retval = target_write_u32(target, 0x200b8044, 0xa25e); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_LOCK"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_TIME_REG */ retval = target_write_u32(target, 0x200b8034, (twp & 0xf) | ((twh & 0xf) << 4) | ((trp & 0xf) << 8) | ((treh & 0xf) << 12) | ((trhz & 0x7) << 16) | ((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24)); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_TIME_REG"); return ERROR_NAND_OPERATION_FAILED; } retval = lpc32xx_reset(nand); if (ERROR_OK != retval) return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { float cycle; int r_setup, r_hold, r_width, r_rdy; int w_setup, w_hold, w_width, w_rdy; /* FLASHCLK_CTRL = 0x05 (enable clk for SLC) */ retval = target_write_u32(target, 0x400040c8, 0x05); if (ERROR_OK != retval) { LOG_ERROR("could not set FLASHCLK_CTRL"); return ERROR_NAND_OPERATION_FAILED; } /* after reset set other registers of SLC, * so reset calling is here at the begining */ retval = lpc32xx_reset(nand); if (ERROR_OK != retval) return ERROR_NAND_OPERATION_FAILED; /* SLC_CFG = Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width) */ retval = target_write_u32(target, 0x20020014, 0x3e | (bus_width == 16) ? 1 : 0); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_CFG"); return ERROR_NAND_OPERATION_FAILED; } /* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */ retval = target_write_u32(target, 0x20020020, 0x03); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_IEN"); return ERROR_NAND_OPERATION_FAILED; } /* DMA configuration */ /* DMACLK_CTRL = 0x01 (enable clock for DMA controller) */ retval = target_write_u32(target, 0x400040e8, 0x01); if (ERROR_OK != retval) { LOG_ERROR("could not set DMACLK_CTRL"); return ERROR_NAND_OPERATION_FAILED; } /* DMACConfig = DMA enabled*/ retval = target_write_u32(target, 0x31000030, 0x01); if (ERROR_OK != retval) { LOG_ERROR("could not set DMACConfig"); return ERROR_NAND_OPERATION_FAILED; } /* calculate NAND controller timings */ cycle = lpc32xx_cycle_time(nand); r_setup = w_setup = 0; r_hold = w_hold = 10 / cycle; r_width = 30 / cycle; w_width = 40 / cycle; r_rdy = w_rdy = 100 / cycle; /* SLC_TAC: SLC timing arcs register */ retval = target_write_u32(target, 0x2002002c, (r_setup & 0xf) | ((r_hold & 0xf) << 4) | ((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) | ((w_setup & 0xf) << 16) | ((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28)); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_TAC"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc32xx_reset(struct nand_device *nand) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use " "LPC32xx NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { /* MLC_CMD = 0xff (reset controller and NAND device) */ retval = target_write_u32(target, 0x200b8000, 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } if (!lpc32xx_controller_ready(nand, 100)) { LOG_ERROR("LPC32xx MLC NAND controller timed out " "after reset"); return ERROR_NAND_OPERATION_TIMEOUT; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */ retval = target_write_u32(target, 0x20020010, 0x6); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_CTRL"); return ERROR_NAND_OPERATION_FAILED; } if (!lpc32xx_controller_ready(nand, 100)) { LOG_ERROR("LPC32xx SLC NAND controller timed out " "after reset"); return ERROR_NAND_OPERATION_TIMEOUT; } } return ERROR_OK; } static int lpc32xx_command(struct nand_device *nand, uint8_t command) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use " "LPC32xx NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { /* MLC_CMD = command */ retval = target_write_u32(target, 0x200b8000, command); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { /* SLC_CMD = command */ retval = target_write_u32(target, 0x20020008, command); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc32xx_address(struct nand_device *nand, uint8_t address) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use " "LPC32xx NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { /* MLC_ADDR = address */ retval = target_write_u32(target, 0x200b8004, address); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { /* SLC_ADDR = address */ retval = target_write_u32(target, 0x20020004, address); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc32xx_write_data(struct nand_device *nand, uint16_t data) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use " "LPC32xx NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { /* MLC_DATA = data */ retval = target_write_u32(target, 0x200b0000, data); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_DATA"); return ERROR_NAND_OPERATION_FAILED; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { /* SLC_DATA = data */ retval = target_write_u32(target, 0x20020000, data); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_DATA"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc32xx_read_data(struct nand_device *nand, void *data) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { /* data = MLC_DATA, use sized access */ if (nand->bus_width == 8) { uint8_t *data8 = data; retval = target_read_u8(target, 0x200b0000, data8); } else { LOG_ERROR("BUG: bus_width neither 8 nor 16 bit"); return ERROR_NAND_OPERATION_FAILED; } if (ERROR_OK != retval) { LOG_ERROR("could not read MLC_DATA"); return ERROR_NAND_OPERATION_FAILED; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { uint32_t data32; /* data = SLC_DATA, must use 32-bit access */ retval = target_read_u32(target, 0x20020000, &data32); if (ERROR_OK != retval) { LOG_ERROR("could not read SLC_DATA"); return ERROR_NAND_OPERATION_FAILED; } if (nand->bus_width == 8) { uint8_t *data8 = data; *data8 = data32 & 0xff; } else { LOG_ERROR("BUG: bus_width neither 8 nor 16 bit"); return ERROR_NAND_OPERATION_FAILED; } } return ERROR_OK; } static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct target *target = nand->target; int retval; uint8_t status; static uint8_t page_buffer[512]; static uint8_t oob_buffer[6]; int quarter, num_quarters; /* MLC_CMD = sequential input */ retval = target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } if (nand->page_size == 512) { /* MLC_ADDR = 0x0 (one column cycle) */ retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_ADDR = row */ retval = target_write_u32(target, 0x200b8004, page & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } if (nand->address_cycles == 4) { retval = target_write_u32(target, 0x200b8004, (page >> 16) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } } } else { /* MLC_ADDR = 0x0 (two column cycles) */ retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_ADDR = row */ retval = target_write_u32(target, 0x200b8004, page & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } } /* when using the MLC controller, we have to treat a large page device * as being made out of four quarters, each the size of a small page * device */ num_quarters = (nand->page_size == 2048) ? 4 : 1; for (quarter = 0; quarter < num_quarters; quarter++) { int thisrun_data_size = (data_size > 512) ? 512 : data_size; int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size; memset(page_buffer, 0xff, 512); if (data) { memcpy(page_buffer, data, thisrun_data_size); data_size -= thisrun_data_size; data += thisrun_data_size; } memset(oob_buffer, 0xff, 6); if (oob) { memcpy(oob_buffer, oob, thisrun_oob_size); oob_size -= thisrun_oob_size; oob += thisrun_oob_size; } /* write MLC_ECC_ENC_REG to start encode cycle */ retval = target_write_u32(target, 0x200b8008, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ECC_ENC_REG"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_memory(target, 0x200a8000, 4, 128, page_buffer); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_BUF (data)"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_memory(target, 0x200a8000, 1, 6, oob_buffer); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_BUF (oob)"); return ERROR_NAND_OPERATION_FAILED; } /* write MLC_ECC_AUTO_ENC_REG to start auto encode */ retval = target_write_u32(target, 0x200b8010, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ECC_AUTO_ENC_REG"); return ERROR_NAND_OPERATION_FAILED; } if (!lpc32xx_controller_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for " "completion of auto encode cycle"); return ERROR_NAND_OPERATION_FAILED; } } /* MLC_CMD = auto program command */ retval = target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } retval = nand_read_status(nand, &status); if (retval != ERROR_OK) { LOG_ERROR("couldn't read status"); return ERROR_NAND_OPERATION_FAILED; } if (status & NAND_STATUS_FAIL) { LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } /* SLC controller in !raw mode will use target cpu to read/write nand from/to * target internal memory. The transfer to/from flash is done by DMA. This * function sets up the dma linked list in host memory for later transfer to * target. */ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size, int do_read) { uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst; /* DMACCxControl = TransferSize =64, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit, Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0, // set later Destination increment = 0, // set later Terminal count interrupt enable bit = 0 // set on last */ /* * Write Operation Sequence for Small Block NAND * ---------------------------------------------------------- * 1. X'fer 256 bytes of data from Memory to Flash. * 2. Copy generated ECC data from Register to Spare Area * 3. X'fer next 256 bytes of data from Memory to Flash. * 4. Copy generated ECC data from Register to Spare Area. * 5. X'fer 16 byets of Spare area from Memory to Flash. * Read Operation Sequence for Small Block NAND * ---------------------------------------------------------- * 1. X'fer 256 bytes of data from Flash to Memory. * 2. Copy generated ECC data from Register to ECC calc Buffer. * 3. X'fer next 256 bytes of data from Flash to Memory. * 4. Copy generated ECC data from Register to ECC calc Buffer. * 5. X'fer 16 bytes of Spare area from Flash to Memory. * Write Operation Sequence for Large Block NAND * ---------------------------------------------------------- * 1. Steps(1-4) of Write Operations repeate for four times * which generates 16 DMA descriptors to X'fer 2048 bytes of * data & 32 bytes of ECC data. * 2. X'fer 64 bytes of Spare area from Memory to Flash. * Read Operation Sequence for Large Block NAND * ---------------------------------------------------------- * 1. Steps(1-4) of Read Operations repeate for four times * which generates 16 DMA descriptors to X'fer 2048 bytes of * data & 32 bytes of ECC data. * 2. X'fer 64 bytes of Spare area from Flash to Memory. */ ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24 | 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31); /* DMACCxControl = TransferSize =1, Source burst size =4, Destination burst size = 4, Source transfer width = 32 bit, Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0, Destination increment = 1, Terminal count interrupt enable bit = 0 */ ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24 | 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31; /* DMACCxControl = TransferSize =16 for lp or 4 for sp, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit, Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0, // set later Destination increment = 0, // set later Terminal count interrupt enable bit = 1 // set on last */ oob_ctrl = (page_size == 2048 ? 0x10 : 0x04) | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24 | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31; if (do_read) { ctrl |= 1 << 27;/* Destination increment = 1 */ oob_ctrl |= 1 << 27; /* Destination increment = 1 */ dmasrc = 0x20020038; /* SLC_DMA_DATA */ dmadst = target_mem_base + DATA_OFFS; } else { ctrl |= 1 << 26;/* Source increment = 1 */ oob_ctrl |= 1 << 26; /* Source increment = 1 */ dmasrc = target_mem_base + DATA_OFFS; dmadst = 0x20020038; /* SLC_DMA_DATA */ } /* * Write Operation Sequence for Small Block NAND * ---------------------------------------------------------- * 1. X'fer 256 bytes of data from Memory to Flash. * 2. Copy generated ECC data from Register to Spare Area * 3. X'fer next 256 bytes of data from Memory to Flash. * 4. Copy generated ECC data from Register to Spare Area. * 5. X'fer 16 byets of Spare area from Memory to Flash. * Read Operation Sequence for Small Block NAND * ---------------------------------------------------------- * 1. X'fer 256 bytes of data from Flash to Memory. * 2. Copy generated ECC data from Register to ECC calc Buffer. * 3. X'fer next 256 bytes of data from Flash to Memory. * 4. Copy generated ECC data from Register to ECC calc Buffer. * 5. X'fer 16 bytes of Spare area from Flash to Memory. * Write Operation Sequence for Large Block NAND * ---------------------------------------------------------- * 1. Steps(1-4) of Write Operations repeate for four times * which generates 16 DMA descriptors to X'fer 2048 bytes of * data & 32 bytes of ECC data. * 2. X'fer 64 bytes of Spare area from Memory to Flash. * Read Operation Sequence for Large Block NAND * ---------------------------------------------------------- * 1. Steps(1-4) of Read Operations repeate for four times * which generates 16 DMA descriptors to X'fer 2048 bytes of * data & 32 bytes of ECC data. * 2. X'fer 64 bytes of Spare area from Flash to Memory. */ for (i = 0; i < page_size/0x100; i++) { dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256)); dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst); dmalist[i*2].next_lli = target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t); dmalist[i*2].next_ctrl = ctrl; dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */ dmalist[(i*2) + 1].dma_dest = target_mem_base + ECC_OFFS + i * 4; dmalist[(i*2) + 1].next_lli = target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t); dmalist[(i*2) + 1].next_ctrl = ecc_ctrl; } if (do_read) dmadst = target_mem_base + SPARE_OFFS; else { dmasrc = target_mem_base + SPARE_OFFS; dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */ dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */ } dmalist[i*2].dma_src = dmasrc; dmalist[i*2].dma_dest = dmadst; dmalist[i*2].next_lli = 0; dmalist[i*2].next_ctrl = oob_ctrl; return i * 2 + 1; /* Number of descriptors */ } static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count, int do_wait) { struct target *target = nand->target; int retval; /* DMACIntTCClear = ch0 */ retval = target_write_u32(target, 0x31000008, 1); if (ERROR_OK != retval) { LOG_ERROR("Could not set DMACIntTCClear"); return retval; } /* DMACIntErrClear = ch0 */ retval = target_write_u32(target, 0x31000010, 1); if (ERROR_OK != retval) { LOG_ERROR("Could not set DMACIntErrClear"); return retval; } /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0 */ retval = target_write_u32(target, 0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18); if (ERROR_OK != retval) { LOG_ERROR("Could not set DMACC0Config"); return retval; } /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */ retval = target_write_u32(target, 0x20020010, 0x3); if (ERROR_OK != retval) { LOG_ERROR("Could not set SLC_CTRL"); return retval; } /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/ retval = target_write_u32(target, 0x20020028, 2); if (ERROR_OK != retval) { LOG_ERROR("Could not set SLC_ICR"); return retval; } /* SLC_TC */ retval = target_write_u32(target, 0x20020030, count); if (ERROR_OK != retval) { LOG_ERROR("lpc32xx_start_slc_dma: Could not set SLC_TC"); return retval; } /* Wait finish */ if (do_wait && !lpc32xx_tc_ready(nand, 100)) { LOG_ERROR("timeout while waiting for completion of DMA"); return ERROR_NAND_OPERATION_FAILED; } return retval; } static int lpc32xx_dma_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; LOG_DEBUG("lpc32xx_dma_ready count start=%d", timeout); do { uint32_t tc_stat; uint32_t err_stat; int retval; /* Read DMACRawIntTCStat */ retval = target_read_u32(target, 0x31000014, &tc_stat); if (ERROR_OK != retval) { LOG_ERROR("Could not read DMACRawIntTCStat"); return 0; } /* Read DMACRawIntErrStat */ retval = target_read_u32(target, 0x31000018, &err_stat); if (ERROR_OK != retval) { LOG_ERROR("Could not read DMACRawIntErrStat"); return 0; } if ((tc_stat | err_stat) & 1) { LOG_DEBUG("lpc32xx_dma_ready count=%d", timeout); if (err_stat & 1) { LOG_ERROR("lpc32xx_dma_ready " "DMA error, aborted"); return 0; } else return 1; } alive_sleep(1); } while (timeout-- > 0); return 0; } static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare, const uint32_t *ecc, int count) { int i; for (i = 0; i < (count * 3); i += 3) { uint32_t ce = ecc[i/3]; ce = ~(ce << 2) & 0xFFFFFF; spare[i+2] = (uint8_t)(ce & 0xFF); ce >>= 8; spare[i+1] = (uint8_t)(ce & 0xFF); ce >>= 8; spare[i] = (uint8_t)(ce & 0xFF); } return 0; } static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size) { int addr = 0; while (oob_size > 0) { LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, oob[0], oob[1], oob[2], oob[3], oob[4], oob[5], oob[6], oob[7]); oob += 8; addr += 8; oob_size -= 8; } } static int lpc32xx_write_page_slc(struct nand_device *nand, struct working_area *pworking_area, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct target *target = nand->target; int retval; uint32_t target_mem_base; LOG_DEBUG("SLC write page %" PRIx32 " data=%d, oob=%d, " "data_size=%" PRIu32 ", oob_size=%" PRIu32, page, data != 0, oob != 0, data_size, oob_size); target_mem_base = pworking_area->address; /* * Skip writting page which has all 0xFF data as this will * generate 0x0 value. */ if (data && !oob) { uint32_t i, all_ff = 1; for (i = 0; i < data_size; i++) if (data[i] != 0xFF) { all_ff = 0; break; } if (all_ff) return ERROR_OK; } /* Make the dma descriptors in local memory */ int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0); /* Write them to target. XXX: Assumes host and target have same byte sex. */ retval = target_write_memory(target, target_mem_base, 4, nll * sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist); if (ERROR_OK != retval) { LOG_ERROR("Could not write DMA descriptors to IRAM"); return retval; } retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); if (ERROR_OK != retval) { LOG_ERROR("NAND_CMD_SEQIN failed"); return retval; } /* SLC_CFG = Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA write to SLC, WIDTH = bus_width */ retval = target_write_u32(target, 0x20020014, 0x3c); if (ERROR_OK != retval) { LOG_ERROR("Could not set SLC_CFG"); return retval; } if (data) { /* Write data to target */ static uint8_t fdata[2048]; memset(fdata, 0xFF, nand->page_size); memcpy(fdata, data, data_size); retval = target_write_memory(target, target_mem_base + DATA_OFFS, 4, nand->page_size/4, fdata); if (ERROR_OK != retval) { LOG_ERROR("Could not write data to IRAM"); return retval; } /* Write first decriptor to DMA controller */ retval = target_write_memory(target, 0x31000100, 4, sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist); if (ERROR_OK != retval) { LOG_ERROR("Could not write DMA descriptor to DMAC"); return retval; } /* Start xfer of data from iram to flash using DMA */ int tot_size = nand->page_size; tot_size += tot_size == 2048 ? 64 : 16; retval = lpc32xx_start_slc_dma(nand, tot_size, 0); if (ERROR_OK != retval) { LOG_ERROR("DMA failed"); return retval; } /* Wait for DMA to finish. SLC is not finished at this stage */ if (!lpc32xx_dma_ready(nand, 100)) { LOG_ERROR("Data DMA failed during write"); return ERROR_FLASH_OPERATION_FAILED; } } /* data xfer */ /* Copy OOB to iram */ static uint8_t foob[64]; int foob_size = nand->page_size == 2048 ? 64 : 16; memset(foob, 0xFF, foob_size); if (oob) /* Raw mode */ memcpy(foob, oob, oob_size); else { /* Get HW generated ECC, made while writing data */ int ecc_count = nand->page_size == 2048 ? 8 : 2; static uint32_t hw_ecc[8]; retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4, ecc_count, (uint8_t *)hw_ecc); if (ERROR_OK != retval) { LOG_ERROR("Reading hw generated ECC from IRAM failed"); return retval; } /* Copy to oob, at correct offsets */ static uint8_t ecc[24]; slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count); const int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout; int i; for (i = 0; i < ecc_count * 3; i++) foob[layout[i]] = ecc[i]; lpc32xx_dump_oob(foob, foob_size); } retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4, foob_size / 4, foob); if (ERROR_OK != retval) { LOG_ERROR("Writing OOB to IRAM failed"); return retval; } /* Write OOB decriptor to DMA controller */ retval = target_write_memory(target, 0x31000100, 4, sizeof(dmac_ll_t) / 4, (uint8_t *)(&dmalist[nll-1])); if (ERROR_OK != retval) { LOG_ERROR("Could not write OOB DMA descriptor to DMAC"); return retval; } if (data) { /* Only restart DMA with last descriptor, * don't setup SLC again */ /* DMACIntTCClear = ch0 */ retval = target_write_u32(target, 0x31000008, 1); if (ERROR_OK != retval) { LOG_ERROR("Could not set DMACIntTCClear"); return retval; } /* DMACCxConfig= * E=1, * SrcPeripheral = 1 (SLC), * DestPeripheral = 1 (SLC), * FlowCntrl = 2 (Pher -> Mem, DMA), * IE = 0, * ITC = 0, * L= 0, * H=0 */ retval = target_write_u32(target, 0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18); if (ERROR_OK != retval) { LOG_ERROR("Could not set DMACC0Config"); return retval; } /* Wait finish */ if (!lpc32xx_tc_ready(nand, 100)) { LOG_ERROR("timeout while waiting for " "completion of DMA"); return ERROR_NAND_OPERATION_FAILED; } } else { /* Start xfer of data from iram to flash using DMA */ retval = lpc32xx_start_slc_dma(nand, foob_size, 1); if (ERROR_OK != retval) { LOG_ERROR("DMA OOB failed"); return retval; } } /* Let NAND start actual writing */ retval = nand_write_finish(nand); if (ERROR_OK != retval) { LOG_ERROR("nand_write_finish failed"); return retval; } return ERROR_OK; } static int lpc32xx_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval = ERROR_OK; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { if (!data && oob) { LOG_ERROR("LPC32xx MLC controller can't write " "OOB data only"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if (oob && (oob_size > 24)) { LOG_ERROR("LPC32xx MLC controller can't write more " "than 6 bytes for each quarter's OOB data"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } if (data_size > (uint32_t)nand->page_size) { LOG_ERROR("data size exceeds page size"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } retval = lpc32xx_write_page_mlc(nand, page, data, data_size, oob, oob_size); } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { struct working_area *pworking_area; if (!data && oob) { /* * if oob only mode is active original method is used * as SLC controller hangs during DMA interworking. (?) * Anyway the code supports the oob only mode below. */ return nand_write_page_raw(nand, page, data, data_size, oob, oob_size); } retval = target_alloc_working_area(target, nand->page_size + DATA_OFFS, &pworking_area); if (retval != ERROR_OK) { LOG_ERROR("Can't allocate working area in " "LPC internal RAM"); return ERROR_FLASH_OPERATION_FAILED; } retval = lpc32xx_write_page_slc(nand, pworking_area, page, data, data_size, oob, oob_size); target_free_working_area(target, pworking_area); } return retval; } static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct target *target = nand->target; static uint8_t page_buffer[2048]; static uint8_t oob_buffer[64]; uint32_t page_bytes_done = 0; uint32_t oob_bytes_done = 0; uint32_t mlc_isr; int retval; if (!data && oob) { /* MLC_CMD = Read OOB * we can use the READOOB command on both small and large page * devices, as the controller translates the 0x50 command to * a 0x0 with appropriate positioning of the serial buffer * read pointer */ retval = target_write_u32(target, 0x200b8000, NAND_CMD_READOOB); } else { /* MLC_CMD = Read0 */ retval = target_write_u32(target, 0x200b8000, NAND_CMD_READ0); } if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } if (nand->page_size == 512) { /* small page device * MLC_ADDR = 0x0 (one column cycle) */ retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_ADDR = row */ retval = target_write_u32(target, 0x200b8004, page & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } if (nand->address_cycles == 4) { retval = target_write_u32(target, 0x200b8004, (page >> 16) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } } } else { /* large page device * MLC_ADDR = 0x0 (two column cycles) */ retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, 0x0); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_ADDR = row */ retval = target_write_u32(target, 0x200b8004, page & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } retval = target_write_u32(target, 0x200b8004, (page >> 8) & 0xff); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ADDR"); return ERROR_NAND_OPERATION_FAILED; } /* MLC_CMD = Read Start */ retval = target_write_u32(target, 0x200b8000, NAND_CMD_READSTART); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_CMD"); return ERROR_NAND_OPERATION_FAILED; } } while (page_bytes_done < (uint32_t)nand->page_size) { /* MLC_ECC_AUTO_DEC_REG = dummy */ retval = target_write_u32(target, 0x200b8014, 0xaa55aa55); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_ECC_AUTO_DEC_REG"); return ERROR_NAND_OPERATION_FAILED; } if (!lpc32xx_controller_ready(nand, 1000)) { LOG_ERROR("timeout while waiting for " "completion of auto decode cycle"); return ERROR_NAND_OPERATION_FAILED; } retval = target_read_u32(target, 0x200b8048, &mlc_isr); if (ERROR_OK != retval) { LOG_ERROR("could not read MLC_ISR"); return ERROR_NAND_OPERATION_FAILED; } if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { LOG_ERROR("uncorrectable error detected: " "0x%2.2x", (unsigned)mlc_isr); return ERROR_NAND_OPERATION_FAILED; } LOG_WARNING("%i symbol error detected and corrected", ((int)(((mlc_isr & 0x30) >> 4) + 1))); } if (data) { retval = target_read_memory(target, 0x200a8000, 4, 128, page_buffer + page_bytes_done); if (ERROR_OK != retval) { LOG_ERROR("could not read MLC_BUF (data)"); return ERROR_NAND_OPERATION_FAILED; } } if (oob) { retval = target_read_memory(target, 0x200a8000, 4, 4, oob_buffer + oob_bytes_done); if (ERROR_OK != retval) { LOG_ERROR("could not read MLC_BUF (oob)"); return ERROR_NAND_OPERATION_FAILED; } } page_bytes_done += 512; oob_bytes_done += 16; } if (data) memcpy(data, page_buffer, data_size); if (oob) memcpy(oob, oob_buffer, oob_size); return ERROR_OK; } static int lpc32xx_read_page_slc(struct nand_device *nand, struct working_area *pworking_area, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct target *target = nand->target; int retval; uint32_t target_mem_base; LOG_DEBUG("SLC read page %" PRIx32 " data=%" PRIu32 ", oob=%" PRIu32, page, data_size, oob_size); target_mem_base = pworking_area->address; /* Make the dma descriptors in local memory */ int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 1); /* Write them to target. XXX: Assumes host and target have same byte sex. */ retval = target_write_memory(target, target_mem_base, 4, nll * sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist); if (ERROR_OK != retval) { LOG_ERROR("Could not write DMA descriptors to IRAM"); return retval; } retval = nand_page_command(nand, page, NAND_CMD_READ0, 0); if (ERROR_OK != retval) { LOG_ERROR("lpc32xx_read_page_slc: NAND_CMD_READ0 failed"); return retval; } /* SLC_CFG = Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width */ retval = target_write_u32(target, 0x20020014, 0x3e); if (ERROR_OK != retval) { LOG_ERROR("lpc32xx_read_page_slc: Could not set SLC_CFG"); return retval; } /* Write first decriptor to DMA controller */ retval = target_write_memory(target, 0x31000100, 4, sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist); if (ERROR_OK != retval) { LOG_ERROR("Could not write DMA descriptor to DMAC"); return retval; } /* Start xfer of data from flash to iram using DMA */ int tot_size = nand->page_size; tot_size += nand->page_size == 2048 ? 64 : 16; retval = lpc32xx_start_slc_dma(nand, tot_size, 1); if (ERROR_OK != retval) { LOG_ERROR("lpc32xx_read_page_slc: DMA read failed"); return retval; } /* Copy data from iram */ if (data) { retval = target_read_memory(target, target_mem_base + DATA_OFFS, 4, data_size/4, data); if (ERROR_OK != retval) { LOG_ERROR("Could not read data from IRAM"); return retval; } } if (oob) { /* No error correction, just return data as read from flash */ retval = target_read_memory(target, target_mem_base + SPARE_OFFS, 4, oob_size/4, oob); if (ERROR_OK != retval) { LOG_ERROR("Could not read OOB from IRAM"); return retval; } return ERROR_OK; } /* Copy OOB from flash, stored in IRAM */ static uint8_t foob[64]; retval = target_read_memory(target, target_mem_base + SPARE_OFFS, 4, nand->page_size == 2048 ? 16 : 4, foob); lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16); if (ERROR_OK != retval) { LOG_ERROR("Could not read OOB from IRAM"); return retval; } /* Copy ECC from HW, generated while reading */ int ecc_count = nand->page_size == 2048 ? 8 : 2; static uint32_t hw_ecc[8]; /* max size */ retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4, ecc_count, (uint8_t *)hw_ecc); if (ERROR_OK != retval) { LOG_ERROR("Could not read hw generated ECC from IRAM"); return retval; } static uint8_t ecc[24]; slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count); /* Copy ECC from flash using correct layout */ static uint8_t fecc[24];/* max size */ const int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout; int i; for (i = 0; i < ecc_count * 3; i++) fecc[i] = foob[layout[i]]; /* Compare ECC and possibly correct data */ for (i = 0; i < ecc_count; i++) { retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3], &ecc[i * 3]); if (retval > 0) LOG_WARNING("error detected and corrected: %" PRIu32 "/%d", page, i); if (retval < 0) break; } if (i == ecc_count) retval = ERROR_OK; else { LOG_ERROR("uncorrectable error detected: %" PRIu32 "/%d", page, i); retval = ERROR_NAND_OPERATION_FAILED; } return retval; } static int lpc32xx_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval = ERROR_OK; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { LOG_ERROR("BUG: no LPC32xx NAND flash controller selected"); return ERROR_NAND_OPERATION_FAILED; } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { if (data_size > (uint32_t)nand->page_size) { LOG_ERROR("data size exceeds page size"); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } retval = lpc32xx_read_page_mlc(nand, page, data, data_size, oob, oob_size); } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { struct working_area *pworking_area; retval = target_alloc_working_area(target, nand->page_size + 0x200, &pworking_area); if (retval != ERROR_OK) { LOG_ERROR("Can't allocate working area in " "LPC internal RAM"); return ERROR_FLASH_OPERATION_FAILED; } retval = lpc32xx_read_page_slc(nand, pworking_area, page, data, data_size, oob, oob_size); target_free_working_area(target, pworking_area); } return retval; } static int lpc32xx_controller_ready(struct nand_device *nand, int timeout) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("lpc32xx_controller_ready count start=%d", timeout); do { if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { uint8_t status; /* Read MLC_ISR, wait for controller to become ready */ retval = target_read_u8(target, 0x200b8048, &status); if (ERROR_OK != retval) { LOG_ERROR("could not set MLC_STAT"); return ERROR_NAND_OPERATION_FAILED; } if (status & 2) { LOG_DEBUG("lpc32xx_controller_ready count=%d", timeout); return 1; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { uint32_t status; /* Read SLC_STAT and check READY bit */ retval = target_read_u32(target, 0x20020018, &status); if (ERROR_OK != retval) { LOG_ERROR("could not set SLC_STAT"); return ERROR_NAND_OPERATION_FAILED; } if (status & 1) { LOG_DEBUG("lpc32xx_controller_ready count=%d", timeout); return 1; } } alive_sleep(1); } while (timeout-- > 0); return 0; } static int lpc32xx_nand_ready(struct nand_device *nand, int timeout) { struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct target *target = nand->target; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use LPC32xx " "NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } LOG_DEBUG("lpc32xx_nand_ready count start=%d", timeout); do { if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { uint8_t status = 0x0; /* Read MLC_ISR, wait for NAND flash device to * become ready */ retval = target_read_u8(target, 0x200b8048, &status); if (ERROR_OK != retval) { LOG_ERROR("could not read MLC_ISR"); return ERROR_NAND_OPERATION_FAILED; } if (status & 1) { LOG_DEBUG("lpc32xx_nand_ready count end=%d", timeout); return 1; } } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { uint32_t status = 0x0; /* Read SLC_STAT and check READY bit */ retval = target_read_u32(target, 0x20020018, &status); if (ERROR_OK != retval) { LOG_ERROR("could not read SLC_STAT"); return ERROR_NAND_OPERATION_FAILED; } if (status & 1) { LOG_DEBUG("lpc32xx_nand_ready count end=%d", timeout); return 1; } } alive_sleep(1); } while (timeout-- > 0); return 0; } static int lpc32xx_tc_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; LOG_DEBUG("lpc32xx_tc_ready count start=%d", timeout); do { uint32_t status = 0x0; int retval; /* Read SLC_INT_STAT and check INT_TC_STAT bit */ retval = target_read_u32(target, 0x2002001c, &status); if (ERROR_OK != retval) { LOG_ERROR("Could not read SLC_INT_STAT"); return 0; } if (status & 2) { LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout); return 1; } alive_sleep(1); } while (timeout-- > 0); return 0; } COMMAND_HANDLER(handle_lpc32xx_select_command) { struct lpc32xx_nand_controller *lpc32xx_info = NULL; char *selected[] = { "no", "mlc", "slc" }; if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; unsigned num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]); return ERROR_OK; } lpc32xx_info = nand->controller_priv; if (CMD_ARGC >= 2) { if (strcmp(CMD_ARGV[1], "mlc") == 0) { lpc32xx_info->selected_controller = LPC32xx_MLC_CONTROLLER; } else if (strcmp(CMD_ARGV[1], "slc") == 0) { lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER; } else return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "%s controller selected", selected[lpc32xx_info->selected_controller]); return ERROR_OK; } static const struct command_registration lpc32xx_exec_command_handlers[] = { { .name = "select", .handler = handle_lpc32xx_select_command, .mode = COMMAND_EXEC, .help = "select MLC or SLC controller (default is MLC)", .usage = "bank_id ['mlc'|'slc' ]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration lpc32xx_command_handler[] = { { .name = "lpc32xx", .mode = COMMAND_ANY, .help = "LPC32xx NAND flash controller commands", .usage = "", .chain = lpc32xx_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct nand_flash_controller lpc32xx_nand_controller = { .name = "lpc32xx", .commands = lpc32xx_command_handler, .nand_device_command = lpc32xx_nand_device_command, .init = lpc32xx_init, .reset = lpc32xx_reset, .command = lpc32xx_command, .address = lpc32xx_address, .write_data = lpc32xx_write_data, .read_data = lpc32xx_read_data, .write_page = lpc32xx_write_page, .read_page = lpc32xx_read_page, .nand_ready = lpc32xx_nand_ready, }; openocd-0.9.0/src/flash/nand/lpc32xx.h0000644000175000017500000000352412315575360014363 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef LPC32xx_NAND_CONTROLLER_H #define LPC32xx_NAND_CONTROLLER_H enum lpc32xx_selected_controller { LPC32xx_NO_CONTROLLER, LPC32xx_MLC_CONTROLLER, LPC32xx_SLC_CONTROLLER, }; struct lpc32xx_nand_controller { int osc_freq; enum lpc32xx_selected_controller selected_controller; int sw_write_protection; uint32_t sw_wp_lower_bound; uint32_t sw_wp_upper_bound; }; #endif /*LPC32xx_NAND_CONTROLLER_H */ openocd-0.9.0/src/flash/nand/arm_io.c0000644000175000017500000002210412315575360014314 00000000000000/* * Copyright (C) 2009 by Marvell Semiconductors, Inc. * Written by Nicolas Pitre * * Copyright (C) 2009 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "core.h" #include "arm_io.h" #include #include #include #include /** * Copies code to a working area. This will allocate room for the code plus the * additional amount requested if the working area pointer is null. * * @param target Pointer to the target to copy code to * @param code Pointer to the code area to be copied * @param code_size Size of the code being copied * @param additional Size of the additional area to be allocated in addition to * code * @param area Pointer to a pointer to a working area to copy code to * @return Success or failure of the operation */ static int arm_code_to_working_area(struct target *target, const uint32_t *code, unsigned code_size, unsigned additional, struct working_area **area) { uint8_t code_buf[code_size]; int retval; unsigned size = code_size + additional; /* REVISIT this assumes size doesn't ever change. * That's usually correct; but there are boards with * both large and small page chips, where it won't be... */ /* make sure we have a working area */ if (NULL == *area) { retval = target_alloc_working_area(target, size, area); if (retval != ERROR_OK) { LOG_DEBUG("%s: no %d byte buffer", __func__, (int) size); return ERROR_NAND_NO_BUFFER; } } /* buffer code in target endianness */ target_buffer_set_u32_array(target, code_buf, code_size / 4, code); /* copy code to work area */ retval = target_write_memory(target, (*area)->address, 4, code_size / 4, code_buf); return retval; } /** * ARM-specific bulk write from buffer to address of 8-bit wide NAND. * For now this supports ARMv4,ARMv5 and ARMv7-M cores. * * Enhancements to target_run_algorithm() could enable: * - ARMv6 and ARMv7 cores in ARM mode * * Different code fragments could handle: * - 16-bit wide data (needs different setup) * * @param nand Pointer to the arm_nand_data struct that defines the I/O * @param data Pointer to the data to be copied to flash * @param size Size of the data being copied * @return Success or failure of the operation */ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) { struct target *target = nand->target; struct arm_algorithm armv4_5_algo; struct armv7m_algorithm armv7m_algo; void *arm_algo; struct arm *arm = target->arch_info; struct reg_param reg_params[3]; uint32_t target_buf; uint32_t exit_var = 0; int retval; /* Inputs: * r0 NAND data address (byte wide) * r1 buffer address * r2 buffer length */ static const uint32_t code_armv4_5[] = { 0xe4d13001, /* s: ldrb r3, [r1], #1 */ 0xe5c03000, /* strb r3, [r0] */ 0xe2522001, /* subs r2, r2, #1 */ 0x1afffffb, /* bne s */ /* exit: ARMv4 needs hardware breakpoint */ 0xe1200070, /* e: bkpt #0 */ }; /* Inputs: * r0 NAND data address (byte wide) * r1 buffer address * r2 buffer length * * see contrib/loaders/flash/armv7m_io.s for src */ static const uint32_t code_armv7m[] = { 0x3b01f811, 0x3a017003, 0xaffaf47f, 0xbf00be00, }; int target_code_size = 0; const uint32_t *target_code_src = NULL; /* set up algorithm */ if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */ armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; armv7m_algo.core_mode = ARM_MODE_THREAD; arm_algo = &armv7m_algo; target_code_size = sizeof(code_armv7m); target_code_src = code_armv7m; } else { armv4_5_algo.common_magic = ARM_COMMON_MAGIC; armv4_5_algo.core_mode = ARM_MODE_SVC; armv4_5_algo.core_state = ARM_STATE_ARM; arm_algo = &armv4_5_algo; target_code_size = sizeof(code_armv4_5); target_code_src = code_armv4_5; } if (nand->op != ARM_NAND_WRITE || !nand->copy_area) { retval = arm_code_to_working_area(target, target_code_src, target_code_size, nand->chunk_size, &nand->copy_area); if (retval != ERROR_OK) return retval; } nand->op = ARM_NAND_WRITE; /* copy data to work area */ target_buf = nand->copy_area->address + target_code_size; retval = target_write_buffer(target, target_buf, size, data); if (retval != ERROR_OK) return retval; /* set up parameters */ init_reg_param(®_params[0], "r0", 32, PARAM_IN); init_reg_param(®_params[1], "r1", 32, PARAM_IN); init_reg_param(®_params[2], "r2", 32, PARAM_IN); buf_set_u32(reg_params[0].value, 0, 32, nand->data); buf_set_u32(reg_params[1].value, 0, 32, target_buf); buf_set_u32(reg_params[2].value, 0, 32, size); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) exit_var = nand->copy_area->address + target_code_size - 4; /* use alg to write data from work area to NAND chip */ retval = target_run_algorithm(target, 0, NULL, 3, reg_params, nand->copy_area->address, exit_var, 1000, arm_algo); if (retval != ERROR_OK) LOG_ERROR("error executing hosted NAND write"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); return retval; } /** * Uses an on-chip algorithm for an ARM device to read from a NAND device and * store the data into the host machine's memory. * * @param nand Pointer to the arm_nand_data struct that defines the I/O * @param data Pointer to the data buffer to store the read data * @param size Amount of data to be stored to the buffer. * @return Success or failure of the operation */ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) { struct target *target = nand->target; struct arm_algorithm armv4_5_algo; struct armv7m_algorithm armv7m_algo; void *arm_algo; struct arm *arm = target->arch_info; struct reg_param reg_params[3]; uint32_t target_buf; uint32_t exit_var = 0; int retval; /* Inputs: * r0 buffer address * r1 NAND data address (byte wide) * r2 buffer length */ static const uint32_t code_armv4_5[] = { 0xe5d13000, /* s: ldrb r3, [r1] */ 0xe4c03001, /* strb r3, [r0], #1 */ 0xe2522001, /* subs r2, r2, #1 */ 0x1afffffb, /* bne s */ /* exit: ARMv4 needs hardware breakpoint */ 0xe1200070, /* e: bkpt #0 */ }; /* Inputs: * r0 buffer address * r1 NAND data address (byte wide) * r2 buffer length * * see contrib/loaders/flash/armv7m_io.s for src */ static const uint32_t code_armv7m[] = { 0xf800780b, 0x3a013b01, 0xaffaf47f, 0xbf00be00, }; int target_code_size = 0; const uint32_t *target_code_src = NULL; /* set up algorithm */ if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */ armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; armv7m_algo.core_mode = ARM_MODE_THREAD; arm_algo = &armv7m_algo; target_code_size = sizeof(code_armv7m); target_code_src = code_armv7m; } else { armv4_5_algo.common_magic = ARM_COMMON_MAGIC; armv4_5_algo.core_mode = ARM_MODE_SVC; armv4_5_algo.core_state = ARM_STATE_ARM; arm_algo = &armv4_5_algo; target_code_size = sizeof(code_armv4_5); target_code_src = code_armv4_5; } /* create the copy area if not yet available */ if (nand->op != ARM_NAND_READ || !nand->copy_area) { retval = arm_code_to_working_area(target, target_code_src, target_code_size, nand->chunk_size, &nand->copy_area); if (retval != ERROR_OK) return retval; } nand->op = ARM_NAND_READ; target_buf = nand->copy_area->address + target_code_size; /* set up parameters */ init_reg_param(®_params[0], "r0", 32, PARAM_IN); init_reg_param(®_params[1], "r1", 32, PARAM_IN); init_reg_param(®_params[2], "r2", 32, PARAM_IN); buf_set_u32(reg_params[0].value, 0, 32, target_buf); buf_set_u32(reg_params[1].value, 0, 32, nand->data); buf_set_u32(reg_params[2].value, 0, 32, size); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) exit_var = nand->copy_area->address + target_code_size - 4; /* use alg to write data from NAND chip to work area */ retval = target_run_algorithm(target, 0, NULL, 3, reg_params, nand->copy_area->address, exit_var, 1000, arm_algo); if (retval != ERROR_OK) LOG_ERROR("error executing hosted NAND read"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); /* read from work area to the host's memory */ retval = target_read_buffer(target, target_buf, size, data); return retval; } openocd-0.9.0/src/flash/nand/arm_io.h0000644000175000017500000000342012315575360014321 00000000000000/* * Copyright (C) 2009 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __ARM_NANDIO_H #define __ARM_NANDIO_H /** * Available operational states the arm_nand_data struct can be in. */ enum arm_nand_op { ARM_NAND_NONE, /**< No operation performed. */ ARM_NAND_READ, /**< Read operation performed. */ ARM_NAND_WRITE, /**< Write operation performed. */ }; /** * The arm_nand_data struct is used for defining NAND I/O operations on an ARM * core. */ struct arm_nand_data { /** Target is proxy for some ARM core. */ struct target *target; /** The copy area holds code loop and data for I/O operations. */ struct working_area *copy_area; /** The chunk size is the page size or ECC chunk. */ unsigned chunk_size; /** Where data is read from or written to. */ uint32_t data; /** Last operation executed using this struct. */ enum arm_nand_op op; /* currently implicit: data width == 8 bits (not 16) */ }; int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size); int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size); #endif /* __ARM_NANDIO_H */ openocd-0.9.0/src/flash/nand/nuc910.c0000644000175000017500000001433712315575360014076 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * NAND controller interface for Nuvoton NUC910 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "nuc910.h" #include "arm_io.h" #include struct nuc910_nand_controller { struct arm_nand_data io; }; static int validate_target_state(struct nand_device *nand) { struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } static int nuc910_nand_command(struct nand_device *nand, uint8_t command) { struct target *target = nand->target; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; target_write_u8(target, NUC910_SMCMD, command); return ERROR_OK; } static int nuc910_nand_address(struct nand_device *nand, uint8_t address) { struct target *target = nand->target; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA)); return ERROR_OK; } static int nuc910_nand_read(struct nand_device *nand, void *data) { struct target *target = nand->target; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; target_read_u8(target, NUC910_SMDATA, data); return ERROR_OK; } static int nuc910_nand_write(struct nand_device *nand, uint16_t data) { struct target *target = nand->target; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; target_write_u8(target, NUC910_SMDATA, data); return ERROR_OK; } static int nuc910_nand_read_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct nuc910_nand_controller *nuc910_nand = nand->controller_priv; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; nuc910_nand->io.chunk_size = nand->page_size; /* try the fast way first */ result = arm_nandread(&nuc910_nand->io, data, data_size); if (result != ERROR_NAND_NO_BUFFER) return result; /* else do it slowly */ while (data_size--) nuc910_nand_read(nand, data++); return ERROR_OK; } static int nuc910_nand_write_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct nuc910_nand_controller *nuc910_nand = nand->controller_priv; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; nuc910_nand->io.chunk_size = nand->page_size; /* try the fast way first */ result = arm_nandwrite(&nuc910_nand->io, data, data_size); if (result != ERROR_NAND_NO_BUFFER) return result; /* else do it slowly */ while (data_size--) nuc910_nand_write(nand, *data++); return ERROR_OK; } static int nuc910_nand_reset(struct nand_device *nand) { return nuc910_nand_command(nand, NAND_CMD_RESET); } static int nuc910_nand_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; uint32_t status; do { target_read_u32(target, NUC910_SMISR, &status); if (status & NUC910_SMISR_RB_) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; } NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command) { struct nuc910_nand_controller *nuc910_nand; nuc910_nand = calloc(1, sizeof(struct nuc910_nand_controller)); if (!nuc910_nand) { LOG_ERROR("no memory for nand controller"); return ERROR_NAND_DEVICE_INVALID; } nand->controller_priv = nuc910_nand; return ERROR_OK; } static int nuc910_nand_init(struct nand_device *nand) { struct nuc910_nand_controller *nuc910_nand = nand->controller_priv; struct target *target = nand->target; int bus_width = nand->bus_width ? : 8; int result; result = validate_target_state(nand); if (result != ERROR_OK) return result; /* nuc910 only supports 8bit */ if (bus_width != 8) { LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width); return ERROR_NAND_OPERATION_NOT_SUPPORTED; } /* inform calling code about selected bus width */ nand->bus_width = bus_width; nuc910_nand->io.target = target; nuc910_nand->io.data = NUC910_SMDATA; nuc910_nand->io.op = ARM_NAND_NONE; /* configure nand controller */ target_write_u32(target, NUC910_FMICSR, NUC910_FMICSR_SM_EN); target_write_u32(target, NUC910_SMCSR, 0x010000a8); /* 2048 page size */ target_write_u32(target, NUC910_SMTCR, 0x00010204); target_write_u32(target, NUC910_SMIER, 0x00000000); return ERROR_OK; } struct nand_flash_controller nuc910_nand_controller = { .name = "nuc910", .command = nuc910_nand_command, .address = nuc910_nand_address, .read_data = nuc910_nand_read, .write_data = nuc910_nand_write, .write_block_data = nuc910_nand_write_block_data, .read_block_data = nuc910_nand_read_block_data, .nand_ready = nuc910_nand_ready, .reset = nuc910_nand_reset, .nand_device_command = nuc910_nand_device_command, .init = nuc910_nand_init, }; openocd-0.9.0/src/flash/nand/nuc910.h0000644000175000017500000000462512315575360014102 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * NAND controller interface for Nuvoton NUC910 */ #ifndef NUC910_H #define NUC910_H #define NUC910_FMICSR 0xB000D000 #define NUC910_SMCSR 0xB000D0A0 #define NUC910_SMTCR 0xB000D0A4 #define NUC910_SMIER 0xB000D0A8 #define NUC910_SMISR 0xB000D0AC #define NUC910_SMCMD 0xB000D0B0 #define NUC910_SMADDR 0xB000D0B4 #define NUC910_SMDATA 0xB000D0B8 #define NUC910_SMECC0 0xB000D0BC #define NUC910_SMECC1 0xB000D0C0 #define NUC910_SMECC2 0xB000D0C4 #define NUC910_SMECC3 0xB000D0C8 #define NUC910_ECC4ST 0xB000D114 /* Global Control and Status Register (FMICSR) */ #define NUC910_FMICSR_SM_EN (1<<3) /* NAND Flash Address Port Register (SMADDR) */ #define NUC910_SMADDR_EOA (1<<31) /* NAND Flash Control and Status Register (SMCSR) */ #define NUC910_SMCSR_PSIZE (1<<3) #define NUC910_SMCSR_DBW (1<<4) /* NAND Flash Interrupt Status Register (SMISR) */ #define NUC910_SMISR_ECC_IF (1<<2) #define NUC910_SMISR_RB_ (1<<18) /* ECC4 Correction Status (ECC4ST) */ #endif /* NUC910_H */ openocd-0.9.0/src/flash/nand/ecc_kw.c0000644000175000017500000001060712315575360014306 00000000000000/* * Reed-Solomon ECC handling for the Marvell Kirkwood SOC * Copyright (C) 2009 Marvell Semiconductor, Inc. * * Authors: Lennert Buytenhek * Nicolas Pitre * * This 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 2 or (at your option) any * later version. * * This 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "core.h" /***************************************************************************** * Arithmetic in GF(2^10) ("F") modulo x^10 + x^3 + 1. * * For multiplication, a discrete log/exponent table is used, with * primitive element x (F is a primitive field, so x is primitive). */ #define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */ /* * Maps an integer a [0..1022] to a polynomial b = gf_exp[a] in * GF(2^10) mod x^10 + x^3 + 1 such that b = x ^ a. There's two * identical copies of this array back-to-back so that we can save * the mod 1023 operation when doing a GF multiplication. */ static uint16_t gf_exp[1023 + 1023]; /* * Maps a polynomial b in GF(2^10) mod x^10 + x^3 + 1 to an index * a = gf_log[b] in [0..1022] such that b = x ^ a. */ static uint16_t gf_log[1024]; static void gf_build_log_exp_table(void) { int i; int p_i; /* * p_i = x ^ i * * Initialise to 1 for i = 0. */ p_i = 1; for (i = 0; i < 1023; i++) { gf_exp[i] = p_i; gf_exp[i + 1023] = p_i; gf_log[p_i] = i; /* * p_i = p_i * x */ p_i <<= 1; if (p_i & (1 << 10)) p_i ^= MODPOLY; } } /***************************************************************************** * Reed-Solomon code * * This implements a (1023,1015) Reed-Solomon ECC code over GF(2^10) * mod x^10 + x^3 + 1, shortened to (520,512). The ECC data consists * of 8 10-bit symbols, or 10 8-bit bytes. * * Given 512 bytes of data, computes 10 bytes of ECC. * * This is done by converting the 512 bytes to 512 10-bit symbols * (elements of F), interpreting those symbols as a polynomial in F[X] * by taking symbol 0 as the coefficient of X^8 and symbol 511 as the * coefficient of X^519, and calculating the residue of that polynomial * divided by the generator polynomial, which gives us the 8 ECC symbols * as the remainder. Finally, we convert the 8 10-bit ECC symbols to 10 * 8-bit bytes. * * The generator polynomial is hardcoded, as that is faster, but it * can be computed by taking the primitive element a = x (in F), and * constructing a polynomial in F[X] with roots a, a^2, a^3, ..., a^8 * by multiplying the minimal polynomials for those roots (which are * just 'x - a^i' for each i). * * Note: due to unfortunate circumstances, the bootrom in the Kirkwood SOC * expects the ECC to be computed backward, i.e. from the last byte down * to the first one. */ int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t *ecc) { unsigned int r7, r6, r5, r4, r3, r2, r1, r0; int i; static int tables_initialized; if (!tables_initialized) { gf_build_log_exp_table(); tables_initialized = 1; } /* * Load bytes 504..511 of the data into r. */ r0 = data[504]; r1 = data[505]; r2 = data[506]; r3 = data[507]; r4 = data[508]; r5 = data[509]; r6 = data[510]; r7 = data[511]; /* * Shift bytes 503..0 (in that order) into r0, followed * by eight zero bytes, while reducing the polynomial by the * generator polynomial in every step. */ for (i = 503; i >= -8; i--) { unsigned int d; d = 0; if (i >= 0) d = data[i]; if (r7) { uint16_t *t = gf_exp + gf_log[r7]; r7 = r6 ^ t[0x21c]; r6 = r5 ^ t[0x181]; r5 = r4 ^ t[0x18e]; r4 = r3 ^ t[0x25f]; r3 = r2 ^ t[0x197]; r2 = r1 ^ t[0x193]; r1 = r0 ^ t[0x237]; r0 = d ^ t[0x024]; } else { r7 = r6; r6 = r5; r5 = r4; r4 = r3; r3 = r2; r2 = r1; r1 = r0; r0 = d; } } ecc[0] = r0; ecc[1] = (r0 >> 8) | (r1 << 2); ecc[2] = (r1 >> 6) | (r2 << 4); ecc[3] = (r2 >> 4) | (r3 << 6); ecc[4] = (r3 >> 2); ecc[5] = r4; ecc[6] = (r4 >> 8) | (r5 << 2); ecc[7] = (r5 >> 6) | (r6 << 4); ecc[8] = (r6 >> 4) | (r7 << 6); ecc[9] = (r7 >> 2); return 0; } openocd-0.9.0/src/flash/nand/orion.c0000644000175000017500000001106712315575360014202 00000000000000/*************************************************************************** * Copyright (C) 2009 by Marvell Semiconductors, Inc. * * Written by Nicolas Pitre * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * NAND controller interface for Marvell Orion/Kirkwood SoCs. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "imp.h" #include "arm_io.h" #include struct orion_nand_controller { struct arm_nand_data io; uint32_t cmd; uint32_t addr; uint32_t data; }; #define CHECK_HALTED \ do { \ if (target->state != TARGET_HALTED) { \ LOG_ERROR("NAND flash access requires halted target"); \ return ERROR_NAND_OPERATION_FAILED; \ } \ } while (0) static int orion_nand_command(struct nand_device *nand, uint8_t command) { struct orion_nand_controller *hw = nand->controller_priv; struct target *target = nand->target; CHECK_HALTED; target_write_u8(target, hw->cmd, command); return ERROR_OK; } static int orion_nand_address(struct nand_device *nand, uint8_t address) { struct orion_nand_controller *hw = nand->controller_priv; struct target *target = nand->target; CHECK_HALTED; target_write_u8(target, hw->addr, address); return ERROR_OK; } static int orion_nand_read(struct nand_device *nand, void *data) { struct orion_nand_controller *hw = nand->controller_priv; struct target *target = nand->target; CHECK_HALTED; target_read_u8(target, hw->data, data); return ERROR_OK; } static int orion_nand_write(struct nand_device *nand, uint16_t data) { struct orion_nand_controller *hw = nand->controller_priv; struct target *target = nand->target; CHECK_HALTED; target_write_u8(target, hw->data, data); return ERROR_OK; } static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size) { while (size--) orion_nand_write(nand, *data++); return ERROR_OK; } static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size) { struct orion_nand_controller *hw = nand->controller_priv; int retval; hw->io.chunk_size = nand->page_size; retval = arm_nandwrite(&hw->io, data, size); if (retval == ERROR_NAND_NO_BUFFER) retval = orion_nand_slow_block_write(nand, data, size); return retval; } static int orion_nand_reset(struct nand_device *nand) { return orion_nand_command(nand, NAND_CMD_RESET); } NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command) { struct orion_nand_controller *hw; uint32_t base; uint8_t ale, cle; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; hw = calloc(1, sizeof(*hw)); if (!hw) { LOG_ERROR("no memory for nand controller"); return ERROR_NAND_DEVICE_INVALID; } nand->controller_priv = hw; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base); cle = 0; ale = 1; hw->data = base; hw->cmd = base + (1 << cle); hw->addr = base + (1 << ale); hw->io.target = nand->target; hw->io.data = hw->data; hw->io.op = ARM_NAND_NONE; return ERROR_OK; } static int orion_nand_init(struct nand_device *nand) { return ERROR_OK; } struct nand_flash_controller orion_nand_controller = { .name = "orion", .usage = " ", .command = orion_nand_command, .address = orion_nand_address, .read_data = orion_nand_read, .write_data = orion_nand_write, .write_block_data = orion_nand_fast_block_write, .reset = orion_nand_reset, .nand_device_command = orion_nand_device_command, .init = orion_nand_init, }; openocd-0.9.0/src/flash/nand/s3c2410.c0000644000175000017500000000733312315575360014054 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C2410 OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" NAND_DEVICE_COMMAND_HANDLER(s3c2410_nand_device_command) { struct s3c24xx_nand_controller *info; CALL_S3C24XX_DEVICE_COMMAND(nand, &info); /* fill in the address fields for the core device */ info->cmd = S3C2410_NFCMD; info->addr = S3C2410_NFADDR; info->data = S3C2410_NFDATA; info->nfstat = S3C2410_NFSTAT; return ERROR_OK; } static int s3c2410_init(struct nand_device *nand) { struct target *target = nand->target; target_write_u32(target, S3C2410_NFCONF, S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) | S3C2410_NFCONF_TWRPH0(5) | S3C2410_NFCONF_TWRPH1(3)); return ERROR_OK; } static int s3c2410_write_data(struct nand_device *nand, uint16_t data) { struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u32(target, S3C2410_NFDATA, data); return ERROR_OK; } static int s3c2410_read_data(struct nand_device *nand, void *data) { struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_read_u8(target, S3C2410_NFDATA, data); return ERROR_OK; } static int s3c2410_nand_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; uint8_t status; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } do { target_read_u8(target, S3C2410_NFSTAT, &status); if (status & S3C2410_NFSTAT_BUSY) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; } struct nand_flash_controller s3c2410_nand_controller = { .name = "s3c2410", .nand_device_command = &s3c2410_nand_device_command, .init = &s3c2410_init, .reset = &s3c24xx_reset, .command = &s3c24xx_command, .address = &s3c24xx_address, .write_data = &s3c2410_write_data, .read_data = &s3c2410_read_data, .write_page = s3c24xx_write_page, .read_page = s3c24xx_read_page, .nand_ready = &s3c2410_nand_ready, }; openocd-0.9.0/src/flash/nand/s3c2412.c0000644000175000017500000000546012315575360014055 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C2412 OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" NAND_DEVICE_COMMAND_HANDLER(s3c2412_nand_device_command) { struct s3c24xx_nand_controller *info; CALL_S3C24XX_DEVICE_COMMAND(nand, &info); /* fill in the address fields for the core device */ info->cmd = S3C2440_NFCMD; info->addr = S3C2440_NFADDR; info->data = S3C2440_NFDATA; info->nfstat = S3C2412_NFSTAT; return ERROR_OK; } static int s3c2412_init(struct nand_device *nand) { struct target *target = nand->target; target_write_u32(target, S3C2410_NFCONF, S3C2440_NFCONF_TACLS(3) | S3C2440_NFCONF_TWRPH0(7) | S3C2440_NFCONF_TWRPH1(7)); target_write_u32(target, S3C2440_NFCONT, S3C2412_NFCONT_INIT_MAIN_ECC | S3C2440_NFCONT_ENABLE); return ERROR_OK; } struct nand_flash_controller s3c2412_nand_controller = { .name = "s3c2412", .nand_device_command = &s3c2412_nand_device_command, .init = &s3c2412_init, .reset = &s3c24xx_reset, .command = &s3c24xx_command, .address = &s3c24xx_address, .write_data = &s3c24xx_write_data, .read_data = &s3c24xx_read_data, .write_page = s3c24xx_write_page, .read_page = s3c24xx_read_page, .write_block_data = &s3c2440_write_block_data, .read_block_data = &s3c2440_read_block_data, .nand_ready = &s3c2440_nand_ready, }; openocd-0.9.0/src/flash/nand/s3c2440.c0000644000175000017500000001146012315575360014053 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C2440 OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command) { struct s3c24xx_nand_controller *info; CALL_S3C24XX_DEVICE_COMMAND(nand, &info); /* fill in the address fields for the core device */ info->cmd = S3C2440_NFCMD; info->addr = S3C2440_NFADDR; info->data = S3C2440_NFDATA; info->nfstat = S3C2440_NFSTAT; return ERROR_OK; } static int s3c2440_init(struct nand_device *nand) { struct target *target = nand->target; target_write_u32(target, S3C2410_NFCONF, S3C2440_NFCONF_TACLS(3) | S3C2440_NFCONF_TWRPH0(7) | S3C2440_NFCONF_TWRPH1(7)); target_write_u32(target, S3C2440_NFCONT, S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE); return ERROR_OK; } int s3c2440_nand_ready(struct nand_device *nand, int timeout) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; uint8_t status; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } do { target_read_u8(target, s3c24xx_info->nfstat, &status); if (status & S3C2440_NFSTAT_READY) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; } /* use the fact we can read/write 4 bytes in one go via a single 32bit op */ int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; uint32_t nfdata = s3c24xx_info->data; uint32_t tmp; LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size); if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } while (data_size >= 4) { target_read_u32(target, nfdata, &tmp); data[0] = tmp; data[1] = tmp >> 8; data[2] = tmp >> 16; data[3] = tmp >> 24; data_size -= 4; data += 4; } while (data_size > 0) { target_read_u8(target, nfdata, data); data_size -= 1; data += 1; } return ERROR_OK; } int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; uint32_t nfdata = s3c24xx_info->data; uint32_t tmp; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } while (data_size >= 4) { tmp = le_to_h_u32(data); target_write_u32(target, nfdata, tmp); data_size -= 4; data += 4; } while (data_size > 0) { target_write_u8(target, nfdata, *data); data_size -= 1; data += 1; } return ERROR_OK; } struct nand_flash_controller s3c2440_nand_controller = { .name = "s3c2440", .nand_device_command = &s3c2440_nand_device_command, .init = &s3c2440_init, .reset = &s3c24xx_reset, .command = &s3c24xx_command, .address = &s3c24xx_address, .write_data = &s3c24xx_write_data, .read_data = &s3c24xx_read_data, .write_page = s3c24xx_write_page, .read_page = s3c24xx_read_page, .write_block_data = &s3c2440_write_block_data, .read_block_data = &s3c2440_read_block_data, .nand_ready = &s3c2440_nand_ready, }; openocd-0.9.0/src/flash/nand/s3c2443.c0000644000175000017500000000546012315575360014061 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C2443 OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command) { struct s3c24xx_nand_controller *info; CALL_S3C24XX_DEVICE_COMMAND(nand, &info); /* fill in the address fields for the core device */ info->cmd = S3C2440_NFCMD; info->addr = S3C2440_NFADDR; info->data = S3C2440_NFDATA; info->nfstat = S3C2412_NFSTAT; return ERROR_OK; } static int s3c2443_init(struct nand_device *nand) { struct target *target = nand->target; target_write_u32(target, S3C2410_NFCONF, S3C2440_NFCONF_TACLS(3) | S3C2440_NFCONF_TWRPH0(7) | S3C2440_NFCONF_TWRPH1(7)); target_write_u32(target, S3C2440_NFCONT, S3C2412_NFCONT_INIT_MAIN_ECC | S3C2440_NFCONT_ENABLE); return ERROR_OK; } struct nand_flash_controller s3c2443_nand_controller = { .name = "s3c2443", .nand_device_command = &s3c2443_nand_device_command, .init = &s3c2443_init, .reset = &s3c24xx_reset, .command = &s3c24xx_command, .address = &s3c24xx_address, .write_data = &s3c24xx_write_data, .read_data = &s3c24xx_read_data, .write_page = s3c24xx_write_page, .read_page = s3c24xx_read_page, .write_block_data = &s3c2440_write_block_data, .read_block_data = &s3c2440_read_block_data, .nand_ready = &s3c2440_nand_ready, }; openocd-0.9.0/src/flash/nand/s3c24xx.c0000644000175000017500000000765412315575360014301 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * S3C24XX Series OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" S3C24XX_DEVICE_COMMAND() { *info = NULL; struct s3c24xx_nand_controller *s3c24xx_info; s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller)); if (s3c24xx_info == NULL) { LOG_ERROR("no memory for nand controller"); return -ENOMEM; } nand->controller_priv = s3c24xx_info; *info = s3c24xx_info; return ERROR_OK; } int s3c24xx_reset(struct nand_device *nand) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u32(target, s3c24xx_info->cmd, 0xff); return ERROR_OK; } int s3c24xx_command(struct nand_device *nand, uint8_t command) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u16(target, s3c24xx_info->cmd, command); return ERROR_OK; } int s3c24xx_address(struct nand_device *nand, uint8_t address) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u16(target, s3c24xx_info->addr, address); return ERROR_OK; } int s3c24xx_write_data(struct nand_device *nand, uint16_t data) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u8(target, s3c24xx_info->data, data); return ERROR_OK; } int s3c24xx_read_data(struct nand_device *nand, void *data) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_read_u8(target, s3c24xx_info->data, data); return ERROR_OK; } openocd-0.9.0/src/flash/nand/s3c24xx.h0000644000175000017500000000574212315575360014302 00000000000000/*************************************************************************** * Copyright (C) 2007, 2008 by Ben Dooks * * ben@fluff.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef S3C24xx_NAND_H #define S3C24xx_NAND_H /* * S3C24XX Series OpenOCD NAND Flash controller support. * * Many thanks to Simtec Electronics for sponsoring this work. */ #include "imp.h" #include "s3c24xx_regs.h" #include struct s3c24xx_nand_controller { /* register addresses */ uint32_t cmd; uint32_t addr; uint32_t data; uint32_t nfstat; }; /* Default to using the un-translated NAND register based address */ #undef S3C2410_NFREG #define S3C2410_NFREG(x) ((x) + 0x4e000000) #define S3C24XX_DEVICE_COMMAND() \ COMMAND_HELPER(s3c24xx_nand_device_command, \ struct nand_device *nand, \ struct s3c24xx_nand_controller **info) S3C24XX_DEVICE_COMMAND(); #define CALL_S3C24XX_DEVICE_COMMAND(d, i) \ do { \ int retval = CALL_COMMAND_HANDLER(s3c24xx_nand_device_command, d, i); \ if (ERROR_OK != retval) \ return retval; \ } while (0) int s3c24xx_reset(struct nand_device *nand); int s3c24xx_command(struct nand_device *nand, uint8_t command); int s3c24xx_address(struct nand_device *nand, uint8_t address); int s3c24xx_write_data(struct nand_device *nand, uint16_t data); int s3c24xx_read_data(struct nand_device *nand, void *data); #define s3c24xx_write_page NULL #define s3c24xx_read_page NULL /* code shared between different controllers */ int s3c2440_nand_ready(struct nand_device *nand, int timeout); int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size); int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size); #endif /* S3C24xx_NAND_H */ openocd-0.9.0/src/flash/nand/s3c6400.c0000644000175000017500000000550312315575360014054 00000000000000/*************************************************************************** * Copyright (C) 2010 by Peter Korsgaard * * Heavily based on s3c2412.c by Ben Dooks * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "s3c24xx.h" /* s3c64xx uses another base address for the nand controller than 24xx */ #undef S3C2410_NFREG #define S3C2410_NFREG(x) ((x) + 0x70200000) NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command) { struct s3c24xx_nand_controller *info; CALL_S3C24XX_DEVICE_COMMAND(nand, &info); /* fill in the address fields for the core device */ info->cmd = S3C2440_NFCMD; info->addr = S3C2440_NFADDR; info->data = S3C2440_NFDATA; info->nfstat = S3C2412_NFSTAT; return ERROR_OK; } static int s3c6400_init(struct nand_device *nand) { struct target *target = nand->target; target_write_u32(target, S3C2410_NFCONF, S3C2440_NFCONF_TACLS(3) | S3C2440_NFCONF_TWRPH0(7) | S3C2440_NFCONF_TWRPH1(7) | 4); target_write_u32(target, S3C2440_NFCONT, S3C2412_NFCONT_INIT_MAIN_ECC | S3C2440_NFCONT_ENABLE); return ERROR_OK; } struct nand_flash_controller s3c6400_nand_controller = { .name = "s3c6400", .nand_device_command = &s3c6400_nand_device_command, .init = &s3c6400_init, .reset = &s3c24xx_reset, .command = &s3c24xx_command, .address = &s3c24xx_address, .write_data = &s3c24xx_write_data, .read_data = &s3c24xx_read_data, .write_page = s3c24xx_write_page, .read_page = s3c24xx_read_page, .write_block_data = &s3c2440_write_block_data, .read_block_data = &s3c2440_read_block_data, .nand_ready = &s3c2440_nand_ready, }; openocd-0.9.0/src/flash/mflash.c0000644000175000017500000011226312315575360013406 00000000000000/*************************************************************************** * Copyright (C) 2007-2008 by unsik Kim * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mflash.h" #include #include #include #include static int s3c2440_set_gpio_to_output(struct mflash_gpio_num gpio); static int s3c2440_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val); static int pxa270_set_gpio_to_output(struct mflash_gpio_num gpio); static int pxa270_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val); static struct mflash_bank *mflash_bank; static struct mflash_gpio_drv pxa270_gpio = { .name = "pxa270", .set_gpio_to_output = pxa270_set_gpio_to_output, .set_gpio_output_val = pxa270_set_gpio_output_val }; static struct mflash_gpio_drv s3c2440_gpio = { .name = "s3c2440", .set_gpio_to_output = s3c2440_set_gpio_to_output, .set_gpio_output_val = s3c2440_set_gpio_output_val }; static struct mflash_gpio_drv *mflash_gpio[] = { &pxa270_gpio, &s3c2440_gpio, NULL }; #define PXA270_GAFR0_L 0x40E00054 #define PXA270_GAFR3_U 0x40E00070 #define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u #define PXA270_GPDR0 0x40E0000C #define PXA270_GPDR3 0x40E0010C #define PXA270_GPDR3_RESERVED_BITS 0xfe000000u #define PXA270_GPSR0 0x40E00018 #define PXA270_GPCR0 0x40E00024 static int pxa270_set_gpio_to_output(struct mflash_gpio_num gpio) { uint32_t addr, value, mask; struct target *target = mflash_bank->target; int ret; /* remove alternate function. */ mask = 0x3u << (gpio.num & 0xF)*2; addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4; ret = target_read_u32(target, addr, &value); if (ret != ERROR_OK) return ret; value &= ~mask; if (addr == PXA270_GAFR3_U) value &= ~PXA270_GAFR3_U_RESERVED_BITS; ret = target_write_u32(target, addr, value); if (ret != ERROR_OK) return ret; /* set direction to output */ mask = 0x1u << (gpio.num & 0x1F); addr = PXA270_GPDR0 + (gpio.num >> 5) * 4; ret = target_read_u32(target, addr, &value); if (ret != ERROR_OK) return ret; value |= mask; if (addr == PXA270_GPDR3) value &= ~PXA270_GPDR3_RESERVED_BITS; ret = target_write_u32(target, addr, value); return ret; } static int pxa270_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val) { uint32_t addr, value, mask; struct target *target = mflash_bank->target; int ret; mask = 0x1u << (gpio.num & 0x1F); if (val) addr = PXA270_GPSR0 + (gpio.num >> 5) * 4; else addr = PXA270_GPCR0 + (gpio.num >> 5) * 4; ret = target_read_u32(target, addr, &value); if (ret != ERROR_OK) return ret; value |= mask; ret = target_write_u32(target, addr, value); return ret; } #define S3C2440_GPACON 0x56000000 #define S3C2440_GPADAT 0x56000004 #define S3C2440_GPJCON 0x560000d0 #define S3C2440_GPJDAT 0x560000d4 static int s3c2440_set_gpio_to_output(struct mflash_gpio_num gpio) { uint32_t data, mask, gpio_con; struct target *target = mflash_bank->target; int ret; if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10; else if (gpio.port[0] == 'j') gpio_con = S3C2440_GPJCON; else { LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port); return ERROR_COMMAND_SYNTAX_ERROR; } ret = target_read_u32(target, gpio_con, &data); if (ret == ERROR_OK) { if (gpio.port[0] == 'a') { mask = 1 << gpio.num; data &= ~mask; } else { mask = 3 << gpio.num * 2; data &= ~mask; data |= (1 << gpio.num * 2); } ret = target_write_u32(target, gpio_con, data); } return ret; } static int s3c2440_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val) { uint32_t data, mask, gpio_dat; struct target *target = mflash_bank->target; int ret; if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10; else if (gpio.port[0] == 'j') gpio_dat = S3C2440_GPJDAT; else { LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port); return ERROR_COMMAND_SYNTAX_ERROR; } ret = target_read_u32(target, gpio_dat, &data); if (ret == ERROR_OK) { mask = 1 << gpio.num; if (val) data |= mask; else data &= ~mask; ret = target_write_u32(target, gpio_dat, data); } return ret; } static int mg_hdrst(uint8_t level) { return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level); } static int mg_init_gpio(void) { int ret; struct mflash_gpio_drv *gpio_drv = mflash_bank->gpio_drv; ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin); if (ret != ERROR_OK) return ret; ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1); return ret; } static int mg_dsk_wait(mg_io_type_wait wait_local, uint32_t time_var) { uint8_t status, error; struct target *target = mflash_bank->target; uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET; int ret; long long t = 0; struct duration bench; duration_start(&bench); while (time_var) { ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status); if (ret != ERROR_OK) return ret; if (status & mg_io_rbit_status_busy) { if (wait_local == mg_io_wait_bsy) return ERROR_OK; } else { switch (wait_local) { case mg_io_wait_not_bsy: return ERROR_OK; case mg_io_wait_rdy_noerr: if (status & mg_io_rbit_status_ready) return ERROR_OK; break; case mg_io_wait_drq_noerr: if (status & mg_io_rbit_status_data_req) return ERROR_OK; break; default: break; } /* Now we check the error condition! */ if (status & mg_io_rbit_status_error) { ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error); if (ret != ERROR_OK) return ret; LOG_ERROR("mflash: io error 0x%02x", error); return ERROR_MG_IO; } switch (wait_local) { case mg_io_wait_rdy: if (status & mg_io_rbit_status_ready) return ERROR_OK; case mg_io_wait_drq: if (status & mg_io_rbit_status_data_req) return ERROR_OK; default: break; } } ret = duration_measure(&bench); if (ERROR_OK == ret) t = duration_elapsed(&bench) * 1000.0; else LOG_ERROR("mflash: duration measurement failed: %d", ret); if (t > time_var) break; } LOG_ERROR("mflash: timeout occured"); return ERROR_MG_TIMEOUT; } static int mg_dsk_srst(uint8_t on) { struct target *target = mflash_bank->target; uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET; uint8_t value; int ret; ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value); if (ret != ERROR_OK) return ret; if (on) value |= (mg_io_rbit_devc_srst); else value &= ~mg_io_rbit_devc_srst; ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value); return ret; } static int mg_dsk_io_cmd(uint32_t sect_num, uint32_t cnt, uint8_t cmd) { struct target *target = mflash_bank->target; uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET; uint8_t value; int ret; ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL); if (ret != ERROR_OK) return ret; value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode | ((sect_num >> 24) & 0xf); ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value); ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (uint8_t)cnt); ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (uint8_t)sect_num); ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (uint8_t)(sect_num >> 8)); ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (uint8_t)(sect_num >> 16)); if (ret != ERROR_OK) return ret; return target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd); } static int mg_dsk_drv_info(void) { struct target *target = mflash_bank->target; uint32_t mg_buff = mflash_bank->base + MG_BUFFER_OFFSET; int ret; ret = mg_dsk_io_cmd(0, 1, mg_io_cmd_identify); if (ret != ERROR_OK) return ret; ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: read drive info"); if (!mflash_bank->drv_info) mflash_bank->drv_info = malloc(sizeof(struct mg_drv_info)); ret = target_read_memory(target, mg_buff, 2, sizeof(mg_io_type_drv_info) >> 1, (uint8_t *)&mflash_bank->drv_info->drv_id); if (ret != ERROR_OK) return ret; mflash_bank->drv_info->tot_sects = (uint32_t)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16) + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo; return target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read); } static int mg_mflash_rst(void) { int ret; ret = mg_init_gpio(); if (ret != ERROR_OK) return ret; ret = mg_hdrst(0); if (ret != ERROR_OK) return ret; ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG); if (ret != ERROR_OK) return ret; ret = mg_hdrst(1); if (ret != ERROR_OK) return ret; ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG); if (ret != ERROR_OK) return ret; ret = mg_dsk_srst(1); if (ret != ERROR_OK) return ret; ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG); if (ret != ERROR_OK) return ret; ret = mg_dsk_srst(0); if (ret != ERROR_OK) return ret; ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: reset ok"); return ERROR_OK; } static int mg_mflash_probe(void) { int ret = mg_mflash_rst(); if (ret != ERROR_OK) return ret; return mg_dsk_drv_info(); } COMMAND_HANDLER(mg_probe_cmd) { int ret; ret = mg_mflash_probe(); if (ret == ERROR_OK) { command_print(CMD_CTX, "mflash (total %" PRIu32 " sectors) found at 0x%8.8" PRIx32 "", mflash_bank->drv_info->tot_sects, mflash_bank->base); } return ret; } static int mg_mflash_do_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt) { uint32_t i, address; int ret; struct target *target = mflash_bank->target; uint8_t *buff_ptr = buff; ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read); if (ret != ERROR_OK) return ret; address = mflash_bank->base + MG_BUFFER_OFFSET; struct duration bench; duration_start(&bench); for (i = 0; i < sect_cnt; i++) { ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL); if (ret != ERROR_OK) return ret; ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr); if (ret != ERROR_OK) return ret; buff_ptr += MG_MFLASH_SECTOR_SIZE; ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read); if (ret != ERROR_OK) return ret; LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector read", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE); ret = duration_measure(&bench); if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) { LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i); duration_start(&bench); } } return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL); } static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt) { uint32_t quotient, residue, i; uint8_t *buff_ptr = buff; int ret = ERROR_OK; quotient = sect_cnt >> 8; residue = sect_cnt % 256; for (i = 0; i < quotient; i++) { LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num, buff_ptr); ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256); if (ret != ERROR_OK) return ret; sect_num += 256; buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE; } if (residue) { LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p", sect_num, buff_ptr); return mg_mflash_do_read_sects(buff_ptr, sect_num, residue); } return ret; } static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt, uint8_t cmd) { uint32_t i, address; int ret; struct target *target = mflash_bank->target; uint8_t *buff_ptr = buff; ret = mg_dsk_io_cmd(sect_num, sect_cnt, cmd); if (ret != ERROR_OK) return ret; address = mflash_bank->base + MG_BUFFER_OFFSET; struct duration bench; duration_start(&bench); for (i = 0; i < sect_cnt; i++) { ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL); if (ret != ERROR_OK) return ret; ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr); if (ret != ERROR_OK) return ret; buff_ptr += MG_MFLASH_SECTOR_SIZE; ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write); if (ret != ERROR_OK) return ret; LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE); ret = duration_measure(&bench); if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) { LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i); duration_start(&bench); } } if (cmd == mg_io_cmd_write) ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL); else ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_LONG); return ret; } static int mg_mflash_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt) { uint32_t quotient, residue, i; uint8_t *buff_ptr = buff; int ret = ERROR_OK; quotient = sect_cnt >> 8; residue = sect_cnt % 256; for (i = 0; i < quotient; i++) { LOG_DEBUG("mflash: sect num : %" PRIu32 "buff : %p", sect_num, buff_ptr); ret = mg_mflash_do_write_sects(buff_ptr, sect_num, 256, mg_io_cmd_write); if (ret != ERROR_OK) return ret; sect_num += 256; buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE; } if (residue) { LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num, buff_ptr); return mg_mflash_do_write_sects(buff_ptr, sect_num, residue, mg_io_cmd_write); } return ret; } static int mg_mflash_read(uint32_t addr, uint8_t *buff, uint32_t len) { uint8_t *buff_ptr = buff; uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE]; uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num; int ret = ERROR_OK; cnt = 0; cur_addr = addr; end_addr = addr + len; if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) { next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK; sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; ret = mg_mflash_read_sects(sect_buff, sect_num, 1); if (ret != ERROR_OK) return ret; if (end_addr < next_sec_addr) { memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), end_addr - cur_addr); LOG_DEBUG( "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr); cur_addr = end_addr; } else { memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), next_sec_addr - cur_addr); LOG_DEBUG( "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr); buff_ptr += (next_sec_addr - cur_addr); cur_addr = next_sec_addr; } } if (cur_addr < end_addr) { sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE; while (next_sec_addr <= end_addr) { cnt++; next_sec_addr += MG_MFLASH_SECTOR_SIZE; } if (cnt) { ret = mg_mflash_read_sects(buff_ptr, sect_num, cnt); if (ret != ERROR_OK) return ret; } buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE; cur_addr += cnt * MG_MFLASH_SECTOR_SIZE; if (cur_addr < end_addr) { sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; ret = mg_mflash_read_sects(sect_buff, sect_num, 1); if (ret != ERROR_OK) return ret; memcpy(buff_ptr, sect_buff, end_addr - cur_addr); LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr - cur_addr)); } } return ret; } static int mg_mflash_write(uint32_t addr, uint8_t *buff, uint32_t len) { uint8_t *buff_ptr = buff; uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE]; uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num; int ret = ERROR_OK; cnt = 0; cur_addr = addr; end_addr = addr + len; if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) { next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK; sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; ret = mg_mflash_read_sects(sect_buff, sect_num, 1); if (ret != ERROR_OK) return ret; if (end_addr < next_sec_addr) { memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, end_addr - cur_addr); LOG_DEBUG( "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr); cur_addr = end_addr; } else { memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, next_sec_addr - cur_addr); LOG_DEBUG( "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr); buff_ptr += (next_sec_addr - cur_addr); cur_addr = next_sec_addr; } ret = mg_mflash_write_sects(sect_buff, sect_num, 1); if (ret != ERROR_OK) return ret; } if (cur_addr < end_addr) { sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE; while (next_sec_addr <= end_addr) { cnt++; next_sec_addr += MG_MFLASH_SECTOR_SIZE; } if (cnt) { ret = mg_mflash_write_sects(buff_ptr, sect_num, cnt); if (ret != ERROR_OK) return ret; } buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE; cur_addr += cnt * MG_MFLASH_SECTOR_SIZE; if (cur_addr < end_addr) { sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT; ret = mg_mflash_read_sects(sect_buff, sect_num, 1); if (ret != ERROR_OK) return ret; memcpy(sect_buff, buff_ptr, end_addr - cur_addr); LOG_DEBUG("mflash: copies %" PRIu32 " byte", end_addr - cur_addr); ret = mg_mflash_write_sects(sect_buff, sect_num, 1); } } return ret; } COMMAND_HANDLER(mg_write_cmd) { uint32_t address, cnt, res, i; uint8_t *buffer; struct fileio fileio; int ret; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address); ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY); if (ret != ERROR_OK) return ret; int filesize; buffer = malloc(MG_FILEIO_CHUNK); if (!buffer) { fileio_close(&fileio); return ERROR_FAIL; } int retval = fileio_size(&fileio, &filesize); if (retval != ERROR_OK) { fileio_close(&fileio); free(buffer); return retval; } cnt = filesize / MG_FILEIO_CHUNK; res = filesize % MG_FILEIO_CHUNK; struct duration bench; duration_start(&bench); size_t buf_cnt; for (i = 0; i < cnt; i++) { ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt); if (ret != ERROR_OK) goto mg_write_cmd_err; ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK); if (ret != ERROR_OK) goto mg_write_cmd_err; address += MG_FILEIO_CHUNK; } if (res) { ret = fileio_read(&fileio, res, buffer, &buf_cnt); if (ret != ERROR_OK) goto mg_write_cmd_err; ret = mg_mflash_write(address, buffer, res); if (ret != ERROR_OK) goto mg_write_cmd_err; } if (duration_measure(&bench) == ERROR_OK) { command_print(CMD_CTX, "wrote %ld bytes from file %s " "in %fs (%0.3f kB/s)", (long)filesize, CMD_ARGV[1], duration_elapsed(&bench), duration_kbps(&bench, filesize)); } free(buffer); fileio_close(&fileio); return ERROR_OK; mg_write_cmd_err: free(buffer); fileio_close(&fileio); return ret; } COMMAND_HANDLER(mg_dump_cmd) { uint32_t address, size, cnt, res, i; uint8_t *buffer; struct fileio fileio; int ret; if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size); ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY); if (ret != ERROR_OK) return ret; buffer = malloc(MG_FILEIO_CHUNK); if (!buffer) { fileio_close(&fileio); return ERROR_FAIL; } cnt = size / MG_FILEIO_CHUNK; res = size % MG_FILEIO_CHUNK; struct duration bench; duration_start(&bench); size_t size_written; for (i = 0; i < cnt; i++) { ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK); if (ret != ERROR_OK) goto mg_dump_cmd_err; ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written); if (ret != ERROR_OK) goto mg_dump_cmd_err; address += MG_FILEIO_CHUNK; } if (res) { ret = mg_mflash_read(address, buffer, res); if (ret != ERROR_OK) goto mg_dump_cmd_err; ret = fileio_write(&fileio, res, buffer, &size_written); if (ret != ERROR_OK) goto mg_dump_cmd_err; } if (duration_measure(&bench) == ERROR_OK) { command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " " "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)", address, size, CMD_ARGV[1], duration_elapsed(&bench), duration_kbps(&bench, size)); } free(buffer); fileio_close(&fileio); return ERROR_OK; mg_dump_cmd_err: free(buffer); fileio_close(&fileio); return ret; } static int mg_set_feature(mg_feature_id feature, mg_feature_val config) { struct target *target = mflash_bank->target; uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET; int ret; ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL); if (ret != ERROR_OK) return ret; ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature); ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config); ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND, mg_io_cmd_set_feature); return ret; } static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO) { double v1 = XIN / N; double v2 = CLK_OUT * NO; if (v1 < 1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000) return ERROR_MG_INVALID_PLL; return ERROR_OK; } static int mg_pll_get_M(unsigned short feedback_div) { int i, M; for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1) M += (feedback_div & 1) * i; return M + 2; } static int mg_pll_get_N(unsigned char input_div) { int i, N; for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1) N += (input_div & 1) * i; return N + 2; } static int mg_pll_get_NO(unsigned char output_div) { int i, NO; for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1) if (output_div & 1) NO = NO << 1; return NO; } static double mg_do_calc_pll(double XIN, mg_pll_t *p_pll_val, int is_approximate) { unsigned short i; unsigned char j, k; int M, N, NO; double CLK_OUT; double DIV = 1; double ROUND = 0; if (is_approximate) { DIV = 1000000; ROUND = 500000; } for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL; ++i) { M = mg_pll_get_M(i); for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL; ++j) { N = mg_pll_get_N(j); for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL; ++k) { NO = mg_pll_get_NO(k); CLK_OUT = XIN * ((double)M / N) / NO; if ((int)((CLK_OUT + ROUND) / DIV) == (int)(MG_PLL_CLK_OUT / DIV)) { if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK) { p_pll_val->lock_cyc = (int)(XIN * MG_PLL_STD_LOCKCYCLE / MG_PLL_STD_INPUTCLK); p_pll_val->feedback_div = i; p_pll_val->input_div = j; p_pll_val->output_div = k; return CLK_OUT; } } } } } return 0; } static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val) { double CLK_OUT; CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0); if (!CLK_OUT) return mg_do_calc_pll(XIN, p_pll_val, 1); else return CLK_OUT; } static int mg_verify_interface(void) { uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1]; uint16_t i, j; uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET; struct target *target = mflash_bank->target; int ret; for (j = 0; j < 10; j++) { for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) buff[i] = i; ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff); if (ret != ERROR_OK) return ret; memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE); ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff); if (ret != ERROR_OK) return ret; for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) { if (buff[i] != i) { LOG_ERROR("mflash: verify interface fail"); return ERROR_MG_INTERFACE; } } } LOG_INFO("mflash: verify interface ok"); return ret; } static const char g_strSEG_SerialNum[20] = { 'G', 'm', 'n', 'i', '-', 'e', 'e', 'S', 'g', 'a', 'e', 'l', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; static const char g_strSEG_FWRev[8] = { 'F', 'X', 'L', 'T', '2', 'v', '0', '.' }; static const char g_strSEG_ModelNum[40] = { 'F', 'X', 'A', 'L', 'H', 'S', '2', 0x20, '0', '0', 's', '7', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo) { /* b15 is ATA device(0) , b7 is Removable Media Device */ pSegIdDrvInfo->general_configuration = 0x045A; /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63 */ pSegIdDrvInfo->number_of_cylinders = 0x02E9; pSegIdDrvInfo->reserved1 = 0x0; pSegIdDrvInfo->number_of_heads = 0x10; pSegIdDrvInfo->unformatted_bytes_per_track = 0x0; pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0; pSegIdDrvInfo->sectors_per_track = 0x3F; pSegIdDrvInfo->vendor_unique1[0] = 0x000B; pSegIdDrvInfo->vendor_unique1[1] = 0x7570; pSegIdDrvInfo->vendor_unique1[2] = 0x8888; memcpy(pSegIdDrvInfo->serial_number, g_strSEG_SerialNum, 20); /* 0x2 : dual buffer */ pSegIdDrvInfo->buffer_type = 0x2; /* buffer size : 2KB */ pSegIdDrvInfo->buffer_sector_size = 0x800; pSegIdDrvInfo->number_of_ecc_bytes = 0; memcpy(pSegIdDrvInfo->firmware_revision, g_strSEG_FWRev, 8); memcpy(pSegIdDrvInfo->model_number, g_strSEG_ModelNum, 40); pSegIdDrvInfo->maximum_block_transfer = 0x4; pSegIdDrvInfo->vendor_unique2 = 0x0; pSegIdDrvInfo->dword_io = 0x00; /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY * b9 : LBA support, b8 : DMA mode support */ pSegIdDrvInfo->capabilities = 0x1 << 9; pSegIdDrvInfo->reserved2 = 0x4000; pSegIdDrvInfo->vendor_unique3 = 0x00; /* PIOMode-2 support */ pSegIdDrvInfo->pio_cycle_timing_mode = 0x02; pSegIdDrvInfo->vendor_unique4 = 0x00; /* MultiWord-2 support */ pSegIdDrvInfo->dma_cycle_timing_mode = 0x00; /* b1 : word64~70 is valid * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors * b2 : If device supports Ultra DMA , set to one to vaildate word88 */ pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0); pSegIdDrvInfo->number_of_current_cylinders = 0x02E9; pSegIdDrvInfo->number_of_current_heads = 0x10; pSegIdDrvInfo->current_sectors_per_track = 0x3F; pSegIdDrvInfo->current_sector_capacity_lo = 0x7570; pSegIdDrvInfo->current_sector_capacity_hi = 0x000B; pSegIdDrvInfo->multi_sector_count = 0x04; /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */ pSegIdDrvInfo->multi_sector_setting_valid = 0x01; pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570; pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B; pSegIdDrvInfo->single_dma_modes_supported = 0x00; pSegIdDrvInfo->single_dma_transfer_active = 0x00; /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */ pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0); /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */ pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0); /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */ pSegIdDrvInfo->adv_pio_mode = 0x00; /* 480(0x1E0)nsec for Multi-word DMA mode0 * 150(0x96) nsec for Multi-word DMA mode1 * 120(0x78) nsec for Multi-word DMA mode2 */ pSegIdDrvInfo->min_dma_cyc = 0x1E0; pSegIdDrvInfo->recommend_dma_cyc = 0x1E0; pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0; pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0; memset(pSegIdDrvInfo->reserved3, 0x00, 22); /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */ pSegIdDrvInfo->major_ver_num = 0x7E; /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */ pSegIdDrvInfo->minor_ver_num = 0x19; /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */ pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068; /* Features/command set is valid/Advanced Pwr management/CFA feature set * not support */ pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C; pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000; /* READ/WRITE BUFFER/PWR Management enable */ pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000; /* CFA feature is disabled / Advancde power management disable */ pSegIdDrvInfo->feature_cmd_set_en1 = 0x0; pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000; pSegIdDrvInfo->reserved4 = 0x0; /* 0x1 * 2minutes */ pSegIdDrvInfo->req_time_for_security_er_done = 0x19; pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19; /* Advanced power management level 1 */ pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0; pSegIdDrvInfo->reserved5 = 0x0; memset(pSegIdDrvInfo->reserved6, 0x00, 68); /* Security mode feature is disabled */ pSegIdDrvInfo->security_stas = 0x0; memset(pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62); /* CFA power mode 1 support in maximum 200mA */ pSegIdDrvInfo->cfa_pwr_mode = 0x0100; memset(pSegIdDrvInfo->reserved7, 0x00, 190); } static int mg_storage_config(void) { uint8_t buff[512]; int ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd); if (ret != ERROR_OK) return ret; mg_gen_ataid((mg_io_type_drv_info *)(void *)buff); ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo); if (ret != ERROR_OK) return ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: storage config ok"); return ret; } static int mg_boot_config(void) { uint8_t buff[512]; int ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd); if (ret != ERROR_OK) return ret; memset(buff, 0xff, 512); buff[0] = mg_op_mode_snd; /* operation mode */ buff[1] = MG_UNLOCK_OTP_AREA; buff[2] = 4; /* boot size */ *((uint32_t *)(void *)(buff + 4)) = 0; /* XIP size */ ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo); if (ret != ERROR_OK) return ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: boot config ok"); return ret; } static int mg_set_pll(mg_pll_t *pll) { uint8_t buff[512]; int ret; memset(buff, 0xff, 512); /* PLL Lock cycle and Feedback 9bit Divider */ memcpy(buff, &pll->lock_cyc, sizeof(uint32_t)); memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t)); buff[6] = pll->input_div; /* PLL Input 5bit Divider */ buff[7] = pll->output_div; /* PLL Output Divider */ ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd); if (ret != ERROR_OK) return ret; ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll); if (ret != ERROR_OK) return ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: set pll ok"); return ret; } static int mg_erase_nand(void) { int ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd); if (ret != ERROR_OK) return ret; ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand); if (ret != ERROR_OK) return ret; ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default); if (ret != ERROR_OK) return ret; LOG_INFO("mflash: erase nand ok"); return ret; } COMMAND_HANDLER(mg_config_cmd) { double fin, fout; mg_pll_t pll; int ret; ret = mg_verify_interface(); if (ret != ERROR_OK) return ret; ret = mg_mflash_rst(); if (ret != ERROR_OK) return ret; switch (CMD_ARGC) { case 2: if (!strcmp(CMD_ARGV[1], "boot")) return mg_boot_config(); else if (!strcmp(CMD_ARGV[1], "storage")) return mg_storage_config(); else return ERROR_COMMAND_NOTFOUND; break; case 3: if (!strcmp(CMD_ARGV[1], "pll")) { unsigned long freq; COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq); fin = freq; if (fin > MG_PLL_CLK_OUT) { LOG_ERROR("mflash: input freq. is too large"); return ERROR_MG_INVALID_OSC; } fout = mg_calc_pll(fin, &pll); if (!fout) { LOG_ERROR("mflash: cannot generate valid pll"); return ERROR_MG_INVALID_PLL; } LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u," "indiv=%u, outdiv=%u, lock=%u", (uint32_t)fout, pll.feedback_div, pll.input_div, pll.output_div, pll.lock_cyc); ret = mg_erase_nand(); if (ret != ERROR_OK) return ret; return mg_set_pll(&pll); } else return ERROR_COMMAND_NOTFOUND; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } } static const struct command_registration mflash_exec_command_handlers[] = { { .name = "probe", .handler = mg_probe_cmd, .mode = COMMAND_EXEC, .help = "Detect bank configuration information", }, { .name = "write", .handler = mg_write_cmd, .mode = COMMAND_EXEC, /* FIXME bank_num is unused */ .usage = "bank_num filename address", .help = "Write binary file at the specified address.", }, { .name = "dump", .handler = mg_dump_cmd, .mode = COMMAND_EXEC, /* FIXME bank_num is unused */ .usage = "bank_num filename address size", .help = "Write specified number of bytes from a binary file " "to the specified, address.", }, { .name = "config", .handler = mg_config_cmd, .mode = COMMAND_EXEC, .help = "Configure MFLASH options.", .usage = "('boot'|'storage'|'pll' frequency)", }, COMMAND_REGISTRATION_DONE }; static int mflash_init_drivers(struct command_context *cmd_ctx) { if (!mflash_bank) return ERROR_OK; return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers); } COMMAND_HANDLER(handle_mflash_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool mflash_initialized; if (mflash_initialized) { LOG_INFO("'mflash init' has already been called"); return ERROR_OK; } mflash_initialized = true; LOG_DEBUG("Initializing mflash devices..."); return mflash_init_drivers(CMD_CTX); } COMMAND_HANDLER(mg_bank_cmd) { struct target *target; int i; if (CMD_ARGC < 4) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[3]); if (target == NULL) { LOG_ERROR("target '%s' not defined", CMD_ARGV[3]); return ERROR_FAIL; } mflash_bank = calloc(sizeof(struct mflash_bank), 1); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base); /** @todo Verify how this parsing should work, then document it. */ char *str; mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0); if (*str) mflash_bank->rst_pin.port[0] = (uint16_t) tolower((unsigned)str[0]); mflash_bank->target = target; for (i = 0; mflash_gpio[i]; i++) { if (!strcmp(mflash_gpio[i]->name, CMD_ARGV[0])) mflash_bank->gpio_drv = mflash_gpio[i]; } if (!mflash_bank->gpio_drv) { LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]); return ERROR_MG_UNSUPPORTED_SOC; } return ERROR_OK; } static const struct command_registration mflash_config_command_handlers[] = { { .name = "bank", .handler = mg_bank_cmd, .mode = COMMAND_CONFIG, .help = "configure a mflash device bank", .usage = "soc_type base_addr pin_id target", }, { .name = "init", .mode = COMMAND_CONFIG, .handler = handle_mflash_init_command, .help = "initialize mflash devices", .usage = "" }, COMMAND_REGISTRATION_DONE }; static const struct command_registration mflash_command_handler[] = { { .name = "mflash", .mode = COMMAND_ANY, .help = "mflash command group", .usage = "", .chain = mflash_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; int mflash_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, mflash_command_handler); } openocd-0.9.0/src/flash/mflash.h0000644000175000017500000002407712315575360013420 00000000000000/*************************************************************************** * Copyright (C) 2007-2008 by unsik Kim * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _MFLASH_H #define _MFLASH_H struct command_context; typedef unsigned long mg_io_uint32; typedef unsigned short mg_io_uint16; typedef unsigned char mg_io_uint8; struct mflash_gpio_num { char port[2]; signed short num; }; struct mflash_gpio_drv { const char *name; int (*set_gpio_to_output)(struct mflash_gpio_num gpio); int (*set_gpio_output_val)(struct mflash_gpio_num gpio, uint8_t val); }; typedef struct _mg_io_type_drv_info { mg_io_uint16 general_configuration; /* 00 */ mg_io_uint16 number_of_cylinders; /* 01 */ mg_io_uint16 reserved1; /* 02 */ mg_io_uint16 number_of_heads; /* 03 */ mg_io_uint16 unformatted_bytes_per_track; /* 04 */ mg_io_uint16 unformatted_bytes_per_sector; /* 05 */ mg_io_uint16 sectors_per_track; /* 06 */ mg_io_uint16 vendor_unique1[3]; /* 07/08/09 */ mg_io_uint8 serial_number[20]; /* 10~19 */ mg_io_uint16 buffer_type; /* 20 */ mg_io_uint16 buffer_sector_size; /* 21 */ mg_io_uint16 number_of_ecc_bytes; /* 22 */ mg_io_uint8 firmware_revision[8]; /* 23~26 */ mg_io_uint8 model_number[40]; /* 27 */ mg_io_uint8 maximum_block_transfer; /* 47 low byte */ mg_io_uint8 vendor_unique2; /* 47 high byte */ mg_io_uint16 dword_io; /* 48 */ mg_io_uint16 capabilities; /* 49 */ mg_io_uint16 reserved2; /* 50 */ mg_io_uint8 vendor_unique3; /* 51 low byte */ mg_io_uint8 pio_cycle_timing_mode; /* 51 high byte */ mg_io_uint8 vendor_unique4; /* 52 low byte */ mg_io_uint8 dma_cycle_timing_mode; /* 52 high byte */ mg_io_uint16 translation_fields_valid; /* 53 (low bit) */ mg_io_uint16 number_of_current_cylinders; /* 54 */ mg_io_uint16 number_of_current_heads; /* 55 */ mg_io_uint16 current_sectors_per_track; /* 56 */ mg_io_uint16 current_sector_capacity_lo; /* 57 & 58 */ mg_io_uint16 current_sector_capacity_hi; /* 57 & 58 */ mg_io_uint8 multi_sector_count; /* 59 low */ mg_io_uint8 multi_sector_setting_valid; /* 59 high (low bit) */ mg_io_uint16 total_user_addressable_sectors_lo; /* 60 & 61 */ mg_io_uint16 total_user_addressable_sectors_hi; /* 60 & 61 */ mg_io_uint8 single_dma_modes_supported; /* 62 low byte */ mg_io_uint8 single_dma_transfer_active; /* 62 high byte */ mg_io_uint8 multi_dma_modes_supported; /* 63 low byte */ mg_io_uint8 multi_dma_transfer_active; /* 63 high byte */ mg_io_uint16 adv_pio_mode; mg_io_uint16 min_dma_cyc; mg_io_uint16 recommend_dma_cyc; mg_io_uint16 min_pio_cyc_no_iordy; mg_io_uint16 min_pio_cyc_with_iordy; mg_io_uint8 reserved3[22]; mg_io_uint16 major_ver_num; mg_io_uint16 minor_ver_num; mg_io_uint16 feature_cmd_set_suprt0; mg_io_uint16 feature_cmd_set_suprt1; mg_io_uint16 feature_cmd_set_suprt2; mg_io_uint16 feature_cmd_set_en0; mg_io_uint16 feature_cmd_set_en1; mg_io_uint16 feature_cmd_set_en2; mg_io_uint16 reserved4; mg_io_uint16 req_time_for_security_er_done; mg_io_uint16 req_time_for_enhan_security_er_done; mg_io_uint16 adv_pwr_mgm_lvl_val; mg_io_uint16 reserved5; mg_io_uint16 re_of_hw_rst; mg_io_uint8 reserved6[68]; mg_io_uint16 security_stas; mg_io_uint8 vendor_uniq_bytes[62]; mg_io_uint16 cfa_pwr_mode; mg_io_uint8 reserved7[186]; mg_io_uint16 scts_per_secure_data_unit; mg_io_uint16 integrity_word; } mg_io_type_drv_info; typedef struct _mg_pll_t { unsigned int lock_cyc; unsigned short feedback_div; /* 9bit divider */ unsigned char input_div; /* 5bit divider */ unsigned char output_div; /* 2bit divider */ } mg_pll_t; struct mg_drv_info { mg_io_type_drv_info drv_id; uint32_t tot_sects; }; struct mflash_bank { uint32_t base; struct mflash_gpio_num rst_pin; struct mflash_gpio_drv *gpio_drv; struct target *target; struct mg_drv_info *drv_info; }; int mflash_register_commands(struct command_context *cmd_ctx); #define MG_MFLASH_SECTOR_SIZE (0x200) /* 512Bytes = 2^9 */ #define MG_MFLASH_SECTOR_SIZE_MASK (0x200-1) #define MG_MFLASH_SECTOR_SIZE_SHIFT (9) #define MG_BUFFER_OFFSET 0x8000 #define MG_REG_OFFSET 0xC000 #define MG_REG_FEATURE 0x2 /* write case */ #define MG_REG_ERROR 0x2 /* read case */ #define MG_REG_SECT_CNT 0x4 #define MG_REG_SECT_NUM 0x6 #define MG_REG_CYL_LOW 0x8 #define MG_REG_CYL_HIGH 0xA #define MG_REG_DRV_HEAD 0xC #define MG_REG_COMMAND 0xE /* write case */ #define MG_REG_STATUS 0xE /* read case */ #define MG_REG_DRV_CTRL 0x10 #define MG_REG_BURST_CTRL 0x12 #define MG_OEM_DISK_WAIT_TIME_LONG 15000 /* msec */ #define MG_OEM_DISK_WAIT_TIME_NORMAL 3000 /* msec */ #define MG_OEM_DISK_WAIT_TIME_SHORT 1000 /* msec */ #define MG_PLL_CLK_OUT 66000000.0 /* 66Mhz */ #define MG_PLL_MAX_FEEDBACKDIV_VAL 512 #define MG_PLL_MAX_INPUTDIV_VAL 32 #define MG_PLL_MAX_OUTPUTDIV_VAL 4 #define MG_PLL_STD_INPUTCLK 12000000.0 /* 12Mhz */ #define MG_PLL_STD_LOCKCYCLE 10000 #define MG_UNLOCK_OTP_AREA 0xFF #define MG_FILEIO_CHUNK 1048576 #define ERROR_MG_IO (-1600) #define ERROR_MG_TIMEOUT (-1601) #define ERROR_MG_INVALID_PLL (-1603) #define ERROR_MG_INTERFACE (-1604) #define ERROR_MG_INVALID_OSC (-1605) #define ERROR_MG_UNSUPPORTED_SOC (-1606) typedef enum _mg_io_type_wait { mg_io_wait_bsy = 1, mg_io_wait_not_bsy = 2, mg_io_wait_rdy = 3, mg_io_wait_drq = 4, /* wait for data request */ mg_io_wait_drq_noerr = 5, /* wait for DRQ but ignore the error status bit */ mg_io_wait_rdy_noerr = 6 /* wait for ready, but ignore error status bit */ } mg_io_type_wait; /*= "Status Register" bit masks. */ typedef enum _mg_io_type_rbit_status { mg_io_rbit_status_error = 0x01, /* error bit in status register */ mg_io_rbit_status_corrected_error = 0x04, /* corrected error in status register */ mg_io_rbit_status_data_req = 0x08, /* data request bit in status register */ mg_io_rbit_status_seek_done = 0x10, /* DSC - Drive Seek Complete */ mg_io_rbit_status_write_fault = 0x20, /* DWF - Drive Write Fault */ mg_io_rbit_status_ready = 0x40, mg_io_rbit_status_busy = 0x80 } mg_io_type_rbit_status; /*= "Error Register" bit masks. */ typedef enum _mg_io_type_rbit_error { mg_io_rbit_err_general = 0x01, mg_io_rbit_err_aborted = 0x04, mg_io_rbit_err_bad_sect_num = 0x10, mg_io_rbit_err_uncorrectable = 0x40, mg_io_rbit_err_bad_block = 0x80 } mg_io_type_rbit_error; /* = "Device Control Register" bit. */ typedef enum _mg_io_type_rbit_devc { mg_io_rbit_devc_intr = 0x02, /* interrupt enable bit (1:disable, 0:enable) */ mg_io_rbit_devc_srst = 0x04 /* softwrae reset bit (1:assert, 0:de-assert) */ } mg_io_type_rbit_devc; /* "Drive Select/Head Register" values. */ typedef enum _mg_io_type_rval_dev { mg_io_rval_dev_must_be_on = 0x80, /* These 1 bits are always on */ mg_io_rval_dev_drv_master = (0x00 | mg_io_rval_dev_must_be_on), /* Master */ mg_io_rval_dev_drv_slave0 = (0x10 | mg_io_rval_dev_must_be_on), /* Slave0 */ mg_io_rval_dev_drv_slave1 = (0x20 | mg_io_rval_dev_must_be_on), /* Slave1 */ mg_io_rval_dev_drv_slave2 = (0x30 | mg_io_rval_dev_must_be_on), /* Slave2 */ mg_io_rval_dev_lba_mode = (0x40 | mg_io_rval_dev_must_be_on) } mg_io_type_rval_dev; typedef enum _mg_io_type_cmd { mg_io_cmd_read = 0x20, mg_io_cmd_write = 0x30, mg_io_cmd_setmul = 0xC6, mg_io_cmd_readmul = 0xC4, mg_io_cmd_writemul = 0xC5, mg_io_cmd_idle = 0x97, /* 0xE3 */ mg_io_cmd_idle_immediate = 0x95, /* 0xE1 */ mg_io_cmd_setsleep = 0x99, /* 0xE6 */ mg_io_cmd_stdby = 0x96, /* 0xE2 */ mg_io_cmd_stdby_immediate = 0x94, /* 0xE0 */ mg_io_cmd_identify = 0xEC, mg_io_cmd_set_feature = 0xEF, mg_io_cmd_confirm_write = 0x3C, mg_io_cmd_confirm_read = 0x40, mg_io_cmd_wakeup = 0xC3 } mg_io_type_cmd; typedef enum _mg_feature_id { mg_feature_id_transmode = 0x3 } mg_feature_id; typedef enum _mg_feature_val { mg_feature_val_trans_default = 0x0, mg_feature_val_trans_vcmd = 0x3, mg_feature_val_trand_vcmds = 0x2 } mg_feature_val; typedef enum _mg_vcmd { mg_vcmd_update_xipinfo = 0xFA, /* FWPATCH commmand through IOM I/O */ mg_vcmd_verify_fwpatch = 0xFB, /* FWPATCH commmand through IOM I/O */ mg_vcmd_update_stgdrvinfo = 0xFC, /* IOM identificatin info program command */ mg_vcmd_prep_fwpatch = 0xFD, /* FWPATCH commmand through IOM I/O */ mg_vcmd_exe_fwpatch = 0xFE, /* FWPATCH commmand through IOM I/O */ mg_vcmd_wr_pll = 0x8B, mg_vcmd_purge_nand = 0x8C, /* Only for Seagle */ mg_vcmd_lock_otp = 0x8D, mg_vcmd_rd_otp = 0x8E, mg_vcmd_wr_otp = 0x8F } mg_vcmd; typedef enum _mg_opmode { mg_op_mode_xip = 1, /* TRUE XIP */ mg_op_mode_snd = 2, /* BOOT + Storage */ mg_op_mode_stg = 0 /* Only Storage */ } mg_opmode; #endif openocd-0.9.0/src/flash/startup.tcl0000644000175000017500000000465212516456302014175 00000000000000# Defines basic Tcl procs for OpenOCD flash module # # program utility proc # usage: program filename # optional args: verify, reset, exit and address # proc program_error {description exit} { if {$exit == 1} { echo $description shutdown error } error $description } proc program {filename args} { set exit 0 foreach arg $args { if {[string equal $arg "verify"]} { set verify 1 } elseif {[string equal $arg "reset"]} { set reset 1 } elseif {[string equal $arg "exit"]} { set exit 1 } else { set address $arg } } # make sure init is called if {[catch {init}] != 0} { program_error "** OpenOCD init failed **" 1 } # reset target and call any init scripts if {[catch {reset init}] != 0} { program_error "** Unable to reset target **" $exit } # start programming phase echo "** Programming Started **" if {[info exists address]} { set flash_args "$filename $address" } else { set flash_args "$filename" } if {[catch {eval flash write_image erase $flash_args}] == 0} { echo "** Programming Finished **" if {[info exists verify]} { # verify phase echo "** Verify Started **" if {[catch {eval verify_image $flash_args}] == 0} { echo "** Verified OK **" } else { program_error "** Verify Failed **" $exit } } if {[info exists reset]} { # reset target if requested # also disable target polling, we are shutting down anyway poll off echo "** Resetting Target **" reset run } } else { program_error "** Programming Failed **" $exit } if {$exit == 1} { shutdown } return } add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional" add_usage_text program " \[address\] \[verify\] \[reset\] \[exit\]" # stm32f0x uses the same flash driver as the stm32f1x # this alias enables the use of either name. proc stm32f0x args { eval stm32f1x $args } # stm32f3x uses the same flash driver as the stm32f1x # this alias enables the use of either name. proc stm32f3x args { eval stm32f1x $args } # stm32f4x uses the same flash driver as the stm32f2x # this alias enables the use of either name. proc stm32f4x args { eval stm32f2x $args } # ease migration to updated flash driver proc stm32x args { echo "DEPRECATED! use 'stm32f1x $args' not 'stm32x $args'" eval stm32f1x $args } proc stm32f2xxx args { echo "DEPRECATED! use 'stm32f2x $args' not 'stm32f2xxx $args'" eval stm32f2x $args } openocd-0.9.0/src/flash/common.c0000644000175000017500000000422712315575360013424 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "common.h" #include unsigned get_flash_name_index(const char *name) { const char *name_index = strrchr(name, '.'); if (NULL == name_index) return 0; if (name_index[1] < '0' || name_index[1] > '9') return ~0U; unsigned requested; int retval = parse_uint(name_index + 1, &requested); /* detect parsing error by forcing past end of bank list */ return (ERROR_OK == retval) ? requested : ~0U; } bool flash_driver_name_matches(const char *name, const char *expected) { unsigned blen = strlen(name); /* only match up to the length of the driver name... */ if (strncmp(name, expected, blen) != 0) return false; /* ...then check that name terminates at this spot. */ return expected[blen] == '.' || expected[blen] == '\0'; } openocd-0.9.0/src/flash/common.h0000644000175000017500000000500512315575360013424 00000000000000/*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FLASH_COMMON_H #define FLASH_COMMON_H #include /** * Parses the optional '.index' portion of a flash bank identifier. * @param name The desired driver name, passed by the user. * @returns The parsed index request, or 0 if not present. If the * name provides a suffix but it does not parse as an unsigned integer, * the routine returns ~0U. This will prevent further matching. */ unsigned get_flash_name_index(const char *name); /** * Attempt to match the @c expected name with the @c name of a driver. * @param name The name of the driver (from the bank's device structure). * @param expected The expected driver name, passed by the user. */ bool flash_driver_name_matches(const char *name, const char *expected); #define ERROR_FLASH_BANK_INVALID (-900) #define ERROR_FLASH_SECTOR_INVALID (-901) #define ERROR_FLASH_OPERATION_FAILED (-902) #define ERROR_FLASH_DST_OUT_OF_BANK (-903) #define ERROR_FLASH_DST_BREAKS_ALIGNMENT (-904) #define ERROR_FLASH_BUSY (-905) #define ERROR_FLASH_SECTOR_NOT_ERASED (-906) #define ERROR_FLASH_BANK_NOT_PROBED (-907) #define ERROR_FLASH_OPER_UNSUPPORTED (-908) #endif /* FLASH_COMMON_H */ openocd-0.9.0/src/flash/Makefile.am0000644000175000017500000000061512315575360014021 00000000000000include $(top_srcdir)/common.mk SUBDIRS = \ nor \ nand METASOURCES = AUTO noinst_LTLIBRARIES = libflash.la libflash_la_SOURCES = \ common.c \ mflash.c libflash_la_LIBADD = \ $(top_builddir)/src/flash/nor/libocdflashnor.la \ $(top_builddir)/src/flash/nand/libocdflashnand.la noinst_HEADERS = \ common.h \ mflash.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/flash/Makefile.in0000644000175000017500000005476312526201647014045 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/flash ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libflash_la_DEPENDENCIES = \ $(top_builddir)/src/flash/nor/libocdflashnor.la \ $(top_builddir)/src/flash/nand/libocdflashnand.la am_libflash_la_OBJECTS = common.lo mflash.lo libflash_la_OBJECTS = $(am_libflash_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libflash_la_SOURCES) DIST_SOURCES = $(libflash_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) SUBDIRS = \ nor \ nand METASOURCES = AUTO noinst_LTLIBRARIES = libflash.la libflash_la_SOURCES = \ common.c \ mflash.c libflash_la_LIBADD = \ $(top_builddir)/src/flash/nor/libocdflashnor.la \ $(top_builddir)/src/flash/nand/libocdflashnand.la noinst_HEADERS = \ common.h \ mflash.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/flash/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/flash/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libflash.la: $(libflash_la_OBJECTS) $(libflash_la_DEPENDENCIES) $(EXTRA_libflash_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libflash_la_OBJECTS) $(libflash_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mflash.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/helper/0000755000175000017500000000000012526202225012214 500000000000000openocd-0.9.0/src/helper/replacements.c0000644000175000017500000002126612315712572015000 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* DANGER!!!! These must be defined *BEFORE* replacements.h and the malloc() macro!!!! */ #include #include /* * clear_malloc * * will alloc memory and clear it */ void *clear_malloc(size_t size) { void *t = malloc(size); if (t != NULL) memset(t, 0x00, size); return t; } void *fill_malloc(size_t size) { void *t = malloc(size); if (t != NULL) { /* We want to initialize memory to some known bad state. * 0 and 0xff yields 0 and -1 as integers, which often * have meaningful values. 0x5555... is not often a valid * integer and is quite easily spotted in the debugger * also it is almost certainly an invalid address */ memset(t, 0x55, size); } return t; } #define IN_REPLACEMENTS_C #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef _WIN32 #include #endif /* replacements for gettimeofday */ #ifndef HAVE_GETTIMEOFDAY /* Windows */ #ifdef _WIN32 #ifndef __GNUC__ #define EPOCHFILETIME (116444736000000000i64) #else #define EPOCHFILETIME (116444736000000000LL) #endif int gettimeofday(struct timeval *tv, struct timezone *tz) { FILETIME ft; LARGE_INTEGER li; __int64 t; static int tzflag; if (tv) { GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; t = li.QuadPart; /* In 100-nanosecond intervals */ t -= EPOCHFILETIME; /* Offset to the Epoch time */ t /= 10; /* In microseconds */ tv->tv_sec = (long)(t / 1000000); tv->tv_usec = (long)(t % 1000000); } if (tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } #endif /* _WIN32 */ #endif /* HAVE_GETTIMEOFDAY */ #ifndef HAVE_STRNLEN size_t strnlen(const char *s, size_t maxlen) { const char *end = (const char *)memchr(s, '\0', maxlen); return end ? (size_t) (end - s) : maxlen; } #endif #ifndef HAVE_STRNDUP char *strndup(const char *s, size_t n) { size_t len = strnlen(s, n); char *new = malloc(len + 1); if (new == NULL) return NULL; new[len] = '\0'; return (char *) memcpy(new, s, len); } #endif #ifdef _WIN32 int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv) { DWORD ms_total, limit; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS]; int n_handles = 0, i; fd_set sock_read, sock_write, sock_except; fd_set aread, awrite, aexcept; int sock_max_fd = -1; struct timeval tvslice; int retcode; #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) /* calculate how long we need to wait in milliseconds */ if (tv == NULL) ms_total = INFINITE; else { ms_total = tv->tv_sec * 1000; ms_total += tv->tv_usec / 1000; } FD_ZERO(&sock_read); FD_ZERO(&sock_write); FD_ZERO(&sock_except); /* build an array of handles for non-sockets */ for (i = 0; i < max_fd; i++) { if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) { intptr_t handle = (intptr_t) _get_osfhandle(i); handles[n_handles] = (HANDLE)handle; if (handles[n_handles] == INVALID_HANDLE_VALUE) { /* socket */ if (SAFE_FD_ISSET(i, rfds)) FD_SET(i, &sock_read); if (SAFE_FD_ISSET(i, wfds)) FD_SET(i, &sock_write); if (SAFE_FD_ISSET(i, efds)) FD_SET(i, &sock_except); if (i > sock_max_fd) sock_max_fd = i; } else { handle_slot_to_fd[n_handles] = i; n_handles++; } } } if (n_handles == 0) { /* plain sockets only - let winsock handle the whole thing */ return select(max_fd, rfds, wfds, efds, tv); } /* mixture of handles and sockets; lets multiplex between * winsock and waiting on the handles */ FD_ZERO(&aread); FD_ZERO(&awrite); FD_ZERO(&aexcept); limit = GetTickCount() + ms_total; do { retcode = 0; if (sock_max_fd >= 0) { /* overwrite the zero'd sets here; the select call * will clear those that are not active */ aread = sock_read; awrite = sock_write; aexcept = sock_except; tvslice.tv_sec = 0; tvslice.tv_usec = 1000; retcode = select(sock_max_fd + 1, &aread, &awrite, &aexcept, &tvslice); } if (n_handles > 0) { /* check handles */ DWORD wret; wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 1, QS_ALLEVENTS); if (wret == WAIT_TIMEOUT) { /* set retcode to 0; this is the default. * select() may have set it to something else, * in which case we leave it alone, so this branch * does nothing */ ; } else if (wret == WAIT_FAILED) { if (retcode == 0) retcode = -1; } else { if (retcode < 0) retcode = 0; for (i = 0; i < n_handles; i++) { if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) { if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) { DWORD dwBytes; intptr_t handle = (intptr_t) _get_osfhandle( handle_slot_to_fd[i]); if (PeekNamedPipe((HANDLE)handle, NULL, 0, NULL, &dwBytes, NULL)) { /* check to see if gdb pipe has data available */ if (dwBytes) { FD_SET(handle_slot_to_fd[i], &aread); retcode++; } } else { FD_SET(handle_slot_to_fd[i], &aread); retcode++; } } if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) { FD_SET(handle_slot_to_fd[i], &awrite); retcode++; } if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) { FD_SET(handle_slot_to_fd[i], &aexcept); retcode++; } } } } } } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit)); if (rfds) *rfds = aread; if (wfds) *wfds = awrite; if (efds) *efds = aexcept; return retcode; } #endif #if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME #include /* Verbatim from git://git.libusb.org/libusb.git tag 1.0.9 * The libusb_error enum is compatible down to v0.9.1 */ const char *libusb_error_name(int error_code) { enum libusb_error error = error_code; switch (error) { case LIBUSB_SUCCESS: return "LIBUSB_SUCCESS"; case LIBUSB_ERROR_IO: return "LIBUSB_ERROR_IO"; case LIBUSB_ERROR_INVALID_PARAM: return "LIBUSB_ERROR_INVALID_PARAM"; case LIBUSB_ERROR_ACCESS: return "LIBUSB_ERROR_ACCESS"; case LIBUSB_ERROR_NO_DEVICE: return "LIBUSB_ERROR_NO_DEVICE"; case LIBUSB_ERROR_NOT_FOUND: return "LIBUSB_ERROR_NOT_FOUND"; case LIBUSB_ERROR_BUSY: return "LIBUSB_ERROR_BUSY"; case LIBUSB_ERROR_TIMEOUT: return "LIBUSB_ERROR_TIMEOUT"; case LIBUSB_ERROR_OVERFLOW: return "LIBUSB_ERROR_OVERFLOW"; case LIBUSB_ERROR_PIPE: return "LIBUSB_ERROR_PIPE"; case LIBUSB_ERROR_INTERRUPTED: return "LIBUSB_ERROR_INTERRUPTED"; case LIBUSB_ERROR_NO_MEM: return "LIBUSB_ERROR_NO_MEM"; case LIBUSB_ERROR_NOT_SUPPORTED: return "LIBUSB_ERROR_NOT_SUPPORTED"; case LIBUSB_ERROR_OTHER: return "LIBUSB_ERROR_OTHER"; } return "**UNKNOWN**"; } #endif openocd-0.9.0/src/helper/replacements.h0000644000175000017500000002036212516456302015000 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef REPLACEMENTS_H #define REPLACEMENTS_H /* MIN,MAX macros */ #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif /* for systems that do not support ENOTSUP * win32 being one of them */ #ifndef ENOTSUP #define ENOTSUP 134 /* Not supported */ #endif /* for systems that do not support O_BINARY * linux being one of them */ #ifndef O_BINARY #define O_BINARY 0 #endif #ifndef HAVE_SYS_TIME_H #ifndef _TIMEVAL_DEFINED #define _TIMEVAL_DEFINED struct timeval { long tv_sec; long tv_usec; }; #endif /* _TIMEVAL_DEFINED */ #endif /* gettimeofday() */ #ifndef HAVE_GETTIMEOFDAY #ifdef _WIN32 struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif struct timezone; int gettimeofday(struct timeval *tv, struct timezone *tz); #endif #ifndef IN_REPLACEMENTS_C /**** clear_malloc & fill_malloc ****/ void *clear_malloc(size_t size); void *fill_malloc(size_t size); #endif /* * Now you have 3 ways for the malloc function: * * 1. Do not change anything, use the original malloc * * 2. Use the clear_malloc function instead of the original malloc. * In this case you must use the following define: * #define malloc((_a)) clear_malloc((_a)) * * 3. Use the fill_malloc function instead of the original malloc. * In this case you must use the following define: * #define malloc((_a)) fill_malloc((_a)) * * We have figured out that there could exist some malloc problems * where variables are using without to be initialise. To find this * places, use the fill_malloc function. With this function we want * to initialize memory to some known bad state. This is quite easily * spotted in the debugger and will trap to an invalid address. * * clear_malloc can be used if you want to set not initialise * variable to 0. * * If you do not want to change the malloc function, to not use one of * the following macros. Which is the default way. */ /* #define malloc(_a) clear_malloc(_a) * #define malloc(_a) fill_malloc(_a) */ /* GNU extensions to the C library that may be missing on some systems */ #ifndef HAVE_STRNDUP char *strndup(const char *s, size_t n); #endif /* HAVE_STRNDUP */ #ifndef HAVE_STRNLEN size_t strnlen(const char *s, size_t maxlen); #endif /* HAVE_STRNLEN */ #ifndef HAVE_USLEEP #ifdef _WIN32 static inline unsigned usleep(unsigned int usecs) { Sleep((usecs/1000)); return 0; } #else #error no usleep defined for your platform #endif #endif /* HAVE_USLEEP */ /* Windows specific */ #ifdef _WIN32 #include #include /* Windows does not declare sockaddr_un */ #define UNIX_PATH_LEN 108 struct sockaddr_un { uint16_t sun_family; char sun_path[UNIX_PATH_LEN]; }; /* win32 systems do not support ETIMEDOUT */ #ifndef ETIMEDOUT #define ETIMEDOUT WSAETIMEDOUT #endif #if IS_MINGW == 1 static inline unsigned char inb(unsigned short int port) { unsigned char _v; __asm__ __volatile__ ("inb %w1,%0" : "=a" (_v) : "Nd" (port)); return _v; } static inline void outb(unsigned char value, unsigned short int port) { __asm__ __volatile__ ("outb %b0,%w1" : : "a" (value), "Nd" (port)); } /* mingw does not have ffs, so use gcc builtin types */ #define ffs __builtin_ffs #endif /* IS_MINGW */ int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv); #endif /* _WIN32 */ /* generic socket functions for Windows and Posix */ static inline int write_socket(int handle, const void *buffer, unsigned int count) { #ifdef _WIN32 return send(handle, buffer, count, 0); #else return write(handle, buffer, count); #endif } static inline int read_socket(int handle, void *buffer, unsigned int count) { #ifdef _WIN32 return recv(handle, buffer, count, 0); #else return read(handle, buffer, count); #endif } static inline int close_socket(int sock) { #ifdef _WIN32 return closesocket(sock); #else return close(sock); #endif } static inline void socket_nonblock(int fd) { #ifdef _WIN32 unsigned long nonblock = 1; ioctlsocket(fd, FIONBIO, &nonblock); #else int oldopts = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, oldopts | O_NONBLOCK); #endif } static inline int socket_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv) { #ifdef _WIN32 return win_select(max_fd, rfds, wfds, efds, tv); #else return select(max_fd, rfds, wfds, efds, tv); #endif } #ifndef HAVE_ELF_H typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Size; typedef Elf32_Off Elf32_Hashelt; typedef struct { unsigned char e_ident[16]; /* Magic number and other info */ Elf32_Half e_type; /* Object file type */ Elf32_Half e_machine; /* Architecture */ Elf32_Word e_version; /* Object file version */ Elf32_Addr e_entry; /* Entry point virtual address */ Elf32_Off e_phoff; /* Program header table file offset */ Elf32_Off e_shoff; /* Section header table file offset */ Elf32_Word e_flags; /* Processor-specific flags */ Elf32_Half e_ehsize; /* ELF header size in bytes */ Elf32_Half e_phentsize; /* Program header table entry size */ Elf32_Half e_phnum; /* Program header table entry count */ Elf32_Half e_shentsize; /* Section header table entry size */ Elf32_Half e_shnum; /* Section header table entry count */ Elf32_Half e_shstrndx; /* Section header string table index */ } Elf32_Ehdr; #define ELFMAG "\177ELF" #define SELFMAG 4 #define EI_CLASS 4 /* File class byte index */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encoding byte index */ #define ELFDATA2LSB 1 /* 2's complement, little endian */ #define ELFDATA2MSB 2 /* 2's complement, big endian */ typedef struct { Elf32_Word p_type; /* Segment type */ Elf32_Off p_offset; /* Segment file offset */ Elf32_Addr p_vaddr; /* Segment virtual address */ Elf32_Addr p_paddr; /* Segment physical address */ Elf32_Size p_filesz; /* Segment size in file */ Elf32_Size p_memsz; /* Segment size in memory */ Elf32_Word p_flags; /* Segment flags */ Elf32_Size p_align; /* Segment alignment */ } Elf32_Phdr; #define PT_LOAD 1 /* Loadable program segment */ #endif /* HAVE_ELF_H */ #if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME const char *libusb_error_name(int error_code); #endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */ #endif /* REPLACEMENTS_H */ openocd-0.9.0/src/helper/time_support_common.c0000644000175000017500000000440212315575360016413 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "time_support.h" /* simple and low overhead fetching of ms counter. Use only * the difference between ms counters returned from this fn. */ int64_t timeval_ms() { struct timeval now; int retval = gettimeofday(&now, NULL); if (retval < 0) return retval; return (int64_t)now.tv_sec * 1000 + now.tv_usec / 1000; } openocd-0.9.0/src/helper/log.c0000644000175000017500000003016212516456302013071 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "time_support.h" /* @todo the inclusion of server.h here is a layering violation */ #include #include #ifdef _DEBUG_FREE_SPACE_ #ifdef HAVE_MALLOC_H #include #else #error "malloc.h is required to use --enable-malloc-logging" #endif #endif int debug_level = -1; static FILE *log_output; static struct log_callback *log_callbacks; static long long last_time; static long long current_time; static long long start; static const char * const log_strings[5] = { "User : ", "Error: ", "Warn : ", /* want a space after each colon, all same width, colons aligned */ "Info : ", "Debug: " }; static int count; static struct store_log_forward *log_head; static int log_forward_count; struct store_log_forward { struct store_log_forward *next; const char *file; int line; const char *function; const char *string; }; /* either forward the log to the listeners or store it for possible forwarding later */ static void log_forward(const char *file, unsigned line, const char *function, const char *string) { if (log_forward_count == 0) { struct log_callback *cb, *next; cb = log_callbacks; /* DANGER!!!! the log callback can remove itself!!!! */ while (cb) { next = cb->next; cb->fn(cb->priv, file, line, function, string); cb = next; } } else { struct store_log_forward *log = malloc(sizeof(struct store_log_forward)); log->file = strdup(file); log->line = line; log->function = strdup(function); log->string = strdup(string); log->next = NULL; if (log_head == NULL) log_head = log; else { /* append to tail */ struct store_log_forward *t; t = log_head; while (t->next != NULL) t = t->next; t->next = log; } } } /* The log_puts() serves to somewhat different goals: * * - logging * - feeding low-level info to the user in GDB or Telnet * * The latter dictates that strings without newline are not logged, lest there * will be *MANY log lines when sending one char at the time(e.g. * target_request.c). * */ static void log_puts(enum log_levels level, const char *file, int line, const char *function, const char *string) { char *f; if (level == LOG_LVL_OUTPUT) { /* do not prepend any headers, just print out what we were given and return */ fputs(string, log_output); fflush(log_output); return; } f = strrchr(file, '/'); if (f != NULL) file = f + 1; if (strlen(string) > 0) { if (debug_level >= LOG_LVL_DEBUG) { /* print with count and time information */ int t = (int)(timeval_ms()-start); #ifdef _DEBUG_FREE_SPACE_ struct mallinfo info; info = mallinfo(); #endif fprintf(log_output, "%s%d %d %s:%d %s()" #ifdef _DEBUG_FREE_SPACE_ " %d" #endif ": %s", log_strings[level + 1], count, t, file, line, function, #ifdef _DEBUG_FREE_SPACE_ info.fordblks, #endif string); } else { /* if we are using gdb through pipes then we do not want any output * to the pipe otherwise we get repeated strings */ fprintf(log_output, "%s%s", (level > LOG_LVL_USER) ? log_strings[level + 1] : "", string); } } else { /* Empty strings are sent to log callbacks to keep e.g. gdbserver alive, here we do *nothing. */ } fflush(log_output); /* Never forward LOG_LVL_DEBUG, too verbose and they can be found in the log if need be */ if (level <= LOG_LVL_INFO) log_forward(file, line, function, string); } void log_printf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) { char *string; va_list ap; count++; if (level > debug_level) return; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { log_puts(level, file, line, function, string); free(string); } va_end(ap); } void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) { char *string; va_list ap; count++; if (level > debug_level) return; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one *char longer */ log_puts(level, file, line, function, string); free(string); } va_end(ap); } COMMAND_HANDLER(handle_debug_level_command) { if (CMD_ARGC == 1) { int new_level; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level); if ((new_level > LOG_LVL_DEBUG) || (new_level < LOG_LVL_SILENT)) { LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG); return ERROR_COMMAND_SYNTAX_ERROR; } debug_level = new_level; } else if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "debug_level: %i", debug_level); return ERROR_OK; } COMMAND_HANDLER(handle_log_output_command) { if (CMD_ARGC == 1) { FILE *file = fopen(CMD_ARGV[0], "w"); if (file) log_output = file; } return ERROR_OK; } static struct command_registration log_command_handlers[] = { { .name = "log_output", .handler = handle_log_output_command, .mode = COMMAND_ANY, .help = "redirect logging to a file (default: stderr)", .usage = "file_name", }, { .name = "debug_level", .handler = handle_debug_level_command, .mode = COMMAND_ANY, .help = "Sets the verbosity level of debugging output. " "0 shows errors only; 1 adds warnings; " "2 (default) adds other info; 3 adds debugging.", .usage = "number", }, COMMAND_REGISTRATION_DONE }; int log_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, log_command_handlers); } void log_init(void) { /* set defaults for daemon configuration, * if not set by cmdline or cfgfile */ if (debug_level == -1) debug_level = LOG_LVL_INFO; char *debug_env = getenv("OPENOCD_DEBUG_LEVEL"); if (NULL != debug_env) { int value; int retval = parse_int(debug_env, &value); if (ERROR_OK == retval && debug_level >= LOG_LVL_SILENT && debug_level <= LOG_LVL_DEBUG) debug_level = value; } if (log_output == NULL) log_output = stderr; start = last_time = timeval_ms(); } int set_log_output(struct command_context *cmd_ctx, FILE *output) { log_output = output; return ERROR_OK; } /* add/remove log callback handler */ int log_add_callback(log_callback_fn fn, void *priv) { struct log_callback *cb; /* prevent the same callback to be registered more than once, just for sure */ for (cb = log_callbacks; cb; cb = cb->next) { if (cb->fn == fn && cb->priv == priv) return ERROR_COMMAND_SYNTAX_ERROR; } /* alloc memory, it is safe just to return in case of an error, no need for the caller to *check this */ cb = malloc(sizeof(struct log_callback)); if (cb == NULL) return ERROR_BUF_TOO_SMALL; /* add item to the beginning of the linked list */ cb->fn = fn; cb->priv = priv; cb->next = log_callbacks; log_callbacks = cb; return ERROR_OK; } int log_remove_callback(log_callback_fn fn, void *priv) { struct log_callback *cb, **p; for (p = &log_callbacks; (cb = *p); p = &(*p)->next) { if (cb->fn == fn && cb->priv == priv) { *p = cb->next; free(cb); return ERROR_OK; } } /* no such item */ return ERROR_COMMAND_SYNTAX_ERROR; } /* return allocated string w/printf() result */ char *alloc_vprintf(const char *fmt, va_list ap) { va_list ap_copy; int len; char *string; /* determine the length of the buffer needed */ va_copy(ap_copy, ap); len = vsnprintf(NULL, 0, fmt, ap_copy); va_end(ap_copy); /* allocate and make room for terminating zero. */ /* FIXME: The old version always allocated at least one byte extra and * other code depend on that. They should be probably be fixed, but for * now reserve the extra byte. */ string = malloc(len + 2); if (string == NULL) return NULL; /* do the real work */ vsnprintf(string, len + 1, fmt, ap); return string; } char *alloc_printf(const char *format, ...) { char *string; va_list ap; va_start(ap, format); string = alloc_vprintf(format, ap); va_end(ap); return string; } /* Code must return to the server loop before 1000ms has returned or invoke * this function. * * The GDB connection will time out if it spends >2000ms and you'll get nasty * error messages from GDB: * * Ignoring packet error, continuing... * Reply contains invalid hex digit 116 * * While it is possible use "set remotetimeout" to more than the default 2000ms * in GDB, OpenOCD guarantees that it sends keep-alive packages on the * GDB protocol and it is a bug in OpenOCD not to either return to the server * loop or invoke keep_alive() every 1000ms. * * This function will send a keep alive packet if >500ms has passed since last time * it was invoked. * * Note that this function can be invoked often, so it needs to be relatively * fast when invoked more often than every 500ms. * */ void keep_alive() { current_time = timeval_ms(); if (current_time-last_time > 1000) { extern int gdb_actual_connections; if (gdb_actual_connections) LOG_WARNING("keep_alive() was not invoked in the " "1000ms timelimit. GDB alive packet not " "sent! (%lld). Workaround: increase " "\"set remotetimeout\" in GDB", current_time-last_time); else LOG_DEBUG("keep_alive() was not invoked in the " "1000ms timelimit (%lld). This may cause " "trouble with GDB connections.", current_time-last_time); } if (current_time-last_time > 500) { /* this will keep the GDB connection alive */ LOG_USER_N("%s", ""); /* DANGER!!!! do not add code to invoke e.g. target event processing, * jim timer processing, etc. it can cause infinite recursion + * jim event callbacks need to happen at a well defined time, * not anywhere keep_alive() is invoked. * * These functions should be invoked at a well defined spot in server.c */ last_time = current_time; } } /* reset keep alive timer without sending message */ void kept_alive() { current_time = timeval_ms(); last_time = current_time; } /* if we sleep for extended periods of time, we must invoke keep_alive() intermittantly */ void alive_sleep(uint64_t ms) { uint64_t napTime = 10; for (uint64_t i = 0; i < ms; i += napTime) { uint64_t sleep_a_bit = ms - i; if (sleep_a_bit > napTime) sleep_a_bit = napTime; usleep(sleep_a_bit * 1000); keep_alive(); } } void busy_sleep(uint64_t ms) { uint64_t then = timeval_ms(); while (timeval_ms() - then < ms) { /* * busy wait */ } } openocd-0.9.0/src/helper/log.h0000644000175000017500000001266212516456302013103 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ERROR_H #define ERROR_H #include /* To achieve C99 printf compatibility in MinGW, gnu_printf should be * used for __attribute__((format( ... ))), with GCC v4.4 or later */ #if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) #define PRINTF_ATTRIBUTE_FORMAT gnu_printf #else #define PRINTF_ATTRIBUTE_FORMAT printf #endif /* logging priorities * LOG_LVL_SILENT - turn off all output. In lieu of try + catch this can be used as a * feeble ersatz. * LOG_LVL_USER - user messages. Could be anything from information * to progress messags. These messages do not represent * incorrect or unexpected behaviour, just normal execution. * LOG_LVL_ERROR - fatal errors, that are likely to cause program abort * LOG_LVL_WARNING - non-fatal errors, that may be resolved later * LOG_LVL_INFO - state information, etc. * LOG_LVL_DEBUG - debug statements, execution trace */ enum log_levels { LOG_LVL_SILENT = -3, LOG_LVL_OUTPUT = -2, LOG_LVL_USER = -1, LOG_LVL_ERROR = 0, LOG_LVL_WARNING = 1, LOG_LVL_INFO = 2, LOG_LVL_DEBUG = 3 }; void log_printf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); /** * Initialize logging module. Call during program startup. */ void log_init(void); int set_log_output(struct command_context *cmd_ctx, FILE *output); int log_register_commands(struct command_context *cmd_ctx); void keep_alive(void); void kept_alive(void); void alive_sleep(uint64_t ms); void busy_sleep(uint64_t ms); typedef void (*log_callback_fn)(void *priv, const char *file, unsigned line, const char *function, const char *string); struct log_callback { log_callback_fn fn; void *priv; struct log_callback *next; }; int log_add_callback(log_callback_fn fn, void *priv); int log_remove_callback(log_callback_fn fn, void *priv); char *alloc_vprintf(const char *fmt, va_list ap); char *alloc_printf(const char *fmt, ...); extern int debug_level; /* Avoid fn call and building parameter list if we're not outputting the information. * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */ #define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO)) #define LOG_DEBUG(expr ...) \ do { \ if (debug_level >= LOG_LVL_DEBUG) \ log_printf_lf(LOG_LVL_DEBUG, \ __FILE__, __LINE__, __func__, \ expr); \ } while (0) #define LOG_INFO(expr ...) \ log_printf_lf(LOG_LVL_INFO, __FILE__, __LINE__, __func__, expr) #define LOG_WARNING(expr ...) \ log_printf_lf(LOG_LVL_WARNING, __FILE__, __LINE__, __func__, expr) #define LOG_ERROR(expr ...) \ log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr) #define LOG_USER(expr ...) \ log_printf_lf(LOG_LVL_USER, __FILE__, __LINE__, __func__, expr) #define LOG_USER_N(expr ...) \ log_printf(LOG_LVL_USER, __FILE__, __LINE__, __func__, expr) #define LOG_OUTPUT(expr ...) \ log_printf(LOG_LVL_OUTPUT, __FILE__, __LINE__, __func__, expr) /* general failures * error codes < 100 */ #define ERROR_OK (0) #define ERROR_NO_CONFIG_FILE (-2) #define ERROR_BUF_TOO_SMALL (-3) /* see "Error:" log entry for meaningful message to the user. The caller should * make no assumptions about what went wrong and try to handle the problem. */ #define ERROR_FAIL (-4) #define ERROR_WAIT (-5) #endif /* LOG_H */ openocd-0.9.0/src/helper/command.c0000644000175000017500000011552012516456302013730 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008, Duane Ellis * * openocd@duaneeellis.com * * * * part of this file is taken from libcli (libcli.sourceforge.net) * * Copyright (C) David Parrish (david@dparrish.com) * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* see Embedded-HOWTO.txt in Jim Tcl project hosted on BerliOS*/ #define JIM_EMBEDDED /* @todo the inclusion of target.h here is a layering violation */ #include #include #include "command.h" #include "configuration.h" #include "log.h" #include "time_support.h" #include "jim-eventloop.h" /* nice short description of source file */ #define __THIS__FILE__ "command.c" static int run_command(struct command_context *context, struct command *c, const char *words[], unsigned num_words); struct log_capture_state { Jim_Interp *interp; Jim_Obj *output; }; static void tcl_output(void *privData, const char *file, unsigned line, const char *function, const char *string) { struct log_capture_state *state = privData; Jim_AppendString(state->interp, state->output, string, strlen(string)); } static struct log_capture_state *command_log_capture_start(Jim_Interp *interp) { /* capture log output and return it. A garbage collect can * happen, so we need a reference count to this object */ Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); if (NULL == tclOutput) return NULL; struct log_capture_state *state = malloc(sizeof(*state)); if (NULL == state) return NULL; state->interp = interp; Jim_IncrRefCount(tclOutput); state->output = tclOutput; log_add_callback(tcl_output, state); return state; } /* Classic openocd commands provide progress output which we * will capture and return as a Tcl return value. * * However, if a non-openocd command has been invoked, then it * makes sense to return the tcl return value from that command. * * The tcl return value is empty for openocd commands that provide * progress output. * * Therefore we set the tcl return value only if we actually * captured output. */ static void command_log_capture_finish(struct log_capture_state *state) { if (NULL == state) return; log_remove_callback(tcl_output, state); int length; Jim_GetString(state->output, &length); if (length > 0) Jim_SetResult(state->interp, state->output); else { /* No output captured, use tcl return value (which could * be empty too). */ } Jim_DecrRefCount(state->interp, state->output); free(state); } static int command_retval_set(Jim_Interp *interp, int retval) { int *return_retval = Jim_GetAssocData(interp, "retval"); if (return_retval != NULL) *return_retval = retval; return (retval == ERROR_OK) ? JIM_OK : retval; } extern struct command_context *global_cmd_ctx; /* dump a single line to the log for the command. * Do nothing in case we are not at debug level 3 */ void script_debug(Jim_Interp *interp, const char *name, unsigned argc, Jim_Obj * const *argv) { if (debug_level < LOG_LVL_DEBUG) return; char *dbg = alloc_printf("command - %s", name); for (unsigned i = 0; i < argc; i++) { int len; const char *w = Jim_GetString(argv[i], &len); char *t = alloc_printf("%s %s", dbg, w); free(dbg); dbg = t; } LOG_DEBUG("%s", dbg); free(dbg); } static void script_command_args_free(char **words, unsigned nwords) { for (unsigned i = 0; i < nwords; i++) free(words[i]); free(words); } static char **script_command_args_alloc( unsigned argc, Jim_Obj * const *argv, unsigned *nwords) { char **words = malloc(argc * sizeof(char *)); if (NULL == words) return NULL; unsigned i; for (i = 0; i < argc; i++) { int len; const char *w = Jim_GetString(argv[i], &len); words[i] = strdup(w); if (words[i] == NULL) { script_command_args_free(words, i); return NULL; } } *nwords = i; return words; } struct command_context *current_command_context(Jim_Interp *interp) { /* grab the command context from the associated data */ struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context"); if (NULL == cmd_ctx) { /* Tcl can invoke commands directly instead of via command_run_line(). This would * happen when the Jim Tcl interpreter is provided by eCos or if we are running * commands in a startup script. * * A telnet or gdb server would provide a non-default command context to * handle piping of error output, have a separate current target, etc. */ cmd_ctx = global_cmd_ctx; } return cmd_ctx; } static int script_command_run(Jim_Interp *interp, int argc, Jim_Obj * const *argv, struct command *c, bool capture) { target_call_timer_callbacks_now(); LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ unsigned nwords; char **words = script_command_args_alloc(argc, argv, &nwords); if (NULL == words) return JIM_ERR; struct log_capture_state *state = NULL; if (capture) state = command_log_capture_start(interp); struct command_context *cmd_ctx = current_command_context(interp); int retval = run_command(cmd_ctx, c, (const char **)words, nwords); command_log_capture_finish(state); script_command_args_free(words, nwords); return command_retval_set(interp, retval); } static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* the private data is stashed in the interp structure */ struct command *c = interp->cmdPrivData; assert(c); script_debug(interp, c->name, argc, argv); return script_command_run(interp, argc, argv, c, true); } static struct command *command_root(struct command *c) { while (NULL != c->parent) c = c->parent; return c; } /** * Find a command by name from a list of commands. * @returns Returns the named command if it exists in the list. * Returns NULL otherwise. */ static struct command *command_find(struct command *head, const char *name) { for (struct command *cc = head; cc; cc = cc->next) { if (strcmp(cc->name, name) == 0) return cc; } return NULL; } struct command *command_find_in_context(struct command_context *cmd_ctx, const char *name) { return command_find(cmd_ctx->commands, name); } struct command *command_find_in_parent(struct command *parent, const char *name) { return command_find(parent->children, name); } /** * Add the command into the linked list, sorted by name. * @param head Address to head of command list pointer, which may be * updated if @c c gets inserted at the beginning of the list. * @param c The command to add to the list pointed to by @c head. */ static void command_add_child(struct command **head, struct command *c) { assert(head); if (NULL == *head) { *head = c; return; } while ((*head)->next && (strcmp(c->name, (*head)->name) > 0)) head = &(*head)->next; if (strcmp(c->name, (*head)->name) > 0) { c->next = (*head)->next; (*head)->next = c; } else { c->next = *head; *head = c; } } static struct command **command_list_for_parent( struct command_context *cmd_ctx, struct command *parent) { return parent ? &parent->children : &cmd_ctx->commands; } static void command_free(struct command *c) { /** @todo if command has a handler, unregister its jim command! */ while (NULL != c->children) { struct command *tmp = c->children; c->children = tmp->next; command_free(tmp); } free(c->name); free(c->help); free(c->usage); free(c); } static struct command *command_new(struct command_context *cmd_ctx, struct command *parent, const struct command_registration *cr) { assert(cr->name); /* * If it is a non-jim command with no .usage specified, * log an error. * * strlen(.usage) == 0 means that the command takes no * arguments. */ if ((cr->jim_handler == NULL) && (cr->usage == NULL)) { LOG_DEBUG("BUG: command '%s%s%s' does not have the " "'.usage' field filled out", parent && parent->name ? parent->name : "", parent && parent->name ? " " : "", cr->name); } struct command *c = calloc(1, sizeof(struct command)); if (NULL == c) return NULL; c->name = strdup(cr->name); if (cr->help) c->help = strdup(cr->help); if (cr->usage) c->usage = strdup(cr->usage); if (!c->name || (cr->help && !c->help) || (cr->usage && !c->usage)) goto command_new_error; c->parent = parent; c->handler = cr->handler; c->jim_handler = cr->jim_handler; c->jim_handler_data = cr->jim_handler_data; c->mode = cr->mode; command_add_child(command_list_for_parent(cmd_ctx, parent), c); return c; command_new_error: command_free(c); return NULL; } static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv); static int register_command_handler(struct command_context *cmd_ctx, struct command *c) { Jim_Interp *interp = cmd_ctx->interp; char *ocd_name = alloc_printf("ocd_%s", c->name); if (NULL == ocd_name) return JIM_ERR; LOG_DEBUG("registering '%s'...", ocd_name); Jim_CmdProc *func = c->handler ? &script_command : &command_unknown; int retval = Jim_CreateCommand(interp, ocd_name, func, c, NULL); free(ocd_name); if (JIM_OK != retval) return retval; /* we now need to add an overrideable proc */ char *override_name = alloc_printf( "proc %s {args} {eval ocd_bouncer %s $args}", c->name, c->name); if (NULL == override_name) return JIM_ERR; retval = Jim_Eval_Named(interp, override_name, 0, 0); free(override_name); return retval; } struct command *register_command(struct command_context *context, struct command *parent, const struct command_registration *cr) { if (!context || !cr->name) return NULL; const char *name = cr->name; struct command **head = command_list_for_parent(context, parent); struct command *c = command_find(*head, name); if (NULL != c) { /* TODO: originally we treated attempting to register a cmd twice as an error * Sometimes we need this behaviour, such as with flash banks. * http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */ LOG_DEBUG("command '%s' is already registered in '%s' context", name, parent ? parent->name : ""); return c; } c = command_new(context, parent, cr); if (NULL == c) return NULL; int retval = ERROR_OK; if (NULL != cr->jim_handler && NULL == parent) { retval = Jim_CreateCommand(context->interp, cr->name, cr->jim_handler, cr->jim_handler_data, NULL); } else if (NULL != cr->handler || NULL != parent) retval = register_command_handler(context, command_root(c)); if (ERROR_OK != retval) { unregister_command(context, parent, name); c = NULL; } return c; } int register_commands(struct command_context *cmd_ctx, struct command *parent, const struct command_registration *cmds) { int retval = ERROR_OK; unsigned i; for (i = 0; cmds[i].name || cmds[i].chain; i++) { const struct command_registration *cr = cmds + i; struct command *c = NULL; if (NULL != cr->name) { c = register_command(cmd_ctx, parent, cr); if (NULL == c) { retval = ERROR_FAIL; break; } } if (NULL != cr->chain) { struct command *p = c ? : parent; retval = register_commands(cmd_ctx, p, cr->chain); if (ERROR_OK != retval) break; } } if (ERROR_OK != retval) { for (unsigned j = 0; j < i; j++) unregister_command(cmd_ctx, parent, cmds[j].name); } return retval; } int unregister_all_commands(struct command_context *context, struct command *parent) { if (context == NULL) return ERROR_OK; struct command **head = command_list_for_parent(context, parent); while (NULL != *head) { struct command *tmp = *head; *head = tmp->next; command_free(tmp); } return ERROR_OK; } int unregister_command(struct command_context *context, struct command *parent, const char *name) { if ((!context) || (!name)) return ERROR_COMMAND_SYNTAX_ERROR; struct command *p = NULL; struct command **head = command_list_for_parent(context, parent); for (struct command *c = *head; NULL != c; p = c, c = c->next) { if (strcmp(name, c->name) != 0) continue; if (p) p->next = c->next; else *head = c->next; command_free(c); return ERROR_OK; } return ERROR_OK; } void command_set_handler_data(struct command *c, void *p) { if (NULL != c->handler || NULL != c->jim_handler) c->jim_handler_data = p; for (struct command *cc = c->children; NULL != cc; cc = cc->next) command_set_handler_data(cc, p); } void command_output_text(struct command_context *context, const char *data) { if (context && context->output_handler && data) context->output_handler(context, data); } void command_print_sameline(struct command_context *context, const char *format, ...) { char *string; va_list ap; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { /* we want this collected in the log + we also want to pick it up as a tcl return * value. * * The latter bit isn't precisely neat, but will do for now. */ LOG_USER_N("%s", string); /* We already printed it above * command_output_text(context, string); */ free(string); } va_end(ap); } void command_print(struct command_context *context, const char *format, ...) { char *string; va_list ap; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one *char longer */ /* we want this collected in the log + we also want to pick it up as a tcl return * value. * * The latter bit isn't precisely neat, but will do for now. */ LOG_USER_N("%s", string); /* We already printed it above * command_output_text(context, string); */ free(string); } va_end(ap); } static char *__command_name(struct command *c, char delim, unsigned extra) { char *name; unsigned len = strlen(c->name); if (NULL == c->parent) { /* allocate enough for the name, child names, and '\0' */ name = malloc(len + extra + 1); strcpy(name, c->name); } else { /* parent's extra must include both the space and name */ name = __command_name(c->parent, delim, 1 + len + extra); char dstr[2] = { delim, 0 }; strcat(name, dstr); strcat(name, c->name); } return name; } char *command_name(struct command *c, char delim) { return __command_name(c, delim, 0); } static bool command_can_run(struct command_context *cmd_ctx, struct command *c) { return c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode; } static int run_command(struct command_context *context, struct command *c, const char *words[], unsigned num_words) { if (!command_can_run(context, c)) { /* Many commands may be run only before/after 'init' */ const char *when; switch (c->mode) { case COMMAND_CONFIG: when = "before"; break; case COMMAND_EXEC: when = "after"; break; /* handle the impossible with humor; it guarantees a bug report! */ default: when = "if Cthulhu is summoned by"; break; } LOG_ERROR("The '%s' command must be used %s 'init'.", c->name, when); return ERROR_FAIL; } struct command_invocation cmd = { .ctx = context, .current = c, .name = c->name, .argc = num_words - 1, .argv = words + 1, }; int retval = c->handler(&cmd); if (retval == ERROR_COMMAND_SYNTAX_ERROR) { /* Print help for command */ char *full_name = command_name(c, ' '); if (NULL != full_name) { command_run_linef(context, "usage %s", full_name); free(full_name); } else retval = -ENOMEM; } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) { /* just fall through for a shutdown request */ } else if (retval != ERROR_OK) { /* we do not print out an error message because the command *should* * have printed out an error */ LOG_DEBUG("Command failed with error code %d", retval); } return retval; } int command_run_line(struct command_context *context, char *line) { /* all the parent commands have been registered with the interpreter * so, can just evaluate the line as a script and check for * results */ /* run the line thru a script engine */ int retval = ERROR_FAIL; int retcode; /* Beware! This code needs to be reentrant. It is also possible * for OpenOCD commands to be invoked directly from Tcl. This would * happen when the Jim Tcl interpreter is provided by eCos for * instance. */ Jim_Interp *interp = context->interp; Jim_DeleteAssocData(interp, "context"); retcode = Jim_SetAssocData(interp, "context", NULL, context); if (retcode == JIM_OK) { /* associated the return value */ Jim_DeleteAssocData(interp, "retval"); retcode = Jim_SetAssocData(interp, "retval", NULL, &retval); if (retcode == JIM_OK) { retcode = Jim_Eval_Named(interp, line, 0, 0); Jim_DeleteAssocData(interp, "retval"); } Jim_DeleteAssocData(interp, "context"); } if (retcode == JIM_OK) { const char *result; int reslen; result = Jim_GetString(Jim_GetResult(interp), &reslen); if (reslen > 0) { int i; char buff[256 + 1]; for (i = 0; i < reslen; i += 256) { int chunk; chunk = reslen - i; if (chunk > 256) chunk = 256; strncpy(buff, result + i, chunk); buff[chunk] = 0; LOG_USER_N("%s", buff); } LOG_USER_N("\n"); } retval = ERROR_OK; } else if (retcode == JIM_EXIT) { /* ignore. * exit(Jim_GetExitCode(interp)); */ } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) { return retcode; } else { Jim_MakeErrorMessage(interp); LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL)); if (retval == ERROR_OK) { /* It wasn't a low level OpenOCD command that failed */ return ERROR_FAIL; } return retval; } return retval; } int command_run_linef(struct command_context *context, const char *format, ...) { int retval = ERROR_FAIL; char *string; va_list ap; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { retval = command_run_line(context, string); free(string); } va_end(ap); return retval; } void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv) { context->output_handler = output_handler; context->output_handler_priv = priv; } struct command_context *copy_command_context(struct command_context *context) { struct command_context *copy_context = malloc(sizeof(struct command_context)); *copy_context = *context; return copy_context; } void command_done(struct command_context *cmd_ctx) { if (NULL == cmd_ctx) return; free(cmd_ctx); } /* find full path to file */ static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2) return JIM_ERR; const char *file = Jim_GetString(argv[1], NULL); char *full_path = find_file(file); if (full_path == NULL) return JIM_ERR; Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path)); free(full_path); Jim_SetResult(interp, result); return JIM_OK; } COMMAND_HANDLER(jim_echo) { if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) { LOG_USER_N("%s", CMD_ARGV[1]); return JIM_OK; } if (CMD_ARGC != 1) return JIM_ERR; LOG_USER("%s", CMD_ARGV[0]); return JIM_OK; } /* Capture progress output and return as tcl return value. If the * progress output was empty, return tcl return value. */ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2) return JIM_ERR; struct log_capture_state *state = command_log_capture_start(interp); /* disable polling during capture. This avoids capturing output * from polling. * * This is necessary in order to avoid accidentally getting a non-empty * string for tcl fn's. */ bool save_poll = jtag_poll_get_enabled(); jtag_poll_set_enabled(false); const char *str = Jim_GetString(argv[1], NULL); int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); jtag_poll_set_enabled(save_poll); command_log_capture_finish(state); return retcode; } static COMMAND_HELPER(command_help_find, struct command *head, struct command **out) { if (0 == CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; *out = command_find(head, CMD_ARGV[0]); if (NULL == *out && strncmp(CMD_ARGV[0], "ocd_", 4) == 0) *out = command_find(head, CMD_ARGV[0] + 4); if (NULL == *out) return ERROR_COMMAND_SYNTAX_ERROR; if (--CMD_ARGC == 0) return ERROR_OK; CMD_ARGV++; return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out); } static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, bool show_help, const char *cmd_match); static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n, bool show_help, const char *cmd_match) { for (struct command *c = head; NULL != c; c = c->next) CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, cmd_match); return ERROR_OK; } #define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n)) static void command_help_show_indent(unsigned n) { for (unsigned i = 0; i < n; i++) LOG_USER_N(" "); } static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) { const char *cp = str, *last = str; while (*cp) { const char *next = last; do { cp = next; do { next++; } while (*next != ' ' && *next != '\t' && *next != '\0'); } while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0'); if (next - last < HELP_LINE_WIDTH(n)) cp = next; command_help_show_indent(n); LOG_USER("%.*s", (int)(cp - last), last); last = cp + 1; n = n2; } } static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, bool show_help, const char *cmd_match) { char *cmd_name = command_name(c, ' '); if (NULL == cmd_name) return -ENOMEM; /* If the match string occurs anywhere, we print out * stuff for this command. */ bool is_match = (strstr(cmd_name, cmd_match) != NULL) || ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) || ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL)); if (is_match) { command_help_show_indent(n); LOG_USER_N("%s", cmd_name); } free(cmd_name); if (is_match) { if (c->usage && strlen(c->usage) > 0) { LOG_USER_N(" "); command_help_show_wrap(c->usage, 0, n + 5); } else LOG_USER_N("\n"); } if (is_match && show_help) { char *msg; /* Normal commands are runtime-only; highlight exceptions */ if (c->mode != COMMAND_EXEC) { const char *stage_msg = ""; switch (c->mode) { case COMMAND_CONFIG: stage_msg = " (configuration command)"; break; case COMMAND_ANY: stage_msg = " (command valid any time)"; break; default: stage_msg = " (?mode error?)"; break; } msg = alloc_printf("%s%s", c->help ? : "", stage_msg); } else msg = alloc_printf("%s", c->help ? : ""); if (NULL != msg) { command_help_show_wrap(msg, n + 3, n + 3); free(msg); } else return -ENOMEM; } if (++n > 5) { LOG_ERROR("command recursion exceeded"); return ERROR_FAIL; } return CALL_COMMAND_HANDLER(command_help_show_list, c->children, n, show_help, cmd_match); } COMMAND_HANDLER(handle_help_command) { bool full = strcmp(CMD_NAME, "help") == 0; int retval; struct command *c = CMD_CTX->commands; char *cmd_match = NULL; if (CMD_ARGC == 0) cmd_match = ""; else if (CMD_ARGC >= 1) { unsigned i; for (i = 0; i < CMD_ARGC; ++i) { if (NULL != cmd_match) { char *prev = cmd_match; cmd_match = alloc_printf("%s %s", cmd_match, CMD_ARGV[i]); free(prev); if (NULL == cmd_match) { LOG_ERROR("unable to build search string"); return -ENOMEM; } } else { cmd_match = alloc_printf("%s", CMD_ARGV[i]); if (NULL == cmd_match) { LOG_ERROR("unable to build search string"); return -ENOMEM; } } } } else return ERROR_COMMAND_SYNTAX_ERROR; retval = CALL_COMMAND_HANDLER(command_help_show_list, c, 0, full, cmd_match); if (CMD_ARGC >= 1) free(cmd_match); return retval; } static int command_unknown_find(unsigned argc, Jim_Obj *const *argv, struct command *head, struct command **out, bool top_level) { if (0 == argc) return argc; const char *cmd_name = Jim_GetString(argv[0], NULL); struct command *c = command_find(head, cmd_name); if (NULL == c && top_level && strncmp(cmd_name, "ocd_", 4) == 0) c = command_find(head, cmd_name + 4); if (NULL == c) return argc; *out = c; return command_unknown_find(--argc, ++argv, (*out)->children, out, false); } static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); if (strcmp(cmd_name, "unknown") == 0) { if (argc == 1) return JIM_OK; argc--; argv++; } script_debug(interp, cmd_name, argc, argv); struct command_context *cmd_ctx = current_command_context(interp); struct command *c = cmd_ctx->commands; int remaining = command_unknown_find(argc, argv, c, &c, true); /* if nothing could be consumed, then it's really an unknown command */ if (remaining == argc) { const char *cmd = Jim_GetString(argv[0], NULL); LOG_ERROR("Unknown command:\n %s", cmd); return JIM_OK; } bool found = true; Jim_Obj *const *start; unsigned count; if (c->handler || c->jim_handler) { /* include the command name in the list */ count = remaining + 1; start = argv + (argc - remaining - 1); } else { c = command_find(cmd_ctx->commands, "usage"); if (NULL == c) { LOG_ERROR("unknown command, but usage is missing too"); return JIM_ERR; } count = argc - remaining; start = argv; found = false; } /* pass the command through to the intended handler */ if (c->jim_handler) { interp->cmdPrivData = c->jim_handler_data; return (*c->jim_handler)(interp, count, start); } return script_command_run(interp, count, start, c, found); } static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *cmd_ctx = current_command_context(interp); enum command_mode mode; if (argc > 1) { struct command *c = cmd_ctx->commands; int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true); /* if nothing could be consumed, then it's an unknown command */ if (remaining == argc - 1) { Jim_SetResultString(interp, "unknown", -1); return JIM_OK; } mode = c->mode; } else mode = cmd_ctx->mode; const char *mode_str; switch (mode) { case COMMAND_ANY: mode_str = "any"; break; case COMMAND_CONFIG: mode_str = "config"; break; case COMMAND_EXEC: mode_str = "exec"; break; default: mode_str = "unknown"; break; } Jim_SetResultString(interp, mode_str, -1); return JIM_OK; } static int jim_command_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (1 == argc) return JIM_ERR; struct command_context *cmd_ctx = current_command_context(interp); struct command *c = cmd_ctx->commands; int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true); /* if nothing could be consumed, then it's an unknown command */ if (remaining == argc - 1) { Jim_SetResultString(interp, "unknown", -1); return JIM_OK; } if (c->jim_handler) Jim_SetResultString(interp, "native", -1); else if (c->handler) Jim_SetResultString(interp, "simple", -1); else if (remaining == 0) Jim_SetResultString(interp, "group", -1); else Jim_SetResultString(interp, "unknown", -1); return JIM_OK; } int help_add_command(struct command_context *cmd_ctx, struct command *parent, const char *cmd_name, const char *help_text, const char *usage) { struct command **head = command_list_for_parent(cmd_ctx, parent); struct command *nc = command_find(*head, cmd_name); if (NULL == nc) { /* add a new command with help text */ struct command_registration cr = { .name = cmd_name, .mode = COMMAND_ANY, .help = help_text, .usage = usage, }; nc = register_command(cmd_ctx, parent, &cr); if (NULL == nc) { LOG_ERROR("failed to add '%s' help text", cmd_name); return ERROR_FAIL; } LOG_DEBUG("added '%s' help text", cmd_name); return ERROR_OK; } if (help_text) { bool replaced = false; if (nc->help) { free(nc->help); replaced = true; } nc->help = strdup(help_text); if (replaced) LOG_INFO("replaced existing '%s' help", cmd_name); else LOG_DEBUG("added '%s' help text", cmd_name); } if (usage) { bool replaced = false; if (nc->usage) { free(nc->usage); replaced = true; } nc->usage = strdup(usage); if (replaced) LOG_INFO("replaced existing '%s' usage", cmd_name); else LOG_DEBUG("added '%s' usage text", cmd_name); } return ERROR_OK; } COMMAND_HANDLER(handle_help_add_command) { if (CMD_ARGC < 2) { LOG_ERROR("%s: insufficient arguments", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } /* save help text and remove it from argument list */ const char *str = CMD_ARGV[--CMD_ARGC]; const char *help = !strcmp(CMD_NAME, "add_help_text") ? str : NULL; const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? str : NULL; if (!help && !usage) { LOG_ERROR("command name '%s' is unknown", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } /* likewise for the leaf command name */ const char *cmd_name = CMD_ARGV[--CMD_ARGC]; struct command *c = NULL; if (CMD_ARGC > 0) { c = CMD_CTX->commands; int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c); if (ERROR_OK != retval) return retval; } return help_add_command(CMD_CTX, c, cmd_name, help, usage); } /* sleep command sleeps for milliseconds * this is useful in target startup scripts */ COMMAND_HANDLER(handle_sleep_command) { bool busy = false; if (CMD_ARGC == 2) { if (strcmp(CMD_ARGV[1], "busy") == 0) busy = true; else return ERROR_COMMAND_SYNTAX_ERROR; } else if (CMD_ARGC < 1 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; unsigned long duration = 0; int retval = parse_ulong(CMD_ARGV[0], &duration); if (ERROR_OK != retval) return retval; if (!busy) { long long then = timeval_ms(); while (timeval_ms() - then < (long long)duration) { target_call_timer_callbacks_now(); usleep(1000); } } else busy_sleep(duration); return ERROR_OK; } static const struct command_registration command_subcommand_handlers[] = { { .name = "mode", .mode = COMMAND_ANY, .jim_handler = jim_command_mode, .usage = "[command_name ...]", .help = "Returns the command modes allowed by a command:" "'any', 'config', or 'exec'. If no command is" "specified, returns the current command mode. " "Returns 'unknown' if an unknown command is given. " "Command can be multiple tokens.", }, { .name = "type", .mode = COMMAND_ANY, .jim_handler = jim_command_type, .usage = "command_name [...]", .help = "Returns the type of built-in command:" "'native', 'simple', 'group', or 'unknown'. " "Command can be multiple tokens.", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration command_builtin_handlers[] = { { .name = "echo", .handler = jim_echo, .mode = COMMAND_ANY, .help = "Logs a message at \"user\" priority. " "Output message to stdout. " "Option \"-n\" suppresses trailing newline", .usage = "[-n] string", }, { .name = "add_help_text", .handler = handle_help_add_command, .mode = COMMAND_ANY, .help = "Add new command help text; " "Command can be multiple tokens.", .usage = "command_name helptext_string", }, { .name = "add_usage_text", .handler = handle_help_add_command, .mode = COMMAND_ANY, .help = "Add new command usage text; " "command can be multiple tokens.", .usage = "command_name usage_string", }, { .name = "sleep", .handler = handle_sleep_command, .mode = COMMAND_ANY, .help = "Sleep for specified number of milliseconds. " "\"busy\" will busy wait instead (avoid this).", .usage = "milliseconds ['busy']", }, { .name = "help", .handler = handle_help_command, .mode = COMMAND_ANY, .help = "Show full command help; " "command can be multiple tokens.", .usage = "[command_name]", }, { .name = "usage", .handler = handle_help_command, .mode = COMMAND_ANY, .help = "Show basic command usage; " "command can be multiple tokens.", .usage = "[command_name]", }, { .name = "command", .mode = COMMAND_ANY, .help = "core command group (introspection)", .chain = command_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp) { struct command_context *context = malloc(sizeof(struct command_context)); const char *HostOs; context->mode = COMMAND_EXEC; context->commands = NULL; context->current_target = 0; context->output_handler = NULL; context->output_handler_priv = NULL; /* Create a jim interpreter if we were not handed one */ if (interp == NULL) { /* Create an interpreter */ interp = Jim_CreateInterp(); /* Add all the Jim core commands */ Jim_RegisterCoreCommands(interp); Jim_InitStaticExtensions(interp); } context->interp = interp; /* Stick to lowercase for HostOS strings. */ #if defined(_MSC_VER) /* WinXX - is generic, the forward * looking problem is this: * * "win32" or "win64" * * "winxx" is generic. */ HostOs = "winxx"; #elif defined(__linux__) HostOs = "linux"; #elif defined(__APPLE__) || defined(__DARWIN__) HostOs = "darwin"; #elif defined(__CYGWIN__) HostOs = "cygwin"; #elif defined(__MINGW32__) HostOs = "mingw32"; #elif defined(__ECOS) HostOs = "ecos"; #elif defined(__FreeBSD__) HostOs = "freebsd"; #elif defined(__NetBSD__) HostOs = "netbsd"; #elif defined(__OpenBSD__) HostOs = "openbsd"; #else #warning "Unrecognized host OS..." HostOs = "other"; #endif Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS", Jim_NewStringObj(interp, HostOs, strlen(HostOs))); Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL); Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL); register_commands(context, NULL, command_builtin_handlers); Jim_SetAssocData(interp, "context", NULL, context); if (Jim_Eval_Named(interp, startup_tcl, "embedded:startup.tcl", 1) == JIM_ERR) { LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD)"); Jim_MakeErrorMessage(interp); LOG_USER_N("%s", Jim_GetString(Jim_GetResult(interp), NULL)); exit(-1); } Jim_DeleteAssocData(interp, "context"); return context; } int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode) { if (!cmd_ctx) return ERROR_COMMAND_SYNTAX_ERROR; cmd_ctx->mode = mode; return ERROR_OK; } void process_jim_events(struct command_context *cmd_ctx) { static int recursion; if (recursion) return; recursion++; Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT); recursion--; } #define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \ int parse ## name(const char *str, type * ul) \ { \ if (!*str) { \ LOG_ERROR("Invalid command argument"); \ return ERROR_COMMAND_ARGUMENT_INVALID; \ } \ char *end; \ *ul = func(str, &end, 0); \ if (*end) { \ LOG_ERROR("Invalid command argument"); \ return ERROR_COMMAND_ARGUMENT_INVALID; \ } \ if ((max == *ul) && (ERANGE == errno)) { \ LOG_ERROR("Argument overflow"); \ return ERROR_COMMAND_ARGUMENT_OVERFLOW; \ } \ if (min && (min == *ul) && (ERANGE == errno)) { \ LOG_ERROR("Argument underflow"); \ return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \ } \ return ERROR_OK; \ } DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long, strtoul, 0, ULONG_MAX) DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX) DEFINE_PARSE_NUM_TYPE(_long, long, strtol, LONG_MIN, LONG_MAX) DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX) #define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \ int parse ## name(const char *str, type * ul) \ { \ functype n; \ int retval = parse ## funcname(str, &n); \ if (ERROR_OK != retval) \ return retval; \ if (n > max) \ return ERROR_COMMAND_ARGUMENT_OVERFLOW; \ if (min) \ return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \ *ul = n; \ return ERROR_OK; \ } #define DEFINE_PARSE_ULONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong) DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX) DEFINE_PARSE_ULONGLONG(_u64, uint64_t, 0, UINT64_MAX) DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX) #define DEFINE_PARSE_LONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong) DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX) DEFINE_PARSE_LONGLONG(_s64, int64_t, n < INT64_MIN, INT64_MAX) DEFINE_PARSE_LONGLONG(_s32, int32_t, n < INT32_MIN, INT32_MAX) DEFINE_PARSE_LONGLONG(_s16, int16_t, n < INT16_MIN, INT16_MAX) DEFINE_PARSE_LONGLONG(_s8, int8_t, n < INT8_MIN, INT8_MAX) static int command_parse_bool(const char *in, bool *out, const char *on, const char *off) { if (strcasecmp(in, on) == 0) *out = true; else if (strcasecmp(in, off) == 0) *out = false; else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } int command_parse_bool_arg(const char *in, bool *out) { if (command_parse_bool(in, out, "on", "off") == ERROR_OK) return ERROR_OK; if (command_parse_bool(in, out, "enable", "disable") == ERROR_OK) return ERROR_OK; if (command_parse_bool(in, out, "true", "false") == ERROR_OK) return ERROR_OK; if (command_parse_bool(in, out, "yes", "no") == ERROR_OK) return ERROR_OK; if (command_parse_bool(in, out, "1", "0") == ERROR_OK) return ERROR_OK; return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label) { switch (CMD_ARGC) { case 1: { const char *in = CMD_ARGV[0]; if (command_parse_bool_arg(in, out) != ERROR_OK) { LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in); return ERROR_COMMAND_SYNTAX_ERROR; } /* fall through */ } case 0: LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled"); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } openocd-0.9.0/src/helper/command.h0000644000175000017500000004004012516456302013727 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef COMMAND_H #define COMMAND_H #include /* To achieve C99 printf compatibility in MinGW, gnu_printf should be * used for __attribute__((format( ... ))), with GCC v4.4 or later */ #if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) #define PRINTF_ATTRIBUTE_FORMAT gnu_printf #else #define PRINTF_ATTRIBUTE_FORMAT printf #endif enum command_mode { COMMAND_EXEC, COMMAND_CONFIG, COMMAND_ANY, }; struct command_context; /** The type signature for command context's output handler. */ typedef int (*command_output_handler_t)(struct command_context *context, const char *line); struct command_context { Jim_Interp *interp; enum command_mode mode; struct command *commands; int current_target; command_output_handler_t output_handler; void *output_handler_priv; }; struct command; /** * When run_command is called, a new instance will be created on the * stack, filled with the proper values, and passed by reference to the * required COMMAND_HANDLER routine. */ struct command_invocation { struct command_context *ctx; struct command *current; const char *name; unsigned argc; const char **argv; }; /** * Command handlers may be defined with more parameters than the base * set provided by command.c. This macro uses C99 magic to allow * defining all such derivative types using this macro. */ #define __COMMAND_HANDLER(name, extra ...) \ int name(struct command_invocation *cmd, ## extra) /** * Use this to macro to call a command helper (or a nested handler). * It provides command handler authors protection against reordering or * removal of unused parameters. * * @b Note: This macro uses lexical capture to provide some arguments. * As a result, this macro should be used @b only within functions * defined by the COMMAND_HANDLER or COMMAND_HELPER macros. Those * macros provide the expected lexical context captured by this macro. * Furthermore, it should be used only from the top-level of handler or * helper function, or care must be taken to avoid redefining the same * variables in intervening scope(s) by accident. */ #define CALL_COMMAND_HANDLER(name, extra ...) \ name(cmd, ## extra) /** * Always use this macro to define new command handler functions. * It ensures the parameters are ordered, typed, and named properly, so * they be can be used by other macros (e.g. COMMAND_PARSE_NUMBER). * All command handler functions must be defined as static in scope. */ #define COMMAND_HANDLER(name) \ static __COMMAND_HANDLER(name) /** * Similar to COMMAND_HANDLER, except some parameters are expected. * A helper is globally-scoped because it may be shared between several * source files (e.g. the s3c24xx device command helper). */ #define COMMAND_HELPER(name, extra ...) __COMMAND_HANDLER(name, extra) /** * Use this macro to access the context of the command being handled, * rather than accessing the variable directly. It may be moved. */ #define CMD_CTX (cmd->ctx) /** * Use this macro to access the number of arguments for the command being * handled, rather than accessing the variable directly. It may be moved. */ #define CMD_ARGC (cmd->argc) /** * Use this macro to access the arguments for the command being handled, * rather than accessing the variable directly. It may be moved. */ #define CMD_ARGV (cmd->argv) /** * Use this macro to access the name of the command being handled, * rather than accessing the variable directly. It may be moved. */ #define CMD_NAME (cmd->name) /** * Use this macro to access the current command being handled, * rather than accessing the variable directly. It may be moved. */ #define CMD_CURRENT (cmd->current) /** * Use this macro to access the invoked command handler's data pointer, * rather than accessing the variable directly. It may be moved. */ #define CMD_DATA (CMD_CURRENT->jim_handler_data) /** * The type signature for command handling functions. They are * usually registered as part of command_registration, providing * a high-level means for executing a command. * * If the command fails, it *MUST* return a value != ERROR_OK * (many commands break this rule, patches welcome!) * * This is *especially* important for commands such as writing * to flash or verifying memory. The reason is that those commands * can be used by programs to determine if the operation succeded * or not. If the operation failed, then a program can try * an alternative approach. * * Returning ERROR_COMMAND_SYNTAX_ERROR will have the effect of * printing out the syntax of the command. */ typedef __COMMAND_HANDLER((*command_handler_t)); struct command { char *name; char *help; char *usage; struct command *parent; struct command *children; command_handler_t handler; Jim_CmdProc *jim_handler; void *jim_handler_data; enum command_mode mode; struct command *next; }; /** * @param c The command to be named. * @param delim The character to place between command names. * @returns A malloc'd string containing the full command name, * which may include one or more ancestor components. Multiple names * are separated by single spaces. The caller must free() the string * when done with it. */ char *command_name(struct command *c, char delim); /* * Commands should be registered by filling in one or more of these * structures and passing them to register_command(). * * A conventioal format should be used for help strings, to provide both * usage and basic information: * @code * "@ ... - some explanation text" * @endcode * * @param name The name of the command to register, which must not have * been registered previously in the intended context. * @param handler The callback function that will be called. If NULL, * then the command serves as a placeholder for its children or a script. * @param mode The command mode(s) in which this command may be run. * @param help The help text that will be displayed to the user. */ struct command_registration { const char *name; command_handler_t handler; Jim_CmdProc *jim_handler; void *jim_handler_data; enum command_mode mode; const char *help; /** a string listing the options and arguments, required or optional */ const char *usage; /** * If non-NULL, the commands in @c chain will be registered in * the same context and scope of this registration record. * This allows modules to inherit lists commands from other * modules. */ const struct command_registration *chain; }; /** Use this as the last entry in an array of command_registration records. */ #define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL } /** * Register a command @c handler that can be called from scripts during * the execution @c mode specified. * * If @c parent is non-NULL, the new command will be registered as a * sub-command under it; otherwise, it will be available as a top-level * command. * * @param cmd_ctx The command_context in which to register the command. * @param parent Register this command as a child of this, or NULL to * register a top-level command. * @param rec A command_registration record that contains the desired * command parameters. * @returns The new command, if successful; otherwise, NULL. */ struct command *register_command(struct command_context *cmd_ctx, struct command *parent, const struct command_registration *rec); /** * Register one or more commands in the specified context, as children * of @c parent (or top-level commends, if NULL). In a registration's * record contains a non-NULL @c chain member and name is NULL, the * commands on the chain will be registered in the same context. * Otherwise, the chained commands are added as children of the command. * * @param cmd_ctx The command_context in which to register the command. * @param parent Register this command as a child of this, or NULL to * register a top-level command. * @param cmds Pointer to an array of command_registration records that * contains the desired command parameters. The last record must have * NULL for all fields. * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ int register_commands(struct command_context *cmd_ctx, struct command *parent, const struct command_registration *cmds); /** * Unregisters command @c name from the given context, @c cmd_ctx. * @param cmd_ctx The context of the registered command. * @param parent The parent of the given command, or NULL. * @param name The name of the command to unregister. * @returns ERROR_OK on success, or an error code. */ int unregister_command(struct command_context *cmd_ctx, struct command *parent, const char *name); /** * Unregisters all commands from the specfied context. * @param cmd_ctx The context that will be cleared of registered commands. * @param parent If given, only clear commands from under this one command. * @returns ERROR_OK on success, or an error code. */ int unregister_all_commands(struct command_context *cmd_ctx, struct command *parent); struct command *command_find_in_context(struct command_context *cmd_ctx, const char *name); struct command *command_find_in_parent(struct command *parent, const char *name); /** * Update the private command data field for a command and all descendents. * This is used when creating a new heirarchy of commands that depends * on obtaining a dynamically created context. The value will be available * in command handlers by using the CMD_DATA macro. * @param c The command (group) whose data pointer(s) will be updated. * @param p The new data pointer to use for the command or its descendents. */ void command_set_handler_data(struct command *c, void *p); void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv); int command_context_mode(struct command_context *context, enum command_mode mode); /* Return the current command context associated with the Jim interpreter or * alternatively the global default command interpreter */ struct command_context *current_command_context(Jim_Interp *interp); /** * Creates a new command context using the startup TCL provided and * the existing Jim interpreter, if any. If interp == NULL, then command_init * creates a command interpreter. */ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp); /** * Creates a copy of an existing command context. This does not create * a deep copy of the command list, so modifications in one context will * affect all shared contexts. The caller must track reference counting * and ensure the commands are freed before destroying the last instance. * @param cmd_ctx The command_context that will be copied. * @returns A new command_context with the same state as the original. */ struct command_context *copy_command_context(struct command_context *cmd_ctx); /** * Frees the resources associated with a command context. The commands * are not removed, so unregister_all_commands() must be called first. * @param context The command_context that will be destroyed. */ void command_done(struct command_context *context); void command_print(struct command_context *context, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))); void command_print_sameline(struct command_context *context, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))); int command_run_line(struct command_context *context, char *line); int command_run_linef(struct command_context *context, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))); void command_output_text(struct command_context *context, const char *data); void process_jim_events(struct command_context *cmd_ctx); #define ERROR_COMMAND_CLOSE_CONNECTION (-600) #define ERROR_COMMAND_SYNTAX_ERROR (-601) #define ERROR_COMMAND_NOTFOUND (-602) #define ERROR_COMMAND_ARGUMENT_INVALID (-603) #define ERROR_COMMAND_ARGUMENT_OVERFLOW (-604) #define ERROR_COMMAND_ARGUMENT_UNDERFLOW (-605) int parse_ulong(const char *str, unsigned long *ul); int parse_ullong(const char *str, unsigned long long *ul); int parse_long(const char *str, long *ul); int parse_llong(const char *str, long long *ul); #define DECLARE_PARSE_WRAPPER(name, type) \ int parse ## name(const char *str, type * ul) DECLARE_PARSE_WRAPPER(_uint, unsigned); DECLARE_PARSE_WRAPPER(_u64, uint64_t); DECLARE_PARSE_WRAPPER(_u32, uint32_t); DECLARE_PARSE_WRAPPER(_u16, uint16_t); DECLARE_PARSE_WRAPPER(_u8, uint8_t); DECLARE_PARSE_WRAPPER(_int, int); DECLARE_PARSE_WRAPPER(_s32, int32_t); DECLARE_PARSE_WRAPPER(_s16, int16_t); DECLARE_PARSE_WRAPPER(_s8, int8_t); /** * @brief parses the string @a in into @a out as a @a type, or prints * a command error and passes the error code to the caller. If an error * does occur, the calling function will return the error code produced * by the parsing function (one of ERROR_COMMAND_ARGUMENT_*). * * This function may cause the calling function to return immediately, * so it should be used carefully to avoid leaking resources. In most * situations, parsing should be completed in full before proceding * to allocate resources, and this strategy will most prevents leaks. */ #define COMMAND_PARSE_NUMBER(type, in, out) \ do { \ int retval_macro_tmp = parse_ ## type(in, &(out)); \ if (ERROR_OK != retval_macro_tmp) { \ command_print(CMD_CTX, stringify(out) \ " option value ('%s') is not valid", in); \ return retval_macro_tmp; \ } \ } while (0) /** * Parse the string @c as a binary parameter, storing the boolean value * in @c out. The strings @c on and @c off are used to match different * strings for true and false options (e.g. "on" and "off" or * "enable" and "disable"). */ #define COMMAND_PARSE_BOOL(in, out, on, off) \ do { \ bool value; \ int retval_macro_tmp = command_parse_bool_arg(in, &value); \ if (ERROR_OK != retval_macro_tmp) { \ command_print(CMD_CTX, stringify(out) \ " option value ('%s') is not valid", in); \ command_print(CMD_CTX, " choices are '%s' or '%s'", \ on, off); \ return retval_macro_tmp; \ } \ out = value; \ } while (0) int command_parse_bool_arg(const char *in, bool *out); COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); /** parses an on/off command argument */ #define COMMAND_PARSE_ON_OFF(in, out) \ COMMAND_PARSE_BOOL(in, out, "on", "off") /** parses an enable/disable command argument */ #define COMMAND_PARSE_ENABLE(in, out) \ COMMAND_PARSE_BOOL(in, out, "enable", "disable") void script_debug(Jim_Interp *interp, const char *cmd, unsigned argc, Jim_Obj * const *argv); #endif /* COMMAND_H */ openocd-0.9.0/src/helper/ioutil.c0000644000175000017500000003356412315575360013631 00000000000000/*************************************************************************** * Copyright (C) 2007-2010 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* this file contains various functionality useful to standalone systems */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "time_support.h" #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_DIRENT_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_IFADDRS_H #include #endif #ifdef HAVE_MALLOC_H #include #endif /* loads a file and returns a pointer to it in memory. The file contains * a 0 byte(sentinel) after len bytes - the length of the file. */ static int loadFile(const char *fileName, char **data, size_t *len) { /* ensure returned length is always sane */ *len = 0; FILE *pFile; pFile = fopen(fileName, "rb"); if (pFile == NULL) { LOG_ERROR("Can't open %s", fileName); return ERROR_FAIL; } if (fseek(pFile, 0, SEEK_END) != 0) { LOG_ERROR("Can't open %s", fileName); fclose(pFile); return ERROR_FAIL; } long fsize = ftell(pFile); if (fsize == -1) { LOG_ERROR("Can't open %s", fileName); fclose(pFile); return ERROR_FAIL; } *len = fsize; if (fseek(pFile, 0, SEEK_SET) != 0) { LOG_ERROR("Can't open %s", fileName); fclose(pFile); return ERROR_FAIL; } *data = malloc(*len + 1); if (*data == NULL) { LOG_ERROR("Can't open %s", fileName); fclose(pFile); return ERROR_FAIL; } if (fread(*data, 1, *len, pFile) != *len) { fclose(pFile); free(*data); LOG_ERROR("Can't open %s", fileName); return ERROR_FAIL; } fclose(pFile); /* 0-byte after buffer (not included in *len) serves as a sentinel */ (*data)[*len] = 0; return ERROR_OK; } COMMAND_HANDLER(handle_cat_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; /* NOTE!!! we only have line printing capability so we print the entire file as a single * line. */ char *data; size_t len; int retval = loadFile(CMD_ARGV[0], &data, &len); if (retval == ERROR_OK) { command_print(CMD_CTX, "%s", data); free(data); } else command_print(CMD_CTX, "%s not found", CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(handle_trunc_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; FILE *config_file = NULL; config_file = fopen(CMD_ARGV[0], "w"); if (config_file != NULL) fclose(config_file); return ERROR_OK; } #ifdef HAVE_MALLOC_H COMMAND_HANDLER(handle_meminfo_command) { static int prev; struct mallinfo info; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; info = mallinfo(); if (prev > 0) command_print(CMD_CTX, "Diff: %d", prev - info.fordblks); prev = info.fordblks; command_print(CMD_CTX, "Available ram: %d", info.fordblks); return ERROR_OK; } #endif COMMAND_HANDLER(handle_append_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; int retval = ERROR_FAIL; FILE *config_file = NULL; config_file = fopen(CMD_ARGV[0], "a"); if (config_file != NULL) { fseek(config_file, 0, SEEK_END); unsigned i; for (i = 1; i < CMD_ARGC; i++) { if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]), config_file) != strlen(CMD_ARGV[i])) break; if (i != CMD_ARGC - 1) { if (fwrite(" ", 1, 1, config_file) != 1) break; } } if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1)) retval = ERROR_OK; fclose(config_file); } return retval; } COMMAND_HANDLER(handle_cp_command) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; /* NOTE!!! we only have line printing capability so we print the entire file as a single * line. */ char *data; size_t len; int retval = loadFile(CMD_ARGV[0], &data, &len); if (retval != ERROR_OK) return retval; FILE *f = fopen(CMD_ARGV[1], "wb"); if (f == NULL) retval = ERROR_COMMAND_SYNTAX_ERROR; size_t pos = 0; for (;; ) { size_t chunk = len - pos; static const size_t maxChunk = 512 * 1024; /* ~1/sec */ if (chunk > maxChunk) chunk = maxChunk; if ((retval == ERROR_OK) && (fwrite(data + pos, 1, chunk, f) != chunk)) retval = ERROR_COMMAND_SYNTAX_ERROR; if (retval != ERROR_OK) break; command_print(CMD_CTX, "%zu", len - pos); pos += chunk; if (pos == len) break; } if (retval == ERROR_OK) command_print(CMD_CTX, "Copied %s to %s", CMD_ARGV[0], CMD_ARGV[1]); else command_print(CMD_CTX, "copy failed"); if (data != NULL) free(data); if (f != NULL) fclose(f); if (retval != ERROR_OK) unlink(CMD_ARGV[1]); return retval; } #define SHOW_RESULT(a, b) LOG_ERROR(# a " failed %d\n", (int)b) #define IOSIZE 512 void copyfile(char *name2, char *name1) { int err; char buf[IOSIZE]; int fd1, fd2; ssize_t done, wrote; fd1 = open(name1, O_WRONLY | O_CREAT, 0664); if (fd1 < 0) SHOW_RESULT(open, fd1); fd2 = open(name2, O_RDONLY); if (fd2 < 0) SHOW_RESULT(open, fd2); for (;; ) { done = read(fd2, buf, IOSIZE); if (done < 0) { SHOW_RESULT(read, done); break; } if (done == 0) break; wrote = write(fd1, buf, done); if (wrote != done) SHOW_RESULT(write, wrote); if (wrote != done) break; } err = close(fd1); if (err < 0) SHOW_RESULT(close, err); err = close(fd2); if (err < 0) SHOW_RESULT(close, err); } /* utility fn to copy a directory */ void copydir(char *name, char *destdir) { int err; DIR *dirp; dirp = opendir(destdir); if (dirp == NULL) mkdir(destdir, 0777); else err = closedir(dirp); dirp = opendir(name); if (dirp == NULL) SHOW_RESULT(opendir, -1); for (;; ) { struct dirent *entry = readdir(dirp); if (entry == NULL) break; if (strcmp(entry->d_name, ".") == 0) continue; if (strcmp(entry->d_name, "..") == 0) continue; int isDir = 0; struct stat buf; char fullPath[PATH_MAX]; strncpy(fullPath, name, PATH_MAX); strcat(fullPath, "/"); strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath)); if (stat(fullPath, &buf) == -1) { LOG_ERROR("unable to read status from %s", fullPath); break; } isDir = S_ISDIR(buf.st_mode) != 0; if (isDir) continue; /* diag_printf(": entry %14s",entry->d_name); */ char fullname[PATH_MAX]; char fullname2[PATH_MAX]; strcpy(fullname, name); strcat(fullname, "/"); strcat(fullname, entry->d_name); strcpy(fullname2, destdir); strcat(fullname2, "/"); strcat(fullname2, entry->d_name); /* diag_printf("from %s to %s\n", fullname, fullname2); */ copyfile(fullname, fullname2); /* diag_printf("\n"); */ } err = closedir(dirp); if (err < 0) SHOW_RESULT(stat, err); } COMMAND_HANDLER(handle_rm_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; bool del = false; if (rmdir(CMD_ARGV[0]) == 0) del = true; else if (unlink(CMD_ARGV[0]) == 0) del = true; return del ? ERROR_OK : ERROR_FAIL; } static int ioutil_Jim_Command_ls(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?"); return JIM_ERR; } const char *name = Jim_GetString(argv[1], NULL); DIR *dirp = NULL; dirp = opendir(name); if (dirp == NULL) return JIM_ERR; Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); for (;; ) { struct dirent *entry = NULL; entry = readdir(dirp); if (entry == NULL) break; if ((strcmp(".", entry->d_name) == 0) || (strcmp("..", entry->d_name) == 0)) continue; Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name))); } closedir(dirp); Jim_SetResult(interp, objPtr); return JIM_OK; } static int ioutil_Jim_Command_peek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "peek ?address?"); return JIM_ERR; } long address; if (Jim_GetLong(interp, argv[1], &address) != JIM_OK) return JIM_ERR; int value = *((volatile int *) address); Jim_SetResult(interp, Jim_NewIntObj(interp, value)); return JIM_OK; } static int ioutil_Jim_Command_poke(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?"); return JIM_ERR; } long address; if (Jim_GetLong(interp, argv[1], &address) != JIM_OK) return JIM_ERR; long value; if (Jim_GetLong(interp, argv[2], &value) != JIM_OK) return JIM_ERR; *((volatile int *) address) = value; return JIM_OK; } /* not so pretty code to fish out ip number*/ static int ioutil_Jim_Command_ip(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { #if !defined(__CYGWIN__) Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); struct ifaddrs *ifa = NULL, *ifp = NULL; if (getifaddrs(&ifp) < 0) return JIM_ERR; for (ifa = ifp; ifa; ifa = ifa->ifa_next) { char ip[200]; socklen_t salen; if (ifa->ifa_addr->sa_family == AF_INET) salen = sizeof(struct sockaddr_in); else if (ifa->ifa_addr->sa_family == AF_INET6) salen = sizeof(struct sockaddr_in6); else continue; if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST) < 0) continue; Jim_AppendString(interp, tclOutput, ip, strlen(ip)); break; } freeifaddrs(ifp); #else Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0); LOG_ERROR("NOT IMPLEMENTED!!!"); #endif Jim_SetResult(interp, tclOutput); return JIM_OK; } #ifdef HAVE_SYS_IOCTL_H #ifdef SIOCGIFHWADDR /* not so pretty code to fish out eth0 mac address */ static int ioutil_Jim_Command_mac(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct ifreq *ifr, *ifend; struct ifreq ifreq; struct ifconf ifc; struct ifreq ifs[5]; int SockFD; SockFD = socket(AF_INET, SOCK_DGRAM, 0); if (SockFD < 0) return JIM_ERR; ifc.ifc_len = sizeof(ifs); ifc.ifc_req = ifs; if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0) { close(SockFD); return JIM_ERR; } ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq)); for (ifr = ifc.ifc_req; ifr < ifend; ifr++) { /* if (ifr->ifr_addr.sa_family == AF_INET) */ { if (strcmp("eth0", ifr->ifr_name) != 0) continue; strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0) { close(SockFD); return JIM_ERR; } close(SockFD); Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); char buffer[256]; sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x", ifreq.ifr_hwaddr.sa_data[0]&0xff, ifreq.ifr_hwaddr.sa_data[1]&0xff, ifreq.ifr_hwaddr.sa_data[2]&0xff, ifreq.ifr_hwaddr.sa_data[3]&0xff, ifreq.ifr_hwaddr.sa_data[4]&0xff, ifreq.ifr_hwaddr.sa_data[5]&0xff); Jim_AppendString(interp, tclOutput, buffer, strlen(buffer)); Jim_SetResult(interp, tclOutput); return JIM_OK; } } close(SockFD); return JIM_ERR; } #endif #endif static const struct command_registration ioutil_command_handlers[] = { { .name = "cat", .handler = handle_cat_command, .mode = COMMAND_ANY, .help = "display text file content", .usage = "file_name", }, { .name = "trunc", .handler = handle_trunc_command, .mode = COMMAND_ANY, .help = "truncate a file to zero length", .usage = "file_name", }, { .name = "cp", .handler = handle_cp_command, .mode = COMMAND_ANY, .help = "copy a file", .usage = "src_file_name dst_file_name", }, { .name = "append_file", .handler = handle_append_command, .mode = COMMAND_ANY, .help = "append a variable number of strings to a file", .usage = "file_name [, [, ...]]", }, #ifdef HAVE_MALLOC_H { .name = "meminfo", .handler = handle_meminfo_command, .mode = COMMAND_ANY, .help = "display free heap space", }, #endif { .name = "rm", .mode = COMMAND_ANY, .handler = handle_rm_command, .help = "remove a directory or file", .usage = "file_name", }, /* * Peek and poke are security holes -- they manipulate * server-internal addresses. */ /* jim handlers */ { .name = "peek", .mode = COMMAND_ANY, .jim_handler = ioutil_Jim_Command_peek, .help = "peek at a memory address", .usage = "address", }, { .name = "poke", .mode = COMMAND_ANY, .jim_handler = ioutil_Jim_Command_poke, .help = "poke at a memory address", .usage = "address value", }, { .name = "ls", .mode = COMMAND_ANY, .jim_handler = ioutil_Jim_Command_ls, .help = "show a listing of files", .usage = "dirname", }, #ifdef HAVE_SYS_IOCTL_H #ifdef SIOCGIFHWADDR { .name = "mac", .mode = COMMAND_ANY, .jim_handler = ioutil_Jim_Command_mac, .help = "show MAC address", }, #endif #endif { .name = "ip", .jim_handler = ioutil_Jim_Command_ip, .mode = COMMAND_ANY, .help = "show IP address", }, COMMAND_REGISTRATION_DONE }; int ioutil_init(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, ioutil_command_handlers); } openocd-0.9.0/src/helper/ioutil.h0000644000175000017500000000301112315575360013616 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef HELPER_IOUTILS_H #define HELPER_IOUTILS_H struct command_context; int ioutil_init(struct command_context *cmd_ctx); #endif /* HELPER_IOUTILS_H */ openocd-0.9.0/src/helper/bin2char.sh0000755000175000017500000000067612516456302014202 00000000000000#!/bin/sh [ $# != 0 ] && { echo "Usage: $0" echo echo "Read binary data from standard input and write it as a comma separated" echo "list of hexadecimal byte values to standard ouput. The output is usable" echo "as a C array initializer. It is terminated with a comma so it can be" echo "continued e.g. for zero termination." exit 1 } echo "/* Autogenerated with $0 */" od -v -A n -t x1 | sed 's/ *\(..\) */0x\1,/g' openocd-0.9.0/src/helper/startup.tcl0000644000175000017500000000342412516456302014353 00000000000000# Defines basic Tcl procs that must exist for OpenOCD scripts to work. # # Embedded into OpenOCD executable # # We need to explicitly redirect this to the OpenOCD command # as Tcl defines the exit proc proc exit {} { ocd_throw exit } # All commands are registered with an 'ocd_' prefix, while the "real" # command is a wrapper that calls this function. Its primary purpose is # to discard 'handler' command output, proc ocd_bouncer {name args} { set cmd [format "ocd_%s" $name] set type [eval ocd_command type $cmd $args] set errcode error if {$type == "native"} { return [eval $cmd $args] } else {if {$type == "simple"} { set errcode [catch {eval $cmd $args}] if {$errcode == 0} { return "" } else { # 'classic' commands output error message as part of progress output set errmsg "" } } else {if {$type == "group"} { catch {eval ocd_usage $name $args} set errmsg [format "%s: command requires more arguments" \ [concat $name " " $args]] } else { set errmsg [format "invalid subcommand \"%s\"" $args] }}} return -code $errcode $errmsg } # Try flipping / and \ to find file if the filename does not # match the precise spelling proc find {filename} { if {[catch {ocd_find $filename} t]==0} { return $t } if {[catch {ocd_find [string map {\ /} $filename} t]==0} { return $t } if {[catch {ocd_find [string map {/ \\} $filename} t]==0} { return $t } # make sure error message matches original input string return -code error "Can't find $filename" } add_usage_text find "" add_help_text find "print full path to file according to OpenOCD search rules" # Find and run a script proc script {filename} { uplevel #0 [list source [find $filename]] } add_help_text script "filename of OpenOCD script (tcl) to run" add_usage_text script "" ######### openocd-0.9.0/src/helper/fileio.c0000644000175000017500000001630312315575360013563 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "configuration.h" #include "fileio.h" struct fileio_internal { char *url; ssize_t size; enum fileio_type type; enum fileio_access access; FILE *file; }; static inline int fileio_close_local(struct fileio_internal *fileio); static inline int fileio_open_local(struct fileio_internal *fileio) { char file_access[4]; switch (fileio->access) { case FILEIO_READ: strcpy(file_access, "r"); break; case FILEIO_WRITE: strcpy(file_access, "w"); break; case FILEIO_READWRITE: strcpy(file_access, "w+"); break; case FILEIO_APPEND: strcpy(file_access, "a"); break; case FILEIO_APPENDREAD: strcpy(file_access, "a+"); break; default: LOG_ERROR("BUG: access neither read, write nor readwrite"); return ERROR_COMMAND_SYNTAX_ERROR; } /* win32 always opens in binary mode */ #ifndef _WIN32 if (fileio->type == FILEIO_BINARY) #endif strcat(file_access, "b"); fileio->file = open_file_from_path(fileio->url, file_access); if (!fileio->file) { LOG_ERROR("couldn't open %s", fileio->url); return ERROR_FILEIO_OPERATION_FAILED; } if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE)) { /* NB! Here we use fseek() instead of stat(), since stat is a * more advanced operation that might not apply to e.g. a disk path * that refers to e.g. a tftp client */ int result, result2; result = fseek(fileio->file, 0, SEEK_END); fileio->size = ftell(fileio->file); result2 = fseek(fileio->file, 0, SEEK_SET); if ((fileio->size < 0) || (result < 0) || (result2 < 0)) { fileio_close_local(fileio); return ERROR_FILEIO_OPERATION_FAILED; } } else fileio->size = 0x0; return ERROR_OK; } int fileio_open(struct fileio *fileio_p, const char *url, enum fileio_access access_type, enum fileio_type type) { int retval = ERROR_OK; struct fileio_internal *fileio = malloc(sizeof(struct fileio_internal)); fileio_p->fp = fileio; fileio->type = type; fileio->access = access_type; fileio->url = strdup(url); retval = fileio_open_local(fileio); return retval; } static inline int fileio_close_local(struct fileio_internal *fileio) { int retval = fclose(fileio->file); if (retval != 0) { if (retval == EBADF) LOG_ERROR("BUG: fileio_local->file not a valid file descriptor"); else LOG_ERROR("couldn't close %s: %s", fileio->url, strerror(errno)); return ERROR_FILEIO_OPERATION_FAILED; } return ERROR_OK; } int fileio_close(struct fileio *fileio_p) { int retval; struct fileio_internal *fileio = fileio_p->fp; retval = fileio_close_local(fileio); free(fileio->url); fileio->url = NULL; free(fileio); fileio_p->fp = NULL; return retval; } int fileio_seek(struct fileio *fileio_p, size_t position) { int retval; struct fileio_internal *fileio = fileio_p->fp; retval = fseek(fileio->file, position, SEEK_SET); if (retval != 0) { LOG_ERROR("couldn't seek file %s: %s", fileio->url, strerror(errno)); return ERROR_FILEIO_OPERATION_FAILED; } return ERROR_OK; } static int fileio_local_read(struct fileio_internal *fileio, size_t size, void *buffer, size_t *size_read) { ssize_t retval = fread(buffer, 1, size, fileio->file); *size_read = (retval >= 0) ? retval : 0; return (retval < 0) ? retval : ERROR_OK; } int fileio_read(struct fileio *fileio_p, size_t size, void *buffer, size_t *size_read) { struct fileio_internal *fileio = fileio_p->fp; return fileio_local_read(fileio, size, buffer, size_read); } int fileio_read_u32(struct fileio *fileio_p, uint32_t *data) { uint8_t buf[4]; size_t size_read; struct fileio_internal *fileio = fileio_p->fp; int retval = fileio_local_read(fileio, sizeof(uint32_t), buf, &size_read); if (ERROR_OK == retval && sizeof(uint32_t) != size_read) retval = -EIO; if (ERROR_OK == retval) *data = be_to_h_u32(buf); return retval; } static int fileio_local_fgets(struct fileio_internal *fileio, size_t size, void *buffer) { if (fgets(buffer, size, fileio->file) == NULL) return ERROR_FILEIO_OPERATION_FAILED; return ERROR_OK; } int fileio_fgets(struct fileio *fileio_p, size_t size, void *buffer) { struct fileio_internal *fileio = fileio_p->fp; return fileio_local_fgets(fileio, size, buffer); } static int fileio_local_write(struct fileio_internal *fileio, size_t size, const void *buffer, size_t *size_written) { ssize_t retval = fwrite(buffer, 1, size, fileio->file); *size_written = (retval >= 0) ? retval : 0; return (retval < 0) ? retval : ERROR_OK; } int fileio_write(struct fileio *fileio_p, size_t size, const void *buffer, size_t *size_written) { struct fileio_internal *fileio = fileio_p->fp; int retval = fileio_local_write(fileio, size, buffer, size_written); if (retval == ERROR_OK) fileio->size += *size_written; return retval; } int fileio_write_u32(struct fileio *fileio_p, uint32_t data) { uint8_t buf[4]; h_u32_to_be(buf, data); size_t size_written; int retval = fileio_write(fileio_p, 4, buf, &size_written); if (ERROR_OK == retval && size_written != sizeof(uint32_t)) retval = -EIO; return retval; } /** * FIX!!!! * * For now this can not fail, but that's because a seek was executed * on startup. * * Avoiding the seek on startup opens up for using streams. * */ int fileio_size(struct fileio *fileio_p, int *size) { struct fileio_internal *fileio = fileio_p->fp; *size = fileio->size; return ERROR_OK; } openocd-0.9.0/src/helper/fileio.h0000644000175000017500000000667312315575360013601 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef FILEIO_H #define FILEIO_H #define FILEIO_MAX_ERROR_STRING (128) enum fileio_type { FILEIO_TEXT, FILEIO_BINARY, }; enum fileio_access { FILEIO_NONE, /* open without any access (invalid mode) */ FILEIO_READ, /* open for reading, position at beginning */ FILEIO_WRITE, /* open for writing, position at beginning */ FILEIO_READWRITE, /* open for writing, position at beginning, allow reading */ FILEIO_APPEND, /* open for writing, position at end */ FILEIO_APPENDREAD, /* open for writing, position at end, allow reading */ }; struct fileio { /* The structure is opaque */ struct fileio_internal *fp; }; int fileio_open(struct fileio *fileio, const char *url, enum fileio_access access_type, enum fileio_type type); int fileio_close(struct fileio *fileio); int fileio_seek(struct fileio *fileio, size_t position); int fileio_fgets(struct fileio *fileio, size_t size, void *buffer); int fileio_read(struct fileio *fileio, size_t size, void *buffer, size_t *size_read); int fileio_write(struct fileio *fileio, size_t size, const void *buffer, size_t *size_written); int fileio_read_u32(struct fileio *fileio, uint32_t *data); int fileio_write_u32(struct fileio *fileio, uint32_t data); int fileio_size(struct fileio *fileio, int *size); #define ERROR_FILEIO_LOCATION_UNKNOWN (-1200) #define ERROR_FILEIO_NOT_FOUND (-1201) #define ERROR_FILEIO_OPERATION_FAILED (-1202) #define ERROR_FILEIO_ACCESS_NOT_SUPPORTED (-1203) #define ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN (-1204) #define ERROR_FILEIO_OPERATION_NOT_SUPPORTED (-1205) #endif /* FILEIO_H */ openocd-0.9.0/src/helper/time_support.c0000644000175000017500000000652012315575360015046 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "time_support.h" /* calculate difference between two struct timeval values */ int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } int timeval_add_time(struct timeval *result, long sec, long usec) { result->tv_sec += sec; result->tv_usec += usec; while (result->tv_usec > 1000000) { result->tv_usec -= 1000000; result->tv_sec++; } return 0; } int duration_start(struct duration *duration) { return gettimeofday(&duration->start, NULL); } int duration_measure(struct duration *duration) { struct timeval end; int retval = gettimeofday(&end, NULL); if (0 == retval) timeval_subtract(&duration->elapsed, &end, &duration->start); return retval; } float duration_elapsed(struct duration *duration) { float t = duration->elapsed.tv_sec; t += (float)duration->elapsed.tv_usec / 1000000.0; return t; } float duration_kbps(struct duration *duration, size_t count) { return count / (1024.0 * duration_elapsed(duration)); } openocd-0.9.0/src/helper/time_support.h0000644000175000017500000000561112315575360015053 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TIME_SUPPORT_H #define TIME_SUPPORT_H #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); int timeval_add_time(struct timeval *result, long sec, long usec); /** @returns gettimeofday() timeval as 64-bit in ms */ int64_t timeval_ms(void); struct duration { struct timeval start; struct timeval elapsed; }; /** Update the duration->start field to start the @a duration measurement. */ int duration_start(struct duration *duration); /** Update the duration->elapsed field to finish the @a duration measurment. */ int duration_measure(struct duration *duration); /** @returns Elapsed time in seconds. */ float duration_elapsed(struct duration *duration); /** @returns KB/sec for the elapsed @a duration and @a count bytes. */ float duration_kbps(struct duration *duration, size_t count); #endif /* TIME_SUPPORT_H */ openocd-0.9.0/src/helper/Makefile.am0000644000175000017500000000156112516456302014201 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libhelper.la CONFIGFILES = options.c time_support_common.c libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) libhelper_la_SOURCES = \ binarybuffer.c \ $(CONFIGFILES) \ configuration.c \ log.c \ command.c \ time_support.c \ replacements.c \ fileio.c \ util.c \ jim-nvp.c if IOUTIL libhelper_la_SOURCES += ioutil.c else libhelper_la_SOURCES += ioutil_stubs.c endif libhelper_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform libhelper_la_CFLAGS += -Wno-sign-compare endif noinst_HEADERS = \ binarybuffer.h \ configuration.h \ ioutil.h \ list.h \ util.h \ types.h \ log.h \ command.h \ time_support.h \ replacements.h \ fileio.h \ system.h \ bin2char.sh \ jim-nvp.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/helper/Makefile.in0000644000175000017500000010467712526201650014221 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl @IOUTIL_TRUE@am__append_2 = ioutil.c @IOUTIL_FALSE@am__append_3 = ioutil_stubs.c # FD_* macros are sloppy with their signs on MinGW32 platform @IS_MINGW_TRUE@am__append_4 = -Wno-sign-compare subdir = src/helper ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libhelper_la_LIBADD = am__libhelper_la_SOURCES_DIST = binarybuffer.c options.c \ time_support_common.c configuration.c log.c command.c \ time_support.c replacements.c fileio.c util.c jim-nvp.c \ ioutil.c ioutil_stubs.c am__objects_1 = libhelper_la-options.lo \ libhelper_la-time_support_common.lo @IOUTIL_TRUE@am__objects_2 = libhelper_la-ioutil.lo @IOUTIL_FALSE@am__objects_3 = libhelper_la-ioutil_stubs.lo am_libhelper_la_OBJECTS = libhelper_la-binarybuffer.lo \ $(am__objects_1) libhelper_la-configuration.lo \ libhelper_la-log.lo libhelper_la-command.lo \ libhelper_la-time_support.lo libhelper_la-replacements.lo \ libhelper_la-fileio.lo libhelper_la-util.lo \ libhelper_la-jim-nvp.lo $(am__objects_2) $(am__objects_3) libhelper_la_OBJECTS = $(am_libhelper_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libhelper_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libhelper_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libhelper_la_SOURCES) DIST_SOURCES = $(am__libhelper_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libhelper.la CONFIGFILES = options.c time_support_common.c libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) libhelper_la_SOURCES = binarybuffer.c $(CONFIGFILES) configuration.c \ log.c command.c time_support.c replacements.c fileio.c util.c \ jim-nvp.c $(am__append_2) $(am__append_3) libhelper_la_CFLAGS = $(am__append_4) noinst_HEADERS = \ binarybuffer.h \ configuration.h \ ioutil.h \ list.h \ util.h \ types.h \ log.h \ command.h \ time_support.h \ replacements.h \ fileio.h \ system.h \ bin2char.sh \ jim-nvp.h EXTRA_DIST = startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/helper/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/helper/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libhelper.la: $(libhelper_la_OBJECTS) $(libhelper_la_DEPENDENCIES) $(EXTRA_libhelper_la_DEPENDENCIES) $(AM_V_CCLD)$(libhelper_la_LINK) $(libhelper_la_OBJECTS) $(libhelper_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-binarybuffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-command.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-configuration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-fileio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-ioutil.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-ioutil_stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-jim-nvp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-options.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-replacements.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-time_support.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-time_support_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhelper_la-util.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libhelper_la-binarybuffer.lo: binarybuffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-binarybuffer.lo -MD -MP -MF $(DEPDIR)/libhelper_la-binarybuffer.Tpo -c -o libhelper_la-binarybuffer.lo `test -f 'binarybuffer.c' || echo '$(srcdir)/'`binarybuffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-binarybuffer.Tpo $(DEPDIR)/libhelper_la-binarybuffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='binarybuffer.c' object='libhelper_la-binarybuffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-binarybuffer.lo `test -f 'binarybuffer.c' || echo '$(srcdir)/'`binarybuffer.c libhelper_la-options.lo: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-options.lo -MD -MP -MF $(DEPDIR)/libhelper_la-options.Tpo -c -o libhelper_la-options.lo `test -f 'options.c' || echo '$(srcdir)/'`options.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-options.Tpo $(DEPDIR)/libhelper_la-options.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='libhelper_la-options.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-options.lo `test -f 'options.c' || echo '$(srcdir)/'`options.c libhelper_la-time_support_common.lo: time_support_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-time_support_common.lo -MD -MP -MF $(DEPDIR)/libhelper_la-time_support_common.Tpo -c -o libhelper_la-time_support_common.lo `test -f 'time_support_common.c' || echo '$(srcdir)/'`time_support_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-time_support_common.Tpo $(DEPDIR)/libhelper_la-time_support_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='time_support_common.c' object='libhelper_la-time_support_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-time_support_common.lo `test -f 'time_support_common.c' || echo '$(srcdir)/'`time_support_common.c libhelper_la-configuration.lo: configuration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-configuration.lo -MD -MP -MF $(DEPDIR)/libhelper_la-configuration.Tpo -c -o libhelper_la-configuration.lo `test -f 'configuration.c' || echo '$(srcdir)/'`configuration.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-configuration.Tpo $(DEPDIR)/libhelper_la-configuration.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='configuration.c' object='libhelper_la-configuration.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-configuration.lo `test -f 'configuration.c' || echo '$(srcdir)/'`configuration.c libhelper_la-log.lo: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-log.lo -MD -MP -MF $(DEPDIR)/libhelper_la-log.Tpo -c -o libhelper_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-log.Tpo $(DEPDIR)/libhelper_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='libhelper_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c libhelper_la-command.lo: command.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-command.lo -MD -MP -MF $(DEPDIR)/libhelper_la-command.Tpo -c -o libhelper_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-command.Tpo $(DEPDIR)/libhelper_la-command.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='command.c' object='libhelper_la-command.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c libhelper_la-time_support.lo: time_support.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-time_support.lo -MD -MP -MF $(DEPDIR)/libhelper_la-time_support.Tpo -c -o libhelper_la-time_support.lo `test -f 'time_support.c' || echo '$(srcdir)/'`time_support.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-time_support.Tpo $(DEPDIR)/libhelper_la-time_support.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='time_support.c' object='libhelper_la-time_support.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-time_support.lo `test -f 'time_support.c' || echo '$(srcdir)/'`time_support.c libhelper_la-replacements.lo: replacements.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-replacements.lo -MD -MP -MF $(DEPDIR)/libhelper_la-replacements.Tpo -c -o libhelper_la-replacements.lo `test -f 'replacements.c' || echo '$(srcdir)/'`replacements.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-replacements.Tpo $(DEPDIR)/libhelper_la-replacements.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='replacements.c' object='libhelper_la-replacements.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-replacements.lo `test -f 'replacements.c' || echo '$(srcdir)/'`replacements.c libhelper_la-fileio.lo: fileio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-fileio.lo -MD -MP -MF $(DEPDIR)/libhelper_la-fileio.Tpo -c -o libhelper_la-fileio.lo `test -f 'fileio.c' || echo '$(srcdir)/'`fileio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-fileio.Tpo $(DEPDIR)/libhelper_la-fileio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fileio.c' object='libhelper_la-fileio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-fileio.lo `test -f 'fileio.c' || echo '$(srcdir)/'`fileio.c libhelper_la-util.lo: util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-util.lo -MD -MP -MF $(DEPDIR)/libhelper_la-util.Tpo -c -o libhelper_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-util.Tpo $(DEPDIR)/libhelper_la-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='libhelper_la-util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c libhelper_la-jim-nvp.lo: jim-nvp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-jim-nvp.lo -MD -MP -MF $(DEPDIR)/libhelper_la-jim-nvp.Tpo -c -o libhelper_la-jim-nvp.lo `test -f 'jim-nvp.c' || echo '$(srcdir)/'`jim-nvp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-jim-nvp.Tpo $(DEPDIR)/libhelper_la-jim-nvp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jim-nvp.c' object='libhelper_la-jim-nvp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-jim-nvp.lo `test -f 'jim-nvp.c' || echo '$(srcdir)/'`jim-nvp.c libhelper_la-ioutil.lo: ioutil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-ioutil.lo -MD -MP -MF $(DEPDIR)/libhelper_la-ioutil.Tpo -c -o libhelper_la-ioutil.lo `test -f 'ioutil.c' || echo '$(srcdir)/'`ioutil.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-ioutil.Tpo $(DEPDIR)/libhelper_la-ioutil.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ioutil.c' object='libhelper_la-ioutil.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-ioutil.lo `test -f 'ioutil.c' || echo '$(srcdir)/'`ioutil.c libhelper_la-ioutil_stubs.lo: ioutil_stubs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -MT libhelper_la-ioutil_stubs.lo -MD -MP -MF $(DEPDIR)/libhelper_la-ioutil_stubs.Tpo -c -o libhelper_la-ioutil_stubs.lo `test -f 'ioutil_stubs.c' || echo '$(srcdir)/'`ioutil_stubs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhelper_la-ioutil_stubs.Tpo $(DEPDIR)/libhelper_la-ioutil_stubs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ioutil_stubs.c' object='libhelper_la-ioutil_stubs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhelper_la_CPPFLAGS) $(CPPFLAGS) $(libhelper_la_CFLAGS) $(CFLAGS) -c -o libhelper_la-ioutil_stubs.lo `test -f 'ioutil_stubs.c' || echo '$(srcdir)/'`ioutil_stubs.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/helper/list.h0000644000175000017500000005254212315575360013301 00000000000000#ifndef _LINUX_LIST_H #define _LINUX_LIST_H /* begin local changes */ #include #define prefetch(x) ((void)x) #define LIST_POISON1 NULL #define LIST_POISON2 NULL struct list_head { struct list_head *next, *prev; }; struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; /* end local changes */ /* * Simple doubly linked list implementation. * * Some of the internal functions ("__xxx") are useful when * manipulating whole lists rather than single entries, as * sometimes we already know the next/prev entries and we can * generate better code by using them directly rather than * using the generic single-entry routines. */ #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; } /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ #ifndef CONFIG_DEBUG_LIST static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } #else extern void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next); #endif /** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } /* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } /** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ #ifndef CONFIG_DEBUG_LIST static inline void __list_del_entry(struct list_head *entry) { __list_del(entry->prev, entry->next); } static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } #else extern void __list_del_entry(struct list_head *entry); extern void list_del(struct list_head *entry); #endif /** * list_replace - replace old entry by new one * @old : the element to be replaced * @new : the new element to insert * * If @old was empty, it will be overwritten. */ static inline void list_replace(struct list_head *old, struct list_head *new) { new->next = old->next; new->next->prev = new; new->prev = old->prev; new->prev->next = new; } static inline void list_replace_init(struct list_head *old, struct list_head *new) { list_replace(old, new); INIT_LIST_HEAD(old); } /** * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ static inline void list_del_init(struct list_head *entry) { __list_del_entry(entry); INIT_LIST_HEAD(entry); } /** * list_move - delete from one list and add as another's head * @list: the entry to move * @head: the head that will precede our entry */ static inline void list_move(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add(list, head); } /** * list_move_tail - delete from one list and add as another's tail * @list: the entry to move * @head: the head that will follow our entry */ static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add_tail(list, head); } /** * list_is_last - tests whether @list is the last entry in list @head * @list: the entry to test * @head: the head of the list */ static inline int list_is_last(const struct list_head *list, const struct list_head *head) { return list->next == head; } /** * list_empty - tests whether a list is empty * @head: the list to test. */ static inline int list_empty(const struct list_head *head) { return head->next == head; } /** * list_empty_careful - tests whether a list is empty and not being modified * @head: the list to test * * Description: * tests whether a list is empty _and_ checks that no other CPU might be * in the process of modifying either member (next or prev) * * NOTE: using list_empty_careful() without synchronization * can only be safe if the only activity that can happen * to the list entry is list_del_init(). Eg. it cannot be used * if another CPU could re-list_add() it. */ static inline int list_empty_careful(const struct list_head *head) { struct list_head *next = head->next; return (next == head) && (next == head->prev); } /** * list_rotate_left - rotate the list to the left * @head: the head of the list */ static inline void list_rotate_left(struct list_head *head) { struct list_head *first; if (!list_empty(head)) { first = head->next; list_move_tail(first, head); } } /** * list_is_singular - tests whether a list has just one entry. * @head: the list to test. */ static inline int list_is_singular(const struct list_head *head) { return !list_empty(head) && (head->next == head->prev); } static inline void __list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { struct list_head *new_first = entry->next; list->next = head->next; list->next->prev = list; list->prev = entry; entry->next = list; head->next = new_first; new_first->prev = head; } /** * list_cut_position - cut a list into two * @list: a new list to add all removed entries * @head: a list with entries * @entry: an entry within head, could be the head itself * and if so we won't cut the list * * This helper moves the initial part of @head, up to and * including @entry, from @head to @list. You should * pass on @entry an element you know is on @head. @list * should be an empty list or a list you do not care about * losing its data. * */ static inline void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { if (list_empty(head)) return; if (list_is_singular(head) && (head->next != entry && head != entry)) return; if (entry == head) INIT_LIST_HEAD(list); else __list_cut_position(list, head, entry); } static inline void __list_splice(const struct list_head *list, struct list_head *prev, struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; first->prev = prev; prev->next = first; last->next = next; next->prev = last; } /** * list_splice - join two lists, this is designed for stacks * @list: the new list to add. * @head: the place to add it in the first list. */ static inline void list_splice(const struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head, head->next); } /** * list_splice_tail - join two lists, each list being a queue * @list: the new list to add. * @head: the place to add it in the first list. */ static inline void list_splice_tail(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head->prev, head); } /** * list_splice_init - join two lists and reinitialise the emptied list. * @list: the new list to add. * @head: the place to add it in the first list. * * The list at @list is reinitialised */ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head, head->next); INIT_LIST_HEAD(list); } } /** * list_splice_tail_init - join two lists and reinitialise the emptied list * @list: the new list to add. * @head: the place to add it in the first list. * * Each of the lists is a queue. * The list at @list is reinitialised */ static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head->prev, head); INIT_LIST_HEAD(list); } } /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member) /** * list_first_entry - get the first element from a list * @ptr: the list head to take the element from. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. * * Note, that list is expected to be not empty. */ #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; prefetch(pos->next), pos != (head); \ pos = pos->next) /** * __list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. * * This variant differs from list_for_each() in that it's the * simplest possible list iteration code, no prefetching is done. * Use this for code that knows the list to be very short (empty * or 1 entry) most of the time. */ #define __list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each_prev(pos, head) \ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ pos = pos->prev) /** * list_for_each_safe - iterate over a list safe against removal of list entry * @pos: the &struct list_head to use as a loop cursor. * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry * @pos: the &struct list_head to use as a loop cursor. * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ #define list_for_each_prev_safe(pos, n, head) \ for (pos = (head)->prev, n = pos->prev; \ prefetch(pos->prev), pos != (head); \ pos = n, n = pos->prev) /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_reverse - iterate backwards over list of given type. * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry_reverse(pos, head, member) \ for (pos = list_entry((head)->prev, typeof(*pos), member); \ prefetch(pos->member.prev), &pos->member != (head); \ pos = list_entry(pos->member.prev, typeof(*pos), member)) /** * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() * @pos: the type * to use as a start point * @head: the head of the list * @member: the name of the list_struct within the struct. * * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). */ #define list_prepare_entry(pos, head, member) \ ((pos) ? : list_entry(head, typeof(*pos), member)) /** * list_for_each_entry_continue - continue iteration over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Continue to iterate over list of given type, continuing after * the current position. */ #define list_for_each_entry_continue(pos, head, member) \ for (pos = list_entry(pos->member.next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_continue_reverse - iterate backwards from the given point * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Start to iterate over list of given type backwards, continuing after * the current position. */ #define list_for_each_entry_continue_reverse(pos, head, member) \ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ prefetch(pos->member.prev), &pos->member != (head); \ pos = list_entry(pos->member.prev, typeof(*pos), member)) /** * list_for_each_entry_from - iterate over list of given type from the current point * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Iterate over list of given type, continuing from current position. */ #define list_for_each_entry_from(pos, head, member) \ for (; prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) /** * list_for_each_entry_safe_continue - continue list iteration safe against removal * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Iterate over list of given type, continuing after current point, * safe against removal of list entry. */ #define list_for_each_entry_safe_continue(pos, n, head, member) \ for (pos = list_entry(pos->member.next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) /** * list_for_each_entry_safe_from - iterate over list from current point safe against removal * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Iterate over list of given type from current point, safe against * removal of list entry. */ #define list_for_each_entry_safe_from(pos, n, head, member) \ for (n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) /** * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Iterate backwards over list of given type, safe against removal * of list entry. */ #define list_for_each_entry_safe_reverse(pos, n, head, member) \ for (pos = list_entry((head)->prev, typeof(*pos), member), \ n = list_entry(pos->member.prev, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.prev, typeof(*n), member)) /** * list_safe_reset_next - reset a stale list_for_each_entry_safe loop * @pos: the loop cursor used in the list_for_each_entry_safe loop * @n: temporary storage used in list_for_each_entry_safe * @member: the name of the list_struct within the struct. * * list_safe_reset_next is not safe to use in general if the list may be * modified concurrently (eg. the lock is dropped in the loop body). An * exception to this is if the cursor element (pos) is pinned in the list, * and list_safe_reset_next is called after re-taking the lock and before * completing the current iteration of the loop body. */ #define list_safe_reset_next(pos, n, member) \ n = list_entry(pos->member.next, typeof(*pos), member) /* * Double linked lists with a single pointer list head. * Mostly useful for hash tables where the two pointer list head is * too wasteful. * You lose the ability to access the tail in O(1). */ #define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) static inline void INIT_HLIST_NODE(struct hlist_node *h) { h->next = NULL; h->pprev = NULL; } static inline int hlist_unhashed(const struct hlist_node *h) { return !h->pprev; } static inline int hlist_empty(const struct hlist_head *h) { return !h->first; } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; if (next) next->pprev = pprev; } static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); n->next = LIST_POISON1; n->pprev = LIST_POISON2; } static inline void hlist_del_init(struct hlist_node *n) { if (!hlist_unhashed(n)) { __hlist_del(n); INIT_HLIST_NODE(n); } } static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; h->first = n; n->pprev = &h->first; } /* next must be != NULL */ static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next) { n->pprev = next->pprev; n->next = next; next->pprev = &n->next; *(n->pprev) = n; } static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next) { next->next = n->next; n->next = next; next->pprev = &n->next; if (next->next) next->next->pprev = &next->next; } /* after that we'll appear to be on some hlist and hlist_del will work */ static inline void hlist_add_fake(struct hlist_node *n) { n->pprev = &n->next; } /* * Move a list from one list head to another. Fixup the pprev * reference of the first entry if it exists. */ static inline void hlist_move_list(struct hlist_head *old, struct hlist_head *new) { new->first = old->first; if (new->first) new->first->pprev = &new->first; old->first = NULL; } #define hlist_entry(ptr, type, member) container_of(ptr, type, member) #define hlist_for_each(pos, head) \ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ pos = pos->next) #define hlist_for_each_safe(pos, n, head) \ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ pos = n) /** * hlist_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @head: the head for your list. * @member: the name of the hlist_node within the struct. */ #define hlist_for_each_entry(tpos, pos, head, member) \ for (pos = (head)->first; \ pos && ({ prefetch(pos->next); 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ pos = pos->next) /** * hlist_for_each_entry_continue - iterate over a hlist continuing after current point * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @member: the name of the hlist_node within the struct. */ #define hlist_for_each_entry_continue(tpos, pos, member) \ for (pos = (pos)->next; \ pos && ({ prefetch(pos->next); 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ pos = pos->next) /** * hlist_for_each_entry_from - iterate over a hlist continuing from current point * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @member: the name of the hlist_node within the struct. */ #define hlist_for_each_entry_from(tpos, pos, member) \ for (; pos && ({ prefetch(pos->next); 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ pos = pos->next) /** * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @n: another &struct hlist_node to use as temporary storage * @head: the head for your list. * @member: the name of the hlist_node within the struct. */ #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ for (pos = (head)->first; \ pos && ({ n = pos->next; 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ pos = n) #endif openocd-0.9.0/src/helper/types.h0000644000175000017500000002266112516456302013466 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TYPES_H #define TYPES_H #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #ifdef HAVE_STDBOOL_H #include #else /* HAVE_STDBOOL_H */ #define __bool_true_false_are_defined 1 #ifndef HAVE__BOOL #ifndef __cplusplus #define false 0 #define true 1 typedef int _Bool; #else typedef bool _Bool; #endif /* __cplusplus */ #endif /* HAVE__BOOL */ #define bool _Bool #endif /* HAVE_STDBOOL_H */ /// turns a macro argument into a string constant #define stringify(s) __stringify(s) #define __stringify(s) #s /** * Compute the number of elements of a variable length array. * * const char *strs[] = { "a", "b", "c" }; * unsigned num_strs = ARRAY_SIZE(strs); * */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) /** * Cast a member of a structure out to the containing structure. * @param ptr The pointer to the member. * @param type The type of the container struct this is embedded in. * @param member The name of the member within the struct. * * This is a mechanism which is used throughout the Linux kernel. */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (void *) ( (char *)__mptr - offsetof(type,member) ) );}) /** * Rounds @c m up to the nearest multiple of @c n using division. * @param m The value to round up to @c n. * @param n Round @c m up to a multiple of this number. * @returns The rounded integer value. */ #define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n)) /* DANGER!!!! here be dragons! * * Leave these fn's as byte accesses because it is safe * across architectures. Clever usage of 32 bit access * will create problems on some hosts. * * Note that the "buf" pointer in memory is probably unaligned. * * Were these functions to be re-written to take a 32 bit wide or 16 bit wide * memory access shortcut, then on some CPU's, i.e. ARM7, the 2 lsbytes of the address are * ignored for 32 bit access, whereas on other CPU's a 32 bit wide unaligned memory access * will cause an exception, and lastly on x86, an unaligned "greater than bytewide" * memory access works as if aligned. So what follows below will work for all * platforms and gives the compiler leeway to do its own platform specific optimizations. * * Again, note that the "buf" pointer in memory is probably unaligned. */ static inline uint64_t le_to_h_u64(const uint8_t *buf) { return (uint64_t)((uint64_t)buf[0] | (uint64_t)buf[1] << 8 | (uint64_t)buf[2] << 16 | (uint64_t)buf[3] << 24 | (uint64_t)buf[4] << 32 | (uint64_t)buf[5] << 40 | (uint64_t)buf[6] << 48 | (uint64_t)buf[7] << 56); } static inline uint32_t le_to_h_u32(const uint8_t* buf) { return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24); } static inline uint32_t le_to_h_u24(const uint8_t* buf) { return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16); } static inline uint16_t le_to_h_u16(const uint8_t* buf) { return (uint16_t)(buf[0] | buf[1] << 8); } static inline uint64_t be_to_h_u64(const uint8_t *buf) { return (uint64_t)((uint64_t)buf[7] | (uint64_t)buf[6] << 8 | (uint64_t)buf[5] << 16 | (uint64_t)buf[4] << 24 | (uint64_t)buf[3] << 32 | (uint64_t)buf[2] << 40 | (uint64_t)buf[1] << 48 | (uint64_t)buf[0] << 56); } static inline uint32_t be_to_h_u32(const uint8_t* buf) { return (uint32_t)(buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24); } static inline uint32_t be_to_h_u24(const uint8_t* buf) { return (uint32_t)(buf[2] | buf[1] << 8 | buf[0] << 16); } static inline uint16_t be_to_h_u16(const uint8_t* buf) { return (uint16_t)(buf[1] | buf[0] << 8); } static inline void h_u64_to_le(uint8_t *buf, int64_t val) { buf[7] = (uint8_t) (val >> 56); buf[6] = (uint8_t) (val >> 48); buf[5] = (uint8_t) (val >> 40); buf[4] = (uint8_t) (val >> 32); buf[3] = (uint8_t) (val >> 24); buf[2] = (uint8_t) (val >> 16); buf[1] = (uint8_t) (val >> 8); buf[0] = (uint8_t) (val >> 0); } static inline void h_u64_to_be(uint8_t *buf, int64_t val) { buf[0] = (uint8_t) (val >> 56); buf[1] = (uint8_t) (val >> 48); buf[2] = (uint8_t) (val >> 40); buf[3] = (uint8_t) (val >> 32); buf[4] = (uint8_t) (val >> 24); buf[5] = (uint8_t) (val >> 16); buf[6] = (uint8_t) (val >> 8); buf[7] = (uint8_t) (val >> 0); } static inline void h_u32_to_le(uint8_t* buf, int val) { buf[3] = (uint8_t) (val >> 24); buf[2] = (uint8_t) (val >> 16); buf[1] = (uint8_t) (val >> 8); buf[0] = (uint8_t) (val >> 0); } static inline void h_u32_to_be(uint8_t* buf, int val) { buf[0] = (uint8_t) (val >> 24); buf[1] = (uint8_t) (val >> 16); buf[2] = (uint8_t) (val >> 8); buf[3] = (uint8_t) (val >> 0); } static inline void h_u24_to_le(uint8_t* buf, int val) { buf[2] = (uint8_t) (val >> 16); buf[1] = (uint8_t) (val >> 8); buf[0] = (uint8_t) (val >> 0); } static inline void h_u24_to_be(uint8_t* buf, int val) { buf[0] = (uint8_t) (val >> 16); buf[1] = (uint8_t) (val >> 8); buf[2] = (uint8_t) (val >> 0); } static inline void h_u16_to_le(uint8_t* buf, int val) { buf[1] = (uint8_t) (val >> 8); buf[0] = (uint8_t) (val >> 0); } static inline void h_u16_to_be(uint8_t* buf, int val) { buf[0] = (uint8_t) (val >> 8); buf[1] = (uint8_t) (val >> 0); } /** * Byte-swap buffer 16-bit. * * Len must be even, dst and src must be either the same or non-overlapping. * * @param dst Destination buffer. * @param src Source buffer. * @param len Length of source (and destination) buffer, in bytes. */ static inline void buf_bswap16(uint8_t *dst, const uint8_t *src, size_t len) { assert(len % 2 == 0); assert(dst == src || dst + len <= src || src + len <= dst); for (size_t n = 0; n < len; n += 2) { uint16_t x = be_to_h_u16(src + n); h_u16_to_le(dst + n, x); } } /** * Byte-swap buffer 32-bit. * * Len must be divisible by four, dst and src must be either the same or non-overlapping. * * @param dst Destination buffer. * @param src Source buffer. * @param len Length of source (and destination) buffer, in bytes. */ static inline void buf_bswap32(uint8_t *dst, const uint8_t *src, size_t len) { assert(len % 4 == 0); assert(dst == src || dst + len <= src || src + len <= dst); for (size_t n = 0; n < len; n += 4) { uint32_t x = be_to_h_u32(src + n); h_u32_to_le(dst + n, x); } } /** * Calculate the (even) parity of a 32-bit datum. * @param x The datum. * @return 1 if the number of set bits in x is odd, 0 if it is even. */ static inline int parity_u32(uint32_t x) { #ifdef __GNUC__ return __builtin_parityl(x); #else x ^= x >> 16; x ^= x >> 8; x ^= x >> 4; x ^= x >> 2; x ^= x >> 1; return x & 1; #endif } #if defined(__ECOS) /* eCos plain lacks these definition... A series of upstream patches * could probably repair it, but it seems like too much work to be * worth it. */ #if !defined(_STDINT_H) #define PRIx32 "x" #define PRId32 "d" #define SCNx32 "x" #define PRIi32 "i" #define PRIu32 "u" #define PRId8 PRId32 #define SCNx64 "llx" #define PRIx64 "llx" typedef CYG_ADDRWORD intptr_t; typedef int64_t intmax_t; typedef uint64_t uintmax_t; #define INT8_MAX 0x7f #define INT8_MIN (-INT8_MAX - 1) # define UINT8_MAX (255) #define INT16_MAX 0x7fff #define INT16_MIN (-INT16_MAX - 1) # define UINT16_MAX (65535) #define INT32_MAX 0x7fffffffL #define INT32_MIN (-INT32_MAX - 1L) # define UINT32_MAX (4294967295U) #define INT64_MAX 0x7fffffffffffffffLL #define INT64_MIN (-INT64_MAX - 1LL) #define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL) #endif #ifndef LLONG_MAX #define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF) #define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF) #define LLONG_MIN ULLONG_MAX #endif #define ULLONG_MAX 18446744073709551615 /* C99, eCos is C90 compliant (with bits of C99) */ #define isblank(c) ((c) == ' ' || (c) == '\t') #endif #endif /* TYPES_H */ openocd-0.9.0/src/helper/options.c0000644000175000017500000001520412516456302014003 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "configuration.h" /* @todo the inclusion of server.h here is a layering violation */ #include #include static int help_flag, version_flag; static const struct option long_options[] = { {"help", no_argument, &help_flag, 1}, {"version", no_argument, &version_flag, 1}, {"debug", optional_argument, 0, 'd'}, {"file", required_argument, 0, 'f'}, {"search", required_argument, 0, 's'}, {"log_output", required_argument, 0, 'l'}, {"command", required_argument, 0, 'c'}, {"pipe", no_argument, 0, 'p'}, {0, 0, 0, 0} }; int configuration_output_handler(struct command_context *context, const char *line) { LOG_USER_N("%s", line); return ERROR_OK; } #ifdef _WIN32 static char *find_suffix(const char *text, const char *suffix) { size_t text_len = strlen(text); size_t suffix_len = strlen(suffix); if (suffix_len == 0) return (char *)text + text_len; if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0) return NULL; /* Not a suffix of text */ return (char *)text + text_len - suffix_len; } #endif static void add_default_dirs(void) { const char *run_prefix; char *path; #ifdef _WIN32 char strExePath[MAX_PATH]; GetModuleFileName(NULL, strExePath, MAX_PATH); /* Strip executable file name, leaving path */ *strrchr(strExePath, '\\') = '\0'; /* Convert path separators to UNIX style, should work on Windows also. */ for (char *p = strExePath; *p; p++) { if (*p == '\\') *p = '/'; } char *end_of_prefix = find_suffix(strExePath, BINDIR); if (end_of_prefix != NULL) *end_of_prefix = '\0'; run_prefix = strExePath; #else run_prefix = ""; #endif LOG_DEBUG("bindir=%s", BINDIR); LOG_DEBUG("pkgdatadir=%s", PKGDATADIR); LOG_DEBUG("run_prefix=%s", run_prefix); /* * The directory containing OpenOCD-supplied scripts should be * listed last in the built-in search order, so the user can * override these scripts with site-specific customizations. */ const char *home = getenv("HOME"); if (home) { path = alloc_printf("%s/.openocd", home); if (path) { add_script_search_dir(path); free(path); } } #ifdef _WIN32 const char *appdata = getenv("APPDATA"); if (appdata) { path = alloc_printf("%s/OpenOCD", appdata); if (path) { add_script_search_dir(path); free(path); } } #endif path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site"); if (path) { add_script_search_dir(path); free(path); } path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts"); if (path) { add_script_search_dir(path); free(path); } } int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) { int c; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 0: break; case 'h': /* --help | -h */ help_flag = 1; break; case 'v': /* --version | -v */ version_flag = 1; break; case 'f': /* --file | -f */ { char *command = alloc_printf("script {%s}", optarg); add_config_command(command); free(command); break; } case 's': /* --search | -s */ add_script_search_dir(optarg); break; case 'd': /* --debug | -d */ { char *command = alloc_printf("debug_level %s", optarg ? optarg : "3"); command_run_line(cmd_ctx, command); free(command); break; } case 'l': /* --log_output | -l */ if (optarg) { char *command = alloc_printf("log_output %s", optarg); command_run_line(cmd_ctx, command); free(command); } break; case 'c': /* --command | -c */ if (optarg) add_config_command(optarg); break; case 'p': /* to replicate the old syntax this needs to be synchronous * otherwise the gdb stdin will overflow with the warning message */ command_run_line(cmd_ctx, "gdb_port pipe; log_output openocd.log"); LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; " "log_output openocd.log\"' instead."); break; } } if (help_flag) { LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--file | -f\tuse configuration file \n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file \n"); LOG_OUTPUT("--command | -c\trun \n"); exit(-1); } if (version_flag) { /* Nothing to do, version gets printed automatically. */ /* It is not an error to request the VERSION number. */ exit(0); } /* paths specified on the command line take precedence over these * built-in paths */ add_default_dirs(); return ERROR_OK; } openocd-0.9.0/src/helper/system.h0000644000175000017500000000544312315575360013650 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Copyright (C) 2007-2008 by Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H /* standard C library header files */ #include #include #include #include #include #include /* +++ AC_HEADER_TIME +++ */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif /* --- AC_HEADER_TIME --- */ /* +++ platform specific headers +++ */ #ifdef _WIN32 #include #include #include #include #endif /* --- platform specific headers --- */ #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #ifdef __ECOS /* missing from eCos */ #ifndef EFAULT #define EFAULT 14 /* Bad address */ #endif #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_SYS_SELECT_H #include /* select, FD_SET and friends (POSIX.1-2001) */ #endif #ifdef HAVE_SYS_PARAM_H #include /* for MIN/MAX macros */ #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifndef true #define true 1 #define false 0 #endif #endif /* SYSTEM_H */ openocd-0.9.0/src/helper/util.c0000644000175000017500000000444612315575360013276 00000000000000/*************************************************************************** * Copyright (C) 2010 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* this file contains various functionality useful to standalone systems */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "time_support.h" static int util_Jim_Command_ms(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?"); return JIM_ERR; } /* Cast from 64 to 32 bit int works for 2's-compliment * when calculating differences*/ Jim_SetResult(interp, Jim_NewIntObj(interp, (int)timeval_ms())); return JIM_OK; } static const struct command_registration util_command_handlers[] = { /* jim handlers */ { .name = "ms", .mode = COMMAND_ANY, .jim_handler = util_Jim_Command_ms, .help = "Returns ever increasing milliseconds. Used to calculuate differences in time.", .usage = "", }, COMMAND_REGISTRATION_DONE }; int util_init(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, util_command_handlers); } openocd-0.9.0/src/helper/util.h0000644000175000017500000000300212315575360013266 00000000000000/*************************************************************************** * Copyright (C) 2010 by Øyvind Harboe * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef HELPER_UTILS_H #define HELPER_UTILS_H struct command_context; int util_init(struct command_context *cmd_ctx); #endif /* HELPER_UTILS_H */ openocd-0.9.0/src/helper/jim-nvp.c0000644000175000017500000001753012315575360013677 00000000000000/* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * Copyright 2008 Steve Bennett * Copyright 2009 Nico Coesel * Copyright 2009 Zachary T Welch zw@superlucidity.net * Copyright 2009 David Brownell * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. */ #include #include int Jim_GetNvp(Jim_Interp *interp, Jim_Obj *objPtr, const Jim_Nvp *nvp_table, const Jim_Nvp **result) { Jim_Nvp *n; int e; e = Jim_Nvp_name2value_obj(interp, nvp_table, objPtr, &n); if (e == JIM_ERR) return e; /* Success? found? */ if (n->name) { /* remove const */ *result = (Jim_Nvp *) n; return JIM_OK; } else return JIM_ERR; } Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *p, const char *name) { while (p->name) { if (0 == strcmp(name, p->name)) break; p++; } return (Jim_Nvp *) (p); } Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *p, const char *name) { while (p->name) { if (0 == strcasecmp(name, p->name)) break; p++; } return (Jim_Nvp *) (p); } int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **result) { return Jim_Nvp_name2value(interp, p, Jim_String(o), result); } int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *_p, const char *name, Jim_Nvp **result) { const Jim_Nvp *p; p = Jim_Nvp_name2value_simple(_p, name); /* result */ if (result) *result = (Jim_Nvp *) (p); /* found? */ if (p->name) return JIM_OK; else return JIM_ERR; } int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **puthere) { return Jim_Nvp_name2value_nocase(interp, p, Jim_String(o), puthere); } int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *_p, const char *name, Jim_Nvp **puthere) { const Jim_Nvp *p; p = Jim_Nvp_name2value_nocase_simple(_p, name); if (puthere) *puthere = (Jim_Nvp *) (p); /* found */ if (p->name) return JIM_OK; else return JIM_ERR; } int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **result) { int e; jim_wide w; e = Jim_GetWide(interp, o, &w); if (e != JIM_OK) return e; return Jim_Nvp_value2name(interp, p, w, result); } Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *p, int value) { while (p->name) { if (value == p->value) break; p++; } return (Jim_Nvp *) (p); } int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *_p, int value, Jim_Nvp **result) { const Jim_Nvp *p; p = Jim_Nvp_value2name_simple(_p, value); if (result) *result = (Jim_Nvp *) (p); if (p->name) return JIM_OK; else return JIM_ERR; } int Jim_GetOpt_Setup(Jim_GetOptInfo *p, Jim_Interp *interp, int argc, Jim_Obj *const *argv) { memset(p, 0, sizeof(*p)); p->interp = interp; p->argc = argc; p->argv = argv; return JIM_OK; } void Jim_GetOpt_Debug(Jim_GetOptInfo *p) { int x; fprintf(stderr, "---args---\n"); for (x = 0; x < p->argc; x++) fprintf(stderr, "%2d) %s\n", x, Jim_String(p->argv[x])); fprintf(stderr, "-------\n"); } int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere) { Jim_Obj *o; o = NULL; /* failure */ if (goi->argc) { /* success */ o = goi->argv[0]; goi->argc -= 1; goi->argv += 1; } if (puthere) *puthere = o; if (o != NULL) return JIM_OK; else return JIM_ERR; } int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len) { int r; Jim_Obj *o; const char *cp; r = Jim_GetOpt_Obj(goi, &o); if (r == JIM_OK) { cp = Jim_GetString(o, len); if (puthere) { /* remove const */ *puthere = (char *)(cp); } } return r; } int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere) { int r; Jim_Obj *o; double _safe; if (puthere == NULL) puthere = &_safe; r = Jim_GetOpt_Obj(goi, &o); if (r == JIM_OK) { r = Jim_GetDouble(goi->interp, o, puthere); if (r != JIM_OK) Jim_SetResultFormatted(goi->interp, "not a number: %#s", o); } return r; } int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere) { int r; Jim_Obj *o; jim_wide _safe; if (puthere == NULL) puthere = &_safe; r = Jim_GetOpt_Obj(goi, &o); if (r == JIM_OK) r = Jim_GetWide(goi->interp, o, puthere); return r; } int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *nvp, Jim_Nvp **puthere) { Jim_Nvp *_safe; Jim_Obj *o; int e; if (puthere == NULL) puthere = &_safe; e = Jim_GetOpt_Obj(goi, &o); if (e == JIM_OK) e = Jim_Nvp_name2value_obj(goi->interp, nvp, o, puthere); return e; } void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *nvptable, int hadprefix) { if (hadprefix) Jim_SetResult_NvpUnknown(goi->interp, goi->argv[-2], goi->argv[-1], nvptable); else Jim_SetResult_NvpUnknown(goi->interp, NULL, goi->argv[-1], nvptable); } int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char *const *lookup, int *puthere) { int _safe; Jim_Obj *o; int e; if (puthere == NULL) puthere = &_safe; e = Jim_GetOpt_Obj(goi, &o); if (e == JIM_OK) e = Jim_GetEnum(goi->interp, o, lookup, puthere, "option", JIM_ERRMSG); return e; } void Jim_SetResult_NvpUnknown(Jim_Interp *interp, Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp *nvp) { if (param_name) Jim_SetResultFormatted(interp, "%#s: Unknown: %#s, try one of: ", param_name, param_value); else Jim_SetResultFormatted(interp, "Unknown param: %#s, try one of: ", param_value); while (nvp->name) { const char *a; const char *b; if ((nvp + 1)->name) { a = nvp->name; b = ", "; } else { a = "or "; b = nvp->name; } Jim_AppendStrings(interp, Jim_GetResult(interp), a, b, NULL); nvp++; } } const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { static Jim_Obj *debug_string_obj; int x; if (debug_string_obj) Jim_FreeObj(interp, debug_string_obj); debug_string_obj = Jim_NewEmptyStringObj(interp); for (x = 0; x < argc; x++) Jim_AppendStrings(interp, debug_string_obj, Jim_String(argv[x]), " ", NULL); return Jim_String(debug_string_obj); } int Jim_nvpInit(Jim_Interp *interp) { /* This is really a helper library, not an extension, but this is the easy way */ return JIM_OK; } openocd-0.9.0/src/helper/jim-nvp.h0000644000175000017500000002323612315575360013704 00000000000000/* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * Copyright 2008 Steve Bennett * Copyright 2009 Nico Coesel * Copyright 2009 Zachary T Welch zw@superlucidity.net * Copyright 2009 David Brownell * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. */ #ifndef JIM_NVP_H #define JIM_NVP_H #include /** Name Value Pairs, aka: NVP * - Given a string - return the associated int. * - Given a number - return the associated string. * . * * Very useful when the number is not a simple index into an array of * known string, or there may be multiple strings (aliases) that mean then same * thing. * * An NVP Table is terminated with ".name = NULL". * * During the 'name2value' operation, if no matching string is found * the pointer to the terminal element (with p->name == NULL) is returned. * * Example: * \code * const Jim_Nvp yn[] = { * { "yes", 1 }, * { "no" , 0 }, * { "yep", 1 }, * { "nope", 0 }, * { NULL, -1 }, * }; * * Jim_Nvp *result * e = Jim_Nvp_name2value(interp, yn, "y", &result); * returns &yn[0]; * e = Jim_Nvp_name2value(interp, yn, "n", &result); * returns &yn[1]; * e = Jim_Nvp_name2value(interp, yn, "Blah", &result); * returns &yn[4]; * \endcode * * During the number2name operation, the first matching value is returned. */ typedef struct { const char *name; int value; } Jim_Nvp; int Jim_GetNvp(Jim_Interp *interp, Jim_Obj *objPtr, const Jim_Nvp *nvp_table, const Jim_Nvp **result); /* Name Value Pairs Operations */ Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *nvp_table, const char *name); Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *nvp_table, const char *name); Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *nvp_table, int v); int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *nvp_table, int value, Jim_Nvp **result); int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *value_obj, Jim_Nvp **result); /** prints a nice 'unknown' parameter error message to the 'result' */ void Jim_SetResult_NvpUnknown(Jim_Interp *interp, Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp *nvp_table); /** Debug: convert argc/argv into a printable string for printf() debug * * \param interp - the interpeter * \param argc - arg count * \param argv - the objects * * \returns string pointer holding the text. * * Note, next call to this function will free the old (last) string. * * For example might want do this: * \code * fp = fopen("some.file.log", "a"); * fprintf(fp, "PARAMS are: %s\n", Jim_DebugArgvString(interp, argc, argv)); * fclose(fp); * \endcode */ const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv); /** A TCL -ish GetOpt like code. * * Some TCL objects have various "configuration" values. * For example - in Tcl/Tk the "buttons" have many options. * * Usefull when dealing with command options. * that may come in any order... * * Does not support "-foo = 123" type options. * Only supports tcl type options, like "-foo 123" */ typedef struct jim_getopt { Jim_Interp *interp; int argc; Jim_Obj *const *argv; int isconfigure; /* non-zero if configure */ } Jim_GetOptInfo; /** GetOpt - how to. * * Example (short and incomplete): * \code * Jim_GetOptInfo goi; * * Jim_GetOpt_Setup(&goi, interp, argc, argv); * * while (goi.argc) { * e = Jim_GetOpt_Nvp(&goi, nvp_options, &n); * if (e != JIM_OK) { * Jim_GetOpt_NvpUnknown(&goi, nvp_options, 0); * return e; * } * * switch (n->value) { * case ALIVE: * printf("Option ALIVE specified\n"); * break; * case FIRST: * if (goi.argc < 1) { * .. not enough args error .. * } * Jim_GetOpt_String(&goi, &cp, NULL); * printf("FIRSTNAME: %s\n", cp); * case AGE: * Jim_GetOpt_Wide(&goi, &w); * printf("AGE: %d\n", (int)(w)); * break; * case POLITICS: * e = Jim_GetOpt_Nvp(&goi, nvp_politics, &n); * if (e != JIM_OK) { * Jim_GetOpt_NvpUnknown(&goi, nvp_politics, 1); * return e; * } * } * } * * \endcode * */ /** Setup GETOPT * * \param goi - get opt info to be initialized * \param interp - jim interp * \param argc - argc count. * \param argv - argv (will be copied) * * \code * Jim_GetOptInfo goi; * * Jim_GetOptSetup(&goi, interp, argc, argv); * \endcode */ int Jim_GetOpt_Setup(Jim_GetOptInfo *goi, Jim_Interp *interp, int argc, Jim_Obj *const *argv); /** Debug - Dump parameters to stderr * \param goi - current parameters */ void Jim_GetOpt_Debug(Jim_GetOptInfo *goi); /** Remove argv[0] from the list. * * \param goi - get opt info * \param puthere - where param is put * */ int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere); /** Remove argv[0] as string. * * \param goi - get opt info * \param puthere - where param is put * \param len - return its length */ int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len); /** Remove argv[0] as double. * * \param goi - get opt info * \param puthere - where param is put. * */ int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere); /** Remove argv[0] as wide. * * \param goi - get opt info * \param puthere - where param is put. */ int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere); /** Remove argv[0] as NVP. * * \param goi - get opt info * \param lookup - nvp lookup table * \param puthere - where param is put. * */ int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, Jim_Nvp **puthere); /** Create an appropriate error message for an NVP. * * \param goi - options info * \param lookup - the NVP table that was used. * \param hadprefix - 0 or 1 if the option had a prefix. * * This function will set the "interp->result" to a human readable * error message listing the available options. * * This function assumes the previous option argv[-1] is the unknown string. * * If this option had some prefix, then pass "hadprefix = 1" else pass "hadprefix = 0" * * Example: * \code * * while (goi.argc) { * // Get the next option * e = Jim_GetOpt_Nvp(&goi, cmd_options, &n); * if (e != JIM_OK) { * // option was not recognized * // pass 'hadprefix = 0' because there is no prefix * Jim_GetOpt_NvpUnknown(&goi, cmd_options, 0); * return e; * } * * switch (n->value) { * case OPT_SEX: * // handle: --sex male | female | lots | needmore * e = Jim_GetOpt_Nvp(&goi, &nvp_sex, &n); * if (e != JIM_OK) { * Jim_GetOpt_NvpUnknown(&ogi, nvp_sex, 1); * return e; * } * printf("Code: (%d) is %s\n", n->value, n->name); * break; * case ...: * [snip] * } * } * \endcode * */ void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadprefix); /** Remove argv[0] as Enum * * \param goi - get opt info * \param lookup - lookup table. * \param puthere - where param is put. * */ int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char *const *lookup, int *puthere); #endif openocd-0.9.0/src/helper/binarybuffer.c0000644000175000017500000002667712516456302015006 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "log.h" #include "binarybuffer.h" static const unsigned char bit_reverse_table256[] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; void *buf_cpy(const void *from, void *_to, unsigned size) { if (NULL == from || NULL == _to) return NULL; /* copy entire buffer */ memcpy(_to, from, DIV_ROUND_UP(size, 8)); /* mask out bits that don't belong to the buffer */ unsigned trailing_bits = size % 8; if (trailing_bits) { uint8_t *to = _to; to[size / 8] &= (1 << trailing_bits) - 1; } return _to; } static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m) { return (a & m) != (b & m); } static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) { uint8_t mask = (1 << trailing) - 1; return buf_cmp_masked(a, b, mask & m); } bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) { if (!_buf1 || !_buf2) return _buf1 != _buf2; unsigned last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) return false; unsigned trailing = size % 8; if (!trailing) return false; const uint8_t *buf1 = _buf1, *buf2 = _buf2; return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing); } bool buf_cmp_mask(const void *_buf1, const void *_buf2, const void *_mask, unsigned size) { if (!_buf1 || !_buf2) return _buf1 != _buf2 || _buf1 != _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; unsigned last = size / 8; for (unsigned i = 0; i < last; i++) { if (buf_cmp_masked(buf1[i], buf2[i], mask[i])) return true; } unsigned trailing = size % 8; if (!trailing) return false; return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); } void *buf_set_ones(void *_buf, unsigned size) { uint8_t *buf = _buf; if (!buf) return NULL; memset(buf, 0xff, size / 8); unsigned trailing_bits = size % 8; if (trailing_bits) buf[size / 8] = (1 << trailing_bits) - 1; return buf; } void *buf_set_buf(const void *_src, unsigned src_start, void *_dst, unsigned dst_start, unsigned len) { const uint8_t *src = _src; uint8_t *dst = _dst; unsigned i, sb, db, sq, dq, lb, lq; sb = src_start / 8; db = dst_start / 8; sq = src_start % 8; dq = dst_start % 8; lb = len / 8; lq = len % 8; src += sb; dst += db; /* check if both buffers are on byte boundary and * len is a multiple of 8bit so we can simple copy * the buffer */ if ((sq == 0) && (dq == 0) && (lq == 0)) { for (i = 0; i < lb; i++) *dst++ = *src++; return _dst; } /* fallback to slow bit copy */ for (i = 0; i < len; i++) { if (((*src >> (sq&7)) & 1) == 1) *dst |= 1 << (dq&7); else *dst &= ~(1 << (dq&7)); if (sq++ == 7) { sq = 0; src++; } if (dq++ == 7) { dq = 0; dst++; } } return _dst; } uint32_t flip_u32(uint32_t value, unsigned int num) { uint32_t c = (bit_reverse_table256[value & 0xff] << 24) | (bit_reverse_table256[(value >> 8) & 0xff] << 16) | (bit_reverse_table256[(value >> 16) & 0xff] << 8) | (bit_reverse_table256[(value >> 24) & 0xff]); if (num < 32) c = c >> (32 - num); return c; } static int ceil_f_to_u32(float x) { if (x < 0) /* return zero for negative numbers */ return 0; uint32_t y = x; /* cut off fraction */ if ((x - y) > 0.0) /* if there was a fractional part, increase by one */ y++; return y; } char *buf_to_str(const void *_buf, unsigned buf_len, unsigned radix) { float factor; switch (radix) { case 16: factor = 2.0; /* log(256) / log(16) = 2.0 */ break; case 10: factor = 2.40824; /* log(256) / log(10) = 2.40824 */ break; case 8: factor = 2.66667; /* log(256) / log(8) = 2.66667 */ break; default: return NULL; } unsigned str_len = ceil_f_to_u32(DIV_ROUND_UP(buf_len, 8) * factor); char *str = calloc(str_len + 1, 1); const uint8_t *buf = _buf; int b256_len = DIV_ROUND_UP(buf_len, 8); for (int i = b256_len - 1; i >= 0; i--) { uint32_t tmp = buf[i]; if (((unsigned)i == (buf_len / 8)) && (buf_len % 8)) tmp &= (0xff >> (8 - (buf_len % 8))); /* base-256 digits */ for (unsigned j = str_len; j > 0; j--) { tmp += (uint32_t)str[j-1] * 256; str[j-1] = (uint8_t)(tmp % radix); tmp /= radix; } } const char * const DIGITS = "0123456789ABCDEF"; for (unsigned j = 0; j < str_len; j++) str[j] = DIGITS[(int)str[j]]; return str; } /** identify radix, and skip radix-prefix (0, 0x or 0X) */ static void str_radix_guess(const char **_str, unsigned *_str_len, unsigned *_radix) { unsigned radix = *_radix; if (0 != radix) return; const char *str = *_str; unsigned str_len = *_str_len; if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { radix = 16; str += 2; str_len -= 2; } else if ((str[0] == '0') && (str_len != 1)) { radix = 8; str += 1; str_len -= 1; } else radix = 10; *_str = str; *_str_len = str_len; *_radix = radix; } int str_to_buf(const char *str, unsigned str_len, void *_buf, unsigned buf_len, unsigned radix) { str_radix_guess(&str, &str_len, &radix); float factor; if (radix == 16) factor = 0.5; /* log(16) / log(256) = 0.5 */ else if (radix == 10) factor = 0.41524; /* log(10) / log(256) = 0.41524 */ else if (radix == 8) factor = 0.375; /* log(8) / log(256) = 0.375 */ else return 0; /* copy to zero-terminated buffer */ char *charbuf = strndup(str, str_len); /* number of digits in base-256 notation */ unsigned b256_len = ceil_f_to_u32(str_len * factor); uint8_t *b256_buf = calloc(b256_len, 1); /* go through zero terminated buffer * input digits (ASCII) */ unsigned i; for (i = 0; charbuf[i]; i++) { uint32_t tmp = charbuf[i]; if ((tmp >= '0') && (tmp <= '9')) tmp = (tmp - '0'); else if ((tmp >= 'a') && (tmp <= 'f')) tmp = (tmp - 'a' + 10); else if ((tmp >= 'A') && (tmp <= 'F')) tmp = (tmp - 'A' + 10); else continue; /* skip characters other than [0-9,a-f,A-F] */ if (tmp >= radix) continue; /* skip digits invalid for the current radix */ /* base-256 digits */ for (unsigned j = 0; j < b256_len; j++) { tmp += (uint32_t)b256_buf[j] * radix; b256_buf[j] = (uint8_t)(tmp & 0xFF); tmp >>= 8; } } uint8_t *buf = _buf; for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) { if (j < b256_len) buf[j] = b256_buf[j]; else buf[j] = 0; } /* mask out bits that don't belong to the buffer */ if (buf_len % 8) buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8)); free(b256_buf); free(charbuf); return i; } void bit_copy_queue_init(struct bit_copy_queue *q) { INIT_LIST_HEAD(&q->list); } int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, unsigned src_offset, unsigned bit_count) { struct bit_copy_queue_entry *qe = malloc(sizeof(*qe)); if (!qe) return ERROR_FAIL; qe->dst = dst; qe->dst_offset = dst_offset; qe->src = src; qe->src_offset = src_offset; qe->bit_count = bit_count; list_add_tail(&qe->list, &q->list); return ERROR_OK; } void bit_copy_execute(struct bit_copy_queue *q) { struct bit_copy_queue_entry *qe; struct bit_copy_queue_entry *tmp; list_for_each_entry_safe(qe, tmp, &q->list, list) { bit_copy(qe->dst, qe->dst_offset, qe->src, qe->src_offset, qe->bit_count); list_del(&qe->list); free(qe); } } void bit_copy_discard(struct bit_copy_queue *q) { struct bit_copy_queue_entry *qe; struct bit_copy_queue_entry *tmp; list_for_each_entry_safe(qe, tmp, &q->list, list) { list_del(&qe->list); free(qe); } } int unhexify(char *bin, const char *hex, int count) { int i, tmp; for (i = 0; i < count; i++) { if (sscanf(hex + (2 * i), "%02x", &tmp) != 1) return i; bin[i] = tmp; } return i; } int hexify(char *hex, const char *bin, int count, int out_maxlen) { int i, cmd_len = 0; /* May use a length, or a null-terminated string as input. */ if (count == 0) count = strlen(bin); for (i = 0; i < count; i++) cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff); return cmd_len; } void buffer_shr(void *_buf, unsigned buf_len, unsigned count) { unsigned i; unsigned char *buf = _buf; unsigned bytes_to_remove; unsigned shift; bytes_to_remove = count / 8; shift = count - (bytes_to_remove * 8); for (i = 0; i < (buf_len - 1); i++) buf[i] = (buf[i] >> shift) | ((buf[i+1] << (8 - shift)) & 0xff); buf[(buf_len - 1)] = buf[(buf_len - 1)] >> shift; if (bytes_to_remove) { memmove(buf, &buf[bytes_to_remove], buf_len - bytes_to_remove); memset(&buf[buf_len - bytes_to_remove], 0, bytes_to_remove); } } openocd-0.9.0/src/helper/binarybuffer.h0000644000175000017500000002143112516456302014772 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef BINARYBUFFER_H #define BINARYBUFFER_H #include "list.h" /** @file * Support functions to access arbitrary bits in a byte array */ /** * Sets @c num bits in @c _buffer, starting at the @c first bit, * using the bits in @c value. This routine fast-paths writes * of little-endian, byte-aligned, 32-bit words. * @param _buffer The buffer whose bits will be set. * @param first The bit offset in @c _buffer to start writing (0-31). * @param num The number of bits from @c value to copy (1-32). * @param value Up to 32 bits that will be copied to _buffer. */ static inline void buf_set_u32(uint8_t *_buffer, unsigned first, unsigned num, uint32_t value) { uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { buffer[3] = (value >> 24) & 0xff; buffer[2] = (value >> 16) & 0xff; buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { for (unsigned i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else buffer[i / 8] &= ~(1 << (i % 8)); } } } /** * Sets @c num bits in @c _buffer, starting at the @c first bit, * using the bits in @c value. This routine fast-paths writes * of little-endian, byte-aligned, 64-bit words. * @param _buffer The buffer whose bits will be set. * @param first The bit offset in @c _buffer to start writing (0-63). * @param num The number of bits from @c value to copy (1-64). * @param value Up to 64 bits that will be copied to _buffer. */ static inline void buf_set_u64(uint8_t *_buffer, unsigned first, unsigned num, uint64_t value) { uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { buffer[3] = (value >> 24) & 0xff; buffer[2] = (value >> 16) & 0xff; buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else if ((num == 64) && (first == 0)) { buffer[7] = (value >> 56) & 0xff; buffer[6] = (value >> 48) & 0xff; buffer[5] = (value >> 40) & 0xff; buffer[4] = (value >> 32) & 0xff; buffer[3] = (value >> 24) & 0xff; buffer[2] = (value >> 16) & 0xff; buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { for (unsigned i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else buffer[i / 8] &= ~(1 << (i % 8)); } } } /** * Retrieves @c num bits from @c _buffer, starting at the @c first bit, * returning the bits in a 32-bit word. This routine fast-paths reads * of little-endian, byte-aligned, 32-bit words. * @param _buffer The buffer whose bits will be read. * @param first The bit offset in @c _buffer to start reading (0-31). * @param num The number of bits from @c _buffer to read (1-32). * @returns Up to 32-bits that were read from @c _buffer. */ static inline uint32_t buf_get_u32(const uint8_t *_buffer, unsigned first, unsigned num) { const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { return (((uint32_t)buffer[3]) << 24) | (((uint32_t)buffer[2]) << 16) | (((uint32_t)buffer[1]) << 8) | (((uint32_t)buffer[0]) << 0); } else { uint32_t result = 0; for (unsigned i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result |= 1 << (i - first); } return result; } } /** * Retrieves @c num bits from @c _buffer, starting at the @c first bit, * returning the bits in a 64-bit word. This routine fast-paths reads * of little-endian, byte-aligned, 64-bit words. * @param _buffer The buffer whose bits will be read. * @param first The bit offset in @c _buffer to start reading (0-63). * @param num The number of bits from @c _buffer to read (1-64). * @returns Up to 64-bits that were read from @c _buffer. */ static inline uint64_t buf_get_u64(const uint8_t *_buffer, unsigned first, unsigned num) { const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { return 0 + ((((uint32_t)buffer[3]) << 24) | /* Note - zero plus is to avoid a checkpatch bug */ (((uint32_t)buffer[2]) << 16) | (((uint32_t)buffer[1]) << 8) | (((uint32_t)buffer[0]) << 0)); } else if ((num == 64) && (first == 0)) { return 0 + ((((uint64_t)buffer[7]) << 56) | /* Note - zero plus is to avoid a checkpatch bug */ (((uint64_t)buffer[6]) << 48) | (((uint64_t)buffer[5]) << 40) | (((uint64_t)buffer[4]) << 32) | (((uint64_t)buffer[3]) << 24) | (((uint64_t)buffer[2]) << 16) | (((uint64_t)buffer[1]) << 8) | (((uint64_t)buffer[0]) << 0)); } else { uint64_t result = 0; for (unsigned i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result = result | ((uint64_t)1 << (uint64_t)(i - first)); } return result; } } /** * Inverts the ordering of bits inside a 32-bit word (e.g. 31..0 -> 0..31). * This routine can be used to flip smaller data types by using smaller * values for @c width. * @param value The word to flip. * @param width The number of bits in value (2-32). * @returns A 32-bit word with @c value in reversed bit-order. */ uint32_t flip_u32(uint32_t value, unsigned width); bool buf_cmp(const void *buf1, const void *buf2, unsigned size); bool buf_cmp_mask(const void *buf1, const void *buf2, const void *mask, unsigned size); /** * Copies @c size bits out of @c from and into @c to. Any extra * bits in the final byte will be set to zero. * @param from The buffer to copy into @c to. * @param to The buffer that will receive the copy of @c from. * @param size The number of bits to copy. */ void *buf_cpy(const void *from, void *to, unsigned size); /** * Set the contents of @c buf with @c count bits, all set to 1. * @param buf The buffer to fill with ones. * @param size The number of bits. * @returns The original buffer (@c buf). */ void *buf_set_ones(void *buf, unsigned size); void *buf_set_buf(const void *src, unsigned src_start, void *dst, unsigned dst_start, unsigned len); int str_to_buf(const char *str, unsigned len, void *bin_buf, unsigned buf_size, unsigned radix); char *buf_to_str(const void *buf, unsigned size, unsigned radix); /* read a uint32_t from a buffer in target memory endianness */ static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le) { return le ? le_to_h_u32(p) : be_to_h_u32(p); } static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src, unsigned src_offset, unsigned bit_count) { buf_set_buf(src, src_offset, dst, dst_offset, bit_count); } struct bit_copy_queue { struct list_head list; }; struct bit_copy_queue_entry { uint8_t *dst; unsigned dst_offset; const uint8_t *src; unsigned src_offset; unsigned bit_count; struct list_head list; }; void bit_copy_queue_init(struct bit_copy_queue *q); int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, unsigned src_offset, unsigned bit_count); void bit_copy_execute(struct bit_copy_queue *q); void bit_copy_discard(struct bit_copy_queue *q); /* functions to convert to/from hex encoded buffer * used in ti-icdi driver and gdb server */ int unhexify(char *bin, const char *hex, int count); int hexify(char *hex, const char *bin, int count, int out_maxlen); void buffer_shr(void *_buf, unsigned buf_len, unsigned count); #endif /* BINARYBUFFER_H */ openocd-0.9.0/src/helper/ioutil_stubs.c0000644000175000017500000000311312315575360015034 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "ioutil.h" #include "log.h" int ioutil_init(struct command_context *cmd_ctx) { LOG_DEBUG("libocdhelper was built without I/O utility support"); return ERROR_OK; } openocd-0.9.0/src/helper/configuration.c0000644000175000017500000001065212315575360015164 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "configuration.h" #include "log.h" static size_t num_config_files; static char **config_file_names; static size_t num_script_dirs; static char **script_search_dirs; void add_script_search_dir(const char *dir) { num_script_dirs++; script_search_dirs = realloc(script_search_dirs, (num_script_dirs + 1) * sizeof(char *)); script_search_dirs[num_script_dirs-1] = strdup(dir); script_search_dirs[num_script_dirs] = NULL; LOG_DEBUG("adding %s", dir); } void add_config_command(const char *cfg) { num_config_files++; config_file_names = realloc(config_file_names, (num_config_files + 1) * sizeof(char *)); config_file_names[num_config_files-1] = strdup(cfg); config_file_names[num_config_files] = NULL; } /* return full path or NULL according to search rules */ char *find_file(const char *file) { FILE *fp = NULL; char **search_dirs = script_search_dirs; char *dir; char const *mode = "r"; char *full_path; /* Check absolute and relative to current working dir first. * This keeps full_path reporting belowing working. */ full_path = alloc_printf("%s", file); fp = fopen(full_path, mode); while (!fp) { free(full_path); full_path = NULL; dir = *search_dirs++; if (!dir) break; full_path = alloc_printf("%s/%s", dir, file); fp = fopen(full_path, mode); } if (fp) { fclose(fp); LOG_DEBUG("found %s", full_path); return full_path; } free(full_path); return NULL; } FILE *open_file_from_path(const char *file, const char *mode) { if (mode[0] != 'r') return fopen(file, mode); else { char *full_path = find_file(file); if (full_path == NULL) return NULL; FILE *fp = NULL; fp = fopen(full_path, mode); free(full_path); return fp; } } int parse_config_file(struct command_context *cmd_ctx) { int retval; char **cfg; if (!config_file_names) { command_run_line(cmd_ctx, "script openocd.cfg"); return ERROR_OK; } cfg = config_file_names; while (*cfg) { retval = command_run_line(cmd_ctx, *cfg); if (retval != ERROR_OK) return retval; cfg++; } return ERROR_OK; } #ifndef _WIN32 #include #endif char *get_home_dir(const char *append_path) { char *home = getenv("HOME"); if (home == NULL) { #ifdef _WIN32 home = getenv("USERPROFILE"); if (home == NULL) { char homepath[MAX_PATH]; char *drive = getenv("HOMEDRIVE"); char *path = getenv("HOMEPATH"); if (drive && path) { snprintf(homepath, MAX_PATH, "%s/%s", drive, path); home = homepath; } } #else struct passwd *pwd = getpwuid(getuid()); if (pwd) home = pwd->pw_dir; #endif } if (home == NULL) return home; char *home_path; if (append_path) home_path = alloc_printf("%s/%s", home, append_path); else home_path = alloc_printf("%s", home); return home_path; } openocd-0.9.0/src/helper/configuration.h0000644000175000017500000000433212315575360015167 00000000000000/*************************************************************************** * Copyright (C) 2004, 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef CONFIGURATION_H #define CONFIGURATION_H #include int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]); int parse_config_file(struct command_context *cmd_ctx); void add_config_command(const char *cfg); void add_script_search_dir(const char *dir); int configuration_output_handler(struct command_context *cmd_ctx, const char *line); FILE *open_file_from_path(const char *file, const char *mode); char *find_file(const char *name); char *get_home_dir(const char *append_path); #endif /* CONFIGURATION_H */ openocd-0.9.0/src/Makefile.am0000644000175000017500000000524712516456302012727 00000000000000include $(top_srcdir)/common.mk SUBDIRS = \ jtag \ helper \ target \ transport \ flash \ svf \ xsvf \ pld \ server \ rtos noinst_LTLIBRARIES = libopenocd.la bin_PROGRAMS = openocd MAINFILE = main.c openocd_SOURCES = $(MAINFILE) openocd_LDADD = libopenocd.la if INTERNAL_JIMTCL openocd_LDADD += $(top_builddir)/jimtcl/libjim.a else openocd_LDADD += -ljim endif if ULINK openocd_LDADD += -lm endif libopenocd_la_SOURCES = \ hello.c \ openocd.c noinst_HEADERS = \ hello.h \ openocd.h libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\" # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" if RELEASE libopenocd_la_CPPFLAGS += -DRELSTR=\"\" libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" else libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" endif # add default CPPFLAGS libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) # the library search path. libopenocd_la_LDFLAGS = $(all_libraries) if IS_MINGW MINGWLDADD = -lws2_32 else MINGWLDADD = endif libopenocd_la_LIBADD = \ $(top_builddir)/src/xsvf/libxsvf.la \ $(top_builddir)/src/svf/libsvf.la \ $(top_builddir)/src/pld/libpld.la \ $(top_builddir)/src/jtag/libjtag.la \ $(top_builddir)/src/transport/libtransport.la \ $(top_builddir)/src/flash/libflash.la \ $(top_builddir)/src/target/libtarget.la \ $(top_builddir)/src/server/libserver.la \ $(top_builddir)/src/rtos/librtos.la \ $(top_builddir)/src/helper/libhelper.la \ $(LIBFTDI_LIBS) $(MINGWLDADD) \ $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) STARTUP_TCL_SRCS = \ $(srcdir)/helper/startup.tcl \ $(srcdir)/jtag/startup.tcl \ $(srcdir)/target/startup.tcl \ $(srcdir)/flash/startup.tcl \ $(srcdir)/server/startup.tcl EXTRA_DIST = $(STARTUP_TCL_SRCS) BUILT_SOURCES = startup_tcl.inc startup.tcl: $(STARTUP_TCL_SRCS) cat $^ > $@ BIN2C = $(top_srcdir)/src/helper/bin2char.sh # Convert .tcl to c-array startup_tcl.inc: startup.tcl $(BIN2C) $(BIN2C) < $< > $@ || { rm -f $@; false; } # add generated files to make clean list CLEANFILES = startup.tcl startup_tcl.inc # we do not want generated file in the dist dist-hook: rm -f $(distdir)/startup_tcl.inc MAINTAINERCLEANFILES = $(srcdir)/Makefile.in # The "quick" target builds executables & reinstalls the executables # Primary use: developer types to quicken the edit/compile/debug # cycle. by not requiring a "full build and full install". Note the # assumption is: You are only rebuilding the EXE.... and everything # else is/was previously installed. # # use at your own risk quick: all install-binPROGRAMS openocd-0.9.0/src/Makefile.in0000644000175000017500000007507112526201647012743 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl bin_PROGRAMS = openocd$(EXEEXT) @INTERNAL_JIMTCL_TRUE@am__append_2 = $(top_builddir)/jimtcl/libjim.a @INTERNAL_JIMTCL_FALSE@am__append_3 = -ljim @ULINK_TRUE@am__append_4 = -lm # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" @RELEASE_TRUE@am__append_5 = -DRELSTR=\"\" -DGITVERSION=\"\" @RELEASE_FALSE@am__append_6 = -DRELSTR=\"`$(top_srcdir)/guess-rev.sh \ @RELEASE_FALSE@ $(top_srcdir)`\" -DGITVERSION=\"`cd \ @RELEASE_FALSE@ $(top_srcdir) && git describe`\" subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libopenocd_la_DEPENDENCIES = $(top_builddir)/src/xsvf/libxsvf.la \ $(top_builddir)/src/svf/libsvf.la \ $(top_builddir)/src/pld/libpld.la \ $(top_builddir)/src/jtag/libjtag.la \ $(top_builddir)/src/transport/libtransport.la \ $(top_builddir)/src/flash/libflash.la \ $(top_builddir)/src/target/libtarget.la \ $(top_builddir)/src/server/libserver.la \ $(top_builddir)/src/rtos/librtos.la \ $(top_builddir)/src/helper/libhelper.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libopenocd_la_OBJECTS = libopenocd_la-hello.lo \ libopenocd_la-openocd.lo libopenocd_la_OBJECTS = $(am_libopenocd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libopenocd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libopenocd_la_LDFLAGS) $(LDFLAGS) -o $@ am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__objects_1 = main.$(OBJEXT) am_openocd_OBJECTS = $(am__objects_1) openocd_OBJECTS = $(am_openocd_OBJECTS) openocd_DEPENDENCIES = libopenocd.la $(am__append_2) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libopenocd_la_SOURCES) $(openocd_SOURCES) DIST_SOURCES = $(libopenocd_la_SOURCES) $(openocd_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) SUBDIRS = \ jtag \ helper \ target \ transport \ flash \ svf \ xsvf \ pld \ server \ rtos noinst_LTLIBRARIES = libopenocd.la MAINFILE = main.c openocd_SOURCES = $(MAINFILE) openocd_LDADD = libopenocd.la $(am__append_2) $(am__append_3) \ $(am__append_4) libopenocd_la_SOURCES = \ hello.c \ openocd.c noinst_HEADERS = \ hello.h \ openocd.h # add default CPPFLAGS libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\" \ $(am__append_5) $(am__append_6) $(AM_CPPFLAGS) $(CPPFLAGS) # the library search path. libopenocd_la_LDFLAGS = $(all_libraries) @IS_MINGW_FALSE@MINGWLDADD = @IS_MINGW_TRUE@MINGWLDADD = -lws2_32 libopenocd_la_LIBADD = \ $(top_builddir)/src/xsvf/libxsvf.la \ $(top_builddir)/src/svf/libsvf.la \ $(top_builddir)/src/pld/libpld.la \ $(top_builddir)/src/jtag/libjtag.la \ $(top_builddir)/src/transport/libtransport.la \ $(top_builddir)/src/flash/libflash.la \ $(top_builddir)/src/target/libtarget.la \ $(top_builddir)/src/server/libserver.la \ $(top_builddir)/src/rtos/librtos.la \ $(top_builddir)/src/helper/libhelper.la \ $(LIBFTDI_LIBS) $(MINGWLDADD) \ $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) STARTUP_TCL_SRCS = \ $(srcdir)/helper/startup.tcl \ $(srcdir)/jtag/startup.tcl \ $(srcdir)/target/startup.tcl \ $(srcdir)/flash/startup.tcl \ $(srcdir)/server/startup.tcl EXTRA_DIST = $(STARTUP_TCL_SRCS) BUILT_SOURCES = startup_tcl.inc BIN2C = $(top_srcdir)/src/helper/bin2char.sh # add generated files to make clean list CLEANFILES = startup.tcl startup_tcl.inc MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libopenocd.la: $(libopenocd_la_OBJECTS) $(libopenocd_la_DEPENDENCIES) $(EXTRA_libopenocd_la_DEPENDENCIES) $(AM_V_CCLD)$(libopenocd_la_LINK) $(libopenocd_la_OBJECTS) $(libopenocd_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list openocd$(EXEEXT): $(openocd_OBJECTS) $(openocd_DEPENDENCIES) $(EXTRA_openocd_DEPENDENCIES) @rm -f openocd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(openocd_OBJECTS) $(openocd_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libopenocd_la-hello.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libopenocd_la-openocd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libopenocd_la-hello.lo: hello.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libopenocd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libopenocd_la-hello.lo -MD -MP -MF $(DEPDIR)/libopenocd_la-hello.Tpo -c -o libopenocd_la-hello.lo `test -f 'hello.c' || echo '$(srcdir)/'`hello.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libopenocd_la-hello.Tpo $(DEPDIR)/libopenocd_la-hello.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hello.c' object='libopenocd_la-hello.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libopenocd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libopenocd_la-hello.lo `test -f 'hello.c' || echo '$(srcdir)/'`hello.c libopenocd_la-openocd.lo: openocd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libopenocd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libopenocd_la-openocd.lo -MD -MP -MF $(DEPDIR)/libopenocd_la-openocd.Tpo -c -o libopenocd_la-openocd.lo `test -f 'openocd.c' || echo '$(srcdir)/'`openocd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libopenocd_la-openocd.Tpo $(DEPDIR)/libopenocd_la-openocd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openocd.c' object='libopenocd_la-openocd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libopenocd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libopenocd_la-openocd.lo `test -f 'openocd.c' || echo '$(srcdir)/'`openocd.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am dist-hook \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS startup.tcl: $(STARTUP_TCL_SRCS) cat $^ > $@ # Convert .tcl to c-array startup_tcl.inc: startup.tcl $(BIN2C) $(BIN2C) < $< > $@ || { rm -f $@; false; } # we do not want generated file in the dist dist-hook: rm -f $(distdir)/startup_tcl.inc # The "quick" target builds executables & reinstalls the executables # Primary use: developer types to quicken the edit/compile/debug # cycle. by not requiring a "full build and full install". Note the # assumption is: You are only rebuilding the EXE.... and everything # else is/was previously installed. # # use at your own risk quick: all install-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/openocd.c0000644000175000017500000002307212516456303012463 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 Richard Missenden * * richard.missenden@googlemail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "openocd.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_STRINGS_H #include #endif #define OPENOCD_VERSION \ "Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")" static const char openocd_startup_tcl[] = { #include "startup_tcl.inc" 0 /* Terminate with zero */ }; /* Give scripts and TELNET a way to find out what version this is */ static int jim_version_command(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { if (argc > 2) return JIM_ERR; const char *str = ""; char *version_str; version_str = OPENOCD_VERSION; if (argc == 2) str = Jim_GetString(argv[1], NULL); if (strcmp("git", str) == 0) version_str = GITVERSION; Jim_SetResult(interp, Jim_NewStringObj(interp, version_str, -1)); return JIM_OK; } static int log_target_callback_event_handler(struct target *target, enum target_event event, void *priv) { switch (event) { case TARGET_EVENT_GDB_START: target->display = 0; break; case TARGET_EVENT_GDB_END: target->display = 1; break; case TARGET_EVENT_HALTED: if (target->display) { /* do not display information when debugger caused the halt */ target_arch_state(target); } break; default: break; } return ERROR_OK; } static bool init_at_startup = true; COMMAND_HANDLER(handle_noinit_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; init_at_startup = false; return ERROR_OK; } /* OpenOCD can't really handle failure of this command. Patches welcome! :-) */ COMMAND_HANDLER(handle_init_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; int retval; static int initialized; if (initialized) return ERROR_OK; initialized = 1; retval = command_run_line(CMD_CTX, "target init"); if (ERROR_OK != retval) return ERROR_FAIL; retval = adapter_init(CMD_CTX); if (retval != ERROR_OK) { /* we must be able to set up the debug adapter */ return retval; } LOG_DEBUG("Debug Adapter init complete"); /* "transport init" verifies the expected devices are present; * for JTAG, it checks the list of configured TAPs against * what's discoverable, possibly with help from the platform's * JTAG event handlers. (which require COMMAND_EXEC) */ command_context_mode(CMD_CTX, COMMAND_EXEC); retval = command_run_line(CMD_CTX, "transport init"); if (ERROR_OK != retval) return ERROR_FAIL; LOG_DEBUG("Examining targets..."); if (target_examine() != ERROR_OK) LOG_DEBUG("target examination failed"); command_context_mode(CMD_CTX, COMMAND_CONFIG); if (command_run_line(CMD_CTX, "flash init") != ERROR_OK) return ERROR_FAIL; if (command_run_line(CMD_CTX, "mflash init") != ERROR_OK) return ERROR_FAIL; if (command_run_line(CMD_CTX, "nand init") != ERROR_OK) return ERROR_FAIL; if (command_run_line(CMD_CTX, "pld init") != ERROR_OK) return ERROR_FAIL; command_context_mode(CMD_CTX, COMMAND_EXEC); /* initialize telnet subsystem */ gdb_target_add_all(all_targets); target_register_event_callback(log_target_callback_event_handler, CMD_CTX); return ERROR_OK; } COMMAND_HANDLER(handle_add_script_search_dir_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; add_script_search_dir(CMD_ARGV[0]); return ERROR_OK; } static const struct command_registration openocd_command_handlers[] = { { .name = "version", .jim_handler = jim_version_command, .mode = COMMAND_ANY, .help = "show program version", }, { .name = "noinit", .handler = &handle_noinit_command, .mode = COMMAND_CONFIG, .help = "Prevent 'init' from being called at startup.", .usage = "" }, { .name = "init", .handler = &handle_init_command, .mode = COMMAND_ANY, .help = "Initializes configured targets and servers. " "Changes command mode from CONFIG to EXEC. " "Unless 'noinit' is called, this command is " "called automatically at the end of startup.", .usage = "" }, { .name = "add_script_search_dir", .handler = &handle_add_script_search_dir_command, .mode = COMMAND_ANY, .help = "dir to search for config files and scripts", .usage = "" }, COMMAND_REGISTRATION_DONE }; static int openocd_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, openocd_command_handlers); } struct command_context *global_cmd_ctx; /* NB! this fn can be invoked outside this file for non PC hosted builds * NB! do not change to 'static'!!!! */ struct command_context *setup_command_handler(Jim_Interp *interp) { log_init(); LOG_DEBUG("log_init: complete"); struct command_context *cmd_ctx = command_init(openocd_startup_tcl, interp); /* register subsystem commands */ typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value); static const command_registrant_t command_registrants[] = { &openocd_register_commands, &server_register_commands, &gdb_register_commands, &log_register_commands, &transport_register_commands, &interface_register_commands, &target_register_commands, &flash_register_commands, &nand_register_commands, &pld_register_commands, &mflash_register_commands, NULL }; for (unsigned i = 0; NULL != command_registrants[i]; i++) { int retval = (*command_registrants[i])(cmd_ctx); if (ERROR_OK != retval) { command_done(cmd_ctx); return NULL; } } LOG_DEBUG("command registration: complete"); LOG_OUTPUT(OPENOCD_VERSION "\n" "Licensed under GNU GPL v2\n"); global_cmd_ctx = cmd_ctx; return cmd_ctx; } /** OpenOCD runtime meat that can become single-thread in future. It parse * commandline, reads configuration, sets up the target and starts server loop. * Commandline arguments are passed into this function from openocd_main(). */ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ctx) { int ret; if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK) return ERROR_FAIL; if (server_preinit() != ERROR_OK) return ERROR_FAIL; ret = parse_config_file(cmd_ctx); if (ret == ERROR_COMMAND_CLOSE_CONNECTION) return ERROR_OK; else if (ret != ERROR_OK) return ERROR_FAIL; ret = server_init(cmd_ctx); if (ERROR_OK != ret) return ERROR_FAIL; if (init_at_startup) { ret = command_run_line(cmd_ctx, "init"); if (ERROR_OK != ret) return ERROR_FAIL; } ret = server_loop(cmd_ctx); int last_signal = server_quit(); if (last_signal != ERROR_OK) return last_signal; if (ret != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } /* normally this is the main() function entry, but if OpenOCD is linked * into application, then this fn will not be invoked, but rather that * application will have it's own implementation of main(). */ int openocd_main(int argc, char *argv[]) { int ret; /* initialize commandline interface */ struct command_context *cmd_ctx; cmd_ctx = setup_command_handler(NULL); if (util_init(cmd_ctx) != ERROR_OK) return EXIT_FAILURE; if (ioutil_init(cmd_ctx) != ERROR_OK) return EXIT_FAILURE; LOG_OUTPUT("For bug reports, read\n\t" "http://openocd.org/doc/doxygen/bugs.html" "\n"); command_context_mode(cmd_ctx, COMMAND_CONFIG); command_set_output_handler(cmd_ctx, configuration_output_handler, NULL); /* Start the executable meat that can evolve into thread in future. */ ret = openocd_thread(argc, argv, cmd_ctx); unregister_all_commands(cmd_ctx, NULL); /* free commandline interface */ command_done(cmd_ctx); adapter_quit(); if (ERROR_FAIL == ret) return EXIT_FAILURE; else if (ERROR_OK != ret) exit_on_signal(ret); return ret; } openocd-0.9.0/src/openocd.h0000644000175000017500000000346512516456303012474 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2009 by Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OPENOCD_H #define OPENOCD_H /** * Different applications can define this entry point to override * the default openocd main function. On most systems, this will be * defined in src/openocd.c. * @param argc normally passed from main() * @param argv normally passed from main() * @returns return code for main() */ int openocd_main(int argc, char *argv[]); #endif openocd-0.9.0/src/main.c0000644000175000017500000000404112315575361011756 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "openocd.h" /* This is the main entry for developer PC hosted OpenOCD. * * OpenOCD can also be used as a library that is linked with * another application(not mainstream yet, but possible), e.g. * w/as an embedded application. * * Those applications will have their own main() implementation * and use bits and pieces from openocd.c. */ int main(int argc, char *argv[]) { /* disable buffering otherwise piping to logs causes problems work */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); return openocd_main(argc, argv); } openocd-0.9.0/src/hello.c0000644000175000017500000000653712315575360012150 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include COMMAND_HANDLER(handle_foo_command) { if (CMD_ARGC < 1 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); const char *msg = ""; if (CMD_ARGC == 2) { bool enable; COMMAND_PARSE_ENABLE(CMD_ARGV[1], enable); msg = enable ? "enable" : "disable"; } LOG_INFO("%s: address=0x%8.8" PRIx32 " enabled=%s", CMD_NAME, address, msg); return ERROR_OK; } static bool foo_flag; COMMAND_HANDLER(handle_flag_command) { return CALL_COMMAND_HANDLER(handle_command_parse_bool, &foo_flag, "foo flag"); } static const struct command_registration foo_command_handlers[] = { { .name = "bar", .handler = &handle_foo_command, .mode = COMMAND_ANY, .usage = "address ['enable'|'disable']", .help = "an example command", }, { .name = "baz", .handler = &handle_foo_command, .mode = COMMAND_ANY, .usage = "address ['enable'|'disable']", .help = "a sample command", }, { .name = "flag", .handler = &handle_flag_command, .mode = COMMAND_ANY, .usage = "[on|off]", .help = "set a flag", }, COMMAND_REGISTRATION_DONE }; static COMMAND_HELPER(handle_hello_args, const char **sep, const char **name) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (1 == CMD_ARGC) { *sep = " "; *name = CMD_ARGV[0]; } else *sep = *name = ""; return ERROR_OK; } COMMAND_HANDLER(handle_hello_command) { const char *sep, *name; int retval = CALL_COMMAND_HANDLER(handle_hello_args, &sep, &name); if (ERROR_OK == retval) command_print(CMD_CTX, "Greetings%s%s!", sep, name); return retval; } const struct command_registration hello_command_handlers[] = { { .name = "hello", .handler = handle_hello_command, .mode = COMMAND_ANY, .help = "prints a warm welcome", .usage = "[name]", }, { .name = "foo", .mode = COMMAND_ANY, .help = "example command handler skeleton", .chain = foo_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/hello.h0000644000175000017500000000321112315575360012137 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OPENOCD_HELLO_H #define OPENOCD_HELLO_H struct command_registration; /** * Export the registration for the hello command group, so it can be * embedded in example drivers. */ extern const struct command_registration hello_command_handlers[]; #endif /* OPENOCD_HELLO_H */ openocd-0.9.0/src/server/0000755000175000017500000000000012526202226012244 500000000000000openocd-0.9.0/src/server/tcl_server.c0000644000175000017500000001771712526201107014512 00000000000000/*************************************************************************** * Copyright (C) 2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tcl_server.h" #include #define TCL_SERVER_VERSION "TCL Server 0.1" #define TCL_MAX_LINE (4096) struct tcl_connection { int tc_linedrop; int tc_lineoffset; char tc_line[TCL_MAX_LINE]; int tc_outerror;/* flag an output error */ enum target_state tc_laststate; bool tc_notify; }; static char *tcl_port; /* handlers */ static int tcl_new_connection(struct connection *connection); static int tcl_input(struct connection *connection); static int tcl_output(struct connection *connection, const void *buf, ssize_t len); static int tcl_closed(struct connection *connection); static int tcl_target_callback_event_handler(struct target *target, enum target_event event, void *priv) { struct connection *connection = priv; struct tcl_connection *tclc; char buf[256]; tclc = connection->priv; if (tclc->tc_notify) { snprintf(buf, sizeof(buf), "type target_event event %s\r\n\x1a", target_event_name(event)); tcl_output(connection, buf, strlen(buf)); } if (tclc->tc_laststate != target->state) { tclc->tc_laststate = target->state; if (tclc->tc_notify) { snprintf(buf, sizeof(buf), "type target_state state %s\r\n\x1a", target_state_name(target)); tcl_output(connection, buf, strlen(buf)); } } return ERROR_OK; } static int tcl_target_callback_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv) { struct connection *connection = priv; struct tcl_connection *tclc; char buf[256]; tclc = connection->priv; if (tclc->tc_notify) { snprintf(buf, sizeof(buf), "type target_reset mode %s\r\n\x1a", target_reset_mode_name(reset_mode)); tcl_output(connection, buf, strlen(buf)); } return ERROR_OK; } /* write data out to a socket. * * this is a blocking write, so the return value must equal the length, if * that is not the case then flag the connection with an output error. */ int tcl_output(struct connection *connection, const void *data, ssize_t len) { ssize_t wlen; struct tcl_connection *tclc; tclc = connection->priv; if (tclc->tc_outerror) return ERROR_SERVER_REMOTE_CLOSED; wlen = connection_write(connection, data, len); if (wlen == len) return ERROR_OK; LOG_ERROR("error during write: %d != %d", (int)wlen, (int)len); tclc->tc_outerror = 1; return ERROR_SERVER_REMOTE_CLOSED; } /* connections */ static int tcl_new_connection(struct connection *connection) { struct tcl_connection *tclc; tclc = malloc(sizeof(struct tcl_connection)); if (tclc == NULL) return ERROR_CONNECTION_REJECTED; memset(tclc, 0, sizeof(struct tcl_connection)); connection->priv = tclc; struct target *target = get_target_by_num(connection->cmd_ctx->current_target); if (target != NULL) tclc->tc_laststate = target->state; /* store the connection object on cmd_ctx so we can access it from command handlers */ connection->cmd_ctx->output_handler_priv = connection; target_register_event_callback(tcl_target_callback_event_handler, connection); target_register_reset_callback(tcl_target_callback_reset_handler, connection); return ERROR_OK; } static int tcl_input(struct connection *connection) { Jim_Interp *interp = (Jim_Interp *)connection->cmd_ctx->interp; int retval; int i; ssize_t rlen; const char *result; int reslen; struct tcl_connection *tclc; unsigned char in[256]; rlen = connection_read(connection, &in, sizeof(in)); if (rlen <= 0) { if (rlen < 0) LOG_ERROR("error during read: %s", strerror(errno)); return ERROR_SERVER_REMOTE_CLOSED; } tclc = connection->priv; if (tclc == NULL) return ERROR_CONNECTION_REJECTED; /* push as much data into the line as possible */ for (i = 0; i < rlen; i++) { /* buffer the data */ tclc->tc_line[tclc->tc_lineoffset] = in[i]; if (tclc->tc_lineoffset < TCL_MAX_LINE) tclc->tc_lineoffset++; else tclc->tc_linedrop = 1; /* ctrl-z is end of command. When testing from telnet, just * press ctrl-z a couple of times first to put telnet into the * mode where it will send 0x1a in response to pressing ctrl-z */ if (in[i] != '\x1a') continue; /* process the line */ if (tclc->tc_linedrop) { #define ESTR "line too long\n" retval = tcl_output(connection, ESTR, sizeof(ESTR)); if (retval != ERROR_OK) return retval; #undef ESTR } else { tclc->tc_line[tclc->tc_lineoffset-1] = '\0'; retval = command_run_line(connection->cmd_ctx, tclc->tc_line); result = Jim_GetString(Jim_GetResult(interp), &reslen); retval = tcl_output(connection, result, reslen); if (retval != ERROR_OK) return retval; /* Always output ctrl-d as end of line to allow multiline results */ tcl_output(connection, "\x1a", 1); } tclc->tc_lineoffset = 0; tclc->tc_linedrop = 0; } return ERROR_OK; } static int tcl_closed(struct connection *connection) { /* cleanup connection context */ if (connection->priv) { free(connection->priv); connection->priv = NULL; } target_unregister_event_callback(tcl_target_callback_event_handler, connection); target_unregister_reset_callback(tcl_target_callback_reset_handler, connection); return ERROR_OK; } int tcl_init(void) { if (strcmp(tcl_port, "disabled") == 0) { LOG_INFO("tcl server disabled"); return ERROR_OK; } return add_service("tcl", tcl_port, 1, &tcl_new_connection, &tcl_input, &tcl_closed, NULL); } COMMAND_HANDLER(handle_tcl_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &tcl_port); } COMMAND_HANDLER(handle_tcl_notifications_command) { struct connection *connection = NULL; struct tcl_connection *tclc = NULL; if (CMD_CTX->output_handler_priv != NULL) connection = CMD_CTX->output_handler_priv; if (connection != NULL && !strcmp(connection->service->name, "tcl")) { tclc = connection->priv; return CALL_COMMAND_HANDLER(handle_command_parse_bool, &tclc->tc_notify, "Target Notification output is"); } else { LOG_ERROR("%s: can only be called from the tcl server", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } } static const struct command_registration tcl_command_handlers[] = { { .name = "tcl_port", .handler = handle_tcl_port_command, .mode = COMMAND_ANY, .help = "Specify port on which to listen " "for incoming Tcl syntax. " "Read help on 'gdb_port'.", .usage = "[port_num]", }, { .name = "tcl_notifications", .handler = handle_tcl_notifications_command, .mode = COMMAND_EXEC, .help = "Target Notification output", .usage = "[on|off]", }, COMMAND_REGISTRATION_DONE }; int tcl_register_commands(struct command_context *cmd_ctx) { tcl_port = strdup("6666"); return register_commands(cmd_ctx, NULL, tcl_command_handlers); } openocd-0.9.0/src/server/tcl_server.h0000644000175000017500000000304412315575361014517 00000000000000/*************************************************************************** * Copyright (C) 2008 * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef _TCL_SERVER_H_ #define _TCL_SERVER_H_ #include int tcl_init(void); int tcl_register_commands(struct command_context *cmd_ctx); #endif /* _TCL_SERVER_H_ */ openocd-0.9.0/src/server/telnet_server.c0000644000175000017500000004751712315575361015240 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "telnet_server.h" #include #include static char *telnet_port; static char *negotiate = "\xFF\xFB\x03" /* IAC WILL Suppress Go Ahead */ "\xFF\xFB\x01" /* IAC WILL Echo */ "\xFF\xFD\x03" /* IAC DO Suppress Go Ahead */ "\xFF\xFE\x01"; /* IAC DON'T Echo */ #define CTRL(c) (c - '@') #define TELNET_HISTORY ".openocd_history" /* The only way we can detect that the socket is closed is the first time * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ static int telnet_write(struct connection *connection, const void *data, int len) { struct telnet_connection *t_con = connection->priv; if (t_con->closed) return ERROR_SERVER_REMOTE_CLOSED; if (connection_write(connection, data, len) == len) return ERROR_OK; t_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } static int telnet_prompt(struct connection *connection) { struct telnet_connection *t_con = connection->priv; return telnet_write(connection, t_con->prompt, strlen(t_con->prompt)); } static int telnet_outputline(struct connection *connection, const char *line) { int len; /* process lines in buffer */ while (*line) { char *line_end = strchr(line, '\n'); if (line_end) len = line_end-line; else len = strlen(line); telnet_write(connection, line, len); if (line_end) { telnet_write(connection, "\r\n", 2); line += len + 1; } else line += len; } return ERROR_OK; } static int telnet_output(struct command_context *cmd_ctx, const char *line) { struct connection *connection = cmd_ctx->output_handler_priv; return telnet_outputline(connection, line); } static void telnet_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string) { struct connection *connection = priv; struct telnet_connection *t_con = connection->priv; int i; /* if there is no prompt, simply output the message */ if (t_con->line_cursor < 0) { telnet_outputline(connection, string); return; } /* clear the command line */ for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16) telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i); for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16) telnet_write(connection, " ", i > 16 ? 16 : i); for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16) telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i); /* output the message */ telnet_outputline(connection, string); /* put the command line to its previous state */ telnet_prompt(connection); telnet_write(connection, t_con->line, t_con->line_size); for (i = t_con->line_size; i > t_con->line_cursor; i--) telnet_write(connection, "\b", 1); } static void telnet_load_history(struct telnet_connection *t_con) { FILE *histfp; char buffer[TELNET_BUFFER_SIZE]; int i = 0; char *history = get_home_dir(TELNET_HISTORY); if (history == NULL) { LOG_INFO("unable to get user home directory, telnet history will be disabled"); return; } histfp = fopen(history, "rb"); if (histfp) { while (fgets(buffer, sizeof(buffer), histfp) != NULL) { char *p = strchr(buffer, '\n'); if (p) *p = '\0'; if (buffer[0] && i < TELNET_LINE_HISTORY_SIZE) t_con->history[i++] = strdup(buffer); } t_con->next_history = i; t_con->next_history %= TELNET_LINE_HISTORY_SIZE; /* try to set to last entry - 1, that way we skip over any exit/shutdown cmds */ t_con->current_history = t_con->next_history > 0 ? i - 1 : 0; fclose(histfp); } free(history); } static void telnet_save_history(struct telnet_connection *t_con) { FILE *histfp; int i; int num; char *history = get_home_dir(TELNET_HISTORY); if (history == NULL) { LOG_INFO("unable to get user home directory, telnet history will be disabled"); return; } histfp = fopen(history, "wb"); if (histfp) { num = TELNET_LINE_HISTORY_SIZE; i = t_con->current_history + 1; i %= TELNET_LINE_HISTORY_SIZE; while (t_con->history[i] == NULL && num > 0) { i++; i %= TELNET_LINE_HISTORY_SIZE; num--; } if (num > 0) { for (; num > 0; num--) { fprintf(histfp, "%s\n", t_con->history[i]); i++; i %= TELNET_LINE_HISTORY_SIZE; } } fclose(histfp); } free(history); } static int telnet_new_connection(struct connection *connection) { struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection)); struct telnet_service *telnet_service = connection->service->priv; int i; connection->priv = telnet_connection; /* initialize telnet connection information */ telnet_connection->closed = 0; telnet_connection->line_size = 0; telnet_connection->line_cursor = 0; telnet_connection->option_size = 0; telnet_connection->prompt = strdup("> "); telnet_connection->state = TELNET_STATE_DATA; /* output goes through telnet connection */ command_set_output_handler(connection->cmd_ctx, telnet_output, connection); /* negotiate telnet options */ telnet_write(connection, negotiate, strlen(negotiate)); /* print connection banner */ if (telnet_service->banner) { telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner)); telnet_write(connection, "\r\n", 2); } /* the prompt is always placed at the line beginning */ telnet_write(connection, "\r", 1); telnet_prompt(connection); /* initialize history */ for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) telnet_connection->history[i] = NULL; telnet_connection->next_history = 0; telnet_connection->current_history = 0; telnet_load_history(telnet_connection); log_add_callback(telnet_log_callback, connection); return ERROR_OK; } static void telnet_clear_line(struct connection *connection, struct telnet_connection *t_con) { /* move to end of line */ if (t_con->line_cursor < t_con->line_size) telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); /* backspace, overwrite with space, backspace */ while (t_con->line_size > 0) { telnet_write(connection, "\b \b", 3); t_con->line_size--; } t_con->line_cursor = 0; } static void telnet_history_go(struct connection *connection, int idx) { struct telnet_connection *t_con = connection->priv; if (t_con->history[idx]) { telnet_clear_line(connection, t_con); t_con->line_size = strlen(t_con->history[idx]); t_con->line_cursor = t_con->line_size; memcpy(t_con->line, t_con->history[idx], t_con->line_size); telnet_write(connection, t_con->line, t_con->line_size); t_con->current_history = idx; } t_con->state = TELNET_STATE_DATA; } static void telnet_history_up(struct connection *connection) { struct telnet_connection *t_con = connection->priv; int last_history = (t_con->current_history > 0) ? t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1; telnet_history_go(connection, last_history); } static void telnet_history_down(struct connection *connection) { struct telnet_connection *t_con = connection->priv; int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE; telnet_history_go(connection, next_history); } static int telnet_input(struct connection *connection) { int bytes_read; unsigned char buffer[TELNET_BUFFER_SIZE]; unsigned char *buf_p; struct telnet_connection *t_con = connection->priv; struct command_context *command_context = connection->cmd_ctx; bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE); if (bytes_read == 0) return ERROR_SERVER_REMOTE_CLOSED; else if (bytes_read == -1) { LOG_ERROR("error during read: %s", strerror(errno)); return ERROR_SERVER_REMOTE_CLOSED; } buf_p = buffer; while (bytes_read) { switch (t_con->state) { case TELNET_STATE_DATA: if (*buf_p == 0xff) t_con->state = TELNET_STATE_IAC; else { if (isprint(*buf_p)) { /* printable character */ /* watch buffer size leaving one spare character for * string null termination */ if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) { /* output audible bell if buffer is full * "\a" does not work, at least on windows */ telnet_write(connection, "\x07", 1); } else if (t_con->line_cursor == t_con->line_size) { telnet_write(connection, buf_p, 1); t_con->line[t_con->line_size++] = *buf_p; t_con->line_cursor++; } else { int i; memmove(t_con->line + t_con->line_cursor + 1, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); t_con->line[t_con->line_cursor] = *buf_p; t_con->line_size++; telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); t_con->line_cursor++; for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } } else { /* non-printable */ if (*buf_p == 0x1b) { /* escape */ t_con->state = TELNET_STATE_ESCAPE; t_con->last_escape = '\x00'; } else if ((*buf_p == 0xd) || (*buf_p == 0xa)) { /* CR/LF */ int retval; /* skip over combinations with CR/LF and NUL characters */ if ((bytes_read > 1) && ((*(buf_p + 1) == 0xa) || (*(buf_p + 1) == 0xd))) { buf_p++; bytes_read--; } if ((bytes_read > 1) && (*(buf_p + 1) == 0)) { buf_p++; bytes_read--; } t_con->line[t_con->line_size] = 0; telnet_write(connection, "\r\n\x00", 3); if (strcmp(t_con->line, "history") == 0) { int i; for (i = 1; i < TELNET_LINE_HISTORY_SIZE; i++) { /* the t_con->next_history line contains empty string * (unless NULL), thus it is not printed */ char *history_line = t_con->history[(t_con-> next_history + i) % TELNET_LINE_HISTORY_SIZE]; if (history_line) { telnet_write(connection, history_line, strlen(history_line)); telnet_write(connection, "\r\n\x00", 3); } } t_con->line_size = 0; t_con->line_cursor = 0; continue; } /* save only non-blank not repeating lines in the history */ char *prev_line = t_con->history[(t_con->current_history > 0) ? t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1]; if (*t_con->line && (prev_line == NULL || strcmp(t_con->line, prev_line))) { /* if the history slot is already taken, free it */ if (t_con->history[t_con->next_history]) free(t_con->history[t_con->next_history]); /* add line to history */ t_con->history[t_con->next_history] = strdup(t_con->line); /* wrap history at TELNET_LINE_HISTORY_SIZE */ t_con->next_history = (t_con->next_history + 1) % TELNET_LINE_HISTORY_SIZE; /* current history line starts at the new entry */ t_con->current_history = t_con->next_history; if (t_con->history[t_con->current_history]) free(t_con->history[t_con->current_history]); t_con->history[t_con->current_history] = strdup(""); } t_con->line_size = 0; /* to suppress prompt in log callback during command execution */ t_con->line_cursor = -1; if (strcmp(t_con->line, "shutdown") == 0) telnet_save_history(t_con); retval = command_run_line(command_context, t_con->line); t_con->line_cursor = 0; if (retval == ERROR_COMMAND_CLOSE_CONNECTION) return ERROR_SERVER_REMOTE_CLOSED; /* the prompt is always * placed at the line beginning */ telnet_write(connection, "\r", 1); retval = telnet_prompt(connection); if (retval == ERROR_SERVER_REMOTE_CLOSED) return ERROR_SERVER_REMOTE_CLOSED; } else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) { /* delete character */ if (t_con->line_cursor > 0) { if (t_con->line_cursor != t_con->line_size) { int i; telnet_write(connection, "\b", 1); t_con->line_cursor--; t_con->line_size--; memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor); telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); telnet_write(connection, " \b", 2); for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } else { t_con->line_size--; t_con->line_cursor--; /* back space: move the 'printer' head one char * back, overwrite with space, move back again */ telnet_write(connection, "\b \b", 3); } } } else if (*buf_p == 0x15) /* clear line */ telnet_clear_line(connection, t_con); else if (*buf_p == CTRL('B')) { /* cursor left */ if (t_con->line_cursor > 0) { telnet_write(connection, "\b", 1); t_con->line_cursor--; } t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('F')) { /* cursor right */ if (t_con->line_cursor < t_con->line_size) telnet_write(connection, t_con->line + t_con->line_cursor++, 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('P')) /* cursor up */ telnet_history_up(connection); else if (*buf_p == CTRL('N')) /* cursor down */ telnet_history_down(connection); else LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p); } } break; case TELNET_STATE_IAC: switch (*buf_p) { case 0xfe: t_con->state = TELNET_STATE_DONT; break; case 0xfd: t_con->state = TELNET_STATE_DO; break; case 0xfc: t_con->state = TELNET_STATE_WONT; break; case 0xfb: t_con->state = TELNET_STATE_WILL; break; } break; case TELNET_STATE_SB: break; case TELNET_STATE_SE: break; case TELNET_STATE_WILL: case TELNET_STATE_WONT: case TELNET_STATE_DO: case TELNET_STATE_DONT: t_con->state = TELNET_STATE_DATA; break; case TELNET_STATE_ESCAPE: if (t_con->last_escape == '[') { if (*buf_p == 'D') { /* cursor left */ if (t_con->line_cursor > 0) { telnet_write(connection, "\b", 1); t_con->line_cursor--; } t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'C') { /* cursor right */ if (t_con->line_cursor < t_con->line_size) telnet_write(connection, t_con->line + t_con->line_cursor++, 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'A') { /* cursor up */ telnet_history_up(connection); } else if (*buf_p == 'B') { /* cursor down */ telnet_history_down(connection); } else if (*buf_p == '3') t_con->last_escape = *buf_p; else t_con->state = TELNET_STATE_DATA; } else if (t_con->last_escape == '3') { /* Remove character */ if (*buf_p == '~') { if (t_con->line_cursor < t_con->line_size) { int i; t_con->line_size--; /* remove char from line buffer */ memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor); /* print remainder of buffer */ telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); /* overwrite last char with whitespace */ telnet_write(connection, " \b", 2); /* move back to cursor position*/ for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } t_con->state = TELNET_STATE_DATA; } else t_con->state = TELNET_STATE_DATA; } else if (t_con->last_escape == '\x00') { if (*buf_p == '[') t_con->last_escape = *buf_p; else t_con->state = TELNET_STATE_DATA; } else { LOG_ERROR("BUG: unexpected value in t_con->last_escape"); t_con->state = TELNET_STATE_DATA; } break; default: LOG_ERROR("unknown telnet state"); exit(-1); } bytes_read--; buf_p++; } return ERROR_OK; } static int telnet_connection_closed(struct connection *connection) { struct telnet_connection *t_con = connection->priv; int i; log_remove_callback(telnet_log_callback, connection); if (t_con->prompt) { free(t_con->prompt); t_con->prompt = NULL; } /* save telnet history */ telnet_save_history(t_con); for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) { if (t_con->history[i]) { free(t_con->history[i]); t_con->history[i] = NULL; } } /* if this connection registered a debug-message receiver delete it */ delete_debug_msg_receiver(connection->cmd_ctx, NULL); if (connection->priv) { free(connection->priv); connection->priv = NULL; } else LOG_ERROR("BUG: connection->priv == NULL"); return ERROR_OK; } int telnet_init(char *banner) { if (strcmp(telnet_port, "disabled") == 0) { LOG_INFO("telnet server disabled"); return ERROR_OK; } struct telnet_service *telnet_service = malloc(sizeof(struct telnet_service)); telnet_service->banner = banner; return add_service("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service); } /* daemon configuration command telnet_port */ COMMAND_HANDLER(handle_telnet_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port); } COMMAND_HANDLER(handle_exit_command) { return ERROR_COMMAND_CLOSE_CONNECTION; } static const struct command_registration telnet_command_handlers[] = { { .name = "exit", .handler = handle_exit_command, .mode = COMMAND_EXEC, .usage = "", .help = "exit telnet session", }, { .name = "telnet_port", .handler = handle_telnet_port_command, .mode = COMMAND_ANY, .help = "Specify port on which to listen " "for incoming telnet connections. " "Read help on 'gdb_port'.", .usage = "[port_num]", }, COMMAND_REGISTRATION_DONE }; int telnet_register_commands(struct command_context *cmd_ctx) { telnet_port = strdup("4444"); return register_commands(cmd_ctx, NULL, telnet_command_handlers); } openocd-0.9.0/src/server/telnet_server.h0000644000175000017500000000542712315575361015237 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TELNET_SERVER_H #define TELNET_SERVER_H #include #define TELNET_BUFFER_SIZE (1024) #define TELNET_OPTION_MAX_SIZE (128) #define TELNET_LINE_HISTORY_SIZE (128) #define TELNET_LINE_MAX_SIZE (256) enum telnet_states { TELNET_STATE_DATA, TELNET_STATE_IAC, TELNET_STATE_SB, TELNET_STATE_SE, TELNET_STATE_WILL, TELNET_STATE_WONT, TELNET_STATE_DO, TELNET_STATE_DONT, TELNET_STATE_ESCAPE, }; struct telnet_connection { char *prompt; enum telnet_states state; char line[TELNET_LINE_MAX_SIZE]; int line_size; int line_cursor; char option[TELNET_OPTION_MAX_SIZE]; int option_size; char last_escape; char *history[TELNET_LINE_HISTORY_SIZE]; int next_history; int current_history; int closed; }; struct telnet_service { char *banner; }; int telnet_init(char *banner); int telnet_register_commands(struct command_context *command_context); #endif /* TELNET_SERVER_H */ openocd-0.9.0/src/server/server_stubs.c0000644000175000017500000000302612315575361015070 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "server.h" void openocd_sleep_prelude(void) { /* no-op */ } void openocd_sleep_postlude(void) { /* no-op */ } openocd-0.9.0/src/server/startup.tcl0000644000175000017500000000051312315575361014402 00000000000000# Defines basic Tcl procs for OpenOCD server modules # Handle GDB 'R' packet. Can be overridden by configuration script, # but it's not something one would expect target scripts to do # normally proc ocd_gdb_restart {target_id} { # Fix!!! we're resetting all targets here! Really we should reset only # one target reset halt } openocd-0.9.0/src/server/gdb_server.c0000644000175000017500000025632412516456303014474 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * Copyright (C) 2013 Franck Jullien * * elec4fun@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "server.h" #include #include "gdb_server.h" #include #include #include "rtos/rtos.h" #include "target/smp.h" /** * @file * GDB server implementation. * * This implements the GDB Remote Serial Protocol, over TCP connections, * giving GDB access to the JTAG or other hardware debugging facilities * found in most modern embedded processors. */ struct target_desc_format { char *tdesc; uint32_t tdesc_length; }; /* private connection data for GDB */ struct gdb_connection { char buffer[GDB_BUFFER_SIZE]; char *buf_p; int buf_cnt; int ctrl_c; enum target_state frontend_state; struct image *vflash_image; int closed; int busy; int noack_mode; /* set flag to true if you want the next stepi to return immediately. * allowing GDB to pick up a fresh set of register values from the target * without modifying the target state. */ bool sync; /* We delay reporting memory write errors until next step/continue or memory * write. This improves performance of gdb load significantly as the GDB packet * can be replied immediately and a new GDB packet will be ready without delay * (ca. 10% or so...). */ bool mem_write_error; /* with extended-remote it seems we need to better emulate attach/detach. * what this means is we reply with a W stop reply after a kill packet, * normally we reply with a S reply via gdb_last_signal_packet. * as a side note this behaviour only effects gdb > 6.8 */ bool attached; /* temporarily used for target description support */ struct target_desc_format target_desc; }; #if 0 #define _DEBUG_GDB_IO_ #endif static struct gdb_connection *current_gdb_connection; static int gdb_breakpoint_override; static enum breakpoint_type gdb_breakpoint_override_type; static int gdb_error(struct connection *connection, int retval); static char *gdb_port; static char *gdb_port_next; static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string); /* number of gdb connections, mainly to suppress gdb related debugging spam * in helper/log.c when no gdb connections are actually active */ int gdb_actual_connections; /* set if we are sending a memory map to gdb * via qXfer:memory-map:read packet */ /* enabled by default*/ static int gdb_use_memory_map = 1; /* enabled by default*/ static int gdb_flash_program = 1; /* if set, data aborts cause an error to be reported in memory read packets * see the code in gdb_read_memory_packet() for further explanations. * Disabled by default. */ static int gdb_report_data_abort; /* set if we are sending target descriptions to gdb * via qXfer:features:read packet */ /* enabled by default */ static int gdb_use_target_description = 1; /* current processing free-run type, used by file-I/O */ static char gdb_running_type; static int gdb_last_signal(struct target *target) { switch (target->debug_reason) { case DBG_REASON_DBGRQ: return 0x2; /* SIGINT */ case DBG_REASON_BREAKPOINT: case DBG_REASON_WATCHPOINT: case DBG_REASON_WPTANDBKPT: return 0x05; /* SIGTRAP */ case DBG_REASON_SINGLESTEP: return 0x05; /* SIGTRAP */ case DBG_REASON_NOTHALTED: return 0x0; /* no signal... shouldn't happen */ default: LOG_USER("undefined debug reason %d - target needs reset", target->debug_reason); return 0x0; } } static int check_pending(struct connection *connection, int timeout_s, int *got_data) { /* a non-blocking socket will block if there is 0 bytes available on the socket, * but return with as many bytes as are available immediately */ struct timeval tv; fd_set read_fds; struct gdb_connection *gdb_con = connection->priv; int t; if (got_data == NULL) got_data = &t; *got_data = 0; if (gdb_con->buf_cnt > 0) { *got_data = 1; return ERROR_OK; } FD_ZERO(&read_fds); FD_SET(connection->fd, &read_fds); tv.tv_sec = timeout_s; tv.tv_usec = 0; if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0) { /* This can typically be because a "monitor" command took too long * before printing any progress messages */ if (timeout_s > 0) return ERROR_GDB_TIMEOUT; else return ERROR_OK; } *got_data = FD_ISSET(connection->fd, &read_fds) != 0; return ERROR_OK; } static int gdb_get_char_inner(struct connection *connection, int *next_char) { struct gdb_connection *gdb_con = connection->priv; int retval = ERROR_OK; #ifdef _DEBUG_GDB_IO_ char *debug_buffer; #endif for (;; ) { if (connection->service->type != CONNECTION_TCP) gdb_con->buf_cnt = read(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE); else { retval = check_pending(connection, 1, NULL); if (retval != ERROR_OK) return retval; gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE); } if (gdb_con->buf_cnt > 0) break; if (gdb_con->buf_cnt == 0) { gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } #ifdef _WIN32 errno = WSAGetLastError(); switch (errno) { case WSAEWOULDBLOCK: usleep(1000); break; case WSAECONNABORTED: gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; case WSAECONNRESET: gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; default: LOG_ERROR("read: %d", errno); exit(-1); } #else switch (errno) { case EAGAIN: usleep(1000); break; case ECONNABORTED: gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; case ECONNRESET: gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; default: LOG_ERROR("read: %s", strerror(errno)); gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } #endif } #ifdef _DEBUG_GDB_IO_ debug_buffer = strndup(gdb_con->buffer, gdb_con->buf_cnt); LOG_DEBUG("received '%s'", debug_buffer); free(debug_buffer); #endif gdb_con->buf_p = gdb_con->buffer; gdb_con->buf_cnt--; *next_char = *(gdb_con->buf_p++); if (gdb_con->buf_cnt > 0) connection->input_pending = 1; else connection->input_pending = 0; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif return retval; } /** * The cool thing about this fn is that it allows buf_p and buf_cnt to be * held in registers in the inner loop. * * For small caches and embedded systems this is important! */ static inline int gdb_get_char_fast(struct connection *connection, int *next_char, char **buf_p, int *buf_cnt) { int retval = ERROR_OK; if ((*buf_cnt)-- > 0) { *next_char = **buf_p; (*buf_p)++; if (*buf_cnt > 0) connection->input_pending = 1; else connection->input_pending = 0; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif return ERROR_OK; } struct gdb_connection *gdb_con = connection->priv; gdb_con->buf_p = *buf_p; gdb_con->buf_cnt = *buf_cnt; retval = gdb_get_char_inner(connection, next_char); *buf_p = gdb_con->buf_p; *buf_cnt = gdb_con->buf_cnt; return retval; } static int gdb_get_char(struct connection *connection, int *next_char) { struct gdb_connection *gdb_con = connection->priv; return gdb_get_char_fast(connection, next_char, &gdb_con->buf_p, &gdb_con->buf_cnt); } static int gdb_putback_char(struct connection *connection, int last_char) { struct gdb_connection *gdb_con = connection->priv; if (gdb_con->buf_p > gdb_con->buffer) { *(--gdb_con->buf_p) = last_char; gdb_con->buf_cnt++; } else LOG_ERROR("BUG: couldn't put character back"); return ERROR_OK; } /* The only way we can detect that the socket is closed is the first time * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ static int gdb_write(struct connection *connection, void *data, int len) { struct gdb_connection *gdb_con = connection->priv; if (gdb_con->closed) return ERROR_SERVER_REMOTE_CLOSED; if (connection_write(connection, data, len) == len) return ERROR_OK; gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } static int gdb_put_packet_inner(struct connection *connection, char *buffer, int len) { int i; unsigned char my_checksum = 0; #ifdef _DEBUG_GDB_IO_ char *debug_buffer; #endif int reply; int retval; struct gdb_connection *gdb_con = connection->priv; for (i = 0; i < len; i++) my_checksum += buffer[i]; #ifdef _DEBUG_GDB_IO_ /* * At this point we should have nothing in the input queue from GDB, * however sometimes '-' is sent even though we've already received * an ACK (+) for everything we've sent off. */ int gotdata; for (;; ) { retval = check_pending(connection, 0, &gotdata); if (retval != ERROR_OK) return retval; if (!gotdata) break; retval = gdb_get_char(connection, &reply); if (retval != ERROR_OK) return retval; if (reply == '$') { /* fix a problem with some IAR tools */ gdb_putback_char(connection, reply); LOG_DEBUG("Unexpected start of new packet"); break; } LOG_WARNING("Discard unexpected char %c", reply); } #endif while (1) { #ifdef _DEBUG_GDB_IO_ debug_buffer = strndup(buffer, len); LOG_DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum); free(debug_buffer); #endif char local_buffer[1024]; local_buffer[0] = '$'; if ((size_t)len + 4 <= sizeof(local_buffer)) { /* performance gain on smaller packets by only a single call to gdb_write() */ memcpy(local_buffer + 1, buffer, len++); len += snprintf(local_buffer + len, sizeof(local_buffer) - len, "#%02x", my_checksum); retval = gdb_write(connection, local_buffer, len); if (retval != ERROR_OK) return retval; } else { /* larger packets are transmitted directly from caller supplied buffer * by several calls to gdb_write() to avoid dynamic allocation */ snprintf(local_buffer + 1, sizeof(local_buffer) - 1, "#%02x", my_checksum); retval = gdb_write(connection, local_buffer, 1); if (retval != ERROR_OK) return retval; retval = gdb_write(connection, buffer, len); if (retval != ERROR_OK) return retval; retval = gdb_write(connection, local_buffer + 1, 3); if (retval != ERROR_OK) return retval; } if (gdb_con->noack_mode) break; retval = gdb_get_char(connection, &reply); if (retval != ERROR_OK) return retval; if (reply == '+') break; else if (reply == '-') { /* Stop sending output packets for now */ log_remove_callback(gdb_log_callback, connection); LOG_WARNING("negative reply, retrying"); } else if (reply == 0x3) { gdb_con->ctrl_c = 1; retval = gdb_get_char(connection, &reply); if (retval != ERROR_OK) return retval; if (reply == '+') break; else if (reply == '-') { /* Stop sending output packets for now */ log_remove_callback(gdb_log_callback, connection); LOG_WARNING("negative reply, retrying"); } else if (reply == '$') { LOG_ERROR("GDB missing ack(1) - assumed good"); gdb_putback_char(connection, reply); return ERROR_OK; } else { LOG_ERROR("unknown character(1) 0x%2.2x in reply, dropping connection", reply); gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } } else if (reply == '$') { LOG_ERROR("GDB missing ack(2) - assumed good"); gdb_putback_char(connection, reply); return ERROR_OK; } else { LOG_ERROR("unknown character(2) 0x%2.2x in reply, dropping connection", reply); gdb_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } } if (gdb_con->closed) return ERROR_SERVER_REMOTE_CLOSED; return ERROR_OK; } int gdb_put_packet(struct connection *connection, char *buffer, int len) { struct gdb_connection *gdb_con = connection->priv; gdb_con->busy = 1; int retval = gdb_put_packet_inner(connection, buffer, len); gdb_con->busy = 0; /* we sent some data, reset timer for keep alive messages */ kept_alive(); return retval; } static inline int fetch_packet(struct connection *connection, int *checksum_ok, int noack, int *len, char *buffer) { unsigned char my_checksum = 0; char checksum[3]; int character; int retval = ERROR_OK; struct gdb_connection *gdb_con = connection->priv; my_checksum = 0; int count = 0; count = 0; /* move this over into local variables to use registers and give the * more freedom to optimize */ char *buf_p = gdb_con->buf_p; int buf_cnt = gdb_con->buf_cnt; for (;; ) { /* The common case is that we have an entire packet with no escape chars. * We need to leave at least 2 bytes in the buffer to have * gdb_get_char() update various bits and bobs correctly. */ if ((buf_cnt > 2) && ((buf_cnt + count) < *len)) { /* The compiler will struggle a bit with constant propagation and * aliasing, so we help it by showing that these values do not * change inside the loop */ int i; char *buf = buf_p; int run = buf_cnt - 2; i = 0; int done = 0; while (i < run) { character = *buf++; i++; if (character == '#') { /* Danger! character can be '#' when esc is * used so we need an explicit boolean for done here. */ done = 1; break; } if (character == '}') { /* data transmitted in binary mode (X packet) * uses 0x7d as escape character */ my_checksum += character & 0xff; character = *buf++; i++; my_checksum += character & 0xff; buffer[count++] = (character ^ 0x20) & 0xff; } else { my_checksum += character & 0xff; buffer[count++] = character & 0xff; } } buf_p += i; buf_cnt -= i; if (done) break; } if (count > *len) { LOG_ERROR("packet buffer too small"); retval = ERROR_GDB_BUFFER_TOO_SMALL; break; } retval = gdb_get_char_fast(connection, &character, &buf_p, &buf_cnt); if (retval != ERROR_OK) break; if (character == '#') break; if (character == '}') { /* data transmitted in binary mode (X packet) * uses 0x7d as escape character */ my_checksum += character & 0xff; retval = gdb_get_char_fast(connection, &character, &buf_p, &buf_cnt); if (retval != ERROR_OK) break; my_checksum += character & 0xff; buffer[count++] = (character ^ 0x20) & 0xff; } else { my_checksum += character & 0xff; buffer[count++] = character & 0xff; } } gdb_con->buf_p = buf_p; gdb_con->buf_cnt = buf_cnt; if (retval != ERROR_OK) return retval; *len = count; retval = gdb_get_char(connection, &character); if (retval != ERROR_OK) return retval; checksum[0] = character; retval = gdb_get_char(connection, &character); if (retval != ERROR_OK) return retval; checksum[1] = character; checksum[2] = 0; if (!noack) *checksum_ok = (my_checksum == strtoul(checksum, NULL, 16)); return ERROR_OK; } static int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len) { int character; int retval; struct gdb_connection *gdb_con = connection->priv; while (1) { do { retval = gdb_get_char(connection, &character); if (retval != ERROR_OK) return retval; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("character: '%c'", character); #endif switch (character) { case '$': break; case '+': /* According to the GDB documentation * (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html): * "gdb sends a final `+` acknowledgment of the stub's `OK` * response, which can be safely ignored by the stub." * However OpenOCD server already is in noack mode at this * point and instead of ignoring this it was emitting a * warning. This code makes server ignore the first ACK * that will be received after going into noack mode, * warning only about subsequent ACK's. */ if (gdb_con->noack_mode > 1) { LOG_WARNING("acknowledgment received, but no packet pending"); } else if (gdb_con->noack_mode) { LOG_DEBUG("Received first acknowledgment after entering noack mode. Ignoring it."); gdb_con->noack_mode = 2; } break; case '-': LOG_WARNING("negative acknowledgment, but no packet pending"); break; case 0x3: gdb_con->ctrl_c = 1; *len = 0; return ERROR_OK; default: LOG_WARNING("ignoring character 0x%x", character); break; } } while (character != '$'); int checksum_ok = 0; /* explicit code expansion here to get faster inlined code in -O3 by not * calculating checksum */ if (gdb_con->noack_mode) { retval = fetch_packet(connection, &checksum_ok, 1, len, buffer); if (retval != ERROR_OK) return retval; } else { retval = fetch_packet(connection, &checksum_ok, 0, len, buffer); if (retval != ERROR_OK) return retval; } if (gdb_con->noack_mode) { /* checksum is not checked in noack mode */ break; } if (checksum_ok) { retval = gdb_write(connection, "+", 1); if (retval != ERROR_OK) return retval; break; } } if (gdb_con->closed) return ERROR_SERVER_REMOTE_CLOSED; return ERROR_OK; } static int gdb_get_packet(struct connection *connection, char *buffer, int *len) { struct gdb_connection *gdb_con = connection->priv; gdb_con->busy = 1; int retval = gdb_get_packet_inner(connection, buffer, len); gdb_con->busy = 0; return retval; } static int gdb_output_con(struct connection *connection, const char *line) { char *hex_buffer; int bin_size; bin_size = strlen(line); hex_buffer = malloc(bin_size * 2 + 2); if (hex_buffer == NULL) return ERROR_GDB_BUFFER_TOO_SMALL; hex_buffer[0] = 'O'; int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1); int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1); free(hex_buffer); return retval; } static int gdb_output(struct command_context *context, const char *line) { /* this will be dumped to the log and also sent as an O packet if possible */ LOG_USER_N("%s", line); return ERROR_OK; } static void gdb_signal_reply(struct target *target, struct connection *connection) { struct gdb_connection *gdb_connection = connection->priv; char sig_reply[45]; char stop_reason[20]; char current_thread[25]; int sig_reply_len; int signal_var; rtos_update_threads(target); if (target->debug_reason == DBG_REASON_EXIT) { sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "W00"); } else { if (gdb_connection->ctrl_c) { signal_var = 0x2; gdb_connection->ctrl_c = 0; } else signal_var = gdb_last_signal(target); stop_reason[0] = '\0'; if (target->debug_reason == DBG_REASON_WATCHPOINT) { enum watchpoint_rw hit_wp_type; uint32_t hit_wp_address; if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) { switch (hit_wp_type) { case WPT_WRITE: snprintf(stop_reason, sizeof(stop_reason), "watch:%08" PRIx32 ";", hit_wp_address); break; case WPT_READ: snprintf(stop_reason, sizeof(stop_reason), "rwatch:%08" PRIx32 ";", hit_wp_address); break; case WPT_ACCESS: snprintf(stop_reason, sizeof(stop_reason), "awatch:%08" PRIx32 ";", hit_wp_address); break; default: break; } } } current_thread[0] = '\0'; if (target->rtos != NULL) { snprintf(current_thread, sizeof(current_thread), "thread:%016" PRIx64 ";", target->rtos->current_thread); target->rtos->current_threadid = target->rtos->current_thread; } sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s%s", signal_var, stop_reason, current_thread); } gdb_put_packet(connection, sig_reply, sig_reply_len); gdb_connection->frontend_state = TARGET_HALTED; } static void gdb_fileio_reply(struct target *target, struct connection *connection) { struct gdb_connection *gdb_connection = connection->priv; char fileio_command[256]; int command_len; bool program_exited = false; if (strcmp(target->fileio_info->identifier, "open") == 0) sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3, target->fileio_info->param_4); else if (strcmp(target->fileio_info->identifier, "close") == 0) sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1); else if (strcmp(target->fileio_info->identifier, "read") == 0) sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "write") == 0) sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "lseek") == 0) sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "rename") == 0) sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3, target->fileio_info->param_4); else if (strcmp(target->fileio_info->identifier, "unlink") == 0) sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "stat") == 0) sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "fstat") == 0) sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "gettimeofday") == 0) sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "isatty") == 0) sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1); else if (strcmp(target->fileio_info->identifier, "system") == 0) sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "exit") == 0) { /* If target hits exit syscall, report to GDB the program is terminated. * In addition, let target run its own exit syscall handler. */ program_exited = true; sprintf(fileio_command, "W%02" PRIx32, target->fileio_info->param_1); } else { LOG_DEBUG("Unknown syscall: %s", target->fileio_info->identifier); /* encounter unknown syscall, continue */ gdb_connection->frontend_state = TARGET_RUNNING; target_resume(target, 1, 0x0, 0, 0); return; } command_len = strlen(fileio_command); gdb_put_packet(connection, fileio_command, command_len); if (program_exited) { /* Use target_resume() to let target run its own exit syscall handler. */ gdb_connection->frontend_state = TARGET_RUNNING; target_resume(target, 1, 0x0, 0, 0); } else { gdb_connection->frontend_state = TARGET_HALTED; rtos_update_threads(target); } } static void gdb_frontend_halted(struct target *target, struct connection *connection) { struct gdb_connection *gdb_connection = connection->priv; /* In the GDB protocol when we are stepping or continuing execution, * we have a lingering reply. Upon receiving a halted event * when we have that lingering packet, we reply to the original * step or continue packet. * * Executing monitor commands can bring the target in and * out of the running state so we'll see lots of TARGET_EVENT_XXX * that are to be ignored. */ if (gdb_connection->frontend_state == TARGET_RUNNING) { /* stop forwarding log packets! */ log_remove_callback(gdb_log_callback, connection); /* check fileio first */ if (target_get_gdb_fileio_info(target, target->fileio_info) == ERROR_OK) gdb_fileio_reply(target, connection); else gdb_signal_reply(target, connection); } } static int gdb_target_callback_event_handler(struct target *target, enum target_event event, void *priv) { int retval; struct connection *connection = priv; struct gdb_service *gdb_service = connection->service->priv; if (gdb_service->target != target) return ERROR_OK; switch (event) { case TARGET_EVENT_GDB_HALT: gdb_frontend_halted(target, connection); break; case TARGET_EVENT_HALTED: target_call_event_callbacks(target, TARGET_EVENT_GDB_END); break; case TARGET_EVENT_GDB_FLASH_ERASE_START: retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; break; default: break; } return ERROR_OK; } static int gdb_new_connection(struct connection *connection) { struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection)); struct gdb_service *gdb_service = connection->service->priv; int retval; int initial_ack; connection->priv = gdb_connection; /* initialize gdb connection information */ gdb_connection->buf_p = gdb_connection->buffer; gdb_connection->buf_cnt = 0; gdb_connection->ctrl_c = 0; gdb_connection->frontend_state = TARGET_HALTED; gdb_connection->vflash_image = NULL; gdb_connection->closed = 0; gdb_connection->busy = 0; gdb_connection->noack_mode = 0; gdb_connection->sync = false; gdb_connection->mem_write_error = false; gdb_connection->attached = true; gdb_connection->target_desc.tdesc = NULL; gdb_connection->target_desc.tdesc_length = 0; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); /* output goes through gdb connection */ command_set_output_handler(connection->cmd_ctx, gdb_output, connection); /* we must remove all breakpoints registered to the target as a previous * GDB session could leave dangling breakpoints if e.g. communication * timed out. */ breakpoint_clear_target(gdb_service->target); watchpoint_clear_target(gdb_service->target); /* clean previous rtos session if supported*/ if ((gdb_service->target->rtos) && (gdb_service->target->rtos->type->clean)) gdb_service->target->rtos->type->clean(gdb_service->target); /* remove the initial ACK from the incoming buffer */ retval = gdb_get_char(connection, &initial_ack); if (retval != ERROR_OK) return retval; /* FIX!!!??? would we actually ever receive a + here??? * Not observed. */ if (initial_ack != '+') gdb_putback_char(connection, initial_ack); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH); if (gdb_use_memory_map) { /* Connect must fail if the memory map can't be set up correctly. * * This will cause an auto_probe to be invoked, which is either * a no-op or it will fail when the target isn't ready(e.g. not halted). */ int i; for (i = 0; i < flash_get_bank_count(); i++) { struct flash_bank *p; p = get_flash_bank_by_num_noprobe(i); if (p->target != gdb_service->target) continue; retval = get_flash_bank_by_num(i, &p); if (retval != ERROR_OK) { LOG_ERROR("Connect failed. Consider setting up a gdb-attach event for the target " \ "to prepare target for GDB connect, or use 'gdb_memory_map disable'."); return retval; } } } gdb_actual_connections++; LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s", gdb_actual_connections, target_name(gdb_service->target), target_state_name(gdb_service->target)); /* DANGER! If we fail subsequently, we must remove this handler, * otherwise we occasionally see crashes as the timer can invoke the * callback fn. * * register callback to be informed about target events */ target_register_event_callback(gdb_target_callback_event_handler, connection); return ERROR_OK; } static int gdb_connection_closed(struct connection *connection) { struct gdb_service *gdb_service = connection->service->priv; struct gdb_connection *gdb_connection = connection->priv; /* we're done forwarding messages. Tear down callback before * cleaning up connection. */ log_remove_callback(gdb_log_callback, connection); gdb_actual_connections--; LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d", target_name(gdb_service->target), target_state_name(gdb_service->target), gdb_actual_connections); /* see if an image built with vFlash commands is left */ if (gdb_connection->vflash_image) { image_close(gdb_connection->vflash_image); free(gdb_connection->vflash_image); gdb_connection->vflash_image = NULL; } /* if this connection registered a debug-message receiver delete it */ delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target); if (connection->priv) { free(connection->priv); connection->priv = NULL; } else LOG_ERROR("BUG: connection->priv == NULL"); target_unregister_event_callback(gdb_target_callback_event_handler, connection); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_END); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH); return ERROR_OK; } static void gdb_send_error(struct connection *connection, uint8_t the_error) { char err[4]; snprintf(err, 4, "E%2.2X", the_error); gdb_put_packet(connection, err, 3); } static int gdb_last_signal_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); struct gdb_connection *gdb_con = connection->priv; char sig_reply[4]; int signal_var; if (!gdb_con->attached) { /* if we are here we have received a kill packet * reply W stop reply otherwise gdb gets very unhappy */ gdb_put_packet(connection, "W00", 3); return ERROR_OK; } signal_var = gdb_last_signal(target); snprintf(sig_reply, 4, "S%2.2x", signal_var); gdb_put_packet(connection, sig_reply, 3); return ERROR_OK; } static inline int gdb_reg_pos(struct target *target, int pos, int len) { if (target->endianness == TARGET_LITTLE_ENDIAN) return pos; else return len - 1 - pos; } /* Convert register to string of bytes. NB! The # of bits in the * register might be non-divisible by 8(a byte), in which * case an entire byte is shown. * * NB! the format on the wire is the target endianness * * The format of reg->value is little endian * */ static void gdb_str_to_target(struct target *target, char *tstr, struct reg *reg) { int i; uint8_t *buf; int buf_len; buf = reg->value; buf_len = DIV_ROUND_UP(reg->size, 8); for (i = 0; i < buf_len; i++) { int j = gdb_reg_pos(target, i, buf_len); tstr += sprintf(tstr, "%02x", buf[j]); } } /* copy over in register buffer */ static void gdb_target_to_reg(struct target *target, char const *tstr, int str_len, uint8_t *bin) { if (str_len % 2) { LOG_ERROR("BUG: gdb value with uneven number of characters encountered"); exit(-1); } int i; for (i = 0; i < str_len; i += 2) { unsigned t; if (sscanf(tstr + i, "%02x", &t) != 1) { LOG_ERROR("BUG: unable to convert register value"); exit(-1); } int j = gdb_reg_pos(target, i/2, str_len/2); bin[j] = t; } } static int gdb_get_registers_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); struct reg **reg_list; int reg_list_size; int retval; int reg_packet_size = 0; char *reg_packet; char *reg_packet_p; int i; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("-"); #endif if ((target->rtos != NULL) && (ERROR_OK == rtos_get_gdb_reg_list(connection))) return ERROR_OK; retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_GENERAL); if (retval != ERROR_OK) return gdb_error(connection, retval); for (i = 0; i < reg_list_size; i++) reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; assert(reg_packet_size > 0); reg_packet = malloc(reg_packet_size + 1); /* plus one for string termination null */ reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { if (!reg_list[i]->valid) reg_list[i]->type->get(reg_list[i]); gdb_str_to_target(target, reg_packet_p, reg_list[i]); reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } #ifdef _DEBUG_GDB_IO_ { char *reg_packet_p_debug; reg_packet_p_debug = strndup(reg_packet, reg_packet_size); LOG_DEBUG("reg_packet: %s", reg_packet_p_debug); free(reg_packet_p_debug); } #endif gdb_put_packet(connection, reg_packet, reg_packet_size); free(reg_packet); free(reg_list); return ERROR_OK; } static int gdb_set_registers_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); int i; struct reg **reg_list; int reg_list_size; int retval; char const *packet_p; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("-"); #endif /* skip command character */ packet++; packet_size--; if (packet_size % 2) { LOG_WARNING("GDB set_registers packet with uneven characters received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_GENERAL); if (retval != ERROR_OK) return gdb_error(connection, retval); packet_p = packet; for (i = 0; i < reg_list_size; i++) { uint8_t *bin_buf; int chars = (DIV_ROUND_UP(reg_list[i]->size, 8) * 2); if (packet_p + chars > packet + packet_size) LOG_ERROR("BUG: register packet is too small for registers"); bin_buf = malloc(DIV_ROUND_UP(reg_list[i]->size, 8)); gdb_target_to_reg(target, packet_p, chars, bin_buf); reg_list[i]->type->set(reg_list[i], bin_buf); /* advance packet pointer */ packet_p += chars; free(bin_buf); } /* free struct reg *reg_list[] array allocated by get_gdb_reg_list */ free(reg_list); gdb_put_packet(connection, "OK", 2); return ERROR_OK; } static int gdb_get_register_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *reg_packet; int reg_num = strtoul(packet + 1, NULL, 16); struct reg **reg_list; int reg_list_size; int retval; #ifdef _DEBUG_GDB_IO_ LOG_DEBUG("-"); #endif retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) return gdb_error(connection, retval); if (reg_list_size <= reg_num) { LOG_ERROR("gdb requested a non-existing register"); return ERROR_SERVER_REMOTE_CLOSED; } if (!reg_list[reg_num]->valid) reg_list[reg_num]->type->get(reg_list[reg_num]); reg_packet = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1); /* plus one for string termination null */ gdb_str_to_target(target, reg_packet, reg_list[reg_num]); gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); free(reg_list); free(reg_packet); return ERROR_OK; } static int gdb_set_register_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; uint8_t *bin_buf; int reg_num = strtoul(packet + 1, &separator, 16); struct reg **reg_list; int reg_list_size; int retval; LOG_DEBUG("-"); retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) return gdb_error(connection, retval); if (reg_list_size <= reg_num) { LOG_ERROR("gdb requested a non-existing register"); return ERROR_SERVER_REMOTE_CLOSED; } if (*separator != '=') { LOG_ERROR("GDB 'set register packet', but no '=' following the register number"); return ERROR_SERVER_REMOTE_CLOSED; } /* convert from GDB-string (target-endian) to hex-string (big-endian) */ bin_buf = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8)); int chars = (DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); if ((unsigned int)chars != strlen(separator + 1)) { LOG_ERROR("gdb sent a packet with wrong register size"); free(bin_buf); return ERROR_SERVER_REMOTE_CLOSED; } gdb_target_to_reg(target, separator + 1, chars, bin_buf); reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); gdb_put_packet(connection, "OK", 2); free(bin_buf); free(reg_list); return ERROR_OK; } /* No attempt is made to translate the "retval" to * GDB speak. This has to be done at the calling * site as no mapping really exists. */ static int gdb_error(struct connection *connection, int retval) { LOG_DEBUG("Reporting %i to GDB as generic error", retval); gdb_send_error(connection, EFAULT); return ERROR_OK; } /* We don't have to worry about the default 2 second timeout for GDB packets, * because GDB breaks up large memory reads into smaller reads. * * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192????? */ static int gdb_read_memory_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; uint32_t addr = 0; uint32_t len = 0; uint8_t *buffer; char *hex_buffer; int retval = ERROR_OK; /* skip command character */ packet++; addr = strtoul(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete read memory packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } len = strtoul(separator + 1, NULL, 16); if (!len) { LOG_WARNING("invalid read memory packet received (len == 0)"); gdb_put_packet(connection, NULL, 0); return ERROR_OK; } buffer = malloc(len); LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_read_buffer(target, addr, len, buffer); if ((retval != ERROR_OK) && !gdb_report_data_abort) { /* TODO : Here we have to lie and send back all zero's lest stack traces won't work. * At some point this might be fixed in GDB, in which case this code can be removed. * * OpenOCD developers are acutely aware of this problem, but there is nothing * gained by involving the user in this problem that hopefully will get resolved * eventually * * http://sourceware.org/cgi-bin/gnatsweb.pl? \ * cmd = view%20audit-trail&database = gdb&pr = 2395 * * For now, the default is to fix up things to make current GDB versions work. * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command. */ memset(buffer, 0, len); retval = ERROR_OK; } if (retval == ERROR_OK) { hex_buffer = malloc(len * 2 + 1); int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1); gdb_put_packet(connection, hex_buffer, pkt_len); free(hex_buffer); } else retval = gdb_error(connection, retval); free(buffer); return retval; } static int gdb_write_memory_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; uint32_t addr = 0; uint32_t len = 0; uint8_t *buffer; int retval; /* skip command character */ packet++; addr = strtoul(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } len = strtoul(separator + 1, &separator, 16); if (*(separator++) != ':') { LOG_ERROR("incomplete write memory packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } buffer = malloc(len); LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); if (unhexify((char *)buffer, separator, len) != (int)len) LOG_ERROR("unable to decode memory packet"); retval = target_write_buffer(target, addr, len, buffer); if (retval == ERROR_OK) gdb_put_packet(connection, "OK", 2); else retval = gdb_error(connection, retval); free(buffer); return retval; } static int gdb_write_memory_binary_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; uint32_t addr = 0; uint32_t len = 0; int retval = ERROR_OK; /* skip command character */ packet++; addr = strtoul(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory binary packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } len = strtoul(separator + 1, &separator, 16); if (*(separator++) != ':') { LOG_ERROR("incomplete write memory binary packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } struct gdb_connection *gdb_connection = connection->priv; if (gdb_connection->mem_write_error) { retval = ERROR_FAIL; /* now that we have reported the memory write error, we can clear the condition */ gdb_connection->mem_write_error = false; } /* By replying the packet *immediately* GDB will send us a new packet * while we write the last one to the target. */ if (retval == ERROR_OK) gdb_put_packet(connection, "OK", 2); else { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; } if (len) { LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_write_buffer(target, addr, len, (uint8_t *)separator); if (retval != ERROR_OK) gdb_connection->mem_write_error = true; } return ERROR_OK; } static int gdb_step_continue_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); int current = 0; uint32_t address = 0x0; int retval = ERROR_OK; LOG_DEBUG("-"); if (packet_size > 1) address = strtoul(packet + 1, NULL, 16); else current = 1; gdb_running_type = packet[0]; if (packet[0] == 'c') { LOG_DEBUG("continue"); /* resume at current address, don't handle breakpoints, not debugging */ retval = target_resume(target, current, address, 0, 0); } else if (packet[0] == 's') { LOG_DEBUG("step"); /* step at current or address, don't handle breakpoints */ retval = target_step(target, current, address, 0); } return retval; } static int gdb_breakpoint_watchpoint_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); int type; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */; uint32_t address; uint32_t size; char *separator; int retval; LOG_DEBUG("-"); type = strtoul(packet + 1, &separator, 16); if (type == 0) /* memory breakpoint */ bp_type = BKPT_SOFT; else if (type == 1) /* hardware breakpoint */ bp_type = BKPT_HARD; else if (type == 2) /* write watchpoint */ wp_type = WPT_WRITE; else if (type == 3) /* read watchpoint */ wp_type = WPT_READ; else if (type == 4) /* access watchpoint */ wp_type = WPT_ACCESS; else { LOG_ERROR("invalid gdb watch/breakpoint type(%d), dropping connection", type); return ERROR_SERVER_REMOTE_CLOSED; } if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT) || (bp_type == BKPT_HARD))) bp_type = gdb_breakpoint_override_type; if (*separator != ',') { LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } address = strtoul(separator + 1, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } size = strtoul(separator + 1, &separator, 16); switch (type) { case 0: case 1: if (packet[0] == 'Z') { retval = breakpoint_add(target, address, size, bp_type); if (retval != ERROR_OK) { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; } else gdb_put_packet(connection, "OK", 2); } else { breakpoint_remove(target, address); gdb_put_packet(connection, "OK", 2); } break; case 2: case 3: case 4: { if (packet[0] == 'Z') { retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu); if (retval != ERROR_OK) { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; } else gdb_put_packet(connection, "OK", 2); } else { watchpoint_remove(target, address); gdb_put_packet(connection, "OK", 2); } break; } default: break; } return ERROR_OK; } /* print out a string and allocate more space as needed, * mainly used for XML at this point */ static void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...) { if (*retval != ERROR_OK) return; int first = 1; for (;; ) { if ((*xml == NULL) || (!first)) { /* start by 0 to exercise all the code paths. * Need minimum 2 bytes to fit 1 char and 0 terminator. */ *size = *size * 2 + 2; char *t = *xml; *xml = realloc(*xml, *size); if (*xml == NULL) { if (t) free(t); *retval = ERROR_SERVER_REMOTE_CLOSED; return; } } va_list ap; int ret; va_start(ap, fmt); ret = vsnprintf(*xml + *pos, *size - *pos, fmt, ap); va_end(ap); if ((ret > 0) && ((ret + 1) < *size - *pos)) { *pos += ret; return; } /* there was just enough or not enough space, allocate more. */ first = 0; } } static int decode_xfer_read(char const *buf, char **annex, int *ofs, unsigned int *len) { /* Locate the annex. */ const char *annex_end = strchr(buf, ':'); if (annex_end == NULL) return ERROR_FAIL; /* After the read marker and annex, qXfer looks like a * traditional 'm' packet. */ char *separator; *ofs = strtoul(annex_end + 1, &separator, 16); if (*separator != ',') return ERROR_FAIL; *len = strtoul(separator + 1, NULL, 16); /* Extract the annex if needed */ if (annex != NULL) { *annex = strndup(buf, annex_end - buf); if (*annex == NULL) return ERROR_FAIL; } return ERROR_OK; } static int compare_bank(const void *a, const void *b) { struct flash_bank *b1, *b2; b1 = *((struct flash_bank **)a); b2 = *((struct flash_bank **)b); if (b1->base == b2->base) return 0; else if (b1->base > b2->base) return 1; else return -1; } static int gdb_memory_map(struct connection *connection, char const *packet, int packet_size) { /* We get away with only specifying flash here. Regions that are not * specified are treated as if we provided no memory map(if not we * could detect the holes and mark them as RAM). * Normally we only execute this code once, but no big deal if we * have to regenerate it a couple of times. */ struct target *target = get_target_from_connection(connection); struct flash_bank *p; char *xml = NULL; int size = 0; int pos = 0; int retval = ERROR_OK; struct flash_bank **banks; int offset; int length; char *separator; uint32_t ram_start = 0; int i; int target_flash_banks = 0; /* skip command character */ packet += 23; offset = strtoul(packet, &separator, 16); length = strtoul(separator + 1, &separator, 16); xml_printf(&retval, &xml, &pos, &size, "\n"); /* Sort banks in ascending order. We need to report non-flash * memory as ram (or rather read/write) by default for GDB, since * it has no concept of non-cacheable read/write memory (i/o etc). * * FIXME Most non-flash addresses are *NOT* RAM! Don't lie. * Current versions of GDB assume unlisted addresses are RAM... */ banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count()); for (i = 0; i < flash_get_bank_count(); i++) { p = get_flash_bank_by_num_noprobe(i); if (p->target != target) continue; retval = get_flash_bank_by_num(i, &p); if (retval != ERROR_OK) { free(banks); gdb_error(connection, retval); return retval; } banks[target_flash_banks++] = p; } qsort(banks, target_flash_banks, sizeof(struct flash_bank *), compare_bank); for (i = 0; i < target_flash_banks; i++) { int j; unsigned sector_size = 0; uint32_t start; p = banks[i]; start = p->base; if (ram_start < p->base) xml_printf(&retval, &xml, &pos, &size, "\n", ram_start, p->base - ram_start); /* Report adjacent groups of same-size sectors. So for * example top boot CFI flash will list an initial region * with several large sectors (maybe 128KB) and several * smaller ones at the end (maybe 32KB). STR7 will have * regions with 8KB, 32KB, and 64KB sectors; etc. */ for (j = 0; j < p->num_sectors; j++) { unsigned group_len; /* Maybe start a new group of sectors. */ if (sector_size == 0) { start = p->base + p->sectors[j].offset; xml_printf(&retval, &xml, &pos, &size, "sectors[j].size; } /* Does this finish a group of sectors? * If not, continue an already-started group. */ if (j == p->num_sectors - 1) group_len = (p->base + p->size) - start; else if (p->sectors[j + 1].size != sector_size) group_len = p->base + p->sectors[j + 1].offset - start; else continue; xml_printf(&retval, &xml, &pos, &size, "length=\"0x%x\">\n" "" "0x%x\n" "\n", group_len, sector_size); sector_size = 0; } ram_start = p->base + p->size; } if (ram_start != 0) xml_printf(&retval, &xml, &pos, &size, "\n", ram_start, 0-ram_start); /* ELSE a flash chip could be at the very end of the 32 bit address * space, in which case ram_start will be precisely 0 */ free(banks); banks = NULL; xml_printf(&retval, &xml, &pos, &size, "\n"); if (retval != ERROR_OK) { gdb_error(connection, retval); return retval; } if (offset + length > pos) length = pos - offset; char *t = malloc(length + 1); t[0] = 'l'; memcpy(t + 1, xml + offset, length); gdb_put_packet(connection, t, length + 1); free(t); free(xml); return ERROR_OK; } static const char *gdb_get_reg_type_name(enum reg_type type) { switch (type) { case REG_TYPE_INT: return "int"; case REG_TYPE_INT8: return "int8"; case REG_TYPE_INT16: return "int16"; case REG_TYPE_INT32: return "int32"; case REG_TYPE_INT64: return "int64"; case REG_TYPE_INT128: return "int128"; case REG_TYPE_UINT8: return "uint8"; case REG_TYPE_UINT16: return "uint16"; case REG_TYPE_UINT32: return "uint32"; case REG_TYPE_UINT64: return "uint64"; case REG_TYPE_UINT128: return "uint128"; case REG_TYPE_CODE_PTR: return "code_ptr"; case REG_TYPE_DATA_PTR: return "data_ptr"; case REG_TYPE_FLOAT: return "float"; case REG_TYPE_IEEE_SINGLE: return "ieee_single"; case REG_TYPE_IEEE_DOUBLE: return "ieee_double"; case REG_TYPE_ARCH_DEFINED: return "int"; /* return arbitrary string to avoid compile warning. */ } return "int"; /* "int" as default value */ } static int gdb_generate_reg_type_description(struct target *target, char **tdesc, int *pos, int *size, struct reg_data_type *type) { int retval = ERROR_OK; if (type->type_class == REG_TYPE_CLASS_VECTOR) { /* */ xml_printf(&retval, tdesc, pos, size, "\n", type->id, type->reg_type_vector->type->id, type->reg_type_vector->count); } else if (type->type_class == REG_TYPE_CLASS_UNION) { /* * ... * */ xml_printf(&retval, tdesc, pos, size, "\n", type->id); struct reg_data_type_union_field *field; field = type->reg_type_union->fields; while (field != NULL) { xml_printf(&retval, tdesc, pos, size, "\n", field->name, field->type->id); field = field->next; } xml_printf(&retval, tdesc, pos, size, "\n"); } else if (type->type_class == REG_TYPE_CLASS_STRUCT) { struct reg_data_type_struct_field *field; field = type->reg_type_struct->fields; if (field->use_bitfields) { /* * ... * */ xml_printf(&retval, tdesc, pos, size, "\n", type->id, type->reg_type_struct->size); while (field != NULL) { xml_printf(&retval, tdesc, pos, size, "\n", field->name, field->bitfield->start, field->bitfield->end); field = field->next; } } else { /* * ... * */ xml_printf(&retval, tdesc, pos, size, "\n", type->id); while (field != NULL) { xml_printf(&retval, tdesc, pos, size, "\n", field->name, field->type->id); field = field->next; } } xml_printf(&retval, tdesc, pos, size, "\n"); } else if (type->type_class == REG_TYPE_CLASS_FLAGS) { /* * ... * */ xml_printf(&retval, tdesc, pos, size, "\n", type->id, type->reg_type_flags->size); struct reg_data_type_flags_field *field; field = type->reg_type_flags->fields; while (field != NULL) { xml_printf(&retval, tdesc, pos, size, "\n", field->name, field->bitfield->start, field->bitfield->end); field = field->next; } xml_printf(&retval, tdesc, pos, size, "\n"); } return ERROR_OK; } /* Get a list of available target registers features. feature_list must * be freed by caller. */ static int get_reg_features_list(struct target *target, char const **feature_list[], int *feature_list_size, struct reg **reg_list, int reg_list_size) { int tbl_sz = 0; /* Start with only one element */ *feature_list = calloc(1, sizeof(char *)); for (int i = 0; i < reg_list_size; i++) { if (reg_list[i]->exist == false) continue; if (reg_list[i]->feature != NULL && reg_list[i]->feature->name != NULL && (strcmp(reg_list[i]->feature->name, ""))) { /* We found a feature, check if the feature is already in the * table. If not, allocate a new entry for the table and * put the new feature in it. */ for (int j = 0; j < (tbl_sz + 1); j++) { if (!((*feature_list)[j])) { (*feature_list)[tbl_sz++] = reg_list[i]->feature->name; *feature_list = realloc(*feature_list, sizeof(char *) * (tbl_sz + 1)); (*feature_list)[tbl_sz] = NULL; break; } else { if (!strcmp((*feature_list)[j], reg_list[i]->feature->name)) break; } } } } if (feature_list_size) *feature_list_size = tbl_sz; return ERROR_OK; } static int gdb_generate_target_description(struct target *target, char **tdesc_out) { int retval = ERROR_OK; struct reg **reg_list = NULL; int reg_list_size; char const **features = NULL; int feature_list_size = 0; char *tdesc = NULL; int pos = 0; int size = 0; retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) { LOG_ERROR("get register list failed"); retval = ERROR_FAIL; goto error; } if (reg_list_size <= 0) { LOG_ERROR("get register list failed"); retval = ERROR_FAIL; goto error; } /* Get a list of available target registers features */ retval = get_reg_features_list(target, &features, &feature_list_size, reg_list, reg_list_size); if (retval != ERROR_OK) { LOG_ERROR("Can't get the registers feature list"); retval = ERROR_FAIL; goto error; } /* If we found some features associated with registers, create sections */ int current_feature = 0; xml_printf(&retval, &tdesc, &pos, &size, "\n" "\n" "\n"); /* generate target description according to register list */ if (features != NULL) { while (features[current_feature]) { xml_printf(&retval, &tdesc, &pos, &size, "\n", features[current_feature]); int i; for (i = 0; i < reg_list_size; i++) { if (reg_list[i]->exist == false) continue; if (strcmp(reg_list[i]->feature->name, features[current_feature])) continue; const char *type_str; if (reg_list[i]->reg_data_type != NULL) { if (reg_list[i]->reg_data_type->type == REG_TYPE_ARCH_DEFINED) { /* generate reg_data_type); type_str = reg_list[i]->reg_data_type->id; } else { /* predefined type */ type_str = gdb_get_reg_type_name( reg_list[i]->reg_data_type->type); } } else { /* Default type is "int" */ type_str = "int"; } xml_printf(&retval, &tdesc, &pos, &size, "name); xml_printf(&retval, &tdesc, &pos, &size, " bitsize=\"%d\"", reg_list[i]->size); xml_printf(&retval, &tdesc, &pos, &size, " regnum=\"%d\"", reg_list[i]->number); if (reg_list[i]->caller_save) xml_printf(&retval, &tdesc, &pos, &size, " save-restore=\"yes\""); else xml_printf(&retval, &tdesc, &pos, &size, " save-restore=\"no\""); xml_printf(&retval, &tdesc, &pos, &size, " type=\"%s\"", type_str); if (reg_list[i]->group != NULL) xml_printf(&retval, &tdesc, &pos, &size, " group=\"%s\"", reg_list[i]->group); xml_printf(&retval, &tdesc, &pos, &size, "/>\n"); } xml_printf(&retval, &tdesc, &pos, &size, "\n"); current_feature++; } } xml_printf(&retval, &tdesc, &pos, &size, "\n"); error: free(features); free(reg_list); if (retval == ERROR_OK) *tdesc_out = tdesc; else free(tdesc); return retval; } static int gdb_get_target_description_chunk(struct target *target, struct target_desc_format *target_desc, char **chunk, int32_t offset, uint32_t length) { if (target_desc == NULL) { LOG_ERROR("Unable to Generate Target Description"); return ERROR_FAIL; } char *tdesc = target_desc->tdesc; uint32_t tdesc_length = target_desc->tdesc_length; if (tdesc == NULL) { int retval = gdb_generate_target_description(target, &tdesc); if (retval != ERROR_OK) { LOG_ERROR("Unable to Generate Target Description"); return ERROR_FAIL; } tdesc_length = strlen(tdesc); } char transfer_type; if (length < (tdesc_length - offset)) transfer_type = 'm'; else transfer_type = 'l'; *chunk = malloc(length + 2); if (*chunk == NULL) { LOG_ERROR("Unable to allocate memory"); return ERROR_FAIL; } (*chunk)[0] = transfer_type; if (transfer_type == 'm') { strncpy((*chunk) + 1, tdesc + offset, length); (*chunk)[1 + length] = '\0'; } else { strncpy((*chunk) + 1, tdesc + offset, tdesc_length - offset); (*chunk)[1 + (tdesc_length - offset)] = '\0'; /* After gdb-server sends out last chunk, invalidate tdesc. */ free(tdesc); tdesc = NULL; tdesc_length = 0; } target_desc->tdesc = tdesc; target_desc->tdesc_length = tdesc_length; return ERROR_OK; } static int gdb_target_description_supported(struct target *target, int *supported) { int retval = ERROR_OK; struct reg **reg_list = NULL; int reg_list_size = 0; char const **features = NULL; int feature_list_size = 0; retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) { LOG_ERROR("get register list failed"); goto error; } if (reg_list_size <= 0) { LOG_ERROR("get register list failed"); retval = ERROR_FAIL; goto error; } /* Get a list of available target registers features */ retval = get_reg_features_list(target, &features, &feature_list_size, reg_list, reg_list_size); if (retval != ERROR_OK) { LOG_ERROR("Can't get the registers feature list"); goto error; } if (supported) { if (feature_list_size) *supported = 1; else *supported = 0; } error: free(features); free(reg_list); return retval; } static int gdb_query_packet(struct connection *connection, char const *packet, int packet_size) { struct command_context *cmd_ctx = connection->cmd_ctx; struct gdb_connection *gdb_connection = connection->priv; struct target *target = get_target_from_connection(connection); if (strncmp(packet, "qRcmd,", 6) == 0) { if (packet_size > 6) { char *cmd; cmd = malloc((packet_size - 6) / 2 + 1); int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2); cmd[len] = 0; /* We want to print all debug output to GDB connection */ log_add_callback(gdb_log_callback, connection); target_call_timer_callbacks_now(); /* some commands need to know the GDB connection, make note of current * GDB connection. */ current_gdb_connection = gdb_connection; command_run_line(cmd_ctx, cmd); current_gdb_connection = NULL; target_call_timer_callbacks_now(); log_remove_callback(gdb_log_callback, connection); free(cmd); } gdb_put_packet(connection, "OK", 2); return ERROR_OK; } else if (strncmp(packet, "qCRC:", 5) == 0) { if (packet_size > 5) { int retval; char gdb_reply[10]; char *separator; uint32_t checksum; uint32_t addr = 0; uint32_t len = 0; /* skip command character */ packet += 5; addr = strtoul(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete read memory packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } len = strtoul(separator + 1, NULL, 16); retval = target_checksum_memory(target, addr, len, &checksum); if (retval == ERROR_OK) { snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum); gdb_put_packet(connection, gdb_reply, 9); } else { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; } return ERROR_OK; } } else if (strncmp(packet, "qSupported", 10) == 0) { /* we currently support packet size and qXfer:memory-map:read (if enabled) * qXfer:features:read is supported for some targets */ int retval = ERROR_OK; char *buffer = NULL; int pos = 0; int size = 0; int gdb_target_desc_supported = 0; /* we need to test that the target supports target descriptions */ retval = gdb_target_description_supported(target, &gdb_target_desc_supported); if (retval != ERROR_OK) { LOG_INFO("Failed detecting Target Description Support, disabling"); gdb_target_desc_supported = 0; } /* support may be disabled globally */ if (gdb_use_target_description == 0) { if (gdb_target_desc_supported) LOG_WARNING("Target Descriptions Supported, but disabled"); gdb_target_desc_supported = 0; } xml_printf(&retval, &buffer, &pos, &size, "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+", (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-', (gdb_target_desc_supported == 1) ? '+' : '-'); if (retval != ERROR_OK) { gdb_send_error(connection, 01); return ERROR_OK; } gdb_put_packet(connection, buffer, strlen(buffer)); free(buffer); return ERROR_OK; } else if ((strncmp(packet, "qXfer:memory-map:read::", 23) == 0) && (flash_get_bank_count() > 0)) return gdb_memory_map(connection, packet, packet_size); else if (strncmp(packet, "qXfer:features:read:", 20) == 0) { char *xml = NULL; int retval = ERROR_OK; int offset; unsigned int length; /* skip command character */ packet += 20; if (decode_xfer_read(packet, NULL, &offset, &length) < 0) { gdb_send_error(connection, 01); return ERROR_OK; } /* Target should prepare correct target description for annex. * The first character of returned xml is 'm' or 'l'. 'm' for * there are *more* chunks to transfer. 'l' for it is the *last* * chunk of target description. */ retval = gdb_get_target_description_chunk(target, &gdb_connection->target_desc, &xml, offset, length); if (retval != ERROR_OK) { gdb_error(connection, retval); return retval; } gdb_put_packet(connection, xml, strlen(xml)); free(xml); return ERROR_OK; } else if (strncmp(packet, "QStartNoAckMode", 15) == 0) { gdb_connection->noack_mode = 1; gdb_put_packet(connection, "OK", 2); return ERROR_OK; } gdb_put_packet(connection, "", 0); return ERROR_OK; } static int gdb_v_packet(struct connection *connection, char const *packet, int packet_size) { struct gdb_connection *gdb_connection = connection->priv; struct gdb_service *gdb_service = connection->service->priv; int result; /* if flash programming disabled - send a empty reply */ if (gdb_flash_program == 0) { gdb_put_packet(connection, "", 0); return ERROR_OK; } if (strncmp(packet, "vFlashErase:", 12) == 0) { unsigned long addr; unsigned long length; char const *parse = packet + 12; if (*parse == '\0') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } addr = strtoul(parse, (char **)&parse, 16); if (*(parse++) != ',' || *parse == '\0') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } length = strtoul(parse, (char **)&parse, 16); if (*parse != '\0') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } /* assume all sectors need erasing - stops any problems * when flash_write is called multiple times */ flash_set_dirty(); /* perform any target specific operations before the erase */ target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_START); /* vFlashErase:addr,length messages require region start and * end to be "block" aligned ... if padding is ever needed, * GDB will have become dangerously confused. */ result = flash_erase_address_range(gdb_service->target, false, addr, length); /* perform any target specific operations after the erase */ target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_END); /* perform erase */ if (result != ERROR_OK) { /* GDB doesn't evaluate the actual error number returned, * treat a failed erase as an I/O error */ gdb_send_error(connection, EIO); LOG_ERROR("flash_erase returned %i", result); } else gdb_put_packet(connection, "OK", 2); return ERROR_OK; } if (strncmp(packet, "vFlashWrite:", 12) == 0) { int retval; unsigned long addr; unsigned long length; char const *parse = packet + 12; if (*parse == '\0') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } addr = strtoul(parse, (char **)&parse, 16); if (*(parse++) != ':') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } length = packet_size - (parse - packet); /* create a new image if there isn't already one */ if (gdb_connection->vflash_image == NULL) { gdb_connection->vflash_image = malloc(sizeof(struct image)); image_open(gdb_connection->vflash_image, "", "build"); } /* create new section with content from packet buffer */ retval = image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (uint8_t const *)parse); if (retval != ERROR_OK) return retval; gdb_put_packet(connection, "OK", 2); return ERROR_OK; } if (strncmp(packet, "vFlashDone", 10) == 0) { uint32_t written; /* process the flashing buffer. No need to erase as GDB * always issues a vFlashErase first. */ target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_START); result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_END); if (result != ERROR_OK) { if (result == ERROR_FLASH_DST_OUT_OF_BANK) gdb_put_packet(connection, "E.memtype", 9); else gdb_send_error(connection, EIO); } else { LOG_DEBUG("wrote %u bytes from vFlash image to flash", (unsigned)written); gdb_put_packet(connection, "OK", 2); } image_close(gdb_connection->vflash_image); free(gdb_connection->vflash_image); gdb_connection->vflash_image = NULL; return ERROR_OK; } gdb_put_packet(connection, "", 0); return ERROR_OK; } static int gdb_detach(struct connection *connection) { struct gdb_service *gdb_service = connection->service->priv; target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH); return gdb_put_packet(connection, "OK", 2); } /* The format of 'F' response packet is * Fretcode,errno,Ctrl-C flag;call-specific attachment */ static int gdb_fileio_response_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; char *parsing_point; int fileio_retcode = strtoul(packet + 1, &separator, 16); int fileio_errno = 0; bool fileio_ctrl_c = false; int retval; LOG_DEBUG("-"); if (*separator == ',') { parsing_point = separator + 1; fileio_errno = strtoul(parsing_point, &separator, 16); if (*separator == ',') { if (*(separator + 1) == 'C') { /* TODO: process ctrl-c */ fileio_ctrl_c = true; } } } LOG_DEBUG("File-I/O response, retcode: 0x%x, errno: 0x%x, ctrl-c: %s", fileio_retcode, fileio_errno, fileio_ctrl_c ? "true" : "false"); retval = target_gdb_fileio_end(target, fileio_retcode, fileio_errno, fileio_ctrl_c); if (retval != ERROR_OK) return ERROR_FAIL; /* After File-I/O ends, keep continue or step */ if (gdb_running_type == 'c') retval = target_resume(target, 1, 0x0, 0, 0); else if (gdb_running_type == 's') retval = target_step(target, 1, 0x0, 0); else retval = ERROR_FAIL; if (retval != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string) { struct connection *connection = priv; struct gdb_connection *gdb_con = connection->priv; if (gdb_con->busy) { /* do not reply this using the O packet */ return; } gdb_output_con(connection, string); } static void gdb_sig_halted(struct connection *connection) { char sig_reply[4]; snprintf(sig_reply, 4, "T%2.2x", 2); gdb_put_packet(connection, sig_reply, 3); } static int gdb_input_inner(struct connection *connection) { /* Do not allocate this on the stack */ static char gdb_packet_buffer[GDB_BUFFER_SIZE]; struct gdb_service *gdb_service = connection->service->priv; struct target *target = gdb_service->target; char const *packet = gdb_packet_buffer; int packet_size; int retval; struct gdb_connection *gdb_con = connection->priv; static int extended_protocol; /* drain input buffer. If one of the packets fail, then an error * packet is replied, if applicable. * * This loop will terminate and the error code is returned. * * The calling fn will check if this error is something that * can be recovered from, or if the connection must be closed. * * If the error is recoverable, this fn is called again to * drain the rest of the buffer. */ do { packet_size = GDB_BUFFER_SIZE-1; retval = gdb_get_packet(connection, gdb_packet_buffer, &packet_size); if (retval != ERROR_OK) return retval; /* terminate with zero */ gdb_packet_buffer[packet_size] = '\0'; if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) { if (packet[0] == 'X') { /* binary packets spew junk into the debug log stream */ char buf[50]; int x; for (x = 0; (x < 49) && (packet[x] != ':'); x++) buf[x] = packet[x]; buf[x] = 0; LOG_DEBUG("received packet: '%s:'", buf); } else LOG_DEBUG("received packet: '%s'", packet); } if (packet_size > 0) { retval = ERROR_OK; switch (packet[0]) { case 'T': /* Is thread alive? */ gdb_thread_packet(connection, packet, packet_size); break; case 'H': /* Set current thread ( 'c' for step and continue, * 'g' for all other operations ) */ gdb_thread_packet(connection, packet, packet_size); break; case 'q': case 'Q': retval = gdb_thread_packet(connection, packet, packet_size); if (retval == GDB_THREAD_PACKET_NOT_CONSUMED) retval = gdb_query_packet(connection, packet, packet_size); break; case 'g': retval = gdb_get_registers_packet(connection, packet, packet_size); break; case 'G': retval = gdb_set_registers_packet(connection, packet, packet_size); break; case 'p': retval = gdb_get_register_packet(connection, packet, packet_size); break; case 'P': retval = gdb_set_register_packet(connection, packet, packet_size); break; case 'm': retval = gdb_read_memory_packet(connection, packet, packet_size); break; case 'M': retval = gdb_write_memory_packet(connection, packet, packet_size); break; case 'z': case 'Z': retval = gdb_breakpoint_watchpoint_packet(connection, packet, packet_size); break; case '?': gdb_last_signal_packet(connection, packet, packet_size); break; case 'c': case 's': { gdb_thread_packet(connection, packet, packet_size); log_add_callback(gdb_log_callback, connection); if (gdb_con->mem_write_error) { LOG_ERROR("Memory write failure!"); /* now that we have reported the memory write error, * we can clear the condition */ gdb_con->mem_write_error = false; } bool nostep = false; bool already_running = false; if (target->state == TARGET_RUNNING) { LOG_WARNING("WARNING! The target is already running. " "All changes GDB did to registers will be discarded! " "Waiting for target to halt."); already_running = true; } else if (target->state != TARGET_HALTED) { LOG_WARNING("The target is not in the halted nor running stated, " \ "stepi/continue ignored."); nostep = true; } else if ((packet[0] == 's') && gdb_con->sync) { /* Hmm..... when you issue a continue in GDB, then a "stepi" is * sent by GDB first to OpenOCD, thus defeating the check to * make only the single stepping have the sync feature... */ nostep = true; LOG_WARNING("stepi ignored. GDB will now fetch the register state " \ "from the target."); } gdb_con->sync = false; if (!already_running && nostep) { /* Either the target isn't in the halted state, then we can't * step/continue. This might be early setup, etc. * * Or we want to allow GDB to pick up a fresh set of * register values without modifying the target state. * */ gdb_sig_halted(connection); /* stop forwarding log packets! */ log_remove_callback(gdb_log_callback, connection); } else { /* We're running/stepping, in which case we can * forward log output until the target is halted */ gdb_con->frontend_state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_GDB_START); if (!already_running) { /* Here we don't want packet processing to stop even if this fails, * so we use a local variable instead of retval. */ retval = gdb_step_continue_packet(connection, packet, packet_size); if (retval != ERROR_OK) { /* we'll never receive a halted * condition... issue a false one.. */ gdb_frontend_halted(target, connection); } } } } break; case 'v': retval = gdb_v_packet(connection, packet, packet_size); break; case 'D': retval = gdb_detach(connection); extended_protocol = 0; break; case 'X': retval = gdb_write_memory_binary_packet(connection, packet, packet_size); if (retval != ERROR_OK) return retval; break; case 'k': if (extended_protocol != 0) { gdb_con->attached = false; break; } gdb_put_packet(connection, "OK", 2); return ERROR_SERVER_REMOTE_CLOSED; case '!': /* handle extended remote protocol */ extended_protocol = 1; gdb_put_packet(connection, "OK", 2); break; case 'R': /* handle extended restart packet */ breakpoint_clear_target(gdb_service->target); watchpoint_clear_target(gdb_service->target); command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %s", target_name(target)); /* set connection as attached after reset */ gdb_con->attached = true; /* info rtos parts */ gdb_thread_packet(connection, packet, packet_size); break; case 'j': /* packet supported only by smp target i.e cortex_a.c*/ /* handle smp packet replying coreid played to gbd */ gdb_read_smp_packet(connection, packet, packet_size); break; case 'J': /* packet supported only by smp target i.e cortex_a.c */ /* handle smp packet setting coreid to be played at next * resume to gdb */ gdb_write_smp_packet(connection, packet, packet_size); break; case 'F': /* File-I/O extension */ /* After gdb uses host-side syscall to complete target file * I/O, gdb sends host-side syscall return value to target * by 'F' packet. * The format of 'F' response packet is * Fretcode,errno,Ctrl-C flag;call-specific attachment */ gdb_con->frontend_state = TARGET_RUNNING; log_add_callback(gdb_log_callback, connection); gdb_fileio_response_packet(connection, packet, packet_size); break; default: /* ignore unknown packets */ LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]); gdb_put_packet(connection, NULL, 0); break; } /* if a packet handler returned an error, exit input loop */ if (retval != ERROR_OK) return retval; } if (gdb_con->ctrl_c) { if (target->state == TARGET_RUNNING) { retval = target_halt(target); if (retval != ERROR_OK) target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); gdb_con->ctrl_c = 0; } else { LOG_INFO("The target is not running when halt was requested, stopping GDB."); target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } } } while (gdb_con->buf_cnt > 0); return ERROR_OK; } static int gdb_input(struct connection *connection) { int retval = gdb_input_inner(connection); struct gdb_connection *gdb_con = connection->priv; if (retval == ERROR_SERVER_REMOTE_CLOSED) return retval; /* logging does not propagate the error, yet can set the gdb_con->closed flag */ if (gdb_con->closed) return ERROR_SERVER_REMOTE_CLOSED; /* we'll recover from any other errors(e.g. temporary timeouts, etc.) */ return ERROR_OK; } static int gdb_target_start(struct target *target, const char *port) { struct gdb_service *gdb_service; int ret; gdb_service = malloc(sizeof(struct gdb_service)); if (NULL == gdb_service) return -ENOMEM; gdb_service->target = target; gdb_service->core[0] = -1; gdb_service->core[1] = -1; target->gdb_service = gdb_service; ret = add_service("gdb", port, 1, &gdb_new_connection, &gdb_input, &gdb_connection_closed, gdb_service); /* initialialize all targets gdb service with the same pointer */ { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if (curr != target) curr->gdb_service = gdb_service; head = head->next; } } return ret; } static int gdb_target_add_one(struct target *target) { /* one gdb instance per smp list */ if ((target->smp) && (target->gdb_service)) return ERROR_OK; int retval = gdb_target_start(target, gdb_port_next); if (retval == ERROR_OK) { long portnumber; /* If we can parse the port number * then we increment the port number for the next target. */ char *end; portnumber = strtol(gdb_port_next, &end, 0); if (!*end) { if (parse_long(gdb_port_next, &portnumber) == ERROR_OK) { free(gdb_port_next); gdb_port_next = alloc_printf("%d", portnumber+1); } } } return retval; } int gdb_target_add_all(struct target *target) { if (NULL == target) { LOG_WARNING("gdb services need one or more targets defined"); return ERROR_OK; } while (NULL != target) { int retval = gdb_target_add_one(target); if (ERROR_OK != retval) return retval; target = target->next; } return ERROR_OK; } COMMAND_HANDLER(handle_gdb_sync_command) { if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; if (current_gdb_connection == NULL) { command_print(CMD_CTX, "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\""); return ERROR_FAIL; } current_gdb_connection->sync = true; return ERROR_OK; } /* daemon configuration command gdb_port */ COMMAND_HANDLER(handle_gdb_port_command) { int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port); if (ERROR_OK == retval) { free(gdb_port_next); gdb_port_next = strdup(gdb_port); } return retval; } COMMAND_HANDLER(handle_gdb_memory_map_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_memory_map); return ERROR_OK; } COMMAND_HANDLER(handle_gdb_flash_program_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_flash_program); return ERROR_OK; } COMMAND_HANDLER(handle_gdb_report_data_abort_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_report_data_abort); return ERROR_OK; } /* gdb_breakpoint_override */ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) { if (CMD_ARGC == 0) { /* nothing */ } else if (CMD_ARGC == 1) { gdb_breakpoint_override = 1; if (strcmp(CMD_ARGV[0], "hard") == 0) gdb_breakpoint_override_type = BKPT_HARD; else if (strcmp(CMD_ARGV[0], "soft") == 0) gdb_breakpoint_override_type = BKPT_SOFT; else if (strcmp(CMD_ARGV[0], "disable") == 0) gdb_breakpoint_override = 0; } else return ERROR_COMMAND_SYNTAX_ERROR; if (gdb_breakpoint_override) LOG_USER("force %s breakpoints", (gdb_breakpoint_override_type == BKPT_HARD) ? "hard" : "soft"); else LOG_USER("breakpoint type is not overridden"); return ERROR_OK; } COMMAND_HANDLER(handle_gdb_target_description_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_target_description); return ERROR_OK; } COMMAND_HANDLER(handle_gdb_save_tdesc_command) { char *tdesc; uint32_t tdesc_length; struct target *target = get_current_target(CMD_CTX); int retval = gdb_generate_target_description(target, &tdesc); if (retval != ERROR_OK) { LOG_ERROR("Unable to Generate Target Description"); return ERROR_FAIL; } tdesc_length = strlen(tdesc); struct fileio fileio; size_t size_written; char *tdesc_filename = alloc_printf("%s.xml", target_type_name(target)); if (tdesc_filename == NULL) { retval = ERROR_FAIL; goto out; } retval = fileio_open(&fileio, tdesc_filename, FILEIO_WRITE, FILEIO_TEXT); if (retval != ERROR_OK) { LOG_ERROR("Can't open %s for writing", tdesc_filename); goto out; } retval = fileio_write(&fileio, tdesc_length, tdesc, &size_written); fileio_close(&fileio); if (retval != ERROR_OK) LOG_ERROR("Error while writing the tdesc file"); out: free(tdesc_filename); free(tdesc); return retval; } static const struct command_registration gdb_command_handlers[] = { { .name = "gdb_sync", .handler = handle_gdb_sync_command, .mode = COMMAND_ANY, .help = "next stepi will return immediately allowing " "GDB to fetch register state without affecting " "target state", .usage = "" }, { .name = "gdb_port", .handler = handle_gdb_port_command, .mode = COMMAND_ANY, .help = "Normally gdb listens to a TCP/IP port. Each subsequent GDB " "server listens for the next port number after the " "base port number specified. " "No arguments reports GDB port. \"pipe\" means listen to stdin " "output to stdout, an integer is base port number, \"disable\" disables " "port. Any other string is are interpreted as named pipe to listen to. " "Output pipe is the same name as input pipe, but with 'o' appended.", .usage = "[port_num]", }, { .name = "gdb_memory_map", .handler = handle_gdb_memory_map_command, .mode = COMMAND_CONFIG, .help = "enable or disable memory map", .usage = "('enable'|'disable')" }, { .name = "gdb_flash_program", .handler = handle_gdb_flash_program_command, .mode = COMMAND_CONFIG, .help = "enable or disable flash program", .usage = "('enable'|'disable')" }, { .name = "gdb_report_data_abort", .handler = handle_gdb_report_data_abort_command, .mode = COMMAND_CONFIG, .help = "enable or disable reporting data aborts", .usage = "('enable'|'disable')" }, { .name = "gdb_breakpoint_override", .handler = handle_gdb_breakpoint_override_command, .mode = COMMAND_ANY, .help = "Display or specify type of breakpoint " "to be used by gdb 'break' commands.", .usage = "('hard'|'soft'|'disable')" }, { .name = "gdb_target_description", .handler = handle_gdb_target_description_command, .mode = COMMAND_CONFIG, .help = "enable or disable target description", .usage = "('enable'|'disable')" }, { .name = "gdb_save_tdesc", .handler = handle_gdb_save_tdesc_command, .mode = COMMAND_EXEC, .help = "Save the target description file", }, COMMAND_REGISTRATION_DONE }; int gdb_register_commands(struct command_context *cmd_ctx) { gdb_port = strdup("3333"); gdb_port_next = strdup("3333"); return register_commands(cmd_ctx, NULL, gdb_command_handlers); } openocd-0.9.0/src/server/gdb_server.h0000644000175000017500000000531312315575361014472 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2009 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef GDB_SERVER_H #define GDB_SERVER_H struct image; struct reg; #include #define GDB_BUFFER_SIZE 16384 int gdb_target_add_all(struct target *target); int gdb_register_commands(struct command_context *command_context); int gdb_put_packet(struct connection *connection, char *buffer, int len); static inline struct target *get_target_from_connection(struct connection *connection) { struct gdb_service *gdb_service = connection->service->priv; return gdb_service->target; } #define ERROR_GDB_BUFFER_TOO_SMALL (-800) #define ERROR_GDB_TIMEOUT (-801) #endif /* GDB_SERVER_H */ openocd-0.9.0/src/server/Makefile.am0000644000175000017500000000104612315575361014232 00000000000000include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = libserver.la noinst_HEADERS = server.h telnet_server.h gdb_server.h libserver_la_SOURCES = server.c telnet_server.c gdb_server.c libserver_la_SOURCES += server_stubs.c libserver_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform libserver_la_CFLAGS += -Wno-sign-compare endif # tcl server addons noinst_HEADERS += tcl_server.h libserver_la_SOURCES += tcl_server.c EXTRA_DIST = \ startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/server/Makefile.in0000644000175000017500000006031612526201651014240 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl # FD_* macros are sloppy with their signs on MinGW32 platform @IS_MINGW_TRUE@am__append_2 = -Wno-sign-compare subdir = src/server ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libserver_la_LIBADD = am_libserver_la_OBJECTS = libserver_la-server.lo \ libserver_la-telnet_server.lo libserver_la-gdb_server.lo \ libserver_la-server_stubs.lo libserver_la-tcl_server.lo libserver_la_OBJECTS = $(am_libserver_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libserver_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libserver_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libserver_la_SOURCES) DIST_SOURCES = $(libserver_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) METASOURCES = AUTO noinst_LTLIBRARIES = libserver.la # tcl server addons noinst_HEADERS = server.h telnet_server.h gdb_server.h tcl_server.h libserver_la_SOURCES = server.c telnet_server.c gdb_server.c \ server_stubs.c tcl_server.c libserver_la_CFLAGS = $(am__append_2) EXTRA_DIST = \ startup.tcl MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/server/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/server/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libserver.la: $(libserver_la_OBJECTS) $(libserver_la_DEPENDENCIES) $(EXTRA_libserver_la_DEPENDENCIES) $(AM_V_CCLD)$(libserver_la_LINK) $(libserver_la_OBJECTS) $(libserver_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-gdb_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-server_stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-tcl_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-telnet_server.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libserver_la-server.lo: server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-server.lo -MD -MP -MF $(DEPDIR)/libserver_la-server.Tpo -c -o libserver_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-server.Tpo $(DEPDIR)/libserver_la-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='libserver_la-server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c libserver_la-telnet_server.lo: telnet_server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-telnet_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-telnet_server.Tpo -c -o libserver_la-telnet_server.lo `test -f 'telnet_server.c' || echo '$(srcdir)/'`telnet_server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-telnet_server.Tpo $(DEPDIR)/libserver_la-telnet_server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telnet_server.c' object='libserver_la-telnet_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-telnet_server.lo `test -f 'telnet_server.c' || echo '$(srcdir)/'`telnet_server.c libserver_la-gdb_server.lo: gdb_server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-gdb_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-gdb_server.Tpo -c -o libserver_la-gdb_server.lo `test -f 'gdb_server.c' || echo '$(srcdir)/'`gdb_server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-gdb_server.Tpo $(DEPDIR)/libserver_la-gdb_server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gdb_server.c' object='libserver_la-gdb_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-gdb_server.lo `test -f 'gdb_server.c' || echo '$(srcdir)/'`gdb_server.c libserver_la-server_stubs.lo: server_stubs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-server_stubs.lo -MD -MP -MF $(DEPDIR)/libserver_la-server_stubs.Tpo -c -o libserver_la-server_stubs.lo `test -f 'server_stubs.c' || echo '$(srcdir)/'`server_stubs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-server_stubs.Tpo $(DEPDIR)/libserver_la-server_stubs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server_stubs.c' object='libserver_la-server_stubs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-server_stubs.lo `test -f 'server_stubs.c' || echo '$(srcdir)/'`server_stubs.c libserver_la-tcl_server.lo: tcl_server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-tcl_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-tcl_server.Tpo -c -o libserver_la-tcl_server.lo `test -f 'tcl_server.c' || echo '$(srcdir)/'`tcl_server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-tcl_server.Tpo $(DEPDIR)/libserver_la-tcl_server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcl_server.c' object='libserver_la-tcl_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-tcl_server.lo `test -f 'tcl_server.c' || echo '$(srcdir)/'`tcl_server.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/server/server.c0000644000175000017500000004263712516456303013660 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "server.h" #include #include #include #include "openocd.h" #include "tcl_server.h" #include "telnet_server.h" #include #ifndef _WIN32 #include #endif static struct service *services; /* shutdown_openocd == 1: exit the main event loop, and quit the * debugger; 2: quit with non-zero return code */ static int shutdown_openocd; /* store received signal to exit application by killing ourselves */ static int last_signal; /* set the polling period to 100ms */ static int polling_period = 100; static int add_connection(struct service *service, struct command_context *cmd_ctx) { socklen_t address_size; struct connection *c, **p; int retval; int flag = 1; c = malloc(sizeof(struct connection)); c->fd = -1; c->fd_out = -1; memset(&c->sin, 0, sizeof(c->sin)); c->cmd_ctx = copy_command_context(cmd_ctx); c->service = service; c->input_pending = 0; c->priv = NULL; c->next = NULL; if (service->type == CONNECTION_TCP) { address_size = sizeof(c->sin); c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size); c->fd_out = c->fd; /* This increases performance dramatically for e.g. GDB load which * does not have a sliding window protocol. * * Ignore errors from this fn as it probably just means less performance */ setsockopt(c->fd, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char *)&flag, /* the cast is historical cruft */ sizeof(int)); /* length of option value */ LOG_INFO("accepting '%s' connection on tcp/%s", service->name, service->port); retval = service->new_connection(c); if (retval != ERROR_OK) { close_socket(c->fd); LOG_ERROR("attempted '%s' connection rejected", service->name); command_done(c->cmd_ctx); free(c); return retval; } } else if (service->type == CONNECTION_STDINOUT) { c->fd = service->fd; c->fd_out = fileno(stdout); #ifdef _WIN32 /* we are using stdin/out so ignore ctrl-c under windoze */ SetConsoleCtrlHandler(NULL, TRUE); #endif /* do not check for new connections again on stdin */ service->fd = -1; LOG_INFO("accepting '%s' connection from pipe", service->name); retval = service->new_connection(c); if (retval != ERROR_OK) { LOG_ERROR("attempted '%s' connection rejected", service->name); command_done(c->cmd_ctx); free(c); return retval; } } else if (service->type == CONNECTION_PIPE) { c->fd = service->fd; /* do not check for new connections again on stdin */ service->fd = -1; char *out_file = alloc_printf("%so", service->port); c->fd_out = open(out_file, O_WRONLY); free(out_file); if (c->fd_out == -1) { LOG_ERROR("could not open %s", service->port); exit(1); } LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port); retval = service->new_connection(c); if (retval != ERROR_OK) { LOG_ERROR("attempted '%s' connection rejected", service->name); command_done(c->cmd_ctx); free(c); return retval; } } /* add to the end of linked list */ for (p = &service->connections; *p; p = &(*p)->next) ; *p = c; service->max_connections--; return ERROR_OK; } static int remove_connection(struct service *service, struct connection *connection) { struct connection **p = &service->connections; struct connection *c; /* find connection */ while ((c = *p)) { if (c->fd == connection->fd) { service->connection_closed(c); if (service->type == CONNECTION_TCP) close_socket(c->fd); else if (service->type == CONNECTION_PIPE) { /* The service will listen to the pipe again */ c->service->fd = c->fd; } command_done(c->cmd_ctx); /* delete connection */ *p = c->next; free(c); service->max_connections++; break; } /* redirect p to next list pointer */ p = &(*p)->next; } return ERROR_OK; } /* FIX! make service return error instead of invoking exit() */ int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv) { struct service *c, **p; int so_reuseaddr_option = 1; c = malloc(sizeof(struct service)); c->name = strdup(name); c->port = strdup(port); c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */ c->fd = -1; c->connections = NULL; c->new_connection = new_connection_handler; c->input = input_handler; c->connection_closed = connection_closed_handler; c->priv = priv; c->next = NULL; long portnumber; if (strcmp(c->port, "pipe") == 0) c->type = CONNECTION_STDINOUT; else { char *end; portnumber = strtol(c->port, &end, 0); if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) { c->portnumber = portnumber; c->type = CONNECTION_TCP; } else c->type = CONNECTION_PIPE; } if (c->type == CONNECTION_TCP) { c->max_connections = max_connections; c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd == -1) { LOG_ERROR("error creating socket: %s", strerror(errno)); exit(-1); } setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&so_reuseaddr_option, sizeof(int)); socket_nonblock(c->fd); memset(&c->sin, 0, sizeof(c->sin)); c->sin.sin_family = AF_INET; c->sin.sin_addr.s_addr = INADDR_ANY; c->sin.sin_port = htons(c->portnumber); if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { LOG_ERROR("couldn't bind to socket: %s", strerror(errno)); exit(-1); } #ifndef _WIN32 int segsize = 65536; setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int)); #endif int window_size = 128 * 1024; /* These setsockopt()s must happen before the listen() */ setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)); setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)); if (listen(c->fd, 1) == -1) { LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); exit(-1); } } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); #ifdef _WIN32 /* for win32 set stdin/stdout to binary mode */ if (_setmode(_fileno(stdout), _O_BINARY) < 0) LOG_WARNING("cannot change stdout mode to binary"); if (_setmode(_fileno(stdin), _O_BINARY) < 0) LOG_WARNING("cannot change stdin mode to binary"); if (_setmode(_fileno(stderr), _O_BINARY) < 0) LOG_WARNING("cannot change stderr mode to binary"); #else socket_nonblock(c->fd); #endif } else if (c->type == CONNECTION_PIPE) { #ifdef _WIN32 /* we currenty do not support named pipes under win32 * so exit openocd for now */ LOG_ERROR("Named pipes currently not supported under this os"); exit(1); #else /* Pipe we're reading from */ c->fd = open(c->port, O_RDONLY | O_NONBLOCK); if (c->fd == -1) { LOG_ERROR("could not open %s", c->port); exit(1); } #endif } /* add to the end of linked list */ for (p = &services; *p; p = &(*p)->next) ; *p = c; return ERROR_OK; } static int remove_services(void) { struct service *c = services; /* loop service */ while (c) { struct service *next = c->next; if (c->name) free(c->name); if (c->type == CONNECTION_PIPE) { if (c->fd != -1) close(c->fd); } if (c->port) free(c->port); if (c->priv) free(c->priv); /* delete service */ free(c); /* remember the last service for unlinking */ c = next; } services = NULL; return ERROR_OK; } int server_loop(struct command_context *command_context) { struct service *service; bool poll_ok = true; /* used in select() */ fd_set read_fds; int fd_max; /* used in accept() */ int retval; #ifndef _WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) LOG_ERROR("couldn't set SIGPIPE to SIG_IGN"); #endif while (!shutdown_openocd) { /* monitor sockets for activity */ fd_max = 0; FD_ZERO(&read_fds); /* add service and connection fds to read_fds */ for (service = services; service; service = service->next) { if (service->fd != -1) { /* listen for new connections */ FD_SET(service->fd, &read_fds); if (service->fd > fd_max) fd_max = service->fd; } if (service->connections) { struct connection *c; for (c = service->connections; c; c = c->next) { /* check for activity on the connection */ FD_SET(c->fd, &read_fds); if (c->fd > fd_max) fd_max = c->fd; } } } struct timeval tv; tv.tv_sec = 0; if (poll_ok) { /* we're just polling this iteration, this is faster on embedded * hosts */ tv.tv_usec = 0; retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv); } else { /* Every 100ms, can be changed with "poll_period" command */ tv.tv_usec = polling_period * 1000; /* Only while we're sleeping we'll let others run */ openocd_sleep_prelude(); kept_alive(); retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv); openocd_sleep_postlude(); } if (retval == -1) { #ifdef _WIN32 errno = WSAGetLastError(); if (errno == WSAEINTR) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); exit(-1); } #else if (errno == EINTR) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); exit(-1); } #endif } if (retval == 0) { /* We only execute these callbacks when there was nothing to do or we timed *out */ target_call_timer_callbacks(); process_jim_events(command_context); FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */ /* We timed out/there was nothing to do, timeout rather than poll next time **/ poll_ok = false; } else { /* There was something to do, next time we'll just poll */ poll_ok = true; } /* This is a simple back-off algorithm where we immediately * re-poll if we did something this time around. * * This greatly improves performance of DCC. */ poll_ok = poll_ok || target_got_message(); for (service = services; service; service = service->next) { /* handle new connections on listeners */ if ((service->fd != -1) && (FD_ISSET(service->fd, &read_fds))) { if (service->max_connections > 0) add_connection(service, command_context); else { if (service->type == CONNECTION_TCP) { struct sockaddr_in sin; socklen_t address_size = sizeof(sin); int tmp_fd; tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size); close_socket(tmp_fd); } LOG_INFO( "rejected '%s' connection, no more connections allowed", service->name); } } /* handle activity on connections */ if (service->connections) { struct connection *c; for (c = service->connections; c; ) { if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) { retval = service->input(c); if (retval != ERROR_OK) { struct connection *next = c->next; if (service->type == CONNECTION_PIPE || service->type == CONNECTION_STDINOUT) { /* if connection uses a pipe then * shutdown openocd on error */ shutdown_openocd = 1; } remove_connection(service, c); LOG_INFO("dropped '%s' connection", service->name); c = next; continue; } } c = c->next; } } } #ifdef _WIN32 MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) shutdown_openocd = 1; } #endif } return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL; } #ifdef _WIN32 BOOL WINAPI ControlHandler(DWORD dwCtrlType) { shutdown_openocd = 1; return TRUE; } #endif void sig_handler(int sig) { /* store only first signal that hits us */ if (!last_signal) last_signal = sig; shutdown_openocd = 1; } int server_preinit(void) { /* this currently only calls WSAStartup on native win32 systems * before any socket operations are performed. * This is an issue if you call init in your config script */ #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); if (WSAStartup(wVersionRequested, &wsaData) != 0) { LOG_ERROR("Failed to Open Winsock"); exit(-1); } /* register ctrl-c handler */ SetConsoleCtrlHandler(ControlHandler, TRUE); signal(SIGBREAK, sig_handler); #endif signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); signal(SIGABRT, sig_handler); return ERROR_OK; } int server_init(struct command_context *cmd_ctx) { int ret = tcl_init(); if (ERROR_OK != ret) return ret; return telnet_init("Open On-Chip Debugger"); } int server_quit(void) { remove_services(); target_quit(); #ifdef _WIN32 WSACleanup(); SetConsoleCtrlHandler(ControlHandler, FALSE); return ERROR_OK; #endif /* return signal number so we can kill ourselves */ return last_signal; } void exit_on_signal(int sig) { #ifndef _WIN32 /* bring back default system handler and kill yourself */ signal(sig, SIG_DFL); kill(getpid(), sig); #endif } int connection_write(struct connection *connection, const void *data, int len) { if (len == 0) { /* successful no-op. Sockets and pipes behave differently here... */ return 0; } if (connection->service->type == CONNECTION_TCP) return write_socket(connection->fd_out, data, len); else return write(connection->fd_out, data, len); } int connection_read(struct connection *connection, void *data, int len) { if (connection->service->type == CONNECTION_TCP) return read_socket(connection->fd, data, len); else return read(connection->fd, data, len); } /* tell the server we want to shut down */ COMMAND_HANDLER(handle_shutdown_command) { LOG_USER("shutdown command invoked"); shutdown_openocd = 1; if (CMD_ARGC == 1) { if (!strcmp(CMD_ARGV[0], "error")) { shutdown_openocd = 2; return ERROR_FAIL; } } return ERROR_COMMAND_CLOSE_CONNECTION; } COMMAND_HANDLER(handle_poll_period_command) { if (CMD_ARGC == 0) LOG_WARNING("You need to set a period value"); else COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], polling_period); LOG_INFO("set servers polling period to %ums", polling_period); return ERROR_OK; } static const struct command_registration server_command_handlers[] = { { .name = "shutdown", .handler = &handle_shutdown_command, .mode = COMMAND_ANY, .usage = "", .help = "shut the server down", }, { .name = "poll_period", .handler = &handle_poll_period_command, .mode = COMMAND_ANY, .usage = "", .help = "set the servers polling period", }, COMMAND_REGISTRATION_DONE }; int server_register_commands(struct command_context *cmd_ctx) { int retval = telnet_register_commands(cmd_ctx); if (ERROR_OK != retval) return retval; retval = tcl_register_commands(cmd_ctx); if (ERROR_OK != retval) return retval; retval = jsp_register_commands(cmd_ctx); if (ERROR_OK != retval) return retval; return register_commands(cmd_ctx, NULL, server_command_handlers); } COMMAND_HELPER(server_port_command, unsigned short *out) { switch (CMD_ARGC) { case 0: command_print(CMD_CTX, "%d", *out); break; case 1: { uint16_t port; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port); *out = port; break; } default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } COMMAND_HELPER(server_pipe_command, char **out) { switch (CMD_ARGC) { case 0: command_print(CMD_CTX, "%s", *out); break; case 1: { if (CMD_CTX->mode == COMMAND_EXEC) { LOG_WARNING("unable to change server port after init"); return ERROR_COMMAND_ARGUMENT_INVALID; } free(*out); *out = strdup(CMD_ARGV[0]); break; } default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } openocd-0.9.0/src/server/server.h0000644000175000017500000001015212516456303013650 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef SERVER_H #define SERVER_H #include #ifdef HAVE_NETINET_IN_H #include #endif enum connection_type { CONNECTION_TCP, CONNECTION_PIPE, CONNECTION_STDINOUT }; struct connection { int fd; int fd_out; /* When using pipes we're writing to a different fd */ struct sockaddr_in sin; struct command_context *cmd_ctx; struct service *service; int input_pending; void *priv; struct connection *next; }; typedef int (*new_connection_handler_t)(struct connection *connection); typedef int (*input_handler_t)(struct connection *connection); typedef int (*connection_closed_handler_t)(struct connection *connection); struct service { char *name; enum connection_type type; char *port; unsigned short portnumber; int fd; struct sockaddr_in sin; int max_connections; struct connection *connections; new_connection_handler_t new_connection; input_handler_t input; connection_closed_handler_t connection_closed; void *priv; struct service *next; }; int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t in_handler, connection_closed_handler_t close_handler, void *priv); int server_preinit(void); int server_init(struct command_context *cmd_ctx); int server_quit(void); void exit_on_signal(int); int server_loop(struct command_context *command_context); int server_register_commands(struct command_context *context); int connection_write(struct connection *connection, const void *data, int len); int connection_read(struct connection *connection, void *data, int len); /** * Used by server_loop(), defined in server_stubs.c */ void openocd_sleep_prelude(void); /** * Used by server_loop(), defined in server_stubs.c */ void openocd_sleep_postlude(void); /** * Defines an extended command handler function declaration to enable * access to (and manipulation of) the server port number. * Call server_port like a normal COMMAND_HANDLER with an extra @a out parameter * to receive the specified port number. */ COMMAND_HELPER(server_pipe_command, char **out); COMMAND_HELPER(server_port_command, unsigned short *out); #define ERROR_SERVER_REMOTE_CLOSED (-400) #define ERROR_CONNECTION_REJECTED (-401) #endif /* SERVER_H */ openocd-0.9.0/src/target/0000755000175000017500000000000012526202226012224 500000000000000openocd-0.9.0/src/target/dsp5680xx.c0000644000175000017500000017526312315575361014030 00000000000000/*************************************************************************** * Copyright (C) 2011 by Rodrigo L. Rosa * * rodrigorosa.LG@gmail.com * * * * Based on dsp563xx_once.h written by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "target_type.h" #include "dsp5680xx.h" struct dsp5680xx_common dsp5680xx_context; #define _E "DSP5680XX_ERROR:%d\nAt:%s:%d:%s" #define err_check(r, c, m) if (r != ERROR_OK) {LOG_ERROR(_E, c, __func__, __LINE__, m); return r; } #define err_check_propagate(retval) if (retval != ERROR_OK) return retval; #define DEBUG_MSG "Debug mode be enabled to read mem." #define DEBUG_FAIL { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IN_DEBUG, DEBUG_MSG) } #define CHECK_DBG if (!dsp5680xx_context.debug_mode_enabled) DEBUG_FAIL #define HALT_MSG "Target must be halted." #define HALT_FAIL { err_check(ERROR_FAIL, DSP5680XX_ERROR_TARGET_RUNNING, HALT_MSG) } #define CHECK_HALT(target) if (target->state != TARGET_HALTED) HALT_FAIL #define check_halt_and_debug(target) { CHECK_HALT(target); CHECK_DBG; } int dsp5680xx_execute_queue(void) { int retval; retval = jtag_execute_queue(); return retval; } /** * Reset state machine */ static int reset_jtag(void) { int retval; tap_state_t states[2]; const char *cp = "RESET"; states[0] = tap_state_by_name(cp); retval = jtag_add_statemove(states[0]); err_check_propagate(retval); retval = jtag_execute_queue(); err_check_propagate(retval); jtag_add_pathmove(0, states + 1); retval = jtag_execute_queue(); return retval; } static int dsp5680xx_drscan(struct target *target, uint8_t *d_in, uint8_t *d_out, int len) { /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * *Inputs: * - d_in: This is the data that will be shifted into the JTAG DR reg. * - d_out: The data that will be shifted out of the JTAG DR reg will stored here * - len: Length of the data to be shifted to JTAG DR. * *Note: If d_out == NULL, discard incoming bits. * *-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */ int retval = ERROR_OK; if (NULL == target->tap) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_INVALID_TAP, "Invalid tap"); } if (len > 32) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_DR_LEN_OVERFLOW, "dr_len overflow, maxium is 32"); } /* TODO what values of len are valid for jtag_add_plain_dr_scan? */ /* can i send as many bits as i want? */ /* is the casting necessary? */ jtag_add_plain_dr_scan(len, d_in, d_out, TAP_IDLE); if (dsp5680xx_context.flush) { retval = dsp5680xx_execute_queue(); err_check(retval, DSP5680XX_ERROR_JTAG_DRSCAN, "drscan failed!"); } if (d_out != NULL) LOG_DEBUG("Data read (%d bits): 0x%04X", len, *d_out); else LOG_DEBUG("Data read was discarded."); return retval; } /** * Test func * * @param target * @param d_in This is the data that will be shifted into the JTAG IR reg. * @param d_out The data that will be shifted out of the JTAG IR reg will be stored here. * @apram ir_len Length of the data to be shifted to JTAG IR. * */ static int dsp5680xx_irscan(struct target *target, uint32_t *d_in, uint32_t *d_out, uint8_t ir_len) { int retval = ERROR_OK; uint16_t tap_ir_len = DSP5680XX_JTAG_MASTER_TAP_IRLEN; if (NULL == target->tap) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_INVALID_TAP, "Invalid tap"); } if (ir_len != target->tap->ir_length) { if (target->tap->enabled) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_INVALID_IR_LEN, "Invalid irlen"); } else { struct jtag_tap *t = jtag_tap_by_string("dsp568013.chp"); if ((t == NULL) || ((t->enabled) && (ir_len != tap_ir_len))) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_INVALID_IR_LEN, "Invalid irlen"); } } } jtag_add_plain_ir_scan(ir_len, (uint8_t *) d_in, (uint8_t *) d_out, TAP_IDLE); if (dsp5680xx_context.flush) { retval = dsp5680xx_execute_queue(); err_check(retval, DSP5680XX_ERROR_JTAG_IRSCAN, "irscan failed!"); } return retval; } static int dsp5680xx_jtag_status(struct target *target, uint8_t *status) { uint32_t read_from_ir; uint32_t instr; int retval; instr = JTAG_INSTR_ENABLE_ONCE; retval = dsp5680xx_irscan(target, &instr, &read_from_ir, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); if (status != NULL) *status = (uint8_t) read_from_ir; return ERROR_OK; } static int jtag_data_read(struct target *target, uint8_t *data_read, int num_bits) { uint32_t bogus_instr = 0; int retval = dsp5680xx_drscan(target, (uint8_t *) &bogus_instr, data_read, num_bits); LOG_DEBUG("Data read (%d bits): 0x%04X", num_bits, *data_read); /** TODO remove this or move to jtagio? */ return retval; } #define jtag_data_read8(target, data_read) jtag_data_read(target, data_read, 8) #define jtag_data_read16(target, data_read) jtag_data_read(target, data_read, 16) #define jtag_data_read32(target, data_read) jtag_data_read(target, data_read, 32) static uint32_t data_read_dummy; static int jtag_data_write(struct target *target, uint32_t instr, int num_bits, uint32_t *data_read) { int retval; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &data_read_dummy, num_bits); err_check_propagate(retval); if (data_read != NULL) *data_read = data_read_dummy; return retval; } #define jtag_data_write8(target, instr, data_read) jtag_data_write(target, instr, 8, data_read) #define jtag_data_write16(target, instr, data_read) jtag_data_write(target, instr, 16, data_read) #define jtag_data_write24(target, instr, data_read) jtag_data_write(target, instr, 24, data_read) #define jtag_data_write32(target, instr, data_read) jtag_data_write(target, instr, 32, data_read) /** * Executes EOnCE instruction. * * @param target * @param instr Instruction to execute. * @param rw * @param go * @param ex * @param eonce_status Value read from the EOnCE status register. * * @return */ static int eonce_instruction_exec_single(struct target *target, uint8_t instr, uint8_t rw, uint8_t go, uint8_t ex, uint8_t *eonce_status) { int retval; uint32_t dr_out_tmp; uint8_t instr_with_flags = instr | (rw << 7) | (go << 6) | (ex << 5); retval = jtag_data_write(target, instr_with_flags, 8, &dr_out_tmp); err_check_propagate(retval); if (eonce_status != NULL) *eonce_status = (uint8_t) dr_out_tmp; return retval; } /* wrappers for multi opcode instructions */ #define dsp5680xx_exe_1(target, oc1, oc2, oc3) dsp5680xx_exe1(target, oc1) #define dsp5680xx_exe_2(target, oc1, oc2, oc3) dsp5680xx_exe2(target, oc1, oc2) #define dsp5680xx_exe_3(target, oc1, oc2, oc3) dsp5680xx_exe3(target, oc1, oc2, oc3) #define dsp5680xx_exe_generic(t, words, oc1, oc2, oc3) dsp5680xx_exe_##words(t, oc1, oc2, oc3) /* Executes one word DSP instruction */ static int dsp5680xx_exe1(struct target *target, uint16_t opcode) { int retval; retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode, NULL); err_check_propagate(retval); return retval; } /* Executes two word DSP instruction */ static int dsp5680xx_exe2(struct target *target, uint16_t opcode1, uint16_t opcode2) { int retval; retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode1, NULL); err_check_propagate(retval); retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode2, NULL); err_check_propagate(retval); return retval; } /* Executes three word DSP instruction */ static int dsp5680xx_exe3(struct target *target, uint16_t opcode1, uint16_t opcode2, uint16_t opcode3) { int retval; retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode1, NULL); err_check_propagate(retval); retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode2, NULL); err_check_propagate(retval); retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, opcode3, NULL); err_check_propagate(retval); return retval; } /* *--------------- Real-time data exchange --------------- * The EOnCE Transmit (OTX) and Receive (ORX) registers are data memory mapped, each with an upper * and lower 16 bit word. * Transmit and receive directions are defined from the core’s perspective. * The core writes to the Transmit register and reads the Receive register, and the host through * JTAG writes to the Receive register and reads the Transmit register. * Both registers have a combined data memory mapped OTXRXSR which provides indication when * each may be accessed. * ref: eonce_rev.1.0_0208081.pdf@36 */ /* writes data into upper ORx register of the target */ static int core_tx_upper_data(struct target *target, uint16_t data, uint32_t *eonce_status_low) { int retval; retval = eonce_instruction_exec_single(target, DSP5680XX_ONCE_ORX1, 0, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_write16(target, data, eonce_status_low); err_check_propagate(retval); return retval; } /* writes data into lower ORx register of the target */ #define CMD1 eonce_instruction_exec_single(target, DSP5680XX_ONCE_ORX, 0, 0, 0, NULL); #define CMD2 jtag_data_write16((t, data) #define core_tx_lower_data(t, data) PT1\ PT2 /** * * @param target * @param data_read: Returns the data read from the upper OTX register via JTAG. * @return: Returns an error code (see error code documentation) */ static int core_rx_upper_data(struct target *target, uint8_t *data_read) { int retval; retval = eonce_instruction_exec_single(target, DSP5680XX_ONCE_OTX1, 1, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_read16(target, data_read); err_check_propagate(retval); return retval; } /** * * @param target * @param data_read: Returns the data read from the lower OTX register via JTAG. * @return: Returns an error code (see error code documentation) */ static int core_rx_lower_data(struct target *target, uint8_t *data_read) { int retval; retval = eonce_instruction_exec_single(target, DSP5680XX_ONCE_OTX, 1, 0, 0, NULL); err_check_propagate(retval); retval = jtag_data_read16(target, data_read); err_check_propagate(retval); return retval; } /* *-- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- *-- -- -- -- --- -- -- -Core Instructions- -- -- -- --- -- -- -- --- -- *-- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- */ #define exe(a, b, c, d, e) dsp5680xx_exe_generic(a, b, c, d, e) /* move.l #value, r0 */ #define core_move_long_to_r0(target, value) exe(target, 3, 0xe418, value&0xffff, value>>16) /* move.l #value, n */ #define core_move_long_to_n(target, value) exe(target, 3, 0xe41e, value&0xffff, value>>16) /* move x:(r0), y0 */ #define core_move_at_r0_to_y0(target) exe(target, 1, 0xF514, 0, 0) /* move x:(r0), y1 */ #define core_move_at_r0_to_y1(target) exe(target, 1, 0xF714, 0, 0) /* move.l x:(r0), y */ #define core_move_long_at_r0_y(target) exe(target, 1, 0xF734, 0, 0) /* move y0, x:(r0) */ #define core_move_y0_at_r0(target) exe(target, 1, 0xd514, 0, 0) /* bfclr #value, x:(r0) */ #define eonce_bfclr_at_r0(target, value) exe(target, 2, 0x8040, value, 0) /* move #value, y0 */ #define core_move_value_to_y0(target, value) exe(target, 2, 0x8745, value, 0) /* move.w y0, x:(r0)+ */ #define core_move_y0_at_r0_inc(target) exe(target, 1, 0xd500, 0, 0) /* move.w y0, p:(r0)+ */ #define core_move_y0_at_pr0_inc(target) exe(target, 1, 0x8560, 0, 0) /* move.w p:(r0)+, y0 */ #define core_move_at_pr0_inc_to_y0(target) exe(target, 1, 0x8568, 0, 0) /* move.w p:(r0)+, y1 */ #define core_move_at_pr0_inc_to_y1(target) exe(target, 1, 0x8768, 0, 0) /* move.l #value, r2 */ #define core_move_long_to_r2(target, value) exe(target, 3, 0xe41A, value&0xffff, value>>16) /* move y0, x:(r2) */ #define core_move_y0_at_r2(target) exe(target, 1, 0xd516, 0, 0) /* move.w #, x:(r2) */ #define core_move_value_at_r2(target, value) exe(target, 2, 0x8642, value, 0) /* move.w #, x:(r0) */ #define core_move_value_at_r0(target, value) exe(target, 2, 0x8640, value, 0) /* move.w #, x:(R2+) */ #define core_move_value_at_r2_disp(target, value, disp) exe(target, 3, 0x8646, value, disp) /* move.w x:(r2), Y0 */ #define core_move_at_r2_to_y0(target) exe(target, 1, 0xF516, 0, 0) /* move.w p:(r2)+, y0 */ #define core_move_at_pr2_inc_to_y0(target) exe(target, 1, 0x856A, 0, 0) /* move.l #value, r3 */ #define core_move_long_to_r1(target, value) exe(target, 3, 0xE419, value&0xffff, value>>16) /* move.l #value, r3 */ #define core_move_long_to_r3(target, value) exe(target, 3, 0xE41B, value&0xffff, value>>16) /* move.w y0, p:(r3)+ */ #define core_move_y0_at_pr3_inc(target) exe(target, 1, 0x8563, 0, 0) /* move.w y0, x:(r3) */ #define core_move_y0_at_r3(target) exe(target, 1, 0xD503, 0, 0) /* move.l #value, r4 */ #define core_move_long_to_r4(target, value) exe(target, 3, 0xE41C, value&0xffff, value>>16) /* move pc, r4 */ #define core_move_pc_to_r4(target) exe(target, 1, 0xE716, 0, 0) /* move.l r4, y */ #define core_move_r4_to_y(target) exe(target, 1, 0xe764, 0, 0) /* move.w p:(r0)+, y0 */ #define core_move_at_pr0_inc_to_y0(target) exe(target, 1, 0x8568, 0, 0) /* move.w x:(r0)+, y0 */ #define core_move_at_r0_inc_to_y0(target) exe(target, 1, 0xf500, 0, 0) /* move x:(r0), y0 */ #define core_move_at_r0_y0(target) exe(target, 1, 0xF514, 0, 0) /* nop */ #define eonce_nop(target) exe(target, 1, 0xe700, 0, 0) /* move.w x:(R2+), Y0 */ #define core_move_at_r2_disp_to_y0(target, disp) exe(target, 2, 0xF542, disp, 0) /* move.w y1, x:(r2) */ #define core_move_y1_at_r2(target) exe(target, 1, 0xd716, 0, 0) /* move.w y1, x:(r0) */ #define core_move_y1_at_r0(target) exe(target, 1, 0xd714, 0, 0) /* move.bp y0, x:(r0)+ */ #define core_move_byte_y0_at_r0(target) exe(target, 1, 0xd5a0, 0, 0) /* move.w y1, p:(r0)+ */ #define core_move_y1_at_pr0_inc(target) exe(target, 1, 0x8760, 0, 0) /* move.w y1, x:(r0)+ */ #define core_move_y1_at_r0_inc(target) exe(target, 1, 0xD700, 0, 0) /* move.l #value, y */ #define core_move_long_to_y(target, value) exe(target, 3, 0xe417, value&0xffff, value>>16) static int core_move_value_to_pc(struct target *target, uint32_t value) { check_halt_and_debug(target); int retval; retval = dsp5680xx_exe_generic(target, 3, 0xE71E, value & 0xffff, value >> 16); err_check_propagate(retval); return retval; } static int eonce_load_TX_RX_to_r0(struct target *target) { int retval; retval = core_move_long_to_r0(target, ((MC568013_EONCE_TX_RX_ADDR) + (MC568013_EONCE_OBASE_ADDR << 16))); return retval; } static int core_load_TX_RX_high_addr_to_r0(struct target *target) { int retval = 0; retval = core_move_long_to_r0(target, ((MC568013_EONCE_TX1_RX1_HIGH_ADDR) + (MC568013_EONCE_OBASE_ADDR << 16))); return retval; } static int dsp5680xx_read_core_reg(struct target *target, uint8_t reg_addr, uint16_t *data_read) { /* TODO implement a general version of this which matches what openocd uses. */ int retval; uint32_t dummy_data_to_shift_into_dr; retval = eonce_instruction_exec_single(target, reg_addr, 1, 0, 0, NULL); err_check_propagate(retval); retval = dsp5680xx_drscan(target, (uint8_t *) &dummy_data_to_shift_into_dr, (uint8_t *) data_read, 8); err_check_propagate(retval); LOG_DEBUG("Reg. data: 0x%02X.", *data_read); return retval; } static int eonce_read_status_reg(struct target *target, uint16_t *data) { int retval; retval = dsp5680xx_read_core_reg(target, DSP5680XX_ONCE_OSR, data); err_check_propagate(retval); return retval; } /** * Takes the core out of debug mode. * * @param target * @param eonce_status Data read from the EOnCE status register. * * @return */ static int eonce_exit_debug_mode(struct target *target, uint8_t *eonce_status) { int retval; retval = eonce_instruction_exec_single(target, 0x1F, 0, 0, 1, eonce_status); err_check_propagate(retval); return retval; } static int switch_tap(struct target *target, struct jtag_tap *master_tap, struct jtag_tap *core_tap) { int retval = ERROR_OK; uint32_t instr; uint32_t ir_out; /* not used, just to make jtag happy. */ if (master_tap == NULL) { master_tap = jtag_tap_by_string("dsp568013.chp"); if (master_tap == NULL) { retval = ERROR_FAIL; const char *msg = "Failed to get master tap."; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER, msg); } } if (core_tap == NULL) { core_tap = jtag_tap_by_string("dsp568013.cpu"); if (core_tap == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE, "Failed to get core tap."); } } if (!(((int)master_tap->enabled) ^ ((int)core_tap->enabled))) { LOG_WARNING ("Master:%d\nCore:%d\nOnly 1 should be enabled.\n", (int)master_tap->enabled, (int)core_tap->enabled); } if (master_tap->enabled) { instr = 0x5; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_MASTER_TAP_IRLEN); err_check_propagate(retval); instr = 0x2; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 4); err_check_propagate(retval); core_tap->enabled = true; master_tap->enabled = false; } else { instr = 0x08; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); instr = 0x1; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 4); err_check_propagate(retval); core_tap->enabled = false; master_tap->enabled = true; } return retval; } /** * Puts the core into debug mode, enabling the EOnCE module. * This will not always work, eonce_enter_debug_mode executes much * more complicated routine, which is guaranteed to work, but requires * a reset. This will complicate comm with the flash module, since * after a reset clock divisors must be set again. * This implementation works most of the time, and is not accesible to the * user. * * @param target * @param eonce_status Data read from the EOnCE status register. * * @return */ static int eonce_enter_debug_mode_without_reset(struct target *target, uint16_t *eonce_status) { int retval; uint32_t instr = JTAG_INSTR_DEBUG_REQUEST; uint32_t ir_out; /* not used, just to make jtag happy.*/ /* Debug request #1 */ retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); /* Enable EOnCE module */ instr = JTAG_INSTR_ENABLE_ONCE; /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */ retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); if ((ir_out & JTAG_STATUS_MASK) == JTAG_STATUS_DEBUG) target->state = TARGET_HALTED; else { retval = ERROR_FAIL; err_check_propagate(retval); } /* Verify that debug mode is enabled */ uint16_t data_read_from_dr; retval = eonce_read_status_reg(target, &data_read_from_dr); err_check_propagate(retval); if ((data_read_from_dr & 0x30) == 0x30) { LOG_DEBUG("EOnCE successfully entered debug mode."); dsp5680xx_context.debug_mode_enabled = true; retval = ERROR_OK; } else { dsp5680xx_context.debug_mode_enabled = false; retval = ERROR_TARGET_FAILURE; /** *No error msg here, since there is still hope with full halting sequence */ err_check_propagate(retval); } if (eonce_status != NULL) *eonce_status = data_read_from_dr; return retval; } /** * Puts the core into debug mode, enabling the EOnCE module. * * @param target * @param eonce_status Data read from the EOnCE status register. * * @return */ static int eonce_enter_debug_mode(struct target *target, uint16_t *eonce_status) { int retval = ERROR_OK; uint32_t instr = JTAG_INSTR_DEBUG_REQUEST; uint32_t ir_out; /* not used, just to make jtag happy. */ uint16_t instr_16; uint16_t read_16; /* First try the easy way */ retval = eonce_enter_debug_mode_without_reset(target, eonce_status); if (retval == ERROR_OK) return retval; struct jtag_tap *tap_chp; struct jtag_tap *tap_cpu; tap_chp = jtag_tap_by_string("dsp568013.chp"); if (tap_chp == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER, "Failed to get master tap."); } tap_cpu = jtag_tap_by_string("dsp568013.cpu"); if (tap_cpu == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE, "Failed to get master tap."); } /* Enable master tap */ tap_chp->enabled = true; tap_cpu->enabled = false; instr = MASTER_TAP_CMD_IDCODE; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_MASTER_TAP_IRLEN); err_check_propagate(retval); jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000); /* Enable EOnCE module */ jtag_add_reset(0, 1); jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000); instr = 0x0606ffff; /* This was selected experimentally. */ retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 32); err_check_propagate(retval); /* ir_out now hold tap idcode */ /* Enable core tap */ tap_chp->enabled = true; retval = switch_tap(target, tap_chp, tap_cpu); err_check_propagate(retval); instr = JTAG_INSTR_ENABLE_ONCE; /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */ retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); instr = JTAG_INSTR_DEBUG_REQUEST; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); instr_16 = 0x1; retval = dsp5680xx_drscan(target, (uint8_t *) &instr_16, (uint8_t *) &read_16, 8); err_check_propagate(retval); instr_16 = 0x20; retval = dsp5680xx_drscan(target, (uint8_t *) &instr_16, (uint8_t *) &read_16, 8); err_check_propagate(retval); jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000); jtag_add_reset(0, 0); jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000); instr = JTAG_INSTR_ENABLE_ONCE; /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */ for (int i = 0; i < 3; i++) { retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); } if ((ir_out & JTAG_STATUS_MASK) == JTAG_STATUS_DEBUG) target->state = TARGET_HALTED; else { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_HALT, "Failed to halt target."); } for (int i = 0; i < 3; i++) { instr_16 = 0x86; dsp5680xx_drscan(target, (uint8_t *) &instr_16, (uint8_t *) &read_16, 16); instr_16 = 0xff; dsp5680xx_drscan(target, (uint8_t *) &instr_16, (uint8_t *) &read_16, 16); } /* Verify that debug mode is enabled */ uint16_t data_read_from_dr; retval = eonce_read_status_reg(target, &data_read_from_dr); err_check_propagate(retval); if ((data_read_from_dr & 0x30) == 0x30) { LOG_DEBUG("EOnCE successfully entered debug mode."); dsp5680xx_context.debug_mode_enabled = true; retval = ERROR_OK; } else { const char *msg = "Failed to set EOnCE module to debug mode"; retval = ERROR_TARGET_FAILURE; err_check(retval, DSP5680XX_ERROR_ENTER_DEBUG_MODE, msg); } if (eonce_status != NULL) *eonce_status = data_read_from_dr; return retval; } /** * Reads the current value of the program counter and stores it. * * @param target * * @return */ static int eonce_pc_store(struct target *target) { uint8_t tmp[2]; int retval; retval = core_move_pc_to_r4(target); err_check_propagate(retval); retval = core_move_r4_to_y(target); err_check_propagate(retval); retval = eonce_load_TX_RX_to_r0(target); err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); retval = core_rx_lower_data(target, tmp); err_check_propagate(retval); LOG_USER("PC value: 0x%X%X\n", tmp[1], tmp[0]); dsp5680xx_context.stored_pc = (tmp[0] | (tmp[1] << 8)); return ERROR_OK; } static int dsp5680xx_target_create(struct target *target, Jim_Interp *interp) { struct dsp5680xx_common *dsp5680xx = calloc(1, sizeof(struct dsp5680xx_common)); target->arch_info = dsp5680xx; return ERROR_OK; } static int dsp5680xx_init_target(struct command_context *cmd_ctx, struct target *target) { dsp5680xx_context.stored_pc = 0; dsp5680xx_context.flush = 1; dsp5680xx_context.debug_mode_enabled = false; LOG_DEBUG("target initiated!"); /* TODO core tap must be enabled before running these commands, currently * this is done in the .cfg tcl script. */ return ERROR_OK; } static int dsp5680xx_arch_state(struct target *target) { LOG_USER("%s not implemented yet.", __func__); return ERROR_OK; } int dsp5680xx_target_status(struct target *target, uint8_t *jtag_st, uint16_t *eonce_st) { return target->state; } static int dsp5680xx_assert_reset(struct target *target) { target->state = TARGET_RESET; return ERROR_OK; } static int dsp5680xx_deassert_reset(struct target *target) { target->state = TARGET_RUNNING; return ERROR_OK; } static int dsp5680xx_halt(struct target *target) { int retval; uint16_t eonce_status = 0xbeef; if ((target->state == TARGET_HALTED) && (dsp5680xx_context.debug_mode_enabled)) { LOG_USER("Target already halted and in debug mode."); return ERROR_OK; } else { if (target->state == TARGET_HALTED) LOG_USER ("Target already halted, re attempting to enter debug mode."); } retval = eonce_enter_debug_mode(target, &eonce_status); err_check_propagate(retval); retval = eonce_pc_store(target); err_check_propagate(retval); if (dsp5680xx_context.debug_mode_enabled) { retval = eonce_pc_store(target); err_check_propagate(retval); } return retval; } static int dsp5680xx_poll(struct target *target) { int retval; uint8_t jtag_status; uint8_t eonce_status; uint16_t read_tmp; retval = dsp5680xx_jtag_status(target, &jtag_status); err_check_propagate(retval); if (jtag_status == JTAG_STATUS_DEBUG) if (target->state != TARGET_HALTED) { retval = eonce_enter_debug_mode(target, &read_tmp); err_check_propagate(retval); eonce_status = (uint8_t) read_tmp; if ((eonce_status & EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_DEBUG_M) { const char *msg = "%s: Failed to put EOnCE in debug mode.Flash locked?..."; LOG_WARNING(msg, __func__); return ERROR_TARGET_FAILURE; } else { target->state = TARGET_HALTED; return ERROR_OK; } } if (jtag_status == JTAG_STATUS_NORMAL) { if (target->state == TARGET_RESET) { retval = dsp5680xx_halt(target); err_check_propagate(retval); retval = eonce_exit_debug_mode(target, &eonce_status); err_check_propagate(retval); if ((eonce_status & EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_NORMAL_M) { const char *msg = "%s: JTAG running, but EOnCE run failed.Try resetting.."; LOG_WARNING(msg, __func__); return ERROR_TARGET_FAILURE; } else { target->state = TARGET_RUNNING; return ERROR_OK; } } if (target->state != TARGET_RUNNING) { retval = eonce_read_status_reg(target, &read_tmp); err_check_propagate(retval); eonce_status = (uint8_t) read_tmp; if ((eonce_status & EONCE_STAT_MASK) != DSP5680XX_ONCE_OSCR_NORMAL_M) { LOG_WARNING ("Inconsistent target status. Restart!"); return ERROR_TARGET_FAILURE; } } target->state = TARGET_RUNNING; return ERROR_OK; } if (jtag_status == JTAG_STATUS_DEAD) { LOG_ERROR ("%s: Cannot communicate with JTAG. Check connection...", __func__); target->state = TARGET_UNKNOWN; return ERROR_TARGET_FAILURE; }; if (target->state == TARGET_UNKNOWN) { LOG_ERROR("%s: Target status invalid - communication failure", __func__); return ERROR_TARGET_FAILURE; }; return ERROR_OK; } static int dsp5680xx_resume(struct target *target, int current, uint32_t address, int hb, int d) { if (target->state == TARGET_RUNNING) { LOG_USER("Target already running."); return ERROR_OK; } int retval; uint8_t eonce_status; uint8_t jtag_status; if (dsp5680xx_context.debug_mode_enabled) { if (!current) { retval = core_move_value_to_pc(target, address); err_check_propagate(retval); } int retry = 20; while (retry-- > 1) { retval = eonce_exit_debug_mode(target, &eonce_status); err_check_propagate(retval); if (eonce_status == DSP5680XX_ONCE_OSCR_NORMAL_M) break; } if (retry == 0) { retval = ERROR_TARGET_FAILURE; err_check(retval, DSP5680XX_ERROR_EXIT_DEBUG_MODE, "Failed to exit debug mode..."); } else { target->state = TARGET_RUNNING; dsp5680xx_context.debug_mode_enabled = false; } LOG_DEBUG("EOnCE status: 0x%02X.", eonce_status); } else { /* * If debug mode was not enabled but target was halted, then it is most likely that * access to eonce registers is locked. * Reset target to make it run again. */ jtag_add_reset(0, 1); jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000); retval = reset_jtag(); err_check(retval, DSP5680XX_ERROR_JTAG_RESET, "Failed to reset JTAG state machine"); jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000); jtag_add_reset(0, 0); jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000); retval = dsp5680xx_jtag_status(target, &jtag_status); err_check_propagate(retval); if ((jtag_status & JTAG_STATUS_MASK) == JTAG_STATUS_NORMAL) { target->state = TARGET_RUNNING; dsp5680xx_context.debug_mode_enabled = false; } else { retval = ERROR_TARGET_FAILURE; err_check(retval, DSP5680XX_ERROR_RESUME, "Failed to resume target"); } } return ERROR_OK; } /** * The value of @address determines if it corresponds to P: (program) or X: (dat) memory. * If the address is over 0x200000 then it is considered X: memory, and @pmem = 0. * The special case of 0xFFXXXX is not modified, since it allows to read out the * memory mapped EOnCE registers. * * @param address * @param pmem * * @return */ static int dsp5680xx_convert_address(uint32_t *address, int *pmem) { /* * Distinguish data memory (x) from program memory (p) by the address. * Addresses over S_FILE_DATA_OFFSET are considered (x) memory. */ if (*address >= S_FILE_DATA_OFFSET) { *pmem = 0; if (((*address) & 0xff0000) != 0xff0000) *address -= S_FILE_DATA_OFFSET; } return ERROR_OK; } static int dsp5680xx_read_16_single(struct target *t, uint32_t a, uint8_t *data_read, int r_pmem) { struct target *target = t; uint32_t address = a; int retval; retval = core_move_long_to_r0(target, address); err_check_propagate(retval); if (r_pmem) retval = core_move_at_pr0_inc_to_y0(target); else retval = core_move_at_r0_to_y0(target); err_check_propagate(retval); retval = eonce_load_TX_RX_to_r0(target); err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); /* at this point the data i want is at the reg eonce can read */ retval = core_rx_lower_data(target, data_read); err_check_propagate(retval); LOG_DEBUG("%s:Data read from 0x%06" PRIX32 ": 0x%02X%02X", __func__, address, data_read[1], data_read[0]); return retval; } static int dsp5680xx_read_32_single(struct target *t, uint32_t a, uint8_t *data_read, int r_pmem) { struct target *target = t; uint32_t address = a; int retval; address = (address & 0xFFFFF); /* Get data to an intermediate register */ retval = core_move_long_to_r0(target, address); err_check_propagate(retval); if (r_pmem) { retval = core_move_at_pr0_inc_to_y0(target); err_check_propagate(retval); retval = core_move_at_pr0_inc_to_y1(target); err_check_propagate(retval); } else { retval = core_move_at_r0_inc_to_y0(target); err_check_propagate(retval); retval = core_move_at_r0_to_y1(target); err_check_propagate(retval); } /* Get lower part of data to TX/RX */ retval = eonce_load_TX_RX_to_r0(target); err_check_propagate(retval); retval = core_move_y0_at_r0_inc(target); /* This also load TX/RX high to r0 */ err_check_propagate(retval); /* Get upper part of data to TX/RX */ retval = core_move_y1_at_r0(target); err_check_propagate(retval); /* at this point the data i want is at the reg eonce can read */ retval = core_rx_lower_data(target, data_read); err_check_propagate(retval); retval = core_rx_upper_data(target, data_read + 2); err_check_propagate(retval); return retval; } static int dsp5680xx_read(struct target *t, uint32_t a, uint32_t size, uint32_t count, uint8_t *buf) { struct target *target = t; uint32_t address = a; uint8_t *buffer = buf; check_halt_and_debug(target); int retval = ERROR_OK; int pmem = 1; retval = dsp5680xx_convert_address(&address, &pmem); err_check_propagate(retval); dsp5680xx_context.flush = 0; int counter = FLUSH_COUNT_READ_WRITE; for (unsigned i = 0; i < count; i++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; } switch (size) { case 1: if (!(i % 2)) retval = dsp5680xx_read_16_single(target, address + i / 2, buffer + i, pmem); break; case 2: retval = dsp5680xx_read_16_single(target, address + i, buffer + 2 * i, pmem); break; case 4: retval = dsp5680xx_read_32_single(target, address + 2 * i, buffer + 4 * i, pmem); break; default: LOG_USER("%s: Invalid read size.", __func__); break; } err_check_propagate(retval); dsp5680xx_context.flush = 0; } dsp5680xx_context.flush = 1; retval = dsp5680xx_execute_queue(); err_check_propagate(retval); return retval; } static int dsp5680xx_write_16_single(struct target *t, uint32_t a, uint16_t data, uint8_t w_pmem) { struct target *target = t; uint32_t address = a; int retval = 0; retval = core_move_long_to_r0(target, address); err_check_propagate(retval); if (w_pmem) { retval = core_move_value_to_y0(target, data); err_check_propagate(retval); retval = core_move_y0_at_pr0_inc(target); err_check_propagate(retval); } else { retval = core_move_value_at_r0(target, data); err_check_propagate(retval); } return retval; } static int dsp5680xx_write_32_single(struct target *t, uint32_t a, uint32_t data, int w_pmem) { struct target *target = t; uint32_t address = a; int retval = ERROR_OK; retval = core_move_long_to_r0(target, address); err_check_propagate(retval); retval = core_move_long_to_y(target, data); err_check_propagate(retval); if (w_pmem) retval = core_move_y0_at_pr0_inc(target); else retval = core_move_y0_at_r0_inc(target); err_check_propagate(retval); if (w_pmem) retval = core_move_y1_at_pr0_inc(target); else retval = core_move_y1_at_r0_inc(target); err_check_propagate(retval); return retval; } static int dsp5680xx_write_8(struct target *t, uint32_t a, uint32_t c, const uint8_t *d, int pmem) { struct target *target = t; uint32_t address = a; uint32_t count = c; const uint8_t *data = d; int retval = 0; uint16_t data_16; uint32_t iter; int counter = FLUSH_COUNT_READ_WRITE; for (iter = 0; iter < count / 2; iter++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; } data_16 = (data[2 * iter] | (data[2 * iter + 1] << 8)); retval = dsp5680xx_write_16_single(target, address + iter, data_16, pmem); if (retval != ERROR_OK) { LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__, address); dsp5680xx_context.flush = 1; return retval; } dsp5680xx_context.flush = 0; } dsp5680xx_context.flush = 1; /* Only one byte left, let's not overwrite the other byte (mem is 16bit) */ /* Need to retrieve the part we do not want to overwrite. */ uint16_t data_old; if ((count == 1) || (count % 2)) { retval = dsp5680xx_read(target, address + iter, 1, 1, (uint8_t *) &data_old); err_check_propagate(retval); if (count == 1) data_old = (((data_old & 0xff) << 8) | data[0]); /* preserve upper byte */ else data_old = (((data_old & 0xff) << 8) | data[2 * iter + 1]); retval = dsp5680xx_write_16_single(target, address + iter, data_old, pmem); err_check_propagate(retval); } return retval; } static int dsp5680xx_write_16(struct target *t, uint32_t a, uint32_t c, const uint8_t *d, int pmem) { struct target *target = t; uint32_t address = a; uint32_t count = c; const uint8_t *data = d; int retval = ERROR_OK; uint32_t iter; int counter = FLUSH_COUNT_READ_WRITE; for (iter = 0; iter < count; iter++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; } retval = dsp5680xx_write_16_single(target, address + iter, data[iter], pmem); if (retval != ERROR_OK) { LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__, address); dsp5680xx_context.flush = 1; return retval; } dsp5680xx_context.flush = 0; } dsp5680xx_context.flush = 1; return retval; } static int dsp5680xx_write_32(struct target *t, uint32_t a, uint32_t c, const uint8_t *d, int pmem) { struct target *target = t; uint32_t address = a; uint32_t count = c; const uint8_t *data = d; int retval = ERROR_OK; uint32_t iter; int counter = FLUSH_COUNT_READ_WRITE; for (iter = 0; iter < count; iter++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; } retval = dsp5680xx_write_32_single(target, address + (iter << 1), data[iter], pmem); if (retval != ERROR_OK) { LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__, address); dsp5680xx_context.flush = 1; return retval; } dsp5680xx_context.flush = 0; } dsp5680xx_context.flush = 1; return retval; } /** * Writes @buffer to memory. * The parameter @address determines whether @buffer should be written to * P: (program) memory or X: (dat) memory. * * @param target * @param address * @param size Bytes (1), Half words (2), Words (4). * @param count In bytes. * @param buffer * * @return */ static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c, const uint8_t *b) { /* TODO Cannot write 32bit to odd address, will write 0x12345678 as 0x5678 0x0012 */ struct target *target = t; uint32_t address = a; uint32_t count = c; uint8_t const *buffer = b; uint32_t size = s; check_halt_and_debug(target); int retval = 0; int p_mem = 1; retval = dsp5680xx_convert_address(&address, &p_mem); err_check_propagate(retval); switch (size) { case 1: retval = dsp5680xx_write_8(target, address, count, buffer, p_mem); break; case 2: retval = dsp5680xx_write_16(target, address, count, buffer, p_mem); break; case 4: retval = dsp5680xx_write_32(target, address, count, buffer, p_mem); break; default: retval = ERROR_TARGET_DATA_ABORT; err_check(retval, DSP5680XX_ERROR_INVALID_DATA_SIZE_UNIT, "Invalid data size."); break; } return retval; } static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size, const uint8_t *b) { check_halt_and_debug(t); return dsp5680xx_write(t, a, 1, size, b); } /** * This function is called by verify_image, it is used to read data from memory. * * @param target * @param address Word addressing. * @param size In bytes. * @param buffer * * @return */ static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size, uint8_t *buf) { check_halt_and_debug(t); /* The "/2" solves the byte/word addressing issue.*/ return dsp5680xx_read(t, a, 2, size / 2, buf); } /** * This function is not implemented. * It returns an error in order to get OpenOCD to do read out the data * and calculate the CRC, or try a binary comparison. * * @param target * @param address Start address of the image. * @param size In bytes. * @param checksum * * @return */ static int dsp5680xx_checksum_memory(struct target *t, uint32_t a, uint32_t s, uint32_t *checksum) { return ERROR_FAIL; } /** * Calculates a signature over @word_count words in the data from @buff16. * The algorithm used is the same the FM uses, so the @return may be used to compare * with the one generated by the FM module, and check if flashing was successful. * This algorithm is based on the perl script available from the Freescale website at FAQ 25630. * * @param buff16 * @param word_count * * @return */ static int perl_crc(const uint8_t *buff8, uint32_t word_count) { uint16_t checksum = 0xffff; uint16_t data, fbmisr; uint32_t i; for (i = 0; i < word_count; i++) { data = (buff8[2 * i] | (buff8[2 * i + 1] << 8)); fbmisr = (checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16) >> 4 ^ (checksum & 0x8000) >> 15; checksum = (data ^ ((checksum << 1) | fbmisr)); } i--; for (; !(i & 0x80000000); i--) { data = (buff8[2 * i] | (buff8[2 * i + 1] << 8)); fbmisr = (checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16) >> 4 ^ (checksum & 0x8000) >> 15; checksum = (data ^ ((checksum << 1) | fbmisr)); } return checksum; } /** * Resets the SIM. (System Integration Modul). * * @param target * * @return */ int dsp5680xx_f_SIM_reset(struct target *target) { int retval = ERROR_OK; uint16_t sim_cmd = SIM_CMD_RESET; uint32_t sim_addr; if (strcmp(target->tap->chip, "dsp568013") == 0) { sim_addr = MC568013_SIM_BASE_ADDR + S_FILE_DATA_OFFSET; retval = dsp5680xx_write(target, sim_addr, 1, 2, (const uint8_t *)&sim_cmd); err_check_propagate(retval); } return retval; } /** * Halts the core and resets the SIM. (System Integration Modul). * * @param target * * @return */ static int dsp5680xx_soft_reset_halt(struct target *target) { /* TODO is this what this function is expected to do...? */ int retval; retval = dsp5680xx_halt(target); err_check_propagate(retval); retval = dsp5680xx_f_SIM_reset(target); err_check_propagate(retval); return retval; } int dsp5680xx_f_protect_check(struct target *target, uint16_t *protected) { int retval; check_halt_and_debug(target); if (protected == NULL) { const char *msg = "NULL pointer not valid."; err_check(ERROR_FAIL, DSP5680XX_ERROR_PROTECT_CHECK_INVALID_ARGS, msg); } retval = dsp5680xx_read_16_single(target, HFM_BASE_ADDR | HFM_PROT, (uint8_t *) protected, 0); err_check_propagate(retval); return retval; } /** * Executes a command on the FM module. * Some commands use the parameters @address and @data, others ignore them. * * @param target * @param command Command to execute. * @param address Command parameter. * @param data Command parameter. * @param hfm_ustat FM status register. * @param pmem Address is P: (program) memory (@pmem == 1) or X: (dat) memory (@pmem == 0) * * @return */ static int dsp5680xx_f_ex(struct target *t, uint16_t c, uint32_t a, uint32_t d, uint16_t *h, int p) { struct target *target = t; uint32_t command = c; uint32_t address = a; uint32_t data = d; uint16_t *hfm_ustat = h; int pmem = p; int retval; retval = core_load_TX_RX_high_addr_to_r0(target); err_check_propagate(retval); retval = core_move_long_to_r2(target, HFM_BASE_ADDR); err_check_propagate(retval); uint8_t i[2]; int watchdog = 100; do { retval = core_move_at_r2_disp_to_y0(target, HFM_USTAT); /* read HMF_USTAT */ err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); retval = core_rx_upper_data(target, i); err_check_propagate(retval); if ((watchdog--) == 1) { retval = ERROR_TARGET_FAILURE; const char *msg = "Timed out waiting for FM to finish old command."; err_check(retval, DSP5680XX_ERROR_FM_BUSY, msg); } } while (!(i[0] & 0x40)); /* wait until current command is complete */ dsp5680xx_context.flush = 0; /* write to HFM_CNFG (lock=0,select bank) - flash_desc.bank&0x03, 0x01 == 0x00, 0x01 ??? */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_CNFG); err_check_propagate(retval); /* write to HMF_USTAT, clear PVIOL, ACCERR &BLANK bits */ retval = core_move_value_at_r2_disp(target, 0x04, HFM_USTAT); err_check_propagate(retval); /* clear only one bit at a time */ retval = core_move_value_at_r2_disp(target, 0x10, HFM_USTAT); err_check_propagate(retval); retval = core_move_value_at_r2_disp(target, 0x20, HFM_USTAT); err_check_propagate(retval); /* write to HMF_PROT, clear protection */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROT); err_check_propagate(retval); /* write to HMF_PROTB, clear protection */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROTB); err_check_propagate(retval); retval = core_move_value_to_y0(target, data); err_check_propagate(retval); /* write to the flash block */ retval = core_move_long_to_r3(target, address); err_check_propagate(retval); if (pmem) { retval = core_move_y0_at_pr3_inc(target); err_check_propagate(retval); } else { retval = core_move_y0_at_r3(target); err_check_propagate(retval); } /* write command to the HFM_CMD reg */ retval = core_move_value_at_r2_disp(target, command, HFM_CMD); err_check_propagate(retval); /* start the command */ retval = core_move_value_at_r2_disp(target, 0x80, HFM_USTAT); err_check_propagate(retval); dsp5680xx_context.flush = 1; retval = dsp5680xx_execute_queue(); err_check_propagate(retval); watchdog = 100; do { /* read HMF_USTAT */ retval = core_move_at_r2_disp_to_y0(target, HFM_USTAT); err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); retval = core_rx_upper_data(target, i); err_check_propagate(retval); if ((watchdog--) == 1) { retval = ERROR_TARGET_FAILURE; err_check(retval, DSP5680XX_ERROR_FM_CMD_TIMED_OUT, "FM execution did not finish."); } } while (!(i[0] & 0x40)); /* wait until the command is complete */ *hfm_ustat = ((i[0] << 8) | (i[1])); if (i[0] & HFM_USTAT_MASK_PVIOL_ACCER) { retval = ERROR_TARGET_FAILURE; const char *msg = "pviol and/or accer bits set. HFM command execution error"; err_check(retval, DSP5680XX_ERROR_FM_EXEC, msg); } return ERROR_OK; } /** * Prior to the execution of any Flash module command, the Flash module Clock Divider (CLKDIV) register must be initialized. The values of this register determine the speed of the internal Flash Clock (FCLK). FCLK must be in the range of 150kHz ≤ FCLK ≤ 200kHz for proper operation of the Flash module. (Running FCLK too slowly wears out the module, while running it too fast under programs Flash leading to bit errors.) * * @param target * * @return */ static int set_fm_ck_div(struct target *target) { uint8_t i[2]; int retval; retval = core_move_long_to_r2(target, HFM_BASE_ADDR); err_check_propagate(retval); retval = core_load_TX_RX_high_addr_to_r0(target); err_check_propagate(retval); /* read HFM_CLKD */ retval = core_move_at_r2_to_y0(target); err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); retval = core_rx_upper_data(target, i); err_check_propagate(retval); unsigned int hfm_at_wrong_value = 0; if ((i[0] & 0x7f) != HFM_CLK_DEFAULT) { LOG_DEBUG("HFM CLK divisor contained incorrect value (0x%02X).", i[0] & 0x7f); hfm_at_wrong_value = 1; } else { LOG_DEBUG ("HFM CLK divisor was already set to correct value (0x%02X).", i[0] & 0x7f); return ERROR_OK; } /* write HFM_CLKD */ retval = core_move_value_at_r2(target, HFM_CLK_DEFAULT); err_check_propagate(retval); /* verify HFM_CLKD */ retval = core_move_at_r2_to_y0(target); err_check_propagate(retval); retval = core_move_y0_at_r0(target); err_check_propagate(retval); retval = core_rx_upper_data(target, i); err_check_propagate(retval); if (i[0] != (0x80 | (HFM_CLK_DEFAULT & 0x7f))) { retval = ERROR_TARGET_FAILURE; err_check(retval, DSP5680XX_ERROR_FM_SET_CLK, "Unable to set HFM CLK divisor."); } if (hfm_at_wrong_value) LOG_DEBUG("HFM CLK divisor set to 0x%02x.", i[0] & 0x7f); return ERROR_OK; } /** * Executes the FM calculate signature command. The FM will calculate over the data from @address to @address + @words -1. The result is written to a register, then read out by this function and returned in @signature. The value @signature may be compared to the the one returned by perl_crc to verify the flash was written correctly. * * @param target * @param address Start of flash array where the signature should be calculated. * @param words Number of words over which the signature should be calculated. * @param signature Value calculated by the FM. * * @return */ static int dsp5680xx_f_signature(struct target *t, uint32_t a, uint32_t words, uint16_t *signature) { struct target *target = t; uint32_t address = a; int retval; uint16_t hfm_ustat; if (!dsp5680xx_context.debug_mode_enabled) { retval = eonce_enter_debug_mode_without_reset(target, NULL); /* * Generate error here, since it is not done in eonce_enter_debug_mode_without_reset */ err_check(retval, DSP5680XX_ERROR_HALT, "Failed to halt target."); } retval = dsp5680xx_f_ex(target, HFM_CALCULATE_DATA_SIGNATURE, address, words, &hfm_ustat, 1); err_check_propagate(retval); retval = dsp5680xx_read_16_single(target, HFM_BASE_ADDR | HFM_DATA, (uint8_t *) signature, 0); return retval; } int dsp5680xx_f_erase_check(struct target *target, uint8_t *erased, uint32_t sector) { int retval; uint16_t hfm_ustat; uint32_t tmp; if (!dsp5680xx_context.debug_mode_enabled) { retval = dsp5680xx_halt(target); err_check_propagate(retval); } retval = set_fm_ck_div(target); err_check_propagate(retval); /* * Check if chip is already erased. */ tmp = HFM_FLASH_BASE_ADDR + sector * HFM_SECTOR_SIZE / 2; retval = dsp5680xx_f_ex(target, HFM_ERASE_VERIFY, tmp, 0, &hfm_ustat, 1); err_check_propagate(retval); if (erased != NULL) *erased = (uint8_t) (hfm_ustat & HFM_USTAT_MASK_BLANK); return retval; } /** * Executes the FM page erase command. * * @param target * @param sector Page to erase. * @param hfm_ustat FM module status register. * * @return */ static int erase_sector(struct target *target, int sector, uint16_t *hfm_ustat) { int retval; uint32_t tmp = HFM_FLASH_BASE_ADDR + sector * HFM_SECTOR_SIZE / 2; retval = dsp5680xx_f_ex(target, HFM_PAGE_ERASE, tmp, 0, hfm_ustat, 1); err_check_propagate(retval); return retval; } /** * Executes the FM mass erase command. Erases the flash array completely. * * @param target * @param hfm_ustat FM module status register. * * @return */ static int mass_erase(struct target *target, uint16_t *hfm_ustat) { int retval; retval = dsp5680xx_f_ex(target, HFM_MASS_ERASE, 0, 0, hfm_ustat, 1); return retval; } int dsp5680xx_f_erase(struct target *target, int first, int last) { int retval; if (!dsp5680xx_context.debug_mode_enabled) { retval = dsp5680xx_halt(target); err_check_propagate(retval); } /* * Reset SIM * */ retval = dsp5680xx_f_SIM_reset(target); err_check_propagate(retval); /* * Set hfmdiv * */ retval = set_fm_ck_div(target); err_check_propagate(retval); uint16_t hfm_ustat; int do_mass_erase = ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1)))); if (do_mass_erase) { /* Mass erase */ retval = mass_erase(target, &hfm_ustat); err_check_propagate(retval); } else { for (int i = first; i <= last; i++) { retval = erase_sector(target, i, &hfm_ustat); err_check_propagate(retval); } } return ERROR_OK; } /* * Algorithm for programming normal p: flash * Follow state machine from "56F801x Peripheral Reference Manual"@163. * Registers to set up before calling: * r0: TX/RX high address. * r2: FM module base address. * r3: Destination address in flash. * * hfm_wait: // wait for buffer empty * brclr #0x80, x:(r2+0x13), hfm_wait * rx_check: // wait for input buffer full * brclr #0x01, x:(r0-2), rx_check * move.w x:(r0), y0 // read from Rx buffer * move.w y0, p:(r3)+ * move.w #0x20, x:(r2+0x14) // write PGM command * move.w #0x80, x:(r2+0x13) // start the command * move.w X:(R2+0x13), A // Read USTAT register * brclr #0x20, A, accerr_check // protection violation check * bfset #0x20, X:(R2+0x13) // clear pviol * bra hfm_wait * accerr_check: * brclr #0x10, A, hfm_wait // access error check * bfset #0x10, X:(R2+0x13) // clear accerr * bra hfm_wait // loop * 0x00000000 0x8A460013807D brclr #0x80, X:(R2+0x13),*+0 * 0x00000003 0xE700 nop * 0x00000004 0xE700 nop * 0x00000005 0x8A44FFFE017B brclr #1, X:(R0-2),*-2 * 0x00000008 0xE700 nop * 0x00000009 0xF514 move.w X:(R0), Y0 * 0x0000000A 0x8563 move.w Y0, P:(R3)+ * 0x0000000B 0x864600200014 move.w #32, X:(R2+0x14) * 0x0000000E 0x864600800013 move.w #128, X:(R2+0x13) * 0x00000011 0xF0420013 move.w X:(R2+0x13), A * 0x00000013 0x8B402004 brclr #0x20, A,*+6 * 0x00000015 0x824600130020 bfset #0x20, X:(R2+0x13) * 0x00000018 0xA967 bra *-24 * 0x00000019 0x8B401065 brclr #0x10, A,*-25 * 0x0000001B 0x824600130010 bfset #0x10, X:(R2+0x13) * 0x0000001E 0xA961 bra *-30 */ const uint16_t pgm_write_pflash[] = { 0x8A46, 0x0013, 0x807D, 0xE700, 0xE700, 0x8A44, 0xFFFE, 0x017B, 0xE700, 0xF514, 0x8563, 0x8646, 0x0020, 0x0014, 0x8646, 0x0080, 0x0013, 0xF042, 0x0013, 0x8B40, 0x2004, 0x8246, 0x0013, 0x0020, 0xA967, 0x8B40, 0x1065, 0x8246, 0x0013, 0x0010, 0xA961 }; const uint32_t pgm_write_pflash_length = 31; int dsp5680xx_f_wr(struct target *t, const uint8_t *b, uint32_t a, uint32_t count, int is_flash_lock) { struct target *target = t; uint32_t address = a; const uint8_t *buffer = b; int retval = ERROR_OK; if (!dsp5680xx_context.debug_mode_enabled) { retval = eonce_enter_debug_mode(target, NULL); err_check_propagate(retval); } /* * Download the pgm that flashes. * */ const uint32_t len = pgm_write_pflash_length; uint32_t ram_addr = 0x8700; /* * This seems to be a safe address. * This one is the one used by codewarrior in 56801x_flash.cfg */ if (!is_flash_lock) { retval = dsp5680xx_write(target, ram_addr, 1, len * 2, (uint8_t *) pgm_write_pflash); err_check_propagate(retval); retval = dsp5680xx_execute_queue(); err_check_propagate(retval); } /* * Set hfmdiv * */ retval = set_fm_ck_div(target); err_check_propagate(retval); /* * Setup registers needed by pgm_write_pflash * */ dsp5680xx_context.flush = 0; retval = core_move_long_to_r3(target, address); /* Destination address to r3 */ err_check_propagate(retval); core_load_TX_RX_high_addr_to_r0(target); /* TX/RX reg address to r0 */ err_check_propagate(retval); retval = core_move_long_to_r2(target, HFM_BASE_ADDR); /* FM base address to r2 */ err_check_propagate(retval); /* * Run flashing program. * */ /* write to HFM_CNFG (lock=0, select bank) */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_CNFG); err_check_propagate(retval); /* write to HMF_USTAT, clear PVIOL, ACCERR &BLANK bits */ retval = core_move_value_at_r2_disp(target, 0x04, HFM_USTAT); err_check_propagate(retval); /* clear only one bit at a time */ retval = core_move_value_at_r2_disp(target, 0x10, HFM_USTAT); err_check_propagate(retval); retval = core_move_value_at_r2_disp(target, 0x20, HFM_USTAT); err_check_propagate(retval); /* write to HMF_PROT, clear protection */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROT); err_check_propagate(retval); /* write to HMF_PROTB, clear protection */ retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROTB); err_check_propagate(retval); if (count % 2) { /* TODO implement handling of odd number of words. */ retval = ERROR_FAIL; const char *msg = "Cannot handle odd number of words."; err_check(retval, DSP5680XX_ERROR_FLASHING_INVALID_WORD_COUNT, msg); } dsp5680xx_context.flush = 1; retval = dsp5680xx_execute_queue(); err_check_propagate(retval); uint32_t drscan_data; uint16_t tmp = (buffer[0] | (buffer[1] << 8)); retval = core_tx_upper_data(target, tmp, &drscan_data); err_check_propagate(retval); retval = dsp5680xx_resume(target, 0, ram_addr, 0, 0); err_check_propagate(retval); int counter = FLUSH_COUNT_FLASH; dsp5680xx_context.flush = 0; uint32_t i; for (i = 1; (i < count / 2) && (i < HFM_SIZE_WORDS); i++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_FLASH; } tmp = (buffer[2 * i] | (buffer[2 * i + 1] << 8)); retval = core_tx_upper_data(target, tmp, &drscan_data); if (retval != ERROR_OK) { dsp5680xx_context.flush = 1; err_check_propagate(retval); } dsp5680xx_context.flush = 0; } dsp5680xx_context.flush = 1; if (!is_flash_lock) { /* *Verify flash (skip when exec lock sequence) * */ uint16_t signature; uint16_t pc_crc; retval = dsp5680xx_f_signature(target, address, i, &signature); err_check_propagate(retval); pc_crc = perl_crc(buffer, i); if (pc_crc != signature) { retval = ERROR_FAIL; const char *msg = "Flashed data failed CRC check, flash again!"; err_check(retval, DSP5680XX_ERROR_FLASHING_CRC, msg); } } return retval; } int dsp5680xx_f_unlock(struct target *target) { int retval = ERROR_OK; uint16_t eonce_status; uint32_t instr; uint32_t ir_out; struct jtag_tap *tap_chp; struct jtag_tap *tap_cpu; tap_chp = jtag_tap_by_string("dsp568013.chp"); if (tap_chp == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER, "Failed to get master tap."); } tap_cpu = jtag_tap_by_string("dsp568013.cpu"); if (tap_cpu == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE, "Failed to get master tap."); } retval = eonce_enter_debug_mode_without_reset(target, &eonce_status); if (retval == ERROR_OK) LOG_WARNING("Memory was not locked."); jtag_add_reset(0, 1); jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000); retval = reset_jtag(); err_check(retval, DSP5680XX_ERROR_JTAG_RESET, "Failed to reset JTAG state machine"); jtag_add_sleep(150); /* Enable core tap */ tap_chp->enabled = true; retval = switch_tap(target, tap_chp, tap_cpu); err_check_propagate(retval); instr = JTAG_INSTR_DEBUG_REQUEST; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_CORE_TAP_IRLEN); err_check_propagate(retval); jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000); jtag_add_reset(0, 0); jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000); /* Enable master tap */ tap_chp->enabled = false; retval = switch_tap(target, tap_chp, tap_cpu); err_check_propagate(retval); /* Execute mass erase to unlock */ instr = MASTER_TAP_CMD_FLASH_ERASE; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_MASTER_TAP_IRLEN); err_check_propagate(retval); instr = HFM_CLK_DEFAULT; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 16); err_check_propagate(retval); jtag_add_sleep(TIME_DIV_FREESCALE * 150 * 1000); jtag_add_reset(0, 1); jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000); retval = reset_jtag(); err_check(retval, DSP5680XX_ERROR_JTAG_RESET, "Failed to reset JTAG state machine"); jtag_add_sleep(150); instr = 0x0606ffff; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 32); err_check_propagate(retval); /* enable core tap */ instr = 0x5; retval = dsp5680xx_irscan(target, &instr, &ir_out, DSP5680XX_JTAG_MASTER_TAP_IRLEN); err_check_propagate(retval); instr = 0x2; retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 4); err_check_propagate(retval); tap_cpu->enabled = true; tap_chp->enabled = false; target->state = TARGET_RUNNING; dsp5680xx_context.debug_mode_enabled = false; return retval; } int dsp5680xx_f_lock(struct target *target) { int retval; struct jtag_tap *tap_chp; struct jtag_tap *tap_cpu; uint16_t lock_word[] = { HFM_LOCK_FLASH }; retval = dsp5680xx_f_wr(target, (uint8_t *) (lock_word), HFM_LOCK_ADDR_L, 2, 1); err_check_propagate(retval); jtag_add_reset(0, 1); jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000); retval = reset_jtag(); err_check(retval, DSP5680XX_ERROR_JTAG_RESET, "Failed to reset JTAG state machine"); jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000); jtag_add_reset(0, 0); jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000); tap_chp = jtag_tap_by_string("dsp568013.chp"); if (tap_chp == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER, "Failed to get master tap."); } tap_cpu = jtag_tap_by_string("dsp568013.cpu"); if (tap_cpu == NULL) { retval = ERROR_FAIL; err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE, "Failed to get master tap."); } target->state = TARGET_RUNNING; dsp5680xx_context.debug_mode_enabled = false; tap_cpu->enabled = false; tap_chp->enabled = true; retval = switch_tap(target, tap_chp, tap_cpu); return retval; } static int dsp5680xx_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP, "Not implemented yet."); } /** Holds methods for dsp5680xx targets. */ struct target_type dsp5680xx_target = { .name = "dsp5680xx", .poll = dsp5680xx_poll, .arch_state = dsp5680xx_arch_state, .halt = dsp5680xx_halt, .resume = dsp5680xx_resume, .step = dsp5680xx_step, .write_buffer = dsp5680xx_write_buffer, .read_buffer = dsp5680xx_read_buffer, .assert_reset = dsp5680xx_assert_reset, .deassert_reset = dsp5680xx_deassert_reset, .soft_reset_halt = dsp5680xx_soft_reset_halt, .read_memory = dsp5680xx_read, .write_memory = dsp5680xx_write, .checksum_memory = dsp5680xx_checksum_memory, .target_create = dsp5680xx_target_create, .init_target = dsp5680xx_init_target, }; openocd-0.9.0/src/target/dsp5680xx.h0000644000175000017500000003525712315575361014033 00000000000000/*************************************************************************** * Copyright (C) 2011 by Rodrigo L. Rosa * * rodrigorosa.LG@gmail.com * * * * Based on dsp563xx_once.h written by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef DSP5680XX_H #define DSP5680XX_H #include /** * @file dsp5680xx.h * @author Rodrigo Rosa * @date Thu Jun 9 18:54:38 2011 * * @brief Basic support for the 5680xx DSP from Freescale. * The chip has two taps in the JTAG chain, the Master tap and the Core tap. * In this code the Master tap is only used to unlock the flash memory by executing a JTAG instruction. * */ #define S_FILE_DATA_OFFSET 0x200000 #define TIME_DIV_FREESCALE 0.3 /** ---------------------------------------------------------------- * JTAG *---------------------------------------------------------------- */ #define DSP5680XX_JTAG_CORE_TAP_IRLEN 4 #define DSP5680XX_JTAG_MASTER_TAP_IRLEN 8 #define JTAG_STATUS_MASK 0x0F #define JTAG_STATUS_NORMAL 0x01 #define JTAG_STATUS_STOPWAIT 0x05 #define JTAG_STATUS_BUSY 0x09 #define JTAG_STATUS_DEBUG 0x0D #define JTAG_STATUS_DEAD 0x0f #define JTAG_INSTR_EXTEST 0x0 #define JTAG_INSTR_SAMPLE_PRELOAD 0x1 #define JTAG_INSTR_IDCODE 0x2 #define JTAG_INSTR_EXTEST_PULLUP 0x3 #define JTAG_INSTR_HIGHZ 0x4 #define JTAG_INSTR_CLAMP 0x5 #define JTAG_INSTR_ENABLE_ONCE 0x6 #define JTAG_INSTR_DEBUG_REQUEST 0x7 #define JTAG_INSTR_BYPASS 0xF /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * Master TAP instructions from MC56F8000RM.pdf * ---------------------------------------------------------------- */ #define MASTER_TAP_CMD_BYPASS 0xF #define MASTER_TAP_CMD_IDCODE 0x2 #define MASTER_TAP_CMD_TLM_SEL 0x5 #define MASTER_TAP_CMD_FLASH_ERASE 0x8 /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * EOnCE control register info * ---------------------------------------------------------------- */ #define DSP5680XX_ONCE_OCR_EX (1<<5) /* EX Bit Definition 0 Remain in the Debug Processing State 1 Leave the Debug Processing State */ #define DSP5680XX_ONCE_OCR_GO (1<<6) /* GO Bit Definition 0 Inactive—No Action Taken 1 Execute Controller Instruction */ #define DSP5680XX_ONCE_OCR_RW (1<<7) /** RW Bit Definition * 0 Write To the Register Specified by the RS[4:0] Bits * 1 ReadFrom the Register Specified by the RS[4:0] Bits * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * EOnCE Status Register * ---------------------------------------------------------------- */ #define DSP5680XX_ONCE_OSCR_OS1 (1<<5) #define DSP5680XX_ONCE_OSCR_OS0 (1<<4) /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * EOnCE Core Status - Describes the operating status of the core controller * ---------------------------------------------------------------- */ #define DSP5680XX_ONCE_OSCR_NORMAL_M (0) /* 00 - Normal - Controller Core Executing Instructions or in Reset */ #define DSP5680XX_ONCE_OSCR_STOPWAIT_M (DSP5680XX_ONCE_OSCR_OS0) /* 01 - Stop/Wait - Controller Core in Stop or Wait Mode */ #define DSP5680XX_ONCE_OSCR_BUSY_M (DSP5680XX_ONCE_OSCR_OS1) /* 10 - Busy - Controller is Performing External or Peripheral Access (Wait States) */ #define DSP5680XX_ONCE_OSCR_DEBUG_M (DSP5680XX_ONCE_OSCR_OS0|DSP5680XX_ONCE_OSCR_OS1) /* 11 - Debug - Controller Core Halted and in Debug Mode */ #define EONCE_STAT_MASK 0x30 /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * Register Select Encoding (eonce_rev.1.0_0208081.pdf:14) * ---------------------------------------------------------------- */ #define DSP5680XX_ONCE_NOREG 0x00 /* No register selected */ #define DSP5680XX_ONCE_OCR 0x01 /* OnCE Debug Control Register */ #define DSP5680XX_ONCE_OCNTR 0x02 /* OnCE Breakpoint and Trace Counter */ #define DSP5680XX_ONCE_OSR 0x03 /* EOnCE status register */ #define DSP5680XX_ONCE_OBAR 0x04 /* OnCE Breakpoint Address Register */ #define DSP5680XX_ONCE_OBASE 0x05 /* EOnCE Peripheral Base Address register */ #define DSP5680XX_ONCE_OTXRXSR 0x06 /* EOnCE TXRX Status and Control Register (OTXRXSR) */ #define DSP5680XX_ONCE_OTX 0x07 /* EOnCE Transmit register (OTX) */ #define DSP5680XX_ONCE_OPDBR 0x08 /* EOnCE Program Data Bus Register (OPDBR) */ #define DSP5680XX_ONCE_OTX1 0x09 /* EOnCE Upper Transmit register (OTX1) */ #define DSP5680XX_ONCE_OPABFR 0x0A /* OnCE Program Address Register—Fetch cycle */ #define DSP5680XX_ONCE_ORX 0x0B /* EOnCE Receive register (ORX) */ #define DSP5680XX_ONCE_OCNTR_C 0x0C /* Clear OCNTR */ #define DSP5680XX_ONCE_ORX1 0x0D /* EOnCE Upper Receive register (ORX1) */ #define DSP5680XX_ONCE_OTBCR 0x0E /* EOnCE Trace Buffer Control Reg (OTBCR) */ #define DSP5680XX_ONCE_OPABER 0x10 /* OnCE Program Address Register—Execute cycle */ #define DSP5680XX_ONCE_OPFIFO 0x11 /* OnCE Program address FIFO */ #define DSP5680XX_ONCE_OBAR1 0x12 /* EOnCE Breakpoint 1 Unit 0 Address Reg.(OBAR1) */ #define DSP5680XX_ONCE_OPABDR 0x13 /* OnCE Program Address Register—Decode cycle (OPABDR) */ /** * ---------------------------------------------------------------- */ #define FLUSH_COUNT_READ_WRITE 8192 /* This value works, higher values (and lower...) may work as well. */ #define FLUSH_COUNT_FLASH 8192 /** ---------------------------------------------------------------- * HFM (flash module) Commands (ref:MC56F801xRM.pdf:159) * ---------------------------------------------------------------- */ #define HFM_ERASE_VERIFY 0x05 #define HFM_CALCULATE_DATA_SIGNATURE 0x06 #define HFM_WORD_PROGRAM 0x20 #define HFM_PAGE_ERASE 0x40 #define HFM_MASS_ERASE 0x41 #define HFM_CALCULATE_IFR_BLOCK_SIGNATURE 0x66 /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * Flashing (ref:MC56F801xRM.pdf:159) * ---------------------------------------------------------------- */ #define HFM_BASE_ADDR 0x0F400 /** In x: mem. (write to S_FILE_DATA_OFFSET+HFM_BASE_ADDR * to get data into x: mem.) */ /** * The following are register addresses, not memory * addresses (though all registers are memory mapped) */ #define HFM_CLK_DIV 0x00 /* r/w */ #define HFM_CNFG 0x01 /* r/w */ #define HFM_SECHI 0x03 /* r */ #define HFM_SECLO 0x04 /* r */ #define HFM_PROT 0x10 /* r/w */ #define HFM_PROTB 0x11 /* r/w */ #define HFM_USTAT 0x13 /* r/w */ #define HFM_CMD 0x14 /* r/w */ #define HFM_DATA 0x18 /* r */ #define HFM_OPT1 0x1B /* r */ #define HFM_TSTSIG 0x1D /* r */ #define HFM_EXEC_COMPLETE 0x40 /* User status register (USTAT) masks (MC56F80XXRM.pdf:6.7.5) */ #define HFM_USTAT_MASK_BLANK 0x4 #define HFM_USTAT_MASK_PVIOL_ACCER 0x30 /** * The value used on for the FM clock is important to prevent flashing errors and to prevent deterioration of the FM. * This value was calculated using a spreadsheet tool available on the Freescale website under FAQ 25464. * */ #define HFM_CLK_DEFAULT 0x27 /* 0x27 according to freescale cfg, but 0x40 according to freescale spreadsheet... */ #define HFM_FLASH_BASE_ADDR 0x0 #define HFM_SIZE_BYTES 0x4000 /* bytes */ #define HFM_SIZE_WORDS 0x2000 /* words */ #define HFM_SECTOR_SIZE 0x200 /* Size in bytes */ #define HFM_SECTOR_COUNT 0x20 /* A 16K block in pages of 256 words. */ /** * Writing HFM_LOCK_FLASH to HFM_LOCK_ADDR_L and HFM_LOCK_ADDR_H will enable security on flash after the next reset. */ #define HFM_LOCK_FLASH 0xE70A #define HFM_LOCK_ADDR_L 0x1FF7 #define HFM_LOCK_ADDR_H 0x1FF8 /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * Register Memory Map (eonce_rev.1.0_0208081.pdf:16) * ---------------------------------------------------------------- */ #define MC568013_EONCE_OBASE_ADDR 0xFF /* The following are relative to EONCE_OBASE_ADDR (EONCE_OBASE_ADDR<<16 + ...) */ #define MC568013_EONCE_TX_RX_ADDR 0xFFFE #define MC568013_EONCE_TX1_RX1_HIGH_ADDR 0xFFFF /* Relative to EONCE_OBASE_ADDR */ #define MC568013_EONCE_OCR 0xFFA0 /* Relative to EONCE_OBASE_ADDR */ /** * ---------------------------------------------------------------- */ /** ---------------------------------------------------------------- * SIM addresses & commands (MC56F80xx.h from freescale) * ---------------------------------------------------------------- */ #define MC568013_SIM_BASE_ADDR 0xF140 #define MC56803x_2x_SIM_BASE_ADDR 0xF100 #define SIM_CMD_RESET 0x10 /** * ---------------------------------------------------------------- */ /** * ---------------------------------------------------------------- * ERROR codes - enable automatic parsing of output * ---------------------------------------------------------------- */ #define DSP5680XX_ERROR_UNKNOWN_OR_ERROR_OPENOCD -100 #define DSP5680XX_ERROR_JTAG_COMM -1 #define DSP5680XX_ERROR_JTAG_RESET -2 #define DSP5680XX_ERROR_JTAG_INVALID_TAP -3 #define DSP5680XX_ERROR_JTAG_DR_LEN_OVERFLOW -4 #define DSP5680XX_ERROR_INVALID_IR_LEN -5 #define DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER -6 #define DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE -7 #define DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER -8 #define DSP5680XX_ERROR_JTAG_TAP_FIND_CORE -9 #define DSP5680XX_ERROR_JTAG_DRSCAN -10 #define DSP5680XX_ERROR_JTAG_IRSCAN -11 #define DSP5680XX_ERROR_ENTER_DEBUG_MODE -12 #define DSP5680XX_ERROR_RESUME -13 #define DSP5680XX_ERROR_WRITE_WITH_TARGET_RUNNING -14 #define DSP5680XX_ERROR_INVALID_DATA_SIZE_UNIT -15 #define DSP5680XX_ERROR_PROTECT_CHECK_INVALID_ARGS -16 #define DSP5680XX_ERROR_FM_BUSY -17 #define DSP5680XX_ERROR_FM_CMD_TIMED_OUT -18 #define DSP5680XX_ERROR_FM_EXEC -19 #define DSP5680XX_ERROR_FM_SET_CLK -20 #define DSP5680XX_ERROR_FLASHING_INVALID_WORD_COUNT -21 #define DSP5680XX_ERROR_FLASHING_CRC -22 #define DSP5680XX_ERROR_FLASHING -23 #define DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP -24 #define DSP5680XX_ERROR_HALT -25 #define DSP5680XX_ERROR_EXIT_DEBUG_MODE -26 #define DSP5680XX_ERROR_TARGET_RUNNING -27 #define DSP5680XX_ERROR_NOT_IN_DEBUG -28 /** * ---------------------------------------------------------------- */ struct dsp5680xx_common { uint32_t stored_pc; int flush; bool debug_mode_enabled; }; extern struct dsp5680xx_common dsp5680xx_context; static inline struct dsp5680xx_common *target_to_dsp5680xx(struct target *target) { return target->arch_info; } /** * Writes to flash memory. * Does not check if flash is erased, it's up to the user to erase the flash before running * this function. * The flashing algorithm runs from RAM, reading from a register to which this function * writes to. The algorithm is open loop, there is no control to verify that the FM read * the register before writing the next data. A closed loop approach was much slower, * and the current implementation does not fail, and if it did the crc check would detect it, * allowing to flash again. * * @param target * @param buffer * @param address Word addressing. * @param count In bytes. * @param is_flash_lock * * @return */ int dsp5680xx_f_wr(struct target *target, const uint8_t * buffer, uint32_t address, uint32_t count, int is_flash_lock); /** * The FM has the functionality of checking if the flash array is erased. This function * executes it. It does not support individual sector analysis. * * @param target * @param erased * @param sector This parameter is ignored because the FM does not support checking if * individual sectors are erased. * * @return */ int dsp5680xx_f_erase_check(struct target *target, uint8_t * erased, uint32_t sector); /** * Erases either a sector or the complete flash array. If either the range first-last covers * the complete array or if first == 0 and last == 0 then a mass erase command is executed * on the FM. If not, then individual sectors are erased. * * @param target * @param first * @param last * * @return */ int dsp5680xx_f_erase(struct target *target, int first, int last); /** * Reads the memory mapped protection register. A 1 implies the sector is protected, * a 0 implies the sector is not protected. * * @param target * @param protected Data read from the protection register. * * @return */ int dsp5680xx_f_protect_check(struct target *target, uint16_t * protected); /** * Writes the flash security words with a specific value. The chip's security will be * enabled after the first reset following the execution of this function. * * @param target * * @return */ int dsp5680xx_f_lock(struct target *target); /** * Executes a mass erase command. The must be done from the Master tap. * It is up to the user to select the master tap (jtag tapenable dsp5680xx.chp) * before running this function. * The flash array will be unsecured (and erased) after the first reset following * the execution of this function. * * @param target * * @return */ int dsp5680xx_f_unlock(struct target *target); #endif /* DSP5680XX_H */ openocd-0.9.0/src/target/nds32_insn.h0000644000175000017500000001060512315575361014310 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_INSN_H__ #define __NDS32_INSN_H__ #define NOP (0x40000009) #define DSB (0x64000008) #define ISB (0x64000009) #define BEQ_MINUS_12 (0x4C000000 | 0x3FFA) #define MTSR_DTR(a) (0x64000003 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20)) #define MFSR_DTR(a) (0x64000002 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20)) #define SETHI(a, b) (0x46000000 | ((a) << 20) | (b)) #define ORI(a, b, c) (0x58000000 | ((a) << 20) | ((b) << 15) | (c)) #define LWI_BI(a, b) (0x0C000001 | (a << 20) | (b << 15)) #define LHI_BI(a, b) (0x0A000001 | (a << 20) | (b << 15)) #define LBI_BI(a, b) (0x08000001 | (a << 20) | (b << 15)) #define SWI_BI(a, b) (0x1C000001 | (a << 20) | (b << 15)) #define SHI_BI(a, b) (0x1A000001 | (a << 20) | (b << 15)) #define SBI_BI(a, b) (0x18000001 | (a << 20) | (b << 15)) #define IRET (0x64000004) #define L1D_IX_WB(a) (0x64000021 | ((a) << 15)) #define L1D_IX_INVAL(a) (0x64000001 | ((a) << 15)) #define L1D_VA_INVAL(a) (0x64000101 | ((a) << 15)) #define L1D_VA_WB(a) (0x64000121 | ((a) << 15)) #define L1D_IX_RTAG(a) (0x64000061 | ((a) << 15)) #define L1D_IX_RWD(a) (0x64000081 | ((a) << 15)) #define L1I_IX_INVAL(a) (0x64000201 | ((a) << 15)) #define L1I_VA_INVAL(a) (0x64000301 | ((a) << 15)) #define L1I_IX_RTAG(a) (0x64000261 | ((a) << 15)) #define L1I_IX_RWD(a) (0x64000281 | ((a) << 15)) #define L1I_VA_FILLCK(a) (0x64000361 | ((a) << 15)) #define ISYNC(a) (0x6400000d | ((a) << 20)) #define MSYNC_STORE (0x6400002c) #define MSYNC_ALL (0x6400000c) #define TLBOP_TARGET_READ(a) (0x6400000e | ((a) << 15)) #define TLBOP_TARGET_PROBE(a, b) (0x640000AE | ((a) << 20) | ((b) << 15)) #define MFCPD(a, b, c) (0x6A000041 | (a << 20) | (b << 8) | (c << 4)) #define MFCPW(a, b, c) (0x6A000001 | (a << 20) | (b << 8) | (c << 4)) #define MTCPD(a, b, c) (0x6A000049 | (a << 20) | (b << 8) | (c << 4)) #define MTCPW(a, b, c) (0x6A000009 | (a << 20) | (b << 8) | (c << 4)) #define MOVI_(a, b) (0x44000000 | (a << 20) | (b & 0xFFFFF)) #define MFUSR_G0(a, b) (0x42000020 | (a << 20) | (b << 15)) #define MTUSR_G0(a, b) (0x42000021 | (a << 20) | (b << 15)) #define MFSR(a, b) (0x64000002 | (b << 10) | (a << 20)) #define MTSR(a, b) (0x64000003 | (b << 10) | (a << 20)) #define AMFAR(a, b) (0x60300060 | (a << 15) | b) #define AMTAR(a, b) (0x60300040 | (a << 15) | b) #define AMFAR2(a, b) (0x60300260 | (a << 15) | b) #define AMTAR2(a, b) (0x60300240 | (a << 15) | b) #define FMFCSR (0x6A000701) #define FMTCSR (0x6A000709) #define FMFCFG (0x6A000301) #define FMFSR(a, b) (0x6A000001 | ((a) << 20) | ((b) << 15)) #define FMTSR(a, b) (0x6A000009 | ((a) << 20) | ((b) << 15)) #define FMFDR(a, b) (0x6A000041 | ((a) << 20) | ((b) << 15)) #define FMTDR(a, b) (0x6A000049 | ((a) << 20) | ((b) << 15)) /* break instructions */ extern const int NDS32_BREAK_16; extern const int NDS32_BREAK_32; #endif /* __NDS32_INSN_H__ */ openocd-0.9.0/src/target/etm_dummy.c0000644000175000017500000000640512315575361014326 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "etm_dummy.h" COMMAND_HANDLER(handle_etm_dummy_config_command) { struct target *target; struct arm *arm; target = get_target(CMD_ARGV[0]); if (!target) { LOG_ERROR("target '%s' not defined", CMD_ARGV[0]); return ERROR_FAIL; } arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "target '%s' isn't an ARM", CMD_ARGV[0]); return ERROR_FAIL; } if (arm->etm) arm->etm->capture_driver_priv = NULL; else { LOG_ERROR("target has no ETM defined, ETM dummy left unconfigured"); return ERROR_FAIL; } return ERROR_OK; } static const struct command_registration etm_dummy_config_command_handlers[] = { { .name = "config", .handler = handle_etm_dummy_config_command, .mode = COMMAND_CONFIG, .usage = "target", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration etm_dummy_command_handlers[] = { { .name = "etm_dummy", .mode = COMMAND_ANY, .help = "Dummy ETM capture driver command group", .chain = etm_dummy_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; static int etm_dummy_init(struct etm_context *etm_ctx) { return ERROR_OK; } static trace_status_t etm_dummy_status(struct etm_context *etm_ctx) { return TRACE_IDLE; } static int etm_dummy_read_trace(struct etm_context *etm_ctx) { return ERROR_OK; } static int etm_dummy_start_capture(struct etm_context *etm_ctx) { return ERROR_ETM_PORTMODE_NOT_SUPPORTED; } static int etm_dummy_stop_capture(struct etm_context *etm_ctx) { return ERROR_OK; } struct etm_capture_driver etm_dummy_capture_driver = { .name = "dummy", .commands = etm_dummy_command_handlers, .init = etm_dummy_init, .status = etm_dummy_status, .start_capture = etm_dummy_start_capture, .stop_capture = etm_dummy_stop_capture, .read_trace = etm_dummy_read_trace, }; openocd-0.9.0/src/target/etm_dummy.h0000644000175000017500000000310312315575361014323 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ETM_DUMMY_H #define ETM_DUMMY_H #include "etm.h" extern struct etm_capture_driver etm_dummy_capture_driver; #endif /* ETB_H */ openocd-0.9.0/src/target/nds32_cmd.c0000644000175000017500000007167512315575361014115 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "nds32.h" #include "nds32_aice.h" #include "nds32_disassembler.h" extern struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM]; extern uint32_t nds32_edm_ops_num; static const char *const NDS_MEMORY_ACCESS_NAME[] = { "BUS", "CPU", }; static const char *const NDS_MEMORY_SELECT_NAME[] = { "AUTO", "MEM", "ILM", "DLM", }; COMMAND_HANDLER(handle_nds32_dssim_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->step_isr_enable = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->step_isr_enable = false; } command_print(CMD_CTX, "%s: $INT_MASK.DSSIM: %d", target_name(target), nds32->step_isr_enable); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_memory_access_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_memory *memory = &(nds32->memory); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "bus") == 0) memory->access_channel = NDS_MEMORY_ACC_BUS; else if (strcmp(CMD_ARGV[0], "cpu") == 0) memory->access_channel = NDS_MEMORY_ACC_CPU; else /* default access channel is NDS_MEMORY_ACC_CPU */ memory->access_channel = NDS_MEMORY_ACC_CPU; LOG_DEBUG("memory access channel is changed to %s", NDS_MEMORY_ACCESS_NAME[memory->access_channel]); aice_memory_access(aice, memory->access_channel); } else { command_print(CMD_CTX, "%s: memory access channel: %s", target_name(target), NDS_MEMORY_ACCESS_NAME[memory->access_channel]); } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_memory_mode_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (nds32->edm.access_control == false) { command_print(CMD_CTX, "%s does not support ACC_CTL. " "Set memory mode to MEMORY", target_name(target)); nds32->memory.mode = NDS_MEMORY_SELECT_MEM; } else if (nds32->edm.direct_access_local_memory == false) { command_print(CMD_CTX, "%s does not support direct access " "local memory. Set memory mode to MEMORY", target_name(target)); nds32->memory.mode = NDS_MEMORY_SELECT_MEM; /* set to ACC_CTL */ aice_memory_mode(aice, nds32->memory.mode); } else { if (strcmp(CMD_ARGV[0], "auto") == 0) { nds32->memory.mode = NDS_MEMORY_SELECT_AUTO; } else if (strcmp(CMD_ARGV[0], "mem") == 0) { nds32->memory.mode = NDS_MEMORY_SELECT_MEM; } else if (strcmp(CMD_ARGV[0], "ilm") == 0) { if (nds32->memory.ilm_base == 0) command_print(CMD_CTX, "%s does not support ILM", target_name(target)); else nds32->memory.mode = NDS_MEMORY_SELECT_ILM; } else if (strcmp(CMD_ARGV[0], "dlm") == 0) { if (nds32->memory.dlm_base == 0) command_print(CMD_CTX, "%s does not support DLM", target_name(target)); else nds32->memory.mode = NDS_MEMORY_SELECT_DLM; } /* set to ACC_CTL */ aice_memory_mode(aice, nds32->memory.mode); } } command_print(CMD_CTX, "%s: memory mode: %s", target_name(target), NDS_MEMORY_SELECT_NAME[nds32->memory.mode]); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_cache_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_cache *icache = &(nds32->memory.icache); struct nds32_cache *dcache = &(nds32->memory.dcache); int result; if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "invalidate") == 0) { if ((dcache->line_size != 0) && (dcache->enable == true)) { /* D$ write back */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Write back data cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Write back data cache...done", target_name(target)); /* D$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Invalidate data cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Invalidate data cache...done", target_name(target)); } else { if (dcache->line_size == 0) command_print(CMD_CTX, "%s: No data cache", target_name(target)); else command_print(CMD_CTX, "%s: Data cache disabled", target_name(target)); } if ((icache->line_size != 0) && (icache->enable == true)) { /* I$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Invalidate instruction cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Invalidate instruction cache...done", target_name(target)); } else { if (icache->line_size == 0) command_print(CMD_CTX, "%s: No instruction cache", target_name(target)); else command_print(CMD_CTX, "%s: Instruction cache disabled", target_name(target)); } } else command_print(CMD_CTX, "No valid parameter"); } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_icache_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_cache *icache = &(nds32->memory.icache); int result; if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (icache->line_size == 0) { command_print(CMD_CTX, "%s: No instruction cache", target_name(target)); return ERROR_OK; } if (strcmp(CMD_ARGV[0], "invalidate") == 0) { if (icache->enable == true) { /* I$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Invalidate instruction cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Invalidate instruction cache...done", target_name(target)); } else { command_print(CMD_CTX, "%s: Instruction cache disabled", target_name(target)); } } else if (strcmp(CMD_ARGV[0], "enable") == 0) { uint32_t value; nds32_get_mapped_reg(nds32, IR8, &value); nds32_set_mapped_reg(nds32, IR8, value | 0x1); } else if (strcmp(CMD_ARGV[0], "disable") == 0) { uint32_t value; nds32_get_mapped_reg(nds32, IR8, &value); nds32_set_mapped_reg(nds32, IR8, value & ~0x1); } else if (strcmp(CMD_ARGV[0], "dump") == 0) { /* TODO: dump cache content */ } else { command_print(CMD_CTX, "%s: No valid parameter", target_name(target)); } } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_dcache_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_cache *dcache = &(nds32->memory.dcache); int result; if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (dcache->line_size == 0) { command_print(CMD_CTX, "%s: No data cache", target_name(target)); return ERROR_OK; } if (strcmp(CMD_ARGV[0], "invalidate") == 0) { if (dcache->enable == true) { /* D$ write back */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Write back data cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Write back data cache...done", target_name(target)); /* D$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0); if (result != ERROR_OK) { command_print(CMD_CTX, "%s: Invalidate data cache...failed", target_name(target)); return result; } command_print(CMD_CTX, "%s: Invalidate data cache...done", target_name(target)); } else { command_print(CMD_CTX, "%s: Data cache disabled", target_name(target)); } } else if (strcmp(CMD_ARGV[0], "enable") == 0) { uint32_t value; nds32_get_mapped_reg(nds32, IR8, &value); nds32_set_mapped_reg(nds32, IR8, value | 0x2); } else if (strcmp(CMD_ARGV[0], "disable") == 0) { uint32_t value; nds32_get_mapped_reg(nds32, IR8, &value); nds32_set_mapped_reg(nds32, IR8, value & ~0x2); } else if (strcmp(CMD_ARGV[0], "dump") == 0) { /* TODO: dump cache content */ } else { command_print(CMD_CTX, "%s: No valid parameter", target_name(target)); } } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_auto_break_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->auto_convert_hw_bp = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->auto_convert_hw_bp = false; } if (nds32->auto_convert_hw_bp) command_print(CMD_CTX, "%s: convert sw break to hw break on ROM: on", target_name(target)); else command_print(CMD_CTX, "%s: convert sw break to hw break on ROM: off", target_name(target)); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_virtual_hosting_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->virtual_hosting = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->virtual_hosting = false; } if (nds32->virtual_hosting) command_print(CMD_CTX, "%s: virtual hosting: on", target_name(target)); else command_print(CMD_CTX, "%s: virtual hosting: off", target_name(target)); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_global_stop_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->global_stop = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->global_stop = false; } if (nds32->global_stop) LOG_INFO("%s: global stop: on", target_name(target)); else LOG_INFO("%s: global stop: off", target_name(target)); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_soft_reset_halt_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->soft_reset_halt = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->soft_reset_halt = false; } if (nds32->soft_reset_halt) LOG_INFO("%s: soft-reset-halt: on", target_name(target)); else LOG_INFO("%s: soft-reset-halt: off", target_name(target)); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_boot_time_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], nds32->boot_time); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_login_edm_passcode_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } nds32->edm_passcode = strdup(CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_login_edm_operation_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 1) { uint32_t misc_reg_no; uint32_t data; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], misc_reg_no); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], data); if (nds32_edm_ops_num >= NDS32_EDM_OPERATION_MAX_NUM) return ERROR_FAIL; /* Just save the operation. Execute it in nds32_login() */ nds32_edm_ops[nds32_edm_ops_num].reg_no = misc_reg_no; nds32_edm_ops[nds32_edm_ops_num].value = data; nds32_edm_ops_num++; } else return ERROR_FAIL; return ERROR_OK; } COMMAND_HANDLER(handle_nds32_reset_halt_as_init_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->reset_halt_as_examine = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->reset_halt_as_examine = false; } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_keep_target_edm_ctl_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->keep_target_edm_ctl = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->keep_target_edm_ctl = false; } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_decode_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 1) { uint32_t addr; uint32_t insn_count; uint32_t opcode; uint32_t read_addr; uint32_t i; struct nds32_instruction instruction; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], insn_count); read_addr = addr; i = 0; while (i < insn_count) { if (ERROR_OK != nds32_read_opcode(nds32, read_addr, &opcode)) return ERROR_FAIL; if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, read_addr, &instruction)) return ERROR_FAIL; command_print(CMD_CTX, "%s", instruction.text); read_addr += instruction.instruction_size; i++; } } else if (CMD_ARGC == 1) { uint32_t addr; uint32_t opcode; struct nds32_instruction instruction; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); if (ERROR_OK != nds32_read_opcode(nds32, addr, &opcode)) return ERROR_FAIL; if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, addr, &instruction)) return ERROR_FAIL; command_print(CMD_CTX, "%s", instruction.text); } else return ERROR_FAIL; return ERROR_OK; } COMMAND_HANDLER(handle_nds32_word_access_mem_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "on") == 0) nds32->word_access_mem = true; if (strcmp(CMD_ARGV[0], "off") == 0) nds32->word_access_mem = false; } return ERROR_OK; } COMMAND_HANDLER(handle_nds32_query_target_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } command_print(CMD_CTX, "OCD"); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_query_endian_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } uint32_t value_psw; nds32_get_mapped_reg(nds32, IR0, &value_psw); if (value_psw & 0x20) command_print(CMD_CTX, "%s: BE", target_name(target)); else command_print(CMD_CTX, "%s: LE", target_name(target)); return ERROR_OK; } COMMAND_HANDLER(handle_nds32_query_cpuid_command) { struct target *target = get_current_target(CMD_CTX); struct nds32 *nds32 = target_to_nds32(target); if (!is_nds32(nds32)) { command_print(CMD_CTX, "current target isn't an Andes core"); return ERROR_FAIL; } command_print(CMD_CTX, "CPUID: %s", target_name(target)); return ERROR_OK; } static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 3) { Jim_SetResultFormatted(goi.interp, "usage: %s

", cmd_name); return JIM_ERR; } int e; jim_wide address; e = Jim_GetOpt_Wide(&goi, &address); if (e != JIM_OK) return e; jim_wide count; e = Jim_GetOpt_Wide(&goi, &count); if (e != JIM_OK) return e; uint32_t *data = malloc(count * sizeof(uint32_t)); if (data == NULL) return JIM_ERR; jim_wide i; for (i = 0; i < count; i++) { jim_wide tmp; e = Jim_GetOpt_Wide(&goi, &tmp); if (e != JIM_OK) { free(data); return e; } data[i] = (uint32_t)tmp; } /* all args must be consumed */ if (goi.argc != 0) { free(data); return JIM_ERR; } struct target *target = Jim_CmdPrivData(goi.interp); int result; result = target_write_buffer(target, address, count * 4, (const uint8_t *)data); free(data); return result; } static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 3) { Jim_SetResultFormatted(goi.interp, "usage: %s # of pairs [
]+", cmd_name); return JIM_ERR; } int e; jim_wide num_of_pairs; e = Jim_GetOpt_Wide(&goi, &num_of_pairs); if (e != JIM_OK) return e; struct target *target = Jim_CmdPrivData(goi.interp); struct aice_port_s *aice = target_to_aice(target); int result; uint32_t address; uint32_t data; jim_wide i; aice_set_command_mode(aice, AICE_COMMAND_MODE_PACK); for (i = 0; i < num_of_pairs; i++) { jim_wide tmp; e = Jim_GetOpt_Wide(&goi, &tmp); if (e != JIM_OK) break; address = (uint32_t)tmp; e = Jim_GetOpt_Wide(&goi, &tmp); if (e != JIM_OK) break; data = (uint32_t)tmp; result = target_write_buffer(target, address, 4, (const uint8_t *)&data); if (result != ERROR_OK) break; } aice_set_command_mode(aice, AICE_COMMAND_MODE_NORMAL); /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; return ERROR_OK; } static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 2) { Jim_SetResultFormatted(goi.interp, "usage: %s
", cmd_name); return JIM_ERR; } int e; jim_wide address; e = Jim_GetOpt_Wide(&goi, &address); if (e != JIM_OK) return e; jim_wide count; e = Jim_GetOpt_Wide(&goi, &count); if (e != JIM_OK) return e; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; struct target *target = Jim_CmdPrivData(goi.interp); uint32_t *data = malloc(count * sizeof(uint32_t)); int result; result = target_read_buffer(target, address, count * 4, (uint8_t *)data); char data_str[11]; jim_wide i; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); for (i = 0; i < count; i++) { sprintf(data_str, "0x%08" PRIx32 " ", data[i]); Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL); } free(data); return result; } static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 1) { Jim_SetResultFormatted(goi.interp, "usage: %s ", cmd_name); return JIM_ERR; } int e; char *edm_sr_name; int edm_sr_name_len; e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len); if (e != JIM_OK) return e; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; uint32_t edm_sr_number; uint32_t edm_sr_value; if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0) edm_sr_number = NDS_EDM_SR_EDM_DTR; else if (strncmp(edm_sr_name, "edmsw", edm_sr_name_len) == 0) edm_sr_number = NDS_EDM_SR_EDMSW; else return ERROR_FAIL; struct target *target = Jim_CmdPrivData(goi.interp); struct aice_port_s *aice = target_to_aice(target); char data_str[11]; aice_read_debug_reg(aice, edm_sr_number, &edm_sr_value); sprintf(data_str, "0x%08" PRIx32, edm_sr_value); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL); return ERROR_OK; } static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 2) { Jim_SetResultFormatted(goi.interp, "usage: %s ", cmd_name); return JIM_ERR; } int e; char *edm_sr_name; int edm_sr_name_len; e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len); if (e != JIM_OK) return e; jim_wide value; e = Jim_GetOpt_Wide(&goi, &value); if (e != JIM_OK) return e; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; uint32_t edm_sr_number; if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0) edm_sr_number = NDS_EDM_SR_EDM_DTR; else return ERROR_FAIL; struct target *target = Jim_CmdPrivData(goi.interp); struct aice_port_s *aice = target_to_aice(target); aice_write_debug_reg(aice, edm_sr_number, value); return ERROR_OK; } static const struct command_registration nds32_query_command_handlers[] = { { .name = "target", .handler = handle_nds32_query_target_command, .mode = COMMAND_EXEC, .usage = "", .help = "reply 'OCD' for gdb to identify server-side is OpenOCD", }, { .name = "endian", .handler = handle_nds32_query_endian_command, .mode = COMMAND_EXEC, .usage = "", .help = "query target endian", }, { .name = "cpuid", .handler = handle_nds32_query_cpuid_command, .mode = COMMAND_EXEC, .usage = "", .help = "query CPU ID", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration nds32_exec_command_handlers[] = { { .name = "dssim", .handler = handle_nds32_dssim_command, .mode = COMMAND_EXEC, .usage = "['on'|'off']", .help = "display/change $INT_MASK.DSSIM status", }, { .name = "mem_access", .handler = handle_nds32_memory_access_command, .mode = COMMAND_EXEC, .usage = "['bus'|'cpu']", .help = "display/change memory access channel", }, { .name = "mem_mode", .handler = handle_nds32_memory_mode_command, .mode = COMMAND_EXEC, .usage = "['auto'|'mem'|'ilm'|'dlm']", .help = "display/change memory mode", }, { .name = "cache", .handler = handle_nds32_cache_command, .mode = COMMAND_EXEC, .usage = "['invalidate']", .help = "cache control", }, { .name = "icache", .handler = handle_nds32_icache_command, .mode = COMMAND_EXEC, .usage = "['invalidate'|'enable'|'disable'|'dump']", .help = "icache control", }, { .name = "dcache", .handler = handle_nds32_dcache_command, .mode = COMMAND_EXEC, .usage = "['invalidate'|'enable'|'disable'|'dump']", .help = "dcache control", }, { .name = "auto_break", .handler = handle_nds32_auto_break_command, .mode = COMMAND_EXEC, .usage = "['on'|'off']", .help = "convert software breakpoints to hardware breakpoints if needed", }, { .name = "virtual_hosting", .handler = handle_nds32_virtual_hosting_command, .mode = COMMAND_ANY, .usage = "['on'|'off']", .help = "turn on/off virtual hosting", }, { .name = "global_stop", .handler = handle_nds32_global_stop_command, .mode = COMMAND_ANY, .usage = "['on'|'off']", .help = "turn on/off global stop. After turning on, every load/store" \ "instructions will be stopped to check memory access.", }, { .name = "soft_reset_halt", .handler = handle_nds32_soft_reset_halt_command, .mode = COMMAND_ANY, .usage = "['on'|'off']", .help = "as issuing rest-halt, to use soft-reset-halt or not." \ "the feature is for backward-compatible.", }, { .name = "boot_time", .handler = handle_nds32_boot_time_command, .mode = COMMAND_CONFIG, .usage = "milliseconds", .help = "set the period to wait after srst.", }, { .name = "login_edm_passcode", .handler = handle_nds32_login_edm_passcode_command, .mode = COMMAND_CONFIG, .usage = "passcode", .help = "set EDM passcode for secure MCU debugging.", }, { .name = "login_edm_operation", .handler = handle_nds32_login_edm_operation_command, .mode = COMMAND_CONFIG, .usage = "login_edm_operation misc_reg_no value", .help = "add EDM operations for secure MCU debugging.", }, { .name = "reset_halt_as_init", .handler = handle_nds32_reset_halt_as_init_command, .mode = COMMAND_CONFIG, .usage = "['on'|'off']", .help = "reset halt as openocd init.", }, { .name = "keep_target_edm_ctl", .handler = handle_nds32_keep_target_edm_ctl_command, .mode = COMMAND_CONFIG, .usage = "['on'|'off']", .help = "Backup/Restore target EDM_CTL register.", }, { .name = "decode", .handler = handle_nds32_decode_command, .mode = COMMAND_EXEC, .usage = "address icount", .help = "decode instruction.", }, { .name = "word_access_mem", .handler = handle_nds32_word_access_mem_command, .mode = COMMAND_ANY, .usage = "['on'|'off']", .help = "Always use word-aligned address to access memory.", }, { .name = "bulk_write", .jim_handler = jim_nds32_bulk_write, .mode = COMMAND_EXEC, .help = "Write multiple 32-bit words to target memory", .usage = "address count data", }, { .name = "multi_write", .jim_handler = jim_nds32_multi_write, .mode = COMMAND_EXEC, .help = "Write multiple addresses/words to target memory", .usage = "num_of_pairs [address data]+", }, { .name = "bulk_read", .jim_handler = jim_nds32_bulk_read, .mode = COMMAND_EXEC, .help = "Read multiple 32-bit words from target memory", .usage = "address count", }, { .name = "read_edmsr", .jim_handler = jim_nds32_read_edm_sr, .mode = COMMAND_EXEC, .help = "Read EDM system register", .usage = "['edmsw'|'edm_dtr']", }, { .name = "write_edmsr", .jim_handler = jim_nds32_write_edm_sr, .mode = COMMAND_EXEC, .help = "Write EDM system register", .usage = "['edm_dtr'] value", }, { .name = "query", .mode = COMMAND_EXEC, .help = "Andes query command group", .usage = "", .chain = nds32_query_command_handlers, }, COMMAND_REGISTRATION_DONE }; const struct command_registration nds32_command_handlers[] = { { .name = "nds", .mode = COMMAND_ANY, .help = "Andes command group", .usage = "", .chain = nds32_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/nds32_cmd.h0000644000175000017500000000314712315575361014107 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_CMD_H__ #define __NDS32_CMD_H__ #include extern const struct command_registration nds32_command_handlers[]; #endif /* __NDS32_CMD_H__ */ openocd-0.9.0/src/target/nds32_edm.h0000644000175000017500000000663112315575361014112 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_EDM_H__ #define __NDS32_EDM_H__ /** * @file * This is the interface to the Embedded Debug Module for Andes cores. */ /* EDM misc registers */ enum nds_edm_misc_reg { NDS_EDM_MISC_DIMIR = 0x0, NDS_EDM_MISC_SBAR, NDS_EDM_MISC_EDM_CMDR, NDS_EDM_MISC_DBGER, NDS_EDM_MISC_ACC_CTL, NDS_EDM_MISC_EDM_PROBE, NDS_EDM_MISC_GEN_PORT0, NDS_EDM_MISC_GEN_PORT1, }; /* EDM system registers */ enum nds_edm_system_reg { NDS_EDM_SR_BPC0 = 0x00, NDS_EDM_SR_BPC1, NDS_EDM_SR_BPC2, NDS_EDM_SR_BPC3, NDS_EDM_SR_BPC4, NDS_EDM_SR_BPC5, NDS_EDM_SR_BPC6, NDS_EDM_SR_BPC7, NDS_EDM_SR_BPA0 = 0x08, NDS_EDM_SR_BPA1, NDS_EDM_SR_BPA2, NDS_EDM_SR_BPA3, NDS_EDM_SR_BPA4, NDS_EDM_SR_BPA5, NDS_EDM_SR_BPA6, NDS_EDM_SR_BPA7, NDS_EDM_SR_BPAM0 = 0x10, NDS_EDM_SR_BPAM1, NDS_EDM_SR_BPAM2, NDS_EDM_SR_BPAM3, NDS_EDM_SR_BPAM4, NDS_EDM_SR_BPAM5, NDS_EDM_SR_BPAM6, NDS_EDM_SR_BPAM7, NDS_EDM_SR_BPV0 = 0x18, NDS_EDM_SR_BPV1, NDS_EDM_SR_BPV2, NDS_EDM_SR_BPV3, NDS_EDM_SR_BPV4, NDS_EDM_SR_BPV5, NDS_EDM_SR_BPV6, NDS_EDM_SR_BPV7, NDS_EDM_SR_BPCID0 = 0x20, NDS_EDM_SR_BPCID1, NDS_EDM_SR_BPCID2, NDS_EDM_SR_BPCID3, NDS_EDM_SR_BPCID4, NDS_EDM_SR_BPCID5, NDS_EDM_SR_BPCID6, NDS_EDM_SR_BPCID7, NDS_EDM_SR_EDM_CFG = 0x28, NDS_EDM_SR_EDMSW = 0x30, NDS_EDM_SR_EDM_CTL = 0x38, NDS_EDM_SR_EDM_DTR = 0x40, NDS_EDM_SR_BPMTV = 0x48, NDS_EDM_SR_DIMBR = 0x50, NDS_EDM_SR_TECR0 = 0x70, NDS_EDM_SR_TECR1 = 0x71, }; enum nds_memory_access { NDS_MEMORY_ACC_BUS = 0, NDS_MEMORY_ACC_CPU, }; enum nds_memory_select { NDS_MEMORY_SELECT_AUTO = 0, NDS_MEMORY_SELECT_MEM = 1, NDS_MEMORY_SELECT_ILM = 2, NDS_MEMORY_SELECT_DLM = 3, }; #define NDS_DBGER_DEX (0x1) #define NDS_DBGER_DPED (0x2) #define NDS_DBGER_CRST (0x4) #define NDS_DBGER_AT_MAX (0x8) #define NDS_DBGER_ILL_SEC_ACC (0x10) #define NDS_DBGER_ALL_SUPRS_EX (0x40000000) #define NDS_DBGER_RESACC (0x80000000) #define NDS_DBGER_CLEAR_ALL (0x1F) #define NDS_EDMSW_WDV (1 << 0) #define NDS_EDMSW_RDV (1 << 1) #endif /* __NDS32_EDM_H__ */ openocd-0.9.0/src/target/nds32_v3m.c0000644000175000017500000003642312315575361014047 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "nds32_cmd.h" #include "nds32_aice.h" #include "nds32_v3m.h" #include "nds32_v3_common.h" static int nds32_v3m_activate_hardware_breakpoint(struct target *target) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; unsigned brp_num = nds32_v3m->n_hbr - 1; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) { /* already set at nds32_v3m_add_breakpoint() */ continue; } else if (bp->type == BKPT_HARD) { /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + brp_num, bp->address); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + brp_num, 0); if (nds32_v3m->nds32.memory.address_translation) /* enable breakpoint (virtual address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x2); else /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0xA); LOG_DEBUG("Add hardware BP %u at %08" PRIx32, brp_num, bp->address); brp_num--; } else { return ERROR_FAIL; } } return ERROR_OK; } static int nds32_v3m_deactivate_hardware_breakpoint(struct target *target) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; unsigned brp_num = nds32_v3m->n_hbr - 1; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) continue; else if (bp->type == BKPT_HARD) /* disable breakpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x0); else return ERROR_FAIL; LOG_DEBUG("Remove hardware BP %u at %08" PRIx32, brp_num, bp->address); brp_num--; } return ERROR_OK; } static int nds32_v3m_activate_hardware_watchpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct watchpoint *wp; int32_t wp_num = 0; uint32_t wp_config = 0; bool ld_stop, st_stop; if (nds32_v3m->nds32.global_stop) ld_stop = st_stop = false; for (wp = target->watchpoints; wp; wp = wp->next) { if (wp_num < nds32_v3m->used_n_wp) { wp->mask = wp->length - 1; if ((wp->address % wp->length) != 0) wp->mask = (wp->mask << 1) + 1; if (wp->rw == WPT_READ) wp_config = 0x3; else if (wp->rw == WPT_WRITE) wp_config = 0x5; else if (wp->rw == WPT_ACCESS) wp_config = 0x7; /* set/unset physical address bit of BPCn according to PSW.DT */ if (nds32_v3m->nds32.memory.address_translation == false) wp_config |= 0x8; /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num, wp->address - (wp->address % wp->length)); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask); /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3m->nds32.global_stop) { if (wp->rw == WPT_READ) ld_stop = true; else if (wp->rw == WPT_WRITE) st_stop = true; else if (wp->rw == WPT_ACCESS) ld_stop = st_stop = true; } } if (nds32_v3m->nds32.global_stop) { uint32_t edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl); if (ld_stop) edm_ctl |= 0x10; if (st_stop) edm_ctl |= 0x20; aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl); } return ERROR_OK; } static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct aice_port_s *aice = target_to_aice(target); struct watchpoint *wp; int32_t wp_num = 0; bool clean_global_stop = false; for (wp = target->watchpoints; wp; wp = wp->next) { if (wp_num < nds32_v3m->used_n_wp) { /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3m->nds32.global_stop) { clean_global_stop = true; } } if (clean_global_stop) { uint32_t edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl); edm_ctl = edm_ctl & (~0x30); aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl); } return ERROR_OK; } static int nds32_v3m_check_interrupt_stack(struct nds32 *nds32) { uint32_t val_ir0; uint32_t value; /* Save interrupt level */ nds32_get_mapped_reg(nds32, IR0, &val_ir0); nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3; if (nds32_reach_max_interrupt_level(nds32)) LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->", nds32->current_interrupt_level); /* backup $ir6 to avoid suppressed exception overwrite */ nds32_get_mapped_reg(nds32, IR6, &value); return ERROR_OK; } static int nds32_v3m_restore_interrupt_stack(struct nds32 *nds32) { uint32_t value; /* get backup value from cache */ /* then set back to make the register dirty */ nds32_get_mapped_reg(nds32, IR0, &value); nds32_set_mapped_reg(nds32, IR0, value); nds32_get_mapped_reg(nds32, IR6, &value); nds32_set_mapped_reg(nds32, IR6, value); return ERROR_OK; } static int nds32_v3m_deassert_reset(struct target *target) { int retval; CHECK_RETVAL(nds32_poll(target)); if (target->state != TARGET_HALTED) { /* reset only */ LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int nds32_v3m_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct nds32 *nds32 = &(nds32_v3m->nds32); int result; if (breakpoint->type == BKPT_HARD) { /* check hardware resource */ if (nds32_v3m->next_hbr_index < nds32_v3m->next_hwp_index) { LOG_WARNING("<-- TARGET WARNING! Insert too many " "hardware breakpoints/watchpoints! " "The limit of combined hardware " "breakpoints/watchpoints is %" PRId32 ". -->", nds32_v3m->n_hbr); LOG_WARNING("<-- TARGET STATUS: Inserted number of " "hardware breakpoint: %" PRId32 ", hardware " "watchpoints: %" PRId32 ". -->", nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1, nds32_v3m->used_n_wp); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware breakpoint */ nds32_v3m->next_hbr_index--; /* hardware breakpoint insertion occurs before 'continue' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { result = nds32_add_software_breakpoint(target, breakpoint); if (ERROR_OK != result) { /* auto convert to hardware breakpoint if failed */ if (nds32->auto_convert_hw_bp) { /* convert to hardware breakpoint */ breakpoint->type = BKPT_HARD; return nds32_v3m_add_breakpoint(target, breakpoint); } } return result; } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v3m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); if (breakpoint->type == BKPT_HARD) { if (nds32_v3m->next_hbr_index >= nds32_v3m->n_hbr - 1) return ERROR_FAIL; /* update next place to put hardware breakpoint */ nds32_v3m->next_hbr_index++; /* hardware breakpoint removal occurs after 'halted' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { return nds32_remove_software_breakpoint(target, breakpoint); } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v3m_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); /* check hardware resource */ if (nds32_v3m->next_hwp_index >= nds32_v3m->n_hwp) { /* No hardware resource */ if (nds32_v3m->nds32.global_stop) { LOG_WARNING("<-- TARGET WARNING! The number of " "watchpoints exceeds the hardware " "resources. Stop at every load/store " "instruction to check for watchpoint matches. -->"); return ERROR_OK; } LOG_WARNING("<-- TARGET WARNING! Insert too many hardware " "watchpoints! The limit of hardware watchpoints " "is %" PRId32 ". -->", nds32_v3m->n_hwp); LOG_WARNING("<-- TARGET STATUS: Inserted number of " "hardware watchpoint: %" PRId32 ". -->", nds32_v3m->used_n_wp); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (nds32_v3m->next_hwp_index > nds32_v3m->next_hbr_index) { /* No hardware resource */ if (nds32_v3m->nds32.global_stop) { LOG_WARNING("<-- TARGET WARNING! The number of " "watchpoints exceeds the hardware " "resources. Stop at every load/store " "instruction to check for watchpoint matches. -->"); return ERROR_OK; } LOG_WARNING("<-- TARGET WARNING! Insert too many hardware " "breakpoints/watchpoints! The limit of combined " "hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v3m->n_hbr); LOG_WARNING("<-- TARGET STATUS: Inserted number of " "hardware breakpoint: %" PRId32 ", hardware " "watchpoints: %" PRId32 ". -->", nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1, nds32_v3m->used_n_wp); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware watchpoint */ nds32_v3m->next_hwp_index++; nds32_v3m->used_n_wp++; return ERROR_OK; } static int nds32_v3m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); if (nds32_v3m->next_hwp_index <= 0) { if (nds32_v3m->nds32.global_stop) return ERROR_OK; return ERROR_FAIL; } /* update next place to put hardware watchpoint */ nds32_v3m->next_hwp_index--; nds32_v3m->used_n_wp--; return ERROR_OK; } struct nds32_v3_common_callback nds32_v3m_common_callback = { .check_interrupt_stack = nds32_v3m_check_interrupt_stack, .restore_interrupt_stack = nds32_v3m_restore_interrupt_stack, .activate_hardware_breakpoint = nds32_v3m_activate_hardware_breakpoint, .activate_hardware_watchpoint = nds32_v3m_activate_hardware_watchpoint, .deactivate_hardware_breakpoint = nds32_v3m_deactivate_hardware_breakpoint, .deactivate_hardware_watchpoint = nds32_v3m_deactivate_hardware_watchpoint, }; static int nds32_v3m_target_create(struct target *target, Jim_Interp *interp) { struct nds32_v3m_common *nds32_v3m; nds32_v3m = calloc(1, sizeof(*nds32_v3m)); if (!nds32_v3m) return ERROR_FAIL; nds32_v3_common_register_callback(&nds32_v3m_common_callback); nds32_v3_target_create_common(target, &(nds32_v3m->nds32)); return ERROR_OK; } /* talk to the target and set things up */ static int nds32_v3m_examine(struct target *target) { struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target); struct nds32 *nds32 = &(nds32_v3m->nds32); struct aice_port_s *aice = target_to_aice(target); if (!target_was_examined(target)) { CHECK_RETVAL(nds32_edm_config(nds32)); if (nds32->reset_halt_as_examine) CHECK_RETVAL(nds32_reset_halt(nds32)); } uint32_t edm_cfg; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); /* get the number of hardware breakpoints */ nds32_v3m->n_hbr = (edm_cfg & 0x7) + 1; nds32_v3m->used_n_wp = 0; /* get the number of hardware watchpoints */ /* If the WP field is hardwired to zero, it means this is a * simple breakpoint. Otherwise, if the WP field is writable * then it means this is a regular watchpoints. */ nds32_v3m->n_hwp = 0; for (int32_t i = 0 ; i < nds32_v3m->n_hbr ; i++) { /** check the hardware breakpoint is simple or not */ uint32_t tmp_value; aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + i, 0x1); aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &tmp_value); if (tmp_value) nds32_v3m->n_hwp++; } /* hardware breakpoint is inserted from high index to low index */ nds32_v3m->next_hbr_index = nds32_v3m->n_hbr - 1; /* hardware watchpoint is inserted from low index to high index */ nds32_v3m->next_hwp_index = 0; LOG_INFO("%s: total hardware breakpoint %" PRId32 " (simple breakpoint %" PRId32 ")", target_name(target), nds32_v3m->n_hbr, nds32_v3m->n_hbr - nds32_v3m->n_hwp); LOG_INFO("%s: total hardware watchpoint %" PRId32, target_name(target), nds32_v3m->n_hwp); nds32->target->state = TARGET_RUNNING; nds32->target->debug_reason = DBG_REASON_NOTHALTED; target_set_examined(target); return ERROR_OK; } /** Holds methods for NDS32 V3m targets. */ struct target_type nds32_v3m_target = { .name = "nds32_v3m", .poll = nds32_poll, .arch_state = nds32_arch_state, .target_request_data = nds32_v3_target_request_data, .halt = nds32_halt, .resume = nds32_resume, .step = nds32_step, .assert_reset = nds32_assert_reset, .deassert_reset = nds32_v3m_deassert_reset, /* register access */ .get_gdb_reg_list = nds32_get_gdb_reg_list, /* memory access */ .read_buffer = nds32_v3_read_buffer, .write_buffer = nds32_v3_write_buffer, .read_memory = nds32_v3_read_memory, .write_memory = nds32_v3_write_memory, .checksum_memory = nds32_v3_checksum_memory, /* breakpoint/watchpoint */ .add_breakpoint = nds32_v3m_add_breakpoint, .remove_breakpoint = nds32_v3m_remove_breakpoint, .add_watchpoint = nds32_v3m_add_watchpoint, .remove_watchpoint = nds32_v3m_remove_watchpoint, .hit_watchpoint = nds32_v3_hit_watchpoint, /* MMU */ .mmu = nds32_mmu, .virt2phys = nds32_virtual_to_physical, .read_phys_memory = nds32_read_phys_memory, .write_phys_memory = nds32_write_phys_memory, .run_algorithm = nds32_v3_run_algorithm, .commands = nds32_command_handlers, .target_create = nds32_v3m_target_create, .init_target = nds32_v3_init_target, .examine = nds32_v3m_examine, .get_gdb_fileio_info = nds32_get_gdb_fileio_info, .gdb_fileio_end = nds32_gdb_fileio_end, }; openocd-0.9.0/src/target/nds32_v3m.h0000644000175000017500000000426212315575361014050 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_V3M_H__ #define __NDS32_V3M_H__ #include "nds32.h" struct nds32_v3m_common { struct nds32 nds32; /** number of hardware breakpoints */ int32_t n_hbr; /** number of hardware watchpoints */ int32_t n_hwp; /** number of used hardware watchpoints */ int32_t used_n_wp; /** next hardware breakpoint index */ /** for simple breakpoints, hardware breakpoints are inserted * from high index to low index */ int32_t next_hbr_index; /** next hardware watchpoint index */ /** increase from low index to high index */ int32_t next_hwp_index; }; static inline struct nds32_v3m_common *target_to_nds32_v3m(struct target *target) { return container_of(target->arch_info, struct nds32_v3m_common, nds32); } #endif /* __NDS32_V3M_H__ */ openocd-0.9.0/src/target/nds32_reg.c0000644000175000017500000005217312516456304014115 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "nds32_reg.h" static bool nds32_reg_init_done; static struct nds32_reg_s nds32_regs[TOTAL_REG_NUM]; static const struct nds32_reg_exception_s nds32_ex_reg_values[] = { {IR0, 3, 0x3, 2}, {IR0, 3, 0x3, 3}, {IR1, 3, 0x3, 2}, {IR1, 3, 0x3, 3}, {IR2, 3, 0x3, 2}, {IR2, 3, 0x3, 3}, {MR3, 1, 0x7, 0}, {MR3, 1, 0x7, 4}, {MR3, 1, 0x7, 6}, {MR3, 8, 0x7, 3}, {0, 0, 0, 0}, }; static inline void nds32_reg_set(uint32_t number, const char *simple_mnemonic, const char *symbolic_mnemonic, uint32_t sr_index, enum nds32_reg_type_s type, uint8_t size) { nds32_regs[number].simple_mnemonic = simple_mnemonic; nds32_regs[number].symbolic_mnemonic = symbolic_mnemonic; nds32_regs[number].sr_index = sr_index; nds32_regs[number].type = type; nds32_regs[number].size = size; } void nds32_reg_init(void) { if (nds32_reg_init_done == true) return; nds32_reg_set(R0, "r0", "r0", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R1, "r1", "r1", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R2, "r2", "r2", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R3, "r3", "r3", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R4, "r4", "r4", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R5, "r5", "r5", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R6, "r6", "r6", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R7, "r7", "r7", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R8, "r8", "r8", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R9, "r9", "r9", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R10, "r10", "r10", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R11, "r11", "r11", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R12, "r12", "r12", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R13, "r13", "r13", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R14, "r14", "r14", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R15, "r15", "r15", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R16, "r16", "r16", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R17, "r17", "r17", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R18, "r18", "r18", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R19, "r19", "r19", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R20, "r20", "r20", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R21, "r21", "r21", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R22, "r22", "r22", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R23, "r23", "r23", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R24, "r24", "r24", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R25, "r25", "r25", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R26, "r26", "p0", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R27, "r27", "p1", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R28, "fp", "fp", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R29, "gp", "gp", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R30, "lp", "lp", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(R31, "sp", "sp", 0, NDS32_REG_TYPE_GPR, 32); nds32_reg_set(PC, "pc", "pc", 31, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(D0LO, "d0lo", "d0lo", 0, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(D0HI, "d0hi", "d0hi", 1, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(D1LO, "d1lo", "d1lo", 2, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(D1HI, "d1hi", "d1hi", 3, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(ITB, "itb", "itb", 28, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(IFC_LP, "ifc_lp", "ifc_lp", 29, NDS32_REG_TYPE_SPR, 32); nds32_reg_set(CR0, "cr0", "CPU_VER", SRIDX(0, 0, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR1, "cr1", "ICM_CFG", SRIDX(0, 1, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR2, "cr2", "DCM_CFG", SRIDX(0, 2, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR3, "cr3", "MMU_CFG", SRIDX(0, 3, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR4, "cr4", "MSC_CFG", SRIDX(0, 4, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR5, "cr5", "CORE_ID", SRIDX(0, 0, 1), NDS32_REG_TYPE_CR, 32); nds32_reg_set(CR6, "cr6", "FUCOP_EXIST", SRIDX(0, 5, 0), NDS32_REG_TYPE_CR, 32); nds32_reg_set(IR0, "ir0", "PSW", SRIDX(1, 0, 0), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR1, "ir1", "IPSW", SRIDX(1, 0, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR2, "ir2", "P_IPSW", SRIDX(1, 0, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR3, "ir3", "IVB", SRIDX(1, 1, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR4, "ir4", "EVA", SRIDX(1, 2, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR5, "ir5", "P_EVA", SRIDX(1, 2, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR6, "ir6", "ITYPE", SRIDX(1, 3, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR7, "ir7", "P_ITYPE", SRIDX(1, 3, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR8, "ir8", "MERR", SRIDX(1, 4, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR9, "ir9", "IPC", SRIDX(1, 5, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR10, "ir10", "P_IPC", SRIDX(1, 5, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR11, "ir11", "OIPC", SRIDX(1, 5, 3), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR12, "ir12", "P_P0", SRIDX(1, 6, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR13, "ir13", "P_P1", SRIDX(1, 7, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR14, "ir14", "INT_MASK", SRIDX(1, 8, 0), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR15, "ir15", "INT_PEND", SRIDX(1, 9, 0), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR16, "ir16", "", SRIDX(1, 10, 0), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR17, "ir17", "", SRIDX(1, 10, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR18, "ir18", "", SRIDX(1, 11, 0), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR19, "ir19", "", SRIDX(1, 1, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR20, "ir20", "", SRIDX(1, 10, 2), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR21, "ir21", "", SRIDX(1, 10, 3), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR22, "ir22", "", SRIDX(1, 10, 4), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR23, "ir23", "", SRIDX(1, 10, 5), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR24, "ir24", "", SRIDX(1, 10, 6), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR25, "ir25", "", SRIDX(1, 10, 7), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR26, "ir26", "", SRIDX(1, 8, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR27, "ir27", "", SRIDX(1, 9, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR28, "ir28", "", SRIDX(1, 11, 1), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR29, "ir29", "", SRIDX(1, 9, 4), NDS32_REG_TYPE_IR, 32); nds32_reg_set(IR30, "ir30", "", SRIDX(1, 1, 3), NDS32_REG_TYPE_IR, 32); nds32_reg_set(MR0, "mr0", "MMU_CTL", SRIDX(2, 0, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR1, "mr1", "L1_PPTB", SRIDX(2, 1, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR2, "mr2", "TLB_VPN", SRIDX(2, 2, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR3, "mr3", "TLB_DATA", SRIDX(2, 3, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR4, "mr4", "TLB_MISC", SRIDX(2, 4, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR5, "mr5", "VLPT_IDX", SRIDX(2, 5, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR6, "mr6", "ILMB", SRIDX(2, 6, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR7, "mr7", "DLMB", SRIDX(2, 7, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR8, "mr8", "CACHE_CTL", SRIDX(2, 8, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR9, "mr9", "HSMP_SADDR", SRIDX(2, 9, 0), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR10, "mr10", "HSMP_EADDR", SRIDX(2, 9, 1), NDS32_REG_TYPE_MR, 32); nds32_reg_set(MR11, "mr11", "", SRIDX(2, 0, 1), NDS32_REG_TYPE_MR, 32); nds32_reg_set(DR0, "dr0", "BPC0", SRIDX(3, 0, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR1, "dr1", "BPA0", SRIDX(3, 1, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR2, "dr2", "BPAM0", SRIDX(3, 2, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR3, "dr3", "BPV0", SRIDX(3, 3, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR4, "dr4", "BPCID0", SRIDX(3, 4, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR5, "dr5", "BPC1", SRIDX(3, 0, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR6, "dr6", "BPA1", SRIDX(3, 1, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR7, "dr7", "BPAM1", SRIDX(3, 2, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR8, "dr8", "BPV1", SRIDX(3, 3, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR9, "dr9", "BPCID1", SRIDX(3, 4, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR10, "dr10", "BPC2", SRIDX(3, 0, 2), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR11, "dr11", "BPA2", SRIDX(3, 1, 2), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR12, "dr12", "BPAM2", SRIDX(3, 2, 2), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR13, "dr13", "BPV2", SRIDX(3, 3, 2), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR14, "dr14", "BPCID2", SRIDX(3, 4, 2), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR15, "dr15", "BPC3", SRIDX(3, 0, 3), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR16, "dr16", "BPA3", SRIDX(3, 1, 3), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR17, "dr17", "BPAM3", SRIDX(3, 2, 3), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR18, "dr18", "BPV3", SRIDX(3, 3, 3), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR19, "dr19", "BPCID3", SRIDX(3, 4, 3), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR20, "dr20", "BPC4", SRIDX(3, 0, 4), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR21, "dr21", "BPA4", SRIDX(3, 1, 4), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR22, "dr22", "BPAM4", SRIDX(3, 2, 4), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR23, "dr23", "BPV4", SRIDX(3, 3, 4), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR24, "dr24", "BPCID4", SRIDX(3, 4, 4), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR25, "dr25", "BPC5", SRIDX(3, 0, 5), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR26, "dr26", "BPA5", SRIDX(3, 1, 5), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR27, "dr27", "BPAM5", SRIDX(3, 2, 5), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR28, "dr28", "BPV5", SRIDX(3, 3, 5), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR29, "dr29", "BPCID5", SRIDX(3, 4, 5), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR30, "dr30", "BPC6", SRIDX(3, 0, 6), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR31, "dr31", "BPA6", SRIDX(3, 1, 6), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR32, "dr32", "BPAM6", SRIDX(3, 2, 6), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR33, "dr33", "BPV6", SRIDX(3, 3, 6), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR34, "dr34", "BPCID6", SRIDX(3, 4, 6), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR35, "dr35", "BPC7", SRIDX(3, 0, 7), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR36, "dr36", "BPA7", SRIDX(3, 1, 7), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR37, "dr37", "BPAM7", SRIDX(3, 2, 7), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR38, "dr38", "BPV7", SRIDX(3, 3, 7), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR39, "dr39", "BPCID7", SRIDX(3, 4, 7), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR40, "dr40", "EDM_CFG", SRIDX(3, 5, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR41, "dr41", "EDMSW", SRIDX(3, 6, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR42, "dr42", "EDM_CTL", SRIDX(3, 7, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR43, "dr43", "EDM_DTR", SRIDX(3, 8, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR44, "dr44", "BPMTC", SRIDX(3, 9, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR45, "dr45", "DIMBR", SRIDX(3, 10, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR46, "dr46", "TECR0", SRIDX(3, 14, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR47, "dr47", "TECR1", SRIDX(3, 14, 1), NDS32_REG_TYPE_DR, 32); nds32_reg_set(DR48, "dr48", "", SRIDX(3, 11, 0), NDS32_REG_TYPE_DR, 32); nds32_reg_set(PFR0, "pfr0", "PFMC0", SRIDX(4, 0, 0), NDS32_REG_TYPE_PFR, 32); nds32_reg_set(PFR1, "pfr1", "PFMC1", SRIDX(4, 0, 1), NDS32_REG_TYPE_PFR, 32); nds32_reg_set(PFR2, "pfr2", "PFMC2", SRIDX(4, 0, 2), NDS32_REG_TYPE_PFR, 32); nds32_reg_set(PFR3, "pfr3", "PFM_CTL", SRIDX(4, 1, 0), NDS32_REG_TYPE_PFR, 32); nds32_reg_set(DMAR0, "dmar0", "DMA_CFG", SRIDX(5, 0, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR1, "dmar1", "DMA_GCSW", SRIDX(5, 1, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR2, "dmar2", "DMA_CHNSEL", SRIDX(5, 2, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR3, "dmar3", "DMA_ACT", SRIDX(5, 3, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR4, "dmar4", "DMA_SETUP", SRIDX(5, 4, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR5, "dmar5", "DMA_ISADDR", SRIDX(5, 5, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR6, "dmar6", "DMA_ESADDR", SRIDX(5, 6, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR7, "dmar7", "DMA_TCNT", SRIDX(5, 7, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR8, "dmar8", "DMA_STATUS", SRIDX(5, 8, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR9, "dmar9", "DMA_2DSET", SRIDX(5, 9, 0), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(DMAR10, "dmar10", "DMA_2DSCTL", SRIDX(5, 9, 1), NDS32_REG_TYPE_DMAR, 32); nds32_reg_set(RACR, "racr", "PRUSR_ACC_CTL", SRIDX(4, 4, 0), NDS32_REG_TYPE_RACR, 32); nds32_reg_set(FUCPR, "fucpr", "FUCOP_CTL", SRIDX(4, 5, 0), NDS32_REG_TYPE_RACR, 32); nds32_reg_set(IDR0, "idr0", "SDZ_CTL", SRIDX(2, 15, 0), NDS32_REG_TYPE_IDR, 32); nds32_reg_set(IDR1, "idr1", "MISC_CTL", SRIDX(2, 15, 1), NDS32_REG_TYPE_IDR, 32); nds32_reg_set(SECUR0, "secur0", "", SRIDX(6, 0, 0), NDS32_REG_TYPE_SECURE, 32); nds32_reg_set(D0L24, "D0L24", "D0L24", 0x10, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(D1L24, "D1L24", "D1L24", 0x11, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I0, "I0", "I0", 0x0, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I1, "I1", "I1", 0x1, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I2, "I2", "I2", 0x2, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I3, "I3", "I3", 0x3, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I4, "I4", "I4", 0x4, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I5, "I5", "I5", 0x5, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I6, "I6", "I6", 0x6, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(I7, "I7", "I7", 0x7, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M1, "M1", "M1", 0x9, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M2, "M2", "M2", 0xA, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M3, "M3", "M3", 0xB, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M5, "M5", "M5", 0xD, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M6, "M6", "M6", 0xE, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(M7, "M7", "M7", 0xF, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(MOD, "MOD", "MOD", 0x8, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(LBE, "LBE", "LBE", 0x18, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(LE, "LE", "LE", 0x19, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(LC, "LC", "LC", 0x1A, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(ADM_VBASE, "ADM_VBASE", "ADM_VBASE", 0x1B, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(SHFT_CTL0, "SHFT_CTL0", "SHFT_CTL0", 0x12, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(SHFT_CTL1, "SHFT_CTL1", "SHFT_CTL1", 0x13, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CB_CTL, "CB_CTL", "CB_CTL", 0x1F, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBB0, "CBB0", "CBB0", 0x0, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBB1, "CBB1", "CBB1", 0x1, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBB2, "CBB2", "CBB2", 0x2, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBB3, "CBB3", "CBB3", 0x3, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBE0, "CBE0", "CBE0", 0x4, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBE1, "CBE1", "CBE1", 0x5, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBE2, "CBE2", "CBE2", 0x6, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(CBE3, "CBE3", "CBE3", 0x7, NDS32_REG_TYPE_AUMR, 32); nds32_reg_set(FPCSR, "fpcsr", "FPCSR", 0x7, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FPCFG, "fpcfg", "FPCFG", 0x7, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS0, "fs0", "FS0", 0, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS1, "fs1", "FS1", 1, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS2, "fs2", "FS2", 2, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS3, "fs3", "FS3", 3, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS4, "fs4", "FS4", 4, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS5, "fs5", "FS5", 5, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS6, "fs6", "FS6", 6, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS7, "fs7", "FS7", 7, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS8, "fs8", "FS8", 8, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS9, "fs9", "FS9", 9, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS10, "fs10", "FS10", 10, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS11, "fs11", "FS11", 11, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS12, "fs12", "FS12", 12, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS13, "fs13", "FS13", 13, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS14, "fs14", "FS14", 14, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS15, "fs15", "FS15", 15, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS16, "fs16", "FS16", 16, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS17, "fs17", "FS17", 17, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS18, "fs18", "FS18", 18, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS19, "fs19", "FS19", 19, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS20, "fs20", "FS20", 20, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS21, "fs21", "FS21", 21, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS22, "fs22", "FS22", 22, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS23, "fs23", "FS23", 23, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS24, "fs24", "FS24", 24, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS25, "fs25", "FS25", 25, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS26, "fs26", "FS26", 26, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS27, "fs27", "FS27", 27, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS28, "fs28", "FS28", 28, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS29, "fs29", "FS29", 29, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS30, "fs30", "FS30", 30, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FS31, "fs31", "FS31", 31, NDS32_REG_TYPE_FPU, 32); nds32_reg_set(FD0, "fd0", "FD0", 0, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD1, "fd1", "FD1", 1, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD2, "fd2", "FD2", 2, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD3, "fd3", "FD3", 3, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD4, "fd4", "FD4", 4, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD5, "fd5", "FD5", 5, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD6, "fd6", "FD6", 6, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD7, "fd7", "FD7", 7, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD8, "fd8", "FD8", 8, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD9, "fd9", "FD9", 9, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD10, "fd10", "FD10", 10, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD11, "fd11", "FD11", 11, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD12, "fd12", "FD12", 12, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD13, "fd13", "FD13", 13, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD14, "fd14", "FD14", 14, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD15, "fd15", "FD15", 15, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD16, "fd16", "FD16", 16, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD17, "fd17", "FD17", 17, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD18, "fd18", "FD18", 18, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD19, "fd19", "FD19", 19, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD20, "fd20", "FD20", 20, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD21, "fd21", "FD21", 21, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD22, "fd22", "FD22", 22, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD23, "fd23", "FD23", 23, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD24, "fd24", "FD24", 24, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD25, "fd25", "FD25", 25, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD26, "fd26", "FD26", 26, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD27, "fd27", "FD27", 27, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD28, "fd28", "FD28", 28, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD29, "fd29", "FD29", 29, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD30, "fd30", "FD30", 30, NDS32_REG_TYPE_FPU, 64); nds32_reg_set(FD31, "fd31", "FD31", 31, NDS32_REG_TYPE_FPU, 64); nds32_reg_init_done = true; } uint32_t nds32_reg_sr_index(uint32_t number) { return nds32_regs[number].sr_index; } enum nds32_reg_type_s nds32_reg_type(uint32_t number) { return nds32_regs[number].type; } uint8_t nds32_reg_size(uint32_t number) { return nds32_regs[number].size; } const char *nds32_reg_simple_name(uint32_t number) { return nds32_regs[number].simple_mnemonic; } const char *nds32_reg_symbolic_name(uint32_t number) { return nds32_regs[number].symbolic_mnemonic; } bool nds32_reg_exception(uint32_t number, uint32_t value) { int i; const struct nds32_reg_exception_s *ex_reg_value; uint32_t field_value; i = 0; while (nds32_ex_reg_values[i].reg_num != 0) { ex_reg_value = nds32_ex_reg_values + i; if (ex_reg_value->reg_num == number) { field_value = (value >> ex_reg_value->ex_value_bit_pos) & ex_reg_value->ex_value_mask; if (field_value == ex_reg_value->ex_value) { LOG_WARNING("It will generate exceptions as setting %" PRId32 " to %s", value, nds32_regs[number].simple_mnemonic); return true; } } i++; } return false; } openocd-0.9.0/src/target/nds32_reg.h0000644000175000017500000001040212315575361014111 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_REG_H__ #define __NDS32_REG_H__ #define SRIDX(a, b, c) ((a << 7) | (b << 3) | c) #define NDS32_REGISTER_DISABLE (0x0) enum nds32_reg_number_s { R0 = 0, /* general registers */ R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, PC, D0LO, D0HI, D1LO, D1HI, ITB, IFC_LP, CR0, /* system registers */ CR1, CR2, CR3, CR4, CR5, CR6, IR0, IR1, IR2, IR3, IR4, IR5, IR6, IR7, IR8, IR9, IR10, IR11, IR12, IR13, IR14, IR15, IR16, IR17, IR18, IR19, IR20, IR21, IR22, IR23, IR24, IR25, IR26, IR27, IR28, IR29, IR30, MR0, MR1, MR2, MR3, MR4, MR5, MR6, MR7, MR8, MR9, MR10, MR11, DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7, DR8, DR9, DR10, DR11, DR12, DR13, DR14, DR15, DR16, DR17, DR18, DR19, DR20, DR21, DR22, DR23, DR24, DR25, DR26, DR27, DR28, DR29, DR30, DR31, DR32, DR33, DR34, DR35, DR36, DR37, DR38, DR39, DR40, DR41, DR42, DR43, DR44, DR45, DR46, DR47, DR48, PFR0, PFR1, PFR2, PFR3, DMAR0, DMAR1, DMAR2, DMAR3, DMAR4, DMAR5, DMAR6, DMAR7, DMAR8, DMAR9, DMAR10, RACR, FUCPR, IDR0, IDR1, SECUR0, D0L24, /* audio registers */ D1L24, I0, I1, I2, I3, I4, I5, I6, I7, M1, M2, M3, M5, M6, M7, MOD, LBE, LE, LC, ADM_VBASE, SHFT_CTL0, SHFT_CTL1, CB_CTL, CBB0, CBB1, CBB2, CBB3, CBE0, CBE1, CBE2, CBE3, FPCSR, /* fpu */ FPCFG, FS0, FS1, FS2, FS3, FS4, FS5, FS6, FS7, FS8, FS9, FS10, FS11, FS12, FS13, FS14, FS15, FS16, FS17, FS18, FS19, FS20, FS21, FS22, FS23, FS24, FS25, FS26, FS27, FS28, FS29, FS30, FS31, FD0, FD1, FD2, FD3, FD4, FD5, FD6, FD7, FD8, FD9, FD10, FD11, FD12, FD13, FD14, FD15, FD16, FD17, FD18, FD19, FD20, FD21, FD22, FD23, FD24, FD25, FD26, FD27, FD28, FD29, FD30, FD31, TOTAL_REG_NUM, }; enum nds32_reg_type_s { NDS32_REG_TYPE_GPR = 0, NDS32_REG_TYPE_SPR, NDS32_REG_TYPE_CR, NDS32_REG_TYPE_IR, NDS32_REG_TYPE_MR, NDS32_REG_TYPE_DR, NDS32_REG_TYPE_PFR, NDS32_REG_TYPE_DMAR, NDS32_REG_TYPE_RACR, NDS32_REG_TYPE_IDR, NDS32_REG_TYPE_AUMR, NDS32_REG_TYPE_SECURE, NDS32_REG_TYPE_FPU, }; struct nds32_reg_s { const char *simple_mnemonic; const char *symbolic_mnemonic; uint32_t sr_index; enum nds32_reg_type_s type; uint8_t size; }; struct nds32_reg_exception_s { uint32_t reg_num; uint32_t ex_value_bit_pos; uint32_t ex_value_mask; uint32_t ex_value; }; void nds32_reg_init(void); uint32_t nds32_reg_sr_index(uint32_t number); enum nds32_reg_type_s nds32_reg_type(uint32_t number); uint8_t nds32_reg_size(uint32_t number); const char *nds32_reg_simple_name(uint32_t number); const char *nds32_reg_symbolic_name(uint32_t number); bool nds32_reg_exception(uint32_t number, uint32_t value); #endif openocd-0.9.0/src/target/hla_target.c0000644000175000017500000005341212516456304014436 00000000000000/*************************************************************************** * Copyright (C) 2011 by Mathias Kuester * * Mathias Kuester * * * * Copyright (C) 2011 by Spencer Oliver * * spen@spen-soft.co.uk * * * * revised: 4/25/13 by brent@mbari.org [DCC target request support] * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/jtag.h" #include "jtag/hla/hla_transport.h" #include "jtag/hla/hla_interface.h" #include "jtag/hla/hla_layout.h" #include "register.h" #include "algorithm.h" #include "target.h" #include "breakpoints.h" #include "target_type.h" #include "armv7m.h" #include "cortex_m.h" #include "arm_semihosting.h" #include "target_request.h" #define savedDCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */ #define ARMV7M_SCS_DCRSR DCB_DCRSR #define ARMV7M_SCS_DCRDR DCB_DCRDR static inline struct hl_interface_s *target_to_adapter(struct target *target) { return target->tap->priv; } static int adapter_load_core_reg_u32(struct target *target, uint32_t num, uint32_t *value) { int retval; struct hl_interface_s *adapter = target_to_adapter(target); LOG_DEBUG("%s", __func__); /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register * Selector values for R0..R15, xPSR, MSP, and PSP. */ switch (num) { case 0 ... 18: /* read a normal core register */ retval = adapter->layout->api->read_reg(adapter->handle, num, value); if (retval != ERROR_OK) { LOG_ERROR("JTAG failure %i", retval); return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value); break; case ARMV7M_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); break; case ARMV7M_S0 ... ARMV7M_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRSR, num-ARMV7M_S0+64); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, (int)(num - ARMV7M_S0), *value); break; case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: case ARMV7M_CONTROL: /* Cortex-M3 packages these four registers as bitfields * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ retval = adapter->layout->api->read_reg(adapter->handle, 20, value); if (retval != ERROR_OK) return retval; switch (num) { case ARMV7M_PRIMASK: *value = buf_get_u32((uint8_t *) value, 0, 1); break; case ARMV7M_BASEPRI: *value = buf_get_u32((uint8_t *) value, 8, 8); break; case ARMV7M_FAULTMASK: *value = buf_get_u32((uint8_t *) value, 16, 1); break; case ARMV7M_CONTROL: *value = buf_get_u32((uint8_t *) value, 24, 2); break; } LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int adapter_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value) { int retval; uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); struct hl_interface_s *adapter = target_to_adapter(target); LOG_DEBUG("%s", __func__); /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register * Selector values for R0..R15, xPSR, MSP, and PSP. */ switch (num) { case 0 ... 18: retval = adapter->layout->api->write_reg(adapter->handle, num, value); if (retval != ERROR_OK) { struct reg *r; LOG_ERROR("JTAG failure"); r = armv7m->arm.core_cache->reg_list + num; r->dirty = r->valid; return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value); break; case ARMV7M_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33 | (1<<16)); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); break; case ARMV7M_S0 ... ARMV7M_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, ARMV7M_SCS_DCRSR, (num-ARMV7M_S0+64) | (1<<16)); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, (int)(num - ARMV7M_S0), value); break; case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: case ARMV7M_CONTROL: /* Cortex-M3 packages these four registers as bitfields * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ adapter->layout->api->read_reg(adapter->handle, 20, ®); switch (num) { case ARMV7M_PRIMASK: buf_set_u32((uint8_t *) ®, 0, 1, value); break; case ARMV7M_BASEPRI: buf_set_u32((uint8_t *) ®, 8, 8, value); break; case ARMV7M_FAULTMASK: buf_set_u32((uint8_t *) ®, 16, 1, value); break; case ARMV7M_CONTROL: buf_set_u32((uint8_t *) ®, 24, 2, value); break; } adapter->layout->api->write_reg(adapter->handle, 20, reg); LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int adapter_examine_debug_reason(struct target *target) { if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { target->debug_reason = DBG_REASON_BREAKPOINT; } return ERROR_OK; } static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl) { uint16_t dcrdr; int retval = hl_if->layout->api->read_mem(hl_if->handle, DCB_DCRDR, 1, sizeof(dcrdr), (uint8_t *)&dcrdr); if (retval == ERROR_OK) { *ctrl = (uint8_t)dcrdr; *value = (uint8_t)(dcrdr >> 8); LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl); if (dcrdr & 1) { /* write ack back to software dcc register * to signify we have read data */ /* atomically clear just the byte containing the busy bit */ static const uint8_t zero; retval = hl_if->layout->api->write_mem(hl_if->handle, DCB_DCRDR, 1, 1, &zero); } } return retval; } static int hl_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { struct hl_interface_s *hl_if = target_to_adapter(target); uint8_t data; uint8_t ctrl; uint32_t i; for (i = 0; i < (size * 4); i++) { hl_dcc_read(hl_if, &data, &ctrl); buffer[i] = data; } return ERROR_OK; } static int hl_handle_target_request(void *priv) { struct target *target = priv; if (!target_was_examined(target)) return ERROR_OK; struct hl_interface_s *hl_if = target_to_adapter(target); if (!target->dbg_msg_enabled) return ERROR_OK; if (target->state == TARGET_RUNNING) { uint8_t data; uint8_t ctrl; hl_dcc_read(hl_if, &data, &ctrl); /* check if we have data */ if (ctrl & (1 << 0)) { uint32_t request; /* we assume target is quick enough */ request = data; hl_dcc_read(hl_if, &data, &ctrl); request |= (data << 8); hl_dcc_read(hl_if, &data, &ctrl); request |= (data << 16); hl_dcc_read(hl_if, &data, &ctrl); request |= (data << 24); target_request(target, request); } } return ERROR_OK; } static int adapter_init_arch_info(struct target *target, struct cortex_m_common *cortex_m, struct jtag_tap *tap) { struct armv7m_common *armv7m; LOG_DEBUG("%s", __func__); armv7m = &cortex_m->armv7m; armv7m_init_arch_info(target, armv7m); armv7m->load_core_reg_u32 = adapter_load_core_reg_u32; armv7m->store_core_reg_u32 = adapter_store_core_reg_u32; armv7m->examine_debug_reason = adapter_examine_debug_reason; armv7m->stlink = true; target_register_timer_callback(hl_handle_target_request, 1, 1, target); return ERROR_OK; } static int adapter_init_target(struct command_context *cmd_ctx, struct target *target) { LOG_DEBUG("%s", __func__); armv7m_build_reg_cache(target); return ERROR_OK; } static int adapter_target_create(struct target *target, Jim_Interp *interp) { LOG_DEBUG("%s", __func__); struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common)); if (!cortex_m) return ERROR_COMMAND_SYNTAX_ERROR; adapter_init_arch_info(target, cortex_m, target->tap); return ERROR_OK; } static int adapter_load_context(struct target *target) { struct armv7m_common *armv7m = target_to_armv7m(target); int num_regs = armv7m->arm.core_cache->num_regs; for (int i = 0; i < num_regs; i++) { struct reg *r = &armv7m->arm.core_cache->reg_list[i]; if (!r->valid) armv7m->arm.read_core_reg(target, r, i, ARM_MODE_ANY); } return ERROR_OK; } static int adapter_debug_entry(struct target *target) { struct hl_interface_s *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); struct arm *arm = &armv7m->arm; struct reg *r; uint32_t xPSR; int retval; /* preserve the DCRDR across halts */ retval = target_read_u32(target, DCB_DCRDR, &target->savedDCRDR); if (retval != ERROR_OK) return retval; retval = armv7m->examine_debug_reason(target); if (retval != ERROR_OK) return retval; adapter_load_context(target); /* make sure we clear the vector catch bit */ adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA); r = arm->cpsr; xPSR = buf_get_u32(r->value, 0, 32); /* Are we in an exception handler */ if (xPSR & 0x1FF) { armv7m->exception_number = (xPSR & 0x1FF); arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { unsigned control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 2); /* is this thread privileged? */ arm->core_mode = control & 1 ? ARM_MODE_USER_THREAD : ARM_MODE_THREAD; /* which stack is it using? */ if (control & 2) arm->map = armv7m_psp_reg_map; else arm->map = armv7m_msp_reg_map; armv7m->exception_number = 0; } LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s", arm_mode_name(arm->core_mode), buf_get_u32(arm->pc->value, 0, 32), target_state_name(target)); return retval; } static int adapter_poll(struct target *target) { enum target_state state; struct hl_interface_s *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); enum target_state prev_target_state = target->state; state = adapter->layout->api->state(adapter->handle); if (state == TARGET_UNKNOWN) { LOG_ERROR("jtag status contains invalid mode value - communication failure"); return ERROR_TARGET_FAILURE; } if (prev_target_state == state) return ERROR_OK; target->state = state; if (state == TARGET_HALTED) { int retval = adapter_debug_entry(target); if (retval != ERROR_OK) return retval; if (prev_target_state == TARGET_DEBUG_RUNNING) { target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } else { if (arm_semihosting(target, &retval) != 0) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); } LOG_DEBUG("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32)); } return ERROR_OK; } static int adapter_assert_reset(struct target *target) { int res = ERROR_OK; struct hl_interface_s *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); bool use_srst_fallback = true; LOG_DEBUG("%s", __func__); enum reset_types jtag_reset_config = jtag_get_reset_config(); bool srst_asserted = false; if ((jtag_reset_config & RESET_HAS_SRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); res = adapter->layout->api->assert_srst(adapter->handle, 0); srst_asserted = true; } adapter->layout->api->write_debug_reg(adapter->handle, DCB_DHCSR, DBGKEY|C_DEBUGEN); /* only set vector catch if halt is requested */ if (target->reset_halt) adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA|VC_CORERESET); else adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA); if (jtag_reset_config & RESET_HAS_SRST) { if (!srst_asserted) { jtag_add_reset(0, 1); res = adapter->layout->api->assert_srst(adapter->handle, 0); } if (res == ERROR_COMMAND_NOTFOUND) LOG_ERROR("Hardware srst not supported, falling back to software reset"); else if (res == ERROR_OK) { /* hardware srst supported */ use_srst_fallback = false; } } if (use_srst_fallback) { /* stlink v1 api does not support hardware srst, so we use a software reset fallback */ adapter->layout->api->write_debug_reg(adapter->handle, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ); } res = adapter->layout->api->reset(adapter->handle); if (res != ERROR_OK) return res; /* registers are now invalid */ register_cache_invalidate(armv7m->arm.core_cache); if (target->reset_halt) { target->state = TARGET_RESET; target->debug_reason = DBG_REASON_DBGRQ; } else { target->state = TARGET_HALTED; } return ERROR_OK; } static int adapter_deassert_reset(struct target *target) { struct hl_interface_s *adapter = target_to_adapter(target); enum reset_types jtag_reset_config = jtag_get_reset_config(); LOG_DEBUG("%s", __func__); if (jtag_reset_config & RESET_HAS_SRST) adapter->layout->api->assert_srst(adapter->handle, 1); /* virtual deassert reset, we need it for the internal * jtag state machine */ jtag_add_reset(0, 0); target->savedDCRDR = 0; /* clear both DCC busy bits on initial resume */ return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0); } static int adapter_halt(struct target *target) { int res; struct hl_interface_s *adapter = target_to_adapter(target); LOG_DEBUG("%s", __func__); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); res = adapter->layout->api->halt(adapter->handle); if (res != ERROR_OK) return res; target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int adapter_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int res; struct hl_interface_s *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); uint32_t resume_pc; struct breakpoint *breakpoint = NULL; struct reg *pc; LOG_DEBUG("%s %d 0x%08" PRIx32 " %d %d", __func__, current, address, handle_breakpoints, debug_execution); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); cortex_m_enable_breakpoints(target); cortex_m_enable_watchpoints(target); } pc = armv7m->arm.pc; if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; pc->valid = true; } if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32)) && !debug_execution) { armv7m_maybe_skip_bkpt_inst(target, NULL); } resume_pc = buf_get_u32(pc->value, 0, 32); /* write any user vector flags */ res = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr); if (res != ERROR_OK) return res; armv7m_restore_context(target); /* restore savedDCRDR */ res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR); if (res != ERROR_OK) return res; /* registers are now invalid */ register_cache_invalidate(armv7m->arm.core_cache); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); res = adapter->layout->api->step(adapter->handle); if (res != ERROR_OK) return res; cortex_m_set_breakpoint(target, breakpoint); } } res = adapter->layout->api->run(adapter->handle); if (res != ERROR_OK) return res; target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); } return ERROR_OK; } static int adapter_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { int res; struct hl_interface_s *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); struct breakpoint *breakpoint = NULL; struct reg *pc = armv7m->arm.pc; bool bkpt_inst_found = false; LOG_DEBUG("%s", __func__); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; pc->valid = true; } uint32_t pc_value = buf_get_u32(pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { breakpoint = breakpoint_find(target, pc_value); if (breakpoint) cortex_m_unset_breakpoint(target, breakpoint); } armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found); target->debug_reason = DBG_REASON_SINGLESTEP; armv7m_restore_context(target); /* restore savedDCRDR */ res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR); if (res != ERROR_OK) return res; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); res = adapter->layout->api->step(adapter->handle); if (res != ERROR_OK) return res; /* registers are now invalid */ register_cache_invalidate(armv7m->arm.core_cache); if (breakpoint) cortex_m_set_breakpoint(target, breakpoint); adapter_debug_entry(target); target_call_event_callbacks(target, TARGET_EVENT_HALTED); LOG_INFO("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32)); return ERROR_OK; } static int adapter_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct hl_interface_s *adapter = target_to_adapter(target); if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer); } static int adapter_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct hl_interface_s *adapter = target_to_adapter(target); if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer); } static const struct command_registration adapter_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = armv7m_trace_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type hla_target = { .name = "hla_target", .deprecated_name = "stm32_stlink", .init_target = adapter_init_target, .deinit_target = cortex_m_deinit_target, .target_create = adapter_target_create, .examine = cortex_m_examine, .commands = adapter_command_handlers, .poll = adapter_poll, .arch_state = armv7m_arch_state, .target_request_data = hl_target_request_data, .assert_reset = adapter_assert_reset, .deassert_reset = adapter_deassert_reset, .halt = adapter_halt, .resume = adapter_resume, .step = adapter_step, .get_gdb_reg_list = armv7m_get_gdb_reg_list, .read_memory = adapter_read_memory, .write_memory = adapter_write_memory, .checksum_memory = armv7m_checksum_memory, .blank_check_memory = armv7m_blank_check_memory, .run_algorithm = armv7m_run_algorithm, .start_algorithm = armv7m_start_algorithm, .wait_algorithm = armv7m_wait_algorithm, .add_breakpoint = cortex_m_add_breakpoint, .remove_breakpoint = cortex_m_remove_breakpoint, .add_watchpoint = cortex_m_add_watchpoint, .remove_watchpoint = cortex_m_remove_watchpoint, }; openocd-0.9.0/src/target/nds32_tlb.c0000644000175000017500000000670512315575361014123 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "nds32_aice.h" #include "nds32_tlb.h" int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, uint32_t *physical_address) { struct target *target = nds32->target; struct aice_port_s *aice = target_to_aice(target); return aice_read_tlb(aice, virtual_address, physical_address); } struct page_table_walker_info_s page_table_info[PAGE_SIZE_NUM] = { /* 4K page */ {0xFFC00000, 20, 0x003FF000, 10, 0x00000FFF, 0xFFFFF000, 0xFFFFF000, 0xFFFFF000}, /* 8K page */ {0xFF000000, 22, 0x00FFE000, 11, 0x00001FFF, 0xFFFFF000, 0xFFFFE000, 0xFFFFE000}, }; int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, uint32_t *physical_address) { struct target *target = nds32->target; uint32_t value_mr1; uint32_t load_address; uint32_t L1_page_table_entry; uint32_t L2_page_table_entry; uint32_t page_size_index = nds32->mmu_config.default_min_page_size; struct page_table_walker_info_s *page_table_info_p = &(page_table_info[page_size_index]); /* Read L1 Physical Page Table */ nds32_get_mapped_reg(nds32, MR1, &value_mr1); load_address = (value_mr1 & page_table_info_p->L1_base_mask) | ((virtual_address & page_table_info_p->L1_offset_mask) >> page_table_info_p->L1_offset_shift); /* load_address is physical address */ nds32_read_buffer(target, load_address, 4, (uint8_t *)&L1_page_table_entry); /* Read L2 Physical Page Table */ if (L1_page_table_entry & 0x1) /* L1_PTE not present */ return ERROR_FAIL; load_address = (L1_page_table_entry & page_table_info_p->L2_base_mask) | ((virtual_address & page_table_info_p->L2_offset_mask) >> page_table_info_p->L2_offset_shift); /* load_address is physical address */ nds32_read_buffer(target, load_address, 4, (uint8_t *)&L2_page_table_entry); if ((L2_page_table_entry & 0x1) != 0x1) /* L2_PTE not valid */ return ERROR_FAIL; *physical_address = (L2_page_table_entry & page_table_info_p->ppn_mask) | (virtual_address & page_table_info_p->va_offset_mask); return ERROR_OK; } openocd-0.9.0/src/target/nds32_tlb.h0000644000175000017500000000402512315575361014121 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_TLB_H__ #define __NDS32_TLB_H__ #include "nds32.h" enum { PAGE_SIZE_4K = 0, PAGE_SIZE_8K, PAGE_SIZE_NUM, }; struct page_table_walker_info_s { uint32_t L1_offset_mask; uint32_t L1_offset_shift; uint32_t L2_offset_mask; uint32_t L2_offset_shift; uint32_t va_offset_mask; uint32_t L1_base_mask; uint32_t L2_base_mask; uint32_t ppn_mask; }; extern int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, uint32_t *physical_address); extern int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, uint32_t *physical_address); #endif openocd-0.9.0/src/target/arm.h0000644000175000017500000001555612516456303013116 00000000000000/* * Copyright (C) 2005 by Dominic Rath * Dominic.Rath@gmx.de * * Copyright (C) 2008 by Spencer Oliver * spen@spen-soft.co.uk * * Copyright (C) 2009 by Øyvind Harboe * oyvind.harboe@zylin.com * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef ARM_H #define ARM_H #include #include "target.h" /** * @file * Holds the interface to ARM cores. * * At this writing, only "classic ARM" cores built on the ARMv4 register * and mode model are supported. The Thumb2-only microcontroller profile * support has not yet been integrated, affecting Cortex-M parts. */ /** * Represent state of an ARM core. * * Most numbers match the five low bits of the *PSR registers on * "classic ARM" processors, which build on the ARMv4 processor * modes and register set. * * ARM_MODE_ANY is a magic value, often used as a wildcard. * * Only the microcontroller cores (ARMv6-M, ARMv7-M) support ARM_MODE_THREAD, * ARM_MODE_USER_THREAD, and ARM_MODE_HANDLER. Those are the only modes * they support. */ enum arm_mode { ARM_MODE_USR = 16, ARM_MODE_FIQ = 17, ARM_MODE_IRQ = 18, ARM_MODE_SVC = 19, ARM_MODE_MON = 22, ARM_MODE_ABT = 23, ARM_MODE_UND = 27, ARM_MODE_SYS = 31, ARM_MODE_THREAD = 0, ARM_MODE_USER_THREAD = 1, ARM_MODE_HANDLER = 2, ARM_MODE_ANY = -1 }; const char *arm_mode_name(unsigned psr_mode); bool is_arm_mode(unsigned psr_mode); /** The PSR "T" and "J" bits define the mode of "classic ARM" cores. */ enum arm_state { ARM_STATE_ARM, ARM_STATE_THUMB, ARM_STATE_JAZELLE, ARM_STATE_THUMB_EE, }; #define ARM_COMMON_MAGIC 0x0A450A45 /** * Represents a generic ARM core, with standard application registers. * * There are sixteen application registers (including PC, SP, LR) and a PSR. * Cortex-M series cores do not support as many core states or shadowed * registers as traditional ARM cores, and only support Thumb2 instructions. */ struct arm { int common_magic; struct reg_cache *core_cache; /** Handle to the PC; valid in all core modes. */ struct reg *pc; /** Handle to the CPSR/xPSR; valid in all core modes. */ struct reg *cpsr; /** Handle to the SPSR; valid only in core modes with an SPSR. */ struct reg *spsr; /** Support for arm_reg_current() */ const int *map; /** * Indicates what registers are in the ARM state core register set. * ARM_MODE_ANY indicates the standard set of 37 registers, * seen on for example ARM7TDMI cores. ARM_MODE_MON indicates three * more registers are shadowed, for "Secure Monitor" mode. * ARM_MODE_THREAD indicates a microcontroller profile core, * which only shadows SP. */ enum arm_mode core_type; /** Record the current core mode: SVC, USR, or some other mode. */ enum arm_mode core_mode; /** Record the current core state: ARM, Thumb, or otherwise. */ enum arm_state core_state; /** Flag reporting unavailability of the BKPT instruction. */ bool is_armv4; /** Flag reporting armv6m based core. */ bool is_armv6m; /** Flag reporting whether semihosting is active. */ bool is_semihosting; /** Value to be returned by semihosting SYS_ERRNO request. */ int semihosting_errno; int (*setup_semihosting)(struct target *target, int enable); /** Backpointer to the target. */ struct target *target; /** Handle for the debug module, if one is present. */ struct arm_dpm *dpm; /** Handle for the Embedded Trace Module, if one is present. */ struct etm_context *etm; /* FIXME all these methods should take "struct arm *" not target */ /** Retrieve all core registers, for display. */ int (*full_context)(struct target *target); /** Retrieve a single core register. */ int (*read_core_reg)(struct target *target, struct reg *reg, int num, enum arm_mode mode); int (*write_core_reg)(struct target *target, struct reg *reg, int num, enum arm_mode mode, uint8_t *value); /** Read coprocessor register. */ int (*mrc)(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); /** Write coprocessor register. */ int (*mcr)(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); void *arch_info; /** For targets conforming to ARM Debug Interface v5, * this handle references the Debug Access Port (DAP) * used to make requests to the target. */ struct adiv5_dap *dap; }; /** Convert target handle to generic ARM target state handle. */ static inline struct arm *target_to_arm(struct target *target) { assert(target != NULL); return target->arch_info; } static inline bool is_arm(struct arm *arm) { assert(arm != NULL); return arm->common_magic == ARM_COMMON_MAGIC; } struct arm_algorithm { int common_magic; enum arm_mode core_mode; enum arm_state core_state; }; struct arm_reg { int num; enum arm_mode mode; struct target *target; struct arm *arm; uint8_t value[4]; }; struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm); extern const struct command_registration arm_command_handlers[]; int arm_arch_state(struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); int arm_init_arch_info(struct target *target, struct arm *arm); /* REVISIT rename this once it's usable by ARMv7-M */ int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)); int arm_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int arm_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); struct reg *arm_reg_current(struct arm *arm, unsigned regnum); extern struct reg arm_gdb_dummy_fp_reg; extern struct reg arm_gdb_dummy_fps_reg; #endif /* ARM_H */ openocd-0.9.0/src/target/arm_jtag.c0000644000175000017500000000657512315575361014122 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm_jtag.h" #if 0 #define _ARM_JTAG_SCAN_N_CHECK_ #endif int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) { struct jtag_tap *tap; tap = jtag_info->tap; struct scan_field field; uint8_t t[4]; field.num_bits = tap->ir_length; field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; if (no_verify_capture == NULL) jtag_add_ir_scan(tap, &field, end_state); else { /* FIX!!!! this is a kludge!!! arm926ejs.c should reimplement this arm_jtag_set_instr to * have special verification code. */ jtag_add_ir_scan_noverify(tap, &field, end_state); } return ERROR_OK; } int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) { int retval = ERROR_OK; uint8_t out_value[4]; buf_set_u32(out_value, 0, jtag_info->scann_size, new_scan_chain); struct scan_field field = { .num_bits = jtag_info->scann_size, .out_value = out_value, }; retval = arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL, end_state); if (retval != ERROR_OK) return retval; jtag_add_dr_scan(jtag_info->tap, 1, &field, end_state); jtag_info->cur_scan_chain = new_scan_chain; return retval; } static int arm_jtag_reset_callback(enum jtag_event event, void *priv) { struct arm_jtag *jtag_info = priv; if (event == JTAG_TRST_ASSERTED) jtag_info->cur_scan_chain = 0; return ERROR_OK; } int arm_jtag_setup_connection(struct arm_jtag *jtag_info) { jtag_info->scann_instr = 0x2; jtag_info->cur_scan_chain = 0; jtag_info->intest_instr = 0xc; return jtag_register_event_callback(arm_jtag_reset_callback, jtag_info); } openocd-0.9.0/src/target/arm_jtag.h0000644000175000017500000000635312315575361014121 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM_JTAG #define ARM_JTAG #include struct arm_jtag { struct jtag_tap *tap; uint32_t scann_size; uint32_t scann_instr; uint32_t cur_scan_chain; uint32_t intest_instr; }; int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info, uint32_t new_instr, void *no_verify_capture, tap_state_t end_state); static inline int arm_jtag_set_instr(struct arm_jtag *jtag_info, uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) { /* inline most common code path */ struct jtag_tap *tap; tap = jtag_info->tap; assert(tap != NULL); if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) return arm_jtag_set_instr_inner(jtag_info, new_instr, no_verify_capture, end_state); return ERROR_OK; } int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state); static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) { /* inline most common code path */ int retval = ERROR_OK; if (jtag_info->cur_scan_chain != new_scan_chain) return arm_jtag_scann_inner(jtag_info, new_scan_chain, end_state); return retval; } int arm_jtag_setup_connection(struct arm_jtag *jtag_info); /* use this as a static so we can inline it in -O3 and refer to it via a pointer */ static inline void arm7flip32(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32); } static inline void arm_le_to_h_u32(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = le_to_h_u32(in); } #endif /* ARM_JTAG */ openocd-0.9.0/src/target/arm720t.c0000644000175000017500000004074012315575361013522 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2009 by Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm720t.h" #include #include "target_type.h" #include "register.h" #include "arm_opcodes.h" /* * ARM720 is an ARM7TDMI-S with MMU and ETM7. For information, see * ARM DDI 0229C especially Chapter 9 about debug support. */ #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif static int arm720t_scan_cp15(struct target *target, uint32_t out, uint32_t *in, int instruction, int clock_arg) { int retval; struct arm720t_common *arm720t = target_to_arm720(target); struct arm_jtag *jtag_info; struct scan_field fields[2]; uint8_t out_buf[4]; uint8_t instruction_buf = instruction; jtag_info = &arm720t->arm7_9_common.jtag_info; buf_set_u32(out_buf, 0, 32, flip_u32(out, 32)); retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 1; fields[0].out_value = &instruction_buf; fields[0].in_value = NULL; fields[1].num_bits = 32; fields[1].out_value = out_buf; fields[1].in_value = NULL; if (in) { fields[1].in_value = (uint8_t *)in; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback(arm7flip32, (jtag_callback_data_t)in); } else jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); if (clock_arg) jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock); else LOG_DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock_arg); #else LOG_DEBUG("out: %8.8" PRIx32 ", instruction: %i, clock: %i", out, instruction, clock_arg); #endif return ERROR_OK; } static int arm720t_read_cp15(struct target *target, uint32_t opcode, uint32_t *value) { /* fetch CP15 opcode */ arm720t_scan_cp15(target, opcode, NULL, 1, 1); /* "DECODE" stage */ arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1); /* "EXECUTE" stage (1) */ arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0); arm720t_scan_cp15(target, 0x0, NULL, 0, 1); /* "EXECUTE" stage (2) */ arm720t_scan_cp15(target, 0x0, NULL, 0, 1); /* "EXECUTE" stage (3), CDATA is read */ arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1); return ERROR_OK; } static int arm720t_write_cp15(struct target *target, uint32_t opcode, uint32_t value) { /* fetch CP15 opcode */ arm720t_scan_cp15(target, opcode, NULL, 1, 1); /* "DECODE" stage */ arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1); /* "EXECUTE" stage (1) */ arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0); arm720t_scan_cp15(target, 0x0, NULL, 0, 1); /* "EXECUTE" stage (2) */ arm720t_scan_cp15(target, value, NULL, 0, 1); arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1); return ERROR_OK; } static int arm720t_get_ttb(struct target *target, uint32_t *result) { uint32_t ttb = 0x0; int retval; retval = arm720t_read_cp15(target, 0xee120f10, &ttb); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; ttb &= 0xffffc000; *result = ttb; return ERROR_OK; } static int arm720t_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) cp15_control &= ~0x1U; if (d_u_cache || i_cache) cp15_control &= ~0x4U; retval = arm720t_write_cp15(target, 0xee010f10, cp15_control); return retval; } static int arm720t_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) cp15_control |= 0x1U; if (d_u_cache || i_cache) cp15_control |= 0x4U; retval = arm720t_write_cp15(target, 0xee010f10, cp15_control); return retval; } static int arm720t_post_debug_entry(struct target *target) { struct arm720t_common *arm720t = target_to_arm720(target); int retval; /* examine cp15 control reg */ retval = arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg); arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0; arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0; arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0; /* save i/d fault status and address register */ retval = arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg); if (retval != ERROR_OK) return retval; retval = arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); return retval; } static void arm720t_pre_restore_context(struct target *target) { struct arm720t_common *arm720t = target_to_arm720(target); /* restore i/d fault status and address register */ arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg); arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg); } static int arm720t_verify_pointer(struct command_context *cmd_ctx, struct arm720t_common *arm720t) { if (arm720t->common_magic != ARM720T_COMMON_MAGIC) { command_print(cmd_ctx, "target is not an ARM720"); return ERROR_TARGET_INVALID; } return ERROR_OK; } static int arm720t_arch_state(struct target *target) { struct arm720t_common *arm720t = target_to_arm720(target); static const char *state[] = { "disabled", "enabled" }; arm_arch_state(target); LOG_USER("MMU: %s, Cache: %s", state[arm720t->armv4_5_mmu.mmu_enabled], state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]); return ERROR_OK; } static int arm720_mmu(struct target *target, int *enabled) { if (target->state != TARGET_HALTED) { LOG_ERROR("%s: target not halted", __func__); return ERROR_TARGET_INVALID; } *enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled; return ERROR_OK; } static int arm720_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) { uint32_t cb; struct arm720t_common *arm720t = target_to_arm720(target); uint32_t ret; int retval = armv4_5_mmu_translate_va(target, &arm720t->armv4_5_mmu, virtual, &cb, &ret); if (retval != ERROR_OK) return retval; *physical = ret; return ERROR_OK; } static int arm720t_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; struct arm720t_common *arm720t = target_to_arm720(target); /* disable cache, but leave MMU enabled */ if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) { retval = arm720t_disable_mmu_caches(target, 0, 1, 0); if (retval != ERROR_OK) return retval; } retval = arm7_9_read_memory(target, address, size, count, buffer); if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) { retval = arm720t_enable_mmu_caches(target, 0, 1, 0); if (retval != ERROR_OK) return retval; } return retval; } static int arm720t_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); return armv4_5_mmu_read_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer); } static int arm720t_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); return armv4_5_mmu_write_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer); } static int arm720t_soft_reset_halt(struct target *target) { int retval = ERROR_OK; struct arm720t_common *arm720t = target_to_arm720(target); struct reg *dbg_stat = &arm720t->arm7_9_common .eice_cache->reg_list[EICE_DBG_STAT]; struct arm *arm = &arm720t->arm7_9_common.arm; retval = target_halt(target); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; } else break; if (debug_level >= 3) alive_sleep(100); else keep_alive(); } if (timeout) { LOG_ERROR("Failed to halt CPU after 1 sec"); return ERROR_TARGET_TIMEOUT; } target->state = TARGET_HALTED; /* SVC, ARM state, IRQ and FIQ disabled */ uint32_t cpsr; cpsr = buf_get_u32(arm->cpsr->value, 0, 32); cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); arm->pc->dirty = 1; arm->pc->valid = 1; retval = arm720t_disable_mmu_caches(target, 1, 1, 1); if (retval != ERROR_OK) return retval; arm720t->armv4_5_mmu.mmu_enabled = 0; arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0; arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0; retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int arm720t_init_target(struct command_context *cmd_ctx, struct target *target) { return arm7tdmi_init_target(cmd_ctx, target); } /* FIXME remove forward decls */ static int arm720t_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); static int arm720t_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); static int arm720t_init_arch_info(struct target *target, struct arm720t_common *arm720t, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common; arm7_9->arm.mrc = arm720t_mrc; arm7_9->arm.mcr = arm720t_mcr; arm7tdmi_init_arch_info(target, arm7_9, tap); arm720t->common_magic = ARM720T_COMMON_MAGIC; arm7_9->post_debug_entry = arm720t_post_debug_entry; arm7_9->pre_restore_context = arm720t_pre_restore_context; arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1; arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb; arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory; arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory; arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches; arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches; arm720t->armv4_5_mmu.has_tiny_pages = 0; arm720t->armv4_5_mmu.mmu_enabled = 0; return ERROR_OK; } static int arm720t_target_create(struct target *target, Jim_Interp *interp) { struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t)); arm720t->arm7_9_common.arm.is_armv4 = true; return arm720t_init_arch_info(target, arm720t, target->tap); } COMMAND_HANDLER(arm720t_handle_cp15_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm720t_common *arm720t = target_to_arm720(target); retval = arm720t_verify_pointer(CMD_CTX, arm720t); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } /* one or more argument, access a single register (write if second argument is given */ if (CMD_ARGC >= 1) { uint32_t opcode; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode); if (CMD_ARGC == 1) { uint32_t value; retval = arm720t_read_cp15(target, opcode, &value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode); return ERROR_OK; } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value); } else if (CMD_ARGC == 2) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); retval = arm720t_write_cp15(target, opcode, value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode); return ERROR_OK; } command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value); } } return ERROR_OK; } static int arm720t_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } /* read "to" r0 */ return arm720t_read_cp15(target, ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2), value); } static int arm720t_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } /* write "from" r0 */ return arm720t_write_cp15(target, ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2), value); } static const struct command_registration arm720t_exec_command_handlers[] = { { .name = "cp15", .handler = arm720t_handle_cp15_command, .mode = COMMAND_EXEC, /* prefer using less error-prone "arm mcr" or "arm mrc" */ .help = "display/modify cp15 register using ARM opcode" " (DEPRECATED)", .usage = "instruction [value]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration arm720t_command_handlers[] = { { .chain = arm7_9_command_handlers, }, { .name = "arm720t", .mode = COMMAND_ANY, .help = "arm720t command group", .usage = "", .chain = arm720t_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM720 targets. */ struct target_type arm720t_target = { .name = "arm720t", .poll = arm7_9_poll, .arch_state = arm720t_arch_state, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm720t_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm720t_read_memory, .write_memory = arm7_9_write_memory_opt, .read_phys_memory = arm720t_read_phys_memory, .write_phys_memory = arm720t_write_phys_memory, .mmu = arm720_mmu, .virt2phys = arm720_virt2phys, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm720t_command_handlers, .target_create = arm720t_target_create, .init_target = arm720t_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm720t.h0000644000175000017500000000366612315575361013535 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM720T_H #define ARM720T_H #include "arm7tdmi.h" #include "armv4_5_mmu.h" #define ARM720T_COMMON_MAGIC 0xa720a720 struct arm720t_common { struct arm7_9_common arm7_9_common; uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; uint32_t cp15_control_reg; uint32_t fsr_reg; uint32_t far_reg; }; static inline struct arm720t_common *target_to_arm720(struct target *target) { return container_of(target->arch_info, struct arm720t_common, arm7_9_common.arm); } #endif /* ARM720T_H */ openocd-0.9.0/src/target/etb.c0000644000175000017500000004626212516456303013102 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "etm.h" #include "etb.h" #include "register.h" static const char * const etb_reg_list[] = { "ETB_identification", "ETB_ram_depth", "ETB_ram_width", "ETB_status", "ETB_ram_data", "ETB_ram_read_pointer", "ETB_ram_write_pointer", "ETB_trigger_counter", "ETB_control", }; static int etb_get_reg(struct reg *reg); static int etb_set_instr(struct etb *etb, uint32_t new_instr) { struct jtag_tap *tap; tap = etb->tap; if (tap == NULL) return ERROR_FAIL; if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { struct scan_field field; field.num_bits = tap->ir_length; void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); free(t); } return ERROR_OK; } static int etb_scann(struct etb *etb, uint32_t new_scan_chain) { if (etb->cur_scan_chain != new_scan_chain) { struct scan_field field; field.num_bits = 5; void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_scan_chain); field.in_value = NULL; /* select INTEST instruction */ etb_set_instr(etb, 0x2); jtag_add_dr_scan(etb->tap, 1, &field, TAP_IDLE); etb->cur_scan_chain = new_scan_chain; free(t); } return ERROR_OK; } static int etb_read_reg_w_check(struct reg *, uint8_t *, uint8_t *); static int etb_set_reg_w_exec(struct reg *, uint8_t *); static int etb_read_reg(struct reg *reg) { return etb_read_reg_w_check(reg, NULL, NULL); } static int etb_get_reg(struct reg *reg) { int retval; retval = etb_read_reg(reg); if (retval != ERROR_OK) { LOG_ERROR("BUG: error scheduling ETB register read"); return retval; } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("ETB register read failed"); return retval; } return ERROR_OK; } static const struct reg_arch_type etb_reg_type = { .get = etb_get_reg, .set = etb_set_reg_w_exec, }; struct reg_cache *etb_build_reg_cache(struct etb *etb) { struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct etb_reg *arch_info = NULL; int num_regs = 9; int i; /* the actual registers are kept in two arrays */ reg_list = calloc(num_regs, sizeof(struct reg)); arch_info = calloc(num_regs, sizeof(struct etb_reg)); /* fill in values for the reg cache */ reg_cache->name = "etb registers"; reg_cache->next = NULL; reg_cache->reg_list = reg_list; reg_cache->num_regs = num_regs; /* set up registers */ for (i = 0; i < num_regs; i++) { reg_list[i].name = etb_reg_list[i]; reg_list[i].size = 32; reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].value = calloc(1, 4); reg_list[i].arch_info = &arch_info[i]; reg_list[i].type = &etb_reg_type; reg_list[i].size = 32; arch_info[i].addr = i; arch_info[i].etb = etb; } return reg_cache; } static void etb_getbuf(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = buf_get_u32(in, 0, 32); } static int etb_read_ram(struct etb *etb, uint32_t *data, int num_frames) { struct scan_field fields[3]; int i; etb_scann(etb, 0x0); etb_set_instr(etb, 0xc); fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = NULL; fields[1].num_bits = 7; uint8_t temp1; fields[1].out_value = &temp1; buf_set_u32(&temp1, 0, 7, 4); fields[1].in_value = NULL; fields[2].num_bits = 1; uint8_t temp2; fields[2].out_value = &temp2; buf_set_u32(&temp2, 0, 1, 0); fields[2].in_value = NULL; jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE); for (i = 0; i < num_frames; i++) { /* ensure nR/W remains set to read */ buf_set_u32(&temp2, 0, 1, 0); /* address remains set to 0x4 (RAM data) until we read the last frame */ if (i < num_frames - 1) buf_set_u32(&temp1, 0, 7, 4); else buf_set_u32(&temp1, 0, 7, 0); fields[0].in_value = (uint8_t *)(data + i); jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE); jtag_add_callback(etb_getbuf, (jtag_callback_data_t)(data + i)); } jtag_execute_queue(); return ERROR_OK; } static int etb_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask) { struct etb_reg *etb_reg = reg->arch_info; uint8_t reg_addr = etb_reg->addr & 0x7f; struct scan_field fields[3]; LOG_DEBUG("%i", (int)(etb_reg->addr)); etb_scann(etb_reg->etb, 0x0); etb_set_instr(etb_reg->etb, 0xc); fields[0].num_bits = 32; fields[0].out_value = reg->value; fields[0].in_value = NULL; fields[0].check_value = NULL; fields[0].check_mask = NULL; fields[1].num_bits = 7; uint8_t temp1; fields[1].out_value = &temp1; buf_set_u32(&temp1, 0, 7, reg_addr); fields[1].in_value = NULL; fields[1].check_value = NULL; fields[1].check_mask = NULL; fields[2].num_bits = 1; uint8_t temp2; fields[2].out_value = &temp2; buf_set_u32(&temp2, 0, 1, 0); fields[2].in_value = NULL; fields[2].check_value = NULL; fields[2].check_mask = NULL; jtag_add_dr_scan(etb_reg->etb->tap, 3, fields, TAP_IDLE); /* read the identification register in the second run, to make sure we * don't read the ETB data register twice, skipping every second entry */ buf_set_u32(&temp1, 0, 7, 0x0); fields[0].in_value = reg->value; fields[0].check_value = check_value; fields[0].check_mask = check_mask; jtag_add_dr_scan_check(etb_reg->etb->tap, 3, fields, TAP_IDLE); return ERROR_OK; } static int etb_write_reg(struct reg *, uint32_t); static int etb_set_reg(struct reg *reg, uint32_t value) { int retval; retval = etb_write_reg(reg, value); if (retval != ERROR_OK) { LOG_ERROR("BUG: error scheduling ETB register write"); return retval; } buf_set_u32(reg->value, 0, reg->size, value); reg->valid = 1; reg->dirty = 0; return ERROR_OK; } static int etb_set_reg_w_exec(struct reg *reg, uint8_t *buf) { int retval; etb_set_reg(reg, buf_get_u32(buf, 0, reg->size)); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("ETB: register write failed"); return retval; } return ERROR_OK; } static int etb_write_reg(struct reg *reg, uint32_t value) { struct etb_reg *etb_reg = reg->arch_info; uint8_t reg_addr = etb_reg->addr & 0x7f; struct scan_field fields[3]; LOG_DEBUG("%i: 0x%8.8" PRIx32 "", (int)(etb_reg->addr), value); etb_scann(etb_reg->etb, 0x0); etb_set_instr(etb_reg->etb, 0xc); fields[0].num_bits = 32; uint8_t temp0[4]; fields[0].out_value = temp0; buf_set_u32(temp0, 0, 32, value); fields[0].in_value = NULL; fields[1].num_bits = 7; uint8_t temp1; fields[1].out_value = &temp1; buf_set_u32(&temp1, 0, 7, reg_addr); fields[1].in_value = NULL; fields[2].num_bits = 1; uint8_t temp2; fields[2].out_value = &temp2; buf_set_u32(&temp2, 0, 1, 1); fields[2].in_value = NULL; jtag_add_dr_scan(etb_reg->etb->tap, 3, fields, TAP_IDLE); return ERROR_OK; } COMMAND_HANDLER(handle_etb_config_command) { struct target *target; struct jtag_tap *tap; struct arm *arm; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[0]); if (!target) { LOG_ERROR("ETB: target '%s' not defined", CMD_ARGV[0]); return ERROR_FAIL; } arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETB: '%s' isn't an ARM", CMD_ARGV[0]); return ERROR_FAIL; } tap = jtag_tap_by_string(CMD_ARGV[1]); if (tap == NULL) { command_print(CMD_CTX, "ETB: TAP %s does not exist", CMD_ARGV[1]); return ERROR_FAIL; } if (arm->etm) { struct etb *etb = malloc(sizeof(struct etb)); arm->etm->capture_driver_priv = etb; etb->tap = tap; etb->cur_scan_chain = 0xffffffff; etb->reg_cache = NULL; etb->ram_width = 0; etb->ram_depth = 0; } else { LOG_ERROR("ETM: target has no ETM defined, ETB left unconfigured"); return ERROR_FAIL; } return ERROR_OK; } COMMAND_HANDLER(handle_etb_trigger_percent_command) { struct target *target; struct arm *arm; struct etm_context *etm; struct etb *etb; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETB: current target isn't an ARM"); return ERROR_FAIL; } etm = arm->etm; if (!etm) { command_print(CMD_CTX, "ETB: target has no ETM configured"); return ERROR_FAIL; } if (etm->capture_driver != &etb_capture_driver) { command_print(CMD_CTX, "ETB: target not using ETB"); return ERROR_FAIL; } etb = arm->etm->capture_driver_priv; if (CMD_ARGC > 0) { uint32_t new_value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_value); if ((new_value < 2) || (new_value > 100)) command_print(CMD_CTX, "valid percentages are 2%% to 100%%"); else etb->trigger_percent = (unsigned) new_value; } command_print(CMD_CTX, "%d percent of tracebuffer fills after trigger", etb->trigger_percent); return ERROR_OK; } static const struct command_registration etb_config_command_handlers[] = { { /* NOTE: with ADIv5, ETBs are accessed using DAP operations, * possibly over SWD, not through separate TAPs... */ .name = "config", .handler = handle_etb_config_command, .mode = COMMAND_CONFIG, .help = "Associate ETB with target and JTAG TAP.", .usage = "target tap", }, { .name = "trigger_percent", .handler = handle_etb_trigger_percent_command, .mode = COMMAND_EXEC, .help = "Set percent of trace buffer to be filled " "after the trigger occurs (2..100).", .usage = "[percent]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration etb_command_handlers[] = { { .name = "etb", .mode = COMMAND_ANY, .help = "Embedded Trace Buffer command group", .chain = etb_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; static int etb_init(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; etb->etm_ctx = etm_ctx; /* identify ETB RAM depth and width */ etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]); etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]); jtag_execute_queue(); etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32); etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32); etb->trigger_percent = 50; return ERROR_OK; } static trace_status_t etb_status(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; struct reg *control = &etb->reg_cache->reg_list[ETB_CTRL]; struct reg *status = &etb->reg_cache->reg_list[ETB_STATUS]; trace_status_t retval = 0; int etb_timeout = 100; etb->etm_ctx = etm_ctx; /* read control and status registers */ etb_read_reg(control); etb_read_reg(status); jtag_execute_queue(); /* See if it's (still) active */ retval = buf_get_u32(control->value, 0, 1) ? TRACE_RUNNING : TRACE_IDLE; /* check Full bit to identify wraparound/overflow */ if (buf_get_u32(status->value, 0, 1) == 1) retval |= TRACE_OVERFLOWED; /* check Triggered bit to identify trigger condition */ if (buf_get_u32(status->value, 1, 1) == 1) retval |= TRACE_TRIGGERED; /* check AcqComp to see if trigger counter dropped to zero */ if (buf_get_u32(status->value, 2, 1) == 1) { /* wait for DFEmpty */ while (etb_timeout-- && buf_get_u32(status->value, 3, 1) == 0) etb_get_reg(status); if (etb_timeout == 0) LOG_ERROR("ETB: DFEmpty won't go high, status 0x%02x", (unsigned) buf_get_u32(status->value, 0, 4)); if (!(etm_ctx->capture_status & TRACE_TRIGGERED)) LOG_WARNING("ETB: trace complete without triggering?"); retval |= TRACE_COMPLETED; } /* NOTE: using a trigger is optional; and at least ETB11 has a mode * where it can ignore the trigger counter. */ /* update recorded state */ etm_ctx->capture_status = retval; return retval; } static int etb_read_trace(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; int first_frame = 0; int num_frames = etb->ram_depth; uint32_t *trace_data = NULL; int i, j; etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]); etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]); jtag_execute_queue(); /* check if we overflowed, and adjust first frame of the trace accordingly * if we didn't overflow, read only up to the frame that would be written next, * i.e. don't read invalid entries */ if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1)) first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32); else num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32); etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame); /* read data into temporary array for unpacking */ trace_data = malloc(sizeof(uint32_t) * num_frames); etb_read_ram(etb, trace_data, num_frames); if (etm_ctx->trace_depth > 0) free(etm_ctx->trace_data); if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT) etm_ctx->trace_depth = num_frames * 3; else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) etm_ctx->trace_depth = num_frames * 2; else etm_ctx->trace_depth = num_frames; etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth); for (i = 0, j = 0; i < num_frames; i++) { if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT) { /* trace word j */ etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7; etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3; etm_ctx->trace_data[j].flags = 0; if ((trace_data[i] & 0x80) >> 7) etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j].pipestat == STAT_TR) { etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7; etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE; } /* trace word j + 1 */ etm_ctx->trace_data[j + 1].pipestat = (trace_data[i] & 0x100) >> 8; etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7800) >> 11; etm_ctx->trace_data[j + 1].flags = 0; if ((trace_data[i] & 0x8000) >> 15) etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) { etm_ctx->trace_data[j + 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7; etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE; } /* trace word j + 2 */ etm_ctx->trace_data[j + 2].pipestat = (trace_data[i] & 0x10000) >> 16; etm_ctx->trace_data[j + 2].packet = (trace_data[i] & 0x780000) >> 19; etm_ctx->trace_data[j + 2].flags = 0; if ((trace_data[i] & 0x800000) >> 23) etm_ctx->trace_data[j + 2].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j + 2].pipestat == STAT_TR) { etm_ctx->trace_data[j + 2].pipestat = etm_ctx->trace_data[j + 2].packet & 0x7; etm_ctx->trace_data[j + 2].flags |= ETMV1_TRIGGER_CYCLE; } j += 3; } else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) { /* trace word j */ etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7; etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3; etm_ctx->trace_data[j].flags = 0; if ((trace_data[i] & 0x800) >> 11) etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j].pipestat == STAT_TR) { etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7; etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE; } /* trace word j + 1 */ etm_ctx->trace_data[j + 1].pipestat = (trace_data[i] & 0x7000) >> 12; etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7f8000) >> 15; etm_ctx->trace_data[j + 1].flags = 0; if ((trace_data[i] & 0x800000) >> 23) etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) { etm_ctx->trace_data[j + 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7; etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE; } j += 2; } else { /* trace word j */ etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7; etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3; etm_ctx->trace_data[j].flags = 0; if ((trace_data[i] & 0x80000) >> 19) etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[j].pipestat == STAT_TR) { etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7; etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE; } j += 1; } } free(trace_data); return ERROR_OK; } static int etb_start_capture(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; uint32_t etb_ctrl_value = 0x1; uint32_t trigger_count; if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED) { if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT) { LOG_ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port"); return ERROR_ETM_PORTMODE_NOT_SUPPORTED; } etb_ctrl_value |= 0x2; } if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED) { LOG_ERROR("ETB: can't run in multiplexed mode"); return ERROR_ETM_PORTMODE_NOT_SUPPORTED; } trigger_count = (etb->ram_depth * etb->trigger_percent) / 100; etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count); etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0); etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value); jtag_execute_queue(); /* we're starting a new trace, initialize capture status */ etm_ctx->capture_status = TRACE_RUNNING; return ERROR_OK; } static int etb_stop_capture(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; struct reg *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL]; etb_write_reg(etb_ctrl_reg, 0x0); jtag_execute_queue(); /* trace stopped, just clear running flag, but preserve others */ etm_ctx->capture_status &= ~TRACE_RUNNING; return ERROR_OK; } struct etm_capture_driver etb_capture_driver = { .name = "etb", .commands = etb_command_handlers, .init = etb_init, .status = etb_status, .start_capture = etb_start_capture, .stop_capture = etb_stop_capture, .read_trace = etb_read_trace, }; openocd-0.9.0/src/target/etb.h0000644000175000017500000000422112315575361013077 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ETB_H #define ETB_H /* ETB registers */ enum { ETB_ID = 0x00, ETB_RAM_DEPTH = 0x01, ETB_RAM_WIDTH = 0x02, ETB_STATUS = 0x03, ETB_RAM_DATA = 0x04, ETB_RAM_READ_POINTER = 0x05, ETB_RAM_WRITE_POINTER = 0x06, ETB_TRIGGER_COUNTER = 0x07, ETB_CTRL = 0x08, }; struct etb { struct etm_context *etm_ctx; struct jtag_tap *tap; uint32_t cur_scan_chain; struct reg_cache *reg_cache; /* ETB parameters */ uint32_t ram_depth; uint32_t ram_width; /** how much trace buffer to fill after trigger */ unsigned trigger_percent; }; struct etb_reg { uint32_t addr; struct etb *etb; }; extern struct etm_capture_driver etb_capture_driver; struct reg_cache *etb_build_reg_cache(struct etb *etb); #endif /* ETB_H */ openocd-0.9.0/src/target/etm.c0000644000175000017500000016156112516456304013116 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "etm.h" #include "etb.h" #include "image.h" #include "arm_disassembler.h" #include "register.h" #include "etm_dummy.h" #if BUILD_OOCD_TRACE == 1 #include "oocd_trace.h" #endif /* * ARM "Embedded Trace Macrocell" (ETM) support -- direct JTAG access. * * ETM modules collect instruction and/or data trace information, compress * it, and transfer it to a debugging host through either a (buffered) trace * port (often a 38-pin Mictor connector) or an Embedded Trace Buffer (ETB). * * There are several generations of these modules. Original versions have * JTAG access through a dedicated scan chain. Recent versions have added * access via coprocessor instructions, memory addressing, and the ARM Debug * Interface v5 (ADIv5); and phased out direct JTAG access. * * This code supports up to the ETMv1.3 architecture, as seen in ETM9 and * most common ARM9 systems. Note: "CoreSight ETM9" implements ETMv3.2, * implying non-JTAG connectivity options. * * Relevant documentation includes: * ARM DDI 0157G ... ETM9 (r2p2) Technical Reference Manual * ARM DDI 0315B ... CoreSight ETM9 (r0p1) Technical Reference Manual * ARM IHI 0014O ... Embedded Trace Macrocell, Architecture Specification */ enum { RO, /* read/only */ WO, /* write/only */ RW, /* read/write */ }; struct etm_reg_info { uint8_t addr; uint8_t size; /* low-N of 32 bits */ uint8_t mode; /* RO, WO, RW */ uint8_t bcd_vers; /* 1.0, 2.0, etc */ const char *name; }; /* * Registers 0..0x7f are JTAG-addressable using scanchain 6. * (Or on some processors, through coprocessor operations.) * Newer versions of ETM make some W/O registers R/W, and * provide definitions for some previously-unused bits. */ /* core registers used to version/configure the ETM */ static const struct etm_reg_info etm_core[] = { /* NOTE: we "know" the order here ... */ { ETM_CONFIG, 32, RO, 0x10, "ETM_config", }, { ETM_ID, 32, RO, 0x20, "ETM_id", }, }; /* basic registers that are always there given the right ETM version */ static const struct etm_reg_info etm_basic[] = { /* ETM Trace Registers */ { ETM_CTRL, 32, RW, 0x10, "ETM_ctrl", }, { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_trig_event", }, { ETM_ASIC_CTRL, 8, WO, 0x10, "ETM_asic_ctrl", }, { ETM_STATUS, 3, RO, 0x11, "ETM_status", }, { ETM_SYS_CONFIG, 9, RO, 0x12, "ETM_sys_config", }, /* TraceEnable configuration */ { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_trace_resource_ctrl", }, { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_trace_en_ctrl2", }, { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_trace_en_event", }, { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_trace_en_ctrl1", }, /* ViewData configuration (data trace) */ { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_viewdata_event", }, { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_viewdata_ctrl1", }, { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_viewdata_ctrl2", }, { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_viewdata_ctrl3", }, /* REVISIT exclude VIEWDATA_CTRL2 when it's not there */ { 0x78, 12, WO, 0x20, "ETM_sync_freq", }, { 0x7a, 22, RO, 0x31, "ETM_config_code_ext", }, { 0x7b, 32, WO, 0x31, "ETM_ext_input_select", }, { 0x7c, 32, WO, 0x34, "ETM_trace_start_stop", }, { 0x7d, 8, WO, 0x34, "ETM_behavior_control", }, }; static const struct etm_reg_info etm_fifofull[] = { /* FIFOFULL configuration */ { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_fifofull_region", }, { ETM_FIFOFULL_LEVEL, 8, WO, 0x10, "ETM_fifofull_level", }, }; static const struct etm_reg_info etm_addr_comp[] = { /* Address comparator register pairs */ #define ADDR_COMPARATOR(i) \ { ETM_ADDR_COMPARATOR_VALUE + (i) - 1, 32, WO, 0x10, \ "ETM_addr_" #i "_comparator_value", }, \ { ETM_ADDR_ACCESS_TYPE + (i) - 1, 7, WO, 0x10, \ "ETM_addr_" #i "_access_type", } ADDR_COMPARATOR(1), ADDR_COMPARATOR(2), ADDR_COMPARATOR(3), ADDR_COMPARATOR(4), ADDR_COMPARATOR(5), ADDR_COMPARATOR(6), ADDR_COMPARATOR(7), ADDR_COMPARATOR(8), ADDR_COMPARATOR(9), ADDR_COMPARATOR(10), ADDR_COMPARATOR(11), ADDR_COMPARATOR(12), ADDR_COMPARATOR(13), ADDR_COMPARATOR(14), ADDR_COMPARATOR(15), ADDR_COMPARATOR(16), { 0, 0, 0, 0, NULL } #undef ADDR_COMPARATOR }; static const struct etm_reg_info etm_data_comp[] = { /* Data Value Comparators (NOTE: odd addresses are reserved) */ #define DATA_COMPARATOR(i) \ { ETM_DATA_COMPARATOR_VALUE + 2*(i) - 1, 32, WO, 0x10, \ "ETM_data_" #i "_comparator_value", }, \ { ETM_DATA_COMPARATOR_MASK + 2*(i) - 1, 32, WO, 0x10, \ "ETM_data_" #i "_comparator_mask", } DATA_COMPARATOR(1), DATA_COMPARATOR(2), DATA_COMPARATOR(3), DATA_COMPARATOR(4), DATA_COMPARATOR(5), DATA_COMPARATOR(6), DATA_COMPARATOR(7), DATA_COMPARATOR(8), { 0, 0, 0, 0, NULL } #undef DATA_COMPARATOR }; static const struct etm_reg_info etm_counters[] = { #define ETM_COUNTER(i) \ { ETM_COUNTER_RELOAD_VALUE + (i) - 1, 16, WO, 0x10, \ "ETM_counter_" #i "_reload_value", }, \ { ETM_COUNTER_ENABLE + (i) - 1, 18, WO, 0x10, \ "ETM_counter_" #i "_enable", }, \ { ETM_COUNTER_RELOAD_EVENT + (i) - 1, 17, WO, 0x10, \ "ETM_counter_" #i "_reload_event", }, \ { ETM_COUNTER_VALUE + (i) - 1, 16, RO, 0x10, \ "ETM_counter_" #i "_value", } ETM_COUNTER(1), ETM_COUNTER(2), ETM_COUNTER(3), ETM_COUNTER(4), { 0, 0, 0, 0, NULL } #undef ETM_COUNTER }; static const struct etm_reg_info etm_sequencer[] = { #define ETM_SEQ(i) \ { ETM_SEQUENCER_EVENT + (i), 17, WO, 0x10, \ "ETM_sequencer_event" #i, } ETM_SEQ(0), /* 1->2 */ ETM_SEQ(1), /* 2->1 */ ETM_SEQ(2), /* 2->3 */ ETM_SEQ(3), /* 3->1 */ ETM_SEQ(4), /* 3->2 */ ETM_SEQ(5), /* 1->3 */ #undef ETM_SEQ /* 0x66 reserved */ { ETM_SEQUENCER_STATE, 2, RO, 0x10, "ETM_sequencer_state", }, }; static const struct etm_reg_info etm_outputs[] = { #define ETM_OUTPUT(i) \ { ETM_EXTERNAL_OUTPUT + (i) - 1, 17, WO, 0x10, \ "ETM_external_output" #i, } ETM_OUTPUT(1), ETM_OUTPUT(2), ETM_OUTPUT(3), ETM_OUTPUT(4), { 0, 0, 0, 0, NULL } #undef ETM_OUTPUT }; #if 0 /* registers from 0x6c..0x7f were added after ETMv1.3 */ /* Context ID Comparators */ { 0x6c, 32, RO, 0x20, "ETM_contextid_comparator_value1", } { 0x6d, 32, RO, 0x20, "ETM_contextid_comparator_value2", } { 0x6e, 32, RO, 0x20, "ETM_contextid_comparator_value3", } { 0x6f, 32, RO, 0x20, "ETM_contextid_comparator_mask", } #endif static int etm_get_reg(struct reg *reg); static int etm_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask); static int etm_register_user_commands(struct command_context *cmd_ctx); static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf); static int etm_write_reg(struct reg *reg, uint32_t value); static const struct reg_arch_type etm_scan6_type = { .get = etm_get_reg, .set = etm_set_reg_w_exec, }; /* Look up register by ID ... most ETM instances only * support a subset of the possible registers. */ static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id) { struct reg_cache *cache = etm_ctx->reg_cache; unsigned i; for (i = 0; i < cache->num_regs; i++) { struct etm_reg *reg = cache->reg_list[i].arch_info; if (reg->reg_info->addr == id) return &cache->reg_list[i]; } /* caller asking for nonexistent register is a bug! * REVISIT say which of the N targets was involved */ LOG_ERROR("ETM: register 0x%02x not available", id); return NULL; } static void etm_reg_add(unsigned bcd_vers, struct arm_jtag *jtag_info, struct reg_cache *cache, struct etm_reg *ereg, const struct etm_reg_info *r, unsigned nreg) { struct reg *reg = cache->reg_list; reg += cache->num_regs; ereg += cache->num_regs; /* add up to "nreg" registers from "r", if supported by this * version of the ETM, to the specified cache. */ for (; nreg--; r++) { /* No more registers to add */ if (!r->size) { LOG_ERROR("etm_reg_add is requested to add non-existing registers, ETM config might be bogus"); return; } /* this ETM may be too old to have some registers */ if (r->bcd_vers > bcd_vers) continue; reg->name = r->name; reg->size = r->size; reg->value = &ereg->value; reg->arch_info = ereg; reg->type = &etm_scan6_type; reg++; cache->num_regs++; ereg->reg_info = r; ereg->jtag_info = jtag_info; ereg++; } } struct reg_cache *etm_build_reg_cache(struct target *target, struct arm_jtag *jtag_info, struct etm_context *etm_ctx) { struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct etm_reg *arch_info = NULL; unsigned bcd_vers, config; /* the actual registers are kept in two arrays */ reg_list = calloc(128, sizeof(struct reg)); arch_info = calloc(128, sizeof(struct etm_reg)); /* fill in values for the reg cache */ reg_cache->name = "etm registers"; reg_cache->next = NULL; reg_cache->reg_list = reg_list; reg_cache->num_regs = 0; /* add ETM_CONFIG, then parse its values to see * which other registers exist in this ETM */ etm_reg_add(0x10, jtag_info, reg_cache, arch_info, etm_core, 1); etm_get_reg(reg_list); etm_ctx->config = buf_get_u32(arch_info->value, 0, 32); config = etm_ctx->config; /* figure ETM version then add base registers */ if (config & (1 << 31)) { LOG_WARNING("ETMv2+ support is incomplete"); /* REVISIT more registers may exist; they may now be * readable; more register bits have defined meanings; * don't presume trace start/stop support is present; * and include any context ID comparator registers. */ etm_reg_add(0x20, jtag_info, reg_cache, arch_info, etm_core + 1, 1); etm_get_reg(reg_list + 1); etm_ctx->id = buf_get_u32( arch_info[1].value, 0, 32); LOG_DEBUG("ETM ID: %08x", (unsigned) etm_ctx->id); bcd_vers = 0x10 + (((etm_ctx->id) >> 4) & 0xff); } else { switch (config >> 28) { case 7: case 5: case 3: bcd_vers = 0x13; break; case 4: case 2: bcd_vers = 0x12; break; case 1: bcd_vers = 0x11; break; case 0: bcd_vers = 0x10; break; default: LOG_WARNING("Bad ETMv1 protocol %d", config >> 28); goto fail; } } etm_ctx->bcd_vers = bcd_vers; LOG_INFO("ETM v%d.%d", bcd_vers >> 4, bcd_vers & 0xf); etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_basic, ARRAY_SIZE(etm_basic)); /* address and data comparators; counters; outputs */ etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_addr_comp, 4 * (0x0f & (config >> 0))); etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_data_comp, 2 * (0x0f & (config >> 4))); etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_counters, 4 * (0x07 & (config >> 13))); etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_outputs, (0x07 & (config >> 20))); /* FIFOFULL presence is optional * REVISIT for ETMv1.2 and later, don't bother adding this * unless ETM_SYS_CONFIG says it's also *supported* ... */ if (config & (1 << 23)) etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_fifofull, ARRAY_SIZE(etm_fifofull)); /* sequencer is optional (for state-dependant triggering) */ if (config & (1 << 16)) etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info, etm_sequencer, ARRAY_SIZE(etm_sequencer)); /* REVISIT could realloc and likely save half the memory * in the two chunks we allocated... */ /* the ETM might have an ETB connected */ if (strcmp(etm_ctx->capture_driver->name, "etb") == 0) { struct etb *etb = etm_ctx->capture_driver_priv; if (!etb) { LOG_ERROR("etb selected as etm capture driver, but no ETB configured"); goto fail; } reg_cache->next = etb_build_reg_cache(etb); etb->reg_cache = reg_cache->next; } etm_ctx->reg_cache = reg_cache; return reg_cache; fail: free(reg_cache); free(reg_list); free(arch_info); return NULL; } static int etm_read_reg(struct reg *reg) { return etm_read_reg_w_check(reg, NULL, NULL); } static int etm_store_reg(struct reg *reg) { return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size)); } int etm_setup(struct target *target) { int retval; uint32_t etm_ctrl_value; struct arm *arm = target_to_arm(target); struct etm_context *etm_ctx = arm->etm; struct reg *etm_ctrl_reg; etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL); if (!etm_ctrl_reg) return ERROR_OK; /* initialize some ETM control register settings */ etm_get_reg(etm_ctrl_reg); etm_ctrl_value = buf_get_u32(etm_ctrl_reg->value, 0, 32); /* clear the ETM powerdown bit (0) */ etm_ctrl_value &= ~ETM_CTRL_POWERDOWN; /* configure port width (21,6:4), mode (13,17:16) and * for older modules clocking (13) */ etm_ctrl_value = (etm_ctrl_value & ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_CTRL_DBGRQ & ~ETM_PORT_CLOCK_MASK) | etm_ctx->control; buf_set_u32(etm_ctrl_reg->value, 0, 32, etm_ctrl_value); etm_store_reg(etm_ctrl_reg); etm_ctx->control = etm_ctrl_value; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* REVISIT for ETMv3.0 and later, read ETM_sys_config to * verify that those width and mode settings are OK ... */ retval = etm_ctx->capture_driver->init(etm_ctx); if (retval != ERROR_OK) { LOG_ERROR("ETM capture driver initialization failed"); return retval; } return ERROR_OK; } static int etm_get_reg(struct reg *reg) { int retval; retval = etm_read_reg(reg); if (retval != ERROR_OK) { LOG_ERROR("BUG: error scheduling etm register read"); return retval; } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } return ERROR_OK; } static int etm_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask) { struct etm_reg *etm_reg = reg->arch_info; const struct etm_reg_info *r = etm_reg->reg_info; uint8_t reg_addr = r->addr & 0x7f; struct scan_field fields[3]; int retval; if (etm_reg->reg_info->mode == WO) { LOG_ERROR("BUG: can't read write-only register %s", r->name); return ERROR_COMMAND_SYNTAX_ERROR; } LOG_DEBUG("%s (%u)", r->name, reg_addr); retval = arm_jtag_scann(etm_reg->jtag_info, 0x6, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = reg->value; fields[0].in_value = NULL; fields[0].check_value = NULL; fields[0].check_mask = NULL; fields[1].num_bits = 7; uint8_t temp1; fields[1].out_value = &temp1; buf_set_u32(&temp1, 0, 7, reg_addr); fields[1].in_value = NULL; fields[1].check_value = NULL; fields[1].check_mask = NULL; fields[2].num_bits = 1; uint8_t temp2; fields[2].out_value = &temp2; buf_set_u32(&temp2, 0, 1, 0); fields[2].in_value = NULL; fields[2].check_value = NULL; fields[2].check_mask = NULL; jtag_add_dr_scan(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE); fields[0].in_value = reg->value; fields[0].check_value = check_value; fields[0].check_mask = check_mask; jtag_add_dr_scan_check(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE); return ERROR_OK; } static int etm_set_reg(struct reg *reg, uint32_t value) { int retval = etm_write_reg(reg, value); if (retval != ERROR_OK) { LOG_ERROR("BUG: error scheduling etm register write"); return retval; } buf_set_u32(reg->value, 0, reg->size, value); reg->valid = 1; reg->dirty = 0; return ERROR_OK; } static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf) { int retval; etm_set_reg(reg, buf_get_u32(buf, 0, reg->size)); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register write failed"); return retval; } return ERROR_OK; } static int etm_write_reg(struct reg *reg, uint32_t value) { struct etm_reg *etm_reg = reg->arch_info; const struct etm_reg_info *r = etm_reg->reg_info; uint8_t reg_addr = r->addr & 0x7f; struct scan_field fields[3]; int retval; if (etm_reg->reg_info->mode == RO) { LOG_ERROR("BUG: can't write read--only register %s", r->name); return ERROR_COMMAND_SYNTAX_ERROR; } LOG_DEBUG("%s (%u): 0x%8.8" PRIx32 "", r->name, reg_addr, value); retval = arm_jtag_scann(etm_reg->jtag_info, 0x6, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; uint8_t tmp1[4]; fields[0].out_value = tmp1; buf_set_u32(tmp1, 0, 32, value); fields[0].in_value = NULL; fields[1].num_bits = 7; uint8_t tmp2; fields[1].out_value = &tmp2; buf_set_u32(&tmp2, 0, 7, reg_addr); fields[1].in_value = NULL; fields[2].num_bits = 1; uint8_t tmp3; fields[2].out_value = &tmp3; buf_set_u32(&tmp3, 0, 1, 1); fields[2].in_value = NULL; jtag_add_dr_scan(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE); return ERROR_OK; } /* ETM trace analysis functionality */ static struct etm_capture_driver *etm_capture_drivers[] = { &etb_capture_driver, &etm_dummy_capture_driver, #if BUILD_OOCD_TRACE == 1 &oocd_trace_capture_driver, #endif NULL }; static int etm_read_instruction(struct etm_context *ctx, struct arm_instruction *instruction) { int i; int section = -1; size_t size_read; uint32_t opcode; int retval; if (!ctx->image) return ERROR_TRACE_IMAGE_UNAVAILABLE; /* search for the section the current instruction belongs to */ for (i = 0; i < ctx->image->num_sections; i++) { if ((ctx->image->sections[i].base_address <= ctx->current_pc) && (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc)) { section = i; break; } } if (section == -1) { /* current instruction couldn't be found in the image */ return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } if (ctx->core_state == ARM_STATE_ARM) { uint8_t buf[4]; retval = image_read_section(ctx->image, section, ctx->current_pc - ctx->image->sections[section].base_address, 4, buf, &size_read); if (retval != ERROR_OK) { LOG_ERROR("error while reading instruction"); return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } opcode = target_buffer_get_u32(ctx->target, buf); arm_evaluate_opcode(opcode, ctx->current_pc, instruction); } else if (ctx->core_state == ARM_STATE_THUMB) { uint8_t buf[2]; retval = image_read_section(ctx->image, section, ctx->current_pc - ctx->image->sections[section].base_address, 2, buf, &size_read); if (retval != ERROR_OK) { LOG_ERROR("error while reading instruction"); return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } opcode = target_buffer_get_u16(ctx->target, buf); thumb_evaluate_opcode(opcode, ctx->current_pc, instruction); } else if (ctx->core_state == ARM_STATE_JAZELLE) { LOG_ERROR("BUG: tracing of jazelle code not supported"); return ERROR_FAIL; } else { LOG_ERROR("BUG: unknown core state encountered"); return ERROR_FAIL; } return ERROR_OK; } static int etmv1_next_packet(struct etm_context *ctx, uint8_t *packet, int apo) { while (ctx->data_index < ctx->trace_depth) { /* if the caller specified an address packet offset, skip until the * we reach the n-th cycle marked with tracesync */ if (apo > 0) { if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE) apo--; if (apo > 0) { ctx->data_index++; ctx->data_half = 0; } continue; } /* no tracedata output during a TD cycle * or in a trigger cycle */ if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD) || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE)) { ctx->data_index++; ctx->data_half = 0; continue; } /* FIXME there are more port widths than these... */ if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT) { if (ctx->data_half == 0) { *packet = ctx->trace_data[ctx->data_index].packet & 0xff; ctx->data_half = 1; } else { *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8; ctx->data_half = 0; ctx->data_index++; } } else if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) { *packet = ctx->trace_data[ctx->data_index].packet & 0xff; ctx->data_index++; } else { /* on a 4-bit port, a packet will be output during two consecutive cycles */ if (ctx->data_index > (ctx->trace_depth - 2)) return -1; *packet = ctx->trace_data[ctx->data_index].packet & 0xf; *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4; ctx->data_index += 2; } return 0; } return -1; } static int etmv1_branch_address(struct etm_context *ctx) { int retval; uint8_t packet; int shift = 0; int apo; uint32_t i; /* quit analysis if less than two cycles are left in the trace * because we can't extract the APO */ if (ctx->data_index > (ctx->trace_depth - 2)) return -1; /* a BE could be output during an APO cycle, skip the current * and continue with the new one */ if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4) return 1; if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4) return 2; /* address packet offset encoded in the next two cycles' pipestat bits */ apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3; apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2; /* count number of tracesync cycles between current pipe_index and data_index * i.e. the number of tracesyncs that data_index already passed by * to subtract them from the APO */ for (i = ctx->pipe_index; i < ctx->data_index; i++) { if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE) apo--; } /* extract up to four 7-bit packets */ do { retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0); if (retval != 0) return -1; ctx->last_branch &= ~(0x7f << shift); ctx->last_branch |= (packet & 0x7f) << shift; shift += 7; } while ((packet & 0x80) && (shift < 28)); /* one last packet holding 4 bits of the address, plus the branch reason code */ if ((shift == 28) && (packet & 0x80)) { retval = etmv1_next_packet(ctx, &packet, 0); if (retval != 0) return -1; ctx->last_branch &= 0x0fffffff; ctx->last_branch |= (packet & 0x0f) << 28; ctx->last_branch_reason = (packet & 0x70) >> 4; shift += 4; } else ctx->last_branch_reason = 0; if (shift == 32) ctx->pc_ok = 1; /* if a full address was output, we might have branched into Jazelle state */ if ((shift == 32) && (packet & 0x80)) ctx->core_state = ARM_STATE_JAZELLE; else { /* if we didn't branch into Jazelle state, the current processor state is * encoded in bit 0 of the branch target address */ if (ctx->last_branch & 0x1) { ctx->core_state = ARM_STATE_THUMB; ctx->last_branch &= ~0x1; } else { ctx->core_state = ARM_STATE_ARM; ctx->last_branch &= ~0x3; } } return 0; } static int etmv1_data(struct etm_context *ctx, int size, uint32_t *data) { int j; uint8_t buf[4]; int retval; for (j = 0; j < size; j++) { retval = etmv1_next_packet(ctx, &buf[j], 0); if (retval != 0) return -1; } if (size == 8) { LOG_ERROR("TODO: add support for 64-bit values"); return -1; } else if (size == 4) *data = target_buffer_get_u32(ctx->target, buf); else if (size == 2) *data = target_buffer_get_u16(ctx->target, buf); else if (size == 1) *data = buf[0]; else return -1; return 0; } static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context *cmd_ctx) { int retval; struct arm_instruction instruction; /* read the trace data if it wasn't read already */ if (ctx->trace_depth == 0) ctx->capture_driver->read_trace(ctx); if (ctx->trace_depth == 0) { command_print(cmd_ctx, "Trace is empty."); return ERROR_OK; } /* start at the beginning of the captured trace */ ctx->pipe_index = 0; ctx->data_index = 0; ctx->data_half = 0; /* neither the PC nor the data pointer are valid */ ctx->pc_ok = 0; ctx->ptr_ok = 0; while (ctx->pipe_index < ctx->trace_depth) { uint8_t pipestat = ctx->trace_data[ctx->pipe_index].pipestat; uint32_t next_pc = ctx->current_pc; uint32_t old_data_index = ctx->data_index; uint32_t old_data_half = ctx->data_half; uint32_t old_index = ctx->pipe_index; uint32_t last_instruction = ctx->last_instruction; uint32_t cycles = 0; int current_pc_ok = ctx->pc_ok; if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE) command_print(cmd_ctx, "--- trigger ---"); /* instructions execute in IE/D or BE/D cycles */ if ((pipestat == STAT_IE) || (pipestat == STAT_ID)) ctx->last_instruction = ctx->pipe_index; /* if we don't have a valid pc skip until we reach an indirect branch */ if ((!ctx->pc_ok) && (pipestat != STAT_BE)) { ctx->pipe_index++; continue; } /* any indirect branch could have interrupted instruction flow * - the branch reason code could indicate a trace discontinuity * - a branch to the exception vectors indicates an exception */ if ((pipestat == STAT_BE) || (pipestat == STAT_BD)) { /* backup current data index, to be able to consume the branch address * before examining data address and values */ old_data_index = ctx->data_index; old_data_half = ctx->data_half; ctx->last_instruction = ctx->pipe_index; retval = etmv1_branch_address(ctx); if (retval != 0) { /* negative return value from etmv1_branch_address means we ran out of packets, * quit analysing the trace */ if (retval < 0) break; /* a positive return values means the current branch was abandoned, * and a new branch was encountered in cycle ctx->pipe_index + retval; */ LOG_WARNING( "abandoned branch encountered, correctness of analysis uncertain"); ctx->pipe_index += retval; continue; } /* skip over APO cycles */ ctx->pipe_index += 2; switch (ctx->last_branch_reason) { case 0x0: /* normal PC change */ next_pc = ctx->last_branch; break; case 0x1: /* tracing enabled */ command_print(cmd_ctx, "--- tracing enabled at 0x%8.8" PRIx32 " ---", ctx->last_branch); ctx->current_pc = ctx->last_branch; ctx->pipe_index++; continue; break; case 0x2: /* trace restarted after FIFO overflow */ command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8" PRIx32 " ---", ctx->last_branch); ctx->current_pc = ctx->last_branch; ctx->pipe_index++; continue; break; case 0x3: /* exit from debug state */ command_print(cmd_ctx, "--- exit from debug state at 0x%8.8" PRIx32 " ---", ctx->last_branch); ctx->current_pc = ctx->last_branch; ctx->pipe_index++; continue; break; case 0x4: /* periodic synchronization point */ next_pc = ctx->last_branch; /* if we had no valid PC prior to this synchronization point, * we have to move on with the next trace cycle */ if (!current_pc_ok) { command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8" PRIx32 " ---", next_pc); ctx->current_pc = next_pc; ctx->pipe_index++; continue; } break; default: /* reserved */ LOG_ERROR( "BUG: branch reason code 0x%" PRIx32 " is reserved", ctx->last_branch_reason); return ERROR_FAIL; } /* if we got here the branch was a normal PC change * (or a periodic synchronization point, which means the same for that matter) * if we didn't acquire a complete PC continue with the next cycle */ if (!ctx->pc_ok) continue; /* indirect branch to the exception vector means an exception occurred */ if ((ctx->last_branch <= 0x20) || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020))) { if ((ctx->last_branch & 0xff) == 0x10) command_print(cmd_ctx, "data abort"); else { command_print(cmd_ctx, "exception vector 0x%2.2" PRIx32 "", ctx->last_branch); ctx->current_pc = ctx->last_branch; ctx->pipe_index++; continue; } } } /* an instruction was executed (or not, depending on the condition flags) * retrieve it from the image for displaying */ if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) && !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) && ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4)))) { retval = etm_read_instruction(ctx, &instruction); if (retval != ERROR_OK) { /* can't continue tracing with no image available */ if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE) return retval; else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE) { /* TODO: handle incomplete images * for now we just quit the analysis*/ return retval; } } cycles = old_index - last_instruction; } if ((pipestat == STAT_ID) || (pipestat == STAT_BD)) { uint32_t new_data_index = ctx->data_index; uint32_t new_data_half = ctx->data_half; /* in case of a branch with data, the branch target address was consumed before * we temporarily go back to the saved data index */ if (pipestat == STAT_BD) { ctx->data_index = old_data_index; ctx->data_half = old_data_half; } if (ctx->control & ETM_CTRL_TRACE_ADDR) { uint8_t packet; int shift = 0; do { retval = etmv1_next_packet(ctx, &packet, 0); if (retval != 0) return ERROR_ETM_ANALYSIS_FAILED; ctx->last_ptr &= ~(0x7f << shift); ctx->last_ptr |= (packet & 0x7f) << shift; shift += 7; } while ((packet & 0x80) && (shift < 32)); if (shift >= 32) ctx->ptr_ok = 1; if (ctx->ptr_ok) command_print(cmd_ctx, "address: 0x%8.8" PRIx32 "", ctx->last_ptr); } if (ctx->control & ETM_CTRL_TRACE_DATA) { if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM)) { int i; for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple. register_list & (1 << i)) { uint32_t data; if (etmv1_data(ctx, 4, &data) != 0) return ERROR_ETM_ANALYSIS_FAILED; command_print(cmd_ctx, "data: 0x%8.8" PRIx32 "", data); } } } else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH)) { uint32_t data; if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0) return ERROR_ETM_ANALYSIS_FAILED; command_print(cmd_ctx, "data: 0x%8.8" PRIx32 "", data); } } /* restore data index after consuming BD address and data */ if (pipestat == STAT_BD) { ctx->data_index = new_data_index; ctx->data_half = new_data_half; } } /* adjust PC */ if ((pipestat == STAT_IE) || (pipestat == STAT_ID)) { if (((instruction.type == ARM_B) || (instruction.type == ARM_BL) || (instruction.type == ARM_BLX)) && (instruction.info.b_bl_bx_blx.target_address != 0xffffffff)) next_pc = instruction.info.b_bl_bx_blx.target_address; else next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2; } else if (pipestat == STAT_IN) next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2; if ((pipestat != STAT_TD) && (pipestat != STAT_WT)) { char cycles_text[32] = ""; /* if the trace was captured with cycle accurate tracing enabled, * output the number of cycles since the last executed instruction */ if (ctx->control & ETM_CTRL_CYCLE_ACCURATE) { snprintf(cycles_text, 32, " (%i %s)", (int)cycles, (cycles == 1) ? "cycle" : "cycles"); } command_print(cmd_ctx, "%s%s%s", instruction.text, (pipestat == STAT_IN) ? " (not executed)" : "", cycles_text); ctx->current_pc = next_pc; /* packets for an instruction don't start on or before the preceding * functional pipestat (i.e. other than WT or TD) */ if (ctx->data_index <= ctx->pipe_index) { ctx->data_index = ctx->pipe_index + 1; ctx->data_half = 0; } } ctx->pipe_index += 1; } return ERROR_OK; } static COMMAND_HELPER(handle_etm_tracemode_command_update, uint32_t *mode) { uint32_t tracemode; /* what parts of data access are traced? */ if (strcmp(CMD_ARGV[0], "none") == 0) tracemode = 0; else if (strcmp(CMD_ARGV[0], "data") == 0) tracemode = ETM_CTRL_TRACE_DATA; else if (strcmp(CMD_ARGV[0], "address") == 0) tracemode = ETM_CTRL_TRACE_ADDR; else if (strcmp(CMD_ARGV[0], "all") == 0) tracemode = ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR; else { command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } uint8_t context_id; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], context_id); switch (context_id) { case 0: tracemode |= ETM_CTRL_CONTEXTID_NONE; break; case 8: tracemode |= ETM_CTRL_CONTEXTID_8; break; case 16: tracemode |= ETM_CTRL_CONTEXTID_16; break; case 32: tracemode |= ETM_CTRL_CONTEXTID_32; break; default: command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[1]); return ERROR_COMMAND_SYNTAX_ERROR; } bool etmv1_cycle_accurate; COMMAND_PARSE_ENABLE(CMD_ARGV[2], etmv1_cycle_accurate); if (etmv1_cycle_accurate) tracemode |= ETM_CTRL_CYCLE_ACCURATE; bool etmv1_branch_output; COMMAND_PARSE_ENABLE(CMD_ARGV[3], etmv1_branch_output); if (etmv1_branch_output) tracemode |= ETM_CTRL_BRANCH_OUTPUT; /* IGNORED: * - CPRT tracing (coprocessor register transfers) * - debug request (causes debug entry on trigger) * - stall on FIFOFULL (preventing tracedata loss) */ *mode = tracemode; return ERROR_OK; } COMMAND_HANDLER(handle_etm_tracemode_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct etm_context *etm; if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm = arm->etm; if (!etm) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } uint32_t tracemode = etm->control; switch (CMD_ARGC) { case 0: break; case 4: CALL_COMMAND_HANDLER(handle_etm_tracemode_command_update, &tracemode); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } /** * todo: fail if parameters were invalid for this hardware, * or couldn't be written; display actual hardware state... */ command_print(CMD_CTX, "current tracemode configuration:"); switch (tracemode & ETM_CTRL_TRACE_MASK) { default: command_print(CMD_CTX, "data tracing: none"); break; case ETM_CTRL_TRACE_DATA: command_print(CMD_CTX, "data tracing: data only"); break; case ETM_CTRL_TRACE_ADDR: command_print(CMD_CTX, "data tracing: address only"); break; case ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR: command_print(CMD_CTX, "data tracing: address and data"); break; } switch (tracemode & ETM_CTRL_CONTEXTID_MASK) { case ETM_CTRL_CONTEXTID_NONE: command_print(CMD_CTX, "contextid tracing: none"); break; case ETM_CTRL_CONTEXTID_8: command_print(CMD_CTX, "contextid tracing: 8 bit"); break; case ETM_CTRL_CONTEXTID_16: command_print(CMD_CTX, "contextid tracing: 16 bit"); break; case ETM_CTRL_CONTEXTID_32: command_print(CMD_CTX, "contextid tracing: 32 bit"); break; } if (tracemode & ETM_CTRL_CYCLE_ACCURATE) command_print(CMD_CTX, "cycle-accurate tracing enabled"); else command_print(CMD_CTX, "cycle-accurate tracing disabled"); if (tracemode & ETM_CTRL_BRANCH_OUTPUT) command_print(CMD_CTX, "full branch address output enabled"); else command_print(CMD_CTX, "full branch address output disabled"); #define TRACEMODE_MASK ( \ ETM_CTRL_CONTEXTID_MASK \ | ETM_CTRL_BRANCH_OUTPUT \ | ETM_CTRL_CYCLE_ACCURATE \ | ETM_CTRL_TRACE_MASK \ ) /* only update ETM_CTRL register if tracemode changed */ if ((etm->control & TRACEMODE_MASK) != tracemode) { struct reg *etm_ctrl_reg; etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL); if (!etm_ctrl_reg) return ERROR_FAIL; etm->control &= ~TRACEMODE_MASK; etm->control |= tracemode & TRACEMODE_MASK; buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control); etm_store_reg(etm_ctrl_reg); /* invalidate old trace data */ etm->capture_status = TRACE_IDLE; if (etm->trace_depth > 0) { free(etm->trace_data); etm->trace_data = NULL; } etm->trace_depth = 0; } #undef TRACEMODE_MASK return ERROR_OK; } COMMAND_HANDLER(handle_etm_config_command) { struct target *target; struct arm *arm; uint32_t portmode = 0x0; struct etm_context *etm_ctx; int i; if (CMD_ARGC != 5) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[0]); if (!target) { LOG_ERROR("target '%s' not defined", CMD_ARGV[0]); return ERROR_FAIL; } arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "target '%s' is '%s'; not an ARM", target_name(target), target_type_name(target)); return ERROR_FAIL; } /* FIXME for ETMv3.0 and above -- and we don't yet know what ETM * version we'll be using!! -- so we can't know how to validate * params yet. "etm config" should likely be *AFTER* hookup... * * - Many more widths might be supported ... and we can easily * check whether our setting "took". * * - The "clock" and "mode" bits are interpreted differently. * See ARM IHI 0014O table 2-17 for the old behaviour, and * table 2-18 for the new. With ETB it's best to specify * "normal full" ... */ uint8_t port_width; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], port_width); switch (port_width) { /* before ETMv3.0 */ case 4: portmode |= ETM_PORT_4BIT; break; case 8: portmode |= ETM_PORT_8BIT; break; case 16: portmode |= ETM_PORT_16BIT; break; /* ETMv3.0 and later*/ case 24: portmode |= ETM_PORT_24BIT; break; case 32: portmode |= ETM_PORT_32BIT; break; case 48: portmode |= ETM_PORT_48BIT; break; case 64: portmode |= ETM_PORT_64BIT; break; case 1: portmode |= ETM_PORT_1BIT; break; case 2: portmode |= ETM_PORT_2BIT; break; default: command_print(CMD_CTX, "unsupported ETM port width '%s'", CMD_ARGV[1]); return ERROR_FAIL; } if (strcmp("normal", CMD_ARGV[2]) == 0) portmode |= ETM_PORT_NORMAL; else if (strcmp("multiplexed", CMD_ARGV[2]) == 0) portmode |= ETM_PORT_MUXED; else if (strcmp("demultiplexed", CMD_ARGV[2]) == 0) portmode |= ETM_PORT_DEMUXED; else { command_print(CMD_CTX, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", CMD_ARGV[2]); return ERROR_FAIL; } if (strcmp("half", CMD_ARGV[3]) == 0) portmode |= ETM_PORT_HALF_CLOCK; else if (strcmp("full", CMD_ARGV[3]) == 0) portmode |= ETM_PORT_FULL_CLOCK; else { command_print(CMD_CTX, "unsupported ETM port clocking '%s', must be 'full' or 'half'", CMD_ARGV[3]); return ERROR_FAIL; } etm_ctx = calloc(1, sizeof(struct etm_context)); if (!etm_ctx) { LOG_DEBUG("out of memory"); return ERROR_FAIL; } for (i = 0; etm_capture_drivers[i]; i++) { if (strcmp(CMD_ARGV[4], etm_capture_drivers[i]->name) == 0) { int retval = register_commands(CMD_CTX, NULL, etm_capture_drivers[i]->commands); if (ERROR_OK != retval) { free(etm_ctx); return retval; } etm_ctx->capture_driver = etm_capture_drivers[i]; break; } } if (!etm_capture_drivers[i]) { /* no supported capture driver found, don't register an ETM */ free(etm_ctx); LOG_ERROR("trace capture driver '%s' not found", CMD_ARGV[4]); return ERROR_FAIL; } etm_ctx->target = target; etm_ctx->trace_data = NULL; etm_ctx->control = portmode; etm_ctx->core_state = ARM_STATE_ARM; arm->etm = etm_ctx; return etm_register_user_commands(CMD_CTX); } COMMAND_HANDLER(handle_etm_info_command) { struct target *target; struct arm *arm; struct etm_context *etm; struct reg *etm_sys_config_reg; int max_port_size; uint32_t config; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm = arm->etm; if (!etm) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } command_print(CMD_CTX, "ETM v%d.%d", etm->bcd_vers >> 4, etm->bcd_vers & 0xf); command_print(CMD_CTX, "pairs of address comparators: %i", (int) (etm->config >> 0) & 0x0f); command_print(CMD_CTX, "data comparators: %i", (int) (etm->config >> 4) & 0x0f); command_print(CMD_CTX, "memory map decoders: %i", (int) (etm->config >> 8) & 0x1f); command_print(CMD_CTX, "number of counters: %i", (int) (etm->config >> 13) & 0x07); command_print(CMD_CTX, "sequencer %spresent", (int) (etm->config & (1 << 16)) ? "" : "not "); command_print(CMD_CTX, "number of ext. inputs: %i", (int) (etm->config >> 17) & 0x07); command_print(CMD_CTX, "number of ext. outputs: %i", (int) (etm->config >> 20) & 0x07); command_print(CMD_CTX, "FIFO full %spresent", (int) (etm->config & (1 << 23)) ? "" : "not "); if (etm->bcd_vers < 0x20) command_print(CMD_CTX, "protocol version: %i", (int) (etm->config >> 28) & 0x07); else { command_print(CMD_CTX, "coprocessor and memory access %ssupported", (etm->config & (1 << 26)) ? "" : "not "); command_print(CMD_CTX, "trace start/stop %spresent", (etm->config & (1 << 26)) ? "" : "not "); command_print(CMD_CTX, "number of context comparators: %i", (int) (etm->config >> 24) & 0x03); } /* SYS_CONFIG isn't present before ETMv1.2 */ etm_sys_config_reg = etm_reg_lookup(etm, ETM_SYS_CONFIG); if (!etm_sys_config_reg) return ERROR_OK; etm_get_reg(etm_sys_config_reg); config = buf_get_u32(etm_sys_config_reg->value, 0, 32); LOG_DEBUG("ETM SYS CONFIG %08x", (unsigned) config); max_port_size = config & 0x7; if (etm->bcd_vers >= 0x30) max_port_size |= (config >> 6) & 0x08; switch (max_port_size) { /* before ETMv3.0 */ case 0: max_port_size = 4; break; case 1: max_port_size = 8; break; case 2: max_port_size = 16; break; /* ETMv3.0 and later*/ case 3: max_port_size = 24; break; case 4: max_port_size = 32; break; case 5: max_port_size = 48; break; case 6: max_port_size = 64; break; case 8: max_port_size = 1; break; case 9: max_port_size = 2; break; default: LOG_ERROR("Illegal max_port_size"); return ERROR_FAIL; } command_print(CMD_CTX, "max. port size: %i", max_port_size); if (etm->bcd_vers < 0x30) { command_print(CMD_CTX, "half-rate clocking %ssupported", (config & (1 << 3)) ? "" : "not "); command_print(CMD_CTX, "full-rate clocking %ssupported", (config & (1 << 4)) ? "" : "not "); command_print(CMD_CTX, "normal trace format %ssupported", (config & (1 << 5)) ? "" : "not "); command_print(CMD_CTX, "multiplex trace format %ssupported", (config & (1 << 6)) ? "" : "not "); command_print(CMD_CTX, "demultiplex trace format %ssupported", (config & (1 << 7)) ? "" : "not "); } else { /* REVISIT show which size and format are selected ... */ command_print(CMD_CTX, "current port size %ssupported", (config & (1 << 10)) ? "" : "not "); command_print(CMD_CTX, "current trace format %ssupported", (config & (1 << 11)) ? "" : "not "); } if (etm->bcd_vers >= 0x21) command_print(CMD_CTX, "fetch comparisons %ssupported", (config & (1 << 17)) ? "not " : ""); command_print(CMD_CTX, "FIFO full %ssupported", (config & (1 << 8)) ? "" : "not "); return ERROR_OK; } COMMAND_HANDLER(handle_etm_status_command) { struct target *target; struct arm *arm; struct etm_context *etm; trace_status_t trace_status; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm = arm->etm; if (!etm) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } /* ETM status */ if (etm->bcd_vers >= 0x11) { struct reg *reg; reg = etm_reg_lookup(etm, ETM_STATUS); if (!reg) return ERROR_FAIL; if (etm_get_reg(reg) == ERROR_OK) { unsigned s = buf_get_u32(reg->value, 0, reg->size); command_print(CMD_CTX, "etm: %s%s%s%s", /* bit(1) == progbit */ (etm->bcd_vers >= 0x12) ? ((s & (1 << 1)) ? "disabled" : "enabled") : "?", ((s & (1 << 3)) && etm->bcd_vers >= 0x31) ? " triggered" : "", ((s & (1 << 2)) && etm->bcd_vers >= 0x12) ? " start/stop" : "", ((s & (1 << 0)) && etm->bcd_vers >= 0x11) ? " untraced-overflow" : ""); } /* else ignore and try showing trace port status */ } /* Trace Port Driver status */ trace_status = etm->capture_driver->status(etm); if (trace_status == TRACE_IDLE) command_print(CMD_CTX, "%s: idle", etm->capture_driver->name); else { static char *completed = " completed"; static char *running = " is running"; static char *overflowed = ", overflowed"; static char *triggered = ", triggered"; command_print(CMD_CTX, "%s: trace collection%s%s%s", etm->capture_driver->name, (trace_status & TRACE_RUNNING) ? running : completed, (trace_status & TRACE_OVERFLOWED) ? overflowed : "", (trace_status & TRACE_TRIGGERED) ? triggered : ""); if (etm->trace_depth > 0) { command_print(CMD_CTX, "%i frames of trace data read", (int)(etm->trace_depth)); } } return ERROR_OK; } COMMAND_HANDLER(handle_etm_image_command) { struct target *target; struct arm *arm; struct etm_context *etm_ctx; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } if (etm_ctx->image) { image_close(etm_ctx->image); free(etm_ctx->image); command_print(CMD_CTX, "previously loaded image found and closed"); } etm_ctx->image = malloc(sizeof(struct image)); etm_ctx->image->base_address_set = 0; etm_ctx->image->start_address_set = 0; /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { etm_ctx->image->base_address_set = 1; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], etm_ctx->image->base_address); } else etm_ctx->image->base_address_set = 0; if (image_open(etm_ctx->image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) { free(etm_ctx->image); etm_ctx->image = NULL; return ERROR_FAIL; } return ERROR_OK; } COMMAND_HANDLER(handle_etm_dump_command) { struct fileio file; struct target *target; struct arm *arm; struct etm_context *etm_ctx; uint32_t i; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } if (etm_ctx->capture_driver->status == TRACE_IDLE) { command_print(CMD_CTX, "trace capture wasn't enabled, no trace data captured"); return ERROR_OK; } if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING) { /* TODO: if on-the-fly capture is to be supported, this needs to be changed */ command_print(CMD_CTX, "trace capture not completed"); return ERROR_FAIL; } /* read the trace data if it wasn't read already */ if (etm_ctx->trace_depth == 0) etm_ctx->capture_driver->read_trace(etm_ctx); if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) return ERROR_FAIL; fileio_write_u32(&file, etm_ctx->capture_status); fileio_write_u32(&file, etm_ctx->control); fileio_write_u32(&file, etm_ctx->trace_depth); for (i = 0; i < etm_ctx->trace_depth; i++) { fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat); fileio_write_u32(&file, etm_ctx->trace_data[i].packet); fileio_write_u32(&file, etm_ctx->trace_data[i].flags); } fileio_close(&file); return ERROR_OK; } COMMAND_HANDLER(handle_etm_load_command) { struct fileio file; struct target *target; struct arm *arm; struct etm_context *etm_ctx; uint32_t i; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING) { command_print(CMD_CTX, "trace capture running, stop first"); return ERROR_FAIL; } if (fileio_open(&file, CMD_ARGV[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) return ERROR_FAIL; int filesize; int retval = fileio_size(&file, &filesize); if (retval != ERROR_OK) { fileio_close(&file); return retval; } if (filesize % 4) { command_print(CMD_CTX, "size isn't a multiple of 4, no valid trace data"); fileio_close(&file); return ERROR_FAIL; } if (etm_ctx->trace_depth > 0) { free(etm_ctx->trace_data); etm_ctx->trace_data = NULL; } { uint32_t tmp; fileio_read_u32(&file, &tmp); etm_ctx->capture_status = tmp; fileio_read_u32(&file, &tmp); etm_ctx->control = tmp; fileio_read_u32(&file, &etm_ctx->trace_depth); } etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth); if (etm_ctx->trace_data == NULL) { command_print(CMD_CTX, "not enough memory to perform operation"); fileio_close(&file); return ERROR_FAIL; } for (i = 0; i < etm_ctx->trace_depth; i++) { uint32_t pipestat, packet, flags; fileio_read_u32(&file, &pipestat); fileio_read_u32(&file, &packet); fileio_read_u32(&file, &flags); etm_ctx->trace_data[i].pipestat = pipestat & 0xff; etm_ctx->trace_data[i].packet = packet & 0xffff; etm_ctx->trace_data[i].flags = flags; } fileio_close(&file); return ERROR_OK; } COMMAND_HANDLER(handle_etm_start_command) { struct target *target; struct arm *arm; struct etm_context *etm_ctx; struct reg *etm_ctrl_reg; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } /* invalidate old tracing data */ etm_ctx->capture_status = TRACE_IDLE; if (etm_ctx->trace_depth > 0) { free(etm_ctx->trace_data); etm_ctx->trace_data = NULL; } etm_ctx->trace_depth = 0; etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL); if (!etm_ctrl_reg) return ERROR_FAIL; etm_get_reg(etm_ctrl_reg); /* Clear programming bit (10), set port selection bit (11) */ buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2); etm_store_reg(etm_ctrl_reg); jtag_execute_queue(); etm_ctx->capture_driver->start_capture(etm_ctx); return ERROR_OK; } COMMAND_HANDLER(handle_etm_stop_command) { struct target *target; struct arm *arm; struct etm_context *etm_ctx; struct reg *etm_ctrl_reg; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL); if (!etm_ctrl_reg) return ERROR_FAIL; etm_get_reg(etm_ctrl_reg); /* Set programming bit (10), clear port selection bit (11) */ buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1); etm_store_reg(etm_ctrl_reg); jtag_execute_queue(); etm_ctx->capture_driver->stop_capture(etm_ctx); return ERROR_OK; } COMMAND_HANDLER(handle_etm_trigger_debug_command) { struct target *target; struct arm *arm; struct etm_context *etm; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: %s isn't an ARM", target_name(target)); return ERROR_FAIL; } etm = arm->etm; if (!etm) { command_print(CMD_CTX, "ETM: no ETM configured for %s", target_name(target)); return ERROR_FAIL; } if (CMD_ARGC == 1) { struct reg *etm_ctrl_reg; bool dbgrq; etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL); if (!etm_ctrl_reg) return ERROR_FAIL; COMMAND_PARSE_ENABLE(CMD_ARGV[0], dbgrq); if (dbgrq) etm->control |= ETM_CTRL_DBGRQ; else etm->control &= ~ETM_CTRL_DBGRQ; /* etm->control will be written to hardware * the next time an "etm start" is issued. */ buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control); } command_print(CMD_CTX, "ETM: %s debug halt", (etm->control & ETM_CTRL_DBGRQ) ? "triggers" : "does not trigger"); return ERROR_OK; } COMMAND_HANDLER(handle_etm_analyze_command) { struct target *target; struct arm *arm; struct etm_context *etm_ctx; int retval; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "ETM: current target isn't an ARM"); return ERROR_FAIL; } etm_ctx = arm->etm; if (!etm_ctx) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } retval = etmv1_analyze_trace(etm_ctx, CMD_CTX); if (retval != ERROR_OK) { /* FIX! error should be reported inside etmv1_analyze_trace() */ switch (retval) { case ERROR_ETM_ANALYSIS_FAILED: command_print(CMD_CTX, "further analysis failed (corrupted trace data or just end of data"); break; case ERROR_TRACE_INSTRUCTION_UNAVAILABLE: command_print(CMD_CTX, "no instruction for current address available, analysis aborted"); break; case ERROR_TRACE_IMAGE_UNAVAILABLE: command_print(CMD_CTX, "no image available for trace analysis"); break; default: command_print(CMD_CTX, "unknown error"); } } return retval; } static const struct command_registration etm_config_command_handlers[] = { { /* NOTE: with ADIv5, ETMs are accessed by DAP operations, * possibly over SWD, not JTAG scanchain 6 of 'target'. * * Also, these parameters don't match ETM v3+ modules... */ .name = "config", .handler = handle_etm_config_command, .mode = COMMAND_CONFIG, .help = "Set up ETM output port.", .usage = "target port_width port_mode clocking capture_driver", }, COMMAND_REGISTRATION_DONE }; const struct command_registration etm_command_handlers[] = { { .name = "etm", .mode = COMMAND_ANY, .help = "Embedded Trace Macrocell command group", .usage = "", .chain = etm_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration etm_exec_command_handlers[] = { { .name = "tracemode", .handler = handle_etm_tracemode_command, .mode = COMMAND_EXEC, .help = "configure/display trace mode", .usage = "('none'|'data'|'address'|'all') " "context_id_bits " "['enable'|'disable'] " "['enable'|'disable']", }, { .name = "info", .handler = handle_etm_info_command, .mode = COMMAND_EXEC, .usage = "", .help = "display info about the current target's ETM", }, { .name = "status", .handler = handle_etm_status_command, .mode = COMMAND_EXEC, .usage = "", .help = "display current target's ETM status", }, { .name = "start", .handler = handle_etm_start_command, .mode = COMMAND_EXEC, .usage = "", .help = "start ETM trace collection", }, { .name = "stop", .handler = handle_etm_stop_command, .mode = COMMAND_EXEC, .usage = "", .help = "stop ETM trace collection", }, { .name = "trigger_debug", .handler = handle_etm_trigger_debug_command, .mode = COMMAND_EXEC, .help = "enable/disable debug entry on trigger", .usage = "['enable'|'disable']", }, { .name = "analyze", .handler = handle_etm_analyze_command, .mode = COMMAND_EXEC, .usage = "", .help = "analyze collected ETM trace", }, { .name = "image", .handler = handle_etm_image_command, .mode = COMMAND_EXEC, .help = "load image from file with optional offset", .usage = " [base address] [type]", }, { .name = "dump", .handler = handle_etm_dump_command, .mode = COMMAND_EXEC, .help = "dump captured trace data to file", .usage = "filename", }, { .name = "load", .handler = handle_etm_load_command, .mode = COMMAND_EXEC, .usage = "", .help = "load trace data for analysis ", }, COMMAND_REGISTRATION_DONE }; static int etm_register_user_commands(struct command_context *cmd_ctx) { struct command *etm_cmd = command_find_in_context(cmd_ctx, "etm"); return register_commands(cmd_ctx, etm_cmd, etm_exec_command_handlers); } openocd-0.9.0/src/target/etm.h0000644000175000017500000001750712516456304013123 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007 by Vincent Palatin * * vincent.palatin_openocd@m4x.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ETM_H #define ETM_H #include "trace.h" #include "arm_jtag.h" struct image; /* ETM registers (JTAG protocol) */ enum { ETM_CTRL = 0x00, ETM_CONFIG = 0x01, ETM_TRIG_EVENT = 0x02, ETM_ASIC_CTRL = 0x03, ETM_STATUS = 0x04, ETM_SYS_CONFIG = 0x05, ETM_TRACE_RESOURCE_CTRL = 0x06, ETM_TRACE_EN_CTRL2 = 0x07, ETM_TRACE_EN_EVENT = 0x08, ETM_TRACE_EN_CTRL1 = 0x09, /* optional FIFOFULL */ ETM_FIFOFULL_REGION = 0x0a, ETM_FIFOFULL_LEVEL = 0x0b, /* viewdata support */ ETM_VIEWDATA_EVENT = 0x0c, ETM_VIEWDATA_CTRL1 = 0x0d, ETM_VIEWDATA_CTRL2 = 0x0e, /* optional */ ETM_VIEWDATA_CTRL3 = 0x0f, /* N pairs of ADDR_{COMPARATOR,ACCESS} registers */ ETM_ADDR_COMPARATOR_VALUE = 0x10, ETM_ADDR_ACCESS_TYPE = 0x20, /* N pairs of DATA_COMPARATOR_{VALUE,MASK} registers */ ETM_DATA_COMPARATOR_VALUE = 0x30, ETM_DATA_COMPARATOR_MASK = 0x40, /* N quads of COUNTER_{RELOAD_{VALUE,EVENT},ENABLE,VALUE} registers */ ETM_COUNTER_RELOAD_VALUE = 0x50, ETM_COUNTER_ENABLE = 0x54, ETM_COUNTER_RELOAD_EVENT = 0x58, ETM_COUNTER_VALUE = 0x5c, /* 6 sequencer event transitions */ ETM_SEQUENCER_EVENT = 0x60, ETM_SEQUENCER_STATE = 0x67, /* N triggered outputs */ ETM_EXTERNAL_OUTPUT = 0x68, /* N task contexts */ ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c, ETM_CONTEXTID_COMPARATOR_MASK = 0x6f, ETM_ID = 0x79, }; struct etm_reg { uint8_t value[4]; const struct etm_reg_info *reg_info; struct arm_jtag *jtag_info; }; /* Subset of ETM_CTRL bit assignments. Many of these * control the configuration of trace output, which * hooks up either to ETB or to an external device. * * NOTE that these have evolved since the ~v1.3 defns ... */ enum { ETM_CTRL_POWERDOWN = (1 << 0), ETM_CTRL_MONITOR_CPRT = (1 << 1), /* bits 3:2 == trace type */ ETM_CTRL_TRACE_DATA = (1 << 2), ETM_CTRL_TRACE_ADDR = (2 << 2), ETM_CTRL_TRACE_MASK = (3 << 2), /* Port width (bits 21 and 6:4) */ ETM_PORT_4BIT = 0x00, ETM_PORT_8BIT = 0x10, ETM_PORT_16BIT = 0x20, ETM_PORT_24BIT = 0x30, ETM_PORT_32BIT = 0x40, ETM_PORT_48BIT = 0x50, ETM_PORT_64BIT = 0x60, ETM_PORT_1BIT = 0x00 | (1 << 21), ETM_PORT_2BIT = 0x10 | (1 << 21), ETM_PORT_WIDTH_MASK = 0x70 | (1 << 21), ETM_CTRL_FIFOFULL_STALL = (1 << 7), ETM_CTRL_BRANCH_OUTPUT = (1 << 8), ETM_CTRL_DBGRQ = (1 << 9), ETM_CTRL_ETM_PROG = (1 << 10), ETM_CTRL_ETMEN = (1 << 11), ETM_CTRL_CYCLE_ACCURATE = (1 << 12), /* Clocking modes -- up to v2.1, bit 13 */ ETM_PORT_FULL_CLOCK = (0 << 13), ETM_PORT_HALF_CLOCK = (1 << 13), ETM_PORT_CLOCK_MASK = (1 << 13), /* bits 15:14 == context ID size used in tracing */ ETM_CTRL_CONTEXTID_NONE = (0 << 14), ETM_CTRL_CONTEXTID_8 = (1 << 14), ETM_CTRL_CONTEXTID_16 = (2 << 14), ETM_CTRL_CONTEXTID_32 = (3 << 14), ETM_CTRL_CONTEXTID_MASK = (3 << 14), /* Port modes -- bits 17:16, tied to clocking mode */ ETM_PORT_NORMAL = (0 << 16), ETM_PORT_MUXED = (1 << 16), ETM_PORT_DEMUXED = (2 << 16), ETM_PORT_MODE_MASK = (3 << 16), /* bits 31:18 defined in v3.0 and later (e.g. ARM11+) */ }; /* forward-declare ETM context */ struct etm_context; struct etm_capture_driver { const char *name; const struct command_registration *commands; int (*init)(struct etm_context *etm_ctx); trace_status_t (*status)(struct etm_context *etm_ctx); int (*read_trace)(struct etm_context *etm_ctx); int (*start_capture)(struct etm_context *etm_ctx); int (*stop_capture)(struct etm_context *etm_ctx); }; enum { ETMV1_TRACESYNC_CYCLE = 0x1, ETMV1_TRIGGER_CYCLE = 0x2, }; struct etmv1_trace_data { uint8_t pipestat; /* bits 0-2 pipeline status */ uint16_t packet; /* packet data (4, 8 or 16 bit) */ int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */ }; /* describe a trace context * if support for ETMv2 or ETMv3 is to be implemented, * this will have to be split into version independent elements * and a version specific part */ struct etm_context { struct target *target; /* target this ETM is connected to */ struct reg_cache *reg_cache; /* ETM register cache */ struct etm_capture_driver *capture_driver; /* driver used to access ETM data */ void *capture_driver_priv; /* capture driver private data */ trace_status_t capture_status; /* current state of capture run */ struct etmv1_trace_data *trace_data; /* trace data */ uint32_t trace_depth; /* number of cycles to be analyzed, 0 if no data available */ uint32_t control; /* shadow of ETM_CTRL */ int /*arm_state*/ core_state; /* current core state */ struct image *image; /* source for target opcodes */ uint32_t pipe_index; /* current trace cycle */ uint32_t data_index; /* cycle holding next data packet */ bool data_half; /* port half on a 16 bit port */ bool pc_ok; /* full PC has been acquired */ bool ptr_ok; /* whether last_ptr is valid */ uint8_t bcd_vers; /* e.g. 0x13 == ETMv1.3 */ uint32_t config; /* cache of ETM_CONFIG value */ uint32_t id; /* cache of ETM_ID value, or 0 */ uint32_t current_pc; /* current program counter */ uint32_t last_branch; /* last branch address output */ uint32_t last_branch_reason; /* type of last branch encountered */ uint32_t last_ptr; /* address of the last data access */ uint32_t last_instruction; /* index of last executed (to calc timings) */ }; /* PIPESTAT values */ typedef enum { STAT_IE = 0x0, STAT_ID = 0x1, STAT_IN = 0x2, STAT_WT = 0x3, STAT_BE = 0x4, STAT_BD = 0x5, STAT_TR = 0x6, STAT_TD = 0x7 } etmv1_pipestat_t; /* branch reason values */ typedef enum { BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */ BR_ENABLE = 0x1, /* Trace has been enabled */ BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */ BR_NODEBUG = 0x3, /* ARM has exited for debug state */ BR_PERIOD = 0x4, /* Peridioc synchronization point (ETM >= v1.2)*/ BR_RSVD5 = 0x5, /* reserved */ BR_RSVD6 = 0x6, /* reserved */ BR_RSVD7 = 0x7, /* reserved */ } etmv1_branch_reason_t; struct reg_cache *etm_build_reg_cache(struct target *target, struct arm_jtag *jtag_info, struct etm_context *etm_ctx); int etm_setup(struct target *target); extern const struct command_registration etm_command_handlers[]; #define ERROR_ETM_INVALID_DRIVER (-1300) #define ERROR_ETM_PORTMODE_NOT_SUPPORTED (-1301) #define ERROR_ETM_CAPTURE_INIT_FAILED (-1302) #define ERROR_ETM_ANALYSIS_FAILED (-1303) #endif /* ETM_H */ openocd-0.9.0/src/target/arm11_dbgtap.c0000644000175000017500000010056512315712572014567 00000000000000/*************************************************************************** * Copyright (C) 2008 digenius technology GmbH. * * Michael Bruck * * * * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm_jtag.h" #include "arm11_dbgtap.h" #include #if 0 #define JTAG_DEBUG(expr ...) do { if (1) \ LOG_DEBUG(expr); } while (0) #else #define JTAG_DEBUG(expr ...) do { if (0) \ LOG_DEBUG(expr); } while (0) #endif /* This pathmove goes from Pause-IR to Shift-IR while avoiding RTI. The behavior of the FTDI driver IIRC was to go via RTI. Conversely there may be other places in this code where the ARM11 code relies on the driver to hit through RTI when coming from Update-?R. */ static const tap_state_t arm11_move_pi_to_si_via_ci[] = { TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT }; /* REVISIT no error handling here! */ static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields, tap_state_t state) { if (cmd_queue_cur_state == TAP_IRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci), arm11_move_pi_to_si_via_ci); jtag_add_ir_scan(tap, fields, state); } static const tap_state_t arm11_move_pd_to_sd_via_cd[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; /* REVISIT no error handling here! */ void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, tap_state_t state) { if (cmd_queue_cur_state == TAP_DRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd), arm11_move_pd_to_sd_via_cd); jtag_add_dr_scan(tap, num_fields, fields, state); } /** Code de-clutter: Construct struct scan_field to write out a value * * \param arm11 Target state variable. * \param num_bits Length of the data field * \param out_data pointer to the data that will be sent out * (data is read when it is added to the JTAG queue) * \param in_data pointer to the memory that will receive data that was clocked in * (data is written when the JTAG queue is executed) * \param field target data structure that will be initialized */ void arm11_setup_field(struct arm11_common *arm11, int num_bits, void *out_data, void *in_data, struct scan_field *field) { field->num_bits = num_bits; field->out_value = out_data; field->in_value = in_data; } static const char *arm11_ir_to_string(uint8_t ir) { const char *s = "unknown"; switch (ir) { case ARM11_EXTEST: s = "EXTEST"; break; case ARM11_SCAN_N: s = "SCAN_N"; break; case ARM11_RESTART: s = "RESTART"; break; case ARM11_HALT: s = "HALT"; break; case ARM11_INTEST: s = "INTEST"; break; case ARM11_ITRSEL: s = "ITRSEL"; break; case ARM11_IDCODE: s = "IDCODE"; break; case ARM11_BYPASS: s = "BYPASS"; break; } return s; } /** Write JTAG instruction register * * \param arm11 Target state variable. * \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions. * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default value (Pause-IR). * * \remarks This adds to the JTAG command queue but does \em not execute it. */ void arm11_add_IR(struct arm11_common *arm11, uint8_t instr, tap_state_t state) { struct jtag_tap *tap = arm11->arm.target->tap; if (buf_get_u32(tap->cur_instr, 0, 5) == instr) { JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr); return; } JTAG_DEBUG("IR <= %s (0x%02x)", arm11_ir_to_string(instr), instr); struct scan_field field; arm11_setup_field(arm11, 5, &instr, NULL, &field); arm11_add_ir_scan_vc(arm11->arm.target->tap, &field, state == ARM11_TAP_DEFAULT ? TAP_IRPAUSE : state); } /** Verify data shifted out from Scan Chain Register (SCREG). */ static void arm11_in_handler_SCAN_N(uint8_t *in_value) { /* Don't expect JTAG layer to modify bits we didn't ask it to read */ uint8_t v = *in_value & 0x1F; if (v != 0x10) { LOG_ERROR("'arm11 target' JTAG error SCREG OUT 0x%02x", v); jtag_set_error(ERROR_FAIL); } } /** Select and write to Scan Chain Register (SCREG) * * This function sets the instruction register to SCAN_N and writes * the data register with the selected chain number. * * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/Cacbjhfg.html * * \param arm11 Target state variable. * \param chain Scan chain that will be selected. * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default * value (Pause-DR). * * Changes the current scan chain if needed, transitions to the specified * TAP state, and leaves the IR undefined. * * The chain takes effect when Update-DR is passed (usually when subsequently * the INTEXT/EXTEST instructions are written). * * \warning (Obsolete) Using this twice in a row will \em fail. The first * call will end in Pause-DR. The second call, due to the IR * caching, will not go through Capture-DR when shifting in the * new scan chain number. As a result the verification in * arm11_in_handler_SCAN_N() must fail. * * \remarks This adds to the JTAG command queue but does \em not execute it. */ int arm11_add_debug_SCAN_N(struct arm11_common *arm11, uint8_t chain, tap_state_t state) { /* Don't needlessly switch the scan chain. * NOTE: the ITRSEL instruction fakes SCREG changing; * but leaves its actual value unchanged. */ #if 0 /* FIX!!! the optimization below is broken because we do not */ /* invalidate the cur_scan_chain upon a TRST/TMS. See arm_jtag.c */ /* for example on how to invalidate cur_scan_chain. Tested patches gladly */ /* accepted! */ if (arm11->jtag_info.cur_scan_chain == chain) { JTAG_DEBUG("SCREG <= %d SKIPPED", chain); return jtag_add_statemove((state == ARM11_TAP_DEFAULT) ? TAP_DRPAUSE : state); } #endif JTAG_DEBUG("SCREG <= %d", chain); arm11_add_IR(arm11, ARM11_SCAN_N, ARM11_TAP_DEFAULT); struct scan_field field; uint8_t tmp[1]; arm11_setup_field(arm11, 5, &chain, &tmp, &field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &field, state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state); jtag_execute_queue_noclear(); arm11_in_handler_SCAN_N(tmp); arm11->jtag_info.cur_scan_chain = chain; return jtag_execute_queue(); } /** * Queue a DR scan of the ITR register. Caller must have selected * scan chain 4 (ITR), possibly using ITRSEL. * * \param arm11 Target state variable. * \param inst An ARM11 processor instruction/opcode. * \param flag Optional parameter to retrieve the Ready flag; * this address will be written when the JTAG chain is scanned. * \param state The TAP state to enter after the DR scan. * * Going through the TAP_DRUPDATE state writes ITR only if Ready was * previously set. Only the Ready flag is readable by the scan. * * An instruction loaded into ITR is executed when going through the * TAP_IDLE state only if Ready was previously set and the debug state * is properly set up. Depending on the instruction, you may also need * to ensure that the rDTR is ready before that Run-Test/Idle state. */ static void arm11_add_debug_INST(struct arm11_common *arm11, uint32_t inst, uint8_t *flag, tap_state_t state) { JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst); struct scan_field itr[2]; arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(itr), itr, state); } /** * Read and save the Debug Status and Control Register (DSCR). * * \param arm11 Target state variable. * \return Error status; arm11->dscr is updated on success. * * \remarks This is a stand-alone function that executes the JTAG * command queue. It does not require the ARM11 debug TAP to be * in any particular state. */ int arm11_read_DSCR(struct arm11_common *arm11) { int retval; retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); uint32_t dscr; struct scan_field chain1_field; arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &chain1_field, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); if (arm11->dscr != dscr) JTAG_DEBUG("DSCR = %08x (OLD %08x)", (unsigned) dscr, (unsigned) arm11->dscr); arm11->dscr = dscr; return ERROR_OK; } /** Write the Debug Status and Control Register (DSCR) * * same as CP14 c1 * * \param arm11 Target state variable. * \param dscr DSCR content * * \remarks This is a stand-alone function that executes the JTAG command queue. */ int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr) { int retval; retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain1_field; arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &chain1_field, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DSCR <= %08x (OLD %08x)", (unsigned) dscr, (unsigned) arm11->dscr); arm11->dscr = dscr; return ERROR_OK; } /** Prepare the stage for ITR/DTR operations * from the arm11_run_instr... group of functions. * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Select scan chain 5 to allow quick access to DTR. When scan * chain 4 is needed to put in a register the ITRSel instruction * shortcut is used instead of actually changing the Scan_N * register. * * \param arm11 Target state variable. * */ int arm11_run_instr_data_prepare(struct arm11_common *arm11) { return arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); } /** Cleanup after ITR/DTR operations * from the arm11_run_instr... group of functions * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Any IDLE can lead to an instruction execution when * scan chains 4 or 5 are selected and the IR holds * INTEST or EXTEST. So we must disable that before * any following activities lead to an IDLE. * * \param arm11 Target state variable. * */ int arm11_run_instr_data_finish(struct arm11_common *arm11) { return arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT); } /** * Execute one or more instructions via ITR. * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode Pointer to sequence of ARM opcodes * \param count Number of opcodes to execute * */ static int arm11_run_instr_no_data(struct arm11_common *arm11, uint32_t *opcode, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); while (count--) { arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_IDLE); int i = 0; while (1) { uint8_t flag; arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_IDLE : TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); if (flag) break; long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING( "Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } } return ERROR_OK; } /** Execute one instruction via ITR * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * */ int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode) { return arm11_run_instr_no_data(arm11, &opcode, 1); } /** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * The executed instruction \em must read data from DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Pointer to the data words to be passed to the core * \param count Number of data words and instruction repetitions * */ int arm11_run_instr_data_to_core(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; uint32_t Data; uint8_t Ready; uint8_t nRetry; arm11_setup_field(arm11, 32, &Data, NULL, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2); while (count--) { int i = 0; do { Data = *data; arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DTR Ready %d nRetry %d", Ready, nRetry); long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING( "Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } while (!Ready); data++; } arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); int i = 0; do { Data = 0; arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", (unsigned) Data, Ready, nRetry); long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } while (!Ready); return ERROR_OK; } /** JTAG path for arm11_run_instr_data_to_core_noack * * The repeated TAP_IDLE's do not cause a repeated execution * if passed without leaving the state. * * Since this is more than 7 bits (adjustable via adding more * TAP_IDLE's) it produces an artificial delay in the lower * layer (FT2232) that is long enough to finish execution on * the core but still shorter than any manually inducible delays. * * To disable this code, try "memwrite burst false" * * FIX!!! should we use multiple TAP_IDLE here or not??? * * https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html * https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html */ static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; /* This inner loop can be implemented by the minidriver, oftentimes in hardware... The * minidriver can call the default implementation as a fallback or implement it * from scratch. */ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap, uint32_t opcode, uint32_t *data, size_t count) { struct scan_field chain5_fields[3]; chain5_fields[0].num_bits = 32; chain5_fields[0].out_value = NULL; /*&Data*/ chain5_fields[0].in_value = NULL; chain5_fields[1].num_bits = 1; chain5_fields[1].out_value = NULL; chain5_fields[1].in_value = NULL; /*&Ready*/ chain5_fields[2].num_bits = 1; chain5_fields[2].out_value = NULL; chain5_fields[2].in_value = NULL; uint8_t *Readies; unsigned readiesNum = count; unsigned bytes = sizeof(*Readies)*readiesNum; Readies = malloc(bytes); if (Readies == NULL) { LOG_ERROR("Out of memory allocating %u bytes", bytes); return ERROR_FAIL; } uint8_t *ReadyPos = Readies; while (count--) { chain5_fields[0].out_value = (uint8_t *)(data++); chain5_fields[1].in_value = ReadyPos++; if (count > 0) { jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); } else jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE); } int retval = jtag_execute_queue(); if (retval == ERROR_OK) { unsigned error_count = 0; for (size_t i = 0; i < readiesNum; i++) { if (Readies[i] != 1) error_count++; } if (error_count > 0) { LOG_ERROR("%u words out of %u not transferred", error_count, readiesNum); retval = ERROR_FAIL; } } free(Readies); return retval; } int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode, uint32_t *data, size_t count); #ifndef HAVE_JTAG_MINIDRIVER_H int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode, uint32_t *data, size_t count) { return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count); } #endif /** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * No Ready check during transmission. * * The executed instruction \em must read data from DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Pointer to the data words to be passed to the core * \param count Number of data words and instruction repetitions * */ int arm11_run_instr_data_to_core_noack(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); int retval = arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap, opcode, data, count); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; arm11_setup_field(arm11, 32, NULL /*&Data*/, NULL, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, NULL /*&Ready*/, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); uint8_t ready_flag; chain5_fields[1].in_value = &ready_flag; arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, TAP_DRPAUSE); retval = jtag_execute_queue(); if (retval == ERROR_OK) { if (ready_flag != 1) { LOG_ERROR("last word not transferred"); retval = ERROR_FAIL; } } return retval; } /** Execute an instruction via ITR while handing data into the core via DTR. * * The executed instruction \em must read data from DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Data word to be passed to the core via DTR * */ int arm11_run_instr_data_to_core1(struct arm11_common *arm11, uint32_t opcode, uint32_t data) { return arm11_run_instr_data_to_core(arm11, opcode, &data, 1); } /** Execute one instruction via ITR repeatedly while * reading data from the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * The executed instruction \em must write data to DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Pointer to an array that receives the data words from the core * \param count Number of data words and instruction repetitions * */ int arm11_run_instr_data_from_core(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_IDLE); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; uint32_t Data; uint8_t Ready; uint8_t nRetry; arm11_setup_field(arm11, 32, NULL, &Data, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2); while (count--) { int i = 0; do { arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, count ? TAP_IDLE : TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", (unsigned) Data, Ready, nRetry); long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING( "Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } while (!Ready); *data++ = Data; } return ERROR_OK; } /** Execute one instruction via ITR * then load r0 into DTR and read DTR from core. * * The first executed instruction (\p opcode) should write data to r0. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode to write r0 with the value of interest * \param data Pointer to a data word that receives the value from r0 after \p opcode was executed. * */ int arm11_run_instr_data_from_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t *data) { int retval; retval = arm11_run_instr_no_data1(arm11, opcode); if (retval != ERROR_OK) return retval; /* MCR p14,0,R0,c0,c5,0 (move r0 -> wDTR -> local var) */ arm11_run_instr_data_from_core(arm11, 0xEE000E15, data, 1); return ERROR_OK; } /** Load data into core via DTR then move it to r0 then * execute one instruction via ITR * * The final executed instruction (\p opcode) should read data from r0. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode to read r0 act upon it * \param data Data word that will be written to r0 before \p opcode is executed * */ int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data) { int retval; /* MRC p14,0,r0,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xEE100E15, data); if (retval != ERROR_OK) return retval; retval = arm11_run_instr_no_data1(arm11, opcode); if (retval != ERROR_OK) return retval; return ERROR_OK; } /** Apply reads and writes to scan chain 7 * * \see struct arm11_sc7_action * * \param arm11 Target state variable. * \param actions A list of read and/or write instructions * \param count Number of instructions in the list. * */ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, size_t count) { int retval; retval = arm11_add_debug_SCAN_N(arm11, 0x07, ARM11_TAP_DEFAULT); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain7_fields[3]; uint8_t nRW; uint32_t DataOut; uint8_t AddressOut; uint8_t Ready; uint32_t DataIn; uint8_t AddressIn; arm11_setup_field(arm11, 1, &nRW, &Ready, chain7_fields + 0); arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1); arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2); for (size_t i = 0; i < count + 1; i++) { if (i < count) { nRW = actions[i].write ? 1 : 0; DataOut = actions[i].value; AddressOut = actions[i].address; } else { nRW = 1; DataOut = 0; AddressOut = 0; } /* Timeout here so we don't get stuck. */ int i_n = 0; while (1) { JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", (unsigned) AddressOut, (unsigned) DataOut, nRW ? "write" : "read"); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain7_fields), chain7_fields, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); /* 'nRW' is 'Ready' on read out */ if (Ready) break; long long then = 0; if (i_n == 1000) then = timeval_ms(); if (i_n >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING( "Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i_n++; } if (!nRW) JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn); if (i > 0) { if (actions[i - 1].address != AddressIn) LOG_WARNING("Scan chain 7 shifted out unexpected address"); if (!actions[i - 1].write) actions[i - 1].value = DataIn; else { if (actions[i - 1].value != DataIn) LOG_WARNING("Scan chain 7 shifted out unexpected data"); } } } return ERROR_OK; } /** Clear VCR and all breakpoints and watchpoints via scan chain 7 * * \param arm11 Target state variable. * */ int arm11_sc7_clear_vbw(struct arm11_common *arm11) { size_t clear_bw_size = arm11->brp + 1; struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size); struct arm11_sc7_action *pos = clear_bw; for (size_t i = 0; i < clear_bw_size; i++) { clear_bw[i].write = true; clear_bw[i].value = 0; } for (size_t i = 0; i < arm11->brp; i++) (pos++)->address = ARM11_SC7_BCR0 + i; (pos++)->address = ARM11_SC7_VCR; int retval; retval = arm11_sc7_run(arm11, clear_bw, clear_bw_size); free(clear_bw); return retval; } /** Write VCR register * * \param arm11 Target state variable. * \param value Value to be written */ int arm11_sc7_set_vcr(struct arm11_common *arm11, uint32_t value) { struct arm11_sc7_action set_vcr; set_vcr.write = true; set_vcr.address = ARM11_SC7_VCR; set_vcr.value = value; return arm11_sc7_run(arm11, &set_vcr, 1); } /** Read word from address * * \param arm11 Target state variable. * \param address Memory address to be read * \param result Pointer where to store result * */ int arm11_read_memory_word(struct arm11_common *arm11, uint32_t address, uint32_t *result) { int retval; retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* MRC p14,0,r0,c0,c5,0 (r0 = address) */ CHECK_RETVAL(arm11_run_instr_data_to_core1(arm11, 0xee100e15, address)); /* LDC p14,c5,[R0],#4 (DTR = [r0]) */ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xecb05e01, result, 1)); return arm11_run_instr_data_finish(arm11); } /************************************************************************/ /* * ARM11 provider for the OpenOCD implementation of the standard * architectural ARM v6/v7 "Debug Programmer's Model" (DPM). */ static inline struct arm11_common *dpm_to_arm11(struct arm_dpm *dpm) { return container_of(dpm, struct arm11_common, dpm); } static int arm11_dpm_prepare(struct arm_dpm *dpm) { return arm11_run_instr_data_prepare(dpm_to_arm11(dpm)); } static int arm11_dpm_finish(struct arm_dpm *dpm) { return arm11_run_instr_data_finish(dpm_to_arm11(dpm)); } static int arm11_dpm_instr_write_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { return arm11_run_instr_data_to_core(dpm_to_arm11(dpm), opcode, &data, 1); } static int arm11_dpm_instr_write_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { return arm11_run_instr_data_to_core_via_r0(dpm_to_arm11(dpm), opcode, data); } static int arm11_dpm_instr_read_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { return arm11_run_instr_data_from_core(dpm_to_arm11(dpm), opcode, data, 1); } static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { return arm11_run_instr_data_from_core_via_r0(dpm_to_arm11(dpm), opcode, data); } /* Because arm11_sc7_run() takes a vector of actions, we batch breakpoint * and watchpoint operations instead of running them right away. Since we * pre-allocated our vector, we don't need to worry about space. */ static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, uint32_t addr, uint32_t control) { struct arm11_common *arm11 = dpm_to_arm11(dpm); struct arm11_sc7_action *action; action = arm11->bpwp_actions + arm11->bpwp_n; /* Invariant: this bp/wp is disabled. * It also happens that the core is halted here, but for * DPM-based cores we don't actually care about that. */ action[0].write = action[1].write = true; action[0].value = addr; action[1].value = control; switch (index_t) { case 0 ... 15: action[0].address = ARM11_SC7_BVR0 + index_t; action[1].address = ARM11_SC7_BCR0 + index_t; break; case 16 ... 32: index_t -= 16; action[0].address = ARM11_SC7_WVR0 + index_t; action[1].address = ARM11_SC7_WCR0 + index_t; break; default: return ERROR_FAIL; } arm11->bpwp_n += 2; return ERROR_OK; } static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) { struct arm11_common *arm11 = dpm_to_arm11(dpm); struct arm11_sc7_action *action; action = arm11->bpwp_actions + arm11->bpwp_n; action[0].write = true; action[0].value = 0; switch (index_t) { case 0 ... 15: action[0].address = ARM11_SC7_BCR0 + index_t; break; case 16 ... 32: index_t -= 16; action[0].address = ARM11_SC7_WCR0 + index_t; break; default: return ERROR_FAIL; } arm11->bpwp_n += 1; return ERROR_OK; } /** Flush any pending breakpoint and watchpoint updates. */ int arm11_bpwp_flush(struct arm11_common *arm11) { int retval; if (!arm11->bpwp_n) return ERROR_OK; retval = arm11_sc7_run(arm11, arm11->bpwp_actions, arm11->bpwp_n); arm11->bpwp_n = 0; return retval; } /** Set up high-level debug module utilities */ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr) { struct arm_dpm *dpm = &arm11->dpm; int retval; dpm->arm = &arm11->arm; dpm->didr = didr; dpm->prepare = arm11_dpm_prepare; dpm->finish = arm11_dpm_finish; dpm->instr_write_data_dcc = arm11_dpm_instr_write_data_dcc; dpm->instr_write_data_r0 = arm11_dpm_instr_write_data_r0; dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc; dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0; dpm->bpwp_enable = arm11_bpwp_enable; dpm->bpwp_disable = arm11_bpwp_disable; retval = arm_dpm_setup(dpm); if (retval != ERROR_OK) return retval; /* alloc enough to enable all breakpoints and watchpoints at once */ arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp), sizeof *arm11->bpwp_actions); if (!arm11->bpwp_actions) return ERROR_FAIL; retval = arm_dpm_initialize(dpm); if (retval != ERROR_OK) return retval; return arm11_bpwp_flush(arm11); } openocd-0.9.0/src/target/arm11_dbgtap.h0000644000175000017500000000761612315575361014602 00000000000000/*************************************************************************** * Copyright (C) 2008 digenius technology GmbH. * * Michael Bruck * * * * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM11_DBGTAP_H #define ARM11_DBGTAP_H #include "arm11.h" /* ARM11 internals */ void arm11_setup_field(struct arm11_common *arm11, int num_bits, void *in_data, void *out_data, struct scan_field *field); void arm11_add_IR(struct arm11_common *arm11, uint8_t instr, tap_state_t state); int arm11_add_debug_SCAN_N(struct arm11_common *arm11, uint8_t chain, tap_state_t state); int arm11_read_DSCR(struct arm11_common *arm11); int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr); int arm11_run_instr_data_prepare(struct arm11_common *arm11); int arm11_run_instr_data_finish(struct arm11_common *arm11); int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode); int arm11_run_instr_data_to_core(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count); int arm11_run_instr_data_to_core_noack(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count); int arm11_run_instr_data_to_core1(struct arm11_common *arm11, uint32_t opcode, uint32_t data); int arm11_run_instr_data_from_core(struct arm11_common *arm11, uint32_t opcode, uint32_t *data, size_t count); int arm11_run_instr_data_from_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t *data); int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data); void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, tap_state_t state); /** * Used with arm11_sc7_run to make a list of read/write commands for * scan chain 7 */ struct arm11_sc7_action { bool write; /**< Access mode: true for write, false for read. */ uint8_t address;/**< Register address mode. Use enum #arm11_sc7 */ /** * If write then set this to value to be written. In read mode * this receives the read value when the function returns. */ uint32_t value; }; int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, size_t count); /* Mid-level helper functions */ int arm11_sc7_clear_vbw(struct arm11_common *arm11); int arm11_sc7_set_vcr(struct arm11_common *arm11, uint32_t value); int arm11_read_memory_word(struct arm11_common *arm11, uint32_t address, uint32_t *result); int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr); int arm11_bpwp_flush(struct arm11_common *arm11); #endif /* ARM11_DBGTAP_H */ openocd-0.9.0/src/target/smp.c0000644000175000017500000001113712516456304013121 00000000000000/*************************************************************************** * * * Copyright (C) ST-Ericsson SA 2011 * * Author: Michel Jaouen for ST-Ericsson. * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "server/server.h" #include "target/target.h" #include "server/gdb_server.h" #include "smp.h" #include "helper/binarybuffer.h" /* implementation of new packet in gdb interface for smp feature */ /* */ /* j : smp status request */ /* J : smp set request */ /* */ /* jc :read core id displayed by gdb connection */ /* reply XXXXXXXX core id is int32_t , 8 hex digits */ /* */ /* Reply ENN error not supported (target not smp) */ /* */ /* JcXX set core id displayed at next gdb continue */ /* maximum 8 bytes described core id int32_t (8 hex digits) */ /* (core id -1 , reserved for returning to normal continue mode) */ /* Reply ENN error not supported(target not smp,core id out of range) */ /* Reply OK : for success */ /* */ /* handling of this packet within gdb can be done by the creation */ /* internal variable by mean of function allocate_computed_value */ /* set $_core 1 => Jc01 packet is sent */ /* print $_core => jc packet is sent and result is affected in $ */ /* Another way to test this packet is the usage of maintenance packet */ /* maint packet Jc01 */ /* maint packet jc */ /* packet j :smp status request */ int gdb_read_smp_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); int retval = ERROR_OK; if (target->smp) { if (strncmp(packet, "jc", 2) == 0) { const uint32_t len = sizeof(target->gdb_service->core[0]); char hex_buffer[len * 2 + 1]; uint8_t buffer[len]; buf_set_u32(buffer, 0, len * 8, target->gdb_service->core[0]); int pkt_len = hexify(hex_buffer, (char *)buffer, sizeof(buffer), sizeof(hex_buffer)); retval = gdb_put_packet(connection, hex_buffer, pkt_len); } } else retval = gdb_put_packet(connection, "E01", 3); return retval; } /* J : smp set request */ int gdb_write_smp_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); char *separator; int coreid = 0; int retval = ERROR_OK; /* skip command character */ if (target->smp) { if (strncmp(packet, "Jc", 2) == 0) { packet += 2; coreid = strtoul(packet, &separator, 16); target->gdb_service->core[1] = coreid; retval = gdb_put_packet(connection, "OK", 2); } } else retval = gdb_put_packet(connection, "E01", 3); return retval; } openocd-0.9.0/src/target/smp.h0000644000175000017500000000322512315575361013127 00000000000000/*************************************************************************** * * * Copyright (C) ST-Ericsson SA 2011 * * Author: Michel Jaouen for ST-Ericsson. * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "server/server.h" int gdb_read_smp_packet(struct connection *connection, char const *packet, int packet_size); int gdb_write_smp_packet(struct connection *connection, char const *packet, int packet_size); openocd-0.9.0/src/target/arm920t.c0000644000175000017500000013565712315575361013540 00000000000000 /*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm920t.h" #include #include "target_type.h" #include "register.h" #include "arm_opcodes.h" /* * For information about the ARM920T, see ARM DDI 0151C especially * Chapter 9 about debug support, which shows how to manipulate each * of the different scan chains: * * 0 ... ARM920 signals, e.g. to rest of SOC (unused here) * 1 ... debugging; watchpoint and breakpoint status, etc; also * MMU and cache access in conjunction with scan chain 15 * 2 ... EmbeddedICE * 3 ... external boundary scan (SoC-specific, unused here) * 4 ... access to cache tag RAM * 6 ... ETM9 * 15 ... access coprocessor 15, "physical" or "interpreted" modes * "interpreted" works with a few actual MRC/MCR instructions * "physical" provides register-like behaviors. Section 9.6.7 * covers these details. * * The ARM922T is similar, but with smaller caches (8K each, vs 16K). */ #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif /* Table 9-8 shows scan chain 15 format during physical access mode, using a * dedicated 6-bit address space (encoded in bits 33:38). Writes use one * JTAG scan, while reads use two. * * Table 9-9 lists the thirteen registers which support physical access. * ARM920T_CP15_PHYS_ADDR() constructs the 6-bit reg_addr parameter passed * to arm920t_read_cp15_physical() and arm920t_write_cp15_physical(). * * x == bit[38] * y == bits[37:34] * z == bit[33] */ #define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z)) /* Registers supporting physical Read access (from table 9-9) */ #define CP15PHYS_CACHETYPE ARM920T_CP15_PHYS_ADDR(0, 0x0, 1) #define CP15PHYS_ICACHE_IDX ARM920T_CP15_PHYS_ADDR(1, 0xd, 1) #define CP15PHYS_DCACHE_IDX ARM920T_CP15_PHYS_ADDR(1, 0xe, 1) /* NOTE: several more registers support only physical read access */ /* Registers supporting physical Read/Write access (from table 9-9) */ #define CP15PHYS_CTRL ARM920T_CP15_PHYS_ADDR(0, 0x1, 0) #define CP15PHYS_PID ARM920T_CP15_PHYS_ADDR(0, 0xd, 0) #define CP15PHYS_TESTSTATE ARM920T_CP15_PHYS_ADDR(0, 0xf, 0) #define CP15PHYS_ICACHE ARM920T_CP15_PHYS_ADDR(1, 0x1, 1) #define CP15PHYS_DCACHE ARM920T_CP15_PHYS_ADDR(1, 0x2, 1) static int arm920t_read_cp15_physical(struct target *target, int reg_addr, uint32_t *value) { struct arm920t_common *arm920t = target_to_arm920(target); struct arm_jtag *jtag_info; struct scan_field fields[4]; uint8_t access_type_buf = 1; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 0; int retval; jtag_info = &arm920t->arm7_9_common.jtag_info; retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 1; fields[0].out_value = &access_type_buf; fields[0].in_value = NULL; fields[1].num_bits = 32; fields[1].out_value = NULL; fields[1].in_value = NULL; fields[2].num_bits = 6; fields[2].out_value = ®_addr_buf; fields[2].in_value = NULL; fields[3].num_bits = 1; fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); fields[1].in_value = (uint8_t *)value; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ jtag_execute_queue(); LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value); #endif return ERROR_OK; } static int arm920t_write_cp15_physical(struct target *target, int reg_addr, uint32_t value) { struct arm920t_common *arm920t = target_to_arm920(target); struct arm_jtag *jtag_info; struct scan_field fields[4]; uint8_t access_type_buf = 1; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 1; uint8_t value_buf[4]; int retval; jtag_info = &arm920t->arm7_9_common.jtag_info; buf_set_u32(value_buf, 0, 32, value); retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 1; fields[0].out_value = &access_type_buf; fields[0].in_value = NULL; fields[1].num_bits = 32; fields[1].out_value = value_buf; fields[1].in_value = NULL; fields[2].num_bits = 6; fields[2].out_value = ®_addr_buf; fields[2].in_value = NULL; fields[3].num_bits = 1; fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value); #endif return ERROR_OK; } /* See table 9-10 for scan chain 15 format during interpreted access mode. * If the TESTSTATE register is set for interpreted access, certain CP15 * MRC and MCR instructions may be executed through scan chain 15. * * Tables 9-11, 9-12, and 9-13 show which MRC and MCR instructions can be * executed using scan chain 15 interpreted mode. */ static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode, uint32_t arm_opcode) { int retval; struct arm920t_common *arm920t = target_to_arm920(target); struct arm_jtag *jtag_info; struct scan_field fields[4]; uint8_t access_type_buf = 0; /* interpreted access */ uint8_t reg_addr_buf = 0x0; uint8_t nr_w_buf = 0; uint8_t cp15_opcode_buf[4]; jtag_info = &arm920t->arm7_9_common.jtag_info; retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode); fields[0].num_bits = 1; fields[0].out_value = &access_type_buf; fields[0].in_value = NULL; fields[1].num_bits = 32; fields[1].out_value = cp15_opcode_buf; fields[1].in_value = NULL; fields[2].num_bits = 6; fields[2].out_value = ®_addr_buf; fields[2].in_value = NULL; fields[3].num_bits = 1; fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); retval = arm7_9_execute_sys_speed(target); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("failed executing JTAG queue"); return retval; } return ERROR_OK; } static int arm920t_read_cp15_interpreted(struct target *target, uint32_t cp15_opcode, uint32_t address, uint32_t *value) { struct arm *arm = target_to_arm(target); uint32_t *regs_p[1]; uint32_t regs[2]; uint32_t cp15c15 = 0x0; struct reg *r = arm->core_cache->reg_list; /* load address into R1 */ regs[1] = address; arm9tdmi_write_core_regs(target, 0x2, regs); /* read-modify-write CP15 test state register * to enable interpreted access mode */ arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); jtag_execute_queue(); cp15c15 |= 1; /* set interpret mode */ arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* execute CP15 instruction and ARM load (reading from coprocessor) */ arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1)); /* disable interpreted access mode */ cp15c15 &= ~1U; /* clear interpret mode */ arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* retrieve value from R0 */ regs_p[0] = value; arm9tdmi_read_core_regs(target, 0x1, regs_p); jtag_execute_queue(); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value); #endif if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } r[0].dirty = 1; r[1].dirty = 1; return ERROR_OK; } static int arm920t_write_cp15_interpreted(struct target *target, uint32_t cp15_opcode, uint32_t value, uint32_t address) { uint32_t cp15c15 = 0x0; struct arm *arm = target_to_arm(target); uint32_t regs[2]; struct reg *r = arm->core_cache->reg_list; /* load value, address into R0, R1 */ regs[0] = value; regs[1] = address; arm9tdmi_write_core_regs(target, 0x3, regs); /* read-modify-write CP15 test state register * to enable interpreted access mode */ arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); jtag_execute_queue(); cp15c15 |= 1; /* set interpret mode */ arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* execute CP15 instruction and ARM store (writing to coprocessor) */ arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1)); /* disable interpreted access mode */ cp15c15 &= ~1U; /* set interpret mode */ arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address); #endif if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } r[0].dirty = 1; r[1].dirty = 1; return ERROR_OK; } /* EXPORTED to FA256 */ int arm920t_get_ttb(struct target *target, uint32_t *result) { int retval; uint32_t ttb = 0x0; retval = arm920t_read_cp15_interpreted(target, /* FIXME use opcode macro */ 0xeebf0f51, 0x0, &ttb); if (retval != ERROR_OK) return retval; *result = ttb; return ERROR_OK; } /* EXPORTED to FA256 */ int arm920t_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) cp15_control &= ~0x1U; if (d_u_cache) cp15_control &= ~0x4U; if (i_cache) cp15_control &= ~0x1000U; retval = arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_control); return retval; } /* EXPORTED to FA256 */ int arm920t_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) cp15_control |= 0x1U; if (d_u_cache) cp15_control |= 0x4U; if (i_cache) cp15_control |= 0x1000U; retval = arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_control); return retval; } /* EXPORTED to FA256 */ int arm920t_post_debug_entry(struct target *target) { uint32_t cp15c15; struct arm920t_common *arm920t = target_to_arm920(target); int retval; /* examine cp15 control reg */ retval = arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &arm920t->cp15_control_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm920t->cp15_control_reg); if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1) { uint32_t cache_type_reg; /* identify caches */ retval = arm920t_read_cp15_physical(target, CP15PHYS_CACHETYPE, &cache_type_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache); } arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0; arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0; arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0; /* save i/d fault status and address register * FIXME use opcode macros */ retval = arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr); if (retval != ERROR_OK) return retval; retval = arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr); if (retval != ERROR_OK) return retval; retval = arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far); if (retval != ERROR_OK) return retval; retval = arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far); if (retval != ERROR_OK) return retval; LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32, arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far); if (arm920t->preserve_cache) { /* read-modify-write CP15 test state register * to disable I/D-cache linefills */ retval = arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; cp15c15 |= 0x600; retval = arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); if (retval != ERROR_OK) return retval; } return ERROR_OK; } /* EXPORTED to FA256 */ void arm920t_pre_restore_context(struct target *target) { uint32_t cp15c15; struct arm920t_common *arm920t = target_to_arm920(target); /* restore i/d fault status and address register */ arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0); arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0); arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0); arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0); /* read-modify-write CP15 test state register * to reenable I/D-cache linefills */ if (arm920t->preserve_cache) { arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); jtag_execute_queue(); cp15c15 &= ~0x600U; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); } } static const char arm920_not[] = "target is not an ARM920"; static int arm920t_verify_pointer(struct command_context *cmd_ctx, struct arm920t_common *arm920t) { if (arm920t->common_magic != ARM920T_COMMON_MAGIC) { command_print(cmd_ctx, arm920_not); return ERROR_TARGET_INVALID; } return ERROR_OK; } /** Logs summary of ARM920 state for a halted target. */ int arm920t_arch_state(struct target *target) { static const char *state[] = { "disabled", "enabled" }; struct arm920t_common *arm920t = target_to_arm920(target); if (arm920t->common_magic != ARM920T_COMMON_MAGIC) { LOG_ERROR("BUG: %s", arm920_not); return ERROR_TARGET_INVALID; } arm_arch_state(target); LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", state[arm920t->armv4_5_mmu.mmu_enabled], state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]); return ERROR_OK; } static int arm920_mmu(struct target *target, int *enabled) { if (target->state != TARGET_HALTED) { LOG_ERROR("%s: target not halted", __func__); return ERROR_TARGET_INVALID; } *enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled; return ERROR_OK; } static int arm920_virt2phys(struct target *target, uint32_t virt, uint32_t *phys) { uint32_t cb; struct arm920t_common *arm920t = target_to_arm920(target); uint32_t ret; int retval = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, virt, &cb, &ret); if (retval != ERROR_OK) return retval; *phys = ret; return ERROR_OK; } /** Reads a buffer, in the specified word size, with current MMU settings. */ int arm920t_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; retval = arm7_9_read_memory(target, address, size, count, buffer); return retval; } static int arm920t_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); return armv4_5_mmu_read_physical(target, &arm920t->armv4_5_mmu, address, size, count, buffer); } static int arm920t_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); return armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, address, size, count, buffer); } /** Writes a buffer, in the specified word size, with current MMU settings. */ int arm920t_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; const uint32_t cache_mask = ~0x1f; /* cache line size : 32 byte */ struct arm920t_common *arm920t = target_to_arm920(target); /* FIX!!!! this should be cleaned up and made much more general. The * plan is to write up and test on arm920t specifically and * then generalize and clean up afterwards. * * Also it should be moved to the callbacks that handle breakpoints * specifically and not the generic memory write fn's. See XScale code. */ if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) && ((size == 2) || (size == 4))) { /* special case the handling of single word writes to * bypass MMU, to allow implementation of breakpoints * in memory marked read only * by MMU */ uint32_t cb; uint32_t pa; /* * We need physical address and cb */ retval = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &cb, &pa); if (retval != ERROR_OK) return retval; if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) { if (cb & 0x1) { LOG_DEBUG("D-Cache buffered, " "drain write buffer"); /* * Buffered ? * Drain write buffer - MCR p15,0,Rd,c7,c10,4 */ retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 10, 4), 0x0, 0); if (retval != ERROR_OK) return retval; } if (cb == 0x3) { /* * Write back memory ? -> clean cache * * There is no way to clean cache lines using * cp15 scan chain, so copy the full cache * line from cache to physical memory. */ uint8_t data[32]; LOG_DEBUG("D-Cache in 'write back' mode, " "flush cache line"); retval = target_read_memory(target, address & cache_mask, 1, sizeof(data), &data[0]); if (retval != ERROR_OK) return retval; retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa & cache_mask, 1, sizeof(data), &data[0]); if (retval != ERROR_OK) return retval; } /* Cached ? */ if (cb & 0x2) { /* * Cached ? -> Invalidate data cache using MVA * * MCR p15,0,Rd,c7,c6,1 */ LOG_DEBUG("D-Cache enabled, " "invalidate cache line"); retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 6, 1), 0x0, address & cache_mask); if (retval != ERROR_OK) return retval; } } /* write directly to physical memory, * bypassing any read only MMU bits, etc. */ retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer); if (retval != ERROR_OK) return retval; } else { retval = arm7_9_write_memory(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; } /* If ICache is enabled, we have to invalidate affected ICache lines * the DCache is forced to write-through, * so we don't have to clean it here */ if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled) { if (count <= 1) { /* invalidate ICache single entry with MVA * mcr 15, 0, r0, cr7, cr5, {1} */ LOG_DEBUG("I-Cache enabled, " "invalidating affected I-Cache line"); retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), 0x0, address & cache_mask); if (retval != ERROR_OK) return retval; } else { /* invalidate ICache * mcr 15, 0, r0, cr7, cr5, {0} */ retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 0), 0x0, 0x0); if (retval != ERROR_OK) return retval; } } return ERROR_OK; } /* EXPORTED to FA256 */ int arm920t_soft_reset_halt(struct target *target) { int retval = ERROR_OK; struct arm920t_common *arm920t = target_to_arm920(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; retval = target_halt(target); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; } else break; if (debug_level >= 3) { /* do not eat all CPU, time out after 1 se*/ alive_sleep(100); } else keep_alive(); } if (timeout) { LOG_ERROR("Failed to halt CPU after 1 sec"); return ERROR_TARGET_TIMEOUT; } target->state = TARGET_HALTED; /* SVC, ARM state, IRQ and FIQ disabled */ uint32_t cpsr; cpsr = buf_get_u32(arm->cpsr->value, 0, 32); cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); arm->pc->dirty = 1; arm->pc->valid = 1; arm920t_disable_mmu_caches(target, 1, 1, 1); arm920t->armv4_5_mmu.mmu_enabled = 0; arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0; arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0; return target_call_event_callbacks(target, TARGET_EVENT_HALTED); } /* FIXME remove forward decls */ static int arm920t_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); static int arm920t_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); static int arm920t_init_arch_info(struct target *target, struct arm920t_common *arm920t, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common; arm7_9->arm.mrc = arm920t_mrc; arm7_9->arm.mcr = arm920t_mcr; /* initialize arm7/arm9 specific info (including armv4_5) */ arm9tdmi_init_arch_info(target, arm7_9, tap); arm920t->common_magic = ARM920T_COMMON_MAGIC; arm7_9->post_debug_entry = arm920t_post_debug_entry; arm7_9->pre_restore_context = arm920t_pre_restore_context; arm7_9->write_memory = arm920t_write_memory; arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1; arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb; arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory; arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory; arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches; arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches; arm920t->armv4_5_mmu.has_tiny_pages = 1; arm920t->armv4_5_mmu.mmu_enabled = 0; /* disabling linefills leads to lockups, so keep them enabled for now * this doesn't affect correctness, but might affect timing issues, if * important data is evicted from the cache during the debug session * */ arm920t->preserve_cache = 0; /* override hw single-step capability from ARM9TDMI */ arm7_9->has_single_step = 1; return ERROR_OK; } static int arm920t_target_create(struct target *target, Jim_Interp *interp) { struct arm920t_common *arm920t; arm920t = calloc(1, sizeof(struct arm920t_common)); return arm920t_init_arch_info(target, arm920t, target->tap); } COMMAND_HANDLER(arm920t_handle_read_cache_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); struct arm920t_common *arm920t = target_to_arm920(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; uint32_t cp15c15; uint32_t cp15_ctrl, cp15_ctrl_saved; uint32_t regs[16]; uint32_t *regs_p[16]; uint32_t C15_C_D_Ind, C15_C_I_Ind; int i; FILE *output; int segment, index_t; struct reg *r; retval = arm920t_verify_pointer(CMD_CTX, arm920t); if (retval != ERROR_OK) return retval; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; output = fopen(CMD_ARGV[0], "w"); if (output == NULL) { LOG_DEBUG("error opening cache content file"); return ERROR_OK; } for (i = 0; i < 16; i++) regs_p[i] = ®s[i]; /* disable MMU and Caches */ arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; cp15_ctrl_saved = cp15_ctrl; cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED); arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl); /* read CP15 test state register */ arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); jtag_execute_queue(); /* read DCache content */ fprintf(output, "DCache:\n"); /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++) { fprintf(output, "\nsegment: %i\n----------", segment); /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* D CAM Read, loads current victim into C15.C.D.Ind */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 6, 2), ARMV4_5_LDR(1, 0)); /* read current victim */ arm920t_read_cp15_physical(target, CP15PHYS_DCACHE_IDX, &C15_C_D_Ind); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); for (index_t = 0; index_t < 64; index_t++) { /* Ra: * r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5) | (index_t << 26); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write DCache victim */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0)); /* Read D RAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 10, 2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0)); /* Read D CAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 6, 2), ARMV4_5_LDR(9, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read D RAM and CAM content */ arm9tdmi_read_core_regs(target, 0x3fe, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* mask LFSR[6] */ regs[9] &= 0xfffffffe; fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8" PRIx32 ", content (%s):\n", segment, index_t, regs[9], (regs[9] & 0x10) ? "valid" : "invalid"); for (i = 1; i < 9; i++) { fprintf(output, "%i: 0x%8.8" PRIx32 "\n", i-1, regs[i]); } } /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write DCache victim */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); } /* read ICache content */ fprintf(output, "ICache:\n"); /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++) { fprintf(output, "segment: %i\n----------", segment); /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* I CAM Read, loads current victim into C15.C.I.Ind */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 5, 2), ARMV4_5_LDR(1, 0)); /* read current victim */ arm920t_read_cp15_physical(target, CP15PHYS_ICACHE_IDX, &C15_C_I_Ind); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); for (index_t = 0; index_t < 64; index_t++) { /* Ra: * r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5) | (index_t << 26); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write ICache victim */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0)); /* Read I RAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 9, 2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0)); /* Read I CAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 2, 0, 15, 5, 2), ARMV4_5_LDR(9, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read I RAM and CAM content */ arm9tdmi_read_core_regs(target, 0x3fe, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* mask LFSR[6] */ regs[9] &= 0xfffffffe; fprintf(output, "\nsegment: %i, index: %i, " "CAM: 0x%8.8" PRIx32 ", content (%s):\n", segment, index_t, regs[9], (regs[9] & 0x10) ? "valid" : "invalid"); for (i = 1; i < 9; i++) { fprintf(output, "%i: 0x%8.8" PRIx32 "\n", i-1, regs[i]); } } /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */ regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26); arm9tdmi_write_core_regs(target, 0x1, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write ICache victim */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); } /* restore CP15 MMU and Cache settings */ arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved); command_print(CMD_CTX, "cache content successfully output to %s", CMD_ARGV[0]); fclose(output); if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* force writeback of the valid data */ r = arm->core_cache->reg_list; r[0].dirty = r[0].valid; r[1].dirty = r[1].valid; r[2].dirty = r[2].valid; r[3].dirty = r[3].valid; r[4].dirty = r[4].valid; r[5].dirty = r[5].valid; r[6].dirty = r[6].valid; r[7].dirty = r[7].valid; r = arm_reg_current(arm, 8); r->dirty = r->valid; r = arm_reg_current(arm, 9); r->dirty = r->valid; return ERROR_OK; } COMMAND_HANDLER(arm920t_handle_read_mmu_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); struct arm920t_common *arm920t = target_to_arm920(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; uint32_t cp15c15; uint32_t cp15_ctrl, cp15_ctrl_saved; uint32_t regs[16]; uint32_t *regs_p[16]; int i; FILE *output; uint32_t Dlockdown, Ilockdown; struct arm920t_tlb_entry d_tlb[64], i_tlb[64]; int victim; struct reg *r; retval = arm920t_verify_pointer(CMD_CTX, arm920t); if (retval != ERROR_OK) return retval; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; output = fopen(CMD_ARGV[0], "w"); if (output == NULL) { LOG_DEBUG("error opening mmu content file"); return ERROR_OK; } for (i = 0; i < 16; i++) regs_p[i] = ®s[i]; /* disable MMU and Caches */ arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; cp15_ctrl_saved = cp15_ctrl; cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED); arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl); /* read CP15 test state register */ arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* prepare reading D TLB content * */ /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Read D TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MRC(15, 0, 0, 10, 0, 0), ARMV4_5_LDR(1, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read D TLB lockdown stored to r1 */ arm9tdmi_read_core_regs(target, 0x2, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; Dlockdown = regs[1]; for (victim = 0; victim < 64; victim += 8) { /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] * base remains unchanged, victim goes through entries 0 to 63 */ regs[1] = (Dlockdown & 0xfc000000) | (victim << 20); arm9tdmi_write_core_regs(target, 0x2, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write D TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0)); /* Read D TLB CAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 6, 4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read D TLB CAM content stored to r2-r9 */ arm9tdmi_read_core_regs(target, 0x3fc, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; for (i = 0; i < 8; i++) d_tlb[victim + i].cam = regs[i + 2]; } for (victim = 0; victim < 64; victim++) { /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] * base remains unchanged, victim goes through entries 0 to 63 */ regs[1] = (Dlockdown & 0xfc000000) | (victim << 20); arm9tdmi_write_core_regs(target, 0x2, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write D TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0)); /* Read D TLB RAM1 */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 10, 4), ARMV4_5_LDR(2, 0)); /* Read D TLB RAM2 */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 2, 5), ARMV4_5_LDR(3, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read D TLB RAM content stored to r2 and r3 */ arm9tdmi_read_core_regs(target, 0xc, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; d_tlb[victim].ram1 = regs[2]; d_tlb[victim].ram2 = regs[3]; } /* restore D TLB lockdown */ regs[1] = Dlockdown; arm9tdmi_write_core_regs(target, 0x2, regs); /* Write D TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0)); /* prepare reading I TLB content * */ /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Read I TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MRC(15, 0, 0, 10, 0, 1), ARMV4_5_LDR(1, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read I TLB lockdown stored to r1 */ arm9tdmi_read_core_regs(target, 0x2, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; Ilockdown = regs[1]; for (victim = 0; victim < 64; victim += 8) { /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] * base remains unchanged, victim goes through entries 0 to 63 */ regs[1] = (Ilockdown & 0xfc000000) | (victim << 20); arm9tdmi_write_core_regs(target, 0x2, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write I TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0)); /* Read I TLB CAM */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 5, 4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read I TLB CAM content stored to r2-r9 */ arm9tdmi_read_core_regs(target, 0x3fc, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; for (i = 0; i < 8; i++) i_tlb[i + victim].cam = regs[i + 2]; } for (victim = 0; victim < 64; victim++) { /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] * base remains unchanged, victim goes through entries 0 to 63 */ regs[1] = (Dlockdown & 0xfc000000) | (victim << 20); arm9tdmi_write_core_regs(target, 0x2, regs); /* set interpret mode */ cp15c15 |= 0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* Write I TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0)); /* Read I TLB RAM1 */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 9, 4), ARMV4_5_LDR(2, 0)); /* Read I TLB RAM2 */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 4, 0, 15, 1, 5), ARMV4_5_LDR(3, 0)); /* clear interpret mode */ cp15c15 &= ~0x1; arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15); /* read I TLB RAM content stored to r2 and r3 */ arm9tdmi_read_core_regs(target, 0xc, regs_p); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; i_tlb[victim].ram1 = regs[2]; i_tlb[victim].ram2 = regs[3]; } /* restore I TLB lockdown */ regs[1] = Ilockdown; arm9tdmi_write_core_regs(target, 0x2, regs); /* Write I TLB lockdown */ arm920t_execute_cp15(target, ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0)); /* restore CP15 MMU and Cache settings */ arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved); /* output data to file */ fprintf(output, "D TLB content:\n"); for (i = 0; i < 64; i++) { fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32 " 0x%8.8" PRIx32 " %s\n", i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2, (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)"); } fprintf(output, "\n\nI TLB content:\n"); for (i = 0; i < 64; i++) { fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32 " 0x%8.8" PRIx32 " %s\n", i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2, (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)"); } command_print(CMD_CTX, "mmu content successfully output to %s", CMD_ARGV[0]); fclose(output); if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* force writeback of the valid data */ r = arm->core_cache->reg_list; r[0].dirty = r[0].valid; r[1].dirty = r[1].valid; r[2].dirty = r[2].valid; r[3].dirty = r[3].valid; r[4].dirty = r[4].valid; r[5].dirty = r[5].valid; r[6].dirty = r[6].valid; r[7].dirty = r[7].valid; r = arm_reg_current(arm, 8); r->dirty = r->valid; r = arm_reg_current(arm, 9); r->dirty = r->valid; return ERROR_OK; } COMMAND_HANDLER(arm920t_handle_cp15_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm920t_common *arm920t = target_to_arm920(target); retval = arm920t_verify_pointer(CMD_CTX, arm920t); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for " "\"%s\" command", CMD_NAME); return ERROR_OK; } /* one argument, read a register. * two arguments, write it. */ if (CMD_ARGC >= 1) { int address; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address); if (CMD_ARGC == 1) { uint32_t value; retval = arm920t_read_cp15_physical(target, address, &value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %i", address); return ERROR_OK; } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "%i: %8.8" PRIx32, address, value); } else if (CMD_ARGC == 2) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); retval = arm920t_write_cp15_physical(target, address, value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %i", address); /* REVISIT why lie? "return retval"? */ return ERROR_OK; } command_print(CMD_CTX, "%i: %8.8" PRIx32, address, value); } } return ERROR_OK; } COMMAND_HANDLER(arm920t_handle_cp15i_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm920t_common *arm920t = target_to_arm920(target); retval = arm920t_verify_pointer(CMD_CTX, arm920t); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for " "\"%s\" command", CMD_NAME); return ERROR_OK; } /* one argument, read a register. * two arguments, write it. */ if (CMD_ARGC >= 1) { uint32_t opcode; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode); if (CMD_ARGC == 1) { uint32_t value; retval = arm920t_read_cp15_interpreted(target, opcode, 0x0, &value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't execute %8.8" PRIx32, opcode); /* REVISIT why lie? "return retval"? */ return ERROR_OK; } command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32, opcode, value); } else if (CMD_ARGC == 2) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); retval = arm920t_write_cp15_interpreted(target, opcode, value, 0); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't execute %8.8" PRIx32, opcode); /* REVISIT why lie? "return retval"? */ return ERROR_OK; } command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32, opcode, value); } else if (CMD_ARGC == 3) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address); retval = arm920t_write_cp15_interpreted(target, opcode, value, address); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't execute %8.8" PRIx32, opcode); /* REVISIT why lie? "return retval"? */ return ERROR_OK; } command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32 " %8.8" PRIx32, opcode, value, address); } } else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(arm920t_handle_cache_info_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm920t_common *arm920t = target_to_arm920(target); retval = arm920t_verify_pointer(CMD_CTX, arm920t); if (retval != ERROR_OK) return retval; return armv4_5_handle_cache_info_command(CMD_CTX, &arm920t->armv4_5_mmu.armv4_5_cache); } static int arm920t_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } /* read "to" r0 */ return arm920t_read_cp15_interpreted(target, ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2), 0, value); } static int arm920t_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } /* write "from" r0 */ return arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2), 0, value); } static const struct command_registration arm920t_exec_command_handlers[] = { { .name = "cp15", .handler = arm920t_handle_cp15_command, .mode = COMMAND_EXEC, .help = "display/modify cp15 register", .usage = "regnum [value]", }, { .name = "cp15i", .handler = arm920t_handle_cp15i_command, .mode = COMMAND_EXEC, /* prefer using less error-prone "arm mcr" or "arm mrc" */ .help = "display/modify cp15 register using ARM opcode" " (DEPRECATED)", .usage = "instruction [value [address]]", }, { .name = "cache_info", .handler = arm920t_handle_cache_info_command, .mode = COMMAND_EXEC, .usage = "", .help = "display information about target caches", }, { .name = "read_cache", .handler = arm920t_handle_read_cache_command, .mode = COMMAND_EXEC, .help = "dump I/D cache content to file", .usage = "filename", }, { .name = "read_mmu", .handler = arm920t_handle_read_mmu_command, .mode = COMMAND_EXEC, .help = "dump I/D mmu content to file", .usage = "filename", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm920t_command_handlers[] = { { .chain = arm9tdmi_command_handlers, }, { .name = "arm920t", .mode = COMMAND_ANY, .help = "arm920t command group", .usage = "", .chain = arm920t_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM920 targets. */ struct target_type arm920t_target = { .name = "arm920t", .poll = arm7_9_poll, .arch_state = arm920t_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm920t_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, .write_memory = arm7_9_write_memory_opt, .read_phys_memory = arm920t_read_phys_memory, .write_phys_memory = arm920t_write_phys_memory, .mmu = arm920_mmu, .virt2phys = arm920_virt2phys, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm920t_command_handlers, .target_create = arm920t_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm920t.h0000644000175000017500000000556512315575361013537 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM920T_H #define ARM920T_H #include "arm9tdmi.h" #include "armv4_5_mmu.h" #define ARM920T_COMMON_MAGIC 0xa920a920 struct arm920t_common { struct arm7_9_common arm7_9_common; uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; uint32_t cp15_control_reg; uint32_t d_fsr; uint32_t i_fsr; uint32_t d_far; uint32_t i_far; int preserve_cache; }; static inline struct arm920t_common *target_to_arm920(struct target *target) { return container_of(target->arch_info, struct arm920t_common, arm7_9_common.arm); } struct arm920t_cache_line { uint32_t cam; uint32_t data[8]; }; struct arm920t_tlb_entry { uint32_t cam; uint32_t ram1; uint32_t ram2; }; int arm920t_arch_state(struct target *target); int arm920t_soft_reset_halt(struct target *target); int arm920t_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm920t_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm920t_post_debug_entry(struct target *target); void arm920t_pre_restore_context(struct target *target); int arm920t_get_ttb(struct target *target, uint32_t *result); int arm920t_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache); int arm920t_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache); extern const struct command_registration arm920t_command_handlers[]; #endif /* ARM920T_H */ openocd-0.9.0/src/target/arm946e.c0000644000175000017500000005530112315575361013514 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2010 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm946e.h" #include "target_type.h" #include "arm_opcodes.h" #include "breakpoints.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif #define NB_CACHE_WAYS 4 #define CP15_CTL 0x02 #define CP15_CTL_DCACHE (1<<2) #define CP15_CTL_ICACHE (1<<12) /** * flag to give info about cache manipulation during debug : * "0" - cache lines are invalidated "on the fly", for affected addresses. * This is prefered from performance point of view. * "1" - cache is invalidated and switched off on debug_entry, and switched back on on restore. * It is kept off during debugging. */ static uint8_t arm946e_preserve_cache; int arm946e_post_debug_entry(struct target *target); void arm946e_pre_restore_context(struct target *target); static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value); int arm946e_init_arch_info(struct target *target, struct arm946e_common *arm946e, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common; /* initialize arm7/arm9 specific info (including armv4_5) */ arm9tdmi_init_arch_info(target, arm7_9, tap); arm946e->common_magic = ARM946E_COMMON_MAGIC; /** * The ARM946E-S implements the ARMv5TE architecture which * has the BKPT instruction, so we don't have to use a watchpoint comparator */ arm7_9->arm_bkpt = ARMV5_BKPT(0x0); arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff; arm7_9->post_debug_entry = arm946e_post_debug_entry; arm7_9->pre_restore_context = arm946e_pre_restore_context; /** * disabling linefills leads to lockups, so keep them enabled for now * this doesn't affect correctness, but might affect timing issues, if * important data is evicted from the cache during the debug session */ arm946e_preserve_cache = 0; /* override hw single-step capability from ARM9TDMI */ /* arm7_9->has_single_step = 1; */ return ERROR_OK; } static int arm946e_target_create(struct target *target, Jim_Interp *interp) { struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common)); arm946e_init_arch_info(target, arm946e, target->tap); return ERROR_OK; } static int arm946e_verify_pointer(struct command_context *cmd_ctx, struct arm946e_common *arm946e) { if (arm946e->common_magic != ARM946E_COMMON_MAGIC) { command_print(cmd_ctx, "target is not an ARM946"); return ERROR_TARGET_INVALID; } return ERROR_OK; } /* * Update cp15_control_reg, saved on debug_entry. */ static void arm946e_update_cp15_caches(struct target *target, uint32_t value) { struct arm946e_common *arm946e = target_to_arm946(target); arm946e->cp15_control_reg = (arm946e->cp15_control_reg & ~(CP15_CTL_DCACHE|CP15_CTL_ICACHE)) | (value & (CP15_CTL_DCACHE|CP15_CTL_ICACHE)); } /* * REVISIT: The "read_cp15" and "write_cp15" commands could hook up * to eventual mrc() and mcr() routines ... the reg_addr values being * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values. * See section 7.3 of the ARM946E-S TRM. */ static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct scan_field fields[3]; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 0; retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; /* REVISIT: table 7-2 shows that bits 31-31 need to be * specified for accessing BIST registers ... */ fields[0].out_value = NULL; fields[0].in_value = NULL; fields[1].num_bits = 6; fields[1].out_value = ®_addr_buf; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); fields[0].in_value = (uint8_t *)value; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value); #endif retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; return ERROR_OK; } int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct scan_field fields[3]; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 1; uint8_t value_buf[4]; buf_set_u32(value_buf, 0, 32, value); retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = value_buf; fields[0].in_value = NULL; fields[1].num_bits = 6; fields[1].out_value = ®_addr_buf; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value); #endif retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; return ERROR_OK; } #define GET_ICACHE_SIZE 6 #define GET_DCACHE_SIZE 18 /* * \param target struct target pointer * \param idsel select GET_ICACHE_SIZE or GET_DCACHE_SIZE * \returns cache size, given in bytes */ static uint32_t arm946e_cp15_get_csize(struct target *target, int idsel) { struct arm946e_common *arm946e = target_to_arm946(target); uint32_t csize = arm946e->cp15_cache_info; if (csize == 0) { if (arm946e_read_cp15(target, 0x01, &csize) == ERROR_OK) arm946e->cp15_cache_info = csize; } if (csize & (1<<(idsel-4))) /* cache absent */ return 0; csize = (csize >> idsel) & 0x0F; return csize ? 1 << (12 + (csize-3)) : 0; } uint32_t arm946e_invalidate_whole_dcache(struct target *target) { uint32_t csize = arm946e_cp15_get_csize(target, GET_DCACHE_SIZE); if (csize == 0) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* One line (index) is 32 bytes (8 words) long, 4-way assoc * ARM DDI 0201D, Section 3.3.5 */ int nb_idx = (csize / (4*8*NB_CACHE_WAYS)); /* gives nb of lines (indexes) in the cache */ /* Loop for all segmentde (i.e. ways) */ uint32_t seg; for (seg = 0; seg < NB_CACHE_WAYS; seg++) { /* Loop for all indexes */ int idx; for (idx = 0; idx < nb_idx; idx++) { /* Form and write cp15 index (segment + line idx) */ uint32_t cp15_idx = seg << 30 | idx << 5; int retval = arm946e_write_cp15(target, 0x3a, cp15_idx); if (retval != ERROR_OK) { LOG_DEBUG("ERROR writing index"); return retval; } /* Read dtag */ uint32_t dtag; arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag); /* Check cache line VALID bit */ if (!(dtag >> 4 & 0x1)) continue; /* Clean data cache line */ retval = arm946e_write_cp15(target, 0x35, 0x1); if (retval != ERROR_OK) { LOG_DEBUG("ERROR cleaning cache line"); return retval; } /* Flush data cache line */ retval = arm946e_write_cp15(target, 0x1a, 0x1); if (retval != ERROR_OK) { LOG_DEBUG("ERROR flushing cache line"); return retval; } } } return ERROR_OK; } uint32_t arm946e_invalidate_whole_icache(struct target *target) { /* Check cache presence before flushing - avoid undefined behavior */ uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE); if (csize == 0) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; LOG_DEBUG("FLUSHING I$"); /** * Invalidate (flush) I$ * mcr 15, 0, r0, cr7, cr5, {0} */ int retval = arm946e_write_cp15(target, 0x0f, 0x1); if (retval != ERROR_OK) { LOG_DEBUG("ERROR flushing I$"); return retval; } return ERROR_OK; } int arm946e_post_debug_entry(struct target *target) { uint32_t ctr_reg = 0x0; uint32_t retval = ERROR_OK; struct arm946e_common *arm946e = target_to_arm946(target); /* See if CACHES are enabled, and save that info * in the context bits, so that arm946e_pre_restore_context() can use them */ arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg); /* Save control reg in the context */ arm946e->cp15_control_reg = ctr_reg; if (arm946e_preserve_cache) { if (ctr_reg & CP15_CTL_DCACHE) { /* Clean and flush D$ */ arm946e_invalidate_whole_dcache(target); /* Disable D$ */ ctr_reg &= ~CP15_CTL_DCACHE; } if (ctr_reg & CP15_CTL_ICACHE) { /* Flush I$ */ arm946e_invalidate_whole_icache(target); /* Disable I$ */ ctr_reg &= ~CP15_CTL_ICACHE; } /* Write the new configuration */ retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg); if (retval != ERROR_OK) { LOG_DEBUG("ERROR disabling cache"); return retval; } } /* if preserve_cache */ return ERROR_OK; } void arm946e_pre_restore_context(struct target *target) { uint32_t ctr_reg = 0x0; uint32_t retval; if (arm946e_preserve_cache) { struct arm946e_common *arm946e = target_to_arm946(target); /* Get the contents of the CTR reg */ arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg); /** * Read-modify-write CP15 control * to reenable I/D-cache operation * NOTE: It is not possible to disable cache by CP15. * if arm946e_preserve_cache debugging flag enabled. */ ctr_reg |= arm946e->cp15_control_reg & (CP15_CTL_DCACHE|CP15_CTL_ICACHE); /* Write the new configuration */ retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg); if (retval != ERROR_OK) LOG_DEBUG("ERROR enabling cache"); } /* if preserve_cache */ } uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address, uint32_t size, uint32_t count) { uint32_t cur_addr = 0x0; uint32_t cp15_idx, set, way, dtag; uint32_t i = 0; int retval; for (i = 0; i < count*size; i++) { cur_addr = address + i; set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */ for (way = 0; way < NB_CACHE_WAYS; way++) { /** * Find if the affected address is kept in the cache. * Because JTAG Scan Chain 15 offers limited approach, * we have to loop through all cache ways (segments) and * read cache tags, then compare them with with address. */ /* Form and write cp15 index (segment + line idx) */ cp15_idx = way << 30 | set << 5; retval = arm946e_write_cp15(target, 0x3a, cp15_idx); if (retval != ERROR_OK) { LOG_DEBUG("ERROR writing index"); return retval; } /* Read dtag */ arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag); /* Check cache line VALID bit */ if (!(dtag >> 4 & 0x1)) continue; /* If line is valid and corresponds to affected address - invalidate it */ if (dtag >> 5 == cur_addr >> 5) { /* Clean data cache line */ retval = arm946e_write_cp15(target, 0x35, 0x1); if (retval != ERROR_OK) { LOG_DEBUG("ERROR cleaning cache line"); return retval; } /* Flush data cache line */ retval = arm946e_write_cp15(target, 0x1c, 0x1); if (retval != ERROR_OK) { LOG_DEBUG("ERROR flushing cache line"); return retval; } break; } } /* loop through all 4 ways */ } /* loop through all addresses */ return ERROR_OK; } uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address, uint32_t size, uint32_t count) { uint32_t cur_addr = 0x0; uint32_t cp15_idx, set, way, itag; uint32_t i = 0; int retval; for (i = 0; i < count*size; i++) { cur_addr = address + i; set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */ for (way = 0; way < NB_CACHE_WAYS; way++) { /* Form and write cp15 index (segment + line idx) */ cp15_idx = way << 30 | set << 5; retval = arm946e_write_cp15(target, 0x3a, cp15_idx); if (retval != ERROR_OK) { LOG_DEBUG("ERROR writing index"); return retval; } /* Read itag */ arm946e_read_cp15(target, 0x17, (uint32_t *) &itag); /* Check cache line VALID bit */ if (!(itag >> 4 & 0x1)) continue; /* If line is valid and corresponds to affected address - invalidate it */ if (itag >> 5 == cur_addr >> 5) { /* Flush I$ line */ retval = arm946e_write_cp15(target, 0x1d, 0x0); if (retval != ERROR_OK) { LOG_DEBUG("ERROR flushing cache line"); return retval; } break; } } /* way loop */ } /* addr loop */ return ERROR_OK; } /** Writes a buffer, in the specified word size, with current MMU settings. */ int arm946e_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; LOG_DEBUG("-"); struct arm946e_common *arm946e = target_to_arm946(target); /* Invalidate D$ if it is ON */ if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_DCACHE)) arm946e_invalidate_dcache(target, address, size, count); /** * Write memory */ retval = arm7_9_write_memory_opt(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; /* * * Invalidate I$ if it is ON. * * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through, * because arm7_9_write_memory() has seen non-valid bit in D$ * and wrote data into physical RAM (without touching or allocating the cache line). * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss" * policy for both I$ and D$ (Chapter 3.2 and 3.3) * * Explanation : * "ARM system developer's guide: designing and optimizing system software" by * Andrew N. Sloss, Dominic Symes and Chris Wright, * Chapter 12.3.3 Allocating Policy on a Cache Miss : * A read allocate on cache miss policy allocates a cache line only during a read from main memory. * If the victim cache line contains valid data, then it is written to main memory before the cache line * is filled with new data. * Under this strategy, a write of new data to memory does not update the contents of the cache memory * unless a cache line was allocated on a previous read from main memory. * If the cache line contains valid data, then the write updates the cache and may update the main memory if * the cache write policy is write-through. * If the data is not in the cache, the controller writes to main memory only. */ if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_ICACHE)) arm946e_invalidate_icache(target, address, size, count); return ERROR_OK; } int arm946e_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; LOG_DEBUG("-"); retval = arm7_9_read_memory(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int jim_arm946e_cp15(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { /* one or two arguments, access a single register (write if second argument is given) */ if (argc < 2 || argc > 3) { Jim_WrongNumArgs(interp, 1, argv, "addr [value]"); return JIM_ERR; } struct command_context *cmd_ctx = current_command_context(interp); assert(cmd_ctx != NULL); struct target *target = get_current_target(cmd_ctx); if (target == NULL) { LOG_ERROR("arm946e: no current target"); return JIM_ERR; } struct arm946e_common *arm946e = target_to_arm946(target); int retval = arm946e_verify_pointer(cmd_ctx, arm946e); if (retval != ERROR_OK) return JIM_ERR; if (target->state != TARGET_HALTED) { command_print(cmd_ctx, "target %s must be stopped for \"cp15\" command", target_name(target)); return JIM_ERR; } long l; uint32_t address; retval = Jim_GetLong(interp, argv[1], &l); address = l; if (JIM_OK != retval) return retval; if (argc == 2) { uint32_t value; retval = arm946e_read_cp15(target, address, &value); if (retval != ERROR_OK) { command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address); return JIM_ERR; } retval = jtag_execute_queue(); if (retval != ERROR_OK) return JIM_ERR; char buf[20]; sprintf(buf, "0x%08" PRIx32, value); /* Return value in hex format */ Jim_SetResultString(interp, buf, -1); } else if (argc == 3) { uint32_t value; retval = Jim_GetLong(interp, argv[2], &l); value = l; if (JIM_OK != retval) return retval; retval = arm946e_write_cp15(target, address, value); if (retval != ERROR_OK) { command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address); return JIM_ERR; } if (address == CP15_CTL) arm946e_update_cp15_caches(target, value); } return JIM_OK; } COMMAND_HANDLER(arm946e_handle_idcache) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; int retval; struct target *target = get_current_target(CMD_CTX); struct arm946e_common *arm946e = target_to_arm946(target); retval = arm946e_verify_pointer(CMD_CTX, arm946e); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_TARGET_NOT_HALTED; } bool icache = (strcmp(CMD_NAME, "icache") == 0); uint32_t csize = arm946e_cp15_get_csize(target, icache ? GET_ICACHE_SIZE : GET_DCACHE_SIZE) / 1024; if (CMD_ARGC == 0) { bool bena = ((arm946e->cp15_control_reg & (icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE)) != 0) && (arm946e->cp15_control_reg & 0x1); if (csize == 0) command_print(CMD_CTX, "%s-cache absent", icache ? "I" : "D"); else command_print(CMD_CTX, "%s-cache size: %" PRIu32 "K, %s", icache ? "I" : "D", csize, bena ? "enabled" : "disabled"); return ERROR_OK; } bool flush = false; bool enable = false; retval = command_parse_bool_arg(CMD_ARGV[0], &enable); if (retval == ERROR_COMMAND_SYNTAX_ERROR) { if (strcmp(CMD_ARGV[0], "flush") == 0) { flush = true; retval = ERROR_OK; } else return retval; } /* Do not invalidate or change state, if cache is absent */ if (csize == 0) { command_print(CMD_CTX, "%s-cache absent, '%s' operation undefined", icache ? "I" : "D", CMD_ARGV[0]); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* NOTE: flushing entire cache will not preserve lock-down cache regions */ if (icache) { if ((arm946e->cp15_control_reg & CP15_CTL_ICACHE) && !enable) retval = arm946e_invalidate_whole_icache(target); } else { if ((arm946e->cp15_control_reg & CP15_CTL_DCACHE) && !enable) retval = arm946e_invalidate_whole_dcache(target); } if (retval != ERROR_OK || flush) return retval; uint32_t value; retval = arm946e_read_cp15(target, CP15_CTL, &value); if (retval != ERROR_OK) return retval; uint32_t vnew = value; uint32_t cmask = icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE; if (enable) { if ((value & 0x1) == 0) LOG_WARNING("arm946e: MPU must be enabled for cache to operate"); vnew |= cmask; } else vnew &= ~cmask; if (vnew == value) return ERROR_OK; retval = arm946e_write_cp15(target, CP15_CTL, vnew); if (retval != ERROR_OK) return retval; arm946e_update_cp15_caches(target, vnew); return ERROR_OK; } static const struct command_registration arm946e_exec_command_handlers[] = { { .name = "cp15", .jim_handler = jim_arm946e_cp15, .mode = COMMAND_EXEC, .usage = "regnum [value]", .help = "read/modify cp15 register", }, { .name = "icache", .handler = arm946e_handle_idcache, .mode = COMMAND_EXEC, .usage = "['enable'|'disable'|'flush']", .help = "I-cache info and operations", }, { .name = "dcache", .handler = arm946e_handle_idcache, .mode = COMMAND_EXEC, .usage = "['enable'|'disable'|'flush']", .help = "D-cache info and operations", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm946e_command_handlers[] = { { .chain = arm9tdmi_command_handlers, }, { .name = "arm946e", .mode = COMMAND_ANY, .help = "arm946e command group", .usage = "", .chain = arm946e_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM946 targets. */ struct target_type arm946e_target = { .name = "arm946e", .poll = arm7_9_poll, .arch_state = arm_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, /* .read_memory = arm7_9_read_memory, */ /* .write_memory = arm7_9_write_memory, */ .read_memory = arm946e_read_memory, .write_memory = arm946e_write_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, /* .add_breakpoint = arm946e_add_breakpoint, */ /* .remove_breakpoint = arm946e_remove_breakpoint, */ .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm946e_command_handlers, .target_create = arm946e_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm946e.h0000644000175000017500000000507112315575361013520 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2010 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM946E_H #define ARM946E_H #include "arm9tdmi.h" #define ARM946E_COMMON_MAGIC 0x20f920f9 struct arm946e_common { struct arm7_9_common arm7_9_common; int common_magic; uint32_t cp15_control_reg; uint32_t cp15_cache_info; }; static inline struct arm946e_common *target_to_arm946(struct target *target) { return container_of(target->arch_info, struct arm946e_common, arm7_9_common.arm); } int arm946e_init_arch_info(struct target *target, struct arm946e_common *arm946e, struct jtag_tap *tap); int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value); extern const struct command_registration arm946e_command_handlers[]; #endif /* ARM946E_H */ openocd-0.9.0/src/target/arm966e.c0000644000175000017500000002053212315575361013514 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm966e.h" #include "target_type.h" #include "arm_opcodes.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm966e->arm7_9_common; /* initialize arm7/arm9 specific info (including armv4_5) */ arm9tdmi_init_arch_info(target, arm7_9, tap); arm966e->common_magic = ARM966E_COMMON_MAGIC; /* The ARM966E-S implements the ARMv5TE architecture which * has the BKPT instruction, so we don't have to use a watchpoint comparator */ arm7_9->arm_bkpt = ARMV5_BKPT(0x0); arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff; return ERROR_OK; } static int arm966e_target_create(struct target *target, Jim_Interp *interp) { struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common)); return arm966e_init_arch_info(target, arm966e, target->tap); } static int arm966e_verify_pointer(struct command_context *cmd_ctx, struct arm966e_common *arm966e) { if (arm966e->common_magic != ARM966E_COMMON_MAGIC) { command_print(cmd_ctx, "target is not an ARM966"); return ERROR_TARGET_INVALID; } return ERROR_OK; } /* * REVISIT: The "read_cp15" and "write_cp15" commands could hook up * to eventual mrc() and mcr() routines ... the reg_addr values being * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values. * See section 7.3 of the ARM966E-S TRM. */ static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct scan_field fields[3]; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 0; retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; /* REVISIT: table 7-2 shows that bits 31-31 need to be * specified for accessing BIST registers ... */ fields[0].out_value = NULL; fields[0].in_value = NULL; fields[1].num_bits = 6; fields[1].out_value = ®_addr_buf; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); fields[1].in_value = (uint8_t *)value; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value); #endif return ERROR_OK; } /* EXPORTED to str9x (flash) */ int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct scan_field fields[3]; uint8_t reg_addr_buf = reg_addr & 0x3f; uint8_t nr_w_buf = 1; uint8_t value_buf[4]; buf_set_u32(value_buf, 0, 32, value); retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = value_buf; fields[0].in_value = NULL; fields[1].num_bits = 6; fields[1].out_value = ®_addr_buf; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value); #endif return ERROR_OK; } COMMAND_HANDLER(arm966e_handle_cp15_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm966e_common *arm966e = target_to_arm966(target); retval = arm966e_verify_pointer(CMD_CTX, arm966e); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } /* one or more argument, access a single register (write if second argument is given */ if (CMD_ARGC >= 1) { uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); if (CMD_ARGC == 1) { uint32_t value; retval = arm966e_read_cp15(target, address, &value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %" PRIi32, address); return ERROR_OK; } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32, address, value); } else if (CMD_ARGC == 2) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); retval = arm966e_write_cp15(target, address, value); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %" PRIi32, address); return ERROR_OK; } command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32, address, value); } } return ERROR_OK; } static const struct command_registration arm966e_exec_command_handlers[] = { { .name = "cp15", .handler = arm966e_handle_cp15_command, .mode = COMMAND_EXEC, .usage = "regnum [value]", .help = "display/modify cp15 register", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm966e_command_handlers[] = { { .chain = arm9tdmi_command_handlers, }, { .name = "arm966e", .mode = COMMAND_ANY, .help = "arm966e command group", .usage = "", .chain = arm966e_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM966 targets. */ struct target_type arm966e_target = { .name = "arm966e", .poll = arm7_9_poll, .arch_state = arm_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm966e_command_handlers, .target_create = arm966e_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm966e.h0000644000175000017500000000446412315575361013527 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM966E_H #define ARM966E_H #include "arm9tdmi.h" #define ARM966E_COMMON_MAGIC 0x20f920f9 struct arm966e_common { struct arm7_9_common arm7_9_common; int common_magic; uint32_t cp15_control_reg; }; static inline struct arm966e_common * target_to_arm966(struct target *target) { return container_of(target->arch_info, struct arm966e_common, arm7_9_common.arm); } int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e, struct jtag_tap *tap); int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value); extern const struct command_registration arm966e_command_handlers[]; #endif /* ARM966E_H */ openocd-0.9.0/src/target/algorithm.c0000644000175000017500000000426312315575361014314 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "algorithm.h" #include void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction direction) { param->address = address; param->size = size; param->value = malloc(size); param->direction = direction; } void destroy_mem_param(struct mem_param *param) { free(param->value); param->value = NULL; } void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction) { param->reg_name = reg_name; param->size = size; param->value = malloc(DIV_ROUND_UP(size, 8)); param->direction = direction; } void destroy_reg_param(struct reg_param *param) { free(param->value); param->value = NULL; } openocd-0.9.0/src/target/algorithm.h0000644000175000017500000000411712315575361014317 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ALGORITHM_H #define ALGORITHM_H enum param_direction { PARAM_IN, PARAM_OUT, PARAM_IN_OUT }; struct mem_param { uint32_t address; uint32_t size; uint8_t *value; enum param_direction direction; }; struct reg_param { const char *reg_name; uint32_t size; uint8_t *value; enum param_direction direction; }; void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction dir); void destroy_mem_param(struct mem_param *param); void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction dir); void destroy_reg_param(struct reg_param *param); #endif /* ALGORITHM_H */ openocd-0.9.0/src/target/feroceon.c0000644000175000017500000006443612315575361014136 00000000000000/*************************************************************************** * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. * * Written by Nicolas Pitre * * * * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * Marvell Feroceon/Dragonite support. * * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others, * mimics the ARM926 ICE interface with the following differences: * * - the MOE (method of entry) reporting is not implemented * * - breakpoint/watchpoint comparator #1 is seemingly not implemented * * - due to a different pipeline implementation, some injected debug * instruction sequences have to be somewhat different * * Other issues: * * - asserting DBGRQ doesn't work if target is looping on the undef vector * * - the EICE version signature in the COMMS_CTL reg is next to the flow bits * not at the top, and rather meaningless due to existing discrepencies * * - the DCC channel is half duplex (only one FIFO for both directions) with * seemingly no proper flow control. * * The Dragonite core is the non-mmu version based on the ARM966 model, and * it shares the above issues as well. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm926ejs.h" #include "arm966e.h" #include "target_type.h" #include "register.h" #include "arm_opcodes.h" static int feroceon_assert_reset(struct target *target) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; int ud = arm7_9->use_dbgrq; arm7_9->use_dbgrq = 0; if (target->reset_halt) arm7_9_halt(target); arm7_9->use_dbgrq = ud; return arm7_9_assert_reset(target); } static int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr) { struct scan_field fields[3]; uint8_t out_buf[4]; uint8_t instr_buf[4]; uint8_t sysspeed_buf = 0x0; int retval; /* prepare buffer */ buf_set_u32(out_buf, 0, 32, 0); buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32)); retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = out_buf; fields[0].in_value = NULL; fields[1].num_bits = 3; fields[1].out_value = &sysspeed_buf; fields[1].in_value = NULL; fields[2].num_bits = 32; fields[2].out_value = instr_buf; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); /* no jtag_add_runtest(0, TAP_DRPAUSE) here */ return ERROR_OK; } static void feroceon_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* * save r0 before using it and put system in ARM state * to allow common handling of ARM and THUMB debugging */ feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP); feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP); feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); jtag_execute_queue(); /* * fix program counter: * MOV R0, PC was the 7th instruction (+12) * reading PC in Thumb state gives address of instruction + 4 */ *pc -= (12 + 4); } static void feroceon_read_core_regs(struct target *target, uint32_t mask, uint32_t *core_regs[16]) { int i; struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) if (mask & (1 << i)) arm9tdmi_clock_data_in(jtag_info, core_regs[i]); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_read_core_regs_target_buffer(struct target *target, uint32_t mask, void *buffer, int size) { int i; struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0; uint32_t *buf_u32 = buffer; uint16_t *buf_u16 = buffer; uint8_t *buf_u8 = buffer; arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) { switch (size) { case 4: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be); break; case 2: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be); break; case 1: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be); break; } } } arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr); arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr); arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16]) { int i; struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) if (mask & (1 << i)) arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void feroceon_branch_resume(struct target *target) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); arm7_9->need_bypass_before_restart = 1; } static void feroceon_branch_resume_thumb(struct target *target) { LOG_DEBUG("-"); struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); uint32_t pc = buf_get_u32(arm->pc->value, 0, 32); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,pc,#1 */ arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); pc = (pc & 2) >> 1; arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1); arm7_9->need_bypass_before_restart = 1; } static int feroceon_read_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; int err; arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); err = arm7_9_execute_sys_speed(target); if (err != ERROR_OK) return err; arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); return jtag_execute_queue(); } static int feroceon_write_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); return arm7_9_execute_sys_speed(target); } static void feroceon_set_dbgrq(struct target *target) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; buf_set_u32(dbg_ctrl->value, 0, 8, 2); embeddedice_store_reg(dbg_ctrl); } static void feroceon_enable_single_step(struct target *target, uint32_t next_pc) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; /* set a breakpoint there */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7); } static void feroceon_disable_single_step(struct target *target) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]); } static int feroceon_examine_debug_reason(struct target *target) { /* the MOE is not implemented */ if (target->debug_reason != DBG_REASON_SINGLESTEP) target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int feroceon_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { int retval; struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; enum arm_state core_state = arm->core_state; uint32_t x, flip, shift, save[7]; uint32_t i; /* * We can't use the dcc flow control bits, so let's transfer data * with 31 bits and flip the MSB each time a new data word is sent. */ static uint32_t dcc_code[] = { 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */ 0xe3a0301e, /* 1: mov r3, #30 */ 0xe3a04002, /* mov r4, #2 */ 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */ 0xe1310005, /* teq r1, r5 */ 0x0afffffc, /* beq 1b */ 0xe1a05001, /* mov r5, r1 */ 0xe1a01081, /* mov r1, r1, lsl #1 */ 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */ 0xe1320005, /* teq r2, r5 */ 0x0afffffc, /* beq 3b */ 0xe1a05002, /* mov r5, r2 */ 0xe3c22102, /* bic r2, r2, #0x80000000 */ 0xe1811332, /* orr r1, r1, r2, lsr r3 */ 0xe2533001, /* subs r3, r3, #1 */ 0xe4801004, /* str r1, [r0], #4 */ 0xe1a01412, /* mov r1, r2, lsl r4 */ 0xe2844001, /* add r4, r4, #1 */ 0x4affffed, /* bmi 1b */ 0xeafffff3, /* b 3b */ }; uint32_t dcc_size = sizeof(dcc_code); if (address % 4 != 0) return ERROR_TARGET_UNALIGNED_ACCESS; if (!arm7_9->dcc_downloads) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* regrab previously allocated working_area, or allocate a new one */ if (!arm7_9->dcc_working_area) { uint8_t dcc_code_buf[dcc_size]; /* make sure we have a working area */ if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) { LOG_INFO("no working area available, falling back to memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* copy target instructions to target endianness */ target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code); /* write DCC code to working area, using the non-optimized * memory write to avoid ending up here again */ retval = arm7_9_write_memory_no_opt(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf); if (retval != ERROR_OK) return retval; } /* backup clobbered processor state */ for (i = 0; i <= 5; i++) save[i] = buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32); save[i] = buf_get_u32(arm->pc->value, 0, 32); /* set up target address in r0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, address); arm->core_cache->reg_list[0].valid = 1; arm->core_cache->reg_list[0].dirty = 1; arm->core_state = ARM_STATE_ARM; embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0); arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1); /* send data over */ x = 0; flip = 0; shift = 1; for (i = 0; i < count; i++) { uint32_t y = target_buffer_get_u32(target, buffer); uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z); x = y << (32 - shift); if (++shift >= 32 || i + 1 >= count) { z = (x >> 1) | (flip ^= 0x80000000); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z); x = 0; shift = 1; } buffer += 4; } retval = target_halt(target); if (retval == ERROR_OK) retval = target_wait_state(target, TARGET_HALTED, 500); if (retval == ERROR_OK) { uint32_t endaddress = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); if (endaddress != address + count*4) { LOG_ERROR("DCC write failed," " expected end address 0x%08" PRIx32 " got 0x%0" PRIx32 "", address + count*4, endaddress); retval = ERROR_FAIL; } } /* restore target state */ for (i = 0; i <= 5; i++) { buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]); arm->core_cache->reg_list[i].valid = 1; arm->core_cache->reg_list[i].dirty = 1; } buf_set_u32(arm->pc->value, 0, 32, save[i]); arm->pc->valid = 1; arm->pc->dirty = 1; arm->core_state = core_state; return retval; } static int feroceon_init_target(struct command_context *cmd_ctx, struct target *target) { arm9tdmi_init_target(cmd_ctx, target); return ERROR_OK; } static void feroceon_common_setup(struct target *target) { struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; /* override some insn sequence functions */ arm7_9->change_to_arm = feroceon_change_to_arm; arm7_9->read_core_regs = feroceon_read_core_regs; arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer; arm7_9->read_xpsr = feroceon_read_xpsr; arm7_9->write_xpsr = feroceon_write_xpsr; arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8; arm7_9->write_core_regs = feroceon_write_core_regs; arm7_9->branch_resume = feroceon_branch_resume; arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb; /* must be implemented with only one comparator */ arm7_9->enable_single_step = feroceon_enable_single_step; arm7_9->disable_single_step = feroceon_disable_single_step; arm7_9->bulk_write_memory = feroceon_bulk_write_memory; /* MOE is not implemented */ arm7_9->examine_debug_reason = feroceon_examine_debug_reason; /* Note: asserting DBGRQ might not win over the undef exception. If that happens then just use "arm7_9 dbgrq disable". */ arm7_9->use_dbgrq = 1; arm7_9->set_special_dbgrq = feroceon_set_dbgrq; /* only one working comparator */ arm7_9->wp_available_max = 1; arm7_9->wp1_used_default = -1; } static int feroceon_target_create(struct target *target, Jim_Interp *interp) { struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common)); arm926ejs_init_arch_info(target, arm926ejs, target->tap); feroceon_common_setup(target); struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; arm7_9->write_memory = arm926ejs_write_memory; /* the standard ARM926 methods don't always work (don't ask...) */ arm926ejs->read_cp15 = feroceon_read_cp15; arm926ejs->write_cp15 = feroceon_write_cp15; return ERROR_OK; } static int dragonite_target_create(struct target *target, Jim_Interp *interp) { struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common)); arm966e_init_arch_info(target, arm966e, target->tap); feroceon_common_setup(target); struct arm *arm = target->arch_info; struct arm7_9_common *arm7_9 = arm->arch_info; arm7_9->write_memory = arm7_9_write_memory; return ERROR_OK; } static int feroceon_examine(struct target *target) { struct arm *arm; struct arm7_9_common *arm7_9; int retval; retval = arm7_9_examine(target); if (retval != ERROR_OK) return retval; arm = target->arch_info; arm7_9 = arm->arch_info; /* the COMMS_CTRL bits are all contiguous */ if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6) LOG_ERROR("unexpected Feroceon EICE version signature"); arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6; arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_monitor_mode = 1; /* vector catch reg is not initialized on reset */ embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0); /* clear monitor mode, enable comparators */ embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); jtag_execute_queue(); buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0); buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); return ERROR_OK; } struct target_type feroceon_target = { .name = "feroceon", .poll = arm7_9_poll, .arch_state = arm926ejs_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = feroceon_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm926ejs_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm926ejs_command_handlers, .target_create = feroceon_target_create, .init_target = feroceon_init_target, .examine = feroceon_examine, }; struct target_type dragonite_target = { .name = "dragonite", .poll = arm7_9_poll, .arch_state = arm_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = feroceon_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm966e_command_handlers, .target_create = dragonite_target_create, .init_target = feroceon_init_target, .examine = feroceon_examine, }; openocd-0.9.0/src/target/fa526.c0000644000175000017500000003374512315575361013160 00000000000000/*************************************************************************** * Copyright (C) 2009 by Paulius Zaleckas * * paulius.zaleckas@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * FA526 is very similar to ARM920T with following differences: * * - execution pipeline is 6 steps * - Unified TLB * - has Branch Target Buffer * - does not support reading of I/D cache contents */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm920t.h" #include "target_type.h" #include "arm_opcodes.h" static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc) { LOG_ERROR("%s: there is no Thumb state on FA526", __func__); } static void fa526_read_core_regs(struct target *target, uint32_t mask, uint32_t *core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, STM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, STM in MEMORY (i'th cycle) */ arm9tdmi_clock_data_in(jtag_info, core_regs[i]); } } static void fa526_read_core_regs_target_buffer(struct target *target, uint32_t mask, void *buffer, int size) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0; uint32_t *buf_u32 = buffer; uint16_t *buf_u16 = buffer; uint8_t *buf_u8 = buffer; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, STM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, STM in MEMORY (i'th cycle) */ switch (size) { case 4: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be); break; case 2: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be); break; case 1: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be); break; } } } static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* STR r0, [r15] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0); /* fetch NOP, STR in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, STR in MEMORY */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0); } static void fa526_write_xpsr(struct target *target, uint32_t xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr); /* MSR1 fetched */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0); /* MSR2 fetched, MSR1 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0); /* MSR3 fetched, MSR1 in SHIFT, MSR2 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0); /* MSR4 fetched, MSR1 in EXECUTE (1), MSR2 in SHIFT, MSR3 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0); /* nothing fetched, MSR1 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR1 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR2 in EXECUTE (1), MSR3 in SHIFT, MSR4 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR2 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR2 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in SHIFT */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR3 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR3 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR4 in EXECUTE (1) */ /* last MSR writes flags, which takes only one cycle */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void fa526_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr); /* MSR fetched */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0); /* NOP fetched, MSR in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR in SHIFT */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR in EXECUTE (1) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* rot == 4 writes flags, which takes only one cycle */ if (rot != 4) { /* nothing fetched, MSR in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } } static void fa526_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0); } arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void fa526_write_pc(struct target *target, uint32_t pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (4th cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (5th cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void fa526_branch_resume_thumb(struct target *target) { LOG_ERROR("%s: there is no Thumb state on FA526", __func__); } static int fa526_init_arch_info_2(struct target *target, struct arm7_9_common *arm7_9, struct jtag_tap *tap) { /* prepare JTAG information for the new target */ arm7_9->jtag_info.tap = tap; arm7_9->jtag_info.scann_size = 5; /* register arch-specific functions */ arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason; arm7_9->change_to_arm = fa526_change_to_arm; arm7_9->read_core_regs = fa526_read_core_regs; arm7_9->read_core_regs_target_buffer = fa526_read_core_regs_target_buffer; arm7_9->read_xpsr = fa526_read_xpsr; arm7_9->write_xpsr = fa526_write_xpsr; arm7_9->write_xpsr_im8 = fa526_write_xpsr_im8; arm7_9->write_core_regs = fa526_write_core_regs; arm7_9->load_word_regs = arm9tdmi_load_word_regs; arm7_9->load_hword_reg = arm9tdmi_load_hword_reg; arm7_9->load_byte_reg = arm9tdmi_load_byte_reg; arm7_9->store_word_regs = arm9tdmi_store_word_regs; arm7_9->store_hword_reg = arm9tdmi_store_hword_reg; arm7_9->store_byte_reg = arm9tdmi_store_byte_reg; arm7_9->write_pc = fa526_write_pc; arm7_9->branch_resume = arm9tdmi_branch_resume; arm7_9->branch_resume_thumb = fa526_branch_resume_thumb; arm7_9->enable_single_step = arm9tdmi_enable_single_step; arm7_9->disable_single_step = arm9tdmi_disable_single_step; arm7_9->write_memory = arm920t_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; arm7_9->pre_restore_context = NULL; /* initialize arch-specific breakpoint handling */ arm7_9->arm_bkpt = 0xdeeedeee; arm7_9->thumb_bkpt = 0xdeee; arm7_9->dbgreq_adjust_pc = 3; arm7_9_init_arch_info(target, arm7_9); /* override use of DBGRQ, this is safe on ARM9TDMI */ arm7_9->use_dbgrq = 1; /* all ARM9s have the vector catch register */ arm7_9->has_vector_catch = 1; return ERROR_OK; } static int fa526_init_arch_info(struct target *target, struct arm920t_common *arm920t, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common; /* initialize arm7/arm9 specific info (including armv4_5) */ fa526_init_arch_info_2(target, arm7_9, tap); arm920t->common_magic = ARM920T_COMMON_MAGIC; arm7_9->post_debug_entry = arm920t_post_debug_entry; arm7_9->pre_restore_context = arm920t_pre_restore_context; arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1; arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb; arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory; arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory; arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches; arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches; arm920t->armv4_5_mmu.has_tiny_pages = 1; arm920t->armv4_5_mmu.mmu_enabled = 0; /* disabling linefills leads to lockups, so keep them enabled for now * this doesn't affect correctness, but might affect timing issues, if * important data is evicted from the cache during the debug session * */ arm920t->preserve_cache = 0; /* override hw single-step capability from ARM9TDMI */ arm7_9->has_single_step = 1; return ERROR_OK; } static int fa526_target_create(struct target *target, Jim_Interp *interp) { struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common)); return fa526_init_arch_info(target, arm920t, target->tap); } /** Holds methods for FA526 targets. */ struct target_type fa526_target = { .name = "fa526", .poll = arm7_9_poll, .arch_state = arm920t_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm920t_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm920t_command_handlers, .target_create = fa526_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/quark_x10xx.c0000644000175000017500000000651512315575361014523 00000000000000/* * Copyright(c) 2013 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation */ /* * @file * Debugger for Intel Quark SoC X1000 * Intel Quark X10xx is the first product in the Quark family of SoCs. * It is an IA-32 (Pentium x86 ISA) compatible SoC. The core CPU in the * X10xx is codenamed Lakemont. Lakemont version 1 (LMT1) is used in X10xx. * The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is * used for SoC level operations. * Useful docs are here: https://communities.intel.com/community/makers/documentation * Intel Quark SoC X1000 OpenOCD/GDB/Eclipse App Note (web search for doc num 330015) * Intel Quark SoC X1000 Debug Operations User Guide (web search for doc num 329866) * Intel Quark SoC X1000 Datasheet (web search for doc num 329676) * * This file implements any Quark SoC specific features such as resetbreak (TODO) */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "target_type.h" #include "lakemont.h" #include "x86_32_common.h" int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) { struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common)); if (x86_32 == NULL) { LOG_ERROR("%s out of memory", __func__); return ERROR_FAIL; } x86_32_common_init_arch_info(t, x86_32); lakemont_init_arch_info(t, x86_32); return ERROR_OK; } int quark_x10xx_init_target(struct command_context *cmd_ctx, struct target *t) { return lakemont_init_target(cmd_ctx, t); } struct target_type quark_x10xx_target = { .name = "quark_x10xx", /* Quark X1000 SoC */ .target_create = quark_x10xx_target_create, .init_target = quark_x10xx_init_target, /* lakemont probemode specific code */ .poll = lakemont_poll, .arch_state = lakemont_arch_state, .halt = lakemont_halt, .resume = lakemont_resume, .step = lakemont_step, .assert_reset = lakemont_reset_assert, .deassert_reset = lakemont_reset_deassert, /* common x86 code */ .commands = x86_32_command_handlers, .get_gdb_reg_list = x86_32_get_gdb_reg_list, .read_memory = x86_32_common_read_memory, .write_memory = x86_32_common_write_memory, .add_breakpoint = x86_32_common_add_breakpoint, .remove_breakpoint = x86_32_common_remove_breakpoint, .add_watchpoint = x86_32_common_add_watchpoint, .remove_watchpoint = x86_32_common_remove_watchpoint, .virt2phys = x86_32_common_virt2phys, .read_phys_memory = x86_32_common_read_phys_mem, .write_phys_memory = x86_32_common_write_phys_mem, .mmu = x86_32_common_mmu, }; openocd-0.9.0/src/target/armv4_5_mmu.c0000644000175000017500000001340612315575361014460 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "armv4_5_mmu.h" int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va, uint32_t *cb, uint32_t *val) { uint32_t first_lvl_descriptor = 0x0; uint32_t second_lvl_descriptor = 0x0; uint32_t ttb; int retval; retval = armv4_5_mmu->get_ttb(target, &ttb); if (retval != ERROR_OK) return retval; retval = armv4_5_mmu_read_physical(target, armv4_5_mmu, (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18), 4, 1, (uint8_t *)&first_lvl_descriptor); if (retval != ERROR_OK) return retval; first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&first_lvl_descriptor); LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor); if ((first_lvl_descriptor & 0x3) == 0) { LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3)) { LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } if ((first_lvl_descriptor & 0x3) == 2) { /* section descriptor */ *cb = (first_lvl_descriptor & 0xc) >> 2; *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff); return ERROR_OK; } if ((first_lvl_descriptor & 0x3) == 1) { /* coarse page table */ retval = armv4_5_mmu_read_physical(target, armv4_5_mmu, (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10), 4, 1, (uint8_t *)&second_lvl_descriptor); if (retval != ERROR_OK) return retval; } else if ((first_lvl_descriptor & 0x3) == 3) { /* fine page table */ retval = armv4_5_mmu_read_physical(target, armv4_5_mmu, (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8), 4, 1, (uint8_t *)&second_lvl_descriptor); if (retval != ERROR_OK) return retval; } second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&second_lvl_descriptor); LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor); if ((second_lvl_descriptor & 0x3) == 0) { LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } /* cacheable/bufferable is always specified in bits 3-2 */ *cb = (second_lvl_descriptor & 0xc) >> 2; if ((second_lvl_descriptor & 0x3) == 1) { /* large page descriptor */ *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff); return ERROR_OK; } if ((second_lvl_descriptor & 0x3) == 2) { /* small page descriptor */ *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff); return ERROR_OK; } if ((second_lvl_descriptor & 0x3) == 3) { /* tiny page descriptor */ *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff); return ERROR_OK; } /* should not happen */ LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } int armv4_5_mmu_read_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; /* disable MMU and data (or unified) cache */ retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0); if (retval != ERROR_OK) return retval; retval = armv4_5_mmu->read_memory(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; /* reenable MMU / cache */ retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled, armv4_5_mmu->armv4_5_cache.d_u_cache_enabled, armv4_5_mmu->armv4_5_cache.i_cache_enabled); if (retval != ERROR_OK) return retval; return retval; } int armv4_5_mmu_write_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; /* disable MMU and data (or unified) cache */ retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0); if (retval != ERROR_OK) return retval; retval = armv4_5_mmu->write_memory(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; /* reenable MMU / cache */ retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled, armv4_5_mmu->armv4_5_cache.d_u_cache_enabled, armv4_5_mmu->armv4_5_cache.i_cache_enabled); if (retval != ERROR_OK) return retval; return retval; } openocd-0.9.0/src/target/armv4_5_mmu.h0000644000175000017500000000530712315575361014466 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARMV4_5_MMU_H #define ARMV4_5_MMU_H #include "armv4_5_cache.h" struct target; struct armv4_5_mmu_common { int (*get_ttb)(struct target *target, uint32_t *result); int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int (*disable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); int (*enable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); struct armv4_5_cache_common armv4_5_cache; int has_tiny_pages; int mmu_enabled; }; int armv4_5_mmu_translate_va(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va, uint32_t *cb, uint32_t *val); int armv4_5_mmu_read_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int armv4_5_mmu_write_physical(struct target *target, struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); enum { ARMV4_5_MMU_ENABLED = 0x1, ARMV4_5_ALIGNMENT_CHECK = 0x2, ARMV4_5_MMU_S_BIT = 0x100, ARMV4_5_MMU_R_BIT = 0x200 }; #endif /* ARMV4_5_MMU_H */ openocd-0.9.0/src/target/adi_v5_jtag.c0000644000175000017500000003332312516456303014476 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * lundin@mlu.mine.nu * * Copyright (C) 2008 by Spencer Oliver * spen@spen-soft.co.uk * * Copyright (C) 2009 by Oyvind Harboe * oyvind.harboe@zylin.com * * Copyright (C) 2009-2010 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ***************************************************************************/ /** * @file * This file implements JTAG transport support for cores implementing the ARM Debug Interface version 5 (ADIv5). */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "arm_adi_v5.h" #include /* JTAG instructions/registers for JTAG-DP and SWJ-DP */ #define JTAG_DP_ABORT 0x8 #define JTAG_DP_DPACC 0xA #define JTAG_DP_APACC 0xB #define JTAG_DP_IDCODE 0xE /* three-bit ACK values for DPACC and APACC reads */ #define JTAG_ACK_OK_FAULT 0x2 #define JTAG_ACK_WAIT 0x1 static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack); /*************************************************************************** * * DPACC and APACC scanchain access through JTAG-DP (or SWJ-DP) * ***************************************************************************/ /** * Scan DPACC or APACC using target ordered uint8_t buffers. No endianness * conversions are performed. See section 4.4.3 of the ADIv5 spec, which * discusses operations which access these registers. * * Note that only one scan is performed. If RnW is set, a separate scan * will be needed to collect the data which was read; the "invalue" collects * the posted result of a preceding operation, not the current one. * * @param dap the DAP * @param instr JTAG_DP_APACC (AP access) or JTAG_DP_DPACC (DP access) * @param reg_addr two significant bits; A[3:2]; for APACC access, the * SELECT register has more addressing bits. * @param RnW false iff outvalue will be written to the DP or AP * @param outvalue points to a 32-bit (little-endian) integer * @param invalue NULL, or points to a 32-bit (little-endian) integer * @param ack points to where the three bit JTAG_ACK_* code will be stored */ static int adi_jtag_dp_scan(struct adiv5_dap *dap, uint8_t instr, uint8_t reg_addr, uint8_t RnW, uint8_t *outvalue, uint8_t *invalue, uint8_t *ack) { struct arm_jtag *jtag_info = dap->jtag_info; struct scan_field fields[2]; uint8_t out_addr_buf; int retval; retval = arm_jtag_set_instr(jtag_info, instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; /* Scan out a read or write operation using some DP or AP register. * For APACC access with any sticky error flag set, this is discarded. */ fields[0].num_bits = 3; buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); fields[0].out_value = &out_addr_buf; fields[0].in_value = ack; /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not * complete; data we write is discarded, data we read is unpredictable. * When overrun detect is active, STICKYORUN is set. */ fields[1].num_bits = 32; fields[1].out_value = outvalue; fields[1].in_value = invalue; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); /* Add specified number of tck clocks after starting memory bus * access, giving the hardware time to complete the access. * They provide more time for the (MEM) AP to complete the read ... * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. */ if ((instr == JTAG_DP_APACC) && ((reg_addr == AP_REG_DRW) || ((reg_addr & 0xF0) == AP_REG_BD0)) && (dap->memaccess_tck != 0)) jtag_add_runtest(dap->memaccess_tck, TAP_IDLE); return ERROR_OK; } /** * Scan DPACC or APACC out and in from host ordered uint32_t buffers. * This is exactly like adi_jtag_dp_scan(), except that endianness * conversions are performed (so the types of invalue and outvalue * must be different). */ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, uint8_t instr, uint8_t reg_addr, uint8_t RnW, uint32_t outvalue, uint32_t *invalue, uint8_t *ack) { uint8_t out_value_buf[4]; int retval; buf_set_u32(out_value_buf, 0, 32, outvalue); retval = adi_jtag_dp_scan(dap, instr, reg_addr, RnW, out_value_buf, (uint8_t *)invalue, ack); if (retval != ERROR_OK) return retval; if (invalue) jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t) invalue); return retval; } /** * Utility to write AP registers. */ static inline int adi_jtag_ap_write_check(struct adiv5_dap *dap, uint8_t reg_addr, uint8_t *outvalue) { return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE, outvalue, NULL, NULL); } static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap, uint8_t instr, uint8_t reg_addr, uint8_t RnW, uint32_t outvalue, uint32_t *invalue) { int retval; /* Issue the read or write */ retval = adi_jtag_dp_scan_u32(dap, instr, reg_addr, RnW, outvalue, NULL, NULL); if (retval != ERROR_OK) return retval; /* For reads, collect posted value; RDBUFF has no other effect. * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK". */ if ((RnW == DPAP_READ) && (invalue != NULL)) retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &dap->ack); return retval; } static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) { int retval; uint32_t ctrlstat; /* too expensive to call keep_alive() here */ /* Here be dragons! * * It is easy to be in a JTAG clock range where the target * is not operating in a stable fashion. This happens * for a few reasons: * * - the user may construct a simple test case to try to see * if a higher JTAG clock works to eke out more performance. * This simple case may pass, but more complex situations can * fail. * * - The mostly works JTAG clock rate and the complete failure * JTAG clock rate may be as much as 2-4x apart. This seems * to be especially true on RC oscillator driven parts. * * So: even if calling adi_jtag_scan_inout_check_u32() multiple * times here seems to "make things better here", it is just * hiding problems with too high a JTAG clock. * * Note that even if some parts have RCLK/RTCK, that doesn't * mean that RCLK/RTCK is the *correct* rate to run the JTAG * interface at, i.e. RCLK/RTCK rates can be "too high", especially * before the RC oscillator phase is not yet complete. */ /* Post CTRL/STAT read; discard any previous posted read value * but collect its ACK status. */ retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; dap->ack = dap->ack & 0x7; /* common code path avoids calling timeval_ms() */ if (dap->ack != JTAG_ACK_OK_FAULT) { long long then = timeval_ms(); while (dap->ack != JTAG_ACK_OK_FAULT) { if (dap->ack == JTAG_ACK_WAIT) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting " "for ACK=OK/FAULT " "in JTAG-DP transaction - aborting"); uint8_t ack; int abort_ret = jtag_ap_q_abort(dap, &ack); if (abort_ret != 0) LOG_WARNING("Abort failed : return=%d ack=%d", abort_ret, ack); return ERROR_JTAG_DEVICE_ERROR; } } else { LOG_WARNING("Invalid ACK %#x " "in JTAG-DP transaction", dap->ack); return ERROR_JTAG_DEVICE_ERROR; } retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; dap->ack = dap->ack & 0x7; } } /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */ /* Check for STICKYERR and STICKYORUN */ if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) { LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat); /* Check power to debug regions */ if ((ctrlstat & 0xf0000000) != 0xf0000000) { LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened"); return ERROR_JTAG_DEVICE_ERROR; } else { uint32_t mem_ap_csw, mem_ap_tar; /* Maybe print information about last intended * MEM-AP access; but not if autoincrementing. * *Real* CSW and TAR values are always shown. */ if (dap->ap_tar_value != (uint32_t) -1) LOG_DEBUG("MEM-AP Cached values: " "ap_bank 0x%" PRIx32 ", ap_csw 0x%" PRIx32 ", ap_tar 0x%" PRIx32, dap->ap_bank_value, dap->ap_csw_value, dap->ap_tar_value); if (ctrlstat & SSTICKYORUN) LOG_ERROR("JTAG-DP OVERRUN - check clock, " "memaccess, or reduce jtag speed"); if (ctrlstat & SSTICKYERR) LOG_ERROR("JTAG-DP STICKY ERROR"); /* Clear Sticky Error Bits */ retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, DP_CTRL_STAT, DPAP_WRITE, dap->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL); if (retval != ERROR_OK) return retval; retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat); retval = dap_queue_ap_read(dap, AP_REG_CSW, &mem_ap_csw); if (retval != ERROR_OK) return retval; retval = dap_queue_ap_read(dap, AP_REG_TAR, &mem_ap_tar); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%" PRIx32, mem_ap_csw, mem_ap_tar); } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } /*--------------------------------------------------------------------------*/ static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, reg, DPAP_READ, 0, data); } static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, reg, DPAP_WRITE, data, NULL); } /** Select the AP register bank matching bits 7:4 of reg. */ static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg) { uint32_t select_ap_bank = reg & 0x000000F0; if (select_ap_bank == dap->ap_bank_value) return ERROR_OK; dap->ap_bank_value = select_ap_bank; select_ap_bank |= dap->ap_current; return jtag_dp_q_write(dap, DP_SELECT, select_ap_bank); } static int jtag_ap_q_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { int retval = jtag_ap_q_bankselect(dap, reg); if (retval != ERROR_OK) return retval; return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_APACC, reg, DPAP_READ, 0, data); } static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { uint8_t out_value_buf[4]; int retval = jtag_ap_q_bankselect(dap, reg); if (retval != ERROR_OK) return retval; buf_set_u32(out_value_buf, 0, 32, data); return adi_jtag_ap_write_check(dap, reg, out_value_buf); } static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack) { /* for JTAG, this is the only valid ABORT register operation */ return adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT, 0, DPAP_WRITE, 1, NULL, ack); } static int jtag_dp_run(struct adiv5_dap *dap) { return jtagdp_transaction_endcheck(dap); } /* FIXME don't export ... just initialize as * part of DAP setup */ const struct dap_ops jtag_dp_ops = { .queue_dp_read = jtag_dp_q_read, .queue_dp_write = jtag_dp_q_write, .queue_ap_read = jtag_ap_q_read, .queue_ap_write = jtag_ap_q_write, .queue_ap_abort = jtag_ap_q_abort, .run = jtag_dp_run, }; static const uint8_t swd2jtag_bitseq[] = { /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, * putting both JTAG and SWD logic into reset state. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Switching equence disables SWD and enables JTAG * NOTE: bits in the DP's IDCODE can expose the need for * the old/deprecated sequence (0xae 0xde). */ 0x3c, 0xe7, /* At least 50 TCK/SWCLK cycles with TMS/SWDIO high, * putting both JTAG and SWD logic into reset state. * NOTE: some docs say "at least 5". */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; /** Put the debug link into JTAG mode, if the target supports it. * The link's initial mode may be either SWD or JTAG. * * @param target Enters JTAG mode (if possible). * * Note that targets implemented with SW-DP do not support JTAG, and * that some targets which could otherwise support it may have been * configured to disable JTAG signaling * * @return ERROR_OK or else a fault code. */ int dap_to_jtag(struct target *target) { int retval; LOG_DEBUG("Enter JTAG mode"); /* REVISIT it's nasty to need to make calls to a "jtag" * subsystem if the link isn't in JTAG mode... */ retval = jtag_add_tms_seq(8 * sizeof(swd2jtag_bitseq), swd2jtag_bitseq, TAP_RESET); if (retval == ERROR_OK) retval = jtag_execute_queue(); /* REVISIT set up the DAP's ops vector for JTAG mode. */ return retval; } openocd-0.9.0/src/target/nds32_disassembler.c0000644000175000017500000040342212315575361016014 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "nds32_disassembler.h" static const int enable4_bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value) { struct target *target = nds32->target; uint8_t value_buf[4]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } int retval = target_read_buffer(target, address, 4, value_buf); if (retval == ERROR_OK) { /* instructions are always big-endian */ *value = be_to_h_u32(value_buf); LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", address, *value); } else { *value = 0x0; LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", address); } return retval; } static int nds32_parse_type_0(uint32_t opcode, int32_t *imm) { *imm = opcode & 0x1FFFFFF; return ERROR_OK; } static int nds32_parse_type_1(uint32_t opcode, uint8_t *rt, int32_t *imm) { *rt = (opcode >> 20) & 0x1F; *imm = opcode & 0xFFFFF; return ERROR_OK; } static int nds32_parse_type_2(uint32_t opcode, uint8_t *rt, uint8_t *ra, int32_t *imm) { *rt = (opcode >> 20) & 0x1F; *ra = (opcode >> 15) & 0x1F; *imm = opcode & 0x7FFF; return ERROR_OK; } static int nds32_parse_type_3(uint32_t opcode, uint8_t *rt, uint8_t *ra, uint8_t *rb, int32_t *imm) { *rt = (opcode >> 20) & 0x1F; *ra = (opcode >> 15) & 0x1F; *rb = (opcode >> 10) & 0x1F; *imm = opcode & 0x3FF; return ERROR_OK; } static int nds32_parse_type_4(uint32_t opcode, uint8_t *rt, uint8_t *ra, uint8_t *rb, uint8_t *rd, uint8_t *sub_opc) { *rt = (opcode >> 20) & 0x1F; *ra = (opcode >> 15) & 0x1F; *rb = (opcode >> 10) & 0x1F; *rd = (opcode >> 5) & 0x1F; *sub_opc = opcode & 0x1F; return ERROR_OK; } /* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */ static int nds32_parse_group_0_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 0: /* LBI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 1: /* LHI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 2: /* LWI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 4: /* LBI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 5: /* LHI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 6: /* LWI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32 "", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_1_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 0: /* SBI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 1: /* SHI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 2: /* SWI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 4: /* SBI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 5: /* SHI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 6: /* SWI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_2_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 0: /* LBSI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 1: /* LHSI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 3: { /* DPREFI */ uint8_t sub_type; nds32_parse_type_2(opcode, &sub_type, &(instruction->info.ra), &(instruction->info.imm)); instruction->info.sub_opc = sub_type & 0xF; instruction->type = NDS32_INSN_MISC; if (sub_type & 0x10) { /* DPREFI.d */ /* sign-extend */ instruction->info.imm = (instruction->info.imm << 17) >> 14; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREFI.d\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.sub_opc, instruction->info.ra, instruction->info.imm); } else { /* DPREFI.w */ /* sign-extend */ instruction->info.imm = (instruction->info.imm << 17) >> 15; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREFI.w\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]", address, opcode, instruction->info.sub_opc, instruction->info.ra, instruction->info.imm); } } break; case 4: /* LBSI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 5: /* LHSI.bi */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 6: /* LBGP */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; if ((instruction->info.imm >> 19) & 0x1) { /* LBSI.gp */ instruction->info.imm = (instruction->info.imm << 13) >> 13; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } else { /* LBI.gp */ instruction->info.imm = (instruction->info.imm << 13) >> 13; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_mem(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint32_t sub_opcode = opcode & 0x3F; uint32_t val_ra, val_rb; switch (sub_opcode >> 3) { case 0: switch (sub_opcode & 0x7) { case 0: /* LB */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), \ &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 1: /* LH */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 2: /* LW */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 4: /* LB.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 5: /* LH.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 6: /* LW.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; case 1: switch (sub_opcode & 0x7) { case 0: /* SB */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 1: /* SH */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 2: /* SW */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 4: /* SB.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 5: /* SH.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 6: /* SW.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; case 2: switch (sub_opcode & 0x7) { case 0: /* LBS */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 1: /* LHS */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 3: /* DPREF */ nds32_parse_type_3(opcode, &(instruction->info.sub_opc), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREF\t#%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<#%" PRId32 ")]", address, opcode, instruction->info.sub_opc, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 4: /* LBS.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 5: /* LHS.bi */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; case 3: switch (sub_opcode & 0x7) { case 0: /* LLW */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 1: /* SCW */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSCW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; case 4: switch (sub_opcode & 0x7) { case 0: /* LBUP */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 2: /* LWUP */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; case 5: switch (sub_opcode & 0x7) { case 0: /* SBUP */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; case 2: /* SWUP */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra); nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb); instruction->access_start = val_ra + (val_rb << ((instruction->info.imm >> 8) & 0x3)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, (instruction->info.imm >> 8) & 0x3); break; } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_calculate_lsmw_access_range(struct nds32 *nds32, struct nds32_instruction *instruction) { uint8_t ba; uint8_t id; uint8_t enable4; enable4 = (instruction->info.imm >> 6) & 0xF; ba = (instruction->info.imm >> 4) & 0x1; id = (instruction->info.imm >> 3) & 0x1; if (ba) { nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); if (id) { /* decrease */ /* access_end is the (last_element+1), so no need to minus 4 */ /* instruction->access_end -= 4; */ instruction->access_end = instruction->access_start; } else { /* increase */ instruction->access_start += 4; } } else { nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start - 4; } if (id) { /* decrease */ instruction->access_start = instruction->access_end - 4 * (instruction->info.rd - instruction->info.rb + 1); instruction->access_start -= (4 * enable4_bits[enable4]); } else { /* increase */ instruction->access_end = instruction->access_start + 4 * (instruction->info.rd - instruction->info.rb + 1); instruction->access_end += (4 * enable4_bits[enable4]); } return ERROR_OK; } static int nds32_parse_lsmw(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { if (opcode & 0x20) { /* SMW, SMWA, SMWZB */ switch (opcode & 0x3) { /* TODO */ case 0: /* SMW */ /* use rd as re */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_calculate_lsmw_access_range(nds32, instruction); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; case 1: /* SMWA */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_calculate_lsmw_access_range(nds32, instruction); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; case 2: /* SMWZB */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; /* TODO: calculate access_start/access_end */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } else { /* LMW, LMWA, LMWZB */ switch (opcode & 0x3) { case 0: /* LMW */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_calculate_lsmw_access_range(nds32, instruction); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; case 1: /* LMWA */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; nds32_calculate_lsmw_access_range(nds32, instruction); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; case 2: /* LMWZB */ nds32_parse_type_3(opcode, &(instruction->info.rb), &(instruction->info.ra), &(instruction->info.rd), &(instruction->info.imm)); instruction->type = NDS32_INSN_LOAD_STORE; /* TODO: calculate access_start/access_end */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rb, instruction->info.ra, instruction->info.rd, (instruction->info.imm >> 6) & 0xF); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } return ERROR_OK; } static int nds32_parse_hwgp(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 18) & 0x3) { case 0: /* LHI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI.gp\t$r%" PRIu8 ",[#%" PRId32"]", address, opcode, instruction->info.rt, instruction->info.imm); break; case 1: /* LHSI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); break; case 2: /* SHI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); break; case 3: instruction->type = NDS32_INSN_LOAD_STORE; if ((opcode >> 17) & 0x1) { /* SWI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 15) >> 13; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } else { /* LWI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 15) >> 13; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_sbgp(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 19) & 0x1) { case 0: /* SBI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */ instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R29, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); break; case 1: /* ADDI.gp */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */ instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADDI.gp\t$r%" PRIu8 ",#%" PRId32 "", address, opcode, instruction->info.rt, instruction->info.imm); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_3_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 4: /* MEM */ nds32_parse_mem(nds32, opcode, address, instruction); break; case 5: /* LSMW */ nds32_parse_lsmw(nds32, opcode, address, instruction); break; case 6: /* HWGP */ nds32_parse_hwgp(nds32, opcode, address, instruction); break; case 7: /* SBGP */ nds32_parse_sbgp(nds32, opcode, address, instruction); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_alu_1(uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch (opcode & 0x1F) { case 0: /* ADD */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 1: /* SUB */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 2: /* AND */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 3: /* XOR */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 4: /* OR */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 5: /* NOR */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 6: /* SLT */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLT\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 7: /* SLTS */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLTS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 8: { /* SLLI */ uint8_t imm; int32_t sub_op; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &sub_op); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 9: { /* SRLI */ uint8_t imm; int32_t sub_op; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &sub_op); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 10: { /* SRAI */ uint8_t imm; int32_t sub_op; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &sub_op); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRAI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 11: { /* ROTRI */ uint8_t imm; int32_t sub_op; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &sub_op); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tROTRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 12: { /* SLL */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 13: { /* SRL */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 14: { /* SRA */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 15: { /* ROTR */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tROTR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 16: { /* SEB */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSEB\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); } break; case 17: { /* SEH */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSEH\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); } break; case 18: /* BITC */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBITC\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 19: { /* ZEH */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tZEH\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); } break; case 20: { /* WSBH */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tWSBH\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); } break; case 21: /* OR_SRLI */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 22: { /* DIVSR */ nds32_parse_type_4(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.rd), &(instruction->info.sub_opc)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIVSR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.rd); } break; case 23: { /* DIVR */ nds32_parse_type_4(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.rd), &(instruction->info.sub_opc)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIVR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.rd); } break; case 24: { /* SVA */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 25: { /* SVS */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 26: { /* CMOVZ */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCMOVZ\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 27: { /* CMOVN */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCMOVN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 28: /* ADD_SRLI */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 29: /* SUB_SRLI */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 30: /* AND_SRLI */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 31: /* XOR_SRLI */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; instruction->info.imm = (instruction->info.imm >> 5) & 0x1F; if (instruction->info.imm) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb, instruction->info.imm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_alu_2(uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch (opcode & 0x3F) { case 0: /* MAX */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMAX\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 1: /* MIN */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMIN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 2: /* AVE */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAVE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 3: /* ABS */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAVE\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 4: { /* CLIPS */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLIPS\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 5: { /* CLIP */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLIP\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 6: /* CLO */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLO\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 7: /* CLZ */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 8: { /* BSET */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBSET\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 9: { /* BCLR */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBCLR\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 10: { /* BTGL */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBTGL\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 11: { /* BTST */ uint8_t imm; nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &imm, &(instruction->info.imm)); instruction->info.imm = imm; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBTST\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; case 12: /* BSE */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBSE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 13: /* BSP */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBSP\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 14: /* FFB */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tFFB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 15: /* FFMISM */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tFFMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 23: /* FFZMISM */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tFFZMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 32: /* MFUSR */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->type = NDS32_INSN_RESOURCE_ACCESS; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMFUSR\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, (instruction->info.imm >> 10) & 0x3FF); break; case 33: /* MTUSR */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->type = NDS32_INSN_RESOURCE_ACCESS; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMTUSR\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, (instruction->info.imm >> 10) & 0x3FF); break; case 36: /* MUL */ nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); break; case 40: { /* MULTS64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMULTS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 41: { /* MULT64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMULT64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 42: { /* MADDS64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMADDS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 43: { /* MADD64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMADD64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 44: { /* MSUBS64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSUBS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 45: { /* MSUB64 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSUB64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 46: { /* DIVS */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIVS\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 47: { /* DIV */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIV\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 49: { /* MULT32 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMULT32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 51: { /* MADD32 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMADD32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; case 53: { /* MSUB32 */ uint8_t dt_val; nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra), &(instruction->info.rb), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSUB32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra, instruction->info.rb); } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_4_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 0: /* ALU_1 */ nds32_parse_alu_1(opcode, address, instruction); break; case 1: /* ALU_2 */ nds32_parse_alu_2(opcode, address, instruction); break; case 2: /* MOVI */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 12) >> 12; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOVI\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 3: /* SETHI */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSETHI\t$r%" PRIu8 ",0x%8.8" PRIx32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 4: /* JI */ nds32_parse_type_0(opcode, &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 8) >> 8; instruction->type = NDS32_INSN_JUMP_BRANCH; if ((instruction->info.imm >> 24) & 0x1) { /* JAL */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJAL\t#%" PRId32, address, opcode, instruction->info.imm); } else { /* J */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJ\t#%" PRId32, address, opcode, instruction->info.imm); } break; case 5: { /* JREG */ int32_t imm; nds32_parse_type_0(opcode, &imm); instruction->info.rb = (imm >> 10) & 0x1F; instruction->type = NDS32_INSN_JUMP_BRANCH; switch (imm & 0x1F) { /* TODO */ case 0: /* JR */ if (imm & 0x20) { /* RET */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tRET\t$r%" PRIu8, address, opcode, instruction->info.rb); } else { /* JR */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJR\t$r%" PRIu8, address, opcode, instruction->info.rb); } break; case 1: /* JRAL */ instruction->info.rt = (imm >> 20) & 0x1F; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJRAL\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.rb); break; case 2: /* JRNEZ */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJRNEZ\t$r%" PRIu8, address, opcode, instruction->info.rb); break; case 3: /* JRALNEZ */ instruction->info.rt = (imm >> 20) & 0x1F; if (instruction->info.rt == R30) snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJRALNEZ\t$r%" PRIu8, address, opcode, instruction->info.rb); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tJRALNEZ\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.rb); break; } } break; case 6: { /* BR1 */ int32_t imm; nds32_parse_type_0(opcode, &imm); instruction->type = NDS32_INSN_JUMP_BRANCH; if ((imm >> 14) & 0x1) { /* BNE */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 18) >> 18; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBNE\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } else { /* BEQ */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); /* sign-extend */ instruction->info.imm = (instruction->info.imm << 18) >> 18; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBEQ\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } } break; case 7: { /* BR2 */ int32_t imm; nds32_parse_type_0(opcode, &imm); instruction->type = NDS32_INSN_JUMP_BRANCH; switch ((imm >> 16) & 0xF) { case 2: /* BEQZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBEQZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 3: /* BNEZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBNEZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 4: /* BGEZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBGEZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 5: /* BLTZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLTZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 6: /* BGTZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBGTZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 7: /* BLEZ */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLEZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 12: /* BGEZAL */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBGEZAL\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 13: /* BLTZAL */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 16) >> 16; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLTZAL\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; } } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_5_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 0: /* ADDI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 1: /* SUBRI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUBRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 2: /* ANDI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tANDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 3: /* XORI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXORI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 4: /* ORI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tORI\t$r%" PRIu8 ",$r%" PRIu8 ",0x%8.8" PRIx32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 6: /* SLTI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLTI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 7: /* SLTSI */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */ instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLTSI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_6_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { uint8_t opc_6; opc_6 = instruction->info.opc_6; switch (opc_6 & 0x7) { case 2: { /* MISC */ int32_t imm; uint8_t sub_opc; nds32_parse_type_0(opcode, &imm); sub_opc = imm & 0x1F; switch (sub_opc) { case 0: /* STANDBY */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSTANDBY\t#%" PRIu32, address, opcode, (opcode >> 5) & 0x3); break; case 1: /* CCTL */ /* TODO */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCCTL", address, opcode); break; case 2: /* MFSR */ nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm)); instruction->type = NDS32_INSN_RESOURCE_ACCESS; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMFSR\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, (instruction->info.imm >> 10) & 0x3FF); break; case 3: /* MTSR */ nds32_parse_type_1(opcode, &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_RESOURCE_ACCESS; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMTSR\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.ra, (instruction->info.imm >> 10) & 0x3FF); break; case 4: /* IRET */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tIRET", address, opcode); break; case 5: /* TRAP */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTRAP\t#%" PRId32, address, opcode, (imm >> 5) & 0x7FFF); break; case 6: /* TEQZ */ nds32_parse_type_1(opcode, &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTEQZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.ra, (instruction->info.imm >> 5) & 0x7FFF); break; case 7: /* TNEZ */ nds32_parse_type_1(opcode, &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTNEZ\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.ra, (instruction->info.imm >> 5) & 0x7FFF); break; case 8: /* DSB */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB", address, opcode); break; case 9: /* ISB */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB", address, opcode); break; case 10: /* BREAK */ instruction->type = NDS32_INSN_MISC; instruction->info.sub_opc = imm & 0x1F; instruction->info.imm = (imm >> 5) & 0x7FFF; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBREAK\t#%" PRId32, address, opcode, instruction->info.imm); break; case 11: /* SYSCALL */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSYSCALL\t#%" PRId32, address, opcode, (imm >> 5) & 0x7FFF); break; case 12: /* MSYNC */ instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSYNC\t#%" PRId32, address, opcode, (imm >> 5) & 0x7); break; case 13: /* ISYNC */ nds32_parse_type_1(opcode, &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISYNC\t$r%" PRIu8, address, opcode, instruction->info.ra); break; case 14: /* TLBOP */ /* TODO */ nds32_parse_type_2(opcode, &(instruction->info.rt), &(instruction->info.ra), &(instruction->info.imm)); instruction->type = NDS32_INSN_RESOURCE_ACCESS; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTLBOP", address, opcode); break; } break; } default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static uint32_t field_mask[9] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, }; static uint8_t nds32_extract_field_8u(uint16_t opcode, uint32_t start, uint32_t length) { if (0 < length && length < 9) return (opcode >> start) & field_mask[length]; return 0; } static int nds32_parse_group_0_insn_16(struct nds32 *nds32, uint16_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 10) & 0x7) { case 0: /* MOV55 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5); instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tMOV55\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 1: /* MOVI55 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->info.imm = (instruction->info.imm << 27) >> 27; instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tMOVI55\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 2: /* ADD45, SUB45 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD45 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADD45\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.rb); } else { /* SUB45 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSUB45\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.rb); } break; case 3: /* ADDI45, SUBI45 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI45 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADDI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } else { /* SUBI45 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSUBI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } break; case 4: /* SRAI45, SRLI45 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SRAI45 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSRAI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } else { /* SRLI45 */ if ((instruction->info.rt == 0) && (instruction->info.imm == 0)) { snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tNOP", address, opcode); } else { snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSRLI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } } break; case 5: instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SLLI333 */ instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSLLI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } else { instruction->info.sub_opc = nds32_extract_field_8u(opcode, 0, 3); switch (instruction->info.sub_opc) { case 0: /* ZEB33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tZEB33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 1: /* ZEH33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tZEH33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 2: /* SEB33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSEB33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 3: /* SEH33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSEH33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 4: /* XLSB33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tXLSB33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 5: /* XLLB33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tXLLB33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 6: /* BMSKI33 */ instruction->info.ra = 0; instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBMSKI33\t$r%" PRIu8 ",$r%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 7: /* FEXTI33 */ instruction->info.ra = 0; instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tFEXTI33\t$r%" PRIu8 ",$r%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } break; case 6: /* ADD333, SUB333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.rb = nds32_extract_field_8u(opcode, 0, 3); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD333 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADD333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } else { /* SUB333 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSUB333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.rb); } break; case 7: /* ADDI333, SUBI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3); instruction->type = NDS32_INSN_DATA_PROC; if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI333 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADDI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } else { /* SUBI333 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSUBI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_1_insn_16(struct nds32 *nds32, uint16_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 9) & 0xF) { case 0: /* LWI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 1: /* LWI333.BI */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm << 2); break; case 2: /* LHI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 3: /* LBI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLBI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 4: /* SWI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 5: /* SWI333.BI */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32, address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 6: /* SHI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 2; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 7: /* SBI333 */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 1; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]", address, opcode, instruction->info.rt, instruction->info.ra, instruction->info.imm); break; case 8: /* ADDRI36.SP */ instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 6) << 2; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADDRI36.SP\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 9: /* LWI45.FE */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->info.imm -= 32; instruction->info.imm <<= 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R8, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI45.FE\t$r%" PRIu8 ",[#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); break; case 10: /* LWI450 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI450\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 11: /* SWI450 */ instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start)); instruction->access_end = instruction->access_start + 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSWI450\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 12: case 13: case 14: case 15: /* LWI37, SWI37 */ instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R28, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } else { /* SWI37 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } break; default: /* ERROR */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } static int nds32_parse_group_2_insn_16(struct nds32 *nds32, uint16_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 11) & 0x3) { case 0: /* BEQZ38 */ instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8); instruction->info.imm = (instruction->info.imm << 24) >> 24; instruction->type = NDS32_INSN_JUMP_BRANCH; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBEQZ38\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 1: /* BNEZ38 */ instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8); instruction->info.imm = (instruction->info.imm << 24) >> 24; instruction->type = NDS32_INSN_JUMP_BRANCH; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBNEZ38\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); break; case 2: /* BEQS38,J8 */ instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8); instruction->info.imm = (instruction->info.imm << 24) >> 24; instruction->type = NDS32_INSN_JUMP_BRANCH; if (instruction->info.rt == 5) { /* J8 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tJ8\t#%" PRId32, address, opcode, instruction->info.imm); } else { /* BEQS38 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBEQS38\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } break; case 3: /* BNES38, JR5, RET5, JRAL5 */ instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8); instruction->info.imm = (instruction->info.imm << 24) >> 24; instruction->type = NDS32_INSN_JUMP_BRANCH; if (instruction->info.rt == 5) { instruction->info.imm = 0; instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5); switch (nds32_extract_field_8u(opcode, 5, 3)) { case 0: /* JR5 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tJR5\t$r%" PRIu8, address, opcode, instruction->info.rb); break; case 1: /* JRAL5 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tJRAL5\t$r%" PRIu8, address, opcode, instruction->info.rb); break; case 2: /* EX9.IT */ instruction->info.rb = 0; instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); /* TODO: implement real instruction semantics */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tEX9.IT\t#%" PRId32, address, opcode, instruction->info.imm); break; case 4: /* RET5 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tRET5\t$r%" PRIu8, address, opcode, instruction->info.rb); break; case 5: /* ADD5.PC */ instruction->info.rt = 0; instruction->info.rt = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADD5.PC\t$r%" PRIu8, address, opcode, instruction->info.rt); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } else { /* BNES38 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBNES38\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rt, instruction->info.imm); } break; } return ERROR_OK; } static int nds32_parse_group_3_insn_16(struct nds32 *nds32, uint16_t opcode, uint32_t address, struct nds32_instruction *instruction) { switch ((opcode >> 11) & 0x3) { case 0: switch ((opcode >> 9) & 0x3) { case 0: /* SLTS45 */ instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4); instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSLTS45\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.ra, instruction->info.rb); break; case 1: /* SLT45 */ instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4); instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSLT45\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.ra, instruction->info.rb); break; case 2: /* SLTSI45 */ instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSLTSI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.ra, instruction->info.imm); break; case 3: /* SLTI45 */ instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5); instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSLTI45\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.ra, instruction->info.imm); break; } break; case 1: switch ((opcode >> 9) & 0x3) { case 0: instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8); instruction->info.imm = (instruction->info.imm << 24) >> 24; instruction->type = NDS32_INSN_JUMP_BRANCH; if (nds32_extract_field_8u(opcode, 8, 1) == 0) { /* BEQZS8 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBEQZS8\t#%" PRId32, address, opcode, instruction->info.imm); } else { /* BNEZS8 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBNEZS8\t#%" PRId32, address, opcode, instruction->info.imm); } break; case 1: /* BREAK16 */ if (((opcode >> 5) & 0xF) == 0) { instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tBREAK16\t#%" PRId16, address, opcode, (int16_t)(opcode & 0x1F)); } else { /* EX9.IT */ instruction->type = NDS32_INSN_MISC; /* TODO: implement real instruction semantics */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tEX9.IT\t#%" PRId16, address, opcode, (int16_t)(opcode & 0x1FF)); } break; case 2: /* ADDI10S */ case 3: instruction->info.imm = opcode & 0x3FF; instruction->info.imm = (instruction->info.imm << 22) >> 22; instruction->type = NDS32_INSN_DATA_PROC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tADDI10.SP\t#%" PRId32, address, opcode, instruction->info.imm); break; } break; case 2: instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3); instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2; instruction->type = NDS32_INSN_LOAD_STORE; nds32_get_mapped_reg(nds32, R31, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + 4; if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37.SP */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tLWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } else { /* SWI37.SP */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tSWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]", address, opcode, instruction->info.rt, instruction->info.imm); } break; case 3: switch ((opcode >> 9) & 0x3) { case 0: /* IFCALL9 */ instruction->info.imm = opcode & 0x1FF; instruction->type = NDS32_INSN_JUMP_BRANCH; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tIFCALL9\t#%" PRId32 "", address, opcode, instruction->info.imm); break; case 1: /* MOVPI45 */ instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5) + 16; instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4); instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tMOVPI45\t$r%" PRIu8 ",#%" PRId32 "", address, opcode, instruction->info.rt, instruction->info.imm); break; case 2: /* PUSH25, POP25, MOVD44 */ switch ((opcode >> 7) & 0x3) { case 0: /* PUSH25 */ { uint8_t re; uint8_t gpr_count; instruction->type = NDS32_INSN_LOAD_STORE; instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5) << 3; re = nds32_extract_field_8u(opcode, 5, 2); if (re == 0) re = 6; else if (re == 1) re = 8; else if (re == 2) re = 10; else if (re == 3) re = 14; instruction->info.rd = re; /* GPRs list: R6 ~ Re and fp, gp, lp */ gpr_count = 3 + (re - 5); nds32_get_mapped_reg(nds32, R31, &(instruction->access_end)); instruction->access_start = instruction->access_end - (gpr_count * 4); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tPUSH25\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rd, instruction->info.imm); } break; case 1: /* POP25 */ { uint8_t re; uint8_t gpr_count; instruction->type = NDS32_INSN_LOAD_STORE; instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5) << 3; re = nds32_extract_field_8u(opcode, 5, 2); if (re == 0) re = 6; else if (re == 1) re = 8; else if (re == 2) re = 10; else if (re == 3) re = 14; instruction->info.rd = re; /* GPRs list: R6 ~ Re and fp, gp, lp */ gpr_count = 3 + (re - 5); nds32_get_mapped_reg(nds32, R31, &(instruction->access_start)); instruction->access_start += instruction->info.imm; instruction->access_end = instruction->access_start + (gpr_count * 4); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tPOP25\t$r%" PRIu8 ",#%" PRId32, address, opcode, instruction->info.rd, instruction->info.imm); } break; case 2: /* MOVD44 */ case 3: instruction->info.ra = nds32_extract_field_8u(opcode, 0, 4) * 2; instruction->info.rt = nds32_extract_field_8u(opcode, 4, 4) * 2; instruction->type = NDS32_INSN_MISC; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tMOVD44\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; } break; case 3: /* NEG33, NOT33, MUL33, XOR33, AND33, OR33 */ instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3); instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3); instruction->type = NDS32_INSN_DATA_PROC; switch (opcode & 0x7) { case 2: /* NEG33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tNEG33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 3: /* NOT33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tNOT33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 4: /* MUL33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tMUL33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 5: /* XOR33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tXOR33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 6: /* AND33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tAND33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; case 7: /* OR33 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tOR33\t$r%" PRIu8 ",$r%" PRIu8, address, opcode, instruction->info.rt, instruction->info.ra); break; } break; } break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } return ERROR_OK; } int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction) { int retval = ERROR_OK; /* clear fields, to avoid confusion */ memset(instruction, 0, sizeof(struct nds32_instruction)); if (opcode >> 31) { /* 16 bits instruction */ instruction->instruction_size = 2; opcode = (opcode >> 16) & 0xFFFF; instruction->opcode = opcode; switch ((opcode >> 13) & 0x3) { case 0: retval = nds32_parse_group_0_insn_16(nds32, opcode, address, instruction); break; case 1: retval = nds32_parse_group_1_insn_16(nds32, opcode, address, instruction); break; case 2: retval = nds32_parse_group_2_insn_16(nds32, opcode, address, instruction); break; case 3: retval = nds32_parse_group_3_insn_16(nds32, opcode, address, instruction); break; default: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } else { /* 32 bits instruction */ instruction->instruction_size = 4; instruction->opcode = opcode; uint8_t opc_6; opc_6 = opcode >> 25; instruction->info.opc_6 = opc_6; switch ((opc_6 >> 3) & 0x7) { case 0: /* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */ retval = nds32_parse_group_0_insn(nds32, opcode, address, instruction); break; case 1: /* SBI, SHI, SWI, SBI.bi, SHI.bi, SWI.bi */ retval = nds32_parse_group_1_insn(nds32, opcode, address, instruction); break; case 2: /* LBSI, LHSI, DPREFI, LBSI.bi, LHSI.bi, LBGP */ retval = nds32_parse_group_2_insn(nds32, opcode, address, instruction); break; case 3: /* MEM, LSMW, HWGP, SBGP */ retval = nds32_parse_group_3_insn(nds32, opcode, address, instruction); break; case 4: /* ALU_1, ALU_2, MOVI, SETHI, JI, JREG, BR1, BR2 */ retval = nds32_parse_group_4_insn(nds32, opcode, address, instruction); break; case 5: /* ADDI, SUBRI, ANDI, XORI, ORI, SLTI, SLTSI */ retval = nds32_parse_group_5_insn(nds32, opcode, address, instruction); break; case 6: /* MISC */ retval = nds32_parse_group_6_insn(nds32, opcode, address, instruction); break; default: /* ERROR */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_FAIL; } } return retval; } openocd-0.9.0/src/target/nds32_disassembler.h0000644000175000017500000000432412315575361016017 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_DISASSEMBLER_H__ #define __NDS32_DISASSEMBLER_H__ #include enum nds32_instruction_type { NDS32_INSN_DATA_PROC = 0, NDS32_INSN_LOAD_STORE, NDS32_INSN_JUMP_BRANCH, NDS32_INSN_RESOURCE_ACCESS, NDS32_INSN_MISC, }; struct nds32_instruction { enum nds32_instruction_type type; char text[128]; uint32_t opcode; uint8_t instruction_size; uint32_t access_start; uint32_t access_end; struct { uint8_t opc_6; uint8_t rt; uint8_t ra; uint8_t rb; uint8_t rd; uint8_t sub_opc; int32_t imm; } info; }; int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value); int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction); #endif /* __NDS32_DISASSEMBLER_H__ */ openocd-0.9.0/src/target/startup.tcl0000644000175000017500000001216712516456304014370 00000000000000# Defines basic Tcl procs for OpenOCD target module proc new_target_name { } { return [target number [expr [target count] - 1 ]] } global in_process_reset set in_process_reset 0 # Catch reset recursion proc ocd_process_reset { MODE } { global in_process_reset if {$in_process_reset} { set in_process_reset 0 return -code error "'reset' can not be invoked recursively" } set in_process_reset 1 set success [expr [catch {ocd_process_reset_inner $MODE} result]==0] set in_process_reset 0 if {$success} { return $result } else { return -code error $result } } proc ocd_process_reset_inner { MODE } { set targets [target names] # If this target must be halted... set halt -1 if { 0 == [string compare $MODE halt] } { set halt 1 } if { 0 == [string compare $MODE init] } { set halt 1; } if { 0 == [string compare $MODE run ] } { set halt 0; } if { $halt < 0 } { return -code error "Invalid mode: $MODE, must be one of: halt, init, or run"; } # Target event handlers *might* change which TAPs are enabled # or disabled, so we fire all of them. But don't issue any # target "arp_*" commands, which may issue JTAG transactions, # unless we know the underlying TAP is active. # # NOTE: ARP == "Advanced Reset Process" ... "advanced" is # relative to a previous restrictive scheme foreach t $targets { # New event script. $t invoke-event reset-start } # Use TRST or TMS/TCK operations to reset all the tap controllers. # TAP reset events get reported; they might enable some taps. init_reset $MODE # Examine all targets on enabled taps. foreach t $targets { if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t invoke-event examine-start set err [catch "$t arp_examine"] if { $err == 0 } { $t invoke-event examine-end } } } # Assert SRST, and report the pre/post events. # Note: no target sees SRST before "pre" or after "post". foreach t $targets { $t invoke-event reset-assert-pre } foreach t $targets { # C code needs to know if we expect to 'halt' if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t arp_reset assert $halt } } foreach t $targets { $t invoke-event reset-assert-post } # Now de-assert SRST, and report the pre/post events. # Note: no target sees !SRST before "pre" or after "post". foreach t $targets { $t invoke-event reset-deassert-pre } foreach t $targets { # Again, de-assert code needs to know if we 'halt' if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t arp_reset deassert $halt } } foreach t $targets { $t invoke-event reset-deassert-post } # Pass 1 - Now wait for any halt (requested as part of reset # assert/deassert) to happen. Ideally it takes effect without # first executing any instructions. if { $halt } { foreach t $targets { if {[using_jtag] && ![jtag tapisenabled [$t cget -chain-position]]} { continue } # Wait upto 1 second for target to halt. Why 1sec? Cause # the JTAG tap reset signal might be hooked to a slow # resistor/capacitor circuit - and it might take a while # to charge # Catch, but ignore any errors. catch { $t arp_waitstate halted 1000 } # Did we succeed? set s [$t curstate] if { 0 != [string compare $s "halted" ] } { return -code error [format "TARGET: %s - Not halted" $t] } } } #Pass 2 - if needed "init" if { 0 == [string compare init $MODE] } { foreach t $targets { if {[using_jtag] && ![jtag tapisenabled [$t cget -chain-position]]} { continue } set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { $t invoke-event reset-init } } } foreach t $targets { $t invoke-event reset-end } } proc using_jtag {} { set _TRANSPORT [ transport select ] expr { [ string first "jtag" $_TRANSPORT ] != -1 } } proc using_swd {} { set _TRANSPORT [ transport select ] expr { [ string first "swd" $_TRANSPORT ] != -1 } } proc using_hla {} { set _TRANSPORT [ transport select ] expr { [ string first "hla" $_TRANSPORT ] != -1 } } ######### # Temporary migration aid. May be removed starting in January 2011. proc armv4_5 params { echo "DEPRECATED! use 'arm $params' not 'armv4_5 $params'" arm $params } # Target/chain configuration scripts can either execute commands directly # or define a procedure which is executed once all configuration # scripts have completed. # # By default(classic) the config scripts will set up the target configuration proc init_targets {} { } proc set_default_target_event {t e s} { if {[$t cget -event $e] == ""} { $t configure -event $e $s } } proc init_target_events {} { set targets [target names] foreach t $targets { set_default_target_event $t gdb-flash-erase-start "reset init" set_default_target_event $t gdb-flash-write-end "reset halt" } } # Additionally board config scripts can define a procedure init_board that will be executed after init and init_targets proc init_board {} { } # deprecated target name cmds proc cortex_m3 args { echo "DEPRECATED! use 'cortex_m' not 'cortex_m3'" eval cortex_m $args } proc cortex_a8 args { echo "DEPRECATED! use 'cortex_a' not 'cortex_a8'" eval cortex_a $args } openocd-0.9.0/src/target/avr32_ap7k.c0000644000175000017500000004065512516456303014207 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * Based on mips_m4k code: * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2008 by David T.L. Wong * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/jtag.h" #include "register.h" #include "algorithm.h" #include "target.h" #include "breakpoints.h" #include "target_type.h" #include "avr32_jtag.h" #include "avr32_mem.h" #include "avr32_regs.h" #include "avr32_ap7k.h" static const char * const avr32_core_reg_list[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr" }; static const struct avr32_core_reg avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] = { {0, NULL, NULL}, {1, NULL, NULL}, {2, NULL, NULL}, {3, NULL, NULL}, {4, NULL, NULL}, {5, NULL, NULL}, {6, NULL, NULL}, {7, NULL, NULL}, {8, NULL, NULL}, {9, NULL, NULL}, {10, NULL, NULL}, {11, NULL, NULL}, {12, NULL, NULL}, {13, NULL, NULL}, {14, NULL, NULL}, {15, NULL, NULL}, {16, NULL, NULL}, }; static int avr32_read_core_reg(struct target *target, int num); static int avr32_write_core_reg(struct target *target, int num); int avr32_ap7k_save_context(struct target *target) { int retval, i; struct avr32_ap7k_common *ap7k = target_to_ap7k(target); retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs); if (retval != ERROR_OK) return retval; for (i = 0; i < AVR32NUMCOREREGS; i++) { if (!ap7k->core_cache->reg_list[i].valid) avr32_read_core_reg(target, i); } return ERROR_OK; } int avr32_ap7k_restore_context(struct target *target) { int i; /* get pointers to arch-specific information */ struct avr32_ap7k_common *ap7k = target_to_ap7k(target); for (i = 0; i < AVR32NUMCOREREGS; i++) { if (ap7k->core_cache->reg_list[i].dirty) avr32_write_core_reg(target, i); } /* write core regs */ avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs); return ERROR_OK; } static int avr32_read_core_reg(struct target *target, int num) { uint32_t reg_value; /* get pointers to arch-specific information */ struct avr32_ap7k_common *ap7k = target_to_ap7k(target); if ((num < 0) || (num >= AVR32NUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = ap7k->core_regs[num]; buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value); ap7k->core_cache->reg_list[num].valid = 1; ap7k->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int avr32_write_core_reg(struct target *target, int num) { uint32_t reg_value; /* get pointers to arch-specific information */ struct avr32_ap7k_common *ap7k = target_to_ap7k(target); if ((num < 0) || (num >= AVR32NUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32); ap7k->core_regs[num] = reg_value; LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value); ap7k->core_cache->reg_list[num].valid = 1; ap7k->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int avr32_get_core_reg(struct reg *reg) { int retval; struct avr32_core_reg *avr32_reg = reg->arch_info; struct target *target = avr32_reg->target; if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; retval = avr32_read_core_reg(target, avr32_reg->num); return retval; } static int avr32_set_core_reg(struct reg *reg, uint8_t *buf) { struct avr32_core_reg *avr32_reg = reg->arch_info; struct target *target = avr32_reg->target; uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static const struct reg_arch_type avr32_reg_type = { .get = avr32_get_core_reg, .set = avr32_set_core_reg, }; static struct reg_cache *avr32_build_reg_cache(struct target *target) { int num_regs = AVR32NUMCOREREGS; struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); struct avr32_core_reg *arch_info = malloc(sizeof(struct avr32_core_reg) * num_regs); int i; /* Build the process context cache */ cache->name = "avr32 registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = num_regs; (*cache_p) = cache; ap7k->core_cache = cache; for (i = 0; i < num_regs; i++) { arch_info[i] = avr32_core_reg_list_arch_info[i]; arch_info[i].target = target; arch_info[i].avr32_common = ap7k; reg_list[i].name = avr32_core_reg_list[i]; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &avr32_reg_type; reg_list[i].arch_info = &arch_info[i]; } return cache; } static int avr32_ap7k_debug_entry(struct target *target) { uint32_t dpc, dinst; int retval; struct avr32_ap7k_common *ap7k = target_to_ap7k(target); retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc); if (retval != ERROR_OK) return retval; retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst); if (retval != ERROR_OK) return retval; ap7k->jtag.dpc = dpc; avr32_ap7k_save_context(target); return ERROR_OK; } static int avr32_ap7k_poll(struct target *target) { uint32_t ds; int retval; struct avr32_ap7k_common *ap7k = target_to_ap7k(target); retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds); if (retval != ERROR_OK) return retval; /* check for processor halted */ if (ds & OCDREG_DS_DBA) { if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { target->state = TARGET_HALTED; retval = avr32_ap7k_debug_entry(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); } else if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; retval = avr32_ap7k_debug_entry(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } else target->state = TARGET_RUNNING; return ERROR_OK; } static int avr32_ap7k_halt(struct target *target) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } } avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR); target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int avr32_ap7k_assert_reset(struct target *target) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_deassert_reset(struct target *target) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); /* avr32_ap7k_enable_breakpoints(target); avr32_ap7k_enable_watchpoints(target); */ } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { #if 0 if (retval != ERROR_OK) return retval; #endif } resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32); avr32_ap7k_restore_context(target); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); #if 0 avr32_ap7k_unset_breakpoint(target, breakpoint); avr32_ap7k_single_step_core(target); avr32_ap7k_set_breakpoint(target, breakpoint); #endif } } #if 0 /* enable interrupts if we are running */ avr32_ap7k_enable_interrupts(target, !debug_execution); /* exit debug mode */ mips_ejtag_exit_debug(ejtag_info); #endif retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR); if (retval != ERROR_OK) return retval; retval = avr32_jtag_exec(&ap7k->jtag, RETD); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ register_cache_invalidate(ap7k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; } static int avr32_ap7k_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int avr32_ap7k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; switch (size) { case 4: return avr32_jtag_read_memory32(&ap7k->jtag, address, count, (uint32_t *)(void *)buffer); break; case 2: return avr32_jtag_read_memory16(&ap7k->jtag, address, count, (uint16_t *)(void *)buffer); break; case 1: return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer); break; default: break; } return ERROR_OK; } static int avr32_ap7k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; switch (size) { case 4: return avr32_jtag_write_memory32(&ap7k->jtag, address, count, (uint32_t *)(void *)buffer); break; case 2: return avr32_jtag_write_memory16(&ap7k->jtag, address, count, (uint16_t *)(void *)buffer); break; case 1: return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer); break; default: break; } return ERROR_OK; } static int avr32_ap7k_init_target(struct command_context *cmd_ctx, struct target *target) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); ap7k->jtag.tap = target->tap; avr32_build_reg_cache(target); return ERROR_OK; } static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp) { struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct avr32_ap7k_common)); ap7k->common_magic = AP7k_COMMON_MAGIC; target->arch_info = ap7k; return ERROR_OK; } static int avr32_ap7k_examine(struct target *target) { uint32_t devid, ds; struct avr32_ap7k_common *ap7k = target_to_ap7k(target); if (!target_was_examined(target)) { target_set_examined(target); avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid); LOG_INFO("device id: %08" PRIx32, devid); avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE); avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds); /* check for processor halted */ if (ds & OCDREG_DS_DBA) { LOG_INFO("target is halted"); target->state = TARGET_HALTED; } else target->state = TARGET_RUNNING; } return ERROR_OK; } int avr32_ap7k_arch_state(struct target *target) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "", debug_reason_name(target), ap7k->jtag.dpc); return ERROR_OK; } int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { #if 0 /* get pointers to arch-specific information */ int i; /* include floating point registers */ *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < AVR32NUMCOREREGS; i++) (*reg_list)[i] = &mips32->core_cache->reg_list[i]; /* add dummy floating points regs */ for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++) (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg; #endif LOG_ERROR("%s: implement me", __func__); return ERROR_FAIL; } struct target_type avr32_ap7k_target = { .name = "avr32_ap7k", .poll = avr32_ap7k_poll, .arch_state = avr32_ap7k_arch_state, .halt = avr32_ap7k_halt, .resume = avr32_ap7k_resume, .step = avr32_ap7k_step, .assert_reset = avr32_ap7k_assert_reset, .deassert_reset = avr32_ap7k_deassert_reset, .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list, .read_memory = avr32_ap7k_read_memory, .write_memory = avr32_ap7k_write_memory, /* .checksum_memory = avr32_ap7k_checksum_memory, */ /* .blank_check_memory = avr32_ap7k_blank_check_memory, */ /* .run_algorithm = avr32_ap7k_run_algorithm, */ .add_breakpoint = avr32_ap7k_add_breakpoint, .remove_breakpoint = avr32_ap7k_remove_breakpoint, .add_watchpoint = avr32_ap7k_add_watchpoint, .remove_watchpoint = avr32_ap7k_remove_watchpoint, .target_create = avr32_ap7k_target_create, .init_target = avr32_ap7k_init_target, .examine = avr32_ap7k_examine, }; openocd-0.9.0/src/target/avr32_ap7k.h0000644000175000017500000000354612315575361014215 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef AVR32_AP7K #define AVR32_AP7K struct target; #define AP7k_COMMON_MAGIC 0x4150374b struct avr32_ap7k_common { int common_magic; struct avr32_jtag jtag; struct reg_cache *core_cache; uint32_t core_regs[AVR32NUMCOREREGS]; }; static inline struct avr32_ap7k_common * target_to_ap7k(struct target *target) { return (struct avr32_ap7k_common *)target->arch_info; } struct avr32_core_reg { uint32_t num; struct target *target; struct avr32_ap7k_common *avr32_common; }; #endif /*AVR32_AP7K*/ openocd-0.9.0/src/target/x86_32_common.c0000644000175000017500000013062312516456304014625 00000000000000/* * Copyright(c) 2013 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation */ /* * @file * This implements generic x86 32 bit memory and breakpoint operations. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "target_type.h" #include "register.h" #include "breakpoints.h" #include "x86_32_common.h" static int set_debug_regs(struct target *t, uint32_t address, uint8_t bp_num, uint8_t bp_type, uint8_t bp_length); static int unset_debug_regs(struct target *t, uint8_t bp_num); static int read_mem(struct target *t, uint32_t size, uint32_t addr, uint8_t *buf); static int write_mem(struct target *t, uint32_t size, uint32_t addr, const uint8_t *buf); static int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr); static int read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); static int write_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); static int set_breakpoint(struct target *target, struct breakpoint *breakpoint); static int unset_breakpoint(struct target *target, struct breakpoint *breakpoint); static int set_watchpoint(struct target *target, struct watchpoint *watchpoint); static int unset_watchpoint(struct target *target, struct watchpoint *watchpoint); static int read_hw_reg_to_cache(struct target *t, int num); static int write_hw_reg_from_cache(struct target *t, int num); int x86_32_get_gdb_reg_list(struct target *t, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct x86_32_common *x86_32 = target_to_x86_32(t); int i; *reg_list_size = x86_32->cache->num_regs; LOG_DEBUG("num_regs=%d, reg_class=%d", (*reg_list_size), reg_class); *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); if (*reg_list == NULL) { LOG_ERROR("%s out of memory", __func__); return ERROR_FAIL; } /* this will copy the values from our reg list to gdbs */ for (i = 0; i < (*reg_list_size); i++) { (*reg_list)[i] = &x86_32->cache->reg_list[i]; LOG_DEBUG("value %s = %08" PRIx32, x86_32->cache->reg_list[i].name, buf_get_u32(x86_32->cache->reg_list[i].value, 0, 32)); } return ERROR_OK; } int x86_32_common_init_arch_info(struct target *t, struct x86_32_common *x86_32) { t->arch_info = x86_32; x86_32->common_magic = X86_32_COMMON_MAGIC; x86_32->num_hw_bpoints = MAX_DEBUG_REGS; x86_32->hw_break_list = calloc(x86_32->num_hw_bpoints, sizeof(struct x86_32_dbg_reg)); if (x86_32->hw_break_list == NULL) { LOG_ERROR("%s out of memory", __func__); return ERROR_FAIL; } x86_32->curr_tap = t->tap; x86_32->fast_data_area = NULL; x86_32->flush = 1; x86_32->read_hw_reg_to_cache = read_hw_reg_to_cache; x86_32->write_hw_reg_from_cache = write_hw_reg_from_cache; return ERROR_OK; } int x86_32_common_mmu(struct target *t, int *enabled) { *enabled = true; return ERROR_OK; } int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical) { struct x86_32_common *x86_32 = target_to_x86_32(t); /* * We need to ignore 'segmentation' for now, as OpenOCD can't handle * segmented addresses. * In protected mode that is almost OK, as (almost) any known OS is using * flat segmentation. In real mode we use use the base of the DS segment, * as we don't know better ... */ uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32); if (!(cr0 & CR0_PG)) { /* target halted in real mode */ /* TODO: needs validation !!! */ uint32_t dsb = buf_get_u32(x86_32->cache->reg_list[DSB].value, 0, 32); *physical = dsb + address; } else { /* target halted in protected mode */ if (calcaddr_pyhsfromlin(t, address, physical) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, address); return ERROR_FAIL; } } return ERROR_OK; } int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); int error; error = read_phys_mem(t, phys_address, size, count, buffer); if (error != ERROR_OK) return error; /* After reading memory from target, we must replace software breakpoints * with the original instructions again. */ struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list; while (iter != NULL) { if (iter->physaddr >= phys_address && iter->physaddr < phys_address+(size*count)) { uint32_t offset = iter->physaddr - phys_address; buffer[offset] = iter->orig_byte; } iter = iter->next; } return ERROR_OK; } static int read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval = ERROR_OK; bool pg_disabled = false; LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", phys_address, size, count, buffer); struct x86_32_common *x86_32 = target_to_x86_32(t); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if (!count || !buffer || !phys_address) { LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, __func__, count, buffer, phys_address); return ERROR_COMMAND_ARGUMENT_INVALID; } /* to access physical memory, switch off the CR0.PG bit */ if (x86_32->is_paging_enabled(t)) { retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } pg_disabled = true; } for (uint32_t i = 0; i < count; i++) { switch (size) { case BYTE: retval = read_mem(t, size, phys_address + i, buffer + i); break; case WORD: retval = read_mem(t, size, phys_address + i * 2, buffer + i * 2); break; case DWORD: retval = read_mem(t, size, phys_address + i * 4, buffer + i * 4); break; default: LOG_ERROR("%s invalid read size", __func__); break; } } /* restore CR0.PG bit if needed (regardless of retval) */ if (pg_disabled) { retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } pg_disabled = true; } /* TODO: After reading memory from target, we must replace * software breakpoints with the original instructions again. * Solve this with the breakpoint fix */ return retval; } int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); int error = ERROR_OK; uint8_t *newbuffer = NULL; check_not_halted(t); if (!count || !buffer || !phys_address) { LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, __func__, count, buffer, phys_address); return ERROR_COMMAND_ARGUMENT_INVALID; } /* Before writing memory to target, we must update software breakpoints * with the new instructions and patch the memory buffer with the * breakpoint instruction. */ newbuffer = malloc(size*count); if (newbuffer == NULL) { LOG_ERROR("%s out of memory", __func__); return ERROR_FAIL; } memcpy(newbuffer, buffer, size*count); struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list; while (iter != NULL) { if (iter->physaddr >= phys_address && iter->physaddr < phys_address+(size*count)) { uint32_t offset = iter->physaddr - phys_address; newbuffer[offset] = SW_BP_OPCODE; /* update the breakpoint */ struct breakpoint *pbiter = t->breakpoints; while (pbiter != NULL && pbiter->unique_id != iter->swbp_unique_id) pbiter = pbiter->next; if (pbiter) pbiter->orig_instr[0] = buffer[offset]; } iter = iter->next; } error = write_phys_mem(t, phys_address, size, count, newbuffer); free(newbuffer); return error; } static int write_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval = ERROR_OK; bool pg_disabled = false; struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", phys_address, size, count, buffer); check_not_halted(t); if (!count || !buffer || !phys_address) { LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, __func__, count, buffer, phys_address); return ERROR_COMMAND_ARGUMENT_INVALID; } /* TODO: Before writing memory to target, we must update * software breakpoints with the new instructions and * patch the memory buffer with the breakpoint instruction. * Solve this with the breakpoint fix */ /* to access physical memory, switch off the CR0.PG bit */ if (x86_32->is_paging_enabled(t)) { retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } pg_disabled = true; } for (uint32_t i = 0; i < count; i++) { switch (size) { case BYTE: retval = write_mem(t, size, phys_address + i, buffer + i); break; case WORD: retval = write_mem(t, size, phys_address + i * 2, buffer + i * 2); break; case DWORD: retval = write_mem(t, size, phys_address + i * 4, buffer + i * 4); break; default: LOG_DEBUG("invalid read size"); break; } } /* restore CR0.PG bit if needed (regardless of retval) */ if (pg_disabled) { retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } } return retval; } static int read_mem(struct target *t, uint32_t size, uint32_t addr, uint8_t *buf) { struct x86_32_common *x86_32 = target_to_x86_32(t); /* if CS.D bit=1 then its a 32 bit code segment, else 16 */ bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D; int retval = x86_32->write_hw_reg(t, EAX, addr, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error write EAX", __func__); return retval; } switch (size) { case BYTE: if (use32) retval = x86_32->submit_instruction(t, MEMRDB32); else retval = x86_32->submit_instruction(t, MEMRDB16); break; case WORD: if (use32) retval = x86_32->submit_instruction(t, MEMRDH32); else retval = x86_32->submit_instruction(t, MEMRDH16); break; case DWORD: if (use32) retval = x86_32->submit_instruction(t, MEMRDW32); else retval = x86_32->submit_instruction(t, MEMRDW16); break; default: LOG_ERROR("%s invalid read mem size", __func__); break; } /* read_hw_reg() will write to 4 bytes (uint32_t) * Watch out, the buffer passed into read_mem() might be 1 or 2 bytes. */ uint32_t regval; retval = x86_32->read_hw_reg(t, EDX, ®val, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error read EDX", __func__); return retval; } for (uint8_t i = 0; i < size; i++) buf[i] = (regval >> (i*8)) & 0x000000FF; retval = x86_32->transaction_status(t); if (retval != ERROR_OK) { LOG_ERROR("%s error on mem read", __func__); return retval; } return retval; } static int write_mem(struct target *t, uint32_t size, uint32_t addr, const uint8_t *buf) { uint32_t i = 0; uint32_t buf4bytes = 0; int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < size; ++i) { buf4bytes = buf4bytes << 8; /* first time we only shift 0s */ buf4bytes += buf[(size-1)-i]; /* it was hard to write, should be hard to read! */ } /* if CS.D bit=1 then its a 32 bit code segment, else 16 */ bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D; retval = x86_32->write_hw_reg(t, EAX, addr, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error write EAX", __func__); return retval; } /* write_hw_reg() will write to 4 bytes (uint32_t) * Watch out, the buffer passed into write_mem() might be 1 or 2 bytes. */ retval = x86_32->write_hw_reg(t, EDX, buf4bytes, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error write EDX", __func__); return retval; } switch (size) { case BYTE: if (use32) retval = x86_32->submit_instruction(t, MEMWRB32); else retval = x86_32->submit_instruction(t, MEMWRB16); break; case WORD: if (use32) retval = x86_32->submit_instruction(t, MEMWRH32); else retval = x86_32->submit_instruction(t, MEMWRH16); break; case DWORD: if (use32) retval = x86_32->submit_instruction(t, MEMWRW32); else retval = x86_32->submit_instruction(t, MEMWRW16); break; default: LOG_ERROR("%s invalid write mem size", __func__); return ERROR_FAIL; } retval = x86_32->transaction_status(t); if (retval != ERROR_OK) { LOG_ERROR("%s error on mem write", __func__); return retval; } return retval; } int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) { uint8_t entry_buffer[8]; if (physaddr == NULL || t == NULL) return ERROR_FAIL; struct x86_32_common *x86_32 = target_to_x86_32(t); /* The 'user-visible' CR0.PG should be set - otherwise the function shouldn't be called * (Don't check the CR0.PG on the target, this might be temporally disabled at this point) */ uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32); if (!(cr0 & CR0_PG)) { /* you are wrong in this function, never mind */ *physaddr = addr; return ERROR_OK; } uint32_t cr4 = buf_get_u32(x86_32->cache->reg_list[CR4].value, 0, 32); bool isPAE = cr4 & 0x00000020; /* PAE - Physical Address Extension */ uint32_t cr3 = buf_get_u32(x86_32->cache->reg_list[CR3].value, 0, 32); if (isPAE) { uint32_t pdpt_base = cr3 & 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */ uint32_t pdpt_index = (addr & 0xC0000000) >> 30; /* A[31:30] index to PDPT */ uint32_t pdpt_addr = pdpt_base + (8 * pdpt_index); if (x86_32_common_read_phys_mem(t, pdpt_addr, 4, 2, entry_buffer) != ERROR_OK) { LOG_ERROR("%s couldn't read page directory pointer table entry at 0x%08" PRIx32, __func__, pdpt_addr); return ERROR_FAIL; } uint64_t pdpt_entry = target_buffer_get_u64(t, entry_buffer); if (!(pdpt_entry & 0x0000000000000001)) { LOG_ERROR("%s page directory pointer table entry at 0x%08" PRIx32 " is not present", __func__, pdpt_addr); return ERROR_FAIL; } uint32_t pd_base = pdpt_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */ uint32_t pd_index = (addr & 0x3FE00000) >> 21; /* A[29:21] index to PD entry with PAE */ uint32_t pd_addr = pd_base + (8 * pd_index); if (x86_32_common_read_phys_mem(t, pd_addr, 4, 2, entry_buffer) != ERROR_OK) { LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32, __func__, pd_addr); return ERROR_FAIL; } uint64_t pd_entry = target_buffer_get_u64(t, entry_buffer); if (!(pd_entry & 0x0000000000000001)) { LOG_ERROR("%s page directory entry at 0x%08" PRIx32 " is not present", __func__, pd_addr); return ERROR_FAIL; } /* PS bit in PD entry is indicating 4KB or 2MB page size */ if (pd_entry & 0x0000000000000080) { uint32_t page_base = (uint32_t)(pd_entry & 0x00000000FFE00000); /* [31:21] */ uint32_t offset = addr & 0x001FFFFF; /* [20:0] */ *physaddr = page_base + offset; return ERROR_OK; } else { uint32_t pt_base = (uint32_t)(pd_entry & 0x00000000FFFFF000); /*[31:12]*/ uint32_t pt_index = (addr & 0x001FF000) >> 12; /*[20:12]*/ uint32_t pt_addr = pt_base + (8 * pt_index); if (x86_32_common_read_phys_mem(t, pt_addr, 4, 2, entry_buffer) != ERROR_OK) { LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32, __func__, pt_addr); return ERROR_FAIL; } uint64_t pt_entry = target_buffer_get_u64(t, entry_buffer); if (!(pt_entry & 0x0000000000000001)) { LOG_ERROR("%s page table entry at 0x%08" PRIx32 " is not present", __func__, pt_addr); return ERROR_FAIL; } uint32_t page_base = (uint32_t)(pt_entry & 0x00000000FFFFF000); /*[31:12]*/ uint32_t offset = addr & 0x00000FFF; /*[11:0]*/ *physaddr = page_base + offset; return ERROR_OK; } } else { uint32_t pd_base = cr3 & 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */ uint32_t pd_index = (addr & 0xFFC00000) >> 22; /* A[31:22] index to PD entry */ uint32_t pd_addr = pd_base + (4 * pd_index); if (x86_32_common_read_phys_mem(t, pd_addr, 4, 1, entry_buffer) != ERROR_OK) { LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32, __func__, pd_addr); return ERROR_FAIL; } uint32_t pd_entry = target_buffer_get_u32(t, entry_buffer); if (!(pd_entry & 0x00000001)) { LOG_ERROR("%s page directory entry at 0x%08" PRIx32 " is not present", __func__, pd_addr); return ERROR_FAIL; } /* Bit 7 in page directory entry is page size. */ if (pd_entry & 0x00000080) { /* 4MB pages */ uint32_t page_base = pd_entry & 0xFFC00000; *physaddr = page_base + (addr & 0x003FFFFF); } else { /* 4KB pages */ uint32_t pt_base = pd_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */ uint32_t pt_index = (addr & 0x003FF000) >> 12; /* A[21:12] index to page table entry */ uint32_t pt_addr = pt_base + (4 * pt_index); if (x86_32_common_read_phys_mem(t, pt_addr, 4, 1, entry_buffer) != ERROR_OK) { LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32, __func__, pt_addr); return ERROR_FAIL; } uint32_t pt_entry = target_buffer_get_u32(t, entry_buffer); if (!(pt_entry & 0x00000001)) { LOG_ERROR("%s page table entry at 0x%08" PRIx32 " is not present", __func__, pt_addr); return ERROR_FAIL; } uint32_t page_base = pt_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */ *physaddr = page_base + (addr & 0x00000FFF); /* A[11:0] offset to 4KB page in linear address */ } } return ERROR_OK; } int x86_32_common_read_memory(struct target *t, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } if (x86_32->is_paging_enabled(t)) { /* all memory accesses from debugger must be physical (CR0.PG == 0) * conversion to physical address space needed */ retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } uint32_t physaddr = 0; if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); retval = ERROR_FAIL; } /* TODO: !!! Watch out for page boundaries * for every 4kB, the physical address has to be re-calculated * This should be fixed together with bulk memory reads */ if (retval == ERROR_OK && x86_32_common_read_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { LOG_ERROR("%s failed to read memory from physical address 0x%08" PRIx32, __func__, physaddr); retval = ERROR_FAIL; } /* restore PG bit if it was cleared prior (regardless of retval) */ retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } } else { /* paging is off - linear address is physical address */ if (x86_32_common_read_phys_mem(t, addr, size, count, buf) != ERROR_OK) { LOG_ERROR("%s failed to read memory from address 0%08" PRIx32, __func__, addr); retval = ERROR_FAIL; } } return retval; } int x86_32_common_write_memory(struct target *t, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } if (x86_32->is_paging_enabled(t)) { /* all memory accesses from debugger must be physical (CR0.PG == 0) * conversion to physical address space needed */ retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } uint32_t physaddr = 0; if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); retval = ERROR_FAIL; } /* TODO: !!! Watch out for page boundaries * for every 4kB, the physical address has to be re-calculated * This should be fixed together with bulk memory reads */ if (retval == ERROR_OK && x86_32_common_write_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { LOG_ERROR("%s failed to write memory to physical address 0x%08" PRIx32, __func__, physaddr); retval = ERROR_FAIL; } /* restore PG bit if it was cleared prior (regardless of retval) */ retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } } else { /* paging is off - linear address is physical address */ if (x86_32_common_write_phys_mem(t, addr, size, count, buf) != ERROR_OK) { LOG_ERROR("%s failed to write memory to address 0x%08" PRIx32, __func__, addr); retval = ERROR_FAIL; } } return retval; } int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf) { struct x86_32_common *x86_32 = target_to_x86_32(t); /* if CS.D bit=1 then its a 32 bit code segment, else 16 */ bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D; int retval = ERROR_FAIL; bool pg_disabled = false; LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", buf=%p", addr, size, buf); check_not_halted(t); if (!buf || !addr) { LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32, __func__, buf, addr); return retval; } retval = x86_32->write_hw_reg(t, EDX, addr, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error EDX write", __func__); return retval; } /* to access physical memory, switch off the CR0.PG bit */ if (x86_32->is_paging_enabled(t)) { retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } pg_disabled = true; } switch (size) { case BYTE: if (use32) retval = x86_32->submit_instruction(t, IORDB32); else retval = x86_32->submit_instruction(t, IORDB16); break; case WORD: if (use32) retval = x86_32->submit_instruction(t, IORDH32); else retval = x86_32->submit_instruction(t, IORDH16); break; case DWORD: if (use32) retval = x86_32->submit_instruction(t, IORDW32); else retval = x86_32->submit_instruction(t, IORDW16); break; default: LOG_ERROR("%s invalid read io size", __func__); return ERROR_FAIL; } /* restore CR0.PG bit if needed */ if (pg_disabled) { retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } pg_disabled = false; } uint32_t regval = 0; retval = x86_32->read_hw_reg(t, EAX, ®val, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error on read EAX", __func__); return retval; } for (uint8_t i = 0; i < size; i++) buf[i] = (regval >> (i*8)) & 0x000000FF; retval = x86_32->transaction_status(t); if (retval != ERROR_OK) { LOG_ERROR("%s error on io read", __func__); return retval; } return retval; } int x86_32_common_write_io(struct target *t, uint32_t addr, uint32_t size, const uint8_t *buf) { struct x86_32_common *x86_32 = target_to_x86_32(t); /* if CS.D bit=1 then its a 32 bit code segment, else 16 */ bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D; LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", buf=%p", addr, size, buf); check_not_halted(t); int retval = ERROR_FAIL; bool pg_disabled = false; if (!buf || !addr) { LOG_ERROR("%s invalid params buf=%p, addr=0x%08" PRIx32, __func__, buf, addr); return retval; } /* no do the write */ retval = x86_32->write_hw_reg(t, EDX, addr, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error on EDX write", __func__); return retval; } uint32_t regval = 0; for (uint8_t i = 0; i < size; i++) regval += (buf[i] << (i*8)); retval = x86_32->write_hw_reg(t, EAX, regval, 0); if (retval != ERROR_OK) { LOG_ERROR("%s error on EAX write", __func__); return retval; } /* to access physical memory, switch off the CR0.PG bit */ if (x86_32->is_paging_enabled(t)) { retval = x86_32->disable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not disable paging", __func__); return retval; } pg_disabled = true; } switch (size) { case BYTE: if (use32) retval = x86_32->submit_instruction(t, IOWRB32); else retval = x86_32->submit_instruction(t, IOWRB16); break; case WORD: if (use32) retval = x86_32->submit_instruction(t, IOWRH32); else retval = x86_32->submit_instruction(t, IOWRH16); break; case DWORD: if (use32) retval = x86_32->submit_instruction(t, IOWRW32); else retval = x86_32->submit_instruction(t, IOWRW16); break; default: LOG_ERROR("%s invalid write io size", __func__); return ERROR_FAIL; } /* restore CR0.PG bit if needed */ if (pg_disabled) { retval = x86_32->enable_paging(t); if (retval != ERROR_OK) { LOG_ERROR("%s could not enable paging", __func__); return retval; } pg_disabled = false; } retval = x86_32->transaction_status(t); if (retval != ERROR_OK) { LOG_ERROR("%s error on io write", __func__); return retval; } return retval; } int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp) { check_not_halted(t); /* set_watchpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all * hardware registers are gone */ return set_watchpoint(t, wp); } int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp) { if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if (wp->set) unset_watchpoint(t, wp); return ERROR_OK; } int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp) { LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all * hardware registers are gone (for hardware breakpoints) */ return set_breakpoint(t, bp); } int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp) { LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if (bp->set) unset_breakpoint(t, bp); return ERROR_OK; } static int set_debug_regs(struct target *t, uint32_t address, uint8_t bp_num, uint8_t bp_type, uint8_t bp_length) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("addr=0x%08" PRIx32 ", bp_num=%" PRIu8 ", bp_type=%" PRIu8 ", pb_length=%" PRIu8, address, bp_num, bp_type, bp_length); /* DR7 - set global enable */ uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32); if (bp_length != 1 && bp_length != 2 && bp_length != 4) return ERROR_FAIL; if (DR7_BP_FREE(dr7, bp_num)) DR7_GLOBAL_ENABLE(dr7, bp_num); else { LOG_ERROR("%s dr7 error, already enabled, val=%08" PRIx32, __func__, dr7); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } switch (bp_type) { case 0: /* 00 - only on instruction execution */ DR7_SET_EXE(dr7, bp_num); DR7_SET_LENGTH(dr7, bp_num, bp_length); break; case 1: /* 01 - only on data writes */ DR7_SET_WRITE(dr7, bp_num); DR7_SET_LENGTH(dr7, bp_num, bp_length); break; case 2: /* 10 UNSUPPORTED - an I/O read and I/O write */ LOG_ERROR("%s unsupported feature bp_type=%d", __func__, bp_type); return ERROR_FAIL; break; case 3: /* on data read or data write */ DR7_SET_ACCESS(dr7, bp_num); DR7_SET_LENGTH(dr7, bp_num, bp_length); break; default: LOG_ERROR("%s invalid request [only 0-3] bp_type=%d", __func__, bp_type); return ERROR_FAIL; } /* update regs in the reg cache ready to be written to hardware * when we exit PM */ buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, address); x86_32->cache->reg_list[bp_num+DR0].dirty = 1; x86_32->cache->reg_list[bp_num+DR0].valid = 1; buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6); x86_32->cache->reg_list[DR6].dirty = 1; x86_32->cache->reg_list[DR6].valid = 1; buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7); x86_32->cache->reg_list[DR7].dirty = 1; x86_32->cache->reg_list[DR7].valid = 1; return ERROR_OK; } static int unset_debug_regs(struct target *t, uint8_t bp_num) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("bp_num=%" PRIu8, bp_num); uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32); if (!(DR7_BP_FREE(dr7, bp_num))) { DR7_GLOBAL_DISABLE(dr7, bp_num); } else { LOG_ERROR("%s dr7 error, not enabled, val=0x%08" PRIx32, __func__, dr7); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* this will clear rw and len bits */ DR7_RESET_RWLEN_BITS(dr7, bp_num); /* update regs in the reg cache ready to be written to hardware * when we exit PM */ buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, 0); x86_32->cache->reg_list[bp_num+DR0].dirty = 1; x86_32->cache->reg_list[bp_num+DR0].valid = 1; buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6); x86_32->cache->reg_list[DR6].dirty = 1; x86_32->cache->reg_list[DR6].valid = 1; buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7); x86_32->cache->reg_list[DR7].dirty = 1; x86_32->cache->reg_list[DR7].valid = 1; return ERROR_OK; } static int set_hwbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; uint8_t hwbp_num = 0; while (debug_reg_list[hwbp_num].used && (hwbp_num < x86_32->num_hw_bpoints)) hwbp_num++; if (hwbp_num >= x86_32->num_hw_bpoints) { LOG_ERROR("%s no free hw breakpoint bpid=0x%" PRIx32, __func__, bp->unique_id); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (set_debug_regs(t, bp->address, hwbp_num, DR7_BP_EXECUTE, 1) != ERROR_OK) return ERROR_FAIL; bp->set = hwbp_num + 1; debug_reg_list[hwbp_num].used = 1; debug_reg_list[hwbp_num].bp_value = bp->address; LOG_USER("%s hardware breakpoint %" PRIu32 " set at 0x%08" PRIx32 " (hwreg=%" PRIu8 ")", __func__, bp->unique_id, debug_reg_list[hwbp_num].bp_value, hwbp_num); return ERROR_OK; } static int unset_hwbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; int hwbp_num = bp->set - 1; if ((hwbp_num < 0) || (hwbp_num >= x86_32->num_hw_bpoints)) { LOG_ERROR("%s invalid breakpoint number=%d, bpid=%" PRIu32, __func__, hwbp_num, bp->unique_id); return ERROR_OK; } if (unset_debug_regs(t, hwbp_num) != ERROR_OK) return ERROR_FAIL; debug_reg_list[hwbp_num].used = 0; debug_reg_list[hwbp_num].bp_value = 0; LOG_USER("%s hardware breakpoint %" PRIu32 " removed from 0x%08" PRIx32 " (hwreg=%d)", __func__, bp->unique_id, bp->address, hwbp_num); return ERROR_OK; } static int set_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); uint32_t physaddr; uint8_t opcode = SW_BP_OPCODE; uint8_t readback; if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; LOG_DEBUG("set software breakpoint - orig byte=0x%02" PRIx8 "", *bp->orig_instr); /* just write the instruction trap byte */ if (write_phys_mem(t, physaddr, 1, 1, &opcode)) return ERROR_FAIL; /* verify that this is not invalid/read-only memory */ if (read_phys_mem(t, physaddr, 1, 1, &readback)) return ERROR_FAIL; if (readback != SW_BP_OPCODE) { LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32 ", check memory", __func__, bp->address); LOG_ERROR("%s readback=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, readback, *bp->orig_instr); return ERROR_FAIL; } bp->set = SW_BP_OPCODE; /* just non 0 */ /* add the memory patch */ struct swbp_mem_patch *new_patch = malloc(sizeof(struct swbp_mem_patch)); if (new_patch == NULL) { LOG_ERROR("%s out of memory", __func__); return ERROR_FAIL; } new_patch->next = NULL; new_patch->orig_byte = *bp->orig_instr; new_patch->physaddr = physaddr; new_patch->swbp_unique_id = bp->unique_id; struct swbp_mem_patch *addto = x86_32->swbbp_mem_patch_list; if (addto == NULL) x86_32->swbbp_mem_patch_list = new_patch; else { while (addto->next != NULL) addto = addto->next; addto->next = new_patch; } LOG_USER("%s software breakpoint %" PRIu32 " set at 0x%08" PRIx32, __func__, bp->unique_id, bp->address); return ERROR_OK; } static int unset_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); uint32_t physaddr; uint8_t current_instr; /* check that user program has not modified breakpoint instruction */ if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, ¤t_instr)) return ERROR_FAIL; if (current_instr == SW_BP_OPCODE) { if (write_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; } else { LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32 ", check memory", __func__, bp->address); LOG_ERROR("%s current=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, current_instr, *bp->orig_instr); return ERROR_FAIL; } /* remove from patch */ struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list; if (iter != NULL) { if (iter->swbp_unique_id == bp->unique_id) { /* it's the first item */ x86_32->swbbp_mem_patch_list = iter->next; free(iter); } else { while (iter->next != NULL && iter->next->swbp_unique_id != bp->unique_id) iter = iter->next; if (iter->next != NULL) { /* it's the next one */ struct swbp_mem_patch *freeme = iter->next; iter->next = iter->next->next; free(freeme); } } } LOG_USER("%s software breakpoint %" PRIu32 " removed from 0x%08" PRIx32, __func__, bp->unique_id, bp->address); return ERROR_OK; } static int set_breakpoint(struct target *t, struct breakpoint *bp) { int error = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); if (bp->set) { LOG_ERROR("breakpoint already set"); return error; } if (bp->type == BKPT_HARD) { error = set_hwbp(t, bp); if (error != ERROR_OK) { LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32, __func__, bp->address); return error; } } else { if (x86_32->sw_bpts_supported(t)) { error = set_swbp(t, bp); if (error != ERROR_OK) { LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32, __func__, bp->address); return error; } } else { LOG_ERROR("%s core doesn't support SW breakpoints", __func__); error = ERROR_FAIL; return ERROR_FAIL; } } return error; } static int unset_breakpoint(struct target *t, struct breakpoint *bp) { LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); if (!bp->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (bp->type == BKPT_HARD) { if (unset_hwbp(t, bp) != ERROR_OK) { LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32, __func__, bp->address); return ERROR_FAIL; } } else { if (unset_swbp(t, bp) != ERROR_OK) { LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32, __func__, bp->address); return ERROR_FAIL; } } bp->set = 0; return ERROR_OK; } static int set_watchpoint(struct target *t, struct watchpoint *wp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; int wp_num = 0; LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); if (wp->set) { LOG_ERROR("%s watchpoint already set", __func__); return ERROR_OK; } if (wp->rw == WPT_READ) { LOG_ERROR("%s no support for 'read' watchpoints, use 'access' or 'write'" , __func__); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } while (debug_reg_list[wp_num].used && (wp_num < x86_32->num_hw_bpoints)) wp_num++; if (wp_num >= x86_32->num_hw_bpoints) { LOG_ERROR("%s no debug registers left", __func__); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (wp->length != 4 && wp->length != 2 && wp->length != 1) { LOG_ERROR("%s only watchpoints of length 1, 2 or 4 are supported", __func__); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } switch (wp->rw) { case WPT_WRITE: if (set_debug_regs(t, wp->address, wp_num, DR7_BP_WRITE, wp->length) != ERROR_OK) { return ERROR_FAIL; } break; case WPT_ACCESS: if (set_debug_regs(t, wp->address, wp_num, DR7_BP_READWRITE, wp->length) != ERROR_OK) { return ERROR_FAIL; } break; default: LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__); break; } wp->set = wp_num + 1; debug_reg_list[wp_num].used = 1; debug_reg_list[wp_num].bp_value = wp->address; LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); return ERROR_OK; } static int unset_watchpoint(struct target *t, struct watchpoint *wp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); if (!wp->set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } int wp_num = wp->set - 1; if ((wp_num < 0) || (wp_num >= x86_32->num_hw_bpoints)) { LOG_DEBUG("Invalid FP Comparator number in watchpoint"); return ERROR_OK; } if (unset_debug_regs(t, wp_num) != ERROR_OK) return ERROR_FAIL; debug_reg_list[wp_num].used = 0; debug_reg_list[wp_num].bp_value = 0; wp->set = 0; LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); return ERROR_OK; } static int read_hw_reg_to_cache(struct target *t, int num) { uint32_t reg_value; struct x86_32_common *x86_32 = target_to_x86_32(t); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if ((num < 0) || (num >= x86_32->get_num_user_regs(t))) return ERROR_COMMAND_SYNTAX_ERROR; if (x86_32->read_hw_reg(t, num, ®_value, 1) != ERROR_OK) { LOG_ERROR("%s fail for %s", x86_32->cache->reg_list[num].name, __func__); return ERROR_FAIL; } LOG_DEBUG("reg %s value 0x%08" PRIx32, x86_32->cache->reg_list[num].name, reg_value); return ERROR_OK; } static int write_hw_reg_from_cache(struct target *t, int num) { struct x86_32_common *x86_32 = target_to_x86_32(t); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if ((num < 0) || (num >= x86_32->get_num_user_regs(t))) return ERROR_COMMAND_SYNTAX_ERROR; if (x86_32->write_hw_reg(t, num, 0, 1) != ERROR_OK) { LOG_ERROR("%s fail for %s", x86_32->cache->reg_list[num].name, __func__); return ERROR_FAIL; } LOG_DEBUG("reg %s value 0x%08" PRIx32, x86_32->cache->reg_list[num].name, buf_get_u32(x86_32->cache->reg_list[num].value, 0, 32)); return ERROR_OK; } /* x86 32 commands */ static void handle_iod_output(struct command_context *cmd_ctx, struct target *target, uint32_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; unsigned line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; unsigned output_len = 0; const char *value_fmt; switch (size) { case 4: value_fmt = "%8.8x "; break; case 2: value_fmt = "%4.4x "; break; case 1: value_fmt = "%2.2x "; break; default: /* "can't happen", caller checked */ LOG_ERROR("%s invalid memory read size: %u", __func__, size); return; } for (unsigned i = 0; i < count; i++) { if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, "0x%8.8x: ", (unsigned)(address + (i*size))); } uint32_t value = 0; const uint8_t *value_ptr = buffer + i * size; switch (size) { case 4: value = target_buffer_get_u32(target, value_ptr); break; case 2: value = target_buffer_get_u16(target, value_ptr); break; case 1: value = *value_ptr; } output_len += snprintf(output + output_len, sizeof(output) - output_len, value_fmt, value); if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { command_print(cmd_ctx, "%s", output); output_len = 0; } } } COMMAND_HANDLER(handle_iod_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); if (address > 0xffff) { LOG_ERROR("%s IA-32 I/O space is 2^16, 0x%08" PRIx32 " exceeds max", __func__, address); return ERROR_COMMAND_SYNTAX_ERROR; } unsigned size = 0; switch (CMD_NAME[2]) { case 'w': size = 4; break; case 'h': size = 2; break; case 'b': size = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } unsigned count = 1; uint8_t *buffer = calloc(count, size); struct target *target = get_current_target(CMD_CTX); int retval = x86_32_common_read_io(target, address, size, buffer); if (ERROR_OK == retval) handle_iod_output(CMD_CTX, target, address, size, count, buffer); free(buffer); return retval; } static int target_fill_io(struct target *target, uint32_t address, unsigned data_size, /* value */ uint32_t b) { LOG_DEBUG("address=0x%08" PRIx32 ", data_size=%u, b=0x%08" PRIx32, address, data_size, b); uint8_t target_buf[data_size]; switch (data_size) { case 4: target_buffer_set_u32(target, target_buf, b); break; case 2: target_buffer_set_u16(target, target_buf, b); break; case 1: target_buf[0] = (b & 0x0ff); break; default: exit(-1); } return x86_32_common_write_io(target, address, data_size, target_buf); } COMMAND_HANDLER(handle_iow_command) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); struct target *target = get_current_target(CMD_CTX); unsigned wordsize; switch (CMD_NAME[2]) { case 'w': wordsize = 4; break; case 'h': wordsize = 2; break; case 'b': wordsize = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return target_fill_io(target, address, wordsize, value); } static const struct command_registration x86_32_exec_command_handlers[] = { { .name = "iww", .mode = COMMAND_EXEC, .handler = handle_iow_command, .help = "write I/O port word", .usage = "port data[word]", }, { .name = "iwh", .mode = COMMAND_EXEC, .handler = handle_iow_command, .help = "write I/O port halfword", .usage = "port data[halfword]", }, { .name = "iwb", .mode = COMMAND_EXEC, .handler = handle_iow_command, .help = "write I/O port byte", .usage = "port data[byte]", }, { .name = "idw", .mode = COMMAND_EXEC, .handler = handle_iod_command, .help = "display I/O port word", .usage = "port", }, { .name = "idh", .mode = COMMAND_EXEC, .handler = handle_iod_command, .help = "display I/O port halfword", .usage = "port", }, { .name = "idb", .mode = COMMAND_EXEC, .handler = handle_iod_command, .help = "display I/O port byte", .usage = "port", }, COMMAND_REGISTRATION_DONE }; const struct command_registration x86_32_command_handlers[] = { { .name = "x86_32", .mode = COMMAND_ANY, .help = "x86_32 target commands", .usage = "", .chain = x86_32_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/x86_32_common.h0000644000175000017500000002003312516456304014623 00000000000000/* * Copyright(c) 2013 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation */ /* * @file * This is the interface to the x86 32 bit memory and breakpoint operations. */ #ifndef X86_32_COMMON_H #define X86_32_COMMON_H #include #include #include extern const struct command_registration x86_32_command_handlers[]; /* for memory access */ #define BYTE 1 #define WORD 2 #define DWORD 4 #define EFLAGS_TF ((uint32_t)0x00000100) /* Trap Flag */ #define EFLAGS_IF ((uint32_t)0x00000200) /* Interrupt Flag */ #define EFLAGS_RF ((uint32_t)0x00010000) /* Resume Flag */ #define EFLAGS_VM86 ((uint32_t)0x00020000) /* Virtual 8086 Mode */ #define CSAR_DPL ((uint32_t)0x00006000) #define CSAR_D ((uint32_t)0x00400000) #define SSAR_DPL ((uint32_t)0x00006000) #define CR0_PE ((uint32_t)0x00000001) /* Protected Mode Enable */ #define CR0_NW ((uint32_t)0x20000000) /* Non Write-Through */ #define CR0_CD ((uint32_t)0x40000000) /* Cache Disable */ #define CR0_PG ((uint32_t)0x80000000) /* Paging Enable */ /* TODO - move back to PM specific file */ #define PM_DR6 ((uint32_t)0xFFFF0FF0) #define DR6_BRKDETECT_0 ((uint32_t)0x00000001) /* B0 through B3 */ #define DR6_BRKDETECT_1 ((uint32_t)0x00000002) /* breakpoint condition detected */ #define DR6_BRKDETECT_2 ((uint32_t)0x00000004) #define DR6_BRKDETECT_3 ((uint32_t)0x00000008) enum { /* general purpose registers */ EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI, /* instruction pointer & flags */ EIP, EFLAGS, /* segment registers */ CS, SS, DS, ES, FS, GS, /* floating point unit registers */ ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, FCTRL, FSTAT, FTAG, FISEG, FIOFF, FOSEG, FOOFF, FOP, /* control registers */ CR0, CR2, CR3, CR4, /* debug registers */ DR0, DR1, DR2, DR3, DR6, DR7, /* descriptor tables */ IDTB, IDTL, IDTAR, GDTB, GDTL, GDTAR, TR, LDTR, LDTB, LDTL, LDTAR, /* segment registers */ CSB, CSL, CSAR, DSB, DSL, DSAR, ESB, ESL, ESAR, FSB, FSL, FSAR, GSB, GSL, GSAR, SSB, SSL, SSAR, TSSB, TSSL, TSSAR, /* PM control reg */ PMCR, }; #define X86_32_COMMON_MAGIC 0x86328632 enum { /* memory read/write */ MEMRDB32 = 0, MEMRDB16, MEMRDH32, MEMRDH16, MEMRDW32, MEMRDW16, MEMWRB32, MEMWRB16, MEMWRH32, MEMWRH16, MEMWRW32, MEMWRW16, /* IO read/write */ IORDB32, IORDB16, IORDH32, IORDH16, IORDW32, IORDW16, IOWRB32, IOWRB16, IOWRH32, IOWRH16, IOWRW32, IOWRW16, /* lakemont1 core shadow ram access opcodes */ SRAMACCESS, SRAM2PDR, PDR2SRAM, WBINVD, }; struct swbp_mem_patch { uint8_t orig_byte; uint32_t swbp_unique_id; uint32_t physaddr; struct swbp_mem_patch *next; }; /* TODO - probemode specific - consider removing */ #define NUM_PM_REGS 18 /* regs used in save/restore */ struct x86_32_common { uint32_t common_magic; void *arch_info; struct reg_cache *cache; struct jtag_tap *curr_tap; uint32_t stored_pc; int flush; /* pm_regs are for probemode save/restore state */ uint32_t pm_regs[NUM_PM_REGS]; /* working area for fastdata access */ struct working_area *fast_data_area; int num_hw_bpoints; struct x86_32_dbg_reg *hw_break_list; struct swbp_mem_patch *swbbp_mem_patch_list; /* core probemode implementation dependent functions */ uint8_t (*get_num_user_regs)(struct target *t); bool (*is_paging_enabled)(struct target *t); int (*disable_paging)(struct target *t); int (*enable_paging)(struct target *t); bool (*sw_bpts_supported)(struct target *t); int (*transaction_status)(struct target *t); int (*submit_instruction)(struct target *t, int num); int (*read_hw_reg)(struct target *t, int reg, uint32_t *regval, uint8_t cache); int (*write_hw_reg)(struct target *t, int reg, uint32_t regval, uint8_t cache); /* register cache to processor synchronization */ int (*read_hw_reg_to_cache)(struct target *target, int num); int (*write_hw_reg_from_cache)(struct target *target, int num); }; static inline struct x86_32_common * target_to_x86_32(struct target *target) { return target->arch_info; } bool check_not_halted(const struct target *t); /* breakpoint defines */ #define MAX_DEBUG_REGS 4 #define SW_BP_OPCODE 0xf1 #define MAX_SW_BPTS 20 struct x86_32_dbg_reg { int used; uint32_t bp_value; }; #define DR7_G_ENABLE_SHIFT 1 #define DR7_ENABLE_SIZE 2 /* 2 bits per debug reg */ #define DR7_RW_SHIFT 16 #define DR7_LENGTH_SHIFT 18 #define DR7_RW_LEN_SIZE 4 #define DR7_BP_EXECUTE 0 /* 00 - only on instruction execution*/ #define DR7_BP_WRITE 1 /* 01 - only on data writes */ /*#define DR7_RW_IORW 2 UNSUPPORTED 10 - an I/O read and I/O write */ #define DR7_BP_READWRITE 3 /* on data read or data write */ #define DR7_BP_LENGTH_1 0 /* 00 - 1 byte length */ #define DR7_BP_LENGTH_2 1 /* 01 - 2 byte length */ #define DR7_BP_LENGTH_4 3 /* 11 - 4 byte length */ #define DR7_GLOBAL_ENABLE(val, regnum) \ (val |= (1 << (DR7_G_ENABLE_SHIFT + (DR7_ENABLE_SIZE * (regnum))))) #define DR7_GLOBAL_DISABLE(val, regnum) \ (val &= ~(3 << (DR7_ENABLE_SIZE * (regnum)))) #define DR7_BP_FREE(val, regnum) \ ((val & (3 << (DR7_ENABLE_SIZE * (regnum)))) == 0) #define DR7_RESET_RWLEN_BITS(val, regnum) \ (val &= ~(0x0f << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum)))) #define DR7_SET_EXE(val, regnum) \ (val &= ~(0x0f << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum)))) #define DR7_SET_WRITE(val, regnum) \ (val |= (DR7_BP_WRITE << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum)))) #define DR7_SET_ACCESS(val, regnum) \ (val |= (DR7_BP_READWRITE << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum)))) #define DR7_SET_LENGTH(val, regnum, len) \ (val |= (len == 1) ? (DR7_BP_LENGTH_1 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum))) : \ (len == 2) ? (DR7_BP_LENGTH_2 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum))) : \ (DR7_BP_LENGTH_4 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum)))) /* public interface */ int x86_32_get_gdb_reg_list(struct target *t, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); int x86_32_common_init_arch_info(struct target *target, struct x86_32_common *x86_32); int x86_32_common_mmu(struct target *t, int *enabled); int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical); int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); int x86_32_common_read_memory(struct target *t, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buf); int x86_32_common_write_memory(struct target *t, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buf); int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf); int x86_32_common_write_io(struct target *t, uint32_t addr, uint32_t size, const uint8_t *buf); int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp); int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp); int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp); int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp); #endif /* X86_32_COMMON_H */ openocd-0.9.0/src/target/testee.c0000644000175000017500000000453612315575361013622 00000000000000/*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "target_type.h" #include "hello.h" static const struct command_registration testee_command_handlers[] = { { .name = "testee", .mode = COMMAND_ANY, .help = "testee target commands", .chain = hello_command_handlers, }, COMMAND_REGISTRATION_DONE }; static int testee_init(struct command_context *cmd_ctx, struct target *target) { return ERROR_OK; } static int testee_poll(struct target *target) { return ERROR_OK; } static int testee_halt(struct target *target) { return ERROR_OK; } static int testee_reset_assert(struct target *target) { return ERROR_OK; } static int testee_reset_deassert(struct target *target) { return ERROR_OK; } struct target_type testee_target = { .name = "testee", .commands = testee_command_handlers, .init_target = &testee_init, .poll = &testee_poll, .halt = &testee_halt, .assert_reset = &testee_reset_assert, .deassert_reset = &testee_reset_deassert, }; openocd-0.9.0/src/target/arm_simulator.c0000644000175000017500000005163412315575361015210 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "armv4_5.h" #include "arm_disassembler.h" #include "arm_simulator.h" #include #include "register.h" #include static uint32_t arm_shift(uint8_t shift, uint32_t Rm, uint32_t shift_amount, uint8_t *carry) { uint32_t return_value = 0; shift_amount &= 0xff; if (shift == 0x0) { /* LSL */ if ((shift_amount > 0) && (shift_amount <= 32)) { return_value = Rm << shift_amount; *carry = Rm >> (32 - shift_amount); } else if (shift_amount > 32) { return_value = 0x0; *carry = 0x0; } else /* (shift_amount == 0) */ return_value = Rm; } else if (shift == 0x1) { /* LSR */ if ((shift_amount > 0) && (shift_amount <= 32)) { return_value = Rm >> shift_amount; *carry = (Rm >> (shift_amount - 1)) & 1; } else if (shift_amount > 32) { return_value = 0x0; *carry = 0x0; } else /* (shift_amount == 0) */ return_value = Rm; } else if (shift == 0x2) { /* ASR */ if ((shift_amount > 0) && (shift_amount <= 32)) { /* C right shifts of unsigned values are guaranteed to * be logical (shift in zeroes); simulate an arithmetic * shift (shift in signed-bit) by adding the sign bit * manually */ return_value = Rm >> shift_amount; if (Rm & 0x80000000) return_value |= 0xffffffff << (32 - shift_amount); } else if (shift_amount > 32) { if (Rm & 0x80000000) { return_value = 0xffffffff; *carry = 0x1; } else { return_value = 0x0; *carry = 0x0; } } else /* (shift_amount == 0) */ return_value = Rm; } else if (shift == 0x3) { /* ROR */ if (shift_amount == 0) return_value = Rm; else { shift_amount = shift_amount % 32; return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount)); *carry = (return_value >> 31) & 0x1; } } else if (shift == 0x4) { /* RRX */ return_value = Rm >> 1; if (*carry) Rm |= 0x80000000; *carry = Rm & 0x1; } return return_value; } static uint32_t arm_shifter_operand(struct arm_sim_interface *sim, int variant, union arm_shifter_operand shifter_operand, uint8_t *shifter_carry_out) { uint32_t return_value; int instruction_size; if (sim->get_state(sim) == ARM_STATE_ARM) instruction_size = 4; else instruction_size = 2; *shifter_carry_out = sim->get_cpsr(sim, 29, 1); if (variant == 0) /* 32-bit immediate */ return_value = shifter_operand.immediate.immediate; else if (variant == 1) {/* immediate shift */ uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.immediate_shift.Rm); /* adjust RM in case the PC is being read */ if (shifter_operand.immediate_shift.Rm == 15) Rm += 2 * instruction_size; return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, shifter_operand.immediate_shift.shift_imm, shifter_carry_out); } else if (variant == 2) { /* register shift */ uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.register_shift.Rm); uint32_t Rs = sim->get_reg_mode(sim, shifter_operand.register_shift.Rs); /* adjust RM in case the PC is being read */ if (shifter_operand.register_shift.Rm == 15) Rm += 2 * instruction_size; return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, Rs, shifter_carry_out); } else { LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2"); return_value = 0xffffffff; } return return_value; } static int pass_condition(uint32_t cpsr, uint32_t opcode) { switch ((opcode & 0xf0000000) >> 28) { case 0x0: /* EQ */ if (cpsr & 0x40000000) return 1; else return 0; case 0x1: /* NE */ if (!(cpsr & 0x40000000)) return 1; else return 0; case 0x2: /* CS */ if (cpsr & 0x20000000) return 1; else return 0; case 0x3: /* CC */ if (!(cpsr & 0x20000000)) return 1; else return 0; case 0x4: /* MI */ if (cpsr & 0x80000000) return 1; else return 0; case 0x5: /* PL */ if (!(cpsr & 0x80000000)) return 1; else return 0; case 0x6: /* VS */ if (cpsr & 0x10000000) return 1; else return 0; case 0x7: /* VC */ if (!(cpsr & 0x10000000)) return 1; else return 0; case 0x8: /* HI */ if ((cpsr & 0x20000000) && !(cpsr & 0x40000000)) return 1; else return 0; case 0x9: /* LS */ if (!(cpsr & 0x20000000) || (cpsr & 0x40000000)) return 1; else return 0; case 0xa: /* GE */ if (((cpsr & 0x80000000) && (cpsr & 0x10000000)) || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000))) return 1; else return 0; case 0xb: /* LT */ if (((cpsr & 0x80000000) && !(cpsr & 0x10000000)) || (!(cpsr & 0x80000000) && (cpsr & 0x10000000))) return 1; else return 0; case 0xc: /* GT */ if (!(cpsr & 0x40000000) && (((cpsr & 0x80000000) && (cpsr & 0x10000000)) || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000)))) return 1; else return 0; case 0xd: /* LE */ if ((cpsr & 0x40000000) || ((cpsr & 0x80000000) && !(cpsr & 0x10000000)) || (!(cpsr & 0x80000000) && (cpsr & 0x10000000))) return 1; else return 0; case 0xe: case 0xf: return 1; } LOG_ERROR("BUG: should never get here"); return 0; } static int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode) { return pass_condition(cpsr, (opcode & 0x0f00) << 20); } /* simulate a single step (if possible) * if the dry_run_pc argument is provided, no state is changed, * but the new pc is stored in the variable pointed at by the argument */ static int arm_simulate_step_core(struct target *target, uint32_t *dry_run_pc, struct arm_sim_interface *sim) { uint32_t current_pc = sim->get_reg(sim, 15); struct arm_instruction instruction; int instruction_size; int retval = ERROR_OK; if (sim->get_state(sim) == ARM_STATE_ARM) { uint32_t opcode; /* get current instruction, and identify it */ retval = target_read_u32(target, current_pc, &opcode); if (retval != ERROR_OK) return retval; retval = arm_evaluate_opcode(opcode, current_pc, &instruction); if (retval != ERROR_OK) return retval; instruction_size = 4; /* check condition code (for all instructions) */ if (!pass_condition(sim->get_cpsr(sim, 0, 32), opcode)) { if (dry_run_pc) *dry_run_pc = current_pc + instruction_size; else sim->set_reg(sim, 15, current_pc + instruction_size); return ERROR_OK; } } else { uint16_t opcode; retval = target_read_u16(target, current_pc, &opcode); if (retval != ERROR_OK) return retval; retval = thumb_evaluate_opcode(opcode, current_pc, &instruction); if (retval != ERROR_OK) return retval; instruction_size = 2; /* check condition code (only for branch (1) instructions) */ if ((opcode & 0xf000) == 0xd000 && !thumb_pass_branch_condition( sim->get_cpsr(sim, 0, 32), opcode)) { if (dry_run_pc) *dry_run_pc = current_pc + instruction_size; else sim->set_reg(sim, 15, current_pc + instruction_size); return ERROR_OK; } /* Deal with 32-bit BL/BLX */ if ((opcode & 0xf800) == 0xf000) { uint32_t high = instruction.info.b_bl_bx_blx.target_address; retval = target_read_u16(target, current_pc+2, &opcode); if (retval != ERROR_OK) return retval; retval = thumb_evaluate_opcode(opcode, current_pc, &instruction); if (retval != ERROR_OK) return retval; instruction.info.b_bl_bx_blx.target_address += high; } } /* examine instruction type */ /* branch instructions */ if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX)) { uint32_t target_address; if (instruction.info.b_bl_bx_blx.reg_operand == -1) target_address = instruction.info.b_bl_bx_blx.target_address; else { target_address = sim->get_reg_mode(sim, instruction.info.b_bl_bx_blx.reg_operand); if (instruction.info.b_bl_bx_blx.reg_operand == 15) target_address += 2 * instruction_size; } if (dry_run_pc) { *dry_run_pc = target_address & ~1; return ERROR_OK; } else { if (instruction.type == ARM_B) sim->set_reg(sim, 15, target_address); else if (instruction.type == ARM_BL) { uint32_t old_pc = sim->get_reg(sim, 15); int T = (sim->get_state(sim) == ARM_STATE_THUMB); sim->set_reg_mode(sim, 14, old_pc + 4 + T); sim->set_reg(sim, 15, target_address); } else if (instruction.type == ARM_BX) { if (target_address & 0x1) sim->set_state(sim, ARM_STATE_THUMB); else sim->set_state(sim, ARM_STATE_ARM); sim->set_reg(sim, 15, target_address & 0xfffffffe); } else if (instruction.type == ARM_BLX) { uint32_t old_pc = sim->get_reg(sim, 15); int T = (sim->get_state(sim) == ARM_STATE_THUMB); sim->set_reg_mode(sim, 14, old_pc + 4 + T); if (target_address & 0x1) sim->set_state(sim, ARM_STATE_THUMB); else sim->set_state(sim, ARM_STATE_ARM); sim->set_reg(sim, 15, target_address & 0xfffffffe); } return ERROR_OK; } } /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */ else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC)) || ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN))) { uint32_t Rd, Rn, shifter_operand; uint8_t C = sim->get_cpsr(sim, 29, 1); uint8_t carry_out; Rd = 0x0; /* ARM_MOV and ARM_MVN does not use Rn */ if ((instruction.type != ARM_MOV) && (instruction.type != ARM_MVN)) Rn = sim->get_reg_mode(sim, instruction.info.data_proc.Rn); else Rn = 0; shifter_operand = arm_shifter_operand(sim, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out); /* adjust Rn in case the PC is being read */ if (instruction.info.data_proc.Rn == 15) Rn += 2 * instruction_size; if (instruction.type == ARM_AND) Rd = Rn & shifter_operand; else if (instruction.type == ARM_EOR) Rd = Rn ^ shifter_operand; else if (instruction.type == ARM_SUB) Rd = Rn - shifter_operand; else if (instruction.type == ARM_RSB) Rd = shifter_operand - Rn; else if (instruction.type == ARM_ADD) Rd = Rn + shifter_operand; else if (instruction.type == ARM_ADC) Rd = Rn + shifter_operand + (C & 1); else if (instruction.type == ARM_SBC) Rd = Rn - shifter_operand - (C & 1) ? 0 : 1; else if (instruction.type == ARM_RSC) Rd = shifter_operand - Rn - (C & 1) ? 0 : 1; else if (instruction.type == ARM_ORR) Rd = Rn | shifter_operand; else if (instruction.type == ARM_BIC) Rd = Rn & ~(shifter_operand); else if (instruction.type == ARM_MOV) Rd = shifter_operand; else if (instruction.type == ARM_MVN) Rd = ~shifter_operand; else LOG_WARNING("unhandled instruction type"); if (dry_run_pc) { if (instruction.info.data_proc.Rd == 15) *dry_run_pc = Rd & ~1; else *dry_run_pc = current_pc + instruction_size; return ERROR_OK; } else { if (instruction.info.data_proc.Rd == 15) { sim->set_reg_mode(sim, 15, Rd & ~1); if (Rd & 1) sim->set_state(sim, ARM_STATE_THUMB); else sim->set_state(sim, ARM_STATE_ARM); return ERROR_OK; } sim->set_reg_mode(sim, instruction.info.data_proc.Rd, Rd); LOG_WARNING("no updating of flags yet"); } } /* compare instructions (CMP, CMN, TST, TEQ) */ else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN)) { if (dry_run_pc) { *dry_run_pc = current_pc + instruction_size; return ERROR_OK; } else LOG_WARNING("no updating of flags yet"); } /* load register instructions */ else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH)) { uint32_t load_address = 0, modified_address = 0, load_value = 0; uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store.Rn); /* adjust Rn in case the PC is being read */ if (instruction.info.load_store.Rn == 15) Rn += 2 * instruction_size; if (instruction.info.load_store.offset_mode == 0) { if (instruction.info.load_store.U) modified_address = Rn + instruction.info.load_store.offset.offset; else modified_address = Rn - instruction.info.load_store.offset.offset; } else if (instruction.info.load_store.offset_mode == 1) { uint32_t offset; uint32_t Rm = sim->get_reg_mode(sim, instruction.info.load_store.offset.reg.Rm); uint8_t shift = instruction.info.load_store.offset.reg.shift; uint8_t shift_imm = instruction.info.load_store.offset.reg.shift_imm; uint8_t carry = sim->get_cpsr(sim, 29, 1); offset = arm_shift(shift, Rm, shift_imm, &carry); if (instruction.info.load_store.U) modified_address = Rn + offset; else modified_address = Rn - offset; } else LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)"); if (instruction.info.load_store.index_mode == 0) { /* offset mode * we load from the modified address, but don't change * the base address register */ load_address = modified_address; modified_address = Rn; } else if (instruction.info.load_store.index_mode == 1) { /* pre-indexed mode * we load from the modified address, and write it * back to the base address register */ load_address = modified_address; } else if (instruction.info.load_store.index_mode == 2) { /* post-indexed mode * we load from the unmodified address, and write the * modified address back */ load_address = Rn; } if ((!dry_run_pc) || (instruction.info.load_store.Rd == 15)) { retval = target_read_u32(target, load_address, &load_value); if (retval != ERROR_OK) return retval; } if (dry_run_pc) { if (instruction.info.load_store.Rd == 15) *dry_run_pc = load_value & ~1; else *dry_run_pc = current_pc + instruction_size; return ERROR_OK; } else { if ((instruction.info.load_store.index_mode == 1) || (instruction.info.load_store.index_mode == 2)) sim->set_reg_mode(sim, instruction.info.load_store.Rn, modified_address); if (instruction.info.load_store.Rd == 15) { sim->set_reg_mode(sim, 15, load_value & ~1); if (load_value & 1) sim->set_state(sim, ARM_STATE_THUMB); else sim->set_state(sim, ARM_STATE_ARM); return ERROR_OK; } sim->set_reg_mode(sim, instruction.info.load_store.Rd, load_value); } } /* load multiple instruction */ else if (instruction.type == ARM_LDM) { int i; uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn); uint32_t load_values[16]; int bits_set = 0; for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple.register_list & (1 << i)) bits_set++; } switch (instruction.info.load_store_multiple.addressing_mode) { case 0: /* Increment after */ /* Rn = Rn; */ break; case 1: /* Increment before */ Rn = Rn + 4; break; case 2: /* Decrement after */ Rn = Rn - (bits_set * 4) + 4; break; case 3: /* Decrement before */ Rn = Rn - (bits_set * 4); break; } for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple.register_list & (1 << i)) { if ((!dry_run_pc) || (i == 15)) target_read_u32(target, Rn, &load_values[i]); Rn += 4; } } if (dry_run_pc) { if (instruction.info.load_store_multiple.register_list & 0x8000) { *dry_run_pc = load_values[15] & ~1; return ERROR_OK; } } else { int update_cpsr = 0; if (instruction.info.load_store_multiple.S) { if (instruction.info.load_store_multiple.register_list & 0x8000) update_cpsr = 1; } for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple.register_list & (1 << i)) { if (i == 15) { uint32_t val = load_values[i]; sim->set_reg_mode(sim, i, val & ~1); if (val & 1) sim->set_state(sim, ARM_STATE_THUMB); else sim->set_state(sim, ARM_STATE_ARM); } else sim->set_reg_mode(sim, i, load_values[i]); } } if (update_cpsr) { uint32_t spsr = sim->get_reg_mode(sim, 16); sim->set_reg(sim, ARMV4_5_CPSR, spsr); } /* base register writeback */ if (instruction.info.load_store_multiple.W) sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn); if (instruction.info.load_store_multiple.register_list & 0x8000) return ERROR_OK; } } /* store multiple instruction */ else if (instruction.type == ARM_STM) { int i; if (dry_run_pc) { /* STM wont affect PC (advance by instruction size */ } else { uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn); int bits_set = 0; for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple.register_list & (1 << i)) bits_set++; } switch (instruction.info.load_store_multiple.addressing_mode) { case 0: /* Increment after */ /* Rn = Rn; */ break; case 1: /* Increment before */ Rn = Rn + 4; break; case 2: /* Decrement after */ Rn = Rn - (bits_set * 4) + 4; break; case 3: /* Decrement before */ Rn = Rn - (bits_set * 4); break; } for (i = 0; i < 16; i++) { if (instruction.info.load_store_multiple.register_list & (1 << i)) { target_write_u32(target, Rn, sim->get_reg_mode(sim, i)); Rn += 4; } } /* base register writeback */ if (instruction.info.load_store_multiple.W) sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn); } } else if (!dry_run_pc) { /* the instruction wasn't handled, but we're supposed to simulate it */ LOG_ERROR("Unimplemented instruction, could not simulate it."); return ERROR_FAIL; } if (dry_run_pc) { *dry_run_pc = current_pc + instruction_size; return ERROR_OK; } else { sim->set_reg(sim, 15, current_pc + instruction_size); return ERROR_OK; } } static uint32_t armv4_5_get_reg(struct arm_sim_interface *sim, int reg) { struct arm *arm = (struct arm *)sim->user_data; return buf_get_u32(arm->core_cache->reg_list[reg].value, 0, 32); } static void armv4_5_set_reg(struct arm_sim_interface *sim, int reg, uint32_t value) { struct arm *arm = (struct arm *)sim->user_data; buf_set_u32(arm->core_cache->reg_list[reg].value, 0, 32, value); } static uint32_t armv4_5_get_reg_mode(struct arm_sim_interface *sim, int reg) { struct arm *arm = (struct arm *)sim->user_data; return buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm->core_mode, reg).value, 0, 32); } static void armv4_5_set_reg_mode(struct arm_sim_interface *sim, int reg, uint32_t value) { struct arm *arm = (struct arm *)sim->user_data; buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm->core_mode, reg).value, 0, 32, value); } static uint32_t armv4_5_get_cpsr(struct arm_sim_interface *sim, int pos, int bits) { struct arm *arm = (struct arm *)sim->user_data; return buf_get_u32(arm->cpsr->value, pos, bits); } static enum arm_state armv4_5_get_state(struct arm_sim_interface *sim) { struct arm *arm = (struct arm *)sim->user_data; return arm->core_state; } static void armv4_5_set_state(struct arm_sim_interface *sim, enum arm_state mode) { struct arm *arm = (struct arm *)sim->user_data; arm->core_state = mode; } static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim) { struct arm *arm = (struct arm *)sim->user_data; return arm->core_mode; } int arm_simulate_step(struct target *target, uint32_t *dry_run_pc) { struct arm *arm = target_to_arm(target); struct arm_sim_interface sim; sim.user_data = arm; sim.get_reg = &armv4_5_get_reg; sim.set_reg = &armv4_5_set_reg; sim.get_reg_mode = &armv4_5_get_reg_mode; sim.set_reg_mode = &armv4_5_set_reg_mode; sim.get_cpsr = &armv4_5_get_cpsr; sim.get_mode = &armv4_5_get_mode; sim.get_state = &armv4_5_get_state; sim.set_state = &armv4_5_set_state; return arm_simulate_step_core(target, dry_run_pc, &sim); } openocd-0.9.0/src/target/arm_simulator.h0000644000175000017500000000430612315575361015207 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM_SIMULATOR_H #define ARM_SIMULATOR_H struct target; struct arm_sim_interface { void *user_data; uint32_t (*get_reg)(struct arm_sim_interface *sim, int reg); void (*set_reg)(struct arm_sim_interface *sim, int reg, uint32_t value); uint32_t (*get_reg_mode)(struct arm_sim_interface *sim, int reg); void (*set_reg_mode)(struct arm_sim_interface *sim, int reg, uint32_t value); uint32_t (*get_cpsr)(struct arm_sim_interface *sim, int pos, int bits); enum arm_state (*get_state)(struct arm_sim_interface *sim); void (*set_state)(struct arm_sim_interface *sim, enum arm_state mode); enum arm_mode (*get_mode)(struct arm_sim_interface *sim); }; /* armv4_5 version */ int arm_simulate_step(struct target *target, uint32_t *dry_run_pc); #endif /* ARM_SIMULATOR_H */ openocd-0.9.0/src/target/arm_opcodes.h0000644000175000017500000002252712315575361014631 00000000000000/* * Copyright (C) 2005 by Dominic Rath * Dominic.Rath@gmx.de * * Copyright (C) 2006 by Magnus Lundin * lundin@mlu.mine.nu * * Copyright (C) 2008 by Spencer Oliver * spen@spen-soft.co.uk * * Copyright (C) 2009 by Øyvind Harboe * oyvind.harboe@zylin.com * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __ARM_OPCODES_H #define __ARM_OPCODES_H /** * @file * Macros used to generate various ARM or Thumb opcodes. */ /* ARM mode instructions */ /* Store multiple increment after * Rn: base register * List: for each bit in list: store register * S: in priviledged mode: store user-mode registers * W = 1: update the base register. W = 0: leave the base register untouched */ #define ARMV4_5_STMIA(Rn, List, S, W) \ (0xe8800000 | ((S) << 22) | ((W) << 21) | ((Rn) << 16) | (List)) /* Load multiple increment after * Rn: base register * List: for each bit in list: store register * S: in priviledged mode: store user-mode registers * W = 1: update the base register. W = 0: leave the base register untouched */ #define ARMV4_5_LDMIA(Rn, List, S, W) \ (0xe8900000 | ((S) << 22) | ((W) << 21) | ((Rn) << 16) | (List)) /* MOV r8, r8 */ #define ARMV4_5_NOP (0xe1a08008) /* Move PSR to general purpose register * R = 1: SPSR R = 0: CPSR * Rn: target register */ #define ARMV4_5_MRS(Rn, R) (0xe10f0000 | ((R) << 22) | ((Rn) << 12)) /* Store register * Rd: register to store * Rn: base register */ #define ARMV4_5_STR(Rd, Rn) (0xe5800000 | ((Rd) << 12) | ((Rn) << 16)) /* Load register * Rd: register to load * Rn: base register */ #define ARMV4_5_LDR(Rd, Rn) (0xe5900000 | ((Rd) << 12) | ((Rn) << 16)) /* Move general purpose register to PSR * R = 1: SPSR R = 0: CPSR * Field: Field mask * 1: control field 2: extension field 4: status field 8: flags field * Rm: source register */ #define ARMV4_5_MSR_GP(Rm, Field, R) \ (0xe120f000 | (Rm) | ((Field) << 16) | ((R) << 22)) #define ARMV4_5_MSR_IM(Im, Rotate, Field, R) \ (0xe320f000 | (Im) | ((Rotate) << 8) | ((Field) << 16) | ((R) << 22)) /* Load Register Word Immediate Post-Index * Rd: register to load * Rn: base register */ #define ARMV4_5_LDRW_IP(Rd, Rn) (0xe4900004 | ((Rd) << 12) | ((Rn) << 16)) /* Load Register Halfword Immediate Post-Index * Rd: register to load * Rn: base register */ #define ARMV4_5_LDRH_IP(Rd, Rn) (0xe0d000b2 | ((Rd) << 12) | ((Rn) << 16)) /* Load Register Byte Immediate Post-Index * Rd: register to load * Rn: base register */ #define ARMV4_5_LDRB_IP(Rd, Rn) (0xe4d00001 | ((Rd) << 12) | ((Rn) << 16)) /* Store register Word Immediate Post-Index * Rd: register to store * Rn: base register */ #define ARMV4_5_STRW_IP(Rd, Rn) (0xe4800004 | ((Rd) << 12) | ((Rn) << 16)) /* Store register Halfword Immediate Post-Index * Rd: register to store * Rn: base register */ #define ARMV4_5_STRH_IP(Rd, Rn) (0xe0c000b2 | ((Rd) << 12) | ((Rn) << 16)) /* Store register Byte Immediate Post-Index * Rd: register to store * Rn: base register */ #define ARMV4_5_STRB_IP(Rd, Rn) (0xe4c00001 | ((Rd) << 12) | ((Rn) << 16)) /* Branch (and Link) * Im: Branch target (left-shifted by 2 bits, added to PC) * L: 1: branch and link 0: branch only */ #define ARMV4_5_B(Im, L) (0xea000000 | (Im) | ((L) << 24)) /* Branch and exchange (ARM state) * Rm: register holding branch target address */ #define ARMV4_5_BX(Rm) (0xe12fff10 | (Rm)) /* Store data from coprocessor to consecutive memory * See Armv7-A arch doc section A8.6.187 * P: 1=index mode (offset from Rn) * U: 1=add, 0=subtract Rn address with imm * D: Opcode D encoding * W: write back the offset start address to the Rn register * CP: Coprocessor number (4 bits) * CRd: Coprocessor source register (4 bits) * Rn: Base register for memory address (4 bits) * imm: Immediate value (0 - 1020, must be divisible by 4) */ #define ARMV4_5_STC(P, U, D, W, CP, CRd, Rn, imm) \ (0xec000000 | ((P) << 24) | ((U) << 23) | ((D) << 22) | \ ((W) << 21) | ((Rn) << 16) | ((CRd) << 12) | ((CP) << 8) | ((imm)>>2)) /* Loads data from consecutive memory to coprocessor * See Armv7-A arch doc section A8.6.51 * P: 1=index mode (offset from Rn) * U: 1=add, 0=subtract Rn address with imm * D: Opcode D encoding * W: write back the offset start address to the Rn register * CP: Coprocessor number (4 bits) * CRd: Coprocessor dest register (4 bits) * Rn: Base register for memory address (4 bits) * imm: Immediate value (0 - 1020, must be divisible by 4) */ #define ARMV4_5_LDC(P, U, D, W, CP, CRd, Rn, imm) \ (0xec100000 | ((P) << 24) | ((U) << 23) | ((D) << 22) | \ ((W) << 21) | ((Rn) << 16) | ((CRd) << 12) | ((CP) << 8) | ((imm) >> 2)) /* Move to ARM register from coprocessor * CP: Coprocessor number * op1: Coprocessor opcode * Rd: destination register * CRn: first coprocessor operand * CRm: second coprocessor operand * op2: Second coprocessor opcode */ #define ARMV4_5_MRC(CP, op1, Rd, CRn, CRm, op2) \ (0xee100010 | (CRm) | ((op2) << 5) | ((CP) << 8) \ | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21)) /* Move to coprocessor from ARM register * CP: Coprocessor number * op1: Coprocessor opcode * Rd: destination register * CRn: first coprocessor operand * CRm: second coprocessor operand * op2: Second coprocessor opcode */ #define ARMV4_5_MCR(CP, op1, Rd, CRn, CRm, op2) \ (0xee000010 | (CRm) | ((op2) << 5) | ((CP) << 8) \ | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21)) /* Breakpoint instruction (ARMv5) * Im: 16-bit immediate */ #define ARMV5_BKPT(Im) (0xe1200070 | ((Im & 0xfff0) << 8) | (Im & 0xf)) /* Thumb mode instructions * * NOTE: these 16-bit opcodes fill both halves of a word with the same * value. The reason for this is that when we need to execute Thumb * opcodes on ARM7/ARM9 cores (to switch to ARM state on debug entry), * we must shift 32 bits to the bus using scan chain 1 ... if we write * both halves, we don't need to track which half matters. On ARMv6 and * ARMv7 we don't execute Thumb instructions in debug mode; the ITR * register does not accept Thumb (or Thumb2) opcodes. */ /* Store register (Thumb mode) * Rd: source register * Rn: base register */ #define ARMV4_5_T_STR(Rd, Rn) \ ((0x6000 | (Rd) | ((Rn) << 3)) | \ ((0x6000 | (Rd) | ((Rn) << 3)) << 16)) /* Load register (Thumb state) * Rd: destination register * Rn: base register */ #define ARMV4_5_T_LDR(Rd, Rn) \ ((0x6800 | ((Rn) << 3) | (Rd)) \ | ((0x6800 | ((Rn) << 3) | (Rd)) << 16)) /* Load multiple (Thumb state) * Rn: base register * List: for each bit in list: store register */ #define ARMV4_5_T_LDMIA(Rn, List) \ ((0xc800 | ((Rn) << 8) | (List)) \ | ((0xc800 | ((Rn) << 8) | (List)) << 16)) /* Load register with PC relative addressing * Rd: register to load */ #define ARMV4_5_T_LDR_PCREL(Rd) \ ((0x4800 | ((Rd) << 8)) \ | ((0x4800 | ((Rd) << 8)) << 16)) /* Move hi register (Thumb mode) * Rd: destination register * Rm: source register */ #define ARMV4_5_T_MOV(Rd, Rm) \ ((0x4600 | ((Rd) & 0x7) | (((Rd) & 0x8) << 4) | \ (((Rm) & 0x7) << 3) | (((Rm) & 0x8) << 3)) \ | ((0x4600 | ((Rd) & 0x7) | (((Rd) & 0x8) << 4) | \ (((Rm) & 0x7) << 3) | (((Rm) & 0x8) << 3)) << 16)) /* No operation (Thumb mode) * NOTE: this is "MOV r8, r8" ... Thumb2 adds two * architected NOPs, 16-bit and 32-bit. */ #define ARMV4_5_T_NOP (0x46c0 | (0x46c0 << 16)) /* Move immediate to register (Thumb state) * Rd: destination register * Im: 8-bit immediate value */ #define ARMV4_5_T_MOV_IM(Rd, Im) \ ((0x2000 | ((Rd) << 8) | (Im)) \ | ((0x2000 | ((Rd) << 8) | (Im)) << 16)) /* Branch and Exchange * Rm: register containing branch target */ #define ARMV4_5_T_BX(Rm) \ ((0x4700 | ((Rm) << 3)) \ | ((0x4700 | ((Rm) << 3)) << 16)) /* Branch (Thumb state) * Imm: Branch target */ #define ARMV4_5_T_B(Imm) \ ((0xe000 | (Imm)) \ | ((0xe000 | (Imm)) << 16)) /* Breakpoint instruction (ARMv5) (Thumb state) * Im: 8-bit immediate */ #define ARMV5_T_BKPT(Im) \ ((0xbe00 | (Im)) \ | ((0xbe00 | (Im)) << 16)) /* Move to Register from Special Register * 32 bit Thumb2 instruction * Rd: destination register * SYSm: source special register */ #define ARM_T2_MRS(Rd, SYSm) \ ((0xF3EF) | ((0x8000 | (Rd << 8) | SYSm) << 16)) /* Move from Register from Special Register * 32 bit Thumb2 instruction * Rd: source register * SYSm: destination special register */ #define ARM_T2_MSR(SYSm, Rn) \ ((0xF380 | (Rn << 8)) | ((0x8800 | SYSm) << 16)) /* Change Processor State. * 16 bit Thumb2 instruction * Rd: source register * IF: A_FLAG and/or I_FLAG and/or F_FLAG */ #define A_FLAG 4 #define I_FLAG 2 #define F_FLAG 1 #define ARM_T2_CPSID(IF) \ ((0xB660 | (1 << 8) | ((IF)&0x3)) \ | ((0xB660 | (1 << 8) | ((IF)&0x3)) << 16)) #define ARM_T2_CPSIE(IF) \ ((0xB660 | (0 << 8) | ((IF)&0x3)) \ | ((0xB660 | (0 << 8) | ((IF)&0x3)) << 16)) #endif /* __ARM_OPCODES_H */ openocd-0.9.0/src/target/arm7tdmi.c0000644000175000017500000005741212315575361014056 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm7tdmi.h" #include "target_type.h" #include "register.h" #include "arm_opcodes.h" /* * For information about ARM7TDMI, see ARM DDI 0210C (r4p1) * or ARM DDI 0029G (r3). "Debug In Depth", Appendix B, * covers JTAG support. */ #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif static int arm7tdmi_examine_debug_reason(struct target *target) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); /* only check the debug reason if we don't know it already */ if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { struct scan_field fields[2]; uint8_t databus[4]; uint8_t breakpoint; fields[0].num_bits = 1; fields[0].out_value = NULL; fields[0].in_value = &breakpoint; fields[1].num_bits = 32; fields[1].out_value = NULL; fields[1].in_value = databus; retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; fields[0].in_value = NULL; fields[0].out_value = &breakpoint; fields[1].in_value = NULL; fields[1].out_value = databus; jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE); if (breakpoint & 1) target->debug_reason = DBG_REASON_WATCHPOINT; else target->debug_reason = DBG_REASON_BREAKPOINT; } return ERROR_OK; } static const int arm7tdmi_num_bits[] = {1, 32}; static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint) { uint8_t bp = breakpoint ? 1 : 0; uint8_t out_value[4]; buf_set_u32(out_value, 0, 32, flip_u32(out, 32)); struct scan_field fields[2] = { { .num_bits = arm7tdmi_num_bits[0], .out_value = &bp }, { .num_bits = arm7tdmi_num_bits[1], .out_value = out_value }, }; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_runtest(0, TAP_DRPAUSE); return ERROR_OK; } /* put an instruction in the ARM7TDMI pipeline or write the data bus, * and optionally read data * * FIXME remove the unused "deprecated" parameter */ static inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t out, uint32_t *deprecated, int breakpoint) { int retval; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; return arm7tdmi_clock_out_inner(jtag_info, out, breakpoint); } /* clock the target, reading the databus */ static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in) { int retval = ERROR_OK; struct scan_field fields[2]; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 1; fields[0].out_value = NULL; fields[0].in_value = NULL; fields[1].num_bits = 32; fields[1].out_value = NULL; fields[1].in_value = (uint8_t *)in; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback(arm7flip32, (jtag_callback_data_t)in); jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("in: 0x%8.8x", *in); else LOG_ERROR("BUG: called with in == NULL"); #endif return ERROR_OK; } /* clock the target, and read the databus * the *in pointer points to a buffer where elements of 'size' bytes * are stored in big (be == 1) or little (be == 0) endianness */ static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info, void *in, int size, int be) { int retval = ERROR_OK; struct scan_field fields[3]; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 1; fields[0].out_value = NULL; fields[0].in_value = NULL; if (size == 4) { fields[1].num_bits = 32; fields[1].out_value = NULL; fields[1].in_value = in; } else { /* Discard irrelevant bits of the scan, making sure we don't write more * than size bytes to in */ fields[1].num_bits = 32 - size * 8; fields[1].out_value = NULL; fields[1].in_value = NULL; fields[2].num_bits = size * 8; fields[2].out_value = NULL; fields[2].in_value = in; } jtag_add_dr_scan(jtag_info->tap, size == 4 ? 2 : 3, fields, TAP_DRPAUSE); jtag_add_callback4(arm7_9_endianness_callback, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)1); jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in); else LOG_ERROR("BUG: called with in == NULL"); } #endif return ERROR_OK; } static void arm7tdmi_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* save r0 before using it and put system in ARM state * to allow common handling of ARM and THUMB debugging */ /* fetch STR r0, [r0] */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, r0); /* MOV r0, r15 fetched, STR in Decode */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, pc); /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, data for LDR r0, [PC, #0] */ arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0); /* nothing fetched, data from previous cycle is written to register */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* fetch BX */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0); /* NOP fetched, BX in Decode, MOV in Execute */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* NOP fetched, BX in Execute (1) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); jtag_execute_queue(); /* fix program counter: * MOV r0, r15 was the 4th instruction (+6) * reading PC in Thumb state gives address of instruction + 4 */ *pc -= 0xa; } /* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s? * * The solution is to arrange for a large out/in scan in this loop and * and convert data afterwards. */ static void arm7tdmi_read_core_regs(struct target *target, uint32_t mask, uint32_t *core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0); /* fetch NOP, STM in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, STM still in EXECUTE (1 + i cycle) */ arm7tdmi_clock_data_in(jtag_info, core_regs[i]); } } static void arm7tdmi_read_core_regs_target_buffer(struct target *target, uint32_t mask, void *buffer, int size) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0; uint32_t *buf_u32 = buffer; uint16_t *buf_u16 = buffer; uint8_t *buf_u8 = buffer; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0); /* fetch NOP, STM in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); for (i = 0; i <= 15; i++) { /* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */ if (mask & (1 << i)) { switch (size) { case 4: arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be); break; case 2: arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be); break; case 1: arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be); break; } } } } static void arm7tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0); /* STR r0, [r15] */ arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0); /* fetch NOP, STR in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, STR still in EXECUTE (2nd cycle) */ arm7tdmi_clock_data_in(jtag_info, xpsr); } static void arm7tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr); /* MSR1 fetched */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0); /* MSR2 fetched, MSR1 in DECODE */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0); /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0); /* nothing fetched, MSR1 in EXECUTE (2) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0); /* nothing fetched, MSR2 in EXECUTE (2) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, MSR3 in EXECUTE (2) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* NOP fetched, MSR4 in EXECUTE (1) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, MSR4 in EXECUTE (2) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); } static void arm7tdmi_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr); /* MSR fetched */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0); /* NOP fetched, MSR in DECODE */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* NOP fetched, MSR in EXECUTE (1) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, MSR in EXECUTE (2) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); } static void arm7tdmi_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */ arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0); } arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); } static void arm7tdmi_load_word_regs(struct target *target, uint32_t mask) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load-multiple into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0); } static void arm7tdmi_load_hword_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load half-word into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0); } static void arm7tdmi_load_byte_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load byte into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0); } static void arm7tdmi_store_word_regs(struct target *target, uint32_t mask) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store-multiple into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0); } static void arm7tdmi_store_hword_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store half-word into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0); } static void arm7tdmi_store_byte_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store byte into the pipeline */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0); } static void arm7tdmi_write_pc(struct target *target, uint32_t pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */ arm7tdmi_clock_out_inner(jtag_info, pc, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (4th cycle) */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (5th cycle) */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); } static void arm7tdmi_branch_resume(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_B(0xfffffa, 0), 0); } static void arm7tdmi_branch_resume_thumb(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; LOG_DEBUG("-"); /* LDMIA r0, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */ arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* Branch and eXchange */ arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0); embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* target is now in Thumb state */ embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* target is now in Thumb state */ embeddedice_read_reg(dbg_stat); /* load r0 value */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0); /* fetch NOP, LDR in Decode */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* fetch NOP, LDR in Execute */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */ arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0); /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); embeddedice_read_reg(dbg_stat); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0); } static void arm7tdmi_build_reg_cache(struct target *target) { struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct arm *arm = target_to_arm(target); (*cache_p) = arm_build_reg_cache(target, arm); } int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm7tdmi_build_reg_cache(target); return ERROR_OK; } int arm7tdmi_init_arch_info(struct target *target, struct arm7_9_common *arm7_9, struct jtag_tap *tap) { /* prepare JTAG information for the new target */ arm7_9->jtag_info.tap = tap; arm7_9->jtag_info.scann_size = 4; /* register arch-specific functions */ arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason; arm7_9->change_to_arm = arm7tdmi_change_to_arm; arm7_9->read_core_regs = arm7tdmi_read_core_regs; arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer; arm7_9->read_xpsr = arm7tdmi_read_xpsr; arm7_9->write_xpsr = arm7tdmi_write_xpsr; arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8; arm7_9->write_core_regs = arm7tdmi_write_core_regs; arm7_9->load_word_regs = arm7tdmi_load_word_regs; arm7_9->load_hword_reg = arm7tdmi_load_hword_reg; arm7_9->load_byte_reg = arm7tdmi_load_byte_reg; arm7_9->store_word_regs = arm7tdmi_store_word_regs; arm7_9->store_hword_reg = arm7tdmi_store_hword_reg; arm7_9->store_byte_reg = arm7tdmi_store_byte_reg; arm7_9->write_pc = arm7tdmi_write_pc; arm7_9->branch_resume = arm7tdmi_branch_resume; arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb; arm7_9->enable_single_step = arm7_9_enable_eice_step; arm7_9->disable_single_step = arm7_9_disable_eice_step; arm7_9->write_memory = arm7_9_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; arm7_9->pre_restore_context = NULL; /* initialize arch-specific breakpoint handling */ arm7_9->arm_bkpt = 0xdeeedeee; arm7_9->thumb_bkpt = 0xdeee; arm7_9->dbgreq_adjust_pc = 2; arm7_9_init_arch_info(target, arm7_9); return ERROR_OK; } static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp) { struct arm7_9_common *arm7_9; arm7_9 = calloc(1, sizeof(struct arm7_9_common)); arm7tdmi_init_arch_info(target, arm7_9, target->tap); arm7_9->arm.is_armv4 = true; return ERROR_OK; } /** Holds methods for ARM7TDMI targets. */ struct target_type arm7tdmi_target = { .name = "arm7tdmi", .poll = arm7_9_poll, .arch_state = arm_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm7_9_command_handlers, .target_create = arm7tdmi_target_create, .init_target = arm7tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm7tdmi.h0000644000175000017500000000367012315575361014060 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM7TDMI_H #define ARM7TDMI_H #include "embeddedice.h" int arm7tdmi_init_arch_info(struct target *target, struct arm7_9_common *arm7_9, struct jtag_tap *tap); int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target); #endif /* ARM7TDMI_H */ openocd-0.9.0/src/target/avrt.c0000644000175000017500000001437012315575361013302 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * SimonQian@SimonQian.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "avrt.h" #include "target.h" #include "target_type.h" #define AVR_JTAG_INS_LEN 4 /* forward declarations */ static int avr_target_create(struct target *target, Jim_Interp *interp); static int avr_init_target(struct command_context *cmd_ctx, struct target *target); static int avr_arch_state(struct target *target); static int avr_poll(struct target *target); static int avr_halt(struct target *target); static int avr_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints); static int avr_assert_reset(struct target *target); static int avr_deassert_reset(struct target *target); /* IR and DR functions */ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti); static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti); static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti); static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti); struct target_type avr_target = { .name = "avr", .poll = avr_poll, .arch_state = avr_arch_state, .halt = avr_halt, .resume = avr_resume, .step = avr_step, .assert_reset = avr_assert_reset, .deassert_reset = avr_deassert_reset, /* .get_gdb_reg_list = avr_get_gdb_reg_list, .read_memory = avr_read_memory, .write_memory = avr_write_memory, .bulk_write_memory = avr_bulk_write_memory, .checksum_memory = avr_checksum_memory, .blank_check_memory = avr_blank_check_memory, .run_algorithm = avr_run_algorithm, .add_breakpoint = avr_add_breakpoint, .remove_breakpoint = avr_remove_breakpoint, .add_watchpoint = avr_add_watchpoint, .remove_watchpoint = avr_remove_watchpoint, */ .target_create = avr_target_create, .init_target = avr_init_target, }; static int avr_target_create(struct target *target, Jim_Interp *interp) { struct avr_common *avr = calloc(1, sizeof(struct avr_common)); avr->jtag_info.tap = target->tap; target->arch_info = avr; return ERROR_OK; } static int avr_init_target(struct command_context *cmd_ctx, struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_arch_state(struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_poll(struct target *target) { if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING)) target->state = TARGET_HALTED; LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_halt(struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_assert_reset(struct target *target) { target->state = TARGET_RESET; LOG_DEBUG("%s", __func__); return ERROR_OK; } static int avr_deassert_reset(struct target *target) { target->state = TARGET_RUNNING; LOG_DEBUG("%s", __func__); return ERROR_OK; } int avr_jtag_senddat(struct jtag_tap *tap, uint32_t* dr_in, uint32_t dr_out, int len) { return mcu_write_dr_u32(tap, dr_in, dr_out, len, 1); } int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out) { return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN, 1); } /* IR and DR functions */ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti) { if (NULL == tap) { LOG_ERROR("invalid tap"); return ERROR_FAIL; } if (ir_len != tap->ir_length) { LOG_ERROR("invalid ir_len"); return ERROR_FAIL; } { jtag_add_plain_ir_scan(tap->ir_length, ir_out, ir_in, TAP_IDLE); } return ERROR_OK; } static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti) { if (NULL == tap) { LOG_ERROR("invalid tap"); return ERROR_FAIL; } { jtag_add_plain_dr_scan(dr_len, dr_out, dr_in, TAP_IDLE); } return ERROR_OK; } static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti) { if (ir_len > 8) { LOG_ERROR("ir_len overflow, maxium is 8"); return ERROR_FAIL; } mcu_write_ir(tap, ir_in, &ir_out, ir_len, rti); return ERROR_OK; } static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int dr_len, int rti) { if (dr_len > 32) { LOG_ERROR("dr_len overflow, maxium is 32"); return ERROR_FAIL; } mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti); return ERROR_OK; } int mcu_execute_queue(void) { return jtag_execute_queue(); } openocd-0.9.0/src/target/avrt.h0000644000175000017500000000345212315575361013306 00000000000000/*************************************************************************** * Copyright (C) 2009 by Simon Qian * * SimonQian@SimonQian.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef AVRT_H #define AVRT_H #include struct mcu_jtag { struct jtag_tap *tap; }; struct avr_common { struct mcu_jtag jtag_info; }; int mcu_execute_queue(void); int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out); int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int len); #endif /* AVRT_H */ openocd-0.9.0/src/target/nds32_v3_common.c0000644000175000017500000005035512315575361015242 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "nds32_reg.h" #include "nds32_disassembler.h" #include "nds32.h" #include "nds32_aice.h" #include "nds32_v3_common.h" static struct nds32_v3_common_callback *v3_common_callback; static int nds32_v3_register_mapping(struct nds32 *nds32, int reg_no) { if (reg_no == PC) return IR11; return reg_no; } static int nds32_v3_get_debug_reason(struct nds32 *nds32, uint32_t *reason) { uint32_t edmsw; struct aice_port_s *aice = target_to_aice(nds32->target); aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw); *reason = (edmsw >> 12) & 0x0F; return ERROR_OK; } /** * Save processor state. This is called after a HALT instruction * succeeds, and on other occasions the processor enters debug mode * (breakpoint, watchpoint, etc). */ static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint) { LOG_DEBUG("nds32_v3_debug_entry"); enum target_state backup_state = nds32->target->state; nds32->target->state = TARGET_HALTED; if (nds32->init_arch_info_after_halted == false) { /* init architecture info according to config registers */ CHECK_RETVAL(nds32_config(nds32)); nds32->init_arch_info_after_halted = true; } /* REVISIT entire cache should already be invalid !!! */ register_cache_invalidate(nds32->core_cache); /* deactivate all hardware breakpoints */ CHECK_RETVAL(v3_common_callback->deactivate_hardware_breakpoint(nds32->target)); if (enable_watchpoint) CHECK_RETVAL(v3_common_callback->deactivate_hardware_watchpoint(nds32->target)); struct breakpoint *syscall_break = &(nds32->syscall_break); if (nds32->virtual_hosting) { if (syscall_break->set) { /** disable virtual hosting */ /* remove breakpoint at syscall entry */ target_remove_breakpoint(nds32->target, syscall_break); syscall_break->set = 0; uint32_t value_pc; nds32_get_mapped_reg(nds32, PC, &value_pc); if (value_pc == syscall_break->address) /** process syscall for virtual hosting */ nds32->hit_syscall = true; } } if (ERROR_OK != nds32_examine_debug_reason(nds32)) { nds32->target->state = backup_state; /* re-activate all hardware breakpoints & watchpoints */ CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(nds32->target)); if (enable_watchpoint) CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(nds32->target)); return ERROR_FAIL; } /* Save registers. */ nds32_full_context(nds32); /* check interrupt level */ v3_common_callback->check_interrupt_stack(nds32); return ERROR_OK; } /** * Restore processor state. */ static int nds32_v3_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint) { LOG_DEBUG("nds32_v3_leave_debug_state"); struct target *target = nds32->target; /* activate all hardware breakpoints */ CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(target)); if (enable_watchpoint) { /* activate all watchpoints */ CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(target)); } /* restore interrupt stack */ v3_common_callback->restore_interrupt_stack(nds32); /* REVISIT once we start caring about MMU and cache state, * address it here ... */ /* restore PSW, PC, and R0 ... after flushing any modified * registers. */ CHECK_RETVAL(nds32_restore_context(target)); if (nds32->virtual_hosting) { /** enable virtual hosting */ uint32_t value_ir3; uint32_t entry_size; uint32_t syscall_address; /* get syscall entry address */ nds32_get_mapped_reg(nds32, IR3, &value_ir3); entry_size = 0x4 << (((value_ir3 >> 14) & 0x3) << 1); syscall_address = (value_ir3 & 0xFFFF0000) + entry_size * 8; /* The index of SYSCALL is 8 */ if (nds32->hit_syscall) { /* single step to skip syscall entry */ /* use IRET to skip syscall */ struct aice_port_s *aice = target_to_aice(target); uint32_t value_ir9; uint32_t value_ir6; uint32_t syscall_id; nds32_get_mapped_reg(nds32, IR6, &value_ir6); syscall_id = (value_ir6 >> 16) & 0x7FFF; if (syscall_id == NDS32_SYSCALL_EXIT) { /* If target hits exit syscall, do not use IRET to skip handler. */ aice_step(aice); } else { /* use api->read/write_reg to skip nds32 register cache */ uint32_t value_dimbr; aice_read_debug_reg(aice, NDS_EDM_SR_DIMBR, &value_dimbr); aice_write_register(aice, IR11, value_dimbr + 0xC); aice_read_register(aice, IR9, &value_ir9); value_ir9 += 4; /* syscall is always 4 bytes */ aice_write_register(aice, IR9, value_ir9); /* backup hardware breakpoint 0 */ uint32_t backup_bpa, backup_bpam, backup_bpc; aice_read_debug_reg(aice, NDS_EDM_SR_BPA0, &backup_bpa); aice_read_debug_reg(aice, NDS_EDM_SR_BPAM0, &backup_bpam); aice_read_debug_reg(aice, NDS_EDM_SR_BPC0, &backup_bpc); /* use hardware breakpoint 0 to stop cpu after skipping syscall */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, value_ir9); aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, 0); aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, 0xA); /* Execute two IRET. * First IRET is used to quit debug mode. * Second IRET is used to quit current syscall. */ uint32_t dim_inst[4] = {NOP, NOP, IRET, IRET}; aice_execute(aice, dim_inst, 4); /* restore origin hardware breakpoint 0 */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, backup_bpa); aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, backup_bpam); aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, backup_bpc); } nds32->hit_syscall = false; } /* insert breakpoint at syscall entry */ struct breakpoint *syscall_break = &(nds32->syscall_break); syscall_break->address = syscall_address; syscall_break->type = BKPT_SOFT; syscall_break->set = 1; target_add_breakpoint(target, syscall_break); } return ERROR_OK; } static int nds32_v3_get_exception_address(struct nds32 *nds32, uint32_t *address, uint32_t reason) { LOG_DEBUG("nds32_v3_get_exception_address"); struct aice_port_s *aice = target_to_aice(nds32->target); struct target *target = nds32->target; uint32_t edmsw; uint32_t edm_cfg; uint32_t match_bits; uint32_t match_count; int32_t i; static int32_t number_of_hard_break; uint32_t bp_control; if (number_of_hard_break == 0) { aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); number_of_hard_break = (edm_cfg & 0x7) + 1; } aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw); /* clear matching bits (write-one-clear) */ aice_write_debug_reg(aice, NDS_EDM_SR_EDMSW, edmsw); match_bits = (edmsw >> 4) & 0xFF; match_count = 0; for (i = 0 ; i < number_of_hard_break ; i++) { if (match_bits & (1 << i)) { aice_read_debug_reg(aice, NDS_EDM_SR_BPA0 + i, address); match_count++; /* If target hits multiple read/access watchpoint, * select the first one. */ aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &bp_control); if (0x3 == (bp_control & 0x3)) { match_count = 1; break; } } } if (match_count > 1) { /* multiple hits */ *address = 0; return ERROR_OK; } else if (match_count == 1) { uint32_t val_pc; uint32_t opcode; struct nds32_instruction instruction; struct watchpoint *wp; bool hit; nds32_get_mapped_reg(nds32, PC, &val_pc); if ((NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE == reason) || (NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE == reason)) { if (edmsw & 0x4) /* check EDMSW.IS_16BIT */ val_pc -= 2; else val_pc -= 4; } nds32_read_opcode(nds32, val_pc, &opcode); nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction); LOG_DEBUG("PC: 0x%08" PRIx32 ", access start: 0x%08" PRIx32 ", end: 0x%08" PRIx32, val_pc, instruction.access_start, instruction.access_end); /* check if multiple hits in the access range */ uint32_t in_range_watch_count = 0; for (wp = target->watchpoints; wp; wp = wp->next) { if ((instruction.access_start <= wp->address) && (wp->address < instruction.access_end)) in_range_watch_count++; } if (in_range_watch_count > 1) { /* Hit LSMW instruction. */ *address = 0; return ERROR_OK; } /* dispel false match */ hit = false; for (wp = target->watchpoints; wp; wp = wp->next) { if (((*address ^ wp->address) & (~wp->mask)) == 0) { uint32_t watch_start; uint32_t watch_end; watch_start = wp->address; watch_end = wp->address + wp->length; if ((watch_end <= instruction.access_start) || (instruction.access_end <= watch_start)) continue; hit = true; break; } } if (hit) return ERROR_OK; else return ERROR_FAIL; } else if (match_count == 0) { /* global stop is precise exception */ if ((NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP == reason) && nds32->global_stop) { /* parse instruction to get correct access address */ uint32_t val_pc; uint32_t opcode; struct nds32_instruction instruction; nds32_get_mapped_reg(nds32, PC, &val_pc); nds32_read_opcode(nds32, val_pc, &opcode); nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction); *address = instruction.access_start; return ERROR_OK; } } *address = 0xFFFFFFFF; return ERROR_FAIL; } void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback) { v3_common_callback = callback; } /** target_type functions: */ /* target request support */ int nds32_v3_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { /* AndesCore could use DTR register to communicate with OpenOCD * to output messages * Target data will be put in buffer * The format of DTR is as follow * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd * target_req_cmd has three possible values: * TARGET_REQ_TRACEMSG * TARGET_REQ_DEBUGMSG * TARGET_REQ_DEBUGCHAR * if size == 0, target will call target_asciimsg(), * else call target_hexmsg() */ LOG_WARNING("Not implemented: %s", __func__); return ERROR_OK; } int nds32_v3_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } /** * find out which watchpoint hits * get exception address and compare the address to watchpoints */ int nds32_v3_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) { static struct watchpoint scan_all_watchpoint; uint32_t exception_address; struct watchpoint *wp; struct nds32 *nds32 = target_to_nds32(target); exception_address = nds32->watched_address; if (exception_address == 0xFFFFFFFF) return ERROR_FAIL; if (exception_address == 0) { scan_all_watchpoint.address = 0; scan_all_watchpoint.rw = WPT_WRITE; scan_all_watchpoint.next = 0; scan_all_watchpoint.unique_id = 0x5CA8; *hit_watchpoint = &scan_all_watchpoint; return ERROR_OK; } for (wp = target->watchpoints; wp; wp = wp->next) { if (((exception_address ^ wp->address) & (~wp->mask)) == 0) { *hit_watchpoint = wp; return ERROR_OK; } } return ERROR_FAIL; } int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32) { nds32->register_map = nds32_v3_register_mapping; nds32->get_debug_reason = nds32_v3_get_debug_reason; nds32->enter_debug_state = nds32_v3_debug_entry; nds32->leave_debug_state = nds32_v3_leave_debug_state; nds32->get_watched_address = nds32_v3_get_exception_address; /* Init target->arch_info in nds32_init_arch_info(). * After this, user could use target_to_nds32() to get nds32 object */ nds32_init_arch_info(target, nds32); return ERROR_OK; } int nds32_v3_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } int nds32_v3_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ /* When DEX is set to one, hardware will enforce the following behavior without * modifying the corresponding control bits in PSW. * * Disable all interrupts * Become superuser mode * Turn off IT/DT * Use MMU_CFG.DE as the data access endian * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted * Disable audio special features * Disable inline function call * * Because hardware will turn off IT/DT by default, it MUST translate virtual address * to physical address. */ if (ERROR_OK == target->type->virt2phys(target, address, &physical_address)) address = physical_address; else return ERROR_FAIL; int result; struct aice_port_s *aice = target_to_aice(target); /* give arbitrary initial value to avoid warning messages */ enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU; if (nds32->hit_syscall) { /* Use bus mode to access memory during virtual hosting */ origin_access_channel = memory->access_channel; memory->access_channel = NDS_MEMORY_ACC_BUS; aice_memory_access(aice, NDS_MEMORY_ACC_BUS); } result = nds32_read_buffer(target, address, size, buffer); if (nds32->hit_syscall) { /* Restore access_channel after virtual hosting */ memory->access_channel = origin_access_channel; aice_memory_access(aice, origin_access_channel); } return result; } int nds32_v3_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ /* When DEX is set to one, hardware will enforce the following behavior without * modifying the corresponding control bits in PSW. * * Disable all interrupts * Become superuser mode * Turn off IT/DT * Use MMU_CFG.DE as the data access endian * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted * Disable audio special features * Disable inline function call * * Because hardware will turn off IT/DT by default, it MUST translate virtual address * to physical address. */ if (ERROR_OK == target->type->virt2phys(target, address, &physical_address)) address = physical_address; else return ERROR_FAIL; if (nds32->hit_syscall) { struct aice_port_s *aice = target_to_aice(target); enum nds_memory_access origin_access_channel; origin_access_channel = memory->access_channel; /* If target has no cache, use BUS mode to access memory. */ if ((memory->dcache.line_size == 0) || (memory->dcache.enable == false)) { /* There is no Dcache or Dcache is disabled. */ memory->access_channel = NDS_MEMORY_ACC_BUS; aice_memory_access(aice, NDS_MEMORY_ACC_BUS); } int result; result = nds32_gdb_fileio_write_memory(nds32, address, size, buffer); if (NDS_MEMORY_ACC_CPU == origin_access_channel) { memory->access_channel = NDS_MEMORY_ACC_CPU; aice_memory_access(aice, NDS_MEMORY_ACC_CPU); } return result; } return nds32_write_buffer(target, address, size, buffer); } int nds32_v3_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ /* When DEX is set to one, hardware will enforce the following behavior without * modifying the corresponding control bits in PSW. * * Disable all interrupts * Become superuser mode * Turn off IT/DT * Use MMU_CFG.DE as the data access endian * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted * Disable audio special features * Disable inline function call * * Because hardware will turn off IT/DT by default, it MUST translate virtual address * to physical address. */ if (ERROR_OK == target->type->virt2phys(target, address, &physical_address)) address = physical_address; else return ERROR_FAIL; struct aice_port_s *aice = target_to_aice(target); /* give arbitrary initial value to avoid warning messages */ enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU; int result; if (nds32->hit_syscall) { /* Use bus mode to access memory during virtual hosting */ origin_access_channel = memory->access_channel; memory->access_channel = NDS_MEMORY_ACC_BUS; aice_memory_access(aice, NDS_MEMORY_ACC_BUS); } result = nds32_read_memory(target, address, size, count, buffer); if (nds32->hit_syscall) { /* Restore access_channel after virtual hosting */ memory->access_channel = origin_access_channel; aice_memory_access(aice, origin_access_channel); } return result; } int nds32_v3_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } uint32_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ /* When DEX is set to one, hardware will enforce the following behavior without * modifying the corresponding control bits in PSW. * * Disable all interrupts * Become superuser mode * Turn off IT/DT * Use MMU_CFG.DE as the data access endian * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted * Disable audio special features * Disable inline function call * * Because hardware will turn off IT/DT by default, it MUST translate virtual address * to physical address. */ if (ERROR_OK == target->type->virt2phys(target, address, &physical_address)) address = physical_address; else return ERROR_FAIL; return nds32_write_memory(target, address, size, count, buffer); } int nds32_v3_init_target(struct command_context *cmd_ctx, struct target *target) { /* Initialize anything we can set up without talking to the target */ struct nds32 *nds32 = target_to_nds32(target); nds32_init(nds32); target->fileio_info = malloc(sizeof(struct gdb_fileio_info)); target->fileio_info->identifier = NULL; return ERROR_OK; } openocd-0.9.0/src/target/nds32_v3_common.h0000644000175000017500000000620312315575361015240 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_V3_COMMON_H__ #define __NDS32_V3_COMMON_H__ #include "target.h" struct nds32_v3_common_callback { int (*check_interrupt_stack)(struct nds32 *nds32); int (*restore_interrupt_stack)(struct nds32 *nds32); int (*activate_hardware_breakpoint)(struct target *target); int (*activate_hardware_watchpoint)(struct target *target); int (*deactivate_hardware_breakpoint)(struct target *target); int (*deactivate_hardware_watchpoint)(struct target *target); }; void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback); int nds32_v3_target_request_data(struct target *target, uint32_t size, uint8_t *buffer); int nds32_v3_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int nds32_v3_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint); int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32); int nds32_v3_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); int nds32_v3_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer); int nds32_v3_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer); int nds32_v3_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int nds32_v3_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int nds32_v3_init_target(struct command_context *cmd_ctx, struct target *target); #endif /* __NDS32_V3_COMMON_H__ */ openocd-0.9.0/src/target/arm_adi_v5.c0000644000175000017500000014145112516456303014332 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009-2010 by Oyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009-2010 by David Brownell * * * * Copyright (C) 2013 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * This file implements support for the ARM Debug Interface version 5 (ADIv5) * debugging architecture. Compared with previous versions, this includes * a low pin-count Serial Wire Debug (SWD) alternative to JTAG for message * transport, and focusses on memory mapped resources as defined by the * CoreSight architecture. * * A key concept in ADIv5 is the Debug Access Port, or DAP. A DAP has two * basic components: a Debug Port (DP) transporting messages to and from a * debugger, and an Access Port (AP) accessing resources. Three types of DP * are defined. One uses only JTAG for communication, and is called JTAG-DP. * One uses only SWD for communication, and is called SW-DP. The third can * use either SWD or JTAG, and is called SWJ-DP. The most common type of AP * is used to access memory mapped resources and is called a MEM-AP. Also a * JTAG-AP is also defined, bridging to JTAG resources; those are uncommon. * * This programming interface allows DAP pipelined operations through a * transaction queue. This primarily affects AP operations (such as using * a MEM-AP to access memory or registers). If the current transaction has * not finished by the time the next one must begin, and the ORUNDETECT bit * is set in the DP_CTRL_STAT register, the SSTICKYORUN status is set and * further AP operations will fail. There are two basic methods to avoid * such overrun errors. One involves polling for status instead of using * transaction piplining. The other involves adding delays to ensure the * AP has enough time to complete one operation before starting the next * one. (For JTAG these delays are controlled by memaccess_tck.) */ /* * Relevant specifications from ARM include: * * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031A * CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B * * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D * Cortex-M3(tm) TRM, ARM DDI 0337G */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/interface.h" #include "arm.h" #include "arm_adi_v5.h" #include /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ /* uint32_t tar_block_size(uint32_t address) Return the largest block starting at address that does not cross a tar block size alignment boundary */ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address) { return tar_autoincr_block - ((tar_autoincr_block - 1) & address); } /*************************************************************************** * * * DP and MEM-AP register access through APACC and DPACC * * * ***************************************************************************/ /** * Select one of the APs connected to the specified DAP. The * selection is implicitly used with future AP transactions. * This is a NOP if the specified AP is already selected. * * @param dap The DAP * @param apsel Number of the AP to (implicitly) use with further * transactions. This normally identifies a MEM-AP. */ void dap_ap_select(struct adiv5_dap *dap, uint8_t ap) { uint32_t new_ap = (ap << 24) & 0xFF000000; if (new_ap != dap->ap_current) { dap->ap_current = new_ap; /* Switching AP invalidates cached values. * Values MUST BE UPDATED BEFORE AP ACCESS. */ dap->ap_bank_value = -1; dap->ap_csw_value = -1; dap->ap_tar_value = -1; } } static int dap_setup_accessport_csw(struct adiv5_dap *dap, uint32_t csw) { csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT | dap->apcsw[dap->ap_current >> 24]; if (csw != dap->ap_csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ int retval = dap_queue_ap_write(dap, AP_REG_CSW, csw); if (retval != ERROR_OK) return retval; dap->ap_csw_value = csw; } return ERROR_OK; } static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) { if (tar != dap->ap_tar_value || dap->ap_csw_value & CSW_ADDRINC_MASK) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ int retval = dap_queue_ap_write(dap, AP_REG_TAR, tar); if (retval != ERROR_OK) return retval; dap->ap_tar_value = tar; } return ERROR_OK; } /** * Queue transactions setting up transfer parameters for the * currently selected MEM-AP. * * Subsequent transfers using registers like AP_REG_DRW or AP_REG_BD2 * initiate data reads or writes using memory or peripheral addresses. * If the CSW is configured for it, the TAR may be automatically * incremented after each transfer. * * @todo Rename to reflect it being specifically a MEM-AP function. * * @param dap The DAP connected to the MEM-AP. * @param csw MEM-AP Control/Status Word (CSW) register to assign. If this * matches the cached value, the register is not changed. * @param tar MEM-AP Transfer Address Register (TAR) to assign. If this * matches the cached address, the register is not changed. * * @return ERROR_OK if the transaction was properly queued, else a fault code. */ int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar) { int retval; retval = dap_setup_accessport_csw(dap, csw); if (retval != ERROR_OK) return retval; retval = dap_setup_accessport_tar(dap, tar); if (retval != ERROR_OK) return retval; return ERROR_OK; } /** * Asynchronous (queued) read of a word from memory or a system register. * * @param dap The DAP connected to the MEM-AP performing the read. * @param address Address of the 32-bit word to read; it must be * readable by the currently selected MEM-AP. * @param value points to where the word will be stored when the * transaction queue is flushed (assuming no errors). * * @return ERROR_OK for success. Otherwise a fault code. */ int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, uint32_t *value) { int retval; /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when reading several consecutive addresses. */ retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); if (retval != ERROR_OK) return retval; return dap_queue_ap_read(dap, AP_REG_BD0 | (address & 0xC), value); } /** * Synchronous read of a word from memory or a system register. * As a side effect, this flushes any queued transactions. * * @param dap The DAP connected to the MEM-AP performing the read. * @param address Address of the 32-bit word to read; it must be * readable by the currently selected MEM-AP. * @param value points to where the result will be stored. * * @return ERROR_OK for success; *value holds the result. * Otherwise a fault code. */ int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, uint32_t *value) { int retval; retval = mem_ap_read_u32(dap, address, value); if (retval != ERROR_OK) return retval; return dap_run(dap); } /** * Asynchronous (queued) write of a word to memory or a system register. * * @param dap The DAP connected to the MEM-AP. * @param address Address to be written; it must be writable by * the currently selected MEM-AP. * @param value Word that will be written to the address when transaction * queue is flushed (assuming no errors). * * @return ERROR_OK for success. Otherwise a fault code. */ int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, uint32_t value) { int retval; /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when writing several consecutive addresses. */ retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); if (retval != ERROR_OK) return retval; return dap_queue_ap_write(dap, AP_REG_BD0 | (address & 0xC), value); } /** * Synchronous write of a word to memory or a system register. * As a side effect, this flushes any queued transactions. * * @param dap The DAP connected to the MEM-AP. * @param address Address to be written; it must be writable by * the currently selected MEM-AP. * @param value Word that will be written. * * @return ERROR_OK for success; the data was written. Otherwise a fault code. */ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, uint32_t value) { int retval = mem_ap_write_u32(dap, address, value); if (retval != ERROR_OK) return retval; return dap_run(dap); } /** * Synchronous write of a block of memory, using a specific access size. * * @param dap The DAP connected to the MEM-AP. * @param buffer The data buffer to write. No particular alignment is assumed. * @param size Which access size to use, in bytes. 1, 2 or 4. * @param count The number of writes to do (in size units, not bytes). * @param address Address to be written; it must be writable by the currently selected MEM-AP. * @param addrinc Whether the target address should be increased for each write or not. This * should normally be true, except when writing to e.g. a FIFO. * @return ERROR_OK on success, otherwise an error code. */ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address, bool addrinc) { size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; uint32_t addr_xor; int retval; /* TI BE-32 Quirks mode: * Writes on big-endian TMS570 behave very strangely. Observed behavior: * size write address bytes written in order * 4 TAR ^ 0 (val >> 24), (val >> 16), (val >> 8), (val) * 2 TAR ^ 2 (val >> 8), (val) * 1 TAR ^ 3 (val) * For example, if you attempt to write a single byte to address 0, the processor * will actually write a byte to address 3. * * To make writes of size < 4 work as expected, we xor a value with the address before * setting the TAP, and we set the TAP after every transfer rather then relying on * address increment. */ if (size == 4) { csw_size = CSW_32BIT; addr_xor = 0; } else if (size == 2) { csw_size = CSW_16BIT; addr_xor = dap->ti_be_32_quirks ? 2 : 0; } else if (size == 1) { csw_size = CSW_8BIT; addr_xor = dap->ti_be_32_quirks ? 3 : 0; } else { return ERROR_TARGET_UNALIGNED_ACCESS; } if (dap->unaligned_access_bad && (address % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; retval = dap_setup_accessport_tar(dap, address ^ addr_xor); if (retval != ERROR_OK) return retval; while (nbytes > 0) { uint32_t this_size = size; /* Select packed transfer if possible */ if (addrinc && dap->packed_transfers && nbytes >= 4 && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); } else { retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr); } if (retval != ERROR_OK) break; /* How many source bytes each transfer will consume, and their location in the DRW, * depends on the type of transfer and alignment. See ARM document IHI0031C. */ uint32_t outvalue = 0; if (dap->ti_be_32_quirks) { switch (this_size) { case 4: outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); break; case 2: outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor); outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor); break; case 1: outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (address++ & 3) ^ addr_xor); break; } } else { switch (this_size) { case 4: outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); case 2: outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); case 1: outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); } } nbytes -= this_size; retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue); if (retval != ERROR_OK) break; /* Rewrite TAR if it wrapped or we're xoring addresses */ if (addrinc && (addr_xor || (address % dap->tar_autoincr_block < size && nbytes > 0))) { retval = dap_setup_accessport_tar(dap, address ^ addr_xor); if (retval != ERROR_OK) break; } } /* REVISIT: Might want to have a queued version of this function that does not run. */ if (retval == ERROR_OK) retval = dap_run(dap); if (retval != ERROR_OK) { uint32_t tar; if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar); else LOG_ERROR("Failed to write memory and, additionally, failed to find out where"); } return retval; } /** * Synchronous read of a block of memory, using a specific access size. * * @param dap The DAP connected to the MEM-AP. * @param buffer The data buffer to receive the data. No particular alignment is assumed. * @param size Which access size to use, in bytes. 1, 2 or 4. * @param count The number of reads to do (in size units, not bytes). * @param address Address to be read; it must be readable by the currently selected MEM-AP. * @param addrinc Whether the target address should be increased after each read or not. This * should normally be true, except when reading from e.g. a FIFO. * @return ERROR_OK on success, otherwise an error code. */ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t adr, bool addrinc) { size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; uint32_t address = adr; int retval; /* TI BE-32 Quirks mode: * Reads on big-endian TMS570 behave strangely differently than writes. * They read from the physical address requested, but with DRW byte-reversed. * For example, a byte read from address 0 will place the result in the high bytes of DRW. * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes, * so avoid them. */ if (size == 4) csw_size = CSW_32BIT; else if (size == 2) csw_size = CSW_16BIT; else if (size == 1) csw_size = CSW_8BIT; else return ERROR_TARGET_UNALIGNED_ACCESS; if (dap->unaligned_access_bad && (adr % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant * over-allocation if packed transfers are going to be used, but determining the real need at * this point would be messy. */ uint32_t *read_buf = malloc(count * sizeof(uint32_t)); uint32_t *read_ptr = read_buf; if (read_buf == NULL) { LOG_ERROR("Failed to allocate read buffer"); return ERROR_FAIL; } retval = dap_setup_accessport_tar(dap, address); if (retval != ERROR_OK) { free(read_buf); return retval; } /* Queue up all reads. Each read will store the entire DRW word in the read buffer. How many * useful bytes it contains, and their location in the word, depends on the type of transfer * and alignment. */ while (nbytes > 0) { uint32_t this_size = size; /* Select packed transfer if possible */ if (addrinc && dap->packed_transfers && nbytes >= 4 && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); } else { retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr); } if (retval != ERROR_OK) break; retval = dap_queue_ap_read(dap, AP_REG_DRW, read_ptr++); if (retval != ERROR_OK) break; nbytes -= this_size; address += this_size; /* Rewrite TAR if it wrapped */ if (addrinc && address % dap->tar_autoincr_block < size && nbytes > 0) { retval = dap_setup_accessport_tar(dap, address); if (retval != ERROR_OK) break; } } if (retval == ERROR_OK) retval = dap_run(dap); /* Restore state */ address = adr; nbytes = size * count; read_ptr = read_buf; /* If something failed, read TAR to find out how much data was successfully read, so we can * at least give the caller what we have. */ if (retval != ERROR_OK) { uint32_t tar; if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) { LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar); if (nbytes > tar - address) nbytes = tar - address; } else { LOG_ERROR("Failed to read memory and, additionally, failed to find out where"); nbytes = 0; } } /* Replay loop to populate caller's buffer from the correct word and byte lane */ while (nbytes > 0) { uint32_t this_size = size; if (addrinc && dap->packed_transfers && nbytes >= 4 && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { this_size = 4; } if (dap->ti_be_32_quirks) { switch (this_size) { case 4: *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); case 2: *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); case 1: *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); } } else { switch (this_size) { case 4: *buffer++ = *read_ptr >> 8 * (address++ & 3); *buffer++ = *read_ptr >> 8 * (address++ & 3); case 2: *buffer++ = *read_ptr >> 8 * (address++ & 3); case 1: *buffer++ = *read_ptr >> 8 * (address++ & 3); } } read_ptr++; nbytes -= this_size; } free(read_buf); return retval; } /*--------------------------------------------------------------------*/ /* Wrapping function with selection of AP */ /*--------------------------------------------------------------------*/ int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t *value) { dap_ap_select(swjdp, ap); return mem_ap_read_u32(swjdp, address, value); } int mem_ap_sel_write_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t value) { dap_ap_select(swjdp, ap); return mem_ap_write_u32(swjdp, address, value); } int mem_ap_sel_read_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t *value) { dap_ap_select(swjdp, ap); return mem_ap_read_atomic_u32(swjdp, address, value); } int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t value) { dap_ap_select(swjdp, ap); return mem_ap_write_atomic_u32(swjdp, address, value); } int mem_ap_sel_read_buf(struct adiv5_dap *swjdp, uint8_t ap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) { dap_ap_select(swjdp, ap); return mem_ap_read(swjdp, buffer, size, count, address, true); } int mem_ap_sel_write_buf(struct adiv5_dap *swjdp, uint8_t ap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) { dap_ap_select(swjdp, ap); return mem_ap_write(swjdp, buffer, size, count, address, true); } int mem_ap_sel_read_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) { dap_ap_select(swjdp, ap); return mem_ap_read(swjdp, buffer, size, count, address, false); } int mem_ap_sel_write_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) { dap_ap_select(swjdp, ap); return mem_ap_write(swjdp, buffer, size, count, address, false); } /*--------------------------------------------------------------------------*/ #define DAP_POWER_DOMAIN_TIMEOUT (10) /* FIXME don't import ... just initialize as * part of DAP transport setup */ extern const struct dap_ops jtag_dp_ops; /*--------------------------------------------------------------------------*/ /** * Initialize a DAP. This sets up the power domains, prepares the DP * for further use, and arranges to use AP #0 for all AP operations * until dap_ap-select() changes that policy. * * @param dap The DAP being initialized. * * @todo Rename this. We also need an initialization scheme which account * for SWD transports not just JTAG; that will need to address differences * in layering. (JTAG is useful without any debug target; but not SWD.) * And this may not even use an AHB-AP ... e.g. DAP-Lite uses an APB-AP. */ int ahbap_debugport_init(struct adiv5_dap *dap) { /* check that we support packed transfers */ uint32_t csw, cfg; int retval; LOG_DEBUG(" "); /* JTAG-DP or SWJ-DP, in JTAG mode * ... for SWD mode this is patched as part * of link switchover */ if (!dap->ops) dap->ops = &jtag_dp_ops; /* Default MEM-AP setup. * * REVISIT AP #0 may be an inappropriate default for this. * Should we probe, or take a hint from the caller? * Presumably we can ignore the possibility of multiple APs. */ dap->ap_current = !0; dap_ap_select(dap, 0); dap->last_read = NULL; for (size_t i = 0; i < 10; i++) { /* DP initialization */ dap->dp_bank_value = 0; retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); if (retval != ERROR_OK) continue; retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); if (retval != ERROR_OK) continue; retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); if (retval != ERROR_OK) continue; dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); if (retval != ERROR_OK) continue; /* Check that we have debug power domains activated */ LOG_DEBUG("DAP: wait CDBGPWRUPACK"); retval = dap_dp_poll_register(dap, DP_CTRL_STAT, CDBGPWRUPACK, CDBGPWRUPACK, DAP_POWER_DOMAIN_TIMEOUT); if (retval != ERROR_OK) continue; LOG_DEBUG("DAP: wait CSYSPWRUPACK"); retval = dap_dp_poll_register(dap, DP_CTRL_STAT, CSYSPWRUPACK, CSYSPWRUPACK, DAP_POWER_DOMAIN_TIMEOUT); if (retval != ERROR_OK) continue; retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); if (retval != ERROR_OK) continue; /* With debug power on we can activate OVERRUN checking */ dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); if (retval != ERROR_OK) continue; retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); if (retval != ERROR_OK) continue; retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); if (retval != ERROR_OK) continue; retval = dap_queue_ap_read(dap, AP_REG_CSW, &csw); if (retval != ERROR_OK) continue; retval = dap_queue_ap_read(dap, AP_REG_CFG, &cfg); if (retval != ERROR_OK) continue; retval = dap_run(dap); if (retval != ERROR_OK) continue; break; } if (retval != ERROR_OK) return retval; if (csw & CSW_ADDRINC_PACKED) dap->packed_transfers = true; else dap->packed_transfers = false; /* Packed transfers on TI BE-32 processors do not work correctly in * many cases. */ if (dap->ti_be_32_quirks) dap->packed_transfers = false; LOG_DEBUG("MEM_AP Packed Transfers: %s", dap->packed_transfers ? "enabled" : "disabled"); /* The ARM ADI spec leaves implementation-defined whether unaligned * memory accesses work, only work partially, or cause a sticky error. * On TI BE-32 processors, reads seem to return garbage in some bytes * and unaligned writes seem to cause a sticky error. * TODO: it would be nice to have a way to detect whether unaligned * operations are supported on other processors. */ dap->unaligned_access_bad = dap->ti_be_32_quirks; LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d", !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01)); return ERROR_OK; } /* CID interpretation -- see ARM IHI 0029B section 3 * and ARM IHI 0031A table 13-3. */ static const char *class_description[16] = { "Reserved", "ROM table", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "CoreSight component", "Reserved", "Peripheral Test Block", "Reserved", "OptimoDE DESS", "Generic IP component", "PrimeCell or System component" }; static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0) { return cid3 == 0xb1 && cid2 == 0x05 && ((cid1 & 0x0f) == 0) && cid0 == 0x0d; } /* * This function checks the ID for each access port to find the requested Access Port type */ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_num_out) { int ap; /* Maximum AP number is 255 since the SELECT register is 8 bits */ for (ap = 0; ap <= 255; ap++) { /* read the IDR register of the Access Port */ uint32_t id_val = 0; dap_ap_select(dap, ap); int retval = dap_queue_ap_read(dap, AP_REG_IDR, &id_val); if (retval != ERROR_OK) return retval; retval = dap_run(dap); /* IDR bits: * 31-28 : Revision * 27-24 : JEDEC bank (0x4 for ARM) * 23-17 : JEDEC code (0x3B for ARM) * 16 : Mem-AP * 15-8 : Reserved * 7-0 : AP Identity (1=AHB-AP 2=APB-AP 0x10=JTAG-AP) */ /* Reading register for a non-existant AP should not cause an error, * but just to be sure, try to continue searching if an error does happen. */ if ((retval == ERROR_OK) && /* Register read success */ ((id_val & 0x0FFF0000) == 0x04770000) && /* Jedec codes match */ ((id_val & 0xFF) == type_to_find)) { /* type matches*/ LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")", (type_to_find == AP_TYPE_AHB_AP) ? "AHB-AP" : (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" : (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown", ap, id_val); *ap_num_out = ap; return ERROR_OK; } } LOG_DEBUG("No %s found", (type_to_find == AP_TYPE_AHB_AP) ? "AHB-AP" : (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" : (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown"); return ERROR_FAIL; } int dap_get_debugbase(struct adiv5_dap *dap, int ap, uint32_t *dbgbase, uint32_t *apid) { uint32_t ap_old; int retval; /* AP address is in bits 31:24 of DP_SELECT */ if (ap >= 256) return ERROR_COMMAND_SYNTAX_ERROR; ap_old = dap->ap_current; dap_ap_select(dap, ap); retval = dap_queue_ap_read(dap, AP_REG_BASE, dbgbase); if (retval != ERROR_OK) return retval; retval = dap_queue_ap_read(dap, AP_REG_IDR, apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; dap_ap_select(dap, ap_old); return ERROR_OK; } int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx) { uint32_t ap_old; uint32_t romentry, entry_offset = 0, component_base, devtype; int retval; if (ap >= 256) return ERROR_COMMAND_SYNTAX_ERROR; *addr = 0; ap_old = dap->ap_current; dap_ap_select(dap, ap); do { retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); if (retval != ERROR_OK) return retval; component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000); if (romentry & 0x1) { uint32_t c_cid1; retval = mem_ap_read_atomic_u32(dap, component_base | 0xff4, &c_cid1); if (retval != ERROR_OK) { LOG_ERROR("Can't read component with base address 0x%" PRIx32 ", the corresponding core might be turned off", component_base); return retval; } if (((c_cid1 >> 4) & 0x0f) == 1) { retval = dap_lookup_cs_component(dap, ap, component_base, type, addr, idx); if (retval == ERROR_OK) break; if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) return retval; } retval = mem_ap_read_atomic_u32(dap, (component_base & 0xfffff000) | 0xfcc, &devtype); if (retval != ERROR_OK) return retval; if ((devtype & 0xff) == type) { if (!*idx) { *addr = component_base; break; } else (*idx)--; } } entry_offset += 4; } while (romentry > 0); dap_ap_select(dap, ap_old); if (!*addr) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_OK; } static int dap_rom_display(struct command_context *cmd_ctx, struct adiv5_dap *dap, int ap, uint32_t dbgbase, int depth) { int retval; uint32_t cid0, cid1, cid2, cid3, memtype, romentry; uint16_t entry_offset; char tabs[7] = ""; if (depth > 16) { command_print(cmd_ctx, "\tTables too deep"); return ERROR_FAIL; } if (depth) snprintf(tabs, sizeof(tabs), "[L%02d] ", depth); /* bit 16 of apid indicates a memory access port */ if (dbgbase & 0x02) command_print(cmd_ctx, "\t%sValid ROM table present", tabs); else command_print(cmd_ctx, "\t%sROM table in legacy format", tabs); /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) command_print(cmd_ctx, "\t%sCID3 0x%02x" ", CID2 0x%02x" ", CID1 0x%02x" ", CID0 0x%02x", tabs, (unsigned)cid3, (unsigned)cid2, (unsigned)cid1, (unsigned)cid0); if (memtype & 0x01) command_print(cmd_ctx, "\t%sMEMTYPE system memory present on bus", tabs); else command_print(cmd_ctx, "\t%sMEMTYPE system memory not present: dedicated debug bus", tabs); /* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */ for (entry_offset = 0; ; entry_offset += 4) { retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); if (retval != ERROR_OK) return retval; command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", tabs, entry_offset, romentry); if (romentry & 0x01) { uint32_t c_cid0, c_cid1, c_cid2, c_cid3; uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4; uint32_t component_base; uint32_t part_num; const char *type, *full; component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000); /* IDs are in last 4K section */ retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE0, &c_pid0); if (retval != ERROR_OK) { command_print(cmd_ctx, "\t%s\tCan't read component with base address 0x%" PRIx32 ", the corresponding core might be turned off", tabs, component_base); continue; } c_pid0 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE4, &c_pid1); if (retval != ERROR_OK) return retval; c_pid1 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE8, &c_pid2); if (retval != ERROR_OK) return retval; c_pid2 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFEC, &c_pid3); if (retval != ERROR_OK) return retval; c_pid3 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFD0, &c_pid4); if (retval != ERROR_OK) return retval; c_pid4 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF0, &c_cid0); if (retval != ERROR_OK) return retval; c_cid0 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF4, &c_cid1); if (retval != ERROR_OK) return retval; c_cid1 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF8, &c_cid2); if (retval != ERROR_OK) return retval; c_cid2 &= 0xff; retval = mem_ap_read_atomic_u32(dap, component_base + 0xFFC, &c_cid3); if (retval != ERROR_OK) return retval; c_cid3 &= 0xff; command_print(cmd_ctx, "\t\tComponent base address 0x%" PRIx32 ", " "start address 0x%" PRIx32, component_base, /* component may take multiple 4K pages */ (uint32_t)(component_base - 0x1000*(c_pid4 >> 4))); command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", (uint8_t)((c_cid1 >> 4) & 0xf), /* See ARM IHI 0029B Table 3-3 */ class_description[(c_cid1 >> 4) & 0xf]); /* CoreSight component? */ if (((c_cid1 >> 4) & 0x0f) == 9) { uint32_t devtype; unsigned minor; const char *major = "Reserved", *subtype = "Reserved"; retval = mem_ap_read_atomic_u32(dap, (component_base & 0xfffff000) | 0xfcc, &devtype); if (retval != ERROR_OK) return retval; minor = (devtype >> 4) & 0x0f; switch (devtype & 0x0f) { case 0: major = "Miscellaneous"; switch (minor) { case 0: subtype = "other"; break; case 4: subtype = "Validation component"; break; } break; case 1: major = "Trace Sink"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Port"; break; case 2: subtype = "Buffer"; break; case 3: subtype = "Router"; break; } break; case 2: major = "Trace Link"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Funnel, router"; break; case 2: subtype = "Filter"; break; case 3: subtype = "FIFO, buffer"; break; } break; case 3: major = "Trace Source"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Processor"; break; case 2: subtype = "DSP"; break; case 3: subtype = "Engine/Coprocessor"; break; case 4: subtype = "Bus"; break; case 6: subtype = "Software"; break; } break; case 4: major = "Debug Control"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Trigger Matrix"; break; case 2: subtype = "Debug Auth"; break; case 3: subtype = "Power Requestor"; break; } break; case 5: major = "Debug Logic"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Processor"; break; case 2: subtype = "DSP"; break; case 3: subtype = "Engine/Coprocessor"; break; case 4: subtype = "Bus"; break; case 5: subtype = "Memory"; break; } break; case 6: major = "Perfomance Monitor"; switch (minor) { case 0: subtype = "other"; break; case 1: subtype = "Processor"; break; case 2: subtype = "DSP"; break; case 3: subtype = "Engine/Coprocessor"; break; case 4: subtype = "Bus"; break; case 5: subtype = "Memory"; break; } break; } command_print(cmd_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s", (uint8_t)(devtype & 0xff), major, subtype); /* REVISIT also show 0xfc8 DevId */ } if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) command_print(cmd_ctx, "\t\tCID3 0%02x" ", CID2 0%02x" ", CID1 0%02x" ", CID0 0%02x", (int)c_cid3, (int)c_cid2, (int)c_cid1, (int)c_cid0); command_print(cmd_ctx, "\t\tPeripheral ID[4..0] = hex " "%02x %02x %02x %02x %02x", (int)c_pid4, (int)c_pid3, (int)c_pid2, (int)c_pid1, (int)c_pid0); /* Part number interpretations are from Cortex * core specs, the CoreSight components TRM * (ARM DDI 0314H), CoreSight System Design * Guide (ARM DGI 0012D) and ETM specs; also * from chip observation (e.g. TI SDTI). */ part_num = (c_pid0 & 0xff); part_num |= (c_pid1 & 0x0f) << 8; switch (part_num) { case 0x000: type = "Cortex-M3 NVIC"; full = "(Interrupt Controller)"; break; case 0x001: type = "Cortex-M3 ITM"; full = "(Instrumentation Trace Module)"; break; case 0x002: type = "Cortex-M3 DWT"; full = "(Data Watchpoint and Trace)"; break; case 0x003: type = "Cortex-M3 FBP"; full = "(Flash Patch and Breakpoint)"; break; case 0x008: type = "Cortex-M0 SCS"; full = "(System Control Space)"; break; case 0x00a: type = "Cortex-M0 DWT"; full = "(Data Watchpoint and Trace)"; break; case 0x00b: type = "Cortex-M0 BPU"; full = "(Breakpoint Unit)"; break; case 0x00c: type = "Cortex-M4 SCS"; full = "(System Control Space)"; break; case 0x00d: type = "CoreSight ETM11"; full = "(Embedded Trace)"; break; /* case 0x113: what? */ case 0x120: /* from OMAP3 memmap */ type = "TI SDTI"; full = "(System Debug Trace Interface)"; break; case 0x343: /* from OMAP3 memmap */ type = "TI DAPCTL"; full = ""; break; case 0x906: type = "Coresight CTI"; full = "(Cross Trigger)"; break; case 0x907: type = "Coresight ETB"; full = "(Trace Buffer)"; break; case 0x908: type = "Coresight CSTF"; full = "(Trace Funnel)"; break; case 0x910: type = "CoreSight ETM9"; full = "(Embedded Trace)"; break; case 0x912: type = "Coresight TPIU"; full = "(Trace Port Interface Unit)"; break; case 0x913: type = "Coresight ITM"; full = "(Instrumentation Trace Macrocell)"; break; case 0x914: type = "Coresight SWO"; full = "(Single Wire Output)"; break; case 0x917: type = "Coresight HTM"; full = "(AHB Trace Macrocell)"; break; case 0x920: type = "CoreSight ETM11"; full = "(Embedded Trace)"; break; case 0x921: type = "Cortex-A8 ETM"; full = "(Embedded Trace)"; break; case 0x922: type = "Cortex-A8 CTI"; full = "(Cross Trigger)"; break; case 0x923: type = "Cortex-M3 TPIU"; full = "(Trace Port Interface Unit)"; break; case 0x924: type = "Cortex-M3 ETM"; full = "(Embedded Trace)"; break; case 0x925: type = "Cortex-M4 ETM"; full = "(Embedded Trace)"; break; case 0x930: type = "Cortex-R4 ETM"; full = "(Embedded Trace)"; break; case 0x950: type = "CoreSight Component"; full = "(unidentified Cortex-A9 component)"; break; case 0x961: type = "CoreSight TMC"; full = "(Trace Memory Controller)"; break; case 0x962: type = "CoreSight STM"; full = "(System Trace Macrocell)"; break; case 0x9a0: type = "CoreSight PMU"; full = "(Performance Monitoring Unit)"; break; case 0x9a1: type = "Cortex-M4 TPUI"; full = "(Trace Port Interface Unit)"; break; case 0x9a5: type = "Cortex-A5 ETM"; full = "(Embedded Trace)"; break; case 0xc05: type = "Cortex-A5 Debug"; full = "(Debug Unit)"; break; case 0xc08: type = "Cortex-A8 Debug"; full = "(Debug Unit)"; break; case 0xc09: type = "Cortex-A9 Debug"; full = "(Debug Unit)"; break; case 0x4af: type = "Cortex-A15 Debug"; full = "(Debug Unit)"; break; default: LOG_DEBUG("Unrecognized Part number 0x%" PRIx32, part_num); type = "-*- unrecognized -*-"; full = ""; break; } command_print(cmd_ctx, "\t\tPart is %s %s", type, full); /* ROM Table? */ if (((c_cid1 >> 4) & 0x0f) == 1) { retval = dap_rom_display(cmd_ctx, dap, ap, component_base, depth + 1); if (retval != ERROR_OK) return retval; } } else { if (romentry) command_print(cmd_ctx, "\t\tComponent not present"); else break; } } command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs); return ERROR_OK; } static int dap_info_command(struct command_context *cmd_ctx, struct adiv5_dap *dap, int ap) { int retval; uint32_t dbgbase, apid; int romtable_present = 0; uint8_t mem_ap; uint32_t ap_old; retval = dap_get_debugbase(dap, ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; ap_old = dap->ap_current; dap_ap_select(dap, ap); /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ mem_ap = ((apid&0x10000) && ((apid&0x0F) != 0)); command_print(cmd_ctx, "AP ID register 0x%8.8" PRIx32, apid); if (apid) { switch (apid&0x0F) { case 0: command_print(cmd_ctx, "\tType is JTAG-AP"); break; case 1: command_print(cmd_ctx, "\tType is MEM-AP AHB"); break; case 2: command_print(cmd_ctx, "\tType is MEM-AP APB"); break; default: command_print(cmd_ctx, "\tUnknown AP type"); break; } /* NOTE: a MEM-AP may have a single CoreSight component that's * not a ROM table ... or have no such components at all. */ if (mem_ap) command_print(cmd_ctx, "AP BASE 0x%8.8" PRIx32, dbgbase); } else command_print(cmd_ctx, "No AP found at this ap 0x%x", ap); romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF)); if (romtable_present) dap_rom_display(cmd_ctx, dap, ap, dbgbase, 0); else command_print(cmd_ctx, "\tNo ROM table present"); dap_ap_select(dap, ap_old); return ERROR_OK; } COMMAND_HANDLER(handle_dap_info_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t apsel; switch (CMD_ARGC) { case 0: apsel = dap->apsel; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return dap_info_command(CMD_CTX, dap, apsel); } COMMAND_HANDLER(dap_baseaddr_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t apsel, baseaddr; int retval; switch (CMD_ARGC) { case 0: apsel = dap->apsel; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ if (apsel >= 256) return ERROR_COMMAND_SYNTAX_ERROR; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap_ap_select(dap, apsel); /* NOTE: assumes we're talking to a MEM-AP, which * has a base address. There are other kinds of AP, * though they're not common for now. This should * use the ID register to verify it's a MEM-AP. */ retval = dap_queue_ap_read(dap, AP_REG_BASE, &baseaddr); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "0x%8.8" PRIx32, baseaddr); return retval; } COMMAND_HANDLER(dap_memaccess_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t memaccess_tck; switch (CMD_ARGC) { case 0: memaccess_tck = dap->memaccess_tck; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap->memaccess_tck = memaccess_tck; command_print(CMD_CTX, "memory bus access delay set to %" PRIi32 " tck", dap->memaccess_tck); return ERROR_OK; } COMMAND_HANDLER(dap_apsel_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t apsel, apid; int retval; switch (CMD_ARGC) { case 0: apsel = 0; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ if (apsel >= 256) return ERROR_COMMAND_SYNTAX_ERROR; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap->apsel = apsel; dap_ap_select(dap, apsel); retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "ap %" PRIi32 " selected, identification register 0x%8.8" PRIx32, apsel, apid); return retval; } COMMAND_HANDLER(dap_apcsw_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t apcsw = dap->apcsw[dap->apsel], sprot = 0; switch (CMD_ARGC) { case 0: command_print(CMD_CTX, "apsel %" PRIi32 " selected, csw 0x%8.8" PRIx32, (dap->apsel), apcsw); break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sprot); /* AP address is in bits 31:24 of DP_SELECT */ if (sprot > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (sprot) apcsw |= CSW_SPROT; else apcsw &= ~CSW_SPROT; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap->apcsw[dap->apsel] = apcsw; return 0; } COMMAND_HANDLER(dap_apid_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t apsel, apid; int retval; switch (CMD_ARGC) { case 0: apsel = dap->apsel; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ if (apsel >= 256) return ERROR_COMMAND_SYNTAX_ERROR; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap_ap_select(dap, apsel); retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "0x%8.8" PRIx32, apid); return retval; } COMMAND_HANDLER(dap_ti_be_32_quirks_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t enable = dap->ti_be_32_quirks; switch (CMD_ARGC) { case 0: break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], enable); if (enable > 1) return ERROR_COMMAND_SYNTAX_ERROR; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } dap->ti_be_32_quirks = enable; command_print(CMD_CTX, "TI BE-32 quirks mode %s", enable ? "enabled" : "disabled"); return 0; } static const struct command_registration dap_commands[] = { { .name = "info", .handler = handle_dap_info_command, .mode = COMMAND_EXEC, .help = "display ROM table for MEM-AP " "(default currently selected AP)", .usage = "[ap_num]", }, { .name = "apsel", .handler = dap_apsel_command, .mode = COMMAND_EXEC, .help = "Set the currently selected AP (default 0) " "and display the result", .usage = "[ap_num]", }, { .name = "apcsw", .handler = dap_apcsw_command, .mode = COMMAND_EXEC, .help = "Set csw access bit ", .usage = "[sprot]", }, { .name = "apid", .handler = dap_apid_command, .mode = COMMAND_EXEC, .help = "return ID register from AP " "(default currently selected AP)", .usage = "[ap_num]", }, { .name = "baseaddr", .handler = dap_baseaddr_command, .mode = COMMAND_EXEC, .help = "return debug base address from MEM-AP " "(default currently selected AP)", .usage = "[ap_num]", }, { .name = "memaccess", .handler = dap_memaccess_command, .mode = COMMAND_EXEC, .help = "set/get number of extra tck for MEM-AP memory " "bus access [0-255]", .usage = "[cycles]", }, { .name = "ti_be_32_quirks", .handler = dap_ti_be_32_quirks_command, .mode = COMMAND_CONFIG, .help = "set/get quirks mode for TI TMS450/TMS570 processors", .usage = "[enable]", }, COMMAND_REGISTRATION_DONE }; const struct command_registration dap_command_handlers[] = { { .name = "dap", .mode = COMMAND_EXEC, .help = "DAP command group", .usage = "", .chain = dap_commands, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/arm_adi_v5.h0000644000175000017500000004074712516456303014345 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM_ADI_V5_H #define ARM_ADI_V5_H /** * @file * This defines formats and data structures used to talk to ADIv5 entities. * Those include a DAP, different types of Debug Port (DP), and memory mapped * resources accessed through a MEM-AP. */ #include "arm_jtag.h" /* FIXME remove these JTAG-specific decls when mem_ap_read_buf_u32() * is no longer JTAG-specific */ #define JTAG_DP_DPACC 0xA #define JTAG_DP_APACC 0xB /* three-bit ACK values for SWD access (sent LSB first) */ #define SWD_ACK_OK 0x1 #define SWD_ACK_WAIT 0x2 #define SWD_ACK_FAULT 0x4 #define DPAP_WRITE 0 #define DPAP_READ 1 #define BANK_REG(bank, reg) (((bank) << 4) | (reg)) /* A[3:0] for DP registers; A[1:0] are always zero. * - JTAG accesses all of these via JTAG_DP_DPACC, except for * IDCODE (JTAG_DP_IDCODE) and ABORT (JTAG_DP_ABORT). * - SWD accesses these directly, sometimes needing SELECT.CTRLSEL */ #define DP_IDCODE BANK_REG(0x0, 0x0) /* SWD: read */ #define DP_ABORT BANK_REG(0x0, 0x0) /* SWD: write */ #define DP_CTRL_STAT BANK_REG(0x0, 0x4) /* r/w */ #define DP_RESEND BANK_REG(0x0, 0x8) /* SWD: read */ #define DP_SELECT BANK_REG(0x0, 0x8) /* JTAG: r/w; SWD: write */ #define DP_RDBUFF BANK_REG(0x0, 0xC) /* read-only */ #define DP_WCR BANK_REG(0x1, 0x4) /* SWD: r/w */ #define WCR_TO_TRN(wcr) ((uint32_t)(1 + (3 & ((wcr)) >> 8))) /* 1..4 clocks */ #define WCR_TO_PRESCALE(wcr) ((uint32_t)(7 & ((wcr)))) /* impl defined */ /* Fields of the DP's AP ABORT register */ #define DAPABORT (1UL << 0) #define STKCMPCLR (1UL << 1) /* SWD-only */ #define STKERRCLR (1UL << 2) /* SWD-only */ #define WDERRCLR (1UL << 3) /* SWD-only */ #define ORUNERRCLR (1UL << 4) /* SWD-only */ /* Fields of the DP's CTRL/STAT register */ #define CORUNDETECT (1UL << 0) #define SSTICKYORUN (1UL << 1) /* 3:2 - transaction mode (e.g. pushed compare) */ #define SSTICKYCMP (1UL << 4) #define SSTICKYERR (1UL << 5) #define READOK (1UL << 6) /* SWD-only */ #define WDATAERR (1UL << 7) /* SWD-only */ /* 11:8 - mask lanes for pushed compare or verify ops */ /* 21:12 - transaction counter */ #define CDBGRSTREQ (1UL << 26) #define CDBGRSTACK (1UL << 27) #define CDBGPWRUPREQ (1UL << 28) #define CDBGPWRUPACK (1UL << 29) #define CSYSPWRUPREQ (1UL << 30) #define CSYSPWRUPACK (1UL << 31) /* MEM-AP register addresses */ /* TODO: rename as MEM_AP_REG_* */ #define AP_REG_CSW 0x00 #define AP_REG_TAR 0x04 #define AP_REG_DRW 0x0C #define AP_REG_BD0 0x10 #define AP_REG_BD1 0x14 #define AP_REG_BD2 0x18 #define AP_REG_BD3 0x1C #define AP_REG_CFG 0xF4 /* big endian? */ #define AP_REG_BASE 0xF8 /* Generic AP register address */ #define AP_REG_IDR 0xFC /* Fields of the MEM-AP's CSW register */ #define CSW_8BIT 0 #define CSW_16BIT 1 #define CSW_32BIT 2 #define CSW_ADDRINC_MASK (3UL << 4) #define CSW_ADDRINC_OFF 0UL #define CSW_ADDRINC_SINGLE (1UL << 4) #define CSW_ADDRINC_PACKED (2UL << 4) #define CSW_DEVICE_EN (1UL << 6) #define CSW_TRIN_PROG (1UL << 7) #define CSW_SPIDEN (1UL << 23) /* 30:24 - implementation-defined! */ #define CSW_HPROT (1UL << 25) /* ? */ #define CSW_MASTER_DEBUG (1UL << 29) /* ? */ #define CSW_SPROT (1UL << 30) #define CSW_DBGSWENABLE (1UL << 31) /** * This represents an ARM Debug Interface (v5) Debug Access Port (DAP). * A DAP has two types of component: one Debug Port (DP), which is a * transport agent; and at least one Access Port (AP), controlling * resource access. Most common is a MEM-AP, for memory access. * * There are two basic DP transports: JTAG, and ARM's low pin-count SWD. * Accordingly, this interface is responsible for hiding the transport * differences so upper layer code can largely ignore them. * * When the chip is implemented with JTAG-DP or SW-DP, the transport is * fixed as JTAG or SWD, respectively. Chips incorporating SWJ-DP permit * a choice made at board design time (by only using the SWD pins), or * as part of setting up a debug session (if all the dual-role JTAG/SWD * signals are available). */ struct adiv5_dap { const struct dap_ops *ops; struct arm_jtag *jtag_info; /* Control config */ uint32_t dp_ctrl_stat; uint32_t apcsw[256]; uint32_t apsel; /** * Cache for DP_SELECT bits identifying the current AP. A DAP may * connect to multiple APs, such as one MEM-AP for general access, * another reserved for accessing debug modules, and a JTAG-DP. * "-1" indicates no cached value. */ uint32_t ap_current; /** * Cache for DP_SELECT bits identifying the current four-word AP * register bank. This caches AP register addresss bits 7:4; JTAG * and SWD access primitves pass address bits 3:2; bits 1:0 are zero. * "-1" indicates no cached value. */ uint32_t ap_bank_value; /** * Cache for DP_SELECT bits identifying the current four-word DP * register bank. This caches DP register addresss bits 7:4; JTAG * and SWD access primitves pass address bits 3:2; bits 1:0 are zero. */ uint32_t dp_bank_value; /** * Cache for (MEM-AP) AP_REG_CSW register value. This is written to * configure an access mode, such as autoincrementing AP_REG_TAR during * word access. "-1" indicates no cached value. */ uint32_t ap_csw_value; /** * Cache for (MEM-AP) AP_REG_TAR register value This is written to * configure the address being read or written * "-1" indicates no cached value. */ uint32_t ap_tar_value; /* information about current pending SWjDP-AHBAP transaction */ uint8_t ack; /** * Holds the pointer to the destination word for the last queued read, * for use with posted AP read sequence optimization. */ uint32_t *last_read; /** * Configures how many extra tck clocks are added after starting a * MEM-AP access before we try to read its status (and/or result). */ uint32_t memaccess_tck; /* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */ uint32_t tar_autoincr_block; /* true if packed transfers are supported by the MEM-AP */ bool packed_transfers; /* true if unaligned memory access is not supported by the MEM-AP */ bool unaligned_access_bad; /* The TI TMS470 and TMS570 series processors use a BE-32 memory ordering * despite lack of support in the ARMv7 architecture. Memory access through * the AHB-AP has strange byte ordering these processors, and we need to * swizzle appropriately. */ bool ti_be_32_quirks; /** * Signals that an attempt to reestablish communication afresh * should be performed before the next access. */ bool do_reconnect; }; /** * Transport-neutral representation of queued DAP transactions, supporting * both JTAG and SWD transports. All submitted transactions are logically * queued, until the queue is executed by run(). Some implementations might * execute transactions as soon as they're submitted, but no status is made * available until run(). */ struct dap_ops { /** If the DAP transport isn't SWD, it must be JTAG. Upper level * code may need to care about the difference in some cases. */ bool is_swd; /** DP register read. */ int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg, uint32_t *data); /** DP register write. */ int (*queue_dp_write)(struct adiv5_dap *dap, unsigned reg, uint32_t data); /** AP register read. */ int (*queue_ap_read)(struct adiv5_dap *dap, unsigned reg, uint32_t *data); /** AP register write. */ int (*queue_ap_write)(struct adiv5_dap *dap, unsigned reg, uint32_t data); /** AP operation abort. */ int (*queue_ap_abort)(struct adiv5_dap *dap, uint8_t *ack); /** Executes all queued DAP operations. */ int (*run)(struct adiv5_dap *dap); }; /* * Access Port types */ enum ap_type { AP_TYPE_AHB_AP = 0x01, /* AHB Memory-AP */ AP_TYPE_APB_AP = 0x02, /* APB Memory-AP */ AP_TYPE_JTAG_AP = 0x10 /* JTAG-AP - JTAG master for controlling other JTAG devices */ }; /** * Queue a DP register read. * Note that not all DP registers are readable; also, that JTAG and SWD * have slight differences in DP register support. * * @param dap The DAP used for reading. * @param reg The two-bit number of the DP register being read. * @param data Pointer saying where to store the register's value * (in host endianness). * * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { assert(dap->ops != NULL); return dap->ops->queue_dp_read(dap, reg, data); } /** * Queue a DP register write. * Note that not all DP registers are writable; also, that JTAG and SWD * have slight differences in DP register support. * * @param dap The DAP used for writing. * @param reg The two-bit number of the DP register being written. * @param data Value being written (host endianness) * * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { assert(dap->ops != NULL); return dap->ops->queue_dp_write(dap, reg, data); } /** * Queue an AP register read. * * @param dap The DAP used for reading. * @param reg The number of the AP register being read. * @param data Pointer saying where to store the register's value * (in host endianness). * * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { assert(dap->ops != NULL); return dap->ops->queue_ap_read(dap, reg, data); } /** * Queue an AP register write. * * @param dap The DAP used for writing. * @param reg The number of the AP register being written. * @param data Value being written (host endianness) * * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { assert(dap->ops != NULL); return dap->ops->queue_ap_write(dap, reg, data); } /** * Queue an AP abort operation. The current AP transaction is aborted, * including any update of the transaction counter. The AP is left in * an unknown state (so it must be re-initialized). For use only after * the AP has reported WAIT status for an extended period. * * @param dap The DAP used for writing. * @param ack Pointer to where transaction status will be stored. * * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) { assert(dap->ops != NULL); return dap->ops->queue_ap_abort(dap, ack); } /** * Perform all queued DAP operations, and clear any errors posted in the * CTRL_STAT register when they are done. Note that if more than one AP * operation will be queued, one of the first operations in the queue * should probably enable CORUNDETECT in the CTRL/STAT register. * * @param dap The DAP used. * * @return ERROR_OK for success, else a fault code. */ static inline int dap_run(struct adiv5_dap *dap) { assert(dap->ops != NULL); return dap->ops->run(dap); } static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, uint32_t *value) { int retval; retval = dap_queue_dp_read(dap, reg, value); if (retval != ERROR_OK) return retval; return dap_run(dap); } static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout) { assert(timeout > 0); assert((value & mask) == value); int ret; uint32_t regval; LOG_DEBUG("DAP: poll %x, mask 0x08%" PRIx32 ", value 0x%08" PRIx32, reg, mask, value); do { ret = dap_dp_read_atomic(dap, reg, ®val); if (ret != ERROR_OK) return ret; if ((regval & mask) == value) break; alive_sleep(10); } while (--timeout); if (!timeout) { LOG_DEBUG("DAP: poll %x timeout", reg); return ERROR_FAIL; } else { return ERROR_OK; } } /** Accessor for currently selected DAP-AP number (0..255) */ static inline uint8_t dap_ap_get_select(struct adiv5_dap *swjdp) { return (uint8_t)(swjdp->ap_current >> 24); } /* AP selection applies to future AP transactions */ void dap_ap_select(struct adiv5_dap *dap, uint8_t ap); /* Queued AP transactions */ int dap_setup_accessport(struct adiv5_dap *swjdp, uint32_t csw, uint32_t tar); /* Queued MEM-AP memory mapped single word transfers */ int mem_ap_read_u32(struct adiv5_dap *swjdp, uint32_t address, uint32_t *value); int mem_ap_write_u32(struct adiv5_dap *swjdp, uint32_t address, uint32_t value); /* Synchronous MEM-AP memory mapped single word transfers */ int mem_ap_read_atomic_u32(struct adiv5_dap *swjdp, uint32_t address, uint32_t *value); int mem_ap_write_atomic_u32(struct adiv5_dap *swjdp, uint32_t address, uint32_t value); /* Queued MEM-AP memory mapped single word transfers with selection of ap */ int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t *value); int mem_ap_sel_write_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t value); /* Synchronous MEM-AP memory mapped single word transfers with selection of ap */ int mem_ap_sel_read_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t *value); int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, uint32_t address, uint32_t value); /* Synchronous MEM-AP memory mapped bus block transfers */ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address, bool addrinc); int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address, bool addrinc); /* Synchronous MEM-AP memory mapped bus block transfers with selection of ap */ int mem_ap_sel_read_buf(struct adiv5_dap *swjdp, uint8_t ap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); int mem_ap_sel_write_buf(struct adiv5_dap *swjdp, uint8_t ap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); /* Synchronous, non-incrementing buffer functions for accessing fifos, with * selection of ap */ int mem_ap_sel_read_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); int mem_ap_sel_write_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); /* Initialisation of the debug system, power domains and registers */ int ahbap_debugport_init(struct adiv5_dap *swjdp); /* Probe the AP for ROM Table location */ int dap_get_debugbase(struct adiv5_dap *dap, int ap, uint32_t *dbgbase, uint32_t *apid); /* Probe Access Ports to find a particular type */ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_num_out); /* Lookup CoreSight component */ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx); struct target; /* Put debug link into SWD mode */ int dap_to_swd(struct target *target); /* Put debug link into JTAG mode */ int dap_to_jtag(struct target *target); extern const struct command_registration dap_command_handlers[]; #endif openocd-0.9.0/src/target/dsp563xx.c0000644000175000017500000017463012516456303013735 00000000000000/*************************************************************************** * Copyright (C) 2009-2011 by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "breakpoints.h" #include "target_type.h" #include "algorithm.h" #include "register.h" #include "dsp563xx.h" #include "dsp563xx_once.h" #define ASM_REG_W_R0 0x60F400 #define ASM_REG_W_R1 0x61F400 #define ASM_REG_W_R2 0x62F400 #define ASM_REG_W_R3 0x63F400 #define ASM_REG_W_R4 0x64F400 #define ASM_REG_W_R5 0x65F400 #define ASM_REG_W_R6 0x66F400 #define ASM_REG_W_R7 0x67F400 #define ASM_REG_W_N0 0x70F400 #define ASM_REG_W_N1 0x71F400 #define ASM_REG_W_N2 0x72F400 #define ASM_REG_W_N3 0x73F400 #define ASM_REG_W_N4 0x74F400 #define ASM_REG_W_N5 0x75F400 #define ASM_REG_W_N6 0x76F400 #define ASM_REG_W_N7 0x77F400 #define ASM_REG_W_M0 0x05F420 #define ASM_REG_W_M1 0x05F421 #define ASM_REG_W_M2 0x05F422 #define ASM_REG_W_M3 0x05F423 #define ASM_REG_W_M4 0x05F424 #define ASM_REG_W_M5 0x05F425 #define ASM_REG_W_M6 0x05F426 #define ASM_REG_W_M7 0x05F427 #define ASM_REG_W_X0 0x44F400 #define ASM_REG_W_X1 0x45F400 #define ASM_REG_W_Y0 0x46F400 #define ASM_REG_W_Y1 0x47F400 #define ASM_REG_W_A0 0x50F400 #define ASM_REG_W_A1 0x54F400 #define ASM_REG_W_A2 0x52F400 #define ASM_REG_W_B0 0x51F400 #define ASM_REG_W_B1 0x55F400 #define ASM_REG_W_B2 0x53F400 #define ASM_REG_W_VBA 0x05F430 #define ASM_REG_W_OMR 0x05F43A #define ASM_REG_W_EP 0x05F42A #define ASM_REG_W_SC 0x05F431 #define ASM_REG_W_SZ 0x05F438 #define ASM_REG_W_SR 0x05F439 #define ASM_REG_W_SP 0x05F43B #define ASM_REG_W_SSH 0x05F43C #define ASM_REG_W_SSL 0x05F43D #define ASM_REG_W_LA 0x05F43E #define ASM_REG_W_LC 0x05F43F #define ASM_REG_W_PC 0x000000 #define ASM_REG_W_IPRC 0xFFFFFF #define ASM_REG_W_IPRP 0xFFFFFE #define ASM_REG_W_BCR 0xFFFFFB #define ASM_REG_W_DCR 0xFFFFFA #define ASM_REG_W_AAR0 0xFFFFF9 #define ASM_REG_W_AAR1 0xFFFFF8 #define ASM_REG_W_AAR2 0xFFFFF7 #define ASM_REG_W_AAR3 0xFFFFF6 /* * OBCR Register bit definitions */ #define OBCR_b0_and_b1 ((0x0) << 10) #define OBCR_b0_or_b1 ((0x1) << 10) #define OBCR_b1_after_b0 ((0x2) << 10) #define OBCR_b0_after_b1 ((0x3) << 10) #define OBCR_BP_DISABLED (0x0) #define OBCR_BP_MEM_P (0x1) #define OBCR_BP_MEM_X (0x2) #define OBCR_BP_MEM_Y (0x3) #define OBCR_BP_ON_READ ((0x2) << 0) #define OBCR_BP_ON_WRITE ((0x1) << 0) #define OBCR_BP_CC_NOT_EQUAL ((0x0) << 2) #define OBCR_BP_CC_EQUAL ((0x1) << 2) #define OBCR_BP_CC_LESS_THAN ((0x2) << 2) #define OBCR_BP_CC_GREATER_THAN ((0x3) << 2) #define OBCR_BP_0(x) ((x)<<2) #define OBCR_BP_1(x) ((x)<<6) enum once_reg_idx { ONCE_REG_IDX_OSCR = 0, ONCE_REG_IDX_OMBC = 1, ONCE_REG_IDX_OBCR = 2, ONCE_REG_IDX_OMLR0 = 3, ONCE_REG_IDX_OMLR1 = 4, ONCE_REG_IDX_OGDBR = 5, ONCE_REG_IDX_OPDBR = 6, ONCE_REG_IDX_OPILR = 7, ONCE_REG_IDX_PDB = 8, ONCE_REG_IDX_OTC = 9, ONCE_REG_IDX_OPABFR = 10, ONCE_REG_IDX_OPABDR = 11, ONCE_REG_IDX_OPABEX = 12, ONCE_REG_IDX_OPABF0 = 13, ONCE_REG_IDX_OPABF1 = 14, ONCE_REG_IDX_OPABF2 = 15, ONCE_REG_IDX_OPABF3 = 16, ONCE_REG_IDX_OPABF4 = 17, ONCE_REG_IDX_OPABF5 = 18, ONCE_REG_IDX_OPABF6 = 19, ONCE_REG_IDX_OPABF7 = 20, ONCE_REG_IDX_OPABF8 = 21, ONCE_REG_IDX_OPABF9 = 22, ONCE_REG_IDX_OPABF10 = 23, ONCE_REG_IDX_OPABF11 = 24, }; static struct once_reg once_regs[] = { {ONCE_REG_IDX_OSCR, DSP563XX_ONCE_OSCR, 24, "OSCR", 0}, {ONCE_REG_IDX_OMBC, DSP563XX_ONCE_OMBC, 24, "OMBC", 0}, {ONCE_REG_IDX_OBCR, DSP563XX_ONCE_OBCR, 24, "OBCR", 0}, {ONCE_REG_IDX_OMLR0, DSP563XX_ONCE_OMLR0, 24, "OMLR0", 0}, {ONCE_REG_IDX_OMLR1, DSP563XX_ONCE_OMLR1, 24, "OMLR1", 0}, {ONCE_REG_IDX_OGDBR, DSP563XX_ONCE_OGDBR, 24, "OGDBR", 0}, {ONCE_REG_IDX_OPDBR, DSP563XX_ONCE_OPDBR, 24, "OPDBR", 0}, {ONCE_REG_IDX_OPILR, DSP563XX_ONCE_OPILR, 24, "OPILR", 0}, {ONCE_REG_IDX_PDB, DSP563XX_ONCE_PDBGOTO, 24, "PDB", 0}, {ONCE_REG_IDX_OTC, DSP563XX_ONCE_OTC, 24, "OTC", 0}, {ONCE_REG_IDX_OPABFR, DSP563XX_ONCE_OPABFR, 24, "OPABFR", 0}, {ONCE_REG_IDX_OPABDR, DSP563XX_ONCE_OPABDR, 24, "OPABDR", 0}, {ONCE_REG_IDX_OPABEX, DSP563XX_ONCE_OPABEX, 24, "OPABEX", 0}, {ONCE_REG_IDX_OPABF0, DSP563XX_ONCE_OPABF11, 25, "OPABF0", 0}, {ONCE_REG_IDX_OPABF1, DSP563XX_ONCE_OPABF11, 25, "OPABF1", 0}, {ONCE_REG_IDX_OPABF2, DSP563XX_ONCE_OPABF11, 25, "OPABF2", 0}, {ONCE_REG_IDX_OPABF3, DSP563XX_ONCE_OPABF11, 25, "OPABF3", 0}, {ONCE_REG_IDX_OPABF4, DSP563XX_ONCE_OPABF11, 25, "OPABF4", 0}, {ONCE_REG_IDX_OPABF5, DSP563XX_ONCE_OPABF11, 25, "OPABF5", 0}, {ONCE_REG_IDX_OPABF6, DSP563XX_ONCE_OPABF11, 25, "OPABF6", 0}, {ONCE_REG_IDX_OPABF7, DSP563XX_ONCE_OPABF11, 25, "OPABF7", 0}, {ONCE_REG_IDX_OPABF8, DSP563XX_ONCE_OPABF11, 25, "OPABF8", 0}, {ONCE_REG_IDX_OPABF9, DSP563XX_ONCE_OPABF11, 25, "OPABF9", 0}, {ONCE_REG_IDX_OPABF10, DSP563XX_ONCE_OPABF11, 25, "OPABF10", 0}, {ONCE_REG_IDX_OPABF11, DSP563XX_ONCE_OPABF11, 25, "OPABF11", 0}, /* {25,0x1f,24,"NRSEL",0}, */ }; enum dsp563xx_reg_idx { DSP563XX_REG_IDX_R0 = 0, DSP563XX_REG_IDX_R1 = 1, DSP563XX_REG_IDX_R2 = 2, DSP563XX_REG_IDX_R3 = 3, DSP563XX_REG_IDX_R4 = 4, DSP563XX_REG_IDX_R5 = 5, DSP563XX_REG_IDX_R6 = 6, DSP563XX_REG_IDX_R7 = 7, DSP563XX_REG_IDX_N0 = 8, DSP563XX_REG_IDX_N1 = 9, DSP563XX_REG_IDX_N2 = 10, DSP563XX_REG_IDX_N3 = 11, DSP563XX_REG_IDX_N4 = 12, DSP563XX_REG_IDX_N5 = 13, DSP563XX_REG_IDX_N6 = 14, DSP563XX_REG_IDX_N7 = 15, DSP563XX_REG_IDX_M0 = 16, DSP563XX_REG_IDX_M1 = 17, DSP563XX_REG_IDX_M2 = 18, DSP563XX_REG_IDX_M3 = 19, DSP563XX_REG_IDX_M4 = 20, DSP563XX_REG_IDX_M5 = 21, DSP563XX_REG_IDX_M6 = 22, DSP563XX_REG_IDX_M7 = 23, DSP563XX_REG_IDX_X0 = 24, DSP563XX_REG_IDX_X1 = 25, DSP563XX_REG_IDX_Y0 = 26, DSP563XX_REG_IDX_Y1 = 27, DSP563XX_REG_IDX_A0 = 28, DSP563XX_REG_IDX_A1 = 29, DSP563XX_REG_IDX_A2 = 30, DSP563XX_REG_IDX_B0 = 31, DSP563XX_REG_IDX_B1 = 32, DSP563XX_REG_IDX_B2 = 33, DSP563XX_REG_IDX_SSH = 34, DSP563XX_REG_IDX_SSL = 35, DSP563XX_REG_IDX_SP = 36, DSP563XX_REG_IDX_EP = 37, DSP563XX_REG_IDX_SZ = 38, DSP563XX_REG_IDX_SC = 39, DSP563XX_REG_IDX_PC = 40, DSP563XX_REG_IDX_SR = 41, DSP563XX_REG_IDX_OMR = 42, DSP563XX_REG_IDX_LA = 43, DSP563XX_REG_IDX_LC = 44, DSP563XX_REG_IDX_VBA = 45, DSP563XX_REG_IDX_IPRC = 46, DSP563XX_REG_IDX_IPRP = 47, DSP563XX_REG_IDX_BCR = 48, DSP563XX_REG_IDX_DCR = 49, DSP563XX_REG_IDX_AAR0 = 50, DSP563XX_REG_IDX_AAR1 = 51, DSP563XX_REG_IDX_AAR2 = 52, DSP563XX_REG_IDX_AAR3 = 53, }; static const struct { unsigned id; const char *name; unsigned bits; /* effective addressing mode encoding */ uint8_t eame; uint32_t instr_mask; } dsp563xx_regs[] = { /* *INDENT-OFF* */ /* address registers */ {DSP563XX_REG_IDX_R0, "r0", 24, 0x10, ASM_REG_W_R0}, {DSP563XX_REG_IDX_R1, "r1", 24, 0x11, ASM_REG_W_R1}, {DSP563XX_REG_IDX_R2, "r2", 24, 0x12, ASM_REG_W_R2}, {DSP563XX_REG_IDX_R3, "r3", 24, 0x13, ASM_REG_W_R3}, {DSP563XX_REG_IDX_R4, "r4", 24, 0x14, ASM_REG_W_R4}, {DSP563XX_REG_IDX_R5, "r5", 24, 0x15, ASM_REG_W_R5}, {DSP563XX_REG_IDX_R6, "r6", 24, 0x16, ASM_REG_W_R6}, {DSP563XX_REG_IDX_R7, "r7", 24, 0x17, ASM_REG_W_R7}, /* offset registers */ {DSP563XX_REG_IDX_N0, "n0", 24, 0x18, ASM_REG_W_N0}, {DSP563XX_REG_IDX_N1, "n1", 24, 0x19, ASM_REG_W_N1}, {DSP563XX_REG_IDX_N2, "n2", 24, 0x1a, ASM_REG_W_N2}, {DSP563XX_REG_IDX_N3, "n3", 24, 0x1b, ASM_REG_W_N3}, {DSP563XX_REG_IDX_N4, "n4", 24, 0x1c, ASM_REG_W_N4}, {DSP563XX_REG_IDX_N5, "n5", 24, 0x1d, ASM_REG_W_N5}, {DSP563XX_REG_IDX_N6, "n6", 24, 0x1e, ASM_REG_W_N6}, {DSP563XX_REG_IDX_N7, "n7", 24, 0x1f, ASM_REG_W_N7}, /* modifier registers */ {DSP563XX_REG_IDX_M0, "m0", 24, 0x20, ASM_REG_W_M0}, {DSP563XX_REG_IDX_M1, "m1", 24, 0x21, ASM_REG_W_M1}, {DSP563XX_REG_IDX_M2, "m2", 24, 0x22, ASM_REG_W_M2}, {DSP563XX_REG_IDX_M3, "m3", 24, 0x23, ASM_REG_W_M3}, {DSP563XX_REG_IDX_M4, "m4", 24, 0x24, ASM_REG_W_M4}, {DSP563XX_REG_IDX_M5, "m5", 24, 0x25, ASM_REG_W_M5}, {DSP563XX_REG_IDX_M6, "m6", 24, 0x26, ASM_REG_W_M6}, {DSP563XX_REG_IDX_M7, "m7", 24, 0x27, ASM_REG_W_M7}, /* data alu input register */ {DSP563XX_REG_IDX_X0, "x0", 24, 0x04, ASM_REG_W_X0}, {DSP563XX_REG_IDX_X1, "x1", 24, 0x05, ASM_REG_W_X1}, {DSP563XX_REG_IDX_Y0, "y0", 24, 0x06, ASM_REG_W_Y0}, {DSP563XX_REG_IDX_Y1, "y1", 24, 0x07, ASM_REG_W_Y1}, /* data alu accumulator register */ {DSP563XX_REG_IDX_A0, "a0", 24, 0x08, ASM_REG_W_A0}, {DSP563XX_REG_IDX_A1, "a1", 24, 0x0c, ASM_REG_W_A1}, {DSP563XX_REG_IDX_A2, "a2", 8, 0x0a, ASM_REG_W_A2}, {DSP563XX_REG_IDX_B0, "b0", 24, 0x09, ASM_REG_W_B0}, {DSP563XX_REG_IDX_B1, "b1", 24, 0x0d, ASM_REG_W_B1}, {DSP563XX_REG_IDX_B2, "b2", 8, 0x0b, ASM_REG_W_B2}, /* stack */ {DSP563XX_REG_IDX_SSH, "ssh", 24, 0x3c, ASM_REG_W_SSH}, {DSP563XX_REG_IDX_SSL, "ssl", 24, 0x3d, ASM_REG_W_SSL}, {DSP563XX_REG_IDX_SP, "sp", 24, 0x3b, ASM_REG_W_SP}, {DSP563XX_REG_IDX_EP, "ep", 24, 0x2a, ASM_REG_W_EP}, {DSP563XX_REG_IDX_SZ, "sz", 24, 0x38, ASM_REG_W_SZ}, {DSP563XX_REG_IDX_SC, "sc", 24, 0x31, ASM_REG_W_SC}, /* system */ {DSP563XX_REG_IDX_PC, "pc", 24, 0x00, ASM_REG_W_PC}, {DSP563XX_REG_IDX_SR, "sr", 24, 0x39, ASM_REG_W_SR}, {DSP563XX_REG_IDX_OMR, "omr", 24, 0x3a, ASM_REG_W_OMR}, {DSP563XX_REG_IDX_LA, "la", 24, 0x3e, ASM_REG_W_LA}, {DSP563XX_REG_IDX_LC, "lc", 24, 0x3f, ASM_REG_W_LC}, /* interrupt */ {DSP563XX_REG_IDX_VBA, "vba", 24, 0x30, ASM_REG_W_VBA}, {DSP563XX_REG_IDX_IPRC, "iprc", 24, 0x00, ASM_REG_W_IPRC}, {DSP563XX_REG_IDX_IPRP, "iprp", 24, 0x00, ASM_REG_W_IPRP}, /* port a */ {DSP563XX_REG_IDX_BCR, "bcr", 24, 0x00, ASM_REG_W_BCR}, {DSP563XX_REG_IDX_DCR, "dcr", 24, 0x00, ASM_REG_W_DCR}, {DSP563XX_REG_IDX_AAR0, "aar0", 24, 0x00, ASM_REG_W_AAR0}, {DSP563XX_REG_IDX_AAR1, "aar1", 24, 0x00, ASM_REG_W_AAR1}, {DSP563XX_REG_IDX_AAR2, "aar2", 24, 0x00, ASM_REG_W_AAR2}, {DSP563XX_REG_IDX_AAR3, "aar3", 24, 0x00, ASM_REG_W_AAR3}, /* *INDENT-ON* */ }; enum memory_type { MEM_X = 0, MEM_Y = 1, MEM_P = 2, MEM_L = 3, }; enum watchpoint_condition { EQUAL, NOT_EQUAL, GREATER, LESS_THAN }; #define INSTR_JUMP 0x0AF080 /* Effective Addressing Mode Encoding */ #define EAME_R0 0x10 /* instrcution encoder */ /* movep * s - peripheral space X/Y (X=0,Y=1) * w - write/read * d - source/destination register * p - IO short address */ #define INSTR_MOVEP_REG_HIO(s, w, d, p) (0x084000 | \ ((s & 1) << 16) | ((w & 1) << 15) | ((d & 0x3f) << 8) | (p & 0x3f)) /* the gdb register list is send in this order */ static const uint8_t gdb_reg_list_idx[] = { DSP563XX_REG_IDX_X1, DSP563XX_REG_IDX_X0, DSP563XX_REG_IDX_Y1, DSP563XX_REG_IDX_Y0, DSP563XX_REG_IDX_A2, DSP563XX_REG_IDX_A1, DSP563XX_REG_IDX_A0, DSP563XX_REG_IDX_B2, DSP563XX_REG_IDX_B1, DSP563XX_REG_IDX_B0, DSP563XX_REG_IDX_PC, DSP563XX_REG_IDX_SR, DSP563XX_REG_IDX_OMR, DSP563XX_REG_IDX_LA, DSP563XX_REG_IDX_LC, DSP563XX_REG_IDX_SSH, DSP563XX_REG_IDX_SSL, DSP563XX_REG_IDX_SP, DSP563XX_REG_IDX_EP, DSP563XX_REG_IDX_SZ, DSP563XX_REG_IDX_SC, DSP563XX_REG_IDX_VBA, DSP563XX_REG_IDX_IPRC, DSP563XX_REG_IDX_IPRP, DSP563XX_REG_IDX_BCR, DSP563XX_REG_IDX_DCR, DSP563XX_REG_IDX_AAR0, DSP563XX_REG_IDX_AAR1, DSP563XX_REG_IDX_AAR2, DSP563XX_REG_IDX_AAR3, DSP563XX_REG_IDX_R0, DSP563XX_REG_IDX_R1, DSP563XX_REG_IDX_R2, DSP563XX_REG_IDX_R3, DSP563XX_REG_IDX_R4, DSP563XX_REG_IDX_R5, DSP563XX_REG_IDX_R6, DSP563XX_REG_IDX_R7, DSP563XX_REG_IDX_N0, DSP563XX_REG_IDX_N1, DSP563XX_REG_IDX_N2, DSP563XX_REG_IDX_N3, DSP563XX_REG_IDX_N4, DSP563XX_REG_IDX_N5, DSP563XX_REG_IDX_N6, DSP563XX_REG_IDX_N7, DSP563XX_REG_IDX_M0, DSP563XX_REG_IDX_M1, DSP563XX_REG_IDX_M2, DSP563XX_REG_IDX_M3, DSP563XX_REG_IDX_M4, DSP563XX_REG_IDX_M5, DSP563XX_REG_IDX_M6, DSP563XX_REG_IDX_M7, }; static int dsp563xx_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { int i; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; *reg_list_size = DSP563XX_NUMCOREREGS; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); if (!*reg_list) return ERROR_COMMAND_SYNTAX_ERROR; for (i = 0; i < DSP563XX_NUMCOREREGS; i++) (*reg_list)[i] = &dsp563xx->core_cache->reg_list[gdb_reg_list_idx[i]]; return ERROR_OK; } static int dsp563xx_read_core_reg(struct target *target, int num) { uint32_t reg_value; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if ((num < 0) || (num >= DSP563XX_NUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = dsp563xx->core_regs[num]; buf_set_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32, reg_value); dsp563xx->core_cache->reg_list[num].valid = 1; dsp563xx->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int dsp563xx_write_core_reg(struct target *target, int num) { uint32_t reg_value; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if ((num < 0) || (num >= DSP563XX_NUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = buf_get_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32); dsp563xx->core_regs[num] = reg_value; dsp563xx->core_cache->reg_list[num].valid = 1; dsp563xx->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int dsp563xx_get_core_reg(struct reg *reg) { struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info; struct target *target = dsp563xx_reg->target; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); LOG_DEBUG("%s", __func__); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; return dsp563xx->read_core_reg(target, dsp563xx_reg->num); } static int dsp563xx_set_core_reg(struct reg *reg, uint8_t *buf) { LOG_DEBUG("%s", __func__); struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info; struct target *target = dsp563xx_reg->target; uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, reg->size, value); reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static const struct reg_arch_type dsp563xx_reg_type = { .get = dsp563xx_get_core_reg, .set = dsp563xx_set_core_reg, }; static void dsp563xx_build_reg_cache(struct target *target) { struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(DSP563XX_NUMCOREREGS, sizeof(struct reg)); struct dsp563xx_core_reg *arch_info = malloc( sizeof(struct dsp563xx_core_reg) * DSP563XX_NUMCOREREGS); int i; /* Build the process context cache */ cache->name = "dsp563xx registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = DSP563XX_NUMCOREREGS; (*cache_p) = cache; dsp563xx->core_cache = cache; for (i = 0; i < DSP563XX_NUMCOREREGS; i++) { arch_info[i].num = dsp563xx_regs[i].id; arch_info[i].name = dsp563xx_regs[i].name; arch_info[i].size = dsp563xx_regs[i].bits; arch_info[i].eame = dsp563xx_regs[i].eame; arch_info[i].instr_mask = dsp563xx_regs[i].instr_mask; arch_info[i].target = target; arch_info[i].dsp563xx_common = dsp563xx; reg_list[i].name = dsp563xx_regs[i].name; reg_list[i].size = 32; /* dsp563xx_regs[i].bits; */ reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &dsp563xx_reg_type; reg_list[i].arch_info = &arch_info[i]; } } static int dsp563xx_read_register(struct target *target, int num, int force); static int dsp563xx_write_register(struct target *target, int num, int force); static int dsp563xx_reg_read_high_io(struct target *target, uint32_t instr_mask, uint32_t *data) { int err; uint32_t instr; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); /* we use r0 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0); /* move source memory to r0 */ instr = INSTR_MOVEP_REG_HIO(MEM_X, 0, EAME_R0, instr_mask); err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr); if (err != ERROR_OK) return err; /* move r0 to debug register */ instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, 0xfffffc); err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr); if (err != ERROR_OK) return err; /* read debug register */ err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data); if (err != ERROR_OK) return err; /* r0 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; return ERROR_OK; } static int dsp563xx_reg_write_high_io(struct target *target, uint32_t instr_mask, uint32_t data) { int err; uint32_t instr; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); /* we use r0 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0); /* move data to r0 */ err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x60F400, data); if (err != ERROR_OK) return err; /* move r0 to destination memory */ instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, instr_mask); err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr); if (err != ERROR_OK) return err; /* r0 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; return ERROR_OK; } static int dsp563xx_reg_read(struct target *target, uint32_t eame, uint32_t *data) { int err; uint32_t instr; instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, eame, 0xfffffc); err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr); if (err != ERROR_OK) return err; /* nop */ err = dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000); if (err != ERROR_OK) return err; /* read debug register */ return dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data); } static int dsp563xx_reg_write(struct target *target, uint32_t instr_mask, uint32_t data) { int err; err = dsp563xx_once_execute_dw_ir(target->tap, 0, instr_mask, data); if (err != ERROR_OK) return err; /* nop */ return dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000); } static int dsp563xx_reg_pc_read(struct target *target) { struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); /* pc was changed, nothing todo */ if (dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) return ERROR_OK; /* conditional branch check */ if (once_regs[ONCE_REG_IDX_OPABDR].reg == once_regs[ONCE_REG_IDX_OPABEX].reg) { if ((once_regs[ONCE_REG_IDX_OPABF11].reg & 1) == 0) { LOG_DEBUG("%s conditional branch not supported yet (0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 ")", __func__, (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1), once_regs[ONCE_REG_IDX_OPABDR].reg, once_regs[ONCE_REG_IDX_OPABEX].reg); /* TODO: use disassembly to set correct pc offset * read 2 words from OPABF11 and disasm the instruction */ dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1) & 0x00FFFFFF; } else { if (once_regs[ONCE_REG_IDX_OPABEX].reg == once_regs[ONCE_REG_IDX_OPABFR].reg) dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = once_regs[ONCE_REG_IDX_OPABEX].reg; else dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = once_regs[ONCE_REG_IDX_OPABEX].reg - 1; } } else dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = once_regs[ONCE_REG_IDX_OPABEX].reg; dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_PC); return ERROR_OK; } static int dsp563xx_reg_ssh_read(struct target *target) { int err; uint32_t sp; struct dsp563xx_core_reg *arch_info; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info; /* get a valid stack pointer */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0); if (err != ERROR_OK) return err; sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP]; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 0); if (err != ERROR_OK) return err; /* get a valid stack count */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SC, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 0); if (err != ERROR_OK) return err; /* get a valid extended pointer */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_EP, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 0); if (err != ERROR_OK) return err; if (!sp) sp = 0x00FFFFFF; else { err = dsp563xx_reg_read(target, arch_info->eame, &sp); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 1); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 1); if (err != ERROR_OK) return err; } dsp563xx->core_regs[DSP563XX_REG_IDX_SSH] = sp; dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSH); return ERROR_OK; } static int dsp563xx_reg_ssh_write(struct target *target) { int err; uint32_t sp; struct dsp563xx_core_reg *arch_info; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info; /* get a valid stack pointer */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0); if (err != ERROR_OK) return err; sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP]; if (sp) { sp--; /* write new stackpointer */ dsp563xx->core_regs[DSP563XX_REG_IDX_SP] = sp; err = dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SP); if (err != ERROR_OK) return err; err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1); if (err != ERROR_OK) return err; err = dsp563xx_reg_write(target, arch_info->instr_mask, dsp563xx->core_regs[DSP563XX_REG_IDX_SSH]); if (err != ERROR_OK) return err; err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 1); if (err != ERROR_OK) return err; err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SSH, 1); if (err != ERROR_OK) return err; } return ERROR_OK; } static int dsp563xx_reg_ssl_read(struct target *target) { int err; uint32_t sp; struct dsp563xx_core_reg *arch_info; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].arch_info; /* get a valid stack pointer */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0); if (err != ERROR_OK) return err; sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP]; if (!sp) sp = 0x00FFFFFF; else { err = dsp563xx_reg_read(target, arch_info->eame, &sp); if (err != ERROR_OK) return err; } dsp563xx->core_regs[DSP563XX_REG_IDX_SSL] = sp; dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSL); return ERROR_OK; } static int dsp563xx_read_register(struct target *target, int num, int force) { int err = ERROR_OK; uint32_t data = 0; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); struct dsp563xx_core_reg *arch_info; if (force) dsp563xx->core_cache->reg_list[num].valid = 0; if (!dsp563xx->core_cache->reg_list[num].valid) { arch_info = dsp563xx->core_cache->reg_list[num].arch_info; switch (arch_info->num) { case DSP563XX_REG_IDX_SSH: err = dsp563xx_reg_ssh_read(target); break; case DSP563XX_REG_IDX_SSL: err = dsp563xx_reg_ssl_read(target); break; case DSP563XX_REG_IDX_PC: err = dsp563xx_reg_pc_read(target); break; case DSP563XX_REG_IDX_IPRC: case DSP563XX_REG_IDX_IPRP: case DSP563XX_REG_IDX_BCR: case DSP563XX_REG_IDX_DCR: case DSP563XX_REG_IDX_AAR0: case DSP563XX_REG_IDX_AAR1: case DSP563XX_REG_IDX_AAR2: case DSP563XX_REG_IDX_AAR3: err = dsp563xx_reg_read_high_io(target, arch_info->instr_mask, &data); if (err == ERROR_OK) { dsp563xx->core_regs[num] = data; dsp563xx->read_core_reg(target, num); } break; default: err = dsp563xx_reg_read(target, arch_info->eame, &data); if (err == ERROR_OK) { dsp563xx->core_regs[num] = data; dsp563xx->read_core_reg(target, num); } break; } } return err; } static int dsp563xx_write_register(struct target *target, int num, int force) { int err = ERROR_OK; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); struct dsp563xx_core_reg *arch_info; if (force) dsp563xx->core_cache->reg_list[num].dirty = 1; if (dsp563xx->core_cache->reg_list[num].dirty) { arch_info = dsp563xx->core_cache->reg_list[num].arch_info; dsp563xx->write_core_reg(target, num); switch (arch_info->num) { case DSP563XX_REG_IDX_SSH: err = dsp563xx_reg_ssh_write(target); break; case DSP563XX_REG_IDX_PC: /* pc is updated on resume, no need to write it here */ break; case DSP563XX_REG_IDX_IPRC: case DSP563XX_REG_IDX_IPRP: case DSP563XX_REG_IDX_BCR: case DSP563XX_REG_IDX_DCR: case DSP563XX_REG_IDX_AAR0: case DSP563XX_REG_IDX_AAR1: case DSP563XX_REG_IDX_AAR2: case DSP563XX_REG_IDX_AAR3: err = dsp563xx_reg_write_high_io(target, arch_info->instr_mask, dsp563xx->core_regs[num]); break; default: err = dsp563xx_reg_write(target, arch_info->instr_mask, dsp563xx->core_regs[num]); if ((err == ERROR_OK) && (arch_info->num == DSP563XX_REG_IDX_SP)) { dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].valid = 0; dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].valid = 0; } break; } } return err; } static int dsp563xx_save_context(struct target *target) { int i, err = ERROR_OK; for (i = 0; i < DSP563XX_NUMCOREREGS; i++) { err = dsp563xx_read_register(target, i, 0); if (err != ERROR_OK) break; } return err; } static int dsp563xx_restore_context(struct target *target) { int i, err = ERROR_OK; for (i = 0; i < DSP563XX_NUMCOREREGS; i++) { err = dsp563xx_write_register(target, i, 0); if (err != ERROR_OK) break; } return err; } static void dsp563xx_invalidate_x_context(struct target *target, uint32_t addr_start, uint32_t addr_end) { int i; struct dsp563xx_core_reg *arch_info; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (addr_start > ASM_REG_W_IPRC) return; if (addr_start < ASM_REG_W_AAR3) return; for (i = DSP563XX_REG_IDX_IPRC; i < DSP563XX_NUMCOREREGS; i++) { arch_info = dsp563xx->core_cache->reg_list[i].arch_info; if ((arch_info->instr_mask >= addr_start) && (arch_info->instr_mask <= addr_end)) { dsp563xx->core_cache->reg_list[i].valid = 0; dsp563xx->core_cache->reg_list[i].dirty = 0; } } } static int dsp563xx_target_create(struct target *target, Jim_Interp *interp) { struct dsp563xx_common *dsp563xx = calloc(1, sizeof(struct dsp563xx_common)); if (!dsp563xx) return ERROR_COMMAND_SYNTAX_ERROR; dsp563xx->jtag_info.tap = target->tap; target->arch_info = dsp563xx; dsp563xx->read_core_reg = dsp563xx_read_core_reg; dsp563xx->write_core_reg = dsp563xx_write_core_reg; return ERROR_OK; } static int dsp563xx_init_target(struct command_context *cmd_ctx, struct target *target) { LOG_DEBUG("%s", __func__); dsp563xx_build_reg_cache(target); struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); dsp563xx->hardware_breakpoints_cleared = 0; dsp563xx->hardware_breakpoint[0].used = BPU_NONE; return ERROR_OK; } static int dsp563xx_examine(struct target *target) { uint32_t chip; if (target->tap->hasidcode == false) { LOG_ERROR("no IDCODE present on device"); return ERROR_COMMAND_SYNTAX_ERROR; } if (!target_was_examined(target)) { target_set_examined(target); /* examine core and chip derivate number */ chip = (target->tap->idcode>>12) & 0x3ff; /* core number 0 means DSP563XX */ if (((chip>>5)&0x1f) == 0) chip += 300; LOG_INFO("DSP56%03" PRId32 " device found", chip); /* Clear all breakpoints */ dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); } return ERROR_OK; } static int dsp563xx_arch_state(struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } #define DSP563XX_SR_SA (1<<17) #define DSP563XX_SR_SC (1<<13) static int dsp563xx_debug_once_init(struct target *target) { return dsp563xx_once_read_register(target->tap, 1, once_regs, DSP563XX_NUMONCEREGS); } static int dsp563xx_debug_init(struct target *target) { int err; uint32_t sr; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); struct dsp563xx_core_reg *arch_info; err = dsp563xx_debug_once_init(target); if (err != ERROR_OK) return err; arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].arch_info; /* check 24bit mode */ err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SR, 0); if (err != ERROR_OK) return err; sr = dsp563xx->core_regs[DSP563XX_REG_IDX_SR]; if (sr & (DSP563XX_SR_SA | DSP563XX_SR_SC)) { sr &= ~(DSP563XX_SR_SA | DSP563XX_SR_SC); err = dsp563xx_once_execute_dw_ir(target->tap, 1, arch_info->instr_mask, sr); if (err != ERROR_OK) return err; dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].dirty = 1; } err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N0, 0); if (err != ERROR_OK) return err; err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N1, 0); if (err != ERROR_OK) return err; err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M0, 0); if (err != ERROR_OK) return err; err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M1, 0); if (err != ERROR_OK) return err; if (dsp563xx->core_regs[DSP563XX_REG_IDX_N0] != 0x000000) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].arch_info; err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000); if (err != ERROR_OK) return err; } dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].dirty = 1; if (dsp563xx->core_regs[DSP563XX_REG_IDX_N1] != 0x000000) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].arch_info; err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000); if (err != ERROR_OK) return err; } dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].dirty = 1; if (dsp563xx->core_regs[DSP563XX_REG_IDX_M0] != 0xffffff) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].arch_info; err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff); if (err != ERROR_OK) return err; } dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].dirty = 1; if (dsp563xx->core_regs[DSP563XX_REG_IDX_M1] != 0xffffff) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].arch_info; err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff); if (err != ERROR_OK) return err; } dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].dirty = 1; err = dsp563xx_save_context(target); if (err != ERROR_OK) return err; return ERROR_OK; } static int dsp563xx_jtag_debug_request(struct target *target) { return dsp563xx_once_request_debug(target->tap, target->state == TARGET_RESET); } static int dsp563xx_poll(struct target *target) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); uint32_t once_status = 0; int state; state = dsp563xx_once_target_status(target->tap); if (state == TARGET_UNKNOWN) { target->state = state; LOG_ERROR("jtag status contains invalid mode value - communication failure"); return ERROR_TARGET_FAILURE; } err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status); if (err != ERROR_OK) return err; if ((once_status & DSP563XX_ONCE_OSCR_DEBUG_M) == DSP563XX_ONCE_OSCR_DEBUG_M) { if (target->state != TARGET_HALTED) { target->state = TARGET_HALTED; err = dsp563xx_debug_init(target); if (err != ERROR_OK) return err; if (once_status & (DSP563XX_ONCE_OSCR_MBO|DSP563XX_ONCE_OSCR_SWO)) target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); else target_call_event_callbacks(target, TARGET_EVENT_HALTED); LOG_DEBUG("target->state: %s (%" PRIx32 ")", target_state_name(target), once_status); LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]); } } if (!dsp563xx->hardware_breakpoints_cleared) { err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, 0); err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0); dsp563xx->hardware_breakpoints_cleared = 1; } return ERROR_OK; } static int dsp563xx_halt(struct target *target) { int err; LOG_DEBUG("%s", __func__); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); err = dsp563xx_jtag_debug_request(target); if (err != ERROR_OK) return err; target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int dsp563xx_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); /* check if pc was changed and resume want to execute the next address * if pc was changed from gdb or other interface we will * jump to this address and don't execute the next address * this will not affect the resume command with an address argument * because current is set to zero then */ if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; current = 0; } LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address); err = dsp563xx_restore_context(target); if (err != ERROR_OK) return err; register_cache_invalidate(dsp563xx->core_cache); if (current) { /* restore pipeline registers and go */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, once_regs[ONCE_REG_IDX_OPILR].reg); if (err != ERROR_OK) return err; err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR | DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, once_regs[ONCE_REG_IDX_OPDBR].reg); if (err != ERROR_OK) return err; } else { /* set to go register and jump */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP); if (err != ERROR_OK) return err; err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO | DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, address); if (err != ERROR_OK) return err; } target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); return ERROR_OK; } static int dsp563xx_step_ex(struct target *target, int current, uint32_t address, int handle_breakpoints, int steps) { int err; uint32_t once_status; uint32_t dr_in, cnt; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (target->state != TARGET_HALTED) { LOG_DEBUG("target was not halted"); return ERROR_OK; } /* check if pc was changed and step want to execute the next address * if pc was changed from gdb or other interface we will * jump to this address and don't execute the next address * this will not affect the step command with an address argument * because current is set to zero then */ if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; current = 0; } LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address); err = dsp563xx_jtag_debug_request(target); if (err != ERROR_OK) return err; err = dsp563xx_restore_context(target); if (err != ERROR_OK) return err; /* reset trace mode */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000); if (err != ERROR_OK) return err; /* enable trace mode */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, DSP563XX_ONCE_OSCR_TME); if (err != ERROR_OK) return err; cnt = steps; /* on JUMP we need one extra cycle */ if (!current) cnt++; /* load step counter with N-1 */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, cnt); if (err != ERROR_OK) return err; if (current) { /* restore pipeline registers and go */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, once_regs[ONCE_REG_IDX_OPILR].reg); if (err != ERROR_OK) return err; err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR | DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, once_regs[ONCE_REG_IDX_OPDBR].reg); if (err != ERROR_OK) return err; } else { /* set to go register and jump */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP); if (err != ERROR_OK) return err; err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO | DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, address); if (err != ERROR_OK) return err; } while (1) { err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status); if (err != ERROR_OK) return err; if (once_status & DSP563XX_ONCE_OSCR_TO) { err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABFR, &dr_in); if (err != ERROR_OK) return err; LOG_DEBUG("fetch: %08X", (unsigned) dr_in&0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABDR, &dr_in); if (err != ERROR_OK) return err; LOG_DEBUG("decode: %08X", (unsigned) dr_in&0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABEX, &dr_in); if (err != ERROR_OK) return err; LOG_DEBUG("execute: %08X", (unsigned) dr_in&0x00ffffff); /* reset trace mode */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000); if (err != ERROR_OK) return err; register_cache_invalidate(dsp563xx->core_cache); err = dsp563xx_debug_init(target); if (err != ERROR_OK) return err; break; } } return ERROR_OK; } static int dsp563xx_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } err = dsp563xx_step_ex(target, current, address, handle_breakpoints, 0); if (err != ERROR_OK) return err; target->debug_reason = DBG_REASON_SINGLESTEP; target_call_event_callbacks(target, TARGET_EVENT_HALTED); LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]); return err; } static int dsp563xx_assert_reset(struct target *target) { int retval = 0; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_HAS_SRST) { /* default to asserting srst */ if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else jtag_add_reset(0, 1); } target->state = TARGET_RESET; jtag_add_sleep(5000); /* registers are now invalid */ register_cache_invalidate(dsp563xx->core_cache); if (target->reset_halt) { retval = target_halt(target); if (retval != ERROR_OK) return retval; } LOG_DEBUG("%s", __func__); return ERROR_OK; } static int dsp563xx_deassert_reset(struct target *target) { int err; /* deassert reset lines */ jtag_add_reset(0, 0); err = dsp563xx_poll(target); if (err != ERROR_OK) return err; if (target->reset_halt) { if (target->state == TARGET_HALTED) { /* after a reset the cpu jmp to the * reset vector and need 2 cycles to fill * the cache (fetch,decode,excecute) */ err = dsp563xx_step_ex(target, 1, 0, 1, 1); if (err != ERROR_OK) return err; } } else target->state = TARGET_RUNNING; LOG_DEBUG("%s", __func__); return ERROR_OK; } static int dsp563xx_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { int i; int retval = ERROR_OK; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = 0; i < num_mem_params; i++) { retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } for (i = 0; i < num_reg_params; i++) { struct reg *reg = register_get_by_name(dsp563xx->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); continue; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); continue; } retval = dsp563xx_set_core_reg(reg, reg_params[i].value); if (retval != ERROR_OK) return retval; } /* exec */ retval = target_resume(target, 0, entry_point, 1, 1); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, timeout_ms); if (retval != ERROR_OK) return retval; for (i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } for (i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { struct reg *reg = register_get_by_name(dsp563xx->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); continue; } if (reg->size != reg_params[i].size) { LOG_ERROR( "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); continue; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } return ERROR_OK; } /* global command context from openocd.c */ extern struct command_context *global_cmd_ctx; static int dsp563xx_get_default_memory(void) { Jim_Interp *interp; Jim_Obj *memspace; char *c; if (!global_cmd_ctx) return MEM_P; interp = global_cmd_ctx->interp; if (!interp) return MEM_P; memspace = Jim_GetGlobalVariableStr(interp, "memspace", JIM_NONE); if (!memspace) return MEM_P; c = (char *)Jim_GetString(memspace, NULL); if (!c) return MEM_P; switch (c[0]) { case '1': return MEM_X; case '2': return MEM_Y; case '3': return MEM_L; default: break; } return MEM_P; } static int dsp563xx_read_memory_core(struct target *target, int mem_type, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); uint32_t i, x; uint32_t data, move_cmd = 0; uint8_t *b; LOG_DEBUG( "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", mem_type, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } switch (mem_type) { case MEM_X: /* TODO: mark effected queued registers */ move_cmd = 0x61d800; break; case MEM_Y: move_cmd = 0x69d800; break; case MEM_P: move_cmd = 0x07d891; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } /* we use r0 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0); /* we use r1 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1); /* r0 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; /* r1 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1; x = count; b = buffer; err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address); if (err != ERROR_OK) return err; for (i = 0; i < x; i++) { err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd); if (err != ERROR_OK) return err; err = dsp563xx_once_execute_sw_ir(target->tap, 0, 0x08D13C); if (err != ERROR_OK) return err; err = dsp563xx_once_reg_read(target->tap, 0, DSP563XX_ONCE_OGDBR, (uint32_t *)(void *)b); if (err != ERROR_OK) return err; b += 4; } /* flush the jtag queue */ err = jtag_execute_queue(); if (err != ERROR_OK) return err; /* walk over the buffer and fix target endianness */ b = buffer; for (i = 0; i < x; i++) { data = buf_get_u32(b, 0, 32) & 0x00FFFFFF; /* LOG_DEBUG("R: %08X", *((uint32_t*)b)); */ target_buffer_set_u32(target, b, data); b += 4; } return ERROR_OK; } static int dsp563xx_read_memory(struct target *target, int mem_type, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int err; uint32_t i, i1; uint8_t *buffer_y, *buffer_x; /* if size equals zero we are called from target read memory * and have to handle the parameter here */ if ((size == 0) && (count != 0)) { size = count % 4; if (size) LOG_DEBUG("size is not aligned to 4 byte"); count = (count - size) / 4; size = 4; } /* we only support 4 byte aligned data */ if ((size != 4) || (!count)) return ERROR_COMMAND_SYNTAX_ERROR; if (mem_type != MEM_L) return dsp563xx_read_memory_core(target, mem_type, address, size, count, buffer); buffer_y = malloc(size * count); if (!buffer_y) return ERROR_COMMAND_SYNTAX_ERROR; buffer_x = malloc(size * count); if (!buffer_x) { free(buffer_y); return ERROR_COMMAND_SYNTAX_ERROR; } err = dsp563xx_read_memory_core(target, MEM_Y, address, size, count / 2, buffer_y); if (err != ERROR_OK) { free(buffer_y); free(buffer_x); return err; } err = dsp563xx_read_memory_core(target, MEM_X, address, size, count / 2, buffer_x); if (err != ERROR_OK) { free(buffer_y); free(buffer_x); return err; } for (i = 0, i1 = 0; i < count; i += 2, i1++) { buf_set_u32(buffer + i*sizeof(uint32_t), 0, 32, buf_get_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32)); buf_set_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32, buf_get_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32)); } free(buffer_y); free(buffer_x); return ERROR_OK; } static int dsp563xx_read_memory_default(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return dsp563xx_read_memory(target, dsp563xx_get_default_memory(), address, size, count, buffer); } static int dsp563xx_read_buffer_default(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { return dsp563xx_read_memory(target, dsp563xx_get_default_memory(), address, size, 0, buffer); } static int dsp563xx_write_memory_core(struct target *target, int mem_type, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); uint32_t i, x; uint32_t data, move_cmd = 0; const uint8_t *b; LOG_DEBUG( "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", mem_type, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } switch (mem_type) { case MEM_X: /* invalidate affected x registers */ dsp563xx_invalidate_x_context(target, address, address + count - 1); move_cmd = 0x615800; break; case MEM_Y: move_cmd = 0x695800; break; case MEM_P: move_cmd = 0x075891; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } /* we use r0 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0); /* we use r1 to store temporary data */ if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid) dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1); /* r0 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; /* r1 is no longer valid on target */ dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1; x = count; b = buffer; err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address); if (err != ERROR_OK) return err; for (i = 0; i < x; i++) { data = target_buffer_get_u32(target, b); /* LOG_DEBUG("W: %08X", data); */ data &= 0x00ffffff; err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x61F400, data); if (err != ERROR_OK) return err; err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd); if (err != ERROR_OK) return err; b += 4; } /* flush the jtag queue */ err = jtag_execute_queue(); if (err != ERROR_OK) return err; return ERROR_OK; } static int dsp563xx_write_memory(struct target *target, int mem_type, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int err; uint32_t i, i1; uint8_t *buffer_y, *buffer_x; /* if size equals zero we are called from target write memory * and have to handle the parameter here */ if ((size == 0) && (count != 0)) { size = count % 4; if (size) LOG_DEBUG("size is not aligned to 4 byte"); count = (count - size) / 4; size = 4; } /* we only support 4 byte aligned data */ if ((size != 4) || (!count)) return ERROR_COMMAND_SYNTAX_ERROR; if (mem_type != MEM_L) return dsp563xx_write_memory_core(target, mem_type, address, size, count, buffer); buffer_y = malloc(size * count); if (!buffer_y) return ERROR_COMMAND_SYNTAX_ERROR; buffer_x = malloc(size * count); if (!buffer_x) { free(buffer_y); return ERROR_COMMAND_SYNTAX_ERROR; } for (i = 0, i1 = 0; i < count; i += 2, i1++) { buf_set_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32, buf_get_u32(buffer + i * sizeof(uint32_t), 0, 32)); buf_set_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32, buf_get_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32)); } err = dsp563xx_write_memory_core(target, MEM_Y, address, size, count / 2, buffer_y); if (err != ERROR_OK) { free(buffer_y); free(buffer_x); return err; } err = dsp563xx_write_memory_core(target, MEM_X, address, size, count / 2, buffer_x); if (err != ERROR_OK) { free(buffer_y); free(buffer_x); return err; } free(buffer_y); free(buffer_x); return ERROR_OK; } static int dsp563xx_write_memory_default(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { return dsp563xx_write_memory(target, dsp563xx_get_default_memory(), address, size, count, buffer); } static int dsp563xx_write_buffer_default(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { return dsp563xx_write_memory(target, dsp563xx_get_default_memory(), address, size, 0, buffer); } /* * Exit with error here, because we support watchpoints over a custom command. * This is because the DSP has separate X,Y,P memspace which is not compatible to the * traditional watchpoint logic. */ static int dsp563xx_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* * @see dsp563xx_add_watchpoint */ static int dsp563xx_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } static void handle_md_output(struct command_context *cmd_ctx, struct target *target, uint32_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; unsigned line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; unsigned output_len = 0; const char *value_fmt; switch (size) { case 4: value_fmt = "%8.8x "; break; case 2: value_fmt = "%4.4x "; break; case 1: value_fmt = "%2.2x "; break; default: /* "can't happen", caller checked */ LOG_ERROR("invalid memory read size: %u", size); return; } for (unsigned i = 0; i < count; i++) { if (i % line_modulo == 0) output_len += snprintf(output + output_len, sizeof(output) - output_len, "0x%8.8x: ", (unsigned) (address + i)); uint32_t value = 0; const uint8_t *value_ptr = buffer + i * size; switch (size) { case 4: value = target_buffer_get_u32(target, value_ptr); break; case 2: value = target_buffer_get_u16(target, value_ptr); break; case 1: value = *value_ptr; } output_len += snprintf(output + output_len, sizeof(output) - output_len, value_fmt, value); if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { command_print(cmd_ctx, "%s", output); output_len = 0; } } } static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t address, uint32_t memType, enum watchpoint_rw rw, enum watchpoint_condition cond) { int err = ERROR_OK; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); bool wasRunning = false; /* Only set breakpoint when halted */ if (target->state != TARGET_HALTED) { dsp563xx_halt(target); wasRunning = true; } if (dsp563xx->hardware_breakpoint[0].used) { LOG_ERROR("Cannot add watchpoint. Hardware resource already used."); err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } uint32_t obcr_value = 0; if (err == ERROR_OK) { obcr_value |= OBCR_b0_or_b1; switch (memType) { case MEM_X: obcr_value |= OBCR_BP_MEM_X; break; case MEM_Y: obcr_value |= OBCR_BP_MEM_Y; break; case MEM_P: obcr_value |= OBCR_BP_MEM_P; break; default: LOG_ERROR("Unknown memType parameter (%" PRIu32 ")", memType); err = ERROR_TARGET_INVALID; } } if (err == ERROR_OK) { switch (rw) { case WPT_READ: obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ); break; case WPT_WRITE: obcr_value |= OBCR_BP_0(OBCR_BP_ON_WRITE); break; case WPT_ACCESS: obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ|OBCR_BP_ON_WRITE); break; default: LOG_ERROR("Unsupported write mode (%d)", rw); err = ERROR_TARGET_INVALID; } } if (err == ERROR_OK) { switch (cond) { case EQUAL: obcr_value |= OBCR_BP_0(OBCR_BP_CC_EQUAL); break; case NOT_EQUAL: obcr_value |= OBCR_BP_0(OBCR_BP_CC_NOT_EQUAL); break; case LESS_THAN: obcr_value |= OBCR_BP_0(OBCR_BP_CC_LESS_THAN); break; case GREATER: obcr_value |= OBCR_BP_0(OBCR_BP_CC_GREATER_THAN); break; default: LOG_ERROR("Unsupported condition code (%d)", cond); err = ERROR_TARGET_INVALID; } } if (err == ERROR_OK) err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, address); if (err == ERROR_OK) err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0x0); if (err == ERROR_OK) err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, obcr_value); if (err == ERROR_OK) { /* You should write the memory breakpoint counter to 0 */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMBC, 0); } if (err == ERROR_OK) { /* You should write the memory breakpoint counter to 0 */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, 0); } if (err == ERROR_OK) dsp563xx->hardware_breakpoint[0].used = BPU_WATCHPOINT; if (err == ERROR_OK && wasRunning) { /* Resume from current PC */ err = dsp563xx_resume(target, 1, 0x0, 0, 0); } return err; } static int dsp563xx_remove_custom_watchpoint(struct target *target) { int err = ERROR_OK; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); if (dsp563xx->hardware_breakpoint[0].used != BPU_WATCHPOINT) { LOG_ERROR("Cannot remove watchpoint, as no watchpoint is currently configured!"); err = ERROR_TARGET_INVALID; } if (err == ERROR_OK) { /* Clear watchpoint by clearing OBCR. */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); } if (err == ERROR_OK) dsp563xx->hardware_breakpoint[0].used = BPU_NONE; return err; } COMMAND_HANDLER(dsp563xx_add_watchpoint_command) { int err = ERROR_OK; struct target *target = get_current_target(CMD_CTX); uint32_t mem_type = 0; switch (CMD_NAME[2]) { case 'x': mem_type = MEM_X; break; case 'y': mem_type = MEM_Y; break; case 'p': mem_type = MEM_P; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address = 0; if (CMD_ARGC > 2) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address); enum watchpoint_condition cond; switch (CMD_ARGV[0][0]) { case '>': cond = GREATER; break; case '<': cond = LESS_THAN; break; case '=': cond = EQUAL; break; case '!': cond = NOT_EQUAL; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } enum watchpoint_rw rw; switch (CMD_ARGV[1][0]) { case 'r': rw = WPT_READ; break; case 'w': rw = WPT_WRITE; break; case 'a': rw = WPT_ACCESS; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } err = dsp563xx_add_custom_watchpoint(target, address, mem_type, rw, cond); return err; } /* Adding a breakpoint using the once breakpoint logic. * Note that this mechanism is a true hw breakpoint and is share between the watchpoint logic. * This means, you can only have one breakpoint/watchpoint at any time. */ static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { return dsp563xx_add_custom_watchpoint(target, breakpoint->address, MEM_P, WPT_READ, EQUAL); } static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { return dsp563xx_remove_custom_watchpoint(target); } COMMAND_HANDLER(dsp563xx_remove_watchpoint_command) { struct target *target = get_current_target(CMD_CTX); return dsp563xx_remove_custom_watchpoint(target); } COMMAND_HANDLER(dsp563xx_mem_command) { struct target *target = get_current_target(CMD_CTX); int err = ERROR_OK; int read_mem; uint32_t address = 0; uint32_t count = 1, i; uint32_t pattern = 0; uint32_t mem_type; uint8_t *buffer, *b; switch (CMD_NAME[1]) { case 'w': read_mem = 0; break; case 'd': read_mem = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } switch (CMD_NAME[3]) { case 'x': mem_type = MEM_X; break; case 'y': mem_type = MEM_Y; break; case 'p': mem_type = MEM_P; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } if (CMD_ARGC > 0) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); if (read_mem == 0) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC > 1) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern); if (CMD_ARGC > 2) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); } if (read_mem == 1) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC > 1) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count); } buffer = calloc(count, sizeof(uint32_t)); if (read_mem == 1) { err = dsp563xx_read_memory(target, mem_type, address, sizeof(uint32_t), count, buffer); if (err == ERROR_OK) handle_md_output(CMD_CTX, target, address, sizeof(uint32_t), count, buffer); } else { b = buffer; for (i = 0; i < count; i++) { target_buffer_set_u32(target, b, pattern); b += 4; } err = dsp563xx_write_memory(target, mem_type, address, sizeof(uint32_t), count, buffer); } free(buffer); return err; } static const struct command_registration dsp563xx_command_handlers[] = { { .name = "mwwx", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write x memory words", .usage = "address value [count]", }, { .name = "mwwy", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write y memory words", .usage = "address value [count]", }, { .name = "mwwp", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write p memory words", .usage = "address value [count]", }, { .name = "mdwx", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display x memory words", .usage = "address [count]", }, { .name = "mdwy", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display y memory words", .usage = "address [count]", }, { .name = "mdwp", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display p memory words", .usage = "address [count]", }, /* * Watchpoint commands */ { .name = "wpp", .handler = dsp563xx_add_watchpoint_command, .mode = COMMAND_EXEC, .help = "Create p memspace watchpoint", .usage = "(>|<|=|!) (r|w|a) address", }, { .name = "wpx", .handler = dsp563xx_add_watchpoint_command, .mode = COMMAND_EXEC, .help = "Create x memspace watchpoint", .usage = "(>|<|=|!) (r|w|a) address", }, { .name = "wpy", .handler = dsp563xx_add_watchpoint_command, .mode = COMMAND_EXEC, .help = "Create y memspace watchpoint", .usage = "(>|<|=|!) (r|w|a) address", }, { .name = "rwpc", .handler = dsp563xx_remove_watchpoint_command, .mode = COMMAND_EXEC, .help = "remove watchpoint custom", .usage = " ", }, COMMAND_REGISTRATION_DONE }; /** Holds methods for DSP563XX targets. */ struct target_type dsp563xx_target = { .name = "dsp563xx", .poll = dsp563xx_poll, .arch_state = dsp563xx_arch_state, .get_gdb_reg_list = dsp563xx_get_gdb_reg_list, .halt = dsp563xx_halt, .resume = dsp563xx_resume, .step = dsp563xx_step, .assert_reset = dsp563xx_assert_reset, .deassert_reset = dsp563xx_deassert_reset, .read_memory = dsp563xx_read_memory_default, .write_memory = dsp563xx_write_memory_default, .read_buffer = dsp563xx_read_buffer_default, .write_buffer = dsp563xx_write_buffer_default, .run_algorithm = dsp563xx_run_algorithm, .add_breakpoint = dsp563xx_add_breakpoint, .remove_breakpoint = dsp563xx_remove_breakpoint, .add_watchpoint = dsp563xx_add_watchpoint, .remove_watchpoint = dsp563xx_remove_watchpoint, .commands = dsp563xx_command_handlers, .target_create = dsp563xx_target_create, .init_target = dsp563xx_init_target, .examine = dsp563xx_examine, }; openocd-0.9.0/src/target/dsp563xx.h0000644000175000017500000000507412315575361013740 00000000000000/*************************************************************************** * Copyright (C) 2009-2011 by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef DSP563XX_H #define DSP563XX_H #include #include #define DSP563XX_NUMCOREREGS 54 #define DSP563XX_NUMONCEREGS 25 struct mcu_jtag { struct jtag_tap *tap; }; enum breakpoint_usage { BPU_NONE = 0, BPU_BREAKPOINT, BPU_WATCHPOINT }; struct hardware_breakpoint { enum breakpoint_usage used; }; struct dsp563xx_common { struct mcu_jtag jtag_info; struct reg_cache *core_cache; uint32_t core_regs[DSP563XX_NUMCOREREGS]; struct once_reg once_regs[DSP563XX_NUMONCEREGS]; /* register cache to processor synchronization */ int (*read_core_reg) (struct target *target, int num); int (*write_core_reg) (struct target *target, int num); struct hardware_breakpoint hardware_breakpoint[1]; /*Were the hardware breakpoints cleared on startup?*/ int hardware_breakpoints_cleared; }; struct dsp563xx_core_reg { uint32_t num; const char *name; uint32_t size; uint8_t eame; uint32_t instr_mask; struct target *target; struct dsp563xx_common *dsp563xx_common; }; static inline struct dsp563xx_common *target_to_dsp563xx(struct target *target) { return target->arch_info; } #endif /* DSP563XX_H */ openocd-0.9.0/src/target/avr32_jtag.c0000644000175000017500000002175012315575361014270 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "jtag/jtag.h" #include "avr32_jtag.h" static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr) { struct jtag_tap *tap; int busy = 0; tap = jtag_info->tap; if (tap == NULL) return ERROR_FAIL; if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) { do { struct scan_field field; uint8_t t[4]; uint8_t ret[4]; field.num_bits = tap->ir_length; field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = ret; jtag_add_ir_scan(tap, &field, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: setting address failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(ret, 2, 1); } while (busy); /* check for busy bit */ } return ERROR_OK; } int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info, uint32_t addr, int mode) { struct scan_field fields[2]; uint8_t addr_buf[4]; uint8_t busy_buf[4]; int busy; memset(fields, 0, sizeof(fields)); do { memset(addr_buf, 0, sizeof(addr_buf)); memset(busy_buf, 0, sizeof(busy_buf)); buf_set_u32(addr_buf, 0, 1, mode); buf_set_u32(addr_buf, 1, 7, addr); fields[0].num_bits = 26; fields[0].in_value = NULL; fields[0].out_value = NULL; fields[1].num_bits = 8; fields[1].in_value = busy_buf; fields[1].out_value = addr_buf; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: setting address failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 6, 1); } while (busy); return ERROR_OK; } int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info, uint32_t *pdata) { struct scan_field fields[2]; uint8_t data_buf[4]; uint8_t busy_buf[4]; int busy; do { memset(data_buf, 0, sizeof(data_buf)); memset(busy_buf, 0, sizeof(busy_buf)); fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = data_buf; fields[1].num_bits = 2; fields[1].in_value = busy_buf; fields[1].out_value = NULL; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: reading data failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 0, 1); } while (busy); *pdata = buf_get_u32(data_buf, 0, 32); return ERROR_OK; } int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info, uint32_t data) { struct scan_field fields[2]; uint8_t data_buf[4]; uint8_t busy_buf[4]; uint8_t dummy_buf[4]; int busy; do { memset(data_buf, 0, sizeof(data_buf)); memset(busy_buf, 0, sizeof(busy_buf)); memset(dummy_buf, 0, sizeof(dummy_buf)); fields[0].num_bits = 2; fields[0].in_value = busy_buf; fields[0].out_value = dummy_buf; buf_set_u32(data_buf, 0, 32, data); fields[1].num_bits = 32; fields[1].in_value = NULL; fields[1].out_value = data_buf; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: reading data failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 0, 0); } while (busy); return ERROR_OK; } int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info, uint32_t addr, uint32_t *value) { avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); avr32_jtag_nexus_set_address(jtag_info, addr, MODE_READ); avr32_jtag_nexus_read_data(jtag_info, value); return ERROR_OK; } int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info, uint32_t addr, uint32_t value) { avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); avr32_jtag_nexus_set_address(jtag_info, addr, MODE_WRITE); avr32_jtag_nexus_write_data(jtag_info, value); return ERROR_OK; } int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave, uint32_t addr, int mode) { struct scan_field fields[2]; uint8_t addr_buf[4]; uint8_t slave_buf[4]; uint8_t busy_buf[4]; int busy; memset(fields, 0, sizeof(fields)); do { memset(addr_buf, 0, sizeof(addr_buf)); memset(busy_buf, 0, sizeof(busy_buf)); memset(slave_buf, 0, sizeof(slave_buf)); buf_set_u32(slave_buf, 0, 4, slave); buf_set_u32(addr_buf, 0, 1, mode); buf_set_u32(addr_buf, 1, 30, addr >> 2); fields[0].num_bits = 31; fields[0].in_value = NULL; fields[0].out_value = addr_buf; fields[1].num_bits = 4; fields[1].in_value = busy_buf; fields[1].out_value = slave_buf; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: setting address failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 1, 1); } while (busy); return ERROR_OK; } int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info, uint32_t *pdata) { struct scan_field fields[2]; uint8_t data_buf[4]; uint8_t busy_buf[4]; int busy; do { memset(data_buf, 0, sizeof(data_buf)); memset(busy_buf, 0, sizeof(busy_buf)); fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = data_buf; fields[1].num_bits = 3; fields[1].in_value = busy_buf; fields[1].out_value = NULL; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: reading data failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 0, 1); } while (busy); *pdata = buf_get_u32(data_buf, 0, 32); return ERROR_OK; } int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info, uint32_t data) { struct scan_field fields[2]; uint8_t data_buf[4]; uint8_t busy_buf[4]; uint8_t zero_buf[4]; int busy; do { memset(data_buf, 0, sizeof(data_buf)); memset(busy_buf, 0, sizeof(busy_buf)); memset(zero_buf, 0, sizeof(zero_buf)); buf_set_u32(data_buf, 0, 32, data); fields[0].num_bits = 3; fields[0].in_value = busy_buf; fields[0].out_value = zero_buf; fields[1].num_bits = 32; fields[1].out_value = data_buf; fields[1].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("%s: reading data failed", __func__); return ERROR_FAIL; } busy = buf_get_u32(busy_buf, 0, 1); } while (busy); return ERROR_OK; } int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave, uint32_t addr, uint32_t *value) { avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS); avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_READ); avr32_jtag_mwa_read_data(jtag_info, value); return ERROR_OK; } int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave, uint32_t addr, uint32_t value) { avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS); avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_WRITE); avr32_jtag_mwa_write_data(jtag_info, value); return ERROR_OK; } int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst) { int retval; uint32_t ds; retval = avr32_jtag_nexus_write(jtag_info, AVR32_OCDREG_DINST, inst); if (retval != ERROR_OK) return retval; do { retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DS, &ds); if (retval != ERROR_OK) return retval; } while ((ds & OCDREG_DS_DBA) && !(ds & OCDREG_DS_INC)); return ERROR_OK; } int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits) { uint32_t value; int res; res = avr32_jtag_nexus_read(jtag, reg, &value); if (res) return res; value |= bits; res = avr32_jtag_nexus_write(jtag, reg, value); if (res) return res; return ERROR_OK; } int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits) { uint32_t value; int res; res = avr32_jtag_nexus_read(jtag, reg, &value); if (res) return res; value &= ~bits; res = avr32_jtag_nexus_write(jtag, reg, value); if (res) return res; return ERROR_OK; } openocd-0.9.0/src/target/avr32_jtag.h0000644000175000017500000000730512315575361014275 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef AVR32_JTAG #define AVR32_JTAG #define AVR32NUMCOREREGS 17 /* tap instructions */ #define AVR32_INST_IDCODE 0x01 #define AVR32_INST_NEXUS_ACCESS 0x10 #define AVR32_INST_MW_ACCESS 0x11 #define AVR32_INST_MB_ACCESS 0x12 #define SLAVE_OCD 0x01 #define SLAVE_HSB_CACHED 0x04 #define SLAVE_HSB_UNCACHED 0x05 /* * Registers */ #define AVR32_OCDREG_DID 0x00 #define AVR32_OCDREG_DC 0x02 #define OCDREG_DC_SS (1 << 8) #define OCDREG_DC_DBR (1 << 12) #define OCDREG_DC_DBE (1 << 13) #define OCDREG_DC_SQA (1 << 22) #define OCDREG_DC_RES (1 << 30) #define OCDREG_DC_ABORT (1 << 31) #define AVR32_OCDREG_DS 0x04 #define OCDREG_DS_SSS (1 << 0) #define OCDREG_DS_SWB (1 << 1) #define OCDREG_DS_HWB (1 << 2) #define OCDREG_DS_STP (1 << 4) #define OCDREG_DS_DBS (1 << 5) #define OCDREG_DS_BP_SHIFT 8 #define OCDREG_DS_BP_MASK 0xff #define OCDREG_DS_INC (1 << 24) #define OCDREG_DS_BOZ (1 << 25) #define OCDREG_DS_DBA (1 << 26) #define OCDREG_DS_EXB (1 << 27) #define OCDREG_DS_NTBF (1 << 28) #define AVR32_OCDREG_DINST 0x41 #define AVR32_OCDREG_DPC 0x42 #define AVR32_OCDREG_DCCPU 0x44 #define AVR32_OCDREG_DCEMU 0x45 #define AVR32_OCDREG_DCSR 0x46 #define OCDREG_DCSR_CPUD (1 << 0) #define OCDREG_DCSR_EMUD (1 << 1) /* * Direction bit */ #define MODE_WRITE 0x00 #define MODE_READ 0x01 /* * Some instructions */ #define RETD 0xd703d623 #define MTDR(dreg, reg) (0xe7b00044 | ((reg) << 16) | dreg) #define MFDR(reg, dreg) (0xe5b00044 | ((reg) << 16) | dreg) #define MTSR(sysreg, reg) (0xe3b00002 | ((reg) << 16) | sysreg) #define MFSR(reg, sysreg) (0xe1b00002 | ((reg) << 16) | sysreg) struct avr32_jtag { struct jtag_tap *tap; uint32_t dpc; /* Debug PC value */ }; int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info, uint32_t addr, uint32_t *value); int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info, uint32_t addr, uint32_t value); int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave, uint32_t addr, uint32_t *value); int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave, uint32_t addr, uint32_t value); int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits); int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits); int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst); #endif /* AVR32_JTAG */ openocd-0.9.0/src/target/target_type.h0000644000175000017500000002610412516456304014656 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TARGET_TYPE_H #define TARGET_TYPE_H #include struct target; /** * This holds methods shared between all instances of a given target * type. For example, all Cortex-M3 targets on a scan chain share * the same method table. */ struct target_type { /** * Name of this type of target. Do @b not access this * field directly, use target_type_name() instead. */ const char *name; const char *deprecated_name; /* poll current target status */ int (*poll)(struct target *target); /* Invoked only from target_arch_state(). * Issue USER() w/architecture specific status. */ int (*arch_state)(struct target *target); /* target request support */ int (*target_request_data)(struct target *target, uint32_t size, uint8_t *buffer); /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); int (*resume)(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); int (*step)(struct target *target, int current, uint32_t address, int handle_breakpoints); /* target reset control. assert reset can be invoked when OpenOCD and * the target is out of sync. * * A typical example is that the target was power cycled while OpenOCD * thought the target was halted or running. * * assert_reset() can therefore make no assumptions whatsoever about the * state of the target * * Before assert_reset() for the target is invoked, a TRST/tms and * chain validation is executed. TRST should not be asserted * during target assert unless there is no way around it due to * the way reset's are configured. * */ int (*assert_reset)(struct target *target); /** * The implementation is responsible for polling the * target such that target->state reflects the * state correctly. * * Otherwise the following would fail, as there will not * be any "poll" invoked inbetween the "reset run" and * "halt". * * reset run; halt */ int (*deassert_reset)(struct target *target); int (*soft_reset_halt)(struct target *target); /** * Target register access for GDB. Do @b not call this function * directly, use target_get_gdb_reg_list() instead. * * Danger! this function will succeed even if the target is running * and return a register list with dummy values. * * The reason is that GDB connection will fail without a valid register * list, however it is after GDB is connected that monitor commands can * be run to properly initialize the target */ int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); /* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) * count: number of items of */ /** * Target memory read callback. Do @b not call this function * directly, use target_read_memory() instead. */ int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Target memory write callback. Do @b not call this function * directly, use target_write_memory() instead. */ int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ int (*read_buffer)(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ int (*write_buffer)(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer); int (*checksum_memory)(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int (*blank_check_memory)(struct target *target, uint32_t address, uint32_t count, uint32_t *blank); /* * target break-/watchpoint control * rw: 0 = write, 1 = read, 2 = access * * Target must be halted while this is invoked as this * will actually set up breakpoints on target. * * The breakpoint hardware will be set up upon adding the * first breakpoint. * * Upon GDB connection all breakpoints/watchpoints are cleared. */ int (*add_breakpoint)(struct target *target, struct breakpoint *breakpoint); int (*add_context_breakpoint)(struct target *target, struct breakpoint *breakpoint); int (*add_hybrid_breakpoint)(struct target *target, struct breakpoint *breakpoint); /* remove breakpoint. hw will only be updated if the target * is currently halted. * However, this method can be invoked on unresponsive targets. */ int (*remove_breakpoint)(struct target *target, struct breakpoint *breakpoint); /* add watchpoint ... see add_breakpoint() comment above. */ int (*add_watchpoint)(struct target *target, struct watchpoint *watchpoint); /* remove watchpoint. hw will only be updated if the target * is currently halted. * However, this method can be invoked on unresponsive targets. */ int (*remove_watchpoint)(struct target *target, struct watchpoint *watchpoint); /* Find out just hit watchpoint. After the target hits a watchpoint, the * information could assist gdb to locate where the modified/accessed memory is. */ int (*hit_watchpoint)(struct target *target, struct watchpoint **hit_watchpoint); /** * Target algorithm support. Do @b not call this method directly, * use target_run_algorithm() instead. */ int (*run_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); int (*start_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, void *arch_info); int (*wait_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t exit_point, int timeout_ms, void *arch_info); const struct command_registration *commands; /* called when target is created */ int (*target_create)(struct target *target, Jim_Interp *interp); /* called for various config parameters */ /* returns JIM_CONTINUE - if option not understood */ /* otherwise: JIM_OK, or JIM_ERR, */ int (*target_jim_configure)(struct target *target, Jim_GetOptInfo *goi); /* target commands specifically handled by the target */ /* returns JIM_OK, or JIM_ERR, or JIM_CONTINUE - if option not understood */ int (*target_jim_commands)(struct target *target, Jim_GetOptInfo *goi); /** * This method is used to perform target setup that requires * JTAG access. * * This may be called multiple times. It is called after the * scan chain is initially validated, or later after the target * is enabled by a JRC. It may also be called during some * parts of the reset sequence. * * For one-time initialization tasks, use target_was_examined() * and target_set_examined(). For example, probe the hardware * before setting up chip-specific state, and then set that * flag so you don't do that again. */ int (*examine)(struct target *target); /* Set up structures for target. * * It is illegal to talk to the target at this stage as this fn is invoked * before the JTAG chain has been examined/verified * */ int (*init_target)(struct command_context *cmd_ctx, struct target *target); /** * Free all the resources allocated by the target. * * @param target The target to deinit */ void (*deinit_target)(struct target *target); /* translate from virtual to physical address. Default implementation is successful * no-op(i.e. virtual==physical). */ int (*virt2phys)(struct target *target, uint32_t address, uint32_t *physical); /* read directly from physical memory. caches are bypassed and untouched. * * If the target does not support disabling caches, leaving them untouched, * then minimally the actual physical memory location will be read even * if cache states are unchanged, flushed, etc. * * Default implementation is to call read_memory. */ int (*read_phys_memory)(struct target *target, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); /* * same as read_phys_memory, except that it writes... */ int (*write_phys_memory)(struct target *target, uint32_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); int (*mmu)(struct target *target, int *enabled); /* after reset is complete, the target can check if things are properly set up. * * This can be used to check if e.g. DCC memory writes have been enabled for * arm7/9 targets, which they really should except in the most contrived * circumstances. */ int (*check_reset)(struct target *target); /* get GDB file-I/O parameters from target */ int (*get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info); /* pass GDB file-I/O response to target */ int (*gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c); /* do target profiling */ int (*profiling)(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); }; #endif /* TARGET_TYPE_H */ openocd-0.9.0/src/target/embeddedice.c0000644000175000017500000004425712516456303014544 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "embeddedice.h" #include "register.h" /** * @file * * This provides lowlevel glue to the EmbeddedICE (or EmbeddedICE-RT) * module found on scan chain 2 in ARM7, ARM9, and some other families * of ARM cores. The module is called "EmbeddedICE-RT" if it has * monitor mode support. * * EmbeddedICE provides basic watchpoint/breakpoint hardware and a Debug * Communications Channel (DCC) used to read or write 32-bit words to * OpenOCD-aware code running on the target CPU. * Newer modules also include vector catch hardware. Some versions * support hardware single-stepping, "monitor mode" debug (which is not * currently supported by OpenOCD), or extended reporting on why the * core entered debug mode. */ static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf); /* * From: ARM9E-S TRM, DDI 0165, table C-4 (and similar, for other cores) */ static const struct { const char *name; unsigned short addr; unsigned short width; } eice_regs[] = { [EICE_DBG_CTRL] = { .name = "debug_ctrl", .addr = 0, /* width is assigned based on EICE version */ }, [EICE_DBG_STAT] = { .name = "debug_status", .addr = 1, /* width is assigned based on EICE version */ }, [EICE_COMMS_CTRL] = { .name = "comms_ctrl", .addr = 4, .width = 6, }, [EICE_COMMS_DATA] = { .name = "comms_data", .addr = 5, .width = 32, }, [EICE_W0_ADDR_VALUE] = { .name = "watch_0_addr_value", .addr = 8, .width = 32, }, [EICE_W0_ADDR_MASK] = { .name = "watch_0_addr_mask", .addr = 9, .width = 32, }, [EICE_W0_DATA_VALUE] = { .name = "watch_0_data_value", .addr = 10, .width = 32, }, [EICE_W0_DATA_MASK] = { .name = "watch_0_data_mask", .addr = 11, .width = 32, }, [EICE_W0_CONTROL_VALUE] = { .name = "watch_0_control_value", .addr = 12, .width = 9, }, [EICE_W0_CONTROL_MASK] = { .name = "watch_0_control_mask", .addr = 13, .width = 8, }, [EICE_W1_ADDR_VALUE] = { .name = "watch_1_addr_value", .addr = 16, .width = 32, }, [EICE_W1_ADDR_MASK] = { .name = "watch_1_addr_mask", .addr = 17, .width = 32, }, [EICE_W1_DATA_VALUE] = { .name = "watch_1_data_value", .addr = 18, .width = 32, }, [EICE_W1_DATA_MASK] = { .name = "watch_1_data_mask", .addr = 19, .width = 32, }, [EICE_W1_CONTROL_VALUE] = { .name = "watch_1_control_value", .addr = 20, .width = 9, }, [EICE_W1_CONTROL_MASK] = { .name = "watch_1_control_mask", .addr = 21, .width = 8, }, /* vector_catch isn't always present */ [EICE_VEC_CATCH] = { .name = "vector_catch", .addr = 2, .width = 8, }, }; static int embeddedice_get_reg(struct reg *reg) { int retval = embeddedice_read_reg(reg); if (retval != ERROR_OK) { LOG_ERROR("error queueing EmbeddedICE register read"); return retval; } retval = jtag_execute_queue(); if (retval != ERROR_OK) LOG_ERROR("EmbeddedICE register read failed"); return retval; } static const struct reg_arch_type eice_reg_type = { .get = embeddedice_get_reg, .set = embeddedice_set_reg_w_exec, }; /** * Probe EmbeddedICE module and set up local records of its registers. * Different versions of the modules have different capabilities, such as * hardware support for vector_catch, single stepping, and monitor mode. */ struct reg_cache *embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9) { int retval; struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct embeddedice_reg *arch_info = NULL; struct arm_jtag *jtag_info = &arm7_9->jtag_info; int num_regs = ARRAY_SIZE(eice_regs); int i; int eice_version = 0; /* vector_catch isn't always present */ if (!arm7_9->has_vector_catch) num_regs--; /* the actual registers are kept in two arrays */ reg_list = calloc(num_regs, sizeof(struct reg)); arch_info = calloc(num_regs, sizeof(struct embeddedice_reg)); /* fill in values for the reg cache */ reg_cache->name = "EmbeddedICE registers"; reg_cache->next = NULL; reg_cache->reg_list = reg_list; reg_cache->num_regs = num_regs; /* FIXME the second watchpoint unit on Feroceon and Dragonite * seems not to work ... we should have a way to not set up * its four registers here! */ /* set up registers */ for (i = 0; i < num_regs; i++) { reg_list[i].name = eice_regs[i].name; reg_list[i].size = eice_regs[i].width; reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].value = calloc(1, 4); reg_list[i].arch_info = &arch_info[i]; reg_list[i].type = &eice_reg_type; arch_info[i].addr = eice_regs[i].addr; arch_info[i].jtag_info = jtag_info; } /* identify EmbeddedICE version by reading DCC control register */ embeddedice_read_reg(®_list[EICE_COMMS_CTRL]); retval = jtag_execute_queue(); if (retval != ERROR_OK) { for (i = 0; i < num_regs; i++) free(reg_list[i].value); free(reg_list); free(reg_cache); free(arch_info); return NULL; } eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4); LOG_INFO("Embedded ICE version %d", eice_version); switch (eice_version) { case 1: /* ARM7TDMI r3, ARM7TDMI-S r3 * * REVISIT docs say ARM7TDMI-S r4 uses version 1 but * that it has 6-bit CTRL and 5-bit STAT... doc bug? * ARM7TDMI r4 docs say EICE v4. */ reg_list[EICE_DBG_CTRL].size = 3; reg_list[EICE_DBG_STAT].size = 5; break; case 2: /* ARM9TDMI */ reg_list[EICE_DBG_CTRL].size = 4; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; break; case 3: LOG_ERROR("EmbeddedICE v%d handling might be broken", eice_version); reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; arm7_9->has_monitor_mode = 1; break; case 4: /* ARM7TDMI r4 */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_monitor_mode = 1; break; case 5: /* ARM9E-S rev 1 */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_single_step = 1; arm7_9->has_monitor_mode = 1; break; case 6: /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */ reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 10; /* DBG_STAT has MOE bits */ arm7_9->has_monitor_mode = 1; break; case 7: LOG_ERROR("EmbeddedICE v%d handling might be broken", eice_version); reg_list[EICE_DBG_CTRL].size = 6; reg_list[EICE_DBG_STAT].size = 5; arm7_9->has_monitor_mode = 1; break; default: /* * The Feroceon implementation has the version number * in some unusual bits. Let feroceon.c validate it * and do the appropriate setup itself. */ if (strcmp(target_type_name(target), "feroceon") == 0 || strcmp(target_type_name(target), "dragonite") == 0) break; LOG_ERROR("unknown EmbeddedICE version " "(comms ctrl: 0x%8.8" PRIx32 ")", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32)); } /* On Feroceon and Dragonite the second unit is seemingly missing. */ LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s", target_name(target), arm7_9->wp_available_max, (arm7_9->wp_available_max != 1) ? "s" : ""); return reg_cache; } /** * Initialize EmbeddedICE module, if needed. */ int embeddedice_setup(struct target *target) { int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); /* Explicitly disable monitor mode. For now we only support halting * debug ... we don't know how to talk with a resident debug monitor * that manages break requests. ARM's "Angel Debug Monitor" is one * common example of such code. */ if (arm7_9->has_monitor_mode) { struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; embeddedice_read_reg(dbg_ctrl); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; buf_set_u32(dbg_ctrl->value, 4, 1, 0); embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value); } return jtag_execute_queue(); } /** * Queue a read for an EmbeddedICE register into the register cache, * optionally checking the value read. * Note that at this level, all registers are 32 bits wide. */ int embeddedice_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask) { struct embeddedice_reg *ice_reg = reg->arch_info; uint8_t reg_addr = ice_reg->addr & 0x1f; struct scan_field fields[3]; uint8_t field1_out[1]; uint8_t field2_out[1]; int retval; retval = arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; /* bits 31:0 -- data (ignored here) */ fields[0].num_bits = 32; fields[0].out_value = reg->value; fields[0].in_value = NULL; fields[0].check_value = NULL; fields[0].check_mask = NULL; /* bits 36:32 -- register */ fields[1].num_bits = 5; fields[1].out_value = field1_out; field1_out[0] = reg_addr; fields[1].in_value = NULL; fields[1].check_value = NULL; fields[1].check_mask = NULL; /* bit 37 -- 0/read */ fields[2].num_bits = 1; fields[2].out_value = field2_out; field2_out[0] = 0; fields[2].in_value = NULL; fields[2].check_value = NULL; fields[2].check_mask = NULL; /* traverse Update-DR, setting address for the next read */ jtag_add_dr_scan(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE); /* bits 31:0 -- the data we're reading (and maybe checking) */ fields[0].in_value = reg->value; fields[0].check_value = check_value; fields[0].check_mask = check_mask; /* when reading the DCC data register, leaving the address field set to * EICE_COMMS_DATA would read the register twice * reading the control register is safe */ field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr; /* traverse Update-DR, reading but with no other side effects */ jtag_add_dr_scan_check(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE); return ERROR_OK; } /** * Receive a block of size 32-bit words from the DCC. * We assume the target is always going to be fast enough (relative to * the JTAG clock) that the debugger won't need to poll the handshake * bit. The JTAG clock is usually at least six times slower than the * functional clock, so the 50+ JTAG clocks needed to receive the word * allow hundreds of instruction cycles (per word) in the target. */ int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size) { struct scan_field fields[3]; uint8_t field1_out[1]; uint8_t field2_out[1]; int retval; retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = NULL; fields[1].num_bits = 5; fields[1].out_value = field1_out; field1_out[0] = eice_regs[EICE_COMMS_DATA].addr; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = field2_out; field2_out[0] = 0; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); while (size > 0) { /* when reading the last item, set the register address to the DCC control reg, * to avoid reading additional data from the DCC data reg */ if (size == 1) field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr; fields[0].in_value = (uint8_t *)data; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)data); data++; size--; } return jtag_execute_queue(); } /** * Queue a read for an EmbeddedICE register into the register cache, * not checking the value read. */ int embeddedice_read_reg(struct reg *reg) { return embeddedice_read_reg_w_check(reg, NULL, NULL); } /** * Queue a write for an EmbeddedICE register, updating the register cache. * Uses embeddedice_write_reg(). */ void embeddedice_set_reg(struct reg *reg, uint32_t value) { embeddedice_write_reg(reg, value); buf_set_u32(reg->value, 0, reg->size, value); reg->valid = 1; reg->dirty = 0; } /** * Write an EmbeddedICE register, updating the register cache. * Uses embeddedice_set_reg(); not queued. */ static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf) { int retval; embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size)); retval = jtag_execute_queue(); if (retval != ERROR_OK) LOG_ERROR("register write failed"); return retval; } /** * Queue a write for an EmbeddedICE register, bypassing the register cache. */ void embeddedice_write_reg(struct reg *reg, uint32_t value) { struct embeddedice_reg *ice_reg = reg->arch_info; LOG_DEBUG("%i: 0x%8.8" PRIx32 "", ice_reg->addr, value); arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE); arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE); uint8_t reg_addr = ice_reg->addr & 0x1f; embeddedice_write_reg_inner(ice_reg->jtag_info->tap, reg_addr, value); } /** * Queue a write for an EmbeddedICE register, using cached value. * Uses embeddedice_write_reg(). */ void embeddedice_store_reg(struct reg *reg) { embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size)); } /** * Send a block of size 32-bit words to the DCC. * We assume the target is always going to be fast enough (relative to * the JTAG clock) that the debugger won't need to poll the handshake * bit. The JTAG clock is usually at least six times slower than the * functional clock, so the 50+ JTAG clocks needed to receive the word * allow hundreds of instruction cycles (per word) in the target. */ int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size) { struct scan_field fields[3]; uint8_t field0_out[4]; uint8_t field1_out[1]; uint8_t field2_out[1]; int retval; retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = field0_out; fields[0].in_value = NULL; fields[1].num_bits = 5; fields[1].out_value = field1_out; field1_out[0] = eice_regs[EICE_COMMS_DATA].addr; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = field2_out; field2_out[0] = 1; fields[2].in_value = NULL; while (size > 0) { buf_set_u32(field0_out, 0, 32, *data); jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); data++; size--; } /* call to jtag_execute_queue() intentionally omitted */ return ERROR_OK; } /** * Poll DCC control register until read or write handshake completes. */ int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout) { struct scan_field fields[3]; uint8_t field0_in[4]; uint8_t field1_out[1]; uint8_t field2_out[1]; int retval; uint32_t hsact; struct timeval lap; struct timeval now; if (hsbit == EICE_COMM_CTRL_WBIT) hsact = 1; else if (hsbit == EICE_COMM_CTRL_RBIT) hsact = 0; else { LOG_ERROR("Invalid arguments"); return ERROR_COMMAND_SYNTAX_ERROR; } retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = field0_in; fields[1].num_bits = 5; fields[1].out_value = field1_out; field1_out[0] = eice_regs[EICE_COMMS_DATA].addr; fields[1].in_value = NULL; fields[2].num_bits = 1; fields[2].out_value = field2_out; field2_out[0] = 0; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); gettimeofday(&lap, NULL); do { jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (buf_get_u32(field0_in, hsbit, 1) == hsact) return ERROR_OK; gettimeofday(&now, NULL); } while ((uint32_t)((now.tv_sec - lap.tv_sec) * 1000 + (now.tv_usec - lap.tv_usec) / 1000) <= timeout); LOG_ERROR("embeddedice handshake timeout"); return ERROR_TARGET_TIMEOUT; } #ifndef HAVE_JTAG_MINIDRIVER_H /** * This is an inner loop of the open loop DCC write of data to target */ void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count) { int i; for (i = 0; i < count; i++) { embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little)); buffer += 4; } } #else /* provided by minidriver */ #endif openocd-0.9.0/src/target/embeddedice.h0000644000175000017500000001065712315575361014551 00000000000000/*************************************************************************** * Copyright (C) 2005, 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef EMBEDDED_ICE_H #define EMBEDDED_ICE_H #include "arm7_9_common.h" enum { EICE_DBG_CTRL = 0, EICE_DBG_STAT = 1, EICE_COMMS_CTRL = 2, EICE_COMMS_DATA = 3, EICE_W0_ADDR_VALUE = 4, EICE_W0_ADDR_MASK = 5, EICE_W0_DATA_VALUE = 6, EICE_W0_DATA_MASK = 7, EICE_W0_CONTROL_VALUE = 8, EICE_W0_CONTROL_MASK = 9, EICE_W1_ADDR_VALUE = 10, EICE_W1_ADDR_MASK = 11, EICE_W1_DATA_VALUE = 12, EICE_W1_DATA_MASK = 13, EICE_W1_CONTROL_VALUE = 14, EICE_W1_CONTROL_MASK = 15, EICE_VEC_CATCH = 16 }; enum { EICE_DBG_CONTROL_ICEDIS = 5, EICE_DBG_CONTROL_MONEN = 4, EICE_DBG_CONTROL_INTDIS = 2, EICE_DBG_CONTROL_DBGRQ = 1, EICE_DBG_CONTROL_DBGACK = 0, }; enum { EICE_DBG_STATUS_IJBIT = 5, EICE_DBG_STATUS_ITBIT = 4, EICE_DBG_STATUS_SYSCOMP = 3, EICE_DBG_STATUS_IFEN = 2, EICE_DBG_STATUS_DBGRQ = 1, EICE_DBG_STATUS_DBGACK = 0 }; enum { EICE_W_CTRL_ENABLE = 0x100, EICE_W_CTRL_RANGE = 0x80, EICE_W_CTRL_CHAIN = 0x40, EICE_W_CTRL_EXTERN = 0x20, EICE_W_CTRL_nTRANS = 0x10, EICE_W_CTRL_nOPC = 0x8, EICE_W_CTRL_MAS = 0x6, EICE_W_CTRL_ITBIT = 0x2, EICE_W_CTRL_nRW = 0x1 }; enum { EICE_COMM_CTRL_WBIT = 1, EICE_COMM_CTRL_RBIT = 0 }; struct embeddedice_reg { int addr; struct arm_jtag *jtag_info; }; struct reg_cache *embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9); int embeddedice_setup(struct target *target); int embeddedice_read_reg(struct reg *reg); int embeddedice_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask); void embeddedice_write_reg(struct reg *reg, uint32_t value); void embeddedice_store_reg(struct reg *reg); void embeddedice_set_reg(struct reg *reg, uint32_t value); int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size); int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size); int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout); /* If many embeddedice_write_reg() follow eachother, then the >1 invocations can be * this faster version of embeddedice_write_reg */ static inline void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_addr, uint32_t value) { uint8_t out_reg_addr = (1 << 5) | reg_addr; uint8_t out_value[4]; buf_set_u32(out_value, 0, 32, value); struct scan_field fields[2] = { { .num_bits = 32, .out_value = out_value }, { .num_bits = 6, .out_value = &out_reg_addr }, }; jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); } void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count); #endif /* EMBEDDED_ICE_H */ openocd-0.9.0/src/target/nds32.c0000644000175000017500000023741412516456304013263 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "nds32.h" #include "nds32_aice.h" #include "nds32_tlb.h" #include "nds32_disassembler.h" const int NDS32_BREAK_16 = 0x00EA; /* 0xEA00 */ const int NDS32_BREAK_32 = 0x0A000064; /* 0x6400000A */ struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM]; uint32_t nds32_edm_ops_num; const char *nds32_debug_type_name[11] = { "SOFTWARE BREAK", "SOFTWARE BREAK_16", "HARDWARE BREAKPOINT", "DATA ADDR WATCHPOINT PRECISE", "DATA VALUE WATCHPOINT PRECISE", "DATA VALUE WATCHPOINT IMPRECISE", "DEBUG INTERRUPT", "HARDWARE SINGLE STEP", "DATA ADDR WATCHPOINT NEXT PRECISE", "DATA VALUE WATCHPOINT NEXT PRECISE", "LOAD STORE GLOBAL STOP", }; static const int NDS32_LM_SIZE_TABLE[16] = { 4 * 1024, 8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024, 512 * 1024, 1024 * 1024, 1 * 1024, 2 * 1024, }; static const int NDS32_LINE_SIZE_TABLE[6] = { 0, 8, 16, 32, 64, 128, }; static int nds32_get_core_reg(struct reg *reg) { int retval; struct nds32_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (reg->valid) { uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); LOG_DEBUG("reading register(cached) %" PRIi32 "(%s), value: 0x%8.8" PRIx32, reg_arch_info->num, reg->name, val); return ERROR_OK; } int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num); if (reg_arch_info->enable == false) { buf_set_u32(reg_arch_info->value, 0, 32, NDS32_REGISTER_DISABLE); retval = ERROR_FAIL; } else { uint32_t val = 0; if ((nds32->fpu_enable == false) && (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; } else if ((nds32->audio_enable == false) && (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; } else { retval = aice_read_register(aice, mapped_regnum, &val); } buf_set_u32(reg_arch_info->value, 0, 32, val); LOG_DEBUG("reading register %" PRIi32 "(%s), value: 0x%8.8" PRIx32, reg_arch_info->num, reg->name, val); } if (retval == ERROR_OK) { reg->valid = true; reg->dirty = false; } return retval; } static int nds32_get_core_reg_64(struct reg *reg) { int retval; struct nds32_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (reg->valid) return ERROR_OK; if (reg_arch_info->enable == false) { buf_set_u64(reg_arch_info->value, 0, 64, NDS32_REGISTER_DISABLE); retval = ERROR_FAIL; } else { uint64_t val = 0; if ((nds32->fpu_enable == false) && ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) { retval = ERROR_OK; } else { retval = aice_read_reg_64(aice, reg_arch_info->num, &val); } buf_set_u64(reg_arch_info->value, 0, 64, val); } if (retval == ERROR_OK) { reg->valid = true; reg->dirty = false; } return retval; } static int nds32_update_psw(struct nds32 *nds32) { uint32_t value_ir0; struct aice_port_s *aice = target_to_aice(nds32->target); nds32_get_mapped_reg(nds32, IR0, &value_ir0); /* Save data memory endian */ if ((value_ir0 >> 5) & 0x1) { nds32->data_endian = TARGET_BIG_ENDIAN; aice_set_data_endian(aice, AICE_BIG_ENDIAN); } else { nds32->data_endian = TARGET_LITTLE_ENDIAN; aice_set_data_endian(aice, AICE_LITTLE_ENDIAN); } /* Save translation status */ nds32->memory.address_translation = ((value_ir0 >> 7) & 0x1) ? true : false; return ERROR_OK; } static int nds32_update_mmu_info(struct nds32 *nds32) { uint32_t value; /* Update MMU control status */ nds32_get_mapped_reg(nds32, MR0, &value); nds32->mmu_config.default_min_page_size = value & 0x1; nds32->mmu_config.multiple_page_size_in_use = (value >> 10) & 0x1; return ERROR_OK; } static int nds32_update_cache_info(struct nds32 *nds32) { uint32_t value; if (ERROR_OK == nds32_get_mapped_reg(nds32, MR8, &value)) { if (value & 0x1) nds32->memory.icache.enable = true; else nds32->memory.icache.enable = false; if (value & 0x2) nds32->memory.dcache.enable = true; else nds32->memory.dcache.enable = false; } else { nds32->memory.icache.enable = false; nds32->memory.dcache.enable = false; } return ERROR_OK; } static int nds32_update_lm_info(struct nds32 *nds32) { struct nds32_memory *memory = &(nds32->memory); uint32_t value_mr6; uint32_t value_mr7; nds32_get_mapped_reg(nds32, MR6, &value_mr6); if (value_mr6 & 0x1) memory->ilm_enable = true; else memory->ilm_enable = false; if (memory->ilm_align_ver == 0) { /* 1MB aligned */ memory->ilm_start = value_mr6 & 0xFFF00000; memory->ilm_end = memory->ilm_start + memory->ilm_size; } else if (memory->ilm_align_ver == 1) { /* aligned to local memory size */ memory->ilm_start = value_mr6 & 0xFFFFFC00; memory->ilm_end = memory->ilm_start + memory->ilm_size; } else { memory->ilm_start = -1; memory->ilm_end = -1; } nds32_get_mapped_reg(nds32, MR7, &value_mr7); if (value_mr7 & 0x1) memory->dlm_enable = true; else memory->dlm_enable = false; if (memory->dlm_align_ver == 0) { /* 1MB aligned */ memory->dlm_start = value_mr7 & 0xFFF00000; memory->dlm_end = memory->dlm_start + memory->dlm_size; } else if (memory->dlm_align_ver == 1) { /* aligned to local memory size */ memory->dlm_start = value_mr7 & 0xFFFFFC00; memory->dlm_end = memory->dlm_start + memory->dlm_size; } else { memory->dlm_start = -1; memory->dlm_end = -1; } return ERROR_OK; } /** * If fpu/audio is disabled, to access fpu/audio registers will cause * exceptions. So, we need to check if fpu/audio is enabled or not as * target is halted. If fpu/audio is disabled, as users access fpu/audio * registers, OpenOCD will return fake value 0 instead of accessing * registers through DIM. */ static int nds32_check_extension(struct nds32 *nds32) { uint32_t value; nds32_get_mapped_reg(nds32, FUCPR, &value); if (value == NDS32_REGISTER_DISABLE) { nds32->fpu_enable = false; nds32->audio_enable = false; return ERROR_OK; } if (value & 0x1) nds32->fpu_enable = true; else nds32->fpu_enable = false; if (value & 0x80000000) nds32->audio_enable = true; else nds32->audio_enable = false; return ERROR_OK; } static int nds32_set_core_reg(struct reg *reg, uint8_t *buf) { struct nds32_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num); /* ignore values that will generate exception */ if (nds32_reg_exception(mapped_regnum, value)) return ERROR_OK; LOG_DEBUG("writing register %" PRIi32 "(%s) with value 0x%8.8" PRIx32, reg_arch_info->num, reg->name, value); if ((nds32->fpu_enable == false) && (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) { buf_set_u32(reg->value, 0, 32, 0); } else if ((nds32->audio_enable == false) && (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { buf_set_u32(reg->value, 0, 32, 0); } else { buf_set_u32(reg->value, 0, 32, value); uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); aice_write_register(aice, mapped_regnum, val); /* After set value to registers, read the value from target * to avoid W1C inconsistency. */ aice_read_register(aice, mapped_regnum, &val); buf_set_u32(reg_arch_info->value, 0, 32, val); } reg->valid = true; reg->dirty = false; /* update registers to take effect right now */ if (IR0 == mapped_regnum) { nds32_update_psw(nds32); } else if (MR0 == mapped_regnum) { nds32_update_mmu_info(nds32); } else if ((MR6 == mapped_regnum) || (MR7 == mapped_regnum)) { /* update lm information */ nds32_update_lm_info(nds32); } else if (MR8 == mapped_regnum) { nds32_update_cache_info(nds32); } else if (FUCPR == mapped_regnum) { /* update audio/fpu setting */ nds32_check_extension(nds32); } return ERROR_OK; } static int nds32_set_core_reg_64(struct reg *reg, uint8_t *buf) { struct nds32_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; struct nds32 *nds32 = target_to_nds32(target); uint32_t low_part = buf_get_u32(buf, 0, 32); uint32_t high_part = buf_get_u32(buf, 32, 32); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((nds32->fpu_enable == false) && ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) { buf_set_u32(reg->value, 0, 32, 0); buf_set_u32(reg->value, 32, 32, 0); reg->valid = true; reg->dirty = false; } else { buf_set_u32(reg->value, 0, 32, low_part); buf_set_u32(reg->value, 32, 32, high_part); reg->valid = true; reg->dirty = true; } return ERROR_OK; } static const struct reg_arch_type nds32_reg_access_type = { .get = nds32_get_core_reg, .set = nds32_set_core_reg, }; static const struct reg_arch_type nds32_reg_access_type_64 = { .get = nds32_get_core_reg_64, .set = nds32_set_core_reg_64, }; static struct reg_cache *nds32_build_reg_cache(struct target *target, struct nds32 *nds32) { struct reg_cache *cache = calloc(sizeof(struct reg_cache), 1); struct reg *reg_list = calloc(TOTAL_REG_NUM, sizeof(struct reg)); struct nds32_reg *reg_arch_info = calloc(TOTAL_REG_NUM, sizeof(struct nds32_reg)); int i; if (!cache || !reg_list || !reg_arch_info) { free(cache); free(reg_list); free(reg_arch_info); return NULL; } cache->name = "Andes registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = 0; for (i = 0; i < TOTAL_REG_NUM; i++) { reg_arch_info[i].num = i; reg_arch_info[i].target = target; reg_arch_info[i].nds32 = nds32; reg_arch_info[i].enable = false; reg_list[i].name = nds32_reg_simple_name(i); reg_list[i].number = reg_arch_info[i].num; reg_list[i].size = nds32_reg_size(i); reg_list[i].arch_info = ®_arch_info[i]; reg_list[i].reg_data_type = calloc(sizeof(struct reg_data_type), 1); if (FD0 <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) { reg_list[i].value = reg_arch_info[i].value; reg_list[i].type = &nds32_reg_access_type_64; reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE; reg_list[i].reg_data_type->id = "ieee_double"; reg_list[i].group = "float"; } else { reg_list[i].value = reg_arch_info[i].value; reg_list[i].type = &nds32_reg_access_type; reg_list[i].group = "general"; if ((FS0 <= reg_arch_info[i].num) && (reg_arch_info[i].num <= FS31)) { reg_list[i].reg_data_type->type = REG_TYPE_IEEE_SINGLE; reg_list[i].reg_data_type->id = "ieee_single"; reg_list[i].group = "float"; } else if ((reg_arch_info[i].num == FPCSR) || (reg_arch_info[i].num == FPCFG)) { reg_list[i].group = "float"; } else if ((reg_arch_info[i].num == R28) || (reg_arch_info[i].num == R29) || (reg_arch_info[i].num == R31)) { reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR; reg_list[i].reg_data_type->id = "data_ptr"; } else if ((reg_arch_info[i].num == R30) || (reg_arch_info[i].num == PC)) { reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR; reg_list[i].reg_data_type->id = "code_ptr"; } else { reg_list[i].reg_data_type->type = REG_TYPE_UINT32; reg_list[i].reg_data_type->id = "uint32"; } } if (R16 <= reg_arch_info[i].num && reg_arch_info[i].num <= R25) reg_list[i].caller_save = true; else reg_list[i].caller_save = false; reg_list[i].feature = malloc(sizeof(struct reg_feature)); if (R0 <= reg_arch_info[i].num && reg_arch_info[i].num <= IFC_LP) reg_list[i].feature->name = "org.gnu.gdb.nds32.core"; else if (CR0 <= reg_arch_info[i].num && reg_arch_info[i].num <= SECUR0) reg_list[i].feature->name = "org.gnu.gdb.nds32.system"; else if (D0L24 <= reg_arch_info[i].num && reg_arch_info[i].num <= CBE3) reg_list[i].feature->name = "org.gnu.gdb.nds32.audio"; else if (FPCSR <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) reg_list[i].feature->name = "org.gnu.gdb.nds32.fpu"; cache->num_regs++; } nds32->core_cache = cache; return cache; } static int nds32_reg_cache_init(struct target *target, struct nds32 *nds32) { struct reg_cache *cache; cache = nds32_build_reg_cache(target, nds32); if (!cache) return ERROR_FAIL; *register_get_last_cache_p(&target->reg_cache) = cache; return ERROR_OK; } static struct reg *nds32_reg_current(struct nds32 *nds32, unsigned regnum) { struct reg *r; r = nds32->core_cache->reg_list + regnum; return r; } int nds32_full_context(struct nds32 *nds32) { uint32_t value, value_ir0; /* save $pc & $psw */ nds32_get_mapped_reg(nds32, PC, &value); nds32_get_mapped_reg(nds32, IR0, &value_ir0); nds32_update_psw(nds32); nds32_update_mmu_info(nds32); nds32_update_cache_info(nds32); nds32_update_lm_info(nds32); nds32_check_extension(nds32); return ERROR_OK; } /* get register value internally */ int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value) { struct reg_cache *reg_cache = nds32->core_cache; struct reg *r; if (regnum > reg_cache->num_regs) return ERROR_FAIL; r = nds32_reg_current(nds32, regnum); if (ERROR_OK != r->type->get(r)) return ERROR_FAIL; *value = buf_get_u32(r->value, 0, 32); return ERROR_OK; } /** set register internally */ int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value) { struct reg_cache *reg_cache = nds32->core_cache; struct reg *r; uint8_t set_value[4]; if (regnum > reg_cache->num_regs) return ERROR_FAIL; r = nds32_reg_current(nds32, regnum); buf_set_u32(set_value, 0, 32, value); return r->type->set(r, set_value); } /** get general register list */ static int nds32_get_general_reg_list(struct nds32 *nds32, struct reg **reg_list[], int *reg_list_size) { struct reg *reg_current; int i; int current_idx; /** freed in gdb_server.c */ *reg_list = malloc(sizeof(struct reg *) * (IFC_LP - R0 + 1)); current_idx = 0; for (i = R0; i < IFC_LP + 1; i++) { reg_current = nds32_reg_current(nds32, i); if (((struct nds32_reg *)reg_current->arch_info)->enable) { (*reg_list)[current_idx] = reg_current; current_idx++; } } *reg_list_size = current_idx; return ERROR_OK; } /** get all register list */ static int nds32_get_all_reg_list(struct nds32 *nds32, struct reg **reg_list[], int *reg_list_size) { struct reg_cache *reg_cache = nds32->core_cache; struct reg *reg_current; unsigned int i; *reg_list_size = reg_cache->num_regs; /** freed in gdb_server.c */ *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < reg_cache->num_regs; i++) { reg_current = nds32_reg_current(nds32, i); reg_current->exist = ((struct nds32_reg *) reg_current->arch_info)->enable; (*reg_list)[i] = reg_current; } return ERROR_OK; } /** get all register list */ int nds32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct nds32 *nds32 = target_to_nds32(target); switch (reg_class) { case REG_CLASS_ALL: return nds32_get_all_reg_list(nds32, reg_list, reg_list_size); case REG_CLASS_GENERAL: return nds32_get_general_reg_list(nds32, reg_list, reg_list_size); default: return ERROR_FAIL; } return ERROR_FAIL; } static int nds32_select_memory_mode(struct target *target, uint32_t address, uint32_t length, uint32_t *end_address) { struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_memory *memory = &(nds32->memory); struct nds32_edm *edm = &(nds32->edm); uint32_t dlm_start, dlm_end; uint32_t ilm_start, ilm_end; uint32_t address_end = address + length; /* init end_address */ *end_address = address_end; if (NDS_MEMORY_ACC_CPU == memory->access_channel) return ERROR_OK; if (edm->access_control == false) { LOG_DEBUG("EDM does not support ACC_CTL"); return ERROR_OK; } if (edm->direct_access_local_memory == false) { LOG_DEBUG("EDM does not support DALM"); aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); return ERROR_OK; } if (NDS_MEMORY_SELECT_AUTO != memory->mode) { LOG_DEBUG("Memory mode is not AUTO"); return ERROR_OK; } /* set default mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); if ((memory->ilm_base != 0) && (memory->ilm_enable == true)) { ilm_start = memory->ilm_start; ilm_end = memory->ilm_end; /* case 1, address < ilm_start */ if (address < ilm_start) { if (ilm_start < address_end) { /* update end_address to split non-ILM from ILM */ *end_address = ilm_start; } /* MEM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); } else if ((ilm_start <= address) && (address < ilm_end)) { /* case 2, ilm_start <= address < ilm_end */ if (ilm_end < address_end) { /* update end_address to split non-ILM from ILM */ *end_address = ilm_end; } /* ILM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_ILM); } else { /* case 3, ilm_end <= address */ /* MEM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); } return ERROR_OK; } else { LOG_DEBUG("ILM is not enabled"); } if ((memory->dlm_base != 0) && (memory->dlm_enable == true)) { dlm_start = memory->dlm_start; dlm_end = memory->dlm_end; /* case 1, address < dlm_start */ if (address < dlm_start) { if (dlm_start < address_end) { /* update end_address to split non-DLM from DLM */ *end_address = dlm_start; } /* MEM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); } else if ((dlm_start <= address) && (address < dlm_end)) { /* case 2, dlm_start <= address < dlm_end */ if (dlm_end < address_end) { /* update end_address to split non-DLM from DLM */ *end_address = dlm_end; } /* DLM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_DLM); } else { /* case 3, dlm_end <= address */ /* MEM mode */ aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM); } return ERROR_OK; } else { LOG_DEBUG("DLM is not enabled"); } return ERROR_OK; } int nds32_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("READ BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32, address, size); int retval = ERROR_OK; struct aice_port_s *aice = target_to_aice(target); uint32_t end_address; if (((address % 2) == 0) && (size == 2)) { nds32_select_memory_mode(target, address, 2, &end_address); return aice_read_mem_unit(aice, address, 2, 1, buffer); } /* handle unaligned head bytes */ if (address % 4) { uint32_t unaligned = 4 - (address % 4); if (unaligned > size) unaligned = size; nds32_select_memory_mode(target, address, unaligned, &end_address); retval = aice_read_mem_unit(aice, address, 1, unaligned, buffer); if (retval != ERROR_OK) return retval; buffer += unaligned; address += unaligned; size -= unaligned; } /* handle aligned words */ if (size >= 4) { int aligned = size - (size % 4); int read_len; do { nds32_select_memory_mode(target, address, aligned, &end_address); read_len = end_address - address; if (read_len > 8) retval = aice_read_mem_bulk(aice, address, read_len, buffer); else retval = aice_read_mem_unit(aice, address, 4, read_len / 4, buffer); if (retval != ERROR_OK) return retval; buffer += read_len; address += read_len; size -= read_len; aligned -= read_len; } while (aligned != 0); } /*prevent byte access when possible (avoid AHB access limitations in some cases)*/ if (size >= 2) { int aligned = size - (size % 2); nds32_select_memory_mode(target, address, aligned, &end_address); retval = aice_read_mem_unit(aice, address, 2, aligned / 2, buffer); if (retval != ERROR_OK) return retval; buffer += aligned; address += aligned; size -= aligned; } /* handle tail writes of less than 4 bytes */ if (size > 0) { nds32_select_memory_mode(target, address, size, &end_address); retval = aice_read_mem_unit(aice, address, 1, size, buffer); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int nds32_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); return aice_read_mem_unit(aice, address, size, count, buffer); } int nds32_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); enum nds_memory_access orig_channel; int result; /* switch to BUS access mode to skip MMU */ orig_channel = memory->access_channel; memory->access_channel = NDS_MEMORY_ACC_BUS; aice_memory_access(aice, memory->access_channel); /* The input address is physical address. No need to do address translation. */ result = aice_read_mem_unit(aice, address, size, count, buffer); /* restore to origin access mode */ memory->access_channel = orig_channel; aice_memory_access(aice, memory->access_channel); return result; } int nds32_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("WRITE BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32, address, size); struct aice_port_s *aice = target_to_aice(target); int retval = ERROR_OK; uint32_t end_address; if (((address % 2) == 0) && (size == 2)) { nds32_select_memory_mode(target, address, 2, &end_address); return aice_write_mem_unit(aice, address, 2, 1, buffer); } /* handle unaligned head bytes */ if (address % 4) { uint32_t unaligned = 4 - (address % 4); if (unaligned > size) unaligned = size; nds32_select_memory_mode(target, address, unaligned, &end_address); retval = aice_write_mem_unit(aice, address, 1, unaligned, buffer); if (retval != ERROR_OK) return retval; buffer += unaligned; address += unaligned; size -= unaligned; } /* handle aligned words */ if (size >= 4) { int aligned = size - (size % 4); int write_len; do { nds32_select_memory_mode(target, address, aligned, &end_address); write_len = end_address - address; if (write_len > 8) retval = aice_write_mem_bulk(aice, address, write_len, buffer); else retval = aice_write_mem_unit(aice, address, 4, write_len / 4, buffer); if (retval != ERROR_OK) return retval; buffer += write_len; address += write_len; size -= write_len; aligned -= write_len; } while (aligned != 0); } /* handle tail writes of less than 4 bytes */ if (size > 0) { nds32_select_memory_mode(target, address, size, &end_address); retval = aice_write_mem_unit(aice, address, 1, size, buffer); if (retval != ERROR_OK) return retval; } return retval; } int nds32_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); return aice_write_mem_unit(aice, address, size, count, buffer); } int nds32_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); enum nds_memory_access orig_channel; int result; /* switch to BUS access mode to skip MMU */ orig_channel = memory->access_channel; memory->access_channel = NDS_MEMORY_ACC_BUS; aice_memory_access(aice, memory->access_channel); /* The input address is physical address. No need to do address translation. */ result = aice_write_mem_unit(aice, address, size, count, buffer); /* restore to origin access mode */ memory->access_channel = orig_channel; aice_memory_access(aice, memory->access_channel); return result; } int nds32_mmu(struct target *target, int *enabled) { if (target->state != TARGET_HALTED) { LOG_ERROR("%s: target not halted", __func__); return ERROR_TARGET_INVALID; } struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); struct nds32_mmu_config *mmu_config = &(nds32->mmu_config); if ((mmu_config->memory_protection == 2) && (memory->address_translation == true)) *enabled = 1; else *enabled = 0; return ERROR_OK; } int nds32_arch_state(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); if (nds32->common_magic != NDS32_COMMON_MAGIC) { LOG_ERROR("BUG: called for a non-Andes target"); return ERROR_FAIL; } uint32_t value_pc, value_psw; nds32_get_mapped_reg(nds32, PC, &value_pc); nds32_get_mapped_reg(nds32, IR0, &value_psw); LOG_USER("target halted due to %s\n" "psw: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s", debug_reason_name(target), value_psw, value_pc, nds32->virtual_hosting ? ", virtual hosting" : ""); /* save pc value to pseudo register pc */ struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); buf_set_u32(reg->value, 0, 32, value_pc); return ERROR_OK; } static void nds32_init_must_have_registers(struct nds32 *nds32) { struct reg_cache *reg_cache = nds32->core_cache; /** MUST have general registers */ ((struct nds32_reg *)reg_cache->reg_list[R0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R4].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R5].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R7].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R8].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R9].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R10].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R15].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R28].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R29].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R30].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R31].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[PC].arch_info)->enable = true; /** MUST have configuration system registers */ ((struct nds32_reg *)reg_cache->reg_list[CR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CR1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CR2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CR3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CR4].arch_info)->enable = true; /** MUST have interrupt system registers */ ((struct nds32_reg *)reg_cache->reg_list[IR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR11].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR14].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR15].arch_info)->enable = true; /** MUST have MMU system registers */ ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = true; /** MUST have EDM system registers */ ((struct nds32_reg *)reg_cache->reg_list[DR40].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR42].arch_info)->enable = true; } static int nds32_init_memory_config(struct nds32 *nds32) { uint32_t value_cr1; /* ICM_CFG */ uint32_t value_cr2; /* DCM_CFG */ struct nds32_memory *memory = &(nds32->memory); /* read $cr1 to init instruction memory information */ nds32_get_mapped_reg(nds32, CR1, &value_cr1); memory->icache.set = value_cr1 & 0x7; memory->icache.way = (value_cr1 >> 3) & 0x7; memory->icache.line_size = (value_cr1 >> 6) & 0x7; memory->icache.lock_support = (value_cr1 >> 9) & 0x1; memory->ilm_base = (value_cr1 >> 10) & 0x7; memory->ilm_align_ver = (value_cr1 >> 13) & 0x3; /* read $cr2 to init data memory information */ nds32_get_mapped_reg(nds32, CR2, &value_cr2); memory->dcache.set = value_cr2 & 0x7; memory->dcache.way = (value_cr2 >> 3) & 0x7; memory->dcache.line_size = (value_cr2 >> 6) & 0x7; memory->dcache.lock_support = (value_cr2 >> 9) & 0x1; memory->dlm_base = (value_cr2 >> 10) & 0x7; memory->dlm_align_ver = (value_cr2 >> 13) & 0x3; return ERROR_OK; } static void nds32_init_config(struct nds32 *nds32) { uint32_t value_cr0; uint32_t value_cr3; uint32_t value_cr4; struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); struct nds32_mmu_config *mmu_config = &(nds32->mmu_config); struct nds32_misc_config *misc_config = &(nds32->misc_config); nds32_get_mapped_reg(nds32, CR0, &value_cr0); nds32_get_mapped_reg(nds32, CR3, &value_cr3); nds32_get_mapped_reg(nds32, CR4, &value_cr4); /* config cpu version */ cpu_version->performance_extension = value_cr0 & 0x1; cpu_version->_16bit_extension = (value_cr0 >> 1) & 0x1; cpu_version->performance_extension_2 = (value_cr0 >> 2) & 0x1; cpu_version->cop_fpu_extension = (value_cr0 >> 3) & 0x1; cpu_version->string_extension = (value_cr0 >> 4) & 0x1; cpu_version->revision = (value_cr0 >> 16) & 0xFF; cpu_version->cpu_id_family = (value_cr0 >> 24) & 0xF; cpu_version->cpu_id_version = (value_cr0 >> 28) & 0xF; /* config MMU */ mmu_config->memory_protection = value_cr3 & 0x3; mmu_config->memory_protection_version = (value_cr3 >> 2) & 0x1F; mmu_config->fully_associative_tlb = (value_cr3 >> 7) & 0x1; if (mmu_config->fully_associative_tlb) { mmu_config->tlb_size = (value_cr3 >> 8) & 0x7F; } else { mmu_config->tlb_ways = (value_cr3 >> 8) & 0x7; mmu_config->tlb_sets = (value_cr3 >> 11) & 0x7; } mmu_config->_8k_page_support = (value_cr3 >> 15) & 0x1; mmu_config->extra_page_size_support = (value_cr3 >> 16) & 0xFF; mmu_config->tlb_lock = (value_cr3 >> 24) & 0x1; mmu_config->hardware_page_table_walker = (value_cr3 >> 25) & 0x1; mmu_config->default_endian = (value_cr3 >> 26) & 0x1; mmu_config->partition_num = (value_cr3 >> 27) & 0x1; mmu_config->invisible_tlb = (value_cr3 >> 28) & 0x1; mmu_config->vlpt = (value_cr3 >> 29) & 0x1; mmu_config->ntme = (value_cr3 >> 30) & 0x1; mmu_config->drde = (value_cr3 >> 31) & 0x1; /* config misc */ misc_config->edm = value_cr4 & 0x1; misc_config->local_memory_dma = (value_cr4 >> 1) & 0x1; misc_config->performance_monitor = (value_cr4 >> 2) & 0x1; misc_config->high_speed_memory_port = (value_cr4 >> 3) & 0x1; misc_config->debug_tracer = (value_cr4 >> 4) & 0x1; misc_config->div_instruction = (value_cr4 >> 5) & 0x1; misc_config->mac_instruction = (value_cr4 >> 6) & 0x1; misc_config->audio_isa = (value_cr4 >> 7) & 0x3; misc_config->L2_cache = (value_cr4 >> 9) & 0x1; misc_config->reduce_register = (value_cr4 >> 10) & 0x1; misc_config->addr_24 = (value_cr4 >> 11) & 0x1; misc_config->interruption_level = (value_cr4 >> 12) & 0x1; misc_config->baseline_instruction = (value_cr4 >> 13) & 0x7; misc_config->no_dx_register = (value_cr4 >> 16) & 0x1; misc_config->implement_dependant_register = (value_cr4 >> 17) & 0x1; misc_config->implement_dependant_sr_encoding = (value_cr4 >> 18) & 0x1; misc_config->ifc = (value_cr4 >> 19) & 0x1; misc_config->mcu = (value_cr4 >> 20) & 0x1; misc_config->shadow = (value_cr4 >> 21) & 0x7; misc_config->ex9 = (value_cr4 >> 24) & 0x1; nds32_init_memory_config(nds32); } static int nds32_init_option_registers(struct nds32 *nds32) { struct reg_cache *reg_cache = nds32->core_cache; struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); struct nds32_mmu_config *mmu_config = &(nds32->mmu_config); struct nds32_misc_config *misc_config = &(nds32->misc_config); struct nds32_memory *memory_config = &(nds32->memory); bool no_cr5; bool mr10_exist; bool no_racr0; if (((cpu_version->cpu_id_family == 0xC) || (cpu_version->cpu_id_family == 0xD)) && ((cpu_version->revision & 0xFC) == 0)) { no_cr5 = true; mr10_exist = true; no_racr0 = true; } else { no_cr5 = false; mr10_exist = false; no_racr0 = false; } if (misc_config->reduce_register == false) { ((struct nds32_reg *)reg_cache->reg_list[R11].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R12].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R13].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R14].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R16].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R17].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R18].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R19].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R20].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R21].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R22].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R23].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R24].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R25].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R26].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[R27].arch_info)->enable = true; } if (misc_config->no_dx_register == false) { ((struct nds32_reg *)reg_cache->reg_list[D0LO].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[D0HI].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[D1LO].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[D1HI].arch_info)->enable = true; } if (misc_config->ex9) ((struct nds32_reg *)reg_cache->reg_list[ITB].arch_info)->enable = true; if (no_cr5 == false) ((struct nds32_reg *)reg_cache->reg_list[CR5].arch_info)->enable = true; if (cpu_version->cop_fpu_extension) { ((struct nds32_reg *)reg_cache->reg_list[CR6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[FPCSR].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[FPCFG].arch_info)->enable = true; } if (mmu_config->memory_protection == 1) { /* Secure MPU has no IPC, IPSW, P_ITYPE */ ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = false; ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = false; } if (nds32->privilege_level != 0) ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = false; if (misc_config->mcu == true) ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = false; if (misc_config->interruption_level == false) { ((struct nds32_reg *)reg_cache->reg_list[IR2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR5].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR10].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR12].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR13].arch_info)->enable = true; /* Secure MPU has no IPC, IPSW, P_ITYPE */ if (mmu_config->memory_protection != 1) ((struct nds32_reg *)reg_cache->reg_list[IR7].arch_info)->enable = true; } if ((cpu_version->cpu_id_family == 0x9) || (cpu_version->cpu_id_family == 0xA) || (cpu_version->cpu_id_family == 0xC) || (cpu_version->cpu_id_family == 0xD)) ((struct nds32_reg *)reg_cache->reg_list[IR8].arch_info)->enable = true; if (misc_config->shadow == 1) { ((struct nds32_reg *)reg_cache->reg_list[IR16].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR17].arch_info)->enable = true; } if (misc_config->ifc) ((struct nds32_reg *)reg_cache->reg_list[IFC_LP].arch_info)->enable = true; if (nds32->privilege_level != 0) ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = false; if (mmu_config->memory_protection == 1) { if (mmu_config->memory_protection_version == 24) ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true; if (nds32->privilege_level == 0) { if ((mmu_config->memory_protection_version == 16) || (mmu_config->memory_protection_version == 24)) { ((struct nds32_reg *)reg_cache->reg_list[MR11].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[SECUR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR20].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR22].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR24].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR30].arch_info)->enable = true; if (misc_config->shadow == 1) { ((struct nds32_reg *)reg_cache->reg_list[IR21].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR23].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR25].arch_info)->enable = true; } } } } else if (mmu_config->memory_protection == 2) { ((struct nds32_reg *)reg_cache->reg_list[MR1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true; if ((cpu_version->cpu_id_family != 0xA) && (cpu_version->cpu_id_family != 0xC) && (cpu_version->cpu_id_family != 0xD)) ((struct nds32_reg *)reg_cache->reg_list[MR5].arch_info)->enable = true; } if (mmu_config->memory_protection > 0) { ((struct nds32_reg *)reg_cache->reg_list[MR2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[MR3].arch_info)->enable = true; } if (memory_config->ilm_base != 0) if (nds32->privilege_level == 0) ((struct nds32_reg *)reg_cache->reg_list[MR6].arch_info)->enable = true; if (memory_config->dlm_base != 0) if (nds32->privilege_level == 0) ((struct nds32_reg *)reg_cache->reg_list[MR7].arch_info)->enable = true; if ((memory_config->icache.line_size != 0) && (memory_config->dcache.line_size != 0)) ((struct nds32_reg *)reg_cache->reg_list[MR8].arch_info)->enable = true; if (misc_config->high_speed_memory_port) ((struct nds32_reg *)reg_cache->reg_list[MR9].arch_info)->enable = true; if (mr10_exist) ((struct nds32_reg *)reg_cache->reg_list[MR10].arch_info)->enable = true; if (misc_config->edm) { int dr_reg_n = nds32->edm.breakpoint_num * 5; for (int i = 0 ; i < dr_reg_n ; i++) ((struct nds32_reg *)reg_cache->reg_list[DR0 + i].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR41].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR43].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR44].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR45].arch_info)->enable = true; } if (misc_config->debug_tracer) { ((struct nds32_reg *)reg_cache->reg_list[DR46].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DR47].arch_info)->enable = true; } if (misc_config->performance_monitor) { ((struct nds32_reg *)reg_cache->reg_list[PFR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[PFR1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[PFR2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[PFR3].arch_info)->enable = true; } if (misc_config->local_memory_dma) { ((struct nds32_reg *)reg_cache->reg_list[DMAR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR4].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR5].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR7].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR8].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR9].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[DMAR10].arch_info)->enable = true; } if ((misc_config->local_memory_dma || misc_config->performance_monitor) && (no_racr0 == false)) ((struct nds32_reg *)reg_cache->reg_list[RACR].arch_info)->enable = true; if (cpu_version->cop_fpu_extension || (misc_config->audio_isa != 0)) ((struct nds32_reg *)reg_cache->reg_list[FUCPR].arch_info)->enable = true; if (misc_config->audio_isa != 0) { if (misc_config->audio_isa > 1) { ((struct nds32_reg *)reg_cache->reg_list[D0L24].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[D1L24].arch_info)->enable = true; } ((struct nds32_reg *)reg_cache->reg_list[I0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I4].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I5].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[I7].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M5].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M6].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[M7].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[MOD].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[LBE].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[LE].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[LC].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[ADM_VBASE].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL1].arch_info)->enable = true; uint32_t value_mod; uint32_t fucpr_backup; /* enable fpu and get configuration */ nds32_get_mapped_reg(nds32, FUCPR, &fucpr_backup); if ((fucpr_backup & 0x80000000) == 0) nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup | 0x80000000); nds32_get_mapped_reg(nds32, MOD, &value_mod); /* restore origin fucpr value */ if ((fucpr_backup & 0x80000000) == 0) nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup); if ((value_mod >> 6) & 0x1) { ((struct nds32_reg *)reg_cache->reg_list[CB_CTL].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBB0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBB1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBB2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBB3].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBE0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBE1].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBE2].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[CBE3].arch_info)->enable = true; } } if ((cpu_version->cpu_id_family == 0x9) || (cpu_version->cpu_id_family == 0xA) || (cpu_version->cpu_id_family == 0xC)) { ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IDR1].arch_info)->enable = true; if ((cpu_version->cpu_id_family == 0xC) && (cpu_version->revision == 0x0C)) ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = false; } uint32_t ir3_value; uint32_t ivb_prog_pri_lvl; uint32_t ivb_ivic_ver; nds32_get_mapped_reg(nds32, IR3, &ir3_value); ivb_prog_pri_lvl = ir3_value & 0x1; ivb_ivic_ver = (ir3_value >> 11) & 0x3; if ((ivb_prog_pri_lvl == 1) || (ivb_ivic_ver >= 1)) { ((struct nds32_reg *)reg_cache->reg_list[IR18].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR19].arch_info)->enable = true; } if (ivb_ivic_ver >= 1) { ((struct nds32_reg *)reg_cache->reg_list[IR26].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR27].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR28].arch_info)->enable = true; ((struct nds32_reg *)reg_cache->reg_list[IR29].arch_info)->enable = true; } return ERROR_OK; } int nds32_init_register_table(struct nds32 *nds32) { nds32_init_must_have_registers(nds32); return ERROR_OK; } int nds32_add_software_breakpoint(struct target *target, struct breakpoint *breakpoint) { uint32_t data; uint32_t check_data; uint32_t break_insn; /* check the breakpoint size */ target->type->read_buffer(target, breakpoint->address, 4, (uint8_t *)&data); /* backup origin instruction * instruction is big-endian */ if (*(char *)&data & 0x80) { /* 16-bits instruction */ breakpoint->length = 2; break_insn = NDS32_BREAK_16; } else { /* 32-bits instruction */ breakpoint->length = 4; break_insn = NDS32_BREAK_32; } if (breakpoint->orig_instr != NULL) free(breakpoint->orig_instr); breakpoint->orig_instr = malloc(breakpoint->length); memcpy(breakpoint->orig_instr, &data, breakpoint->length); /* self-modified code */ target->type->write_buffer(target, breakpoint->address, breakpoint->length, (const uint8_t *)&break_insn); /* write_back & invalidate dcache & invalidate icache */ nds32_cache_sync(target, breakpoint->address, breakpoint->length); /* read back to check */ target->type->read_buffer(target, breakpoint->address, breakpoint->length, (uint8_t *)&check_data); if (memcmp(&check_data, &break_insn, breakpoint->length) == 0) return ERROR_OK; return ERROR_FAIL; } int nds32_remove_software_breakpoint(struct target *target, struct breakpoint *breakpoint) { uint32_t check_data; uint32_t break_insn; if (breakpoint->length == 2) break_insn = NDS32_BREAK_16; else if (breakpoint->length == 4) break_insn = NDS32_BREAK_32; else return ERROR_FAIL; target->type->read_buffer(target, breakpoint->address, breakpoint->length, (uint8_t *)&check_data); /* break instruction is modified */ if (memcmp(&check_data, &break_insn, breakpoint->length) != 0) return ERROR_FAIL; /* self-modified code */ target->type->write_buffer(target, breakpoint->address, breakpoint->length, breakpoint->orig_instr); /* write_back & invalidate dcache & invalidate icache */ nds32_cache_sync(target, breakpoint->address, breakpoint->length); return ERROR_OK; } /** * Restore the processor context on an Andes target. The full processor * context is analyzed to see if any of the registers are dirty on this end, but * have a valid new value. If this is the case, the processor is changed to the * appropriate mode and the new register values are written out to the * processor. If there happens to be a dirty register with an invalid value, an * error will be logged. * * @param target Pointer to the Andes target to have its context restored * @return Error status if the target is not halted. */ int nds32_restore_context(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct reg_cache *reg_cache = nds32->core_cache; struct reg *reg; struct nds32_reg *reg_arch_info; unsigned int i; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* check if there are dirty registers */ for (i = 0; i < reg_cache->num_regs; i++) { reg = &(reg_cache->reg_list[i]); if (reg->dirty == true) { if (reg->valid == true) { LOG_DEBUG("examining dirty reg: %s", reg->name); LOG_DEBUG("writing register %d with value 0x%8.8" PRIx32, i, buf_get_u32(reg->value, 0, 32)); reg_arch_info = reg->arch_info; if (FD0 <= reg_arch_info->num && reg_arch_info->num <= FD31) { uint64_t val = buf_get_u64(reg_arch_info->value, 0, 64); aice_write_reg_64(aice, reg_arch_info->num, val); } else { uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); aice_write_register(aice, reg_arch_info->num, val); } reg->valid = true; reg->dirty = false; } } } return ERROR_OK; } int nds32_edm_config(struct nds32 *nds32) { struct target *target = nds32->target; struct aice_port_s *aice = target_to_aice(target); uint32_t edm_cfg; uint32_t edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); nds32->edm.version = (edm_cfg >> 16) & 0xFFFF; LOG_INFO("EDM version 0x%04x", nds32->edm.version); nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1; if ((nds32->edm.version & 0x1000) || (0x60 <= nds32->edm.version)) nds32->edm.access_control = true; else nds32->edm.access_control = false; if ((edm_cfg >> 4) & 0x1) nds32->edm.direct_access_local_memory = true; else nds32->edm.direct_access_local_memory = false; if (nds32->edm.version <= 0x20) nds32->edm.direct_access_local_memory = false; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl); if (edm_ctl & (0x1 << 29)) nds32->edm.support_max_stop = true; else nds32->edm.support_max_stop = false; /* set passcode for secure MCU */ nds32_login(nds32); return ERROR_OK; } int nds32_config(struct nds32 *nds32) { nds32_init_config(nds32); /* init optional system registers according to config registers */ nds32_init_option_registers(nds32); /* get max interrupt level */ if (nds32->misc_config.interruption_level) nds32->max_interrupt_level = 2; else nds32->max_interrupt_level = 3; /* get ILM/DLM size from MR6/MR7 */ uint32_t value_mr6, value_mr7; uint32_t size_index; nds32_get_mapped_reg(nds32, MR6, &value_mr6); size_index = (value_mr6 >> 1) & 0xF; nds32->memory.ilm_size = NDS32_LM_SIZE_TABLE[size_index]; nds32_get_mapped_reg(nds32, MR7, &value_mr7); size_index = (value_mr7 >> 1) & 0xF; nds32->memory.dlm_size = NDS32_LM_SIZE_TABLE[size_index]; return ERROR_OK; } int nds32_init_arch_info(struct target *target, struct nds32 *nds32) { target->arch_info = nds32; nds32->target = target; nds32->common_magic = NDS32_COMMON_MAGIC; nds32->init_arch_info_after_halted = false; nds32->auto_convert_hw_bp = true; nds32->global_stop = false; nds32->soft_reset_halt = false; nds32->edm_passcode = NULL; nds32->privilege_level = 0; nds32->boot_time = 1500; nds32->reset_halt_as_examine = false; nds32->keep_target_edm_ctl = false; nds32->word_access_mem = false; nds32->virtual_hosting = true; nds32->hit_syscall = false; nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED; nds32->virtual_hosting_errno = 0; nds32->virtual_hosting_ctrl_c = false; nds32->attached = false; nds32->syscall_break.asid = 0; nds32->syscall_break.length = 4; nds32->syscall_break.set = 0; nds32->syscall_break.orig_instr = NULL; nds32->syscall_break.next = NULL; nds32->syscall_break.unique_id = 0x515CAll + target->target_number; nds32->syscall_break.linked_BRP = 0; nds32_reg_init(); if (ERROR_FAIL == nds32_reg_cache_init(target, nds32)) return ERROR_FAIL; if (ERROR_OK != nds32_init_register_table(nds32)) return ERROR_FAIL; return ERROR_OK; } int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical) { struct nds32 *nds32 = target_to_nds32(target); if (nds32->memory.address_translation == false) { *physical = address; return ERROR_OK; } if (ERROR_OK == nds32_probe_tlb(nds32, address, physical)) return ERROR_OK; if (ERROR_OK == nds32_walk_page_table(nds32, address, physical)) return ERROR_OK; return ERROR_FAIL; } int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) { struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); struct nds32_cache *dcache = &(nds32->memory.dcache); struct nds32_cache *icache = &(nds32->memory.icache); uint32_t dcache_line_size = NDS32_LINE_SIZE_TABLE[dcache->line_size]; uint32_t icache_line_size = NDS32_LINE_SIZE_TABLE[icache->line_size]; uint32_t cur_address; int result; uint32_t start_line, end_line; uint32_t cur_line; if ((dcache->line_size != 0) && (dcache->enable == true)) { /* address / dcache_line_size */ start_line = address >> (dcache->line_size + 2); /* (address + length - 1) / dcache_line_size */ end_line = (address + length - 1) >> (dcache->line_size + 2); for (cur_address = address, cur_line = start_line ; cur_line <= end_line ; cur_address += dcache_line_size, cur_line++) { /* D$ write back */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_WB, cur_address); if (result != ERROR_OK) return result; /* D$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_INVAL, cur_address); if (result != ERROR_OK) return result; } } if ((icache->line_size != 0) && (icache->enable == true)) { /* address / icache_line_size */ start_line = address >> (icache->line_size + 2); /* (address + length - 1) / icache_line_size */ end_line = (address + length - 1) >> (icache->line_size + 2); for (cur_address = address, cur_line = start_line ; cur_line <= end_line ; cur_address += icache_line_size, cur_line++) { /* Because PSW.IT is turned off under debug exception, address MUST * be physical address. L1I_VA_INVALIDATE uses PSW.IT to decide * address translation or not. */ uint32_t physical_addr; if (ERROR_FAIL == target->type->virt2phys(target, cur_address, &physical_addr)) return ERROR_FAIL; /* I$ invalidate */ result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_VA_INVAL, physical_addr); if (result != ERROR_OK) return result; } } return ERROR_OK; } uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address) { if (!current) nds32_set_mapped_reg(nds32, PC, address); else nds32_get_mapped_reg(nds32, PC, &address); return address; } int nds32_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } struct nds32 *nds32 = target_to_nds32(target); address = nds32_nextpc(nds32, current, address); LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); /** set DSSIM */ uint32_t ir14_value; nds32_get_mapped_reg(nds32, IR14, &ir14_value); if (nds32->step_isr_enable) ir14_value |= (0x1 << 31); else ir14_value &= ~(0x1 << 31); nds32_set_mapped_reg(nds32, IR14, ir14_value); /* check hit_syscall before leave_debug_state() because * leave_debug_state() may clear hit_syscall flag */ bool no_step = false; if (nds32->hit_syscall) /* step after hit_syscall should be ignored because * leave_debug_state will step implicitly to skip the * syscall */ no_step = true; /********* TODO: maybe create another function to handle this part */ CHECK_RETVAL(nds32->leave_debug_state(nds32, true)); CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); if (no_step == false) { struct aice_port_s *aice = target_to_aice(target); if (ERROR_OK != aice_step(aice)) return ERROR_FAIL; } /* save state */ CHECK_RETVAL(nds32->enter_debug_state(nds32, true)); /********* TODO: maybe create another function to handle this part */ /* restore DSSIM */ if (nds32->step_isr_enable) { nds32_get_mapped_reg(nds32, IR14, &ir14_value); ir14_value &= ~(0x1 << 31); nds32_set_mapped_reg(nds32, IR14, ir14_value); } CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); return ERROR_OK; } static int nds32_step_without_watchpoint(struct nds32 *nds32) { struct target *target = nds32->target; if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } /** set DSSIM */ uint32_t ir14_value; nds32_get_mapped_reg(nds32, IR14, &ir14_value); if (nds32->step_isr_enable) ir14_value |= (0x1 << 31); else ir14_value &= ~(0x1 << 31); nds32_set_mapped_reg(nds32, IR14, ir14_value); /********* TODO: maybe create another function to handle this part */ CHECK_RETVAL(nds32->leave_debug_state(nds32, false)); struct aice_port_s *aice = target_to_aice(target); if (ERROR_OK != aice_step(aice)) return ERROR_FAIL; /* save state */ CHECK_RETVAL(nds32->enter_debug_state(nds32, false)); /********* TODO: maybe create another function to handle this part */ /* restore DSSIM */ if (nds32->step_isr_enable) { nds32_get_mapped_reg(nds32, IR14, &ir14_value); ir14_value &= ~(0x1 << 31); nds32_set_mapped_reg(nds32, IR14, ir14_value); } return ERROR_OK; } int nds32_target_state(struct nds32 *nds32, enum target_state *state) { struct aice_port_s *aice = target_to_aice(nds32->target); enum aice_target_state_s nds32_state; if (aice_state(aice, &nds32_state) != ERROR_OK) return ERROR_FAIL; switch (nds32_state) { case AICE_DISCONNECT: LOG_INFO("USB is disconnected"); return ERROR_FAIL; case AICE_TARGET_DETACH: LOG_INFO("Target is disconnected"); return ERROR_FAIL; case AICE_TARGET_UNKNOWN: *state = TARGET_UNKNOWN; break; case AICE_TARGET_RUNNING: *state = TARGET_RUNNING; break; case AICE_TARGET_HALTED: *state = TARGET_HALTED; break; case AICE_TARGET_RESET: *state = TARGET_RESET; break; case AICE_TARGET_DEBUG_RUNNING: *state = TARGET_DEBUG_RUNNING; break; default: return ERROR_FAIL; } return ERROR_OK; } int nds32_examine_debug_reason(struct nds32 *nds32) { uint32_t reason; struct target *target = nds32->target; if (nds32->hit_syscall == true) { LOG_DEBUG("Hit syscall breakpoint"); target->debug_reason = DBG_REASON_BREAKPOINT; return ERROR_OK; } nds32->get_debug_reason(nds32, &reason); LOG_DEBUG("nds32 examines debug reason: %s", nds32_debug_type_name[reason]); /* Examine debug reason */ switch (reason) { case NDS32_DEBUG_BREAK: case NDS32_DEBUG_BREAK_16: case NDS32_DEBUG_INST_BREAK: { uint32_t value_pc; uint32_t opcode; struct nds32_instruction instruction; nds32_get_mapped_reg(nds32, PC, &value_pc); if (ERROR_OK != nds32_read_opcode(nds32, value_pc, &opcode)) return ERROR_FAIL; if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, value_pc, &instruction)) return ERROR_FAIL; /* hit 'break 0x7FFF' */ if ((instruction.info.opc_6 == 0x32) && (instruction.info.sub_opc == 0xA) && (instruction.info.imm == 0x7FFF)) { target->debug_reason = DBG_REASON_EXIT; } else target->debug_reason = DBG_REASON_BREAKPOINT; } break; case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE: case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE: case NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP: /* GLOBAL_STOP is precise exception */ { int result; result = nds32->get_watched_address(nds32, &(nds32->watched_address), reason); /* do single step(without watchpoints) to skip the "watched" instruction */ nds32_step_without_watchpoint(nds32); /* before single_step, save exception address */ if (ERROR_OK != result) return ERROR_FAIL; target->debug_reason = DBG_REASON_WATCHPOINT; } break; case NDS32_DEBUG_DEBUG_INTERRUPT: target->debug_reason = DBG_REASON_DBGRQ; break; case NDS32_DEBUG_HARDWARE_SINGLE_STEP: target->debug_reason = DBG_REASON_SINGLESTEP; break; case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE: case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE: case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE: if (ERROR_OK != nds32->get_watched_address(nds32, &(nds32->watched_address), reason)) return ERROR_FAIL; target->debug_reason = DBG_REASON_WATCHPOINT; break; default: target->debug_reason = DBG_REASON_UNDEFINED; break; } return ERROR_OK; } int nds32_login(struct nds32 *nds32) { struct target *target = nds32->target; struct aice_port_s *aice = target_to_aice(target); uint32_t passcode_length; char command_sequence[129]; char command_str[33]; char code_str[9]; uint32_t copy_length; uint32_t code; uint32_t i; LOG_DEBUG("nds32_login"); if (nds32->edm_passcode != NULL) { /* convert EDM passcode to command sequences */ passcode_length = strlen(nds32->edm_passcode); command_sequence[0] = '\0'; for (i = 0; i < passcode_length; i += 8) { if (passcode_length - i < 8) copy_length = passcode_length - i; else copy_length = 8; strncpy(code_str, nds32->edm_passcode + i, copy_length); code_str[copy_length] = '\0'; code = strtoul(code_str, NULL, 16); sprintf(command_str, "write_misc gen_port0 0x%" PRIx32 ";", code); strcat(command_sequence, command_str); } if (ERROR_OK != aice_program_edm(aice, command_sequence)) return ERROR_FAIL; /* get current privilege level */ uint32_t value_edmsw; aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &value_edmsw); nds32->privilege_level = (value_edmsw >> 16) & 0x3; LOG_INFO("Current privilege level: %d", nds32->privilege_level); } if (nds32_edm_ops_num > 0) { const char *reg_name; for (i = 0 ; i < nds32_edm_ops_num ; i++) { code = nds32_edm_ops[i].value; if (nds32_edm_ops[i].reg_no == 6) reg_name = "gen_port0"; else if (nds32_edm_ops[i].reg_no == 7) reg_name = "gen_port1"; else return ERROR_FAIL; sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code); if (ERROR_OK != aice_program_edm(aice, command_str)) return ERROR_FAIL; } } return ERROR_OK; } int nds32_halt(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); enum target_state state; LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (nds32_target_state(nds32, &state) != ERROR_OK) return ERROR_FAIL; if (TARGET_HALTED != state) /* TODO: if state == TARGET_HALTED, check ETYPE is DBGI or not */ if (ERROR_OK != aice_halt(aice)) return ERROR_FAIL; CHECK_RETVAL(nds32->enter_debug_state(nds32, true)); CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); return ERROR_OK; } /* poll current target status */ int nds32_poll(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); enum target_state state; if (nds32_target_state(nds32, &state) != ERROR_OK) return ERROR_FAIL; if (state == TARGET_HALTED) { if (target->state != TARGET_HALTED) { /* if false_hit, continue free_run */ if (ERROR_OK != nds32->enter_debug_state(nds32, true)) { struct aice_port_s *aice = target_to_aice(target); aice_run(aice); return ERROR_OK; } LOG_DEBUG("Change target state to TARGET_HALTED."); target_call_event_callbacks(target, TARGET_EVENT_HALTED); } } else if (state == TARGET_RESET) { if (target->state == TARGET_HALTED) { /* similar to assert srst */ register_cache_invalidate(nds32->core_cache); target->state = TARGET_RESET; /* TODO: deassert srst */ } else if (target->state == TARGET_RUNNING) { /* reset as running */ LOG_WARNING("<-- TARGET WARNING! The debug target has been reset. -->"); } } else { if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) { LOG_DEBUG("Change target state to TARGET_RUNNING."); target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; } } return ERROR_OK; } int nds32_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("current %d address %08" PRIx32 " handle_breakpoints %d" " debug_execution %d", current, address, handle_breakpoints, debug_execution); struct nds32 *nds32 = target_to_nds32(target); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } address = nds32_nextpc(nds32, current, address); LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); if (!debug_execution) target_free_all_working_areas(target); /* Disable HSS to avoid users misuse HSS */ if (nds32_reach_max_interrupt_level(nds32) == false) { uint32_t value_ir0; nds32_get_mapped_reg(nds32, IR0, &value_ir0); value_ir0 &= ~(0x1 << 11); nds32_set_mapped_reg(nds32, IR0, value_ir0); } CHECK_RETVAL(nds32->leave_debug_state(nds32, true)); CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); if (nds32->virtual_hosting_ctrl_c == false) { struct aice_port_s *aice = target_to_aice(target); aice_run(aice); } else nds32->virtual_hosting_ctrl_c = false; target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) target->state = TARGET_RUNNING; else target->state = TARGET_DEBUG_RUNNING; LOG_DEBUG("target->state: %s", target_state_name(target)); return ERROR_OK; } static int nds32_soft_reset_halt(struct target *target) { /* TODO: test it */ struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); aice_assert_srst(aice, AICE_SRST); /* halt core and set pc to 0x0 */ int retval = target_halt(target); if (retval != ERROR_OK) return retval; /* start fetching from IVB */ uint32_t value_ir3; nds32_get_mapped_reg(nds32, IR3, &value_ir3); nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000); return ERROR_OK; } int nds32_assert_reset(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); if (target->reset_halt) { if ((nds32->soft_reset_halt) || (nds32->edm.version < 0x51) || ((nds32->edm.version == 0x51) && (cpu_version->revision == 0x1C) && (cpu_version->cpu_id_family == 0xC) && (cpu_version->cpu_id_version == 0x0))) nds32_soft_reset_halt(target); else aice_assert_srst(aice, AICE_RESET_HOLD); } else { aice_assert_srst(aice, AICE_SRST); alive_sleep(nds32->boot_time); } /* set passcode for secure MCU after core reset */ nds32_login(nds32); /* registers are now invalid */ register_cache_invalidate(nds32->core_cache); target->state = TARGET_RESET; return ERROR_OK; } static int nds32_gdb_attach(struct nds32 *nds32) { LOG_DEBUG("nds32_gdb_attach, target coreid: %" PRId32, nds32->target->coreid); if (nds32->attached == false) { if (nds32->keep_target_edm_ctl) { /* backup target EDM_CTL */ struct aice_port_s *aice = target_to_aice(nds32->target); aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32->backup_edm_ctl); } target_halt(nds32->target); nds32->attached = true; } return ERROR_OK; } static int nds32_gdb_detach(struct nds32 *nds32) { LOG_DEBUG("nds32_gdb_detach"); bool backup_virtual_hosting_setting; if (nds32->attached) { backup_virtual_hosting_setting = nds32->virtual_hosting; /* turn off virtual hosting before resume as gdb-detach */ nds32->virtual_hosting = false; target_resume(nds32->target, 1, 0, 0, 0); nds32->virtual_hosting = backup_virtual_hosting_setting; if (nds32->keep_target_edm_ctl) { /* restore target EDM_CTL */ struct aice_port_s *aice = target_to_aice(nds32->target); aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32->backup_edm_ctl); } nds32->attached = false; } return ERROR_OK; } static int nds32_callback_event_handler(struct target *target, enum target_event event, void *priv) { int retval = ERROR_OK; int target_number = *(int *)priv; if (target_number != target->target_number) return ERROR_OK; struct nds32 *nds32 = target_to_nds32(target); switch (event) { case TARGET_EVENT_GDB_ATTACH: retval = nds32_gdb_attach(nds32); break; case TARGET_EVENT_GDB_DETACH: retval = nds32_gdb_detach(nds32); break; default: break; } return retval; } int nds32_init(struct nds32 *nds32) { /* Initialize anything we can set up without talking to the target */ nds32->memory.access_channel = NDS_MEMORY_ACC_CPU; /* register event callback */ target_register_event_callback(nds32_callback_event_handler, &(nds32->target->target_number)); return ERROR_OK; } int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) { /* fill syscall parameters to file-I/O info */ if (NULL == fileio_info) { LOG_ERROR("Target has not initial file-I/O data structure"); return ERROR_FAIL; } struct nds32 *nds32 = target_to_nds32(target); uint32_t value_ir6; uint32_t syscall_id; if (nds32->hit_syscall == false) return ERROR_FAIL; nds32_get_mapped_reg(nds32, IR6, &value_ir6); syscall_id = (value_ir6 >> 16) & 0x7FFF; nds32->active_syscall_id = syscall_id; LOG_DEBUG("hit syscall ID: 0x%" PRIx32, syscall_id); /* free previous identifier storage */ if (NULL != fileio_info->identifier) { free(fileio_info->identifier); fileio_info->identifier = NULL; } switch (syscall_id) { case NDS32_SYSCALL_EXIT: fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "exit"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_OPEN: { uint8_t filename[256]; fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "open"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of path */ nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_4)); target->type->read_buffer(target, fileio_info->param_1, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_CLOSE: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "close"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_READ: fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "read"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); break; case NDS32_SYSCALL_WRITE: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "write"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); break; case NDS32_SYSCALL_LSEEK: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "lseek"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); break; case NDS32_SYSCALL_UNLINK: { uint8_t filename[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "unlink"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of path */ target->type->read_buffer(target, fileio_info->param_1, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_RENAME: { uint8_t filename[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "rename"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); /* reserve fileio_info->param_4 for length of new path */ target->type->read_buffer(target, fileio_info->param_1, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; target->type->read_buffer(target, fileio_info->param_3, 256, filename); fileio_info->param_4 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_FSTAT: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "fstat"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); break; case NDS32_SYSCALL_STAT: { uint8_t filename[256]; fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "stat"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); target->type->read_buffer(target, fileio_info->param_1, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_GETTIMEOFDAY: fileio_info->identifier = malloc(13); sprintf(fileio_info->identifier, "gettimeofday"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); break; case NDS32_SYSCALL_ISATTY: fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "isatty"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_SYSTEM: { uint8_t command[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "system"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ target->type->read_buffer(target, fileio_info->param_1, 256, command); fileio_info->param_2 = strlen((char *)command) + 1; } break; case NDS32_SYSCALL_ERRNO: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "errno"); nds32_set_mapped_reg(nds32, R0, nds32->virtual_hosting_errno); break; default: fileio_info->identifier = malloc(8); sprintf(fileio_info->identifier, "unknown"); break; } return ERROR_OK; } int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s", retcode, fileio_errno, ctrl_c ? "true" : "false"); struct nds32 *nds32 = target_to_nds32(target); nds32_set_mapped_reg(nds32, R0, (uint32_t)retcode); nds32->virtual_hosting_errno = fileio_errno; nds32->virtual_hosting_ctrl_c = ctrl_c; nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED; return ERROR_OK; } int nds32_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { /* sample $PC every 10 milliseconds */ uint32_t iteration = seconds * 100; struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); if (max_num_samples < iteration) iteration = max_num_samples; int pc_regnum = nds32->register_map(nds32, PC); aice_profiling(aice, 10, iteration, pc_regnum, samples, num_samples); register_cache_invalidate(nds32->core_cache); return ERROR_OK; } int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address, uint32_t size, const uint8_t *buffer) { if ((NDS32_SYSCALL_FSTAT == nds32->active_syscall_id) || (NDS32_SYSCALL_STAT == nds32->active_syscall_id)) { /* If doing GDB file-I/O, target should convert 'struct stat' * from gdb-format to target-format */ uint8_t stat_buffer[NDS32_STRUCT_STAT_SIZE]; /* st_dev 2 */ stat_buffer[0] = buffer[3]; stat_buffer[1] = buffer[2]; /* st_ino 2 */ stat_buffer[2] = buffer[7]; stat_buffer[3] = buffer[6]; /* st_mode 4 */ stat_buffer[4] = buffer[11]; stat_buffer[5] = buffer[10]; stat_buffer[6] = buffer[9]; stat_buffer[7] = buffer[8]; /* st_nlink 2 */ stat_buffer[8] = buffer[15]; stat_buffer[9] = buffer[16]; /* st_uid 2 */ stat_buffer[10] = buffer[19]; stat_buffer[11] = buffer[18]; /* st_gid 2 */ stat_buffer[12] = buffer[23]; stat_buffer[13] = buffer[22]; /* st_rdev 2 */ stat_buffer[14] = buffer[27]; stat_buffer[15] = buffer[26]; /* st_size 4 */ stat_buffer[16] = buffer[35]; stat_buffer[17] = buffer[34]; stat_buffer[18] = buffer[33]; stat_buffer[19] = buffer[32]; /* st_atime 4 */ stat_buffer[20] = buffer[55]; stat_buffer[21] = buffer[54]; stat_buffer[22] = buffer[53]; stat_buffer[23] = buffer[52]; /* st_spare1 4 */ stat_buffer[24] = 0; stat_buffer[25] = 0; stat_buffer[26] = 0; stat_buffer[27] = 0; /* st_mtime 4 */ stat_buffer[28] = buffer[59]; stat_buffer[29] = buffer[58]; stat_buffer[30] = buffer[57]; stat_buffer[31] = buffer[56]; /* st_spare2 4 */ stat_buffer[32] = 0; stat_buffer[33] = 0; stat_buffer[34] = 0; stat_buffer[35] = 0; /* st_ctime 4 */ stat_buffer[36] = buffer[63]; stat_buffer[37] = buffer[62]; stat_buffer[38] = buffer[61]; stat_buffer[39] = buffer[60]; /* st_spare3 4 */ stat_buffer[40] = 0; stat_buffer[41] = 0; stat_buffer[42] = 0; stat_buffer[43] = 0; /* st_blksize 4 */ stat_buffer[44] = buffer[43]; stat_buffer[45] = buffer[42]; stat_buffer[46] = buffer[41]; stat_buffer[47] = buffer[40]; /* st_blocks 4 */ stat_buffer[48] = buffer[51]; stat_buffer[49] = buffer[50]; stat_buffer[50] = buffer[49]; stat_buffer[51] = buffer[48]; /* st_spare4 8 */ stat_buffer[52] = 0; stat_buffer[53] = 0; stat_buffer[54] = 0; stat_buffer[55] = 0; stat_buffer[56] = 0; stat_buffer[57] = 0; stat_buffer[58] = 0; stat_buffer[59] = 0; return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_STAT_SIZE, stat_buffer); } else if (NDS32_SYSCALL_GETTIMEOFDAY == nds32->active_syscall_id) { /* If doing GDB file-I/O, target should convert 'struct timeval' * from gdb-format to target-format */ uint8_t timeval_buffer[NDS32_STRUCT_TIMEVAL_SIZE]; timeval_buffer[0] = buffer[3]; timeval_buffer[1] = buffer[2]; timeval_buffer[2] = buffer[1]; timeval_buffer[3] = buffer[0]; timeval_buffer[4] = buffer[11]; timeval_buffer[5] = buffer[10]; timeval_buffer[6] = buffer[9]; timeval_buffer[7] = buffer[8]; return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_TIMEVAL_SIZE, timeval_buffer); } return nds32_write_buffer(nds32->target, address, size, buffer); } int nds32_reset_halt(struct nds32 *nds32) { LOG_INFO("reset halt as init"); struct aice_port_s *aice = target_to_aice(nds32->target); aice_assert_srst(aice, AICE_RESET_HOLD); return ERROR_OK; } openocd-0.9.0/src/target/nds32.h0000644000175000017500000003147512516456304013267 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_H__ #define __NDS32_H__ #include #include "target.h" #include "target_type.h" #include "register.h" #include "breakpoints.h" #include "nds32_reg.h" #include "nds32_insn.h" #include "nds32_edm.h" #define NDS32_EDM_OPERATION_MAX_NUM 64 #define CHECK_RETVAL(action) \ do { \ int __retval = (action); \ if (__retval != ERROR_OK) { \ LOG_DEBUG("error while calling \"%s\"", \ # action); \ return __retval; \ } \ } while (0) /** * @file * Holds the interface to Andes cores. */ extern const char *nds32_debug_type_name[11]; enum nds32_debug_reason { NDS32_DEBUG_BREAK = 0, NDS32_DEBUG_BREAK_16, NDS32_DEBUG_INST_BREAK, NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE, NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE, NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE, NDS32_DEBUG_DEBUG_INTERRUPT, NDS32_DEBUG_HARDWARE_SINGLE_STEP, NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE, NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE, NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP, }; #define NDS32_STRUCT_STAT_SIZE 60 #define NDS32_STRUCT_TIMEVAL_SIZE 8 enum nds32_syscall_id { NDS32_SYSCALL_UNDEFINED = 0, NDS32_SYSCALL_EXIT = 1, NDS32_SYSCALL_OPEN = 2, NDS32_SYSCALL_CLOSE = 3, NDS32_SYSCALL_READ = 4, NDS32_SYSCALL_WRITE = 5, NDS32_SYSCALL_LSEEK = 6, NDS32_SYSCALL_UNLINK = 7, NDS32_SYSCALL_RENAME = 3001, NDS32_SYSCALL_FSTAT = 10, NDS32_SYSCALL_STAT = 15, NDS32_SYSCALL_GETTIMEOFDAY = 19, NDS32_SYSCALL_ISATTY = 3002, NDS32_SYSCALL_SYSTEM = 3003, NDS32_SYSCALL_ERRNO = 6001, }; #define NDS32_COMMON_MAGIC (int)0xADE5ADE5 struct nds32_edm { /** EDM_CFG.VER, indicate the EDM version */ int version; /** The number of hardware breakpoints */ int breakpoint_num; /** EDM_CFG.DALM, indicate if direct local memory access * feature is supported or not */ bool direct_access_local_memory; /** Support ACC_CTL register */ bool access_control; /** */ bool support_max_stop; }; struct nds32_cache { /** enable cache or not */ bool enable; /** cache sets per way */ int set; /** cache ways */ int way; /** cache line size */ int line_size; /** cache locking support */ bool lock_support; }; struct nds32_memory { /** ICache */ struct nds32_cache icache; /** DCache */ struct nds32_cache dcache; /** On-chip instruction local memory base */ int ilm_base; /** On-chip instruction local memory size */ int ilm_size; /** ILM base register alignment version */ int ilm_align_ver; /** DLM is enabled or not */ bool ilm_enable; /** DLM start address */ int ilm_start; /** DLM end address */ int ilm_end; /** On-chip data local memory base */ int dlm_base; /** On-chip data local memory size */ int dlm_size; /** DLM base register alignment version */ int dlm_align_ver; /** DLM is enabled or not */ bool dlm_enable; /** DLM start address */ int dlm_start; /** DLM end address */ int dlm_end; /** Memory access method */ enum nds_memory_access access_channel; /** Memory access mode */ enum nds_memory_select mode; /** Address translation */ bool address_translation; }; struct nds32_cpu_version { bool performance_extension; bool _16bit_extension; bool performance_extension_2; bool cop_fpu_extension; bool string_extension; int revision; int cpu_id_family; int cpu_id_version; }; struct nds32_mmu_config { int memory_protection; int memory_protection_version; bool fully_associative_tlb; int tlb_size; int tlb_ways; int tlb_sets; bool _8k_page_support; int extra_page_size_support; bool tlb_lock; bool hardware_page_table_walker; bool default_endian; int partition_num; bool invisible_tlb; bool vlpt; bool ntme; bool drde; int default_min_page_size; bool multiple_page_size_in_use; }; struct nds32_misc_config { bool edm; bool local_memory_dma; bool performance_monitor; bool high_speed_memory_port; bool debug_tracer; bool div_instruction; bool mac_instruction; int audio_isa; bool L2_cache; bool reduce_register; bool addr_24; bool interruption_level; int baseline_instruction; bool no_dx_register; bool implement_dependant_register; bool implement_dependant_sr_encoding; bool ifc; bool mcu; bool ex9; int shadow; }; /** * Represents a generic Andes core. */ struct nds32 { int common_magic; struct reg_cache *core_cache; /** Handle for the debug module. */ struct nds32_edm edm; /** Memory information */ struct nds32_memory memory; /** cpu version */ struct nds32_cpu_version cpu_version; /** MMU configuration */ struct nds32_mmu_config mmu_config; /** Misc configuration */ struct nds32_misc_config misc_config; /** Retrieve all core registers, for display. */ int (*full_context)(struct nds32 *nds32); /** Register mappings */ int (*register_map)(struct nds32 *nds32, int reg_no); /** Get debug exception virtual address */ int (*get_debug_reason)(struct nds32 *nds32, uint32_t *reason); /** Restore target registers may be modified in debug state */ int (*leave_debug_state)(struct nds32 *nds32, bool enable_watchpoint); /** Backup target registers may be modified in debug state */ int (*enter_debug_state)(struct nds32 *nds32, bool enable_watchpoint); /** Get address hit watchpoint */ int (*get_watched_address)(struct nds32 *nds32, uint32_t *address, uint32_t reason); /** maximum interrupt level */ uint32_t max_interrupt_level; /** current interrupt level */ uint32_t current_interrupt_level; uint32_t watched_address; /** Flag reporting whether virtual hosting is active. */ bool virtual_hosting; /** Flag reporting whether continue/step hits syscall or not */ bool hit_syscall; /** Value to be returned by virtual hosting SYS_ERRNO request. */ int virtual_hosting_errno; /** Flag reporting whether syscall is aborted */ bool virtual_hosting_ctrl_c; /** Record syscall ID for other operations to do special processing for target */ int active_syscall_id; struct breakpoint syscall_break; /** Flag reporting whether global stop is active. */ bool global_stop; /** Flag reporting whether to use soft-reset-halt or not as issuing reset-halt. */ bool soft_reset_halt; /** reset-halt as target examine */ bool reset_halt_as_examine; /** backup/restore target EDM_CTL value. As debugging target debug * handler, it should be true. */ bool keep_target_edm_ctl; /* Value of $EDM_CTL before target enters debug mode */ uint32_t backup_edm_ctl; /** always use word-aligned address to access memory */ bool word_access_mem; /** EDM passcode for debugging secure MCU */ char *edm_passcode; /** current privilege_level if using secure MCU. value 0 is the highest level. */ int privilege_level; /** Period to wait after SRST. */ uint32_t boot_time; /** Flag to indicate HSS steps into ISR or not */ bool step_isr_enable; /** Flag to indicate register table is ready or not */ bool init_arch_info_after_halted; /** Flag to indicate audio-extension is enabled or not */ bool audio_enable; /** Flag to indicate fpu-extension is enabled or not */ bool fpu_enable; /* Andes Core has mixed endian model. Instruction is always big-endian. * Data may be big or little endian. Device registers may have different * endian from data and instruction. */ /** Endian of data memory */ enum target_endianness data_endian; /** Endian of device registers */ enum target_endianness device_reg_endian; /** Flag to indicate if auto convert software breakpoints to * hardware breakpoints or not in ROM */ bool auto_convert_hw_bp; /* Flag to indicate the target is attached by debugger or not */ bool attached; /** Backpointer to the target. */ struct target *target; void *arch_info; }; struct nds32_reg { int32_t num; uint8_t value[8]; struct target *target; struct nds32 *nds32; bool enable; }; struct nds32_edm_operation { uint32_t reg_no; uint32_t value; }; extern int nds32_config(struct nds32 *nds32); extern int nds32_init_arch_info(struct target *target, struct nds32 *nds32); extern int nds32_full_context(struct nds32 *nds32); extern int nds32_arch_state(struct target *target); extern int nds32_add_software_breakpoint(struct target *target, struct breakpoint *breakpoint); extern int nds32_remove_software_breakpoint(struct target *target, struct breakpoint *breakpoint); extern int nds32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); extern int nds32_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer); extern int nds32_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer); extern int nds32_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); extern int nds32_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); extern int nds32_init_register_table(struct nds32 *nds32); extern int nds32_init_memory_info(struct nds32 *nds32); extern int nds32_restore_context(struct target *target); extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value); extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value); extern int nds32_edm_config(struct nds32 *nds32); extern int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length); extern int nds32_mmu(struct target *target, int *enabled); extern int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical); extern int nds32_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); extern int nds32_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address); extern int nds32_examine_debug_reason(struct nds32 *nds32); extern int nds32_step(struct target *target, int current, uint32_t address, int handle_breakpoints); extern int nds32_target_state(struct nds32 *nds32, enum target_state *state); extern int nds32_halt(struct target *target); extern int nds32_poll(struct target *target); extern int nds32_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); extern int nds32_assert_reset(struct target *target); extern int nds32_init(struct nds32 *nds32); extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); extern int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address, uint32_t size, const uint8_t *buffer); extern int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c); extern int nds32_reset_halt(struct nds32 *nds32); extern int nds32_login(struct nds32 *nds32); extern int nds32_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); /** Convert target handle to generic Andes target state handle. */ static inline struct nds32 *target_to_nds32(struct target *target) { assert(target != NULL); return target->arch_info; } /** */ static inline struct aice_port_s *target_to_aice(struct target *target) { assert(target != NULL); return target->tap->priv; } static inline bool is_nds32(struct nds32 *nds32) { assert(nds32 != NULL); return nds32->common_magic == NDS32_COMMON_MAGIC; } static inline bool nds32_reach_max_interrupt_level(struct nds32 *nds32) { assert(nds32 != NULL); return nds32->max_interrupt_level == nds32->current_interrupt_level; } #endif /* __NDS32_H__ */ openocd-0.9.0/src/target/avr32_mem.c0000644000175000017500000001671212315575361014123 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "jtag/jtag.h" #include "avr32_jtag.h" #include "avr32_mem.h" int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint32_t *buffer) { int i, retval; uint32_t data; for (i = 0; i < count; i++) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i*4, &data); if (retval != ERROR_OK) return retval; /* XXX: Assume AVR32 is BE */ buffer[i] = be_to_h_u32((uint8_t *)&data); } return ERROR_OK; } int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint16_t *buffer) { int i, retval; uint32_t data; i = 0; /* any unaligned half-words? */ if (addr & 3) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, &data); if (retval != ERROR_OK) return retval; /* XXX: Assume AVR32 is BE */ data = be_to_h_u32((uint8_t *)&data); buffer[i] = (data >> 16) & 0xffff; i++; } /* read all complete words */ for (; i < (count & ~1); i += 2) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, &data); if (retval != ERROR_OK) return retval; /* XXX: Assume AVR32 is BE */ data = be_to_h_u32((uint8_t *)&data); buffer[i] = data & 0xffff; buffer[i+1] = (data >> 16) & 0xffff; } /* last halfword */ if (i < count) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, &data); if (retval != ERROR_OK) return retval; /* XXX: Assume AVR32 is BE */ data = be_to_h_u32((uint8_t *)&data); buffer[i] = data & 0xffff; } return ERROR_OK; } int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint8_t *buffer) { int i, j, retval; uint8_t data[4]; i = 0; /* Do we have non-aligned bytes? */ if (addr & 3) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i, (uint32_t *)(void *)data); if (retval != ERROR_OK) return retval; for (j = addr & 3; (j < 4) && (i < count); j++, i++) buffer[i] = data[3-j]; } /* read all complete words */ for (; i < (count & ~3); i += 4) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i, (uint32_t *)(void *)data); if (retval != ERROR_OK) return retval; for (j = 0; j < 4; j++) buffer[i+j] = data[3-j]; } /* remaining bytes */ if (i < count) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i, (uint32_t *)(void *)data); if (retval != ERROR_OK) return retval; for (j = 0; i + j < count; j++) buffer[i+j] = data[3-j]; } return ERROR_OK; } int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint32_t *buffer) { int i, retval; uint32_t data; for (i = 0; i < count; i++) { /* XXX: Assume AVR32 is BE */ h_u32_to_be((uint8_t *)&data, buffer[i]); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr + i*4, data); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint16_t *buffer) { int i, retval; uint32_t data; uint32_t data_out; i = 0; /* * Do we have any non-aligned half-words? */ if (addr & 3) { /* * mwa_read will read whole world, no nead to fiddle * with address. It will be truncated in set_addr */ retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr, &data); if (retval != ERROR_OK) return retval; data = be_to_h_u32((uint8_t *)&data); data = (buffer[i] << 16) | (data & 0xffff); h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr, data_out); if (retval != ERROR_OK) return retval; i++; } /* write all complete words */ for (; i < (count & ~1); i += 2) { /* XXX: Assume AVR32 is BE */ data = (buffer[i+1] << 16) | buffer[i]; h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, data_out); if (retval != ERROR_OK) return retval; } /* last halfword */ if (i < count) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, &data); if (retval != ERROR_OK) return retval; data = be_to_h_u32((uint8_t *)&data); data &= ~0xffff; data |= buffer[i]; h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr + i*2, data_out); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint8_t *buffer) { int i, j, retval; uint32_t data; uint32_t data_out; i = 0; /* * Do we have any non-aligned bytes? */ if (addr & 3) { /* * mwa_read will read whole world, no nead to fiddle * with address. It will be truncated in set_addr */ retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr, &data); if (retval != ERROR_OK) return retval; data = be_to_h_u32((uint8_t *)&data); for (j = addr & 3; (j < 4) && (i < count); j++, i++) { data &= ~(0xff << j*8); data |= (buffer[i] << j*8); } h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr, data_out); if (retval != ERROR_OK) return retval; } /* write all complete words */ for (; i < (count & ~3); i += 4) { data = 0; for (j = 0; j < 4; j++) data |= (buffer[j+i] << j*8); h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr + i, data_out); if (retval != ERROR_OK) return retval; } /* * Write trailing bytes */ if (i < count) { retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED, addr + i, &data); if (retval != ERROR_OK) return retval; data = be_to_h_u32((uint8_t *)&data); for (j = 0; i < count; j++, i++) { data &= ~(0xff << j*8); data |= (buffer[j+i] << j*8); } h_u32_to_be((uint8_t *)&data_out, data); retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED, addr+i, data_out); if (retval != ERROR_OK) return retval; } return ERROR_OK; } openocd-0.9.0/src/target/avr32_mem.h0000644000175000017500000000406712315575361014130 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef AVR32_MEM #define AVR32_MEM int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint32_t *buffer); int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint16_t *buffer); int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint8_t *buffer); int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint32_t *buffer); int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint16_t *buffer); int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint8_t *buffer); #endif /* AVR32_MEM */ openocd-0.9.0/src/target/Makefile.am0000644000175000017500000000617012516456303014212 00000000000000include $(top_srcdir)/common.mk if OOCD_TRACE OOCD_TRACE_FILES = oocd_trace.c else OOCD_TRACE_FILES = endif SUBDIRS = openrisc libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la BIN2C = $(top_srcdir)/src/helper/bin2char.sh DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin EXTRA_DIST = \ startup.tcl \ $(wildcard $(srcdir)/xscale/*) DEBUG_HEADER = xscale_debug.inc BUILT_SOURCES = $(DEBUG_HEADER) CLEANFILES = $(DEBUG_HEADER) $(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C) $(BIN2C) < $< > $@ || { rm -f $@; false; } METASOURCES = AUTO noinst_LTLIBRARIES = libtarget.la libtarget_la_SOURCES = \ $(TARGET_CORE_SRC) \ $(ARM_DEBUG_SRC) \ $(ARMV4_5_SRC) \ $(ARMV6_SRC) \ $(ARMV7_SRC) \ $(ARM_MISC_SRC) \ $(AVR32_SRC) \ $(MIPS32_SRC) \ $(NDS32_SRC) \ $(INTEL_IA32_SRC) \ avrt.c \ dsp563xx.c \ dsp563xx_once.c \ dsp5680xx.c \ hla_target.c TARGET_CORE_SRC = \ algorithm.c \ register.c \ image.c \ breakpoints.c \ target.c \ target_request.c \ testee.c \ smp.c ARMV4_5_SRC = \ armv4_5.c \ armv4_5_mmu.c \ armv4_5_cache.c \ $(ARM7_9_SRC) ARM7_9_SRC = \ arm7_9_common.c \ arm7tdmi.c \ arm720t.c \ arm9tdmi.c \ arm920t.c \ arm966e.c \ arm946e.c \ arm926ejs.c \ feroceon.c ARM_MISC_SRC = \ fa526.c \ xscale.c ARMV6_SRC = \ arm11.c \ arm11_dbgtap.c ARMV7_SRC = \ armv7m.c \ armv7m_trace.c \ cortex_m.c \ armv7a.c \ cortex_a.c ARM_DEBUG_SRC = \ arm_dpm.c \ arm_jtag.c \ arm_disassembler.c \ arm_simulator.c \ arm_semihosting.c \ arm_adi_v5.c \ adi_v5_jtag.c \ adi_v5_swd.c \ embeddedice.c \ trace.c \ etb.c \ etm.c \ $(OOCD_TRACE_FILES) \ etm_dummy.c AVR32_SRC = \ avr32_ap7k.c \ avr32_jtag.c \ avr32_mem.c \ avr32_regs.c MIPS32_SRC = \ mips32.c \ mips_m4k.c \ mips32_pracc.c \ mips32_dmaacc.c \ mips_ejtag.c NDS32_SRC = \ nds32.c \ nds32_reg.c \ nds32_cmd.c \ nds32_disassembler.c \ nds32_tlb.c \ nds32_v2.c \ nds32_v3_common.c \ nds32_v3.c \ nds32_v3m.c \ nds32_aice.c INTEL_IA32_SRC = \ quark_x10xx.c \ lakemont.c \ x86_32_common.c noinst_HEADERS = \ algorithm.h \ arm.h \ arm_dpm.h \ arm_jtag.h \ arm_adi_v5.h \ arm_disassembler.h \ arm_opcodes.h \ arm_simulator.h \ arm_semihosting.h \ arm7_9_common.h \ arm7tdmi.h \ arm720t.h \ arm9tdmi.h \ arm920t.h \ arm926ejs.h \ arm966e.h \ arm946e.h \ arm11.h \ arm11_dbgtap.h \ armv4_5.h \ armv4_5_mmu.h \ armv4_5_cache.h \ armv7a.h \ armv7m.h \ armv7m_trace.h \ avrt.h \ dsp563xx.h \ dsp563xx_once.h \ dsp5680xx.h \ breakpoints.h \ cortex_m.h \ cortex_a.h \ embeddedice.h \ etb.h \ etm.h \ etm_dummy.h \ image.h \ mips32.h \ mips_m4k.h \ mips_ejtag.h \ mips32_pracc.h \ mips32_dmaacc.h \ oocd_trace.h \ register.h \ target.h \ target_type.h \ trace.h \ target_request.h \ trace.h \ xscale.h \ smp.h \ avr32_ap7k.h \ avr32_jtag.h \ avr32_mem.h \ avr32_regs.h \ nds32.h \ nds32_cmd.h \ nds32_disassembler.h \ nds32_edm.h \ nds32_insn.h \ nds32_reg.h \ nds32_tlb.h \ nds32_v2.h \ nds32_v3_common.h \ nds32_v3.h \ nds32_v3m.h \ nds32_aice.h \ lakemont.h \ x86_32_common.h ocddatadir = $(pkglibdir) nobase_dist_ocddata_DATA = MAINTAINERCLEANFILES = $(srcdir)/Makefile.in openocd-0.9.0/src/target/Makefile.in0000644000175000017500000010622712526201652014223 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(nobase_dist_ocddata_DATA) $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/target ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtarget_la_DEPENDENCIES = \ $(top_builddir)/src/target/openrisc/libopenrisc.la am__libtarget_la_SOURCES_DIST = algorithm.c register.c image.c \ breakpoints.c target.c target_request.c testee.c smp.c \ arm_dpm.c arm_jtag.c arm_disassembler.c arm_simulator.c \ arm_semihosting.c arm_adi_v5.c adi_v5_jtag.c adi_v5_swd.c \ embeddedice.c trace.c etb.c etm.c oocd_trace.c etm_dummy.c \ armv4_5.c armv4_5_mmu.c armv4_5_cache.c arm7_9_common.c \ arm7tdmi.c arm720t.c arm9tdmi.c arm920t.c arm966e.c arm946e.c \ arm926ejs.c feroceon.c arm11.c arm11_dbgtap.c armv7m.c \ armv7m_trace.c cortex_m.c armv7a.c cortex_a.c fa526.c xscale.c \ avr32_ap7k.c avr32_jtag.c avr32_mem.c avr32_regs.c mips32.c \ mips_m4k.c mips32_pracc.c mips32_dmaacc.c mips_ejtag.c nds32.c \ nds32_reg.c nds32_cmd.c nds32_disassembler.c nds32_tlb.c \ nds32_v2.c nds32_v3_common.c nds32_v3.c nds32_v3m.c \ nds32_aice.c quark_x10xx.c lakemont.c x86_32_common.c avrt.c \ dsp563xx.c dsp563xx_once.c dsp5680xx.c hla_target.c am__objects_1 = algorithm.lo register.lo image.lo breakpoints.lo \ target.lo target_request.lo testee.lo smp.lo @OOCD_TRACE_TRUE@am__objects_2 = oocd_trace.lo am__objects_3 = arm_dpm.lo arm_jtag.lo arm_disassembler.lo \ arm_simulator.lo arm_semihosting.lo arm_adi_v5.lo \ adi_v5_jtag.lo adi_v5_swd.lo embeddedice.lo trace.lo etb.lo \ etm.lo $(am__objects_2) etm_dummy.lo am__objects_4 = arm7_9_common.lo arm7tdmi.lo arm720t.lo arm9tdmi.lo \ arm920t.lo arm966e.lo arm946e.lo arm926ejs.lo feroceon.lo am__objects_5 = armv4_5.lo armv4_5_mmu.lo armv4_5_cache.lo \ $(am__objects_4) am__objects_6 = arm11.lo arm11_dbgtap.lo am__objects_7 = armv7m.lo armv7m_trace.lo cortex_m.lo armv7a.lo \ cortex_a.lo am__objects_8 = fa526.lo xscale.lo am__objects_9 = avr32_ap7k.lo avr32_jtag.lo avr32_mem.lo avr32_regs.lo am__objects_10 = mips32.lo mips_m4k.lo mips32_pracc.lo \ mips32_dmaacc.lo mips_ejtag.lo am__objects_11 = nds32.lo nds32_reg.lo nds32_cmd.lo \ nds32_disassembler.lo nds32_tlb.lo nds32_v2.lo \ nds32_v3_common.lo nds32_v3.lo nds32_v3m.lo nds32_aice.lo am__objects_12 = quark_x10xx.lo lakemont.lo x86_32_common.lo am_libtarget_la_OBJECTS = $(am__objects_1) $(am__objects_3) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) $(am__objects_12) avrt.lo dsp563xx.lo \ dsp563xx_once.lo dsp5680xx.lo hla_target.lo libtarget_la_OBJECTS = $(am_libtarget_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libtarget_la_SOURCES) DIST_SOURCES = $(am__libtarget_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(ocddatadir)" DATA = $(nobase_dist_ocddata_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) @OOCD_TRACE_FALSE@OOCD_TRACE_FILES = @OOCD_TRACE_TRUE@OOCD_TRACE_FILES = oocd_trace.c SUBDIRS = openrisc libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la BIN2C = $(top_srcdir)/src/helper/bin2char.sh DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin EXTRA_DIST = \ startup.tcl \ $(wildcard $(srcdir)/xscale/*) DEBUG_HEADER = xscale_debug.inc BUILT_SOURCES = $(DEBUG_HEADER) CLEANFILES = $(DEBUG_HEADER) METASOURCES = AUTO noinst_LTLIBRARIES = libtarget.la libtarget_la_SOURCES = \ $(TARGET_CORE_SRC) \ $(ARM_DEBUG_SRC) \ $(ARMV4_5_SRC) \ $(ARMV6_SRC) \ $(ARMV7_SRC) \ $(ARM_MISC_SRC) \ $(AVR32_SRC) \ $(MIPS32_SRC) \ $(NDS32_SRC) \ $(INTEL_IA32_SRC) \ avrt.c \ dsp563xx.c \ dsp563xx_once.c \ dsp5680xx.c \ hla_target.c TARGET_CORE_SRC = \ algorithm.c \ register.c \ image.c \ breakpoints.c \ target.c \ target_request.c \ testee.c \ smp.c ARMV4_5_SRC = \ armv4_5.c \ armv4_5_mmu.c \ armv4_5_cache.c \ $(ARM7_9_SRC) ARM7_9_SRC = \ arm7_9_common.c \ arm7tdmi.c \ arm720t.c \ arm9tdmi.c \ arm920t.c \ arm966e.c \ arm946e.c \ arm926ejs.c \ feroceon.c ARM_MISC_SRC = \ fa526.c \ xscale.c ARMV6_SRC = \ arm11.c \ arm11_dbgtap.c ARMV7_SRC = \ armv7m.c \ armv7m_trace.c \ cortex_m.c \ armv7a.c \ cortex_a.c ARM_DEBUG_SRC = \ arm_dpm.c \ arm_jtag.c \ arm_disassembler.c \ arm_simulator.c \ arm_semihosting.c \ arm_adi_v5.c \ adi_v5_jtag.c \ adi_v5_swd.c \ embeddedice.c \ trace.c \ etb.c \ etm.c \ $(OOCD_TRACE_FILES) \ etm_dummy.c AVR32_SRC = \ avr32_ap7k.c \ avr32_jtag.c \ avr32_mem.c \ avr32_regs.c MIPS32_SRC = \ mips32.c \ mips_m4k.c \ mips32_pracc.c \ mips32_dmaacc.c \ mips_ejtag.c NDS32_SRC = \ nds32.c \ nds32_reg.c \ nds32_cmd.c \ nds32_disassembler.c \ nds32_tlb.c \ nds32_v2.c \ nds32_v3_common.c \ nds32_v3.c \ nds32_v3m.c \ nds32_aice.c INTEL_IA32_SRC = \ quark_x10xx.c \ lakemont.c \ x86_32_common.c noinst_HEADERS = \ algorithm.h \ arm.h \ arm_dpm.h \ arm_jtag.h \ arm_adi_v5.h \ arm_disassembler.h \ arm_opcodes.h \ arm_simulator.h \ arm_semihosting.h \ arm7_9_common.h \ arm7tdmi.h \ arm720t.h \ arm9tdmi.h \ arm920t.h \ arm926ejs.h \ arm966e.h \ arm946e.h \ arm11.h \ arm11_dbgtap.h \ armv4_5.h \ armv4_5_mmu.h \ armv4_5_cache.h \ armv7a.h \ armv7m.h \ armv7m_trace.h \ avrt.h \ dsp563xx.h \ dsp563xx_once.h \ dsp5680xx.h \ breakpoints.h \ cortex_m.h \ cortex_a.h \ embeddedice.h \ etb.h \ etm.h \ etm_dummy.h \ image.h \ mips32.h \ mips_m4k.h \ mips_ejtag.h \ mips32_pracc.h \ mips32_dmaacc.h \ oocd_trace.h \ register.h \ target.h \ target_type.h \ trace.h \ target_request.h \ trace.h \ xscale.h \ smp.h \ avr32_ap7k.h \ avr32_jtag.h \ avr32_mem.h \ avr32_regs.h \ nds32.h \ nds32_cmd.h \ nds32_disassembler.h \ nds32_edm.h \ nds32_insn.h \ nds32_reg.h \ nds32_tlb.h \ nds32_v2.h \ nds32_v3_common.h \ nds32_v3.h \ nds32_v3m.h \ nds32_aice.h \ lakemont.h \ x86_32_common.h ocddatadir = $(pkglibdir) nobase_dist_ocddata_DATA = MAINTAINERCLEANFILES = $(srcdir)/Makefile.in all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/target/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/target/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libtarget.la: $(libtarget_la_OBJECTS) $(libtarget_la_DEPENDENCIES) $(EXTRA_libtarget_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtarget_la_OBJECTS) $(libtarget_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adi_v5_jtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adi_v5_swd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/algorithm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm11_dbgtap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm720t.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm7_9_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm7tdmi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm920t.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm926ejs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm946e.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm966e.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm9tdmi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_adi_v5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_disassembler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_dpm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_jtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_semihosting.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_simulator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv4_5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv4_5_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv4_5_mmu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv7a.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv7m.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armv7m_trace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avr32_ap7k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avr32_jtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avr32_mem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avr32_regs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avrt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/breakpoints.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cortex_a.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cortex_m.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsp563xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsp563xx_once.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsp5680xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/embeddedice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etm_dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fa526.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/feroceon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hla_target.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lakemont.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips32_dmaacc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips32_pracc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips_ejtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips_m4k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_aice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_cmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_disassembler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_reg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_tlb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_v2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_v3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_v3_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32_v3m.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oocd_trace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quark_x10xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/register.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testee.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_32_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xscale.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_dist_ocddataDATA: $(nobase_dist_ocddata_DATA) @$(NORMAL_INSTALL) @list='$(nobase_dist_ocddata_DATA)'; test -n "$(ocddatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(ocddatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(ocddatadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(ocddatadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(ocddatadir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(ocddatadir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(ocddatadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_dist_ocddataDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_ocddata_DATA)'; test -n "$(ocddatadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(ocddatadir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(ocddatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-nobase_dist_ocddataDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-nobase_dist_ocddataDATA .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-nobase_dist_ocddataDATA install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-nobase_dist_ocddataDATA $(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C) $(BIN2C) < $< > $@ || { rm -f $@; false; } # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/target/trace.c0000644000175000017500000001312212315575361013416 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "trace.h" #include "target.h" int trace_point(struct target *target, uint32_t number) { struct trace *trace = target->trace_info; LOG_DEBUG("tracepoint: %i", (int)number); if (number < trace->num_trace_points) trace->trace_points[number].hit_counter++; if (trace->trace_history_size) { trace->trace_history[trace->trace_history_pos++] = number; if (trace->trace_history_pos == trace->trace_history_size) { trace->trace_history_pos = 0; trace->trace_history_overflowed = 1; } } return ERROR_OK; } COMMAND_HANDLER(handle_trace_point_command) { struct target *target = get_current_target(CMD_CTX); struct trace *trace = target->trace_info; if (CMD_ARGC == 0) { uint32_t i; for (i = 0; i < trace->num_trace_points; i++) { command_print(CMD_CTX, "trace point 0x%8.8" PRIx32 " (%lld times hit)", trace->trace_points[i].address, (long long)trace->trace_points[i].hit_counter); } return ERROR_OK; } if (!strcmp(CMD_ARGV[0], "clear")) { if (trace->trace_points) { free(trace->trace_points); trace->trace_points = NULL; } trace->num_trace_points = 0; trace->trace_points_size = 0; return ERROR_OK; } /* resize array if necessary */ if (!trace->trace_points || (trace->trace_points_size == trace->num_trace_points)) { trace->trace_points = realloc(trace->trace_points, sizeof(struct trace_point) * (trace->trace_points_size + 32)); trace->trace_points_size += 32; } uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); trace->trace_points[trace->num_trace_points].address = address; trace->trace_points[trace->num_trace_points].hit_counter = 0; trace->num_trace_points++; return ERROR_OK; } COMMAND_HANDLER(handle_trace_history_command) { struct target *target = get_current_target(CMD_CTX); struct trace *trace = target->trace_info; if (CMD_ARGC > 0) { trace->trace_history_pos = 0; trace->trace_history_overflowed = 0; if (!strcmp(CMD_ARGV[0], "clear")) { /* clearing is implicit, we've just reset position anyway */ return ERROR_OK; } if (trace->trace_history) free(trace->trace_history); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], trace->trace_history_size); trace->trace_history = malloc(sizeof(uint32_t) * trace->trace_history_size); command_print(CMD_CTX, "new trace history size: %i", (int)(trace->trace_history_size)); } else { uint32_t i; uint32_t first = 0; uint32_t last = trace->trace_history_pos; if (!trace->trace_history_size) { command_print(CMD_CTX, "trace history buffer is not allocated"); return ERROR_OK; } if (trace->trace_history_overflowed) { first = trace->trace_history_pos; last = trace->trace_history_pos - 1; } for (i = first; (i % trace->trace_history_size) != last; i++) { if (trace->trace_history[i % trace->trace_history_size] < trace->num_trace_points) { uint32_t address; address = trace->trace_points[trace->trace_history[i % trace->trace_history_size]].address; command_print(CMD_CTX, "trace point %i: 0x%8.8" PRIx32 "", (int)(trace->trace_history[i % trace->trace_history_size]), address); } else command_print(CMD_CTX, "trace point %i: -not defined-", (int)(trace->trace_history[i % trace->trace_history_size])); } } return ERROR_OK; } static const struct command_registration trace_exec_command_handlers[] = { { .name = "history", .handler = handle_trace_history_command, .mode = COMMAND_EXEC, .help = "display trace history, clear history or set size", .usage = "['clear'|size]", }, { .name = "point", .handler = handle_trace_point_command, .mode = COMMAND_EXEC, .help = "display trace points, clear list of trace points, " "or add new tracepoint at address", .usage = "['clear'|address]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration trace_command_handlers[] = { { .name = "trace", .mode = COMMAND_EXEC, .help = "trace command group", .usage = "", .chain = trace_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; int trace_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, trace_command_handlers); } openocd-0.9.0/src/target/trace.h0000644000175000017500000000454212315575361013431 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TRACE_H #define TRACE_H struct target; struct command_context; struct trace_point { uint32_t address; uint64_t hit_counter; }; struct trace { uint32_t num_trace_points; uint32_t trace_points_size; struct trace_point *trace_points; uint32_t trace_history_size; uint32_t *trace_history; uint32_t trace_history_pos; int trace_history_overflowed; }; /** * \todo This enum is one of the few things in this file related * to *hardware* tracing ... split such "real" tracing out from * the contrib/libdcc support. */ typedef enum trace_status { TRACE_IDLE = 0x0, TRACE_RUNNING = 0x1, TRACE_TRIGGERED = 0x2, TRACE_COMPLETED = 0x4, TRACE_OVERFLOWED = 0x8, } trace_status_t; int trace_point(struct target *target, uint32_t number); int trace_register_commands(struct command_context *cmd_ctx); #define ERROR_TRACE_IMAGE_UNAVAILABLE (-1500) #define ERROR_TRACE_INSTRUCTION_UNAVAILABLE (-1501) #endif /* TRACE_H */ openocd-0.9.0/src/target/avr32_regs.c0000644000175000017500000000656512315575361014312 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "jtag/jtag.h" #include "avr32_jtag.h" #include "avr32_regs.h" static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg, uint32_t *val) { int retval; uint32_t dcsr; retval = avr32_jtag_exec(jtag_info, MTDR(AVR32_OCDREG_DCCPU, reg)); if (retval != ERROR_OK) return retval; do { retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DCSR, &dcsr); if (retval != ERROR_OK) return retval; } while (!(dcsr & OCDREG_DCSR_CPUD)); retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DCCPU, val); return retval; } static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg, uint32_t val) { int retval; uint32_t dcsr; /* Restore Status reg */ retval = avr32_jtag_nexus_write(jtag_info, AVR32_OCDREG_DCEMU, val); if (retval != ERROR_OK) return retval; retval = avr32_jtag_exec(jtag_info, MFDR(reg, AVR32_OCDREG_DCEMU)); if (retval != ERROR_OK) return retval; do { retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DCSR, &dcsr); } while (!(dcsr & OCDREG_DCSR_EMUD) && (retval == ERROR_OK)); return retval; } int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs) { int i, retval; /* read core registers */ for (i = 0; i < AVR32NUMCOREREGS - 1; i++) avr32_jtag_read_reg(jtag_info, i, regs + i); /* read status register */ retval = avr32_jtag_exec(jtag_info, MFSR(0, 0)); if (retval != ERROR_OK) return retval; retval = avr32_jtag_read_reg(jtag_info, 0, regs + AVR32_REG_SR); return retval; } int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs) { int i, retval; retval = avr32_jtag_write_reg(jtag_info, 0, regs[AVR32_REG_SR]); if (retval != ERROR_OK) return retval; /* Restore Status reg */ retval = avr32_jtag_exec(jtag_info, MTSR(0, 0)); if (retval != ERROR_OK) return retval; /* * And now the rest of registers */ for (i = 0; i < AVR32NUMCOREREGS - 1; i++) avr32_jtag_write_reg(jtag_info, i, regs[i]); return ERROR_OK; } openocd-0.9.0/src/target/avr32_regs.h0000644000175000017500000000353512315575361014311 00000000000000/*************************************************************************** * Copyright (C) 2010 by Oleksandr Tymoshenko * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef AVR32_REGS #define AVR32_REGS enum avr32_reg_nums { AVR32_REG_R0 = 0, AVR32_REG_R1, AVR32_REG_R2, AVR32_REG_R3, AVR32_REG_R4, AVR32_REG_R5, AVR32_REG_R6, AVR32_REG_R7, AVR32_REG_R8, AVR32_REG_R9, AVR32_REG_R10, AVR32_REG_R11, AVR32_REG_R12, AVR32_REG_SP, AVR32_REG_LR, AVR32_REG_PC, AVR32_REG_SR, }; int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs); int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs); #endif /* AVR32_REGS */ openocd-0.9.0/src/target/xscale.c0000644000175000017500000031374312516456304013611 00000000000000/*************************************************************************** * Copyright (C) 2006, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 Michael Schwingen * * michael@schwingen.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "xscale.h" #include "target_type.h" #include "arm_jtag.h" #include "arm_simulator.h" #include "arm_disassembler.h" #include #include "register.h" #include "image.h" #include "arm_opcodes.h" #include "armv4_5.h" /* * Important XScale documents available as of October 2009 include: * * Intel XScale® Core Developer’s Manual, January 2004 * Order Number: 273473-002 * This has a chapter detailing debug facilities, and punts some * details to chip-specific microarchitecture documents. * * Hot-Debug for Intel XScale® Core Debug White Paper, May 2005 * Document Number: 273539-005 * Less detailed than the developer's manual, but summarizes those * missing details (for most XScales) and gives LOTS of notes about * debugger/handler interaction issues. Presents a simpler reset * and load-handler sequence than the arch doc. (Note, OpenOCD * doesn't currently support "Hot-Debug" as defined there.) * * Chip-specific microarchitecture documents may also be useful. */ /* forward declarations */ static int xscale_resume(struct target *, int current, uint32_t address, int handle_breakpoints, int debug_execution); static int xscale_debug_entry(struct target *); static int xscale_restore_banked(struct target *); static int xscale_get_reg(struct reg *reg); static int xscale_set_reg(struct reg *reg, uint8_t *buf); static int xscale_set_breakpoint(struct target *, struct breakpoint *); static int xscale_set_watchpoint(struct target *, struct watchpoint *); static int xscale_unset_breakpoint(struct target *, struct breakpoint *); static int xscale_read_trace(struct target *); /* This XScale "debug handler" is loaded into the processor's * mini-ICache, which is 2K of code writable only via JTAG. */ static const uint8_t xscale_debug_handler[] = { #include "xscale_debug.inc" }; static const char *const xscale_reg_list[] = { "XSCALE_MAINID", /* 0 */ "XSCALE_CACHETYPE", "XSCALE_CTRL", "XSCALE_AUXCTRL", "XSCALE_TTB", "XSCALE_DAC", "XSCALE_FSR", "XSCALE_FAR", "XSCALE_PID", "XSCALE_CPACCESS", "XSCALE_IBCR0", /* 10 */ "XSCALE_IBCR1", "XSCALE_DBR0", "XSCALE_DBR1", "XSCALE_DBCON", "XSCALE_TBREG", "XSCALE_CHKPT0", "XSCALE_CHKPT1", "XSCALE_DCSR", "XSCALE_TX", "XSCALE_RX", /* 20 */ "XSCALE_TXRXCTRL", }; static const struct xscale_reg xscale_reg_arch_info[] = { {XSCALE_MAINID, NULL}, {XSCALE_CACHETYPE, NULL}, {XSCALE_CTRL, NULL}, {XSCALE_AUXCTRL, NULL}, {XSCALE_TTB, NULL}, {XSCALE_DAC, NULL}, {XSCALE_FSR, NULL}, {XSCALE_FAR, NULL}, {XSCALE_PID, NULL}, {XSCALE_CPACCESS, NULL}, {XSCALE_IBCR0, NULL}, {XSCALE_IBCR1, NULL}, {XSCALE_DBR0, NULL}, {XSCALE_DBR1, NULL}, {XSCALE_DBCON, NULL}, {XSCALE_TBREG, NULL}, {XSCALE_CHKPT0, NULL}, {XSCALE_CHKPT1, NULL}, {XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */ {-1, NULL}, /* TX accessed via JTAG */ {-1, NULL}, /* RX accessed via JTAG */ {-1, NULL}, /* TXRXCTRL implicit access via JTAG */ }; /* convenience wrapper to access XScale specific registers */ static int xscale_set_reg_u32(struct reg *reg, uint32_t value) { uint8_t buf[4]; buf_set_u32(buf, 0, 32, value); return xscale_set_reg(reg, buf); } static const char xscale_not[] = "target is not an XScale"; static int xscale_verify_pointer(struct command_context *cmd_ctx, struct xscale_common *xscale) { if (xscale->common_magic != XSCALE_COMMON_MAGIC) { command_print(cmd_ctx, xscale_not); return ERROR_TARGET_INVALID; } return ERROR_OK; } static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) { assert(tap != NULL); if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { struct scan_field field; uint8_t scratch[4]; memset(&field, 0, sizeof field); field.num_bits = tap->ir_length; field.out_value = scratch; buf_set_u32(scratch, 0, field.num_bits, new_instr); jtag_add_ir_scan(tap, &field, end_state); } return ERROR_OK; } static int xscale_read_dcsr(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); int retval; struct scan_field fields[3]; uint8_t field0 = 0x0; uint8_t field0_check_value = 0x2; uint8_t field0_check_mask = 0x7; uint8_t field2 = 0x0; uint8_t field2_check_value = 0x0; uint8_t field2_check_mask = 0x1; xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR << xscale->xscale_variant, TAP_DRPAUSE); buf_set_u32(&field0, 1, 1, xscale->hold_rst); buf_set_u32(&field0, 2, 1, xscale->external_debug_break); memset(&fields, 0, sizeof fields); fields[0].num_bits = 3; fields[0].out_value = &field0; uint8_t tmp; fields[0].in_value = &tmp; fields[1].num_bits = 32; fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value; fields[2].num_bits = 1; fields[2].out_value = &field2; uint8_t tmp2; fields[2].in_value = &tmp2; jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE); jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask); jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while reading DCSR"); return retval; } xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0; xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1; /* write the register with the value we just read * on this second pass, only the first bit of field0 is guaranteed to be 0) */ field0_check_mask = 0x1; fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value; fields[1].in_value = NULL; jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE); /* DANGER!!! this must be here. It will make sure that the arguments * to jtag_set_check_value() does not go out of scope! */ return jtag_execute_queue(); } static void xscale_getbuf(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = buf_get_u32(in, 0, 32); } static int xscale_receive(struct target *target, uint32_t *buffer, int num_words) { if (num_words == 0) return ERROR_COMMAND_SYNTAX_ERROR; struct xscale_common *xscale = target_to_xscale(target); int retval = ERROR_OK; tap_state_t path[3]; struct scan_field fields[3]; uint8_t *field0 = malloc(num_words * 1); uint8_t field0_check_value = 0x2; uint8_t field0_check_mask = 0x6; uint32_t *field1 = malloc(num_words * 4); uint8_t field2_check_value = 0x0; uint8_t field2_check_mask = 0x1; int words_done = 0; int words_scheduled = 0; int i; path[0] = TAP_DRSELECT; path[1] = TAP_DRCAPTURE; path[2] = TAP_DRSHIFT; memset(&fields, 0, sizeof fields); fields[0].num_bits = 3; uint8_t tmp; fields[0].in_value = &tmp; fields[0].check_value = &field0_check_value; fields[0].check_mask = &field0_check_mask; fields[1].num_bits = 32; fields[2].num_bits = 1; uint8_t tmp2; fields[2].in_value = &tmp2; fields[2].check_value = &field2_check_value; fields[2].check_mask = &field2_check_mask; xscale_jtag_set_instr(target->tap, XSCALE_DBGTX << xscale->xscale_variant, TAP_IDLE); jtag_add_runtest(1, TAP_IDLE); /* ensures that we're in the TAP_IDLE state as the above *could be a no-op */ /* repeat until all words have been collected */ int attempts = 0; while (words_done < num_words) { /* schedule reads */ words_scheduled = 0; for (i = words_done; i < num_words; i++) { fields[0].in_value = &field0[i]; jtag_add_pathmove(3, path); fields[1].in_value = (uint8_t *)(field1 + i); jtag_add_dr_scan_check(target->tap, 3, fields, TAP_IDLE); jtag_add_callback(xscale_getbuf, (jtag_callback_data_t)(field1 + i)); words_scheduled++; } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while receiving data from debug handler"); break; } /* examine results */ for (i = words_done; i < num_words; i++) { if (!(field0[i] & 1)) { /* move backwards if necessary */ int j; for (j = i; j < num_words - 1; j++) { field0[j] = field0[j + 1]; field1[j] = field1[j + 1]; } words_scheduled--; } } if (words_scheduled == 0) { if (attempts++ == 1000) { LOG_ERROR( "Failed to receiving data from debug handler after 1000 attempts"); retval = ERROR_TARGET_TIMEOUT; break; } } words_done += words_scheduled; } for (i = 0; i < num_words; i++) *(buffer++) = buf_get_u32((uint8_t *)&field1[i], 0, 32); free(field1); return retval; } static int xscale_read_tx(struct target *target, int consume) { struct xscale_common *xscale = target_to_xscale(target); tap_state_t path[3]; tap_state_t noconsume_path[6]; int retval; struct timeval timeout, now; struct scan_field fields[3]; uint8_t field0_in = 0x0; uint8_t field0_check_value = 0x2; uint8_t field0_check_mask = 0x6; uint8_t field2_check_value = 0x0; uint8_t field2_check_mask = 0x1; xscale_jtag_set_instr(target->tap, XSCALE_DBGTX << xscale->xscale_variant, TAP_IDLE); path[0] = TAP_DRSELECT; path[1] = TAP_DRCAPTURE; path[2] = TAP_DRSHIFT; noconsume_path[0] = TAP_DRSELECT; noconsume_path[1] = TAP_DRCAPTURE; noconsume_path[2] = TAP_DREXIT1; noconsume_path[3] = TAP_DRPAUSE; noconsume_path[4] = TAP_DREXIT2; noconsume_path[5] = TAP_DRSHIFT; memset(&fields, 0, sizeof fields); fields[0].num_bits = 3; fields[0].in_value = &field0_in; fields[1].num_bits = 32; fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value; fields[2].num_bits = 1; uint8_t tmp; fields[2].in_value = &tmp; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, 1, 0); for (;; ) { /* if we want to consume the register content (i.e. clear TX_READY), * we have to go straight from Capture-DR to Shift-DR * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR */ if (consume) jtag_add_pathmove(3, path); else jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path); jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE); jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask); jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while reading TX"); return ERROR_TARGET_TIMEOUT; } gettimeofday(&now, NULL); if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) { LOG_ERROR("time out reading TX register"); return ERROR_TARGET_TIMEOUT; } if (!((!(field0_in & 1)) && consume)) goto done; if (debug_level >= 3) { LOG_DEBUG("waiting 100ms"); alive_sleep(100); /* avoid flooding the logs */ } else keep_alive(); } done: if (!(field0_in & 1)) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_OK; } static int xscale_write_rx(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); int retval; struct timeval timeout, now; struct scan_field fields[3]; uint8_t field0_out = 0x0; uint8_t field0_in = 0x0; uint8_t field0_check_value = 0x2; uint8_t field0_check_mask = 0x6; uint8_t field2 = 0x0; uint8_t field2_check_value = 0x0; uint8_t field2_check_mask = 0x1; xscale_jtag_set_instr(target->tap, XSCALE_DBGRX << xscale->xscale_variant, TAP_IDLE); memset(&fields, 0, sizeof fields); fields[0].num_bits = 3; fields[0].out_value = &field0_out; fields[0].in_value = &field0_in; fields[1].num_bits = 32; fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value; fields[2].num_bits = 1; fields[2].out_value = &field2; uint8_t tmp; fields[2].in_value = &tmp; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, 1, 0); /* poll until rx_read is low */ LOG_DEBUG("polling RX"); for (;;) { jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE); jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask); jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while writing RX"); return retval; } gettimeofday(&now, NULL); if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) { LOG_ERROR("time out writing RX register"); return ERROR_TARGET_TIMEOUT; } if (!(field0_in & 1)) goto done; if (debug_level >= 3) { LOG_DEBUG("waiting 100ms"); alive_sleep(100); /* avoid flooding the logs */ } else keep_alive(); } done: /* set rx_valid */ field2 = 0x1; jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while writing RX"); return retval; } return ERROR_OK; } /* send count elements of size byte to the debug handler */ static int xscale_send(struct target *target, const uint8_t *buffer, int count, int size) { struct xscale_common *xscale = target_to_xscale(target); int retval; int done_count = 0; xscale_jtag_set_instr(target->tap, XSCALE_DBGRX << xscale->xscale_variant, TAP_IDLE); static const uint8_t t0; uint8_t t1[4]; static const uint8_t t2 = 1; struct scan_field fields[3] = { { .num_bits = 3, .out_value = &t0 }, { .num_bits = 32, .out_value = t1 }, { .num_bits = 1, .out_value = &t2 }, }; int endianness = target->endianness; while (done_count++ < count) { uint32_t t; switch (size) { case 4: if (endianness == TARGET_LITTLE_ENDIAN) t = le_to_h_u32(buffer); else t = be_to_h_u32(buffer); break; case 2: if (endianness == TARGET_LITTLE_ENDIAN) t = le_to_h_u16(buffer); else t = be_to_h_u16(buffer); break; case 1: t = buffer[0]; break; default: LOG_ERROR("BUG: size neither 4, 2 nor 1"); return ERROR_COMMAND_SYNTAX_ERROR; } buf_set_u32(t1, 0, 32, t); jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE); buffer += size; } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while sending data to debug handler"); return retval; } return ERROR_OK; } static int xscale_send_u32(struct target *target, uint32_t value) { struct xscale_common *xscale = target_to_xscale(target); buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value); return xscale_write_rx(target); } static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_brk) { struct xscale_common *xscale = target_to_xscale(target); int retval; struct scan_field fields[3]; uint8_t field0 = 0x0; uint8_t field0_check_value = 0x2; uint8_t field0_check_mask = 0x7; uint8_t field2 = 0x0; uint8_t field2_check_value = 0x0; uint8_t field2_check_mask = 0x1; if (hold_rst != -1) xscale->hold_rst = hold_rst; if (ext_dbg_brk != -1) xscale->external_debug_break = ext_dbg_brk; xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR << xscale->xscale_variant, TAP_IDLE); buf_set_u32(&field0, 1, 1, xscale->hold_rst); buf_set_u32(&field0, 2, 1, xscale->external_debug_break); memset(&fields, 0, sizeof fields); fields[0].num_bits = 3; fields[0].out_value = &field0; uint8_t tmp; fields[0].in_value = &tmp; fields[1].num_bits = 32; fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value; fields[2].num_bits = 1; fields[2].out_value = &field2; uint8_t tmp2; fields[2].in_value = &tmp2; jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE); jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask); jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while writing DCSR"); return retval; } xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0; xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1; return ERROR_OK; } /* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */ static unsigned int parity(unsigned int v) { /* unsigned int ov = v; */ v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; /* LOG_DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1); */ return (0x6996 >> v) & 1; } static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]) { struct xscale_common *xscale = target_to_xscale(target); uint8_t packet[4]; uint8_t cmd; int word; struct scan_field fields[2]; LOG_DEBUG("loading miniIC at 0x%8.8" PRIx32 "", va); /* LDIC into IR */ xscale_jtag_set_instr(target->tap, XSCALE_LDIC << xscale->xscale_variant, TAP_IDLE); /* CMD is b011 to load a cacheline into the Mini ICache. * Loading into the main ICache is deprecated, and unused. * It's followed by three zero bits, and 27 address bits. */ buf_set_u32(&cmd, 0, 6, 0x3); /* virtual address of desired cache line */ buf_set_u32(packet, 0, 27, va >> 5); memset(&fields, 0, sizeof fields); fields[0].num_bits = 6; fields[0].out_value = &cmd; fields[1].num_bits = 27; fields[1].out_value = packet; jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE); /* rest of packet is a cacheline: 8 instructions, with parity */ fields[0].num_bits = 32; fields[0].out_value = packet; fields[1].num_bits = 1; fields[1].out_value = &cmd; for (word = 0; word < 8; word++) { buf_set_u32(packet, 0, 32, buffer[word]); uint32_t value; memcpy(&value, packet, sizeof(uint32_t)); cmd = parity(value); jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE); } return jtag_execute_queue(); } static int xscale_invalidate_ic_line(struct target *target, uint32_t va) { struct xscale_common *xscale = target_to_xscale(target); uint8_t packet[4]; uint8_t cmd; struct scan_field fields[2]; xscale_jtag_set_instr(target->tap, XSCALE_LDIC << xscale->xscale_variant, TAP_IDLE); /* CMD for invalidate IC line b000, bits [6:4] b000 */ buf_set_u32(&cmd, 0, 6, 0x0); /* virtual address of desired cache line */ buf_set_u32(packet, 0, 27, va >> 5); memset(&fields, 0, sizeof fields); fields[0].num_bits = 6; fields[0].out_value = &cmd; fields[1].num_bits = 27; fields[1].out_value = packet; jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE); return ERROR_OK; } static int xscale_update_vectors(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); int i; int retval; uint32_t low_reset_branch, high_reset_branch; for (i = 1; i < 8; i++) { /* if there's a static vector specified for this exception, override */ if (xscale->static_high_vectors_set & (1 << i)) xscale->high_vectors[i] = xscale->static_high_vectors[i]; else { retval = target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]); if (retval == ERROR_TARGET_TIMEOUT) return retval; if (retval != ERROR_OK) { /* Some of these reads will fail as part of normal execution */ xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0); } } } for (i = 1; i < 8; i++) { if (xscale->static_low_vectors_set & (1 << i)) xscale->low_vectors[i] = xscale->static_low_vectors[i]; else { retval = target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]); if (retval == ERROR_TARGET_TIMEOUT) return retval; if (retval != ERROR_OK) { /* Some of these reads will fail as part of normal execution */ xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0); } } } /* calculate branches to debug handler */ low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2; high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2; xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0); xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0); /* invalidate and load exception vectors in mini i-cache */ xscale_invalidate_ic_line(target, 0x0); xscale_invalidate_ic_line(target, 0xffff0000); xscale_load_ic(target, 0x0, xscale->low_vectors); xscale_load_ic(target, 0xffff0000, xscale->high_vectors); return ERROR_OK; } static int xscale_arch_state(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; static const char *state[] = { "disabled", "enabled" }; static const char *arch_dbg_reason[] = { "", "\n(processor reset)", "\n(trace buffer full)" }; if (arm->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("BUG: called for a non-ARMv4/5 target"); return ERROR_COMMAND_SYNTAX_ERROR; } arm_arch_state(target); LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s%s", state[xscale->armv4_5_mmu.mmu_enabled], state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled], arch_dbg_reason[xscale->arch_debug_reason]); return ERROR_OK; } static int xscale_poll(struct target *target) { int retval = ERROR_OK; if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING)) { enum target_state previous_state = target->state; retval = xscale_read_tx(target, 0); if (retval == ERROR_OK) { /* there's data to read from the tx register, we entered debug state */ target->state = TARGET_HALTED; /* process debug entry, fetching current mode regs */ retval = xscale_debug_entry(target); } else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { LOG_USER("error while polling TX register, reset CPU"); /* here we "lie" so GDB won't get stuck and a reset can be perfomed */ target->state = TARGET_HALTED; } /* debug_entry could have overwritten target state (i.e. immediate resume) * don't signal event handlers in that case */ if (target->state != TARGET_HALTED) return ERROR_OK; /* if target was running, signal that we halted * otherwise we reentered from debug execution */ if (previous_state == TARGET_RUNNING) target_call_event_callbacks(target, TARGET_EVENT_HALTED); else target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } return retval; } static int xscale_debug_entry(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; uint32_t pc; uint32_t buffer[10]; unsigned i; int retval; uint32_t moe; /* clear external dbg break (will be written on next DCSR read) */ xscale->external_debug_break = 0; retval = xscale_read_dcsr(target); if (retval != ERROR_OK) return retval; /* get r0, pc, r1 to r7 and cpsr */ retval = xscale_receive(target, buffer, 10); if (retval != ERROR_OK) return retval; /* move r0 from buffer to register cache */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, buffer[0]); arm->core_cache->reg_list[0].dirty = 1; arm->core_cache->reg_list[0].valid = 1; LOG_DEBUG("r0: 0x%8.8" PRIx32 "", buffer[0]); /* move pc from buffer to register cache */ buf_set_u32(arm->pc->value, 0, 32, buffer[1]); arm->pc->dirty = 1; arm->pc->valid = 1; LOG_DEBUG("pc: 0x%8.8" PRIx32 "", buffer[1]); /* move data from buffer to register cache */ for (i = 1; i <= 7; i++) { buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]); arm->core_cache->reg_list[i].dirty = 1; arm->core_cache->reg_list[i].valid = 1; LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, buffer[i + 1]); } arm_set_cpsr(arm, buffer[9]); LOG_DEBUG("cpsr: 0x%8.8" PRIx32 "", buffer[9]); if (!is_arm_mode(arm->core_mode)) { target->state = TARGET_UNKNOWN; LOG_ERROR("cpsr contains invalid mode value - communication failure"); return ERROR_TARGET_FAILURE; } LOG_DEBUG("target entered debug state in %s mode", arm_mode_name(arm->core_mode)); /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */ if (arm->spsr) { xscale_receive(target, buffer, 8); buf_set_u32(arm->spsr->value, 0, 32, buffer[7]); arm->spsr->dirty = false; arm->spsr->valid = true; } else { /* r8 to r14, but no spsr */ xscale_receive(target, buffer, 7); } /* move data from buffer to right banked register in cache */ for (i = 8; i <= 14; i++) { struct reg *r = arm_reg_current(arm, i); buf_set_u32(r->value, 0, 32, buffer[i - 8]); r->dirty = false; r->valid = true; } /* mark xscale regs invalid to ensure they are retrieved from the * debug handler if requested */ for (i = 0; i < xscale->reg_cache->num_regs; i++) xscale->reg_cache->reg_list[i].valid = 0; /* examine debug reason */ xscale_read_dcsr(target); moe = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 2, 3); /* stored PC (for calculating fixup) */ pc = buf_get_u32(arm->pc->value, 0, 32); switch (moe) { case 0x0: /* Processor reset */ target->debug_reason = DBG_REASON_DBGRQ; xscale->arch_debug_reason = XSCALE_DBG_REASON_RESET; pc -= 4; break; case 0x1: /* Instruction breakpoint hit */ target->debug_reason = DBG_REASON_BREAKPOINT; xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC; pc -= 4; break; case 0x2: /* Data breakpoint hit */ target->debug_reason = DBG_REASON_WATCHPOINT; xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC; pc -= 4; break; case 0x3: /* BKPT instruction executed */ target->debug_reason = DBG_REASON_BREAKPOINT; xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC; pc -= 4; break; case 0x4: /* Ext. debug event */ target->debug_reason = DBG_REASON_DBGRQ; xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC; pc -= 4; break; case 0x5: /* Vector trap occured */ target->debug_reason = DBG_REASON_BREAKPOINT; xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC; pc -= 4; break; case 0x6: /* Trace buffer full break */ target->debug_reason = DBG_REASON_DBGRQ; xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL; pc -= 4; break; case 0x7: /* Reserved (may flag Hot-Debug support) */ default: LOG_ERROR("Method of Entry is 'Reserved'"); exit(-1); break; } /* apply PC fixup */ buf_set_u32(arm->pc->value, 0, 32, pc); /* on the first debug entry, identify cache type */ if (xscale->armv4_5_mmu.armv4_5_cache.ctype == -1) { uint32_t cache_type_reg; /* read cp15 cache type register */ xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]); cache_type_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CACHETYPE].value, 0, 32); armv4_5_identify_cache(cache_type_reg, &xscale->armv4_5_mmu.armv4_5_cache); } /* examine MMU and Cache settings * read cp15 control register */ xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]); xscale->cp15_control_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32); xscale->armv4_5_mmu.mmu_enabled = (xscale->cp15_control_reg & 0x1U) ? 1 : 0; xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (xscale->cp15_control_reg & 0x4U) ? 1 : 0; xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0; /* tracing enabled, read collected trace data */ if (xscale->trace.mode != XSCALE_TRACE_DISABLED) { xscale_read_trace(target); /* Resume if entered debug due to buffer fill and we're still collecting * trace data. Note that a debug exception due to trace buffer full * can only happen in fill mode. */ if (xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL) { if (--xscale->trace.fill_counter > 0) xscale_resume(target, 1, 0x0, 1, 0); } else /* entered debug for other reason; reset counter */ xscale->trace.fill_counter = 0; } return ERROR_OK; } static int xscale_halt(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } else if (target->state == TARGET_UNKNOWN) { /* this must not happen for a xscale target */ LOG_ERROR("target was in unknown state when halt was requested"); return ERROR_TARGET_INVALID; } else if (target->state == TARGET_RESET) LOG_DEBUG("target->state == TARGET_RESET"); else { /* assert external dbg break */ xscale->external_debug_break = 1; xscale_read_dcsr(target); target->debug_reason = DBG_REASON_DBGRQ; } return ERROR_OK; } static int xscale_enable_single_step(struct target *target, uint32_t next_pc) { struct xscale_common *xscale = target_to_xscale(target); struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0]; int retval; if (xscale->ibcr0_used) { struct breakpoint *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe); if (ibcr0_bp) xscale_unset_breakpoint(target, ibcr0_bp); else { LOG_ERROR( "BUG: xscale->ibcr0_used is set, but no breakpoint with that address found"); exit(-1); } } retval = xscale_set_reg_u32(ibcr0, next_pc | 0x1); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int xscale_disable_single_step(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0]; int retval; retval = xscale_set_reg_u32(ibcr0, 0x0); if (retval != ERROR_OK) return retval; return ERROR_OK; } static void xscale_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { if (watchpoint->set == 0) xscale_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } } static void xscale_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; /* set any pending breakpoints */ while (breakpoint) { if (breakpoint->set == 0) xscale_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } } static void xscale_free_trace_data(struct xscale_common *xscale) { struct xscale_trace_data *td = xscale->trace.data; while (td) { struct xscale_trace_data *next_td = td->next; if (td->entries) free(td->entries); free(td); td = next_td; } xscale->trace.data = NULL; } static int xscale_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; uint32_t current_pc; int retval; int i; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) target_free_all_working_areas(target); /* update vector tables */ retval = xscale_update_vectors(target); if (retval != ERROR_OK) return retval; /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); current_pc = buf_get_u32(arm->pc->value, 0, 32); /* if we're at the reset vector, we have to simulate the branch */ if (current_pc == 0x0) { arm_simulate_step(target, NULL); current_pc = buf_get_u32(arm->pc->value, 0, 32); } /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { struct breakpoint *breakpoint; breakpoint = breakpoint_find(target, buf_get_u32(arm->pc->value, 0, 32)); if (breakpoint != NULL) { uint32_t next_pc; enum trace_mode saved_trace_mode; /* there's a breakpoint at the current PC, we have to step over it */ LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); xscale_unset_breakpoint(target, breakpoint); /* calculate PC of next instruction */ retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) { uint32_t current_opcode; target_read_u32(target, current_pc, ¤t_opcode); LOG_ERROR( "BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); } LOG_DEBUG("enable single-step"); xscale_enable_single_step(target, next_pc); /* restore banked registers */ retval = xscale_restore_banked(target); if (retval != ERROR_OK) return retval; /* send resume request */ xscale_send_u32(target, 0x30); /* send CPSR */ xscale_send_u32(target, buf_get_u32(arm->cpsr->value, 0, 32)); LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32, buf_get_u32(arm->cpsr->value, 0, 32)); for (i = 7; i >= 0; i--) { /* send register */ xscale_send_u32(target, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); } /* send PC */ xscale_send_u32(target, buf_get_u32(arm->pc->value, 0, 32)); LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); /* disable trace data collection in xscale_debug_entry() */ saved_trace_mode = xscale->trace.mode; xscale->trace.mode = XSCALE_TRACE_DISABLED; /* wait for and process debug entry */ xscale_debug_entry(target); /* re-enable trace buffer, if enabled previously */ xscale->trace.mode = saved_trace_mode; LOG_DEBUG("disable single-step"); xscale_disable_single_step(target); LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); xscale_set_breakpoint(target, breakpoint); } } /* enable any pending breakpoints and watchpoints */ xscale_enable_breakpoints(target); xscale_enable_watchpoints(target); /* restore banked registers */ retval = xscale_restore_banked(target); if (retval != ERROR_OK) return retval; /* send resume request (command 0x30 or 0x31) * clean the trace buffer if it is to be enabled (0x62) */ if (xscale->trace.mode != XSCALE_TRACE_DISABLED) { if (xscale->trace.mode == XSCALE_TRACE_FILL) { /* If trace enabled in fill mode and starting collection of new set * of buffers, initialize buffer counter and free previous buffers */ if (xscale->trace.fill_counter == 0) { xscale->trace.fill_counter = xscale->trace.buffer_fill; xscale_free_trace_data(xscale); } } else /* wrap mode; free previous buffer */ xscale_free_trace_data(xscale); xscale_send_u32(target, 0x62); xscale_send_u32(target, 0x31); } else xscale_send_u32(target, 0x30); /* send CPSR */ xscale_send_u32(target, buf_get_u32(arm->cpsr->value, 0, 32)); LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32, buf_get_u32(arm->cpsr->value, 0, 32)); for (i = 7; i >= 0; i--) { /* send register */ xscale_send_u32(target, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); } /* send PC */ xscale_send_u32(target, buf_get_u32(arm->pc->value, 0, 32)); LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) { /* registers are now invalid */ register_cache_invalidate(arm->core_cache); target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); } LOG_DEBUG("target resumed"); return ERROR_OK; } static int xscale_step_inner(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; uint32_t next_pc; int retval; int i; target->debug_reason = DBG_REASON_SINGLESTEP; /* calculate PC of next instruction */ retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) { uint32_t current_opcode, current_pc; current_pc = buf_get_u32(arm->pc->value, 0, 32); target_read_u32(target, current_pc, ¤t_opcode); LOG_ERROR( "BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); return retval; } LOG_DEBUG("enable single-step"); retval = xscale_enable_single_step(target, next_pc); if (retval != ERROR_OK) return retval; /* restore banked registers */ retval = xscale_restore_banked(target); if (retval != ERROR_OK) return retval; /* send resume request (command 0x30 or 0x31) * clean the trace buffer if it is to be enabled (0x62) */ if (xscale->trace.mode != XSCALE_TRACE_DISABLED) { retval = xscale_send_u32(target, 0x62); if (retval != ERROR_OK) return retval; retval = xscale_send_u32(target, 0x31); if (retval != ERROR_OK) return retval; } else { retval = xscale_send_u32(target, 0x30); if (retval != ERROR_OK) return retval; } /* send CPSR */ retval = xscale_send_u32(target, buf_get_u32(arm->cpsr->value, 0, 32)); if (retval != ERROR_OK) return retval; LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32, buf_get_u32(arm->cpsr->value, 0, 32)); for (i = 7; i >= 0; i--) { /* send register */ retval = xscale_send_u32(target, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); if (retval != ERROR_OK) return retval; LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32)); } /* send PC */ retval = xscale_send_u32(target, buf_get_u32(arm->pc->value, 0, 32)); if (retval != ERROR_OK) return retval; LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); target_call_event_callbacks(target, TARGET_EVENT_RESUMED); /* registers are now invalid */ register_cache_invalidate(arm->core_cache); /* wait for and process debug entry */ retval = xscale_debug_entry(target); if (retval != ERROR_OK) return retval; LOG_DEBUG("disable single-step"); retval = xscale_disable_single_step(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); return ERROR_OK; } static int xscale_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct arm *arm = target_to_arm(target); struct breakpoint *breakpoint = NULL; uint32_t current_pc; int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); current_pc = buf_get_u32(arm->pc->value, 0, 32); /* if we're at the reset vector, we have to simulate the step */ if (current_pc == 0x0) { retval = arm_simulate_step(target, NULL); if (retval != ERROR_OK) return retval; current_pc = buf_get_u32(arm->pc->value, 0, 32); LOG_DEBUG("current pc %" PRIx32, current_pc); target->debug_reason = DBG_REASON_SINGLESTEP; target_call_event_callbacks(target, TARGET_EVENT_HALTED); return ERROR_OK; } /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) breakpoint = breakpoint_find(target, buf_get_u32(arm->pc->value, 0, 32)); if (breakpoint != NULL) { retval = xscale_unset_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } retval = xscale_step_inner(target, current, address, handle_breakpoints); if (retval != ERROR_OK) return retval; if (breakpoint) xscale_set_breakpoint(target, breakpoint); LOG_DEBUG("target stepped"); return ERROR_OK; } static int xscale_assert_reset(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); LOG_DEBUG("target->state: %s", target_state_name(target)); /* assert reset */ jtag_add_reset(0, 1); /* sleep 1ms, to be sure we fulfill any requirements */ jtag_add_sleep(1000); jtag_execute_queue(); /* select DCSR instruction (set endstate to R-T-I to ensure we don't * end up in T-L-R, which would reset JTAG */ xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR << xscale->xscale_variant, TAP_IDLE); /* set Hold reset, Halt mode and Trap Reset */ buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1); buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1); xscale_write_dcsr(target, 1, 0); /* select BYPASS, because having DCSR selected caused problems on the PXA27x */ xscale_jtag_set_instr(target->tap, ~0, TAP_IDLE); jtag_execute_queue(); target->state = TARGET_RESET; if (target->reset_halt) { int retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int xscale_deassert_reset(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct breakpoint *breakpoint = target->breakpoints; LOG_DEBUG("-"); xscale->ibcr_available = 2; xscale->ibcr0_used = 0; xscale->ibcr1_used = 0; xscale->dbr_available = 2; xscale->dbr0_used = 0; xscale->dbr1_used = 0; /* mark all hardware breakpoints as unset */ while (breakpoint) { if (breakpoint->type == BKPT_HARD) breakpoint->set = 0; breakpoint = breakpoint->next; } xscale->trace.mode = XSCALE_TRACE_DISABLED; xscale_free_trace_data(xscale); register_cache_invalidate(xscale->arm.core_cache); /* FIXME mark hardware watchpoints got unset too. Also, * at least some of the XScale registers are invalid... */ /* * REVISIT: *assumes* we had a SRST+TRST reset so the mini-icache * contents got invalidated. Safer to force that, so writing new * contents can't ever fail.. */ { uint32_t address; unsigned buf_cnt; const uint8_t *buffer = xscale_debug_handler; int retval; /* release SRST */ jtag_add_reset(0, 0); /* wait 300ms; 150 and 100ms were not enough */ jtag_add_sleep(300*1000); jtag_add_runtest(2030, TAP_IDLE); jtag_execute_queue(); /* set Hold reset, Halt mode and Trap Reset */ buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1); buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1); xscale_write_dcsr(target, 1, 0); /* Load the debug handler into the mini-icache. Since * it's using halt mode (not monitor mode), it runs in * "Special Debug State" for access to registers, memory, * coprocessors, trace data, etc. */ address = xscale->handler_address; for (unsigned binary_size = sizeof xscale_debug_handler; binary_size > 0; binary_size -= buf_cnt, buffer += buf_cnt) { uint32_t cache_line[8]; unsigned i; buf_cnt = binary_size; if (buf_cnt > 32) buf_cnt = 32; for (i = 0; i < buf_cnt; i += 4) { /* convert LE buffer to host-endian uint32_t */ cache_line[i / 4] = le_to_h_u32(&buffer[i]); } for (; i < 32; i += 4) cache_line[i / 4] = 0xe1a08008; /* only load addresses other than the reset vectors */ if ((address % 0x400) != 0x0) { retval = xscale_load_ic(target, address, cache_line); if (retval != ERROR_OK) return retval; } address += buf_cnt; } ; retval = xscale_load_ic(target, 0x0, xscale->low_vectors); if (retval != ERROR_OK) return retval; retval = xscale_load_ic(target, 0xffff0000, xscale->high_vectors); if (retval != ERROR_OK) return retval; jtag_add_runtest(30, TAP_IDLE); jtag_add_sleep(100000); /* set Hold reset, Halt mode and Trap Reset */ buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1); buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1); xscale_write_dcsr(target, 1, 0); /* clear Hold reset to let the target run (should enter debug handler) */ xscale_write_dcsr(target, 0, 1); target->state = TARGET_RUNNING; if (!target->reset_halt) { jtag_add_sleep(10000); /* we should have entered debug now */ xscale_debug_entry(target); target->state = TARGET_HALTED; /* resume the target */ xscale_resume(target, 1, 0x0, 1, 0); } } return ERROR_OK; } static int xscale_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { /** \todo add debug handler support for core register reads */ LOG_ERROR("not implemented"); return ERROR_OK; } static int xscale_write_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode, uint8_t *value) { /** \todo add debug handler support for core register writes */ LOG_ERROR("not implemented"); return ERROR_OK; } static int xscale_full_context(struct target *target) { struct arm *arm = target_to_arm(target); uint32_t *buffer; int i, j; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } buffer = malloc(4 * 8); /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS) * we can't enter User mode on an XScale (unpredictable), * but User shares registers with SYS */ for (i = 1; i < 7; i++) { enum arm_mode mode = armv4_5_number_to_mode(i); bool valid = true; struct reg *r; if (mode == ARM_MODE_USR) continue; /* check if there are invalid registers in the current mode */ for (j = 0; valid && j <= 16; j++) { if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, j).valid) valid = false; } if (valid) continue; /* request banked registers */ xscale_send_u32(target, 0x0); /* send CPSR for desired bank mode */ xscale_send_u32(target, mode | 0xc0 /* I/F bits */); /* get banked registers: r8 to r14; and SPSR * except in USR/SYS mode */ if (mode != ARM_MODE_SYS) { /* SPSR */ r = &ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, 16); xscale_receive(target, buffer, 8); buf_set_u32(r->value, 0, 32, buffer[7]); r->dirty = false; r->valid = true; } else xscale_receive(target, buffer, 7); /* move data from buffer to register cache */ for (j = 8; j <= 14; j++) { r = &ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, j); buf_set_u32(r->value, 0, 32, buffer[j - 8]); r->dirty = false; r->valid = true; } } free(buffer); return ERROR_OK; } static int xscale_restore_banked(struct target *target) { struct arm *arm = target_to_arm(target); int i, j; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS) * and check if any banked registers need to be written. Ignore * USR mode (number 0) in favor of SYS; we can't enter User mode on * an XScale (unpredictable), but they share all registers. */ for (i = 1; i < 7; i++) { enum arm_mode mode = armv4_5_number_to_mode(i); struct reg *r; if (mode == ARM_MODE_USR) continue; /* check if there are dirty registers in this mode */ for (j = 8; j <= 14; j++) { if (ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, j).dirty) goto dirty; } /* if not USR/SYS, check if the SPSR needs to be written */ if (mode != ARM_MODE_SYS) { if (ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, 16).dirty) goto dirty; } /* there's nothing to flush for this mode */ continue; dirty: /* command 0x1: "send banked registers" */ xscale_send_u32(target, 0x1); /* send CPSR for desired mode */ xscale_send_u32(target, mode | 0xc0 /* I/F bits */); /* send r8 to r14/lr ... only FIQ needs more than r13..r14, * but this protocol doesn't understand that nuance. */ for (j = 8; j <= 14; j++) { r = &ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, j); xscale_send_u32(target, buf_get_u32(r->value, 0, 32)); r->dirty = false; } /* send spsr if not in USR/SYS mode */ if (mode != ARM_MODE_SYS) { r = &ARMV4_5_CORE_REG_MODE(arm->core_cache, mode, 16); xscale_send_u32(target, buf_get_u32(r->value, 0, 32)); r->dirty = false; } } return ERROR_OK; } static int xscale_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); uint32_t *buf32; uint32_t i; int retval; LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /* send memory read request (command 0x1n, n: access size) */ retval = xscale_send_u32(target, 0x10 | size); if (retval != ERROR_OK) return retval; /* send base address for read request */ retval = xscale_send_u32(target, address); if (retval != ERROR_OK) return retval; /* send number of requested data words */ retval = xscale_send_u32(target, count); if (retval != ERROR_OK) return retval; /* receive data from target (count times 32-bit words in host endianness) */ buf32 = malloc(4 * count); retval = xscale_receive(target, buf32, count); if (retval != ERROR_OK) { free(buf32); return retval; } /* extract data from host-endian buffer into byte stream */ for (i = 0; i < count; i++) { switch (size) { case 4: target_buffer_set_u32(target, buffer, buf32[i]); buffer += 4; break; case 2: target_buffer_set_u16(target, buffer, buf32[i] & 0xffff); buffer += 2; break; case 1: *buffer++ = buf32[i] & 0xff; break; default: LOG_ERROR("invalid read size"); return ERROR_COMMAND_SYNTAX_ERROR; } } free(buf32); /* examine DCSR, to see if Sticky Abort (SA) got set */ retval = xscale_read_dcsr(target); if (retval != ERROR_OK) return retval; if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1) { /* clear SA bit */ retval = xscale_send_u32(target, 0x60); if (retval != ERROR_OK) return retval; return ERROR_TARGET_DATA_ABORT; } return ERROR_OK; } static int xscale_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); /* with MMU inactive, there are only physical addresses */ if (!xscale->armv4_5_mmu.mmu_enabled) return xscale_read_memory(target, address, size, count, buffer); /** \todo: provide a non-stub implementation of this routine. */ LOG_ERROR("%s: %s is not implemented. Disable MMU?", target_name(target), __func__); return ERROR_FAIL; } static int xscale_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); int retval; LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /* send memory write request (command 0x2n, n: access size) */ retval = xscale_send_u32(target, 0x20 | size); if (retval != ERROR_OK) return retval; /* send base address for read request */ retval = xscale_send_u32(target, address); if (retval != ERROR_OK) return retval; /* send number of requested data words to be written*/ retval = xscale_send_u32(target, count); if (retval != ERROR_OK) return retval; /* extract data from host-endian buffer into byte stream */ #if 0 for (i = 0; i < count; i++) { switch (size) { case 4: value = target_buffer_get_u32(target, buffer); xscale_send_u32(target, value); buffer += 4; break; case 2: value = target_buffer_get_u16(target, buffer); xscale_send_u32(target, value); buffer += 2; break; case 1: value = *buffer; xscale_send_u32(target, value); buffer += 1; break; default: LOG_ERROR("should never get here"); exit(-1); } } #endif retval = xscale_send(target, buffer, count, size); if (retval != ERROR_OK) return retval; /* examine DCSR, to see if Sticky Abort (SA) got set */ retval = xscale_read_dcsr(target); if (retval != ERROR_OK) return retval; if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1) { /* clear SA bit */ retval = xscale_send_u32(target, 0x60); if (retval != ERROR_OK) return retval; LOG_ERROR("data abort writing memory"); return ERROR_TARGET_DATA_ABORT; } return ERROR_OK; } static int xscale_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); /* with MMU inactive, there are only physical addresses */ if (!xscale->armv4_5_mmu.mmu_enabled) return xscale_write_memory(target, address, size, count, buffer); /** \todo: provide a non-stub implementation of this routine. */ LOG_ERROR("%s: %s is not implemented. Disable MMU?", target_name(target), __func__); return ERROR_FAIL; } static int xscale_get_ttb(struct target *target, uint32_t *result) { struct xscale_common *xscale = target_to_xscale(target); uint32_t ttb; int retval; retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]); if (retval != ERROR_OK) return retval; ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32); *result = ttb; return ERROR_OK; } static int xscale_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { struct xscale_common *xscale = target_to_xscale(target); uint32_t cp15_control; int retval; /* read cp15 control register */ retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]); if (retval != ERROR_OK) return retval; cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32); if (mmu) cp15_control &= ~0x1U; if (d_u_cache) { /* clean DCache */ retval = xscale_send_u32(target, 0x50); if (retval != ERROR_OK) return retval; retval = xscale_send_u32(target, xscale->cache_clean_address); if (retval != ERROR_OK) return retval; /* invalidate DCache */ retval = xscale_send_u32(target, 0x51); if (retval != ERROR_OK) return retval; cp15_control &= ~0x4U; } if (i_cache) { /* invalidate ICache */ retval = xscale_send_u32(target, 0x52); if (retval != ERROR_OK) return retval; cp15_control &= ~0x1000U; } /* write new cp15 control register */ retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control); if (retval != ERROR_OK) return retval; /* execute cpwait to ensure outstanding operations complete */ retval = xscale_send_u32(target, 0x53); return retval; } static int xscale_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { struct xscale_common *xscale = target_to_xscale(target); uint32_t cp15_control; int retval; /* read cp15 control register */ retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]); if (retval != ERROR_OK) return retval; cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32); if (mmu) cp15_control |= 0x1U; if (d_u_cache) cp15_control |= 0x4U; if (i_cache) cp15_control |= 0x1000U; /* write new cp15 control register */ retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control); if (retval != ERROR_OK) return retval; /* execute cpwait to ensure outstanding operations complete */ retval = xscale_send_u32(target, 0x53); return retval; } static int xscale_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval; struct xscale_common *xscale = target_to_xscale(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (breakpoint->set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { uint32_t value = breakpoint->address | 1; if (!xscale->ibcr0_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value); xscale->ibcr0_used = 1; breakpoint->set = 1; /* breakpoint set on first breakpoint register */ } else if (!xscale->ibcr1_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value); xscale->ibcr1_used = 1; breakpoint->set = 2; /* breakpoint set on second breakpoint register */ } else {/* bug: availability previously verified in xscale_add_breakpoint() */ LOG_ERROR("BUG: no hardware comparator available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } else if (breakpoint->type == BKPT_SOFT) { if (breakpoint->length == 4) { /* keep the original instruction in target endianness */ retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; /* write the bkpt instruction in target endianness *(arm7_9->arm_bkpt is host endian) */ retval = target_write_u32(target, breakpoint->address, xscale->arm_bkpt); if (retval != ERROR_OK) return retval; } else { /* keep the original instruction in target endianness */ retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; /* write the bkpt instruction in target endianness *(arm7_9->arm_bkpt is host endian) */ retval = target_write_u16(target, breakpoint->address, xscale->thumb_bkpt); if (retval != ERROR_OK) return retval; } breakpoint->set = 1; xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, xscale->cache_clean_address); xscale_send_u32(target, 0x51); /* invalidate dcache */ xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */ } return ERROR_OK; } static int xscale_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct xscale_common *xscale = target_to_xscale(target); if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1)) { LOG_ERROR("no breakpoint unit available for hardware breakpoint"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if ((breakpoint->length != 2) && (breakpoint->length != 4)) { LOG_ERROR("only breakpoints of two (Thumb) or four (ARM) bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) xscale->ibcr_available--; return xscale_set_breakpoint(target, breakpoint); } static int xscale_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval; struct xscale_common *xscale = target_to_xscale(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { if (breakpoint->set == 1) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0); xscale->ibcr0_used = 0; } else if (breakpoint->set == 2) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0); xscale->ibcr1_used = 0; } breakpoint->set = 0; } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } else { retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } breakpoint->set = 0; xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, xscale->cache_clean_address); xscale_send_u32(target, 0x51); /* invalidate dcache */ xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */ } return ERROR_OK; } static int xscale_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct xscale_common *xscale = target_to_xscale(target); if (target->state != TARGET_HALTED) { LOG_ERROR("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (breakpoint->set) xscale_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) xscale->ibcr_available++; return ERROR_OK; } static int xscale_set_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct xscale_common *xscale = target_to_xscale(target); uint32_t enable = 0; struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON]; uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32); if (target->state != TARGET_HALTED) { LOG_ERROR("target not halted"); return ERROR_TARGET_NOT_HALTED; } switch (watchpoint->rw) { case WPT_READ: enable = 0x3; break; case WPT_ACCESS: enable = 0x2; break; case WPT_WRITE: enable = 0x1; break; default: LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); } /* For watchpoint across more than one word, both DBR registers must be enlisted, with the second used as a mask. */ if (watchpoint->length > 4) { if (xscale->dbr0_used || xscale->dbr1_used) { LOG_ERROR("BUG: sufficient hardware comparators unavailable"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* Write mask value to DBR1, based on the length argument. * Address bits ignored by the comparator are those set in mask. */ xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->length - 1); xscale->dbr1_used = 1; enable |= 0x100; /* DBCON[M] */ } if (!xscale->dbr0_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address); dbcon_value |= enable; xscale_set_reg_u32(dbcon, dbcon_value); watchpoint->set = 1; xscale->dbr0_used = 1; } else if (!xscale->dbr1_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address); dbcon_value |= enable << 2; xscale_set_reg_u32(dbcon, dbcon_value); watchpoint->set = 2; xscale->dbr1_used = 1; } else { LOG_ERROR("BUG: no hardware comparator available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } return ERROR_OK; } static int xscale_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct xscale_common *xscale = target_to_xscale(target); if (xscale->dbr_available < 1) { LOG_ERROR("no more watchpoint registers available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->value) LOG_WARNING("xscale does not support value, mask arguments; ignoring"); /* check that length is a power of two */ for (uint32_t len = watchpoint->length; len != 1; len /= 2) { if (len % 2) { LOG_ERROR("xscale requires that watchpoint length is a power of two"); return ERROR_COMMAND_ARGUMENT_INVALID; } } if (watchpoint->length == 4) { /* single word watchpoint */ xscale->dbr_available--;/* one DBR reg used */ return ERROR_OK; } /* watchpoints across multiple words require both DBR registers */ if (xscale->dbr_available < 2) { LOG_ERROR("insufficient watchpoint registers available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->length > watchpoint->address) { LOG_ERROR("xscale does not support watchpoints with length " "greater than address"); return ERROR_COMMAND_ARGUMENT_INVALID; } xscale->dbr_available = 0; return ERROR_OK; } static int xscale_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct xscale_common *xscale = target_to_xscale(target); struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON]; uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!watchpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (watchpoint->set == 1) { if (watchpoint->length > 4) { dbcon_value &= ~0x103; /* clear DBCON[M] as well */ xscale->dbr1_used = 0; /* DBR1 was used for mask */ } else dbcon_value &= ~0x3; xscale_set_reg_u32(dbcon, dbcon_value); xscale->dbr0_used = 0; } else if (watchpoint->set == 2) { dbcon_value &= ~0xc; xscale_set_reg_u32(dbcon, dbcon_value); xscale->dbr1_used = 0; } watchpoint->set = 0; return ERROR_OK; } static int xscale_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct xscale_common *xscale = target_to_xscale(target); if (target->state != TARGET_HALTED) { LOG_ERROR("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (watchpoint->set) xscale_unset_watchpoint(target, watchpoint); if (watchpoint->length > 4) xscale->dbr_available++;/* both DBR regs now available */ xscale->dbr_available++; return ERROR_OK; } static int xscale_get_reg(struct reg *reg) { struct xscale_reg *arch_info = reg->arch_info; struct target *target = arch_info->target; struct xscale_common *xscale = target_to_xscale(target); /* DCSR, TX and RX are accessible via JTAG */ if (strcmp(reg->name, "XSCALE_DCSR") == 0) return xscale_read_dcsr(arch_info->target); else if (strcmp(reg->name, "XSCALE_TX") == 0) { /* 1 = consume register content */ return xscale_read_tx(arch_info->target, 1); } else if (strcmp(reg->name, "XSCALE_RX") == 0) { /* can't read from RX register (host -> debug handler) */ return ERROR_OK; } else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0) { /* can't (explicitly) read from TXRXCTRL register */ return ERROR_OK; } else {/* Other DBG registers have to be transfered by the debug handler * send CP read request (command 0x40) */ xscale_send_u32(target, 0x40); /* send CP register number */ xscale_send_u32(target, arch_info->dbg_handler_number); /* read register value */ xscale_read_tx(target, 1); buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32); reg->dirty = 0; reg->valid = 1; } return ERROR_OK; } static int xscale_set_reg(struct reg *reg, uint8_t *buf) { struct xscale_reg *arch_info = reg->arch_info; struct target *target = arch_info->target; struct xscale_common *xscale = target_to_xscale(target); uint32_t value = buf_get_u32(buf, 0, 32); /* DCSR, TX and RX are accessible via JTAG */ if (strcmp(reg->name, "XSCALE_DCSR") == 0) { buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32, value); return xscale_write_dcsr(arch_info->target, -1, -1); } else if (strcmp(reg->name, "XSCALE_RX") == 0) { buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value); return xscale_write_rx(arch_info->target); } else if (strcmp(reg->name, "XSCALE_TX") == 0) { /* can't write to TX register (debug-handler -> host) */ return ERROR_OK; } else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0) { /* can't (explicitly) write to TXRXCTRL register */ return ERROR_OK; } else {/* Other DBG registers have to be transfered by the debug handler * send CP write request (command 0x41) */ xscale_send_u32(target, 0x41); /* send CP register number */ xscale_send_u32(target, arch_info->dbg_handler_number); /* send CP register value */ xscale_send_u32(target, value); buf_set_u32(reg->value, 0, 32, value); } return ERROR_OK; } static int xscale_write_dcsr_sw(struct target *target, uint32_t value) { struct xscale_common *xscale = target_to_xscale(target); struct reg *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR]; struct xscale_reg *dcsr_arch_info = dcsr->arch_info; /* send CP write request (command 0x41) */ xscale_send_u32(target, 0x41); /* send CP register number */ xscale_send_u32(target, dcsr_arch_info->dbg_handler_number); /* send CP register value */ xscale_send_u32(target, value); buf_set_u32(dcsr->value, 0, 32, value); return ERROR_OK; } static int xscale_read_trace(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; struct xscale_trace_data **trace_data_p; /* 258 words from debug handler * 256 trace buffer entries * 2 checkpoint addresses */ uint32_t trace_buffer[258]; int is_address[256]; int i, j; unsigned int num_checkpoints = 0; if (target->state != TARGET_HALTED) { LOG_WARNING("target must be stopped to read trace data"); return ERROR_TARGET_NOT_HALTED; } /* send read trace buffer command (command 0x61) */ xscale_send_u32(target, 0x61); /* receive trace buffer content */ xscale_receive(target, trace_buffer, 258); /* parse buffer backwards to identify address entries */ for (i = 255; i >= 0; i--) { /* also count number of checkpointed entries */ if ((trace_buffer[i] & 0xe0) == 0xc0) num_checkpoints++; is_address[i] = 0; if (((trace_buffer[i] & 0xf0) == 0x90) || ((trace_buffer[i] & 0xf0) == 0xd0)) { if (i > 0) is_address[--i] = 1; if (i > 0) is_address[--i] = 1; if (i > 0) is_address[--i] = 1; if (i > 0) is_address[--i] = 1; } } /* search first non-zero entry that is not part of an address */ for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++) ; if (j == 256) { LOG_DEBUG("no trace data collected"); return ERROR_XSCALE_NO_TRACE_DATA; } /* account for possible partial address at buffer start (wrap mode only) */ if (is_address[0]) { /* first entry is address; complete set of 4? */ i = 1; while (i < 4) if (!is_address[i++]) break; if (i < 4) j += i; /* partial address; can't use it */ } /* if first valid entry is indirect branch, can't use that either (no address) */ if (((trace_buffer[j] & 0xf0) == 0x90) || ((trace_buffer[j] & 0xf0) == 0xd0)) j++; /* walk linked list to terminating entry */ for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next) ; *trace_data_p = malloc(sizeof(struct xscale_trace_data)); (*trace_data_p)->next = NULL; (*trace_data_p)->chkpt0 = trace_buffer[256]; (*trace_data_p)->chkpt1 = trace_buffer[257]; (*trace_data_p)->last_instruction = buf_get_u32(arm->pc->value, 0, 32); (*trace_data_p)->entries = malloc(sizeof(struct xscale_trace_entry) * (256 - j)); (*trace_data_p)->depth = 256 - j; (*trace_data_p)->num_checkpoints = num_checkpoints; for (i = j; i < 256; i++) { (*trace_data_p)->entries[i - j].data = trace_buffer[i]; if (is_address[i]) (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS; else (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE; } return ERROR_OK; } static int xscale_read_instruction(struct target *target, uint32_t pc, struct arm_instruction *instruction) { struct xscale_common *const xscale = target_to_xscale(target); int i; int section = -1; size_t size_read; uint32_t opcode; int retval; if (!xscale->trace.image) return ERROR_TRACE_IMAGE_UNAVAILABLE; /* search for the section the current instruction belongs to */ for (i = 0; i < xscale->trace.image->num_sections; i++) { if ((xscale->trace.image->sections[i].base_address <= pc) && (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > pc)) { section = i; break; } } if (section == -1) { /* current instruction couldn't be found in the image */ return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } if (xscale->trace.core_state == ARM_STATE_ARM) { uint8_t buf[4]; retval = image_read_section(xscale->trace.image, section, pc - xscale->trace.image->sections[section].base_address, 4, buf, &size_read); if (retval != ERROR_OK) { LOG_ERROR("error while reading instruction"); return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } opcode = target_buffer_get_u32(target, buf); arm_evaluate_opcode(opcode, pc, instruction); } else if (xscale->trace.core_state == ARM_STATE_THUMB) { uint8_t buf[2]; retval = image_read_section(xscale->trace.image, section, pc - xscale->trace.image->sections[section].base_address, 2, buf, &size_read); if (retval != ERROR_OK) { LOG_ERROR("error while reading instruction"); return ERROR_TRACE_INSTRUCTION_UNAVAILABLE; } opcode = target_buffer_get_u16(target, buf); thumb_evaluate_opcode(opcode, pc, instruction); } else { LOG_ERROR("BUG: unknown core state encountered"); exit(-1); } return ERROR_OK; } /* Extract address encoded into trace data. * Write result to address referenced by argument 'target', or 0 if incomplete. */ static inline void xscale_branch_address(struct xscale_trace_data *trace_data, int i, uint32_t *target) { /* if there are less than four entries prior to the indirect branch message * we can't extract the address */ if (i < 4) *target = 0; else { *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) | (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24); } } static inline void xscale_display_instruction(struct target *target, uint32_t pc, struct arm_instruction *instruction, struct command_context *cmd_ctx) { int retval = xscale_read_instruction(target, pc, instruction); if (retval == ERROR_OK) command_print(cmd_ctx, "%s", instruction->text); else command_print(cmd_ctx, "0x%8.8" PRIx32 "\t", pc); } static int xscale_analyze_trace(struct target *target, struct command_context *cmd_ctx) { struct xscale_common *xscale = target_to_xscale(target); struct xscale_trace_data *trace_data = xscale->trace.data; int i, retval; uint32_t breakpoint_pc; struct arm_instruction instruction; uint32_t current_pc = 0;/* initialized when address determined */ if (!xscale->trace.image) LOG_WARNING("No trace image loaded; use 'xscale trace_image'"); /* loop for each trace buffer that was loaded from target */ while (trace_data) { int chkpt = 0; /* incremented as checkpointed entries found */ int j; /* FIXME: set this to correct mode when trace buffer is first enabled */ xscale->trace.core_state = ARM_STATE_ARM; /* loop for each entry in this trace buffer */ for (i = 0; i < trace_data->depth; i++) { int exception = 0; uint32_t chkpt_reg = 0x0; uint32_t branch_target = 0; int count; /* trace entry type is upper nybble of 'message byte' */ int trace_msg_type = (trace_data->entries[i].data & 0xf0) >> 4; /* Target addresses of indirect branches are written into buffer * before the message byte representing the branch. Skip past it */ if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS) continue; switch (trace_msg_type) { case 0: /* Exceptions */ case 1: case 2: case 3: case 4: case 5: case 6: case 7: exception = (trace_data->entries[i].data & 0x70) >> 4; /* FIXME: vector table may be at ffff0000 */ branch_target = (trace_data->entries[i].data & 0xf0) >> 2; break; case 8: /* Direct Branch */ break; case 9: /* Indirect Branch */ xscale_branch_address(trace_data, i, &branch_target); break; case 13: /* Checkpointed Indirect Branch */ xscale_branch_address(trace_data, i, &branch_target); if ((trace_data->num_checkpoints == 2) && (chkpt == 0)) chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is *oldest */ else chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and *newest */ chkpt++; break; case 12: /* Checkpointed Direct Branch */ if ((trace_data->num_checkpoints == 2) && (chkpt == 0)) chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is *oldest */ else chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and *newest */ /* if no current_pc, checkpoint will be starting point */ if (current_pc == 0) branch_target = chkpt_reg; chkpt++; break; case 15:/* Roll-over */ break; default:/* Reserved */ LOG_WARNING("trace is suspect: invalid trace message byte"); continue; } /* If we don't have the current_pc yet, but we did get the branch target * (either from the trace buffer on indirect branch, or from a checkpoint reg), * then we can start displaying instructions at the next iteration, with * branch_target as the starting point. */ if (current_pc == 0) { current_pc = branch_target; /* remains 0 unless branch_target *obtained */ continue; } /* We have current_pc. Read and display the instructions from the image. * First, display count instructions (lower nybble of message byte). */ count = trace_data->entries[i].data & 0x0f; for (j = 0; j < count; j++) { xscale_display_instruction(target, current_pc, &instruction, cmd_ctx); current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2; } /* An additional instruction is implicitly added to count for * rollover and some exceptions: undef, swi, prefetch abort. */ if ((trace_msg_type == 15) || (exception > 0 && exception < 4)) { xscale_display_instruction(target, current_pc, &instruction, cmd_ctx); current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2; } if (trace_msg_type == 15) /* rollover */ continue; if (exception) { command_print(cmd_ctx, "--- exception %i ---", exception); continue; } /* not exception or rollover; next instruction is a branch and is * not included in the count */ xscale_display_instruction(target, current_pc, &instruction, cmd_ctx); /* for direct branches, extract branch destination from instruction */ if ((trace_msg_type == 8) || (trace_msg_type == 12)) { retval = xscale_read_instruction(target, current_pc, &instruction); if (retval == ERROR_OK) current_pc = instruction.info.b_bl_bx_blx.target_address; else current_pc = 0; /* branch destination unknown */ /* direct branch w/ checkpoint; can also get from checkpoint reg */ if (trace_msg_type == 12) { if (current_pc == 0) current_pc = chkpt_reg; else if (current_pc != chkpt_reg) /* sanity check */ LOG_WARNING("trace is suspect: checkpoint register " "inconsistent with adddress from image"); } if (current_pc == 0) command_print(cmd_ctx, "address unknown"); continue; } /* indirect branch; the branch destination was read from trace buffer */ if ((trace_msg_type == 9) || (trace_msg_type == 13)) { current_pc = branch_target; /* sanity check (checkpoint reg is redundant) */ if ((trace_msg_type == 13) && (chkpt_reg != branch_target)) LOG_WARNING("trace is suspect: checkpoint register " "inconsistent with address from trace buffer"); } } /* END: for (i = 0; i < trace_data->depth; i++) */ breakpoint_pc = trace_data->last_instruction; /* used below */ trace_data = trace_data->next; } /* END: while (trace_data) */ /* Finally... display all instructions up to the value of the pc when the * debug break occurred (saved when trace data was collected from target). * This is necessary because the trace only records execution branches and 16 * consecutive instructions (rollovers), so last few typically missed. */ if (current_pc == 0) return ERROR_OK;/* current_pc was never found */ /* how many instructions remaining? */ int gap_count = (breakpoint_pc - current_pc) / (xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2); /* should never be negative or over 16, but verify */ if (gap_count < 0 || gap_count > 16) { LOG_WARNING("trace is suspect: excessive gap at end of trace"); return ERROR_OK;/* bail; large number or negative value no good */ } /* display remaining instructions */ for (i = 0; i < gap_count; i++) { xscale_display_instruction(target, current_pc, &instruction, cmd_ctx); current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2; } return ERROR_OK; } static const struct reg_arch_type xscale_reg_type = { .get = xscale_get_reg, .set = xscale_set_reg, }; static void xscale_build_reg_cache(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct xscale_reg *arch_info = malloc(sizeof(xscale_reg_arch_info)); int i; int num_regs = ARRAY_SIZE(xscale_reg_arch_info); (*cache_p) = arm_build_reg_cache(target, arm); (*cache_p)->next = malloc(sizeof(struct reg_cache)); cache_p = &(*cache_p)->next; /* fill in values for the xscale reg cache */ (*cache_p)->name = "XScale registers"; (*cache_p)->next = NULL; (*cache_p)->reg_list = malloc(num_regs * sizeof(struct reg)); (*cache_p)->num_regs = num_regs; for (i = 0; i < num_regs; i++) { (*cache_p)->reg_list[i].name = xscale_reg_list[i]; (*cache_p)->reg_list[i].value = calloc(4, 1); (*cache_p)->reg_list[i].dirty = 0; (*cache_p)->reg_list[i].valid = 0; (*cache_p)->reg_list[i].size = 32; (*cache_p)->reg_list[i].arch_info = &arch_info[i]; (*cache_p)->reg_list[i].type = &xscale_reg_type; arch_info[i] = xscale_reg_arch_info[i]; arch_info[i].target = target; } xscale->reg_cache = (*cache_p); } static int xscale_init_target(struct command_context *cmd_ctx, struct target *target) { xscale_build_reg_cache(target); return ERROR_OK; } static int xscale_init_arch_info(struct target *target, struct xscale_common *xscale, struct jtag_tap *tap) { struct arm *arm; uint32_t high_reset_branch, low_reset_branch; int i; arm = &xscale->arm; /* store architecture specfic data */ xscale->common_magic = XSCALE_COMMON_MAGIC; /* PXA3xx with 11 bit IR shifts the JTAG instructions */ if (tap->ir_length == 11) xscale->xscale_variant = XSCALE_PXA3XX; else xscale->xscale_variant = XSCALE_IXP4XX_PXA2XX; /* the debug handler isn't installed (and thus not running) at this time */ xscale->handler_address = 0xfe000800; /* clear the vectors we keep locally for reference */ memset(xscale->low_vectors, 0, sizeof(xscale->low_vectors)); memset(xscale->high_vectors, 0, sizeof(xscale->high_vectors)); /* no user-specified vectors have been configured yet */ xscale->static_low_vectors_set = 0x0; xscale->static_high_vectors_set = 0x0; /* calculate branches to debug handler */ low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2; high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2; xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0); xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0); for (i = 1; i <= 7; i++) { xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0); xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0); } /* 64kB aligned region used for DCache cleaning */ xscale->cache_clean_address = 0xfffe0000; xscale->hold_rst = 0; xscale->external_debug_break = 0; xscale->ibcr_available = 2; xscale->ibcr0_used = 0; xscale->ibcr1_used = 0; xscale->dbr_available = 2; xscale->dbr0_used = 0; xscale->dbr1_used = 0; LOG_INFO("%s: hardware has 2 breakpoints and 2 watchpoints", target_name(target)); xscale->arm_bkpt = ARMV5_BKPT(0x0); xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff; xscale->vector_catch = 0x1; xscale->trace.data = NULL; xscale->trace.image = NULL; xscale->trace.mode = XSCALE_TRACE_DISABLED; xscale->trace.buffer_fill = 0; xscale->trace.fill_counter = 0; /* prepare ARMv4/5 specific information */ arm->arch_info = xscale; arm->core_type = ARM_MODE_ANY; arm->read_core_reg = xscale_read_core_reg; arm->write_core_reg = xscale_write_core_reg; arm->full_context = xscale_full_context; arm_init_arch_info(target, arm); xscale->armv4_5_mmu.armv4_5_cache.ctype = -1; xscale->armv4_5_mmu.get_ttb = xscale_get_ttb; xscale->armv4_5_mmu.read_memory = xscale_read_memory; xscale->armv4_5_mmu.write_memory = xscale_write_memory; xscale->armv4_5_mmu.disable_mmu_caches = xscale_disable_mmu_caches; xscale->armv4_5_mmu.enable_mmu_caches = xscale_enable_mmu_caches; xscale->armv4_5_mmu.has_tiny_pages = 1; xscale->armv4_5_mmu.mmu_enabled = 0; return ERROR_OK; } static int xscale_target_create(struct target *target, Jim_Interp *interp) { struct xscale_common *xscale; if (sizeof xscale_debug_handler > 0x800) { LOG_ERROR("debug_handler.bin: larger than 2kb"); return ERROR_FAIL; } xscale = calloc(1, sizeof(*xscale)); if (!xscale) return ERROR_FAIL; return xscale_init_arch_info(target, xscale, target->tap); } COMMAND_HANDLER(xscale_handle_debug_handler_command) { struct target *target = NULL; struct xscale_common *xscale; int retval; uint32_t handler_address; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[0]); if (target == NULL) { LOG_ERROR("target '%s' not defined", CMD_ARGV[0]); return ERROR_FAIL; } xscale = target_to_xscale(target); retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], handler_address); if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) || ((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800))) xscale->handler_address = handler_address; else { LOG_ERROR( "xscale debug_handler
must be between 0x800 and 0x1fef800 or between 0xfe000800 and 0xfffff800"); return ERROR_FAIL; } return ERROR_OK; } COMMAND_HANDLER(xscale_handle_cache_clean_address_command) { struct target *target = NULL; struct xscale_common *xscale; int retval; uint32_t cache_clean_address; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; target = get_target(CMD_ARGV[0]); if (target == NULL) { LOG_ERROR("target '%s' not defined", CMD_ARGV[0]); return ERROR_FAIL; } xscale = target_to_xscale(target); retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cache_clean_address); if (cache_clean_address & 0xffff) LOG_ERROR("xscale cache_clean_address
must be 64kb aligned"); else xscale->cache_clean_address = cache_clean_address; return ERROR_OK; } COMMAND_HANDLER(xscale_handle_cache_info_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; return armv4_5_handle_cache_info_command(CMD_CTX, &xscale->armv4_5_mmu.armv4_5_cache); } static int xscale_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) { struct xscale_common *xscale = target_to_xscale(target); uint32_t cb; if (xscale->common_magic != XSCALE_COMMON_MAGIC) { LOG_ERROR(xscale_not); return ERROR_TARGET_INVALID; } uint32_t ret; int retval = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &cb, &ret); if (retval != ERROR_OK) return retval; *physical = ret; return ERROR_OK; } static int xscale_mmu(struct target *target, int *enabled) { struct xscale_common *xscale = target_to_xscale(target); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_INVALID; } *enabled = xscale->armv4_5_mmu.mmu_enabled; return ERROR_OK; } COMMAND_HANDLER(xscale_handle_mmu_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } if (CMD_ARGC >= 1) { bool enable; COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable); if (enable) xscale_enable_mmu_caches(target, 1, 0, 0); else xscale_disable_mmu_caches(target, 1, 0, 0); xscale->armv4_5_mmu.mmu_enabled = enable; } command_print(CMD_CTX, "mmu %s", (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled"); return ERROR_OK; } COMMAND_HANDLER(xscale_handle_idcache_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } bool icache = false; if (strcmp(CMD_NAME, "icache") == 0) icache = true; if (CMD_ARGC >= 1) { bool enable; COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable); if (icache) { xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = enable; if (enable) xscale_enable_mmu_caches(target, 0, 0, 1); else xscale_disable_mmu_caches(target, 0, 0, 1); } else { xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = enable; if (enable) xscale_enable_mmu_caches(target, 0, 1, 0); else xscale_disable_mmu_caches(target, 0, 1, 0); } } bool enabled = icache ? xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled : xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled; const char *msg = enabled ? "enabled" : "disabled"; command_print(CMD_CTX, "%s %s", CMD_NAME, msg); return ERROR_OK; } static const struct { char name[15]; unsigned mask; } vec_ids[] = { { "fiq", DCSR_TF, }, { "irq", DCSR_TI, }, { "dabt", DCSR_TD, }, { "pabt", DCSR_TA, }, { "swi", DCSR_TS, }, { "undef", DCSR_TU, }, { "reset", DCSR_TR, }, }; COMMAND_HANDLER(xscale_handle_vector_catch_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; uint32_t dcsr_value; uint32_t catch = 0; struct reg *dcsr_reg = &xscale->reg_cache->reg_list[XSCALE_DCSR]; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32); if (CMD_ARGC > 0) { if (CMD_ARGC == 1) { if (strcmp(CMD_ARGV[0], "all") == 0) { catch = DCSR_TRAP_MASK; CMD_ARGC--; } else if (strcmp(CMD_ARGV[0], "none") == 0) { catch = 0; CMD_ARGC--; } } while (CMD_ARGC-- > 0) { unsigned i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name)) continue; catch |= vec_ids[i].mask; break; } if (i == ARRAY_SIZE(vec_ids)) { LOG_ERROR("No vector '%s'", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } } buf_set_u32(dcsr_reg->value, 0, 32, (buf_get_u32(dcsr_reg->value, 0, 32) & ~DCSR_TRAP_MASK) | catch); xscale_write_dcsr(target, -1, -1); } dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32); for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD_CTX, "%15s: %s", vec_ids[i].name, (dcsr_value & vec_ids[i].mask) ? "catch" : "ignore"); } return ERROR_OK; } COMMAND_HANDLER(xscale_handle_vector_table_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int err = 0; int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (CMD_ARGC == 0) { /* print current settings */ int idx; command_print(CMD_CTX, "active user-set static vectors:"); for (idx = 1; idx < 8; idx++) if (xscale->static_low_vectors_set & (1 << idx)) command_print(CMD_CTX, "low %d: 0x%" PRIx32, idx, xscale->static_low_vectors[idx]); for (idx = 1; idx < 8; idx++) if (xscale->static_high_vectors_set & (1 << idx)) command_print(CMD_CTX, "high %d: 0x%" PRIx32, idx, xscale->static_high_vectors[idx]); return ERROR_OK; } if (CMD_ARGC != 3) err = 1; else { int idx; COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], idx); uint32_t vec; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], vec); if (idx < 1 || idx >= 8) err = 1; if (!err && strcmp(CMD_ARGV[0], "low") == 0) { xscale->static_low_vectors_set |= (1<static_low_vectors[idx] = vec; } else if (!err && (strcmp(CMD_ARGV[0], "high") == 0)) { xscale->static_high_vectors_set |= (1<static_high_vectors[idx] = vec; } else err = 1; } if (err) return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(xscale_handle_trace_buffer_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); uint32_t dcsr_value; int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } if (CMD_ARGC >= 1) { if (strcmp("enable", CMD_ARGV[0]) == 0) xscale->trace.mode = XSCALE_TRACE_WRAP; /* default */ else if (strcmp("disable", CMD_ARGV[0]) == 0) xscale->trace.mode = XSCALE_TRACE_DISABLED; else return ERROR_COMMAND_SYNTAX_ERROR; } if (CMD_ARGC >= 2 && xscale->trace.mode != XSCALE_TRACE_DISABLED) { if (strcmp("fill", CMD_ARGV[1]) == 0) { int buffcount = 1; /* default */ if (CMD_ARGC >= 3) COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], buffcount); if (buffcount < 1) { /* invalid */ command_print(CMD_CTX, "fill buffer count must be > 0"); xscale->trace.mode = XSCALE_TRACE_DISABLED; return ERROR_COMMAND_SYNTAX_ERROR; } xscale->trace.buffer_fill = buffcount; xscale->trace.mode = XSCALE_TRACE_FILL; } else if (strcmp("wrap", CMD_ARGV[1]) == 0) xscale->trace.mode = XSCALE_TRACE_WRAP; else { xscale->trace.mode = XSCALE_TRACE_DISABLED; return ERROR_COMMAND_SYNTAX_ERROR; } } if (xscale->trace.mode != XSCALE_TRACE_DISABLED) { char fill_string[12]; sprintf(fill_string, "fill %d", xscale->trace.buffer_fill); command_print(CMD_CTX, "trace buffer enabled (%s)", (xscale->trace.mode == XSCALE_TRACE_FILL) ? fill_string : "wrap"); } else command_print(CMD_CTX, "trace buffer disabled"); dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32); if (xscale->trace.mode == XSCALE_TRACE_FILL) xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2); else xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc); return ERROR_OK; } COMMAND_HANDLER(xscale_handle_trace_image_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (xscale->trace.image) { image_close(xscale->trace.image); free(xscale->trace.image); command_print(CMD_CTX, "previously loaded image found and closed"); } xscale->trace.image = malloc(sizeof(struct image)); xscale->trace.image->base_address_set = 0; xscale->trace.image->start_address_set = 0; /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { xscale->trace.image->base_address_set = 1; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address); } else xscale->trace.image->base_address_set = 0; if (image_open(xscale->trace.image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) { free(xscale->trace.image); xscale->trace.image = NULL; return ERROR_OK; } return ERROR_OK; } COMMAND_HANDLER(xscale_handle_dump_trace_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); struct xscale_trace_data *trace_data; struct fileio file; int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; trace_data = xscale->trace.data; if (!trace_data) { command_print(CMD_CTX, "no trace data collected"); return ERROR_OK; } if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) return ERROR_OK; while (trace_data) { int i; fileio_write_u32(&file, trace_data->chkpt0); fileio_write_u32(&file, trace_data->chkpt1); fileio_write_u32(&file, trace_data->last_instruction); fileio_write_u32(&file, trace_data->depth); for (i = 0; i < trace_data->depth; i++) fileio_write_u32(&file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16)); trace_data = trace_data->next; } fileio_close(&file); return ERROR_OK; } COMMAND_HANDLER(xscale_handle_analyze_trace_buffer_command) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; xscale_analyze_trace(target, CMD_CTX); return ERROR_OK; } COMMAND_HANDLER(xscale_handle_cp15) { struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } uint32_t reg_no = 0; struct reg *reg = NULL; if (CMD_ARGC > 0) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg_no); /*translate from xscale cp15 register no to openocd register*/ switch (reg_no) { case 0: reg_no = XSCALE_MAINID; break; case 1: reg_no = XSCALE_CTRL; break; case 2: reg_no = XSCALE_TTB; break; case 3: reg_no = XSCALE_DAC; break; case 5: reg_no = XSCALE_FSR; break; case 6: reg_no = XSCALE_FAR; break; case 13: reg_no = XSCALE_PID; break; case 15: reg_no = XSCALE_CPACCESS; break; default: command_print(CMD_CTX, "invalid register number"); return ERROR_COMMAND_SYNTAX_ERROR; } reg = &xscale->reg_cache->reg_list[reg_no]; } if (CMD_ARGC == 1) { uint32_t value; /* read cp15 control register */ xscale_get_reg(reg); value = buf_get_u32(reg->value, 0, 32); command_print(CMD_CTX, "%s (/%i): 0x%" PRIx32 "", reg->name, (int)(reg->size), value); } else if (CMD_ARGC == 2) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); /* send CP write request (command 0x41) */ xscale_send_u32(target, 0x41); /* send CP register number */ xscale_send_u32(target, reg_no); /* send CP register value */ xscale_send_u32(target, value); /* execute cpwait to ensure outstanding operations complete */ xscale_send_u32(target, 0x53); } else return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } static const struct command_registration xscale_exec_command_handlers[] = { { .name = "cache_info", .handler = xscale_handle_cache_info_command, .mode = COMMAND_EXEC, .help = "display information about CPU caches", }, { .name = "mmu", .handler = xscale_handle_mmu_command, .mode = COMMAND_EXEC, .help = "enable or disable the MMU", .usage = "['enable'|'disable']", }, { .name = "icache", .handler = xscale_handle_idcache_command, .mode = COMMAND_EXEC, .help = "display ICache state, optionally enabling or " "disabling it", .usage = "['enable'|'disable']", }, { .name = "dcache", .handler = xscale_handle_idcache_command, .mode = COMMAND_EXEC, .help = "display DCache state, optionally enabling or " "disabling it", .usage = "['enable'|'disable']", }, { .name = "vector_catch", .handler = xscale_handle_vector_catch_command, .mode = COMMAND_EXEC, .help = "set or display mask of vectors " "that should trigger debug entry", .usage = "['all'|'none'|'fiq'|'irq'|'dabt'|'pabt'|'swi'|'undef'|'reset']", }, { .name = "vector_table", .handler = xscale_handle_vector_table_command, .mode = COMMAND_EXEC, .help = "set vector table entry in mini-ICache, " "or display current tables", .usage = "[('high'|'low') index code]", }, { .name = "trace_buffer", .handler = xscale_handle_trace_buffer_command, .mode = COMMAND_EXEC, .help = "display trace buffer status, enable or disable " "tracing, and optionally reconfigure trace mode", .usage = "['enable'|'disable' ['fill' [number]|'wrap']]", }, { .name = "dump_trace", .handler = xscale_handle_dump_trace_command, .mode = COMMAND_EXEC, .help = "dump content of trace buffer to file", .usage = "filename", }, { .name = "analyze_trace", .handler = xscale_handle_analyze_trace_buffer_command, .mode = COMMAND_EXEC, .help = "analyze content of trace buffer", .usage = "", }, { .name = "trace_image", .handler = xscale_handle_trace_image_command, .mode = COMMAND_EXEC, .help = "load image from file to address (default 0)", .usage = "filename [offset [filetype]]", }, { .name = "cp15", .handler = xscale_handle_cp15, .mode = COMMAND_EXEC, .help = "Read or write coprocessor 15 register.", .usage = "register [value]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration xscale_any_command_handlers[] = { { .name = "debug_handler", .handler = xscale_handle_debug_handler_command, .mode = COMMAND_ANY, .help = "Change address used for debug handler.", .usage = "
", }, { .name = "cache_clean_address", .handler = xscale_handle_cache_clean_address_command, .mode = COMMAND_ANY, .help = "Change address used for cleaning data cache.", .usage = "address", }, { .chain = xscale_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration xscale_command_handlers[] = { { .chain = arm_command_handlers, }, { .name = "xscale", .mode = COMMAND_ANY, .help = "xscale command group", .usage = "", .chain = xscale_any_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type xscale_target = { .name = "xscale", .poll = xscale_poll, .arch_state = xscale_arch_state, .halt = xscale_halt, .resume = xscale_resume, .step = xscale_step, .assert_reset = xscale_assert_reset, .deassert_reset = xscale_deassert_reset, /* REVISIT on some cores, allow exporting iwmmxt registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = xscale_read_memory, .read_phys_memory = xscale_read_phys_memory, .write_memory = xscale_write_memory, .write_phys_memory = xscale_write_phys_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = xscale_add_breakpoint, .remove_breakpoint = xscale_remove_breakpoint, .add_watchpoint = xscale_add_watchpoint, .remove_watchpoint = xscale_remove_watchpoint, .commands = xscale_command_handlers, .target_create = xscale_target_create, .init_target = xscale_init_target, .virt2phys = xscale_virt2phys, .mmu = xscale_mmu }; openocd-0.9.0/src/target/xscale.h0000644000175000017500000001221012315575361013601 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef XSCALE_H #define XSCALE_H #include "arm.h" #include "armv4_5_mmu.h" #include "trace.h" #define XSCALE_COMMON_MAGIC 0x58534341 /* These four JTAG instructions are architecturally defined. * Lengths are core-specific; originally 5 bits, later 7. */ #define XSCALE_DBGRX 0x02 #define XSCALE_DBGTX 0x10 #define XSCALE_LDIC 0x07 #define XSCALE_SELDCSR 0x09 /* Possible CPU types */ #define XSCALE_IXP4XX_PXA2XX 0x0 #define XSCALE_PXA3XX 0x4 enum xscale_debug_reason { XSCALE_DBG_REASON_GENERIC, XSCALE_DBG_REASON_RESET, XSCALE_DBG_REASON_TB_FULL, }; enum xscale_trace_entry_type { XSCALE_TRACE_MESSAGE = 0x0, XSCALE_TRACE_ADDRESS = 0x1, }; struct xscale_trace_entry { uint8_t data; enum xscale_trace_entry_type type; }; struct xscale_trace_data { struct xscale_trace_entry *entries; int depth; uint32_t chkpt0; uint32_t chkpt1; uint32_t last_instruction; unsigned int num_checkpoints; struct xscale_trace_data *next; }; enum trace_mode { XSCALE_TRACE_DISABLED, XSCALE_TRACE_FILL, XSCALE_TRACE_WRAP }; struct xscale_trace { struct image *image; /* source for target opcodes */ struct xscale_trace_data *data; /* linked list of collected trace data */ int buffer_fill; /* maximum number of trace runs to read */ int fill_counter; /* running count during trace collection */ enum trace_mode mode; enum arm_state core_state; /* current core state (ARM, Thumb) */ }; struct xscale_common { /* armv4/5 common stuff */ struct arm arm; int common_magic; /* XScale registers (CP15, DBG) */ struct reg_cache *reg_cache; /* current state of the debug handler */ uint32_t handler_address; /* target-endian buffers with exception vectors */ uint32_t low_vectors[8]; uint32_t high_vectors[8]; /* static low vectors */ uint8_t static_low_vectors_set; /* bit field with static vectors set by the user */ uint8_t static_high_vectors_set; /* bit field with static vectors set by the user */ uint32_t static_low_vectors[8]; uint32_t static_high_vectors[8]; /* DCache cleaning */ uint32_t cache_clean_address; /* whether hold_rst and ext_dbg_break should be set */ int hold_rst; int external_debug_break; /* breakpoint / watchpoint handling */ int dbr_available; int dbr0_used; int dbr1_used; int ibcr_available; int ibcr0_used; int ibcr1_used; uint32_t arm_bkpt; uint16_t thumb_bkpt; uint8_t vector_catch; struct xscale_trace trace; int arch_debug_reason; /* MMU/Caches */ struct armv4_5_mmu_common armv4_5_mmu; uint32_t cp15_control_reg; int fast_memory_access; /* CPU variant */ int xscale_variant; }; static inline struct xscale_common * target_to_xscale(struct target *target) { return container_of(target->arch_info, struct xscale_common, arm); } struct xscale_reg { int dbg_handler_number; struct target *target; }; enum { XSCALE_MAINID, /* 0 */ XSCALE_CACHETYPE, XSCALE_CTRL, XSCALE_AUXCTRL, XSCALE_TTB, XSCALE_DAC, XSCALE_FSR, XSCALE_FAR, XSCALE_PID, XSCALE_CPACCESS, XSCALE_IBCR0, /* 10 */ XSCALE_IBCR1, XSCALE_DBR0, XSCALE_DBR1, XSCALE_DBCON, XSCALE_TBREG, XSCALE_CHKPT0, XSCALE_CHKPT1, XSCALE_DCSR, XSCALE_TX, XSCALE_RX, /* 20 */ XSCALE_TXRXCTRL, }; #define ERROR_XSCALE_NO_TRACE_DATA (-700) /* DCSR bit and field definitions */ #define DCSR_TR (1 << 16) #define DCSR_TU (1 << 17) #define DCSR_TS (1 << 18) #define DCSR_TA (1 << 19) #define DCSR_TD (1 << 20) #define DCSR_TI (1 << 22) #define DCSR_TF (1 << 23) #define DCSR_TRAP_MASK \ (DCSR_TF | DCSR_TI | DCSR_TD | DCSR_TA | DCSR_TS | DCSR_TU | DCSR_TR) #endif /* XSCALE_H */ openocd-0.9.0/src/target/mips_m4k.c0000644000175000017500000012306012516456304014044 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2009 by David N. Claffey * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "mips32.h" #include "mips_m4k.h" #include "mips32_dmaacc.h" #include "target_type.h" #include "register.h" static void mips_m4k_enable_breakpoints(struct target *target); static void mips_m4k_enable_watchpoints(struct target *target); static int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_internal_restore(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); static int mips_m4k_halt(struct target *target); static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer); static int mips_m4k_examine_debug_reason(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; uint32_t break_status; int retval; if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { if (ejtag_info->debug_caps & EJTAG_DCR_IB) { /* get info about inst breakpoint support */ retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &break_status); if (retval != ERROR_OK) return retval; if (break_status & 0x1f) { /* we have halted on a breakpoint */ retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_BREAKPOINT; } } if (ejtag_info->debug_caps & EJTAG_DCR_DB) { /* get info about data breakpoint support */ retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &break_status); if (retval != ERROR_OK) return retval; if (break_status & 0x1f) { /* we have halted on a breakpoint */ retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_WATCHPOINT; } } } return ERROR_OK; } static int mips_m4k_debug_entry(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; mips32_save_context(target); /* make sure stepping disabled, SSt bit in CP0 debug register cleared */ mips_ejtag_config_step(ejtag_info, 0); /* make sure break unit configured */ mips32_configure_break_unit(target); /* attempt to find halt reason */ mips_m4k_examine_debug_reason(target); /* default to mips32 isa, it will be changed below if required */ mips32->isa_mode = MIPS32_ISA_MIPS32; if (ejtag_info->impcode & EJTAG_IMP_MIPS16) mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1); LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s", buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32), target_state_name(target)); return ERROR_OK; } static struct target *get_mips_m4k(struct target *target, int32_t coreid) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; head = head->next; } return target; } static int mips_m4k_halt_smp(struct target *target) { int retval = ERROR_OK; struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { int ret = ERROR_OK; curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED)) ret = mips_m4k_halt(curr); if (ret != ERROR_OK) { LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid); retval = ret; } head = head->next; } return retval; } static int update_halt_gdb(struct target *target) { int retval = ERROR_OK; if (target->gdb_service->core[0] == -1) { target->gdb_service->target = target; target->gdb_service->core[0] = target->coreid; retval = mips_m4k_halt_smp(target); } return retval; } static int mips_m4k_poll(struct target *target) { int retval = ERROR_OK; struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl; enum target_state prev_target_state = target->state; /* toggle to another core is done by gdb as follow */ /* maint packet J core_id */ /* continue */ /* the next polling trigger an halt event sent to gdb */ if ((target->state == TARGET_HALTED) && (target->smp) && (target->gdb_service) && (target->gdb_service->target == NULL)) { target->gdb_service->target = get_mips_m4k(target, target->gdb_service->core[1]); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return retval; } /* read ejtag control reg */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; /* clear this bit before handling polling * as after reset registers will read zero */ if (ejtag_ctrl & EJTAG_CTRL_ROCC) { /* we have detected a reset, clear flag * otherwise ejtag will not work */ ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; LOG_DEBUG("Reset Detected"); } /* check for processor halted */ if (ejtag_ctrl & EJTAG_CTRL_BRKST) { if ((target->state != TARGET_HALTED) && (target->state != TARGET_DEBUG_RUNNING)) { if (target->state == TARGET_UNKNOWN) LOG_DEBUG("EJTAG_CTRL_BRKST already set during server startup."); /* OpenOCD was was probably started on the board with EJTAG_CTRL_BRKST already set * (maybe put on by HALT-ing the board in the previous session). * * Force enable debug entry for this session. */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT); target->state = TARGET_HALTED; retval = mips_m4k_debug_entry(target); if (retval != ERROR_OK) return retval; if (target->smp && ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))) { retval = update_halt_gdb(target); if (retval != ERROR_OK) return retval; } target_call_event_callbacks(target, TARGET_EVENT_HALTED); } else if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; retval = mips_m4k_debug_entry(target); if (retval != ERROR_OK) return retval; if (target->smp) { retval = update_halt_gdb(target); if (retval != ERROR_OK) return retval; } target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } else target->state = TARGET_RUNNING; /* LOG_DEBUG("ctrl = 0x%08X", ejtag_ctrl); */ return ERROR_OK; } static int mips_m4k_halt(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { /* we came here in a reset_halt or reset_init sequence * debug entry was already prepared in mips_m4k_assert_reset() */ target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } } /* break processor */ mips_ejtag_enter_debug(ejtag_info); target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int mips_m4k_assert_reset(struct target *target) { struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; LOG_DEBUG("target->state: %s", target_state_name(target)); enum reset_types jtag_reset_config = jtag_get_reset_config(); /* some cores support connecting while srst is asserted * use that mode is it has been configured */ bool srst_asserted = false; if (!(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); srst_asserted = true; } /* EJTAG before v2.5/2.6 does not support EJTAGBOOT or NORMALBOOT */ if (ejtag_info->ejtag_version != EJTAG_VERSION_20) { if (target->reset_halt) { /* use hardware to catch reset */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT); } else mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT); } if (jtag_reset_config & RESET_HAS_SRST) { /* here we should issue a srst only, but we may have to assert trst as well */ if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else if (!srst_asserted) jtag_add_reset(0, 1); } else { if (mips_m4k->is_pic32mx) { LOG_DEBUG("Using MTAP reset to reset processor..."); /* use microchip specific MTAP reset */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP); mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST); mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST); mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); } else { /* use ejtag reset - not supported by all cores */ uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST; LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor..."); mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); } } target->state = TARGET_RESET; jtag_add_sleep(50000); register_cache_invalidate(mips_m4k->mips32.core_cache); if (target->reset_halt) { int retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int mips_m4k_deassert_reset(struct target *target) { LOG_DEBUG("target->state: %s", target_state_name(target)); /* deassert reset lines */ jtag_add_reset(0, 0); return ERROR_OK; } static int mips_m4k_single_step_core(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; /* configure single step mode */ mips_ejtag_config_step(ejtag_info, 1); /* disable interrupts while stepping */ mips32_enable_interrupts(target, 0); /* exit debug mode */ mips_ejtag_exit_debug(ejtag_info); mips_m4k_debug_entry(target); return ERROR_OK; } static int mips_m4k_restore_smp(struct target *target, uint32_t address, int handle_breakpoints) { int retval = ERROR_OK; struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { int ret = ERROR_OK; curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { /* resume current address , not in step mode */ ret = mips_m4k_internal_restore(curr, 1, address, handle_breakpoints, 0); if (ret != ERROR_OK) { LOG_ERROR("target->coreid :%" PRId32 " failed to resume at address :0x%" PRIx32, curr->coreid, address); retval = ret; } } head = head->next; } return retval; } static int mips_m4k_internal_restore(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct breakpoint *breakpoint = NULL; uint32_t resume_pc; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); mips_m4k_enable_breakpoints(target); mips_m4k_enable_watchpoints(target); } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; } if (ejtag_info->impcode & EJTAG_IMP_MIPS16) buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode); if (!current) resume_pc = address; else resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); mips32_restore_context(target); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); mips_m4k_unset_breakpoint(target, breakpoint); mips_m4k_single_step_core(target); mips_m4k_set_breakpoint(target, breakpoint); } } /* enable interrupts if we are running */ mips32_enable_interrupts(target, !debug_execution); /* exit debug mode */ mips_ejtag_exit_debug(ejtag_info); target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ register_cache_invalidate(mips32->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; } static int mips_m4k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval = ERROR_OK; /* dummy resume for smp toggle in order to reduce gdb impact */ if ((target->smp) && (target->gdb_service->core[1] != -1)) { /* simulate a start and halt of target */ target->gdb_service->target = NULL; target->gdb_service->core[0] = target->gdb_service->core[1]; /* fake resume at next poll we play the target core[1], see poll*/ target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return retval; } retval = mips_m4k_internal_restore(target, current, address, handle_breakpoints, debug_execution); if (retval == ERROR_OK && target->smp) { target->gdb_service->core[0] = -1; retval = mips_m4k_restore_smp(target, address, handle_breakpoints); } return retval; } static int mips_m4k_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct breakpoint *breakpoint = NULL; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; } /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)); if (breakpoint) mips_m4k_unset_breakpoint(target, breakpoint); } /* restore context */ mips32_restore_context(target); /* configure single step mode */ mips_ejtag_config_step(ejtag_info, 1); target->debug_reason = DBG_REASON_SINGLESTEP; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); /* disable interrupts while stepping */ mips32_enable_interrupts(target, 0); /* exit debug mode */ mips_ejtag_exit_debug(ejtag_info); /* registers are now invalid */ register_cache_invalidate(mips32->core_cache); LOG_DEBUG("target stepped "); mips_m4k_debug_entry(target); if (breakpoint) mips_m4k_set_breakpoint(target, breakpoint); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return ERROR_OK; } static void mips_m4k_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; /* set any pending breakpoints */ while (breakpoint) { if (breakpoint->set == 0) mips_m4k_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } } static int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct mips32_comparator *comparator_list = mips32->inst_break_list; int retval; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { int bp_num = 0; while (comparator_list[bp_num].used && (bp_num < mips32->num_inst_bpoints)) bp_num++; if (bp_num >= mips32->num_inst_bpoints) { LOG_ERROR("Can not find free FP Comparator(bpid: %" PRIu32 ")", breakpoint->unique_id); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } breakpoint->set = bp_num + 1; comparator_list[bp_num].used = 1; comparator_list[bp_num].bp_value = breakpoint->address; /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved. * Warning: there is no IB ASID registers in 2.0. * Do not set it! :) */ if (ejtag_info->ejtag_version == EJTAG_VERSION_20) comparator_list[bp_num].bp_value &= 0xFFFFFFFC; target_write_u32(target, comparator_list[bp_num].reg_address, comparator_list[bp_num].bp_value); target_write_u32(target, comparator_list[bp_num].reg_address + ejtag_info->ejtag_ibm_offs, 0x00000000); target_write_u32(target, comparator_list[bp_num].reg_address + ejtag_info->ejtag_ibc_offs, 1); LOG_DEBUG("bpid: %" PRIu32 ", bp_num %i bp_value 0x%" PRIx32 "", breakpoint->unique_id, bp_num, comparator_list[bp_num].bp_value); } else if (breakpoint->type == BKPT_SOFT) { LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t verify = 0xffffffff; retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; if (verify != MIPS32_SDBBP) { LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } } else { uint16_t verify = 0xffff; retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; if (verify != MIPS16_SDBBP) { LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } } breakpoint->set = 20; /* Any nice value but 0 */ } return ERROR_OK; } static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct mips32_comparator *comparator_list = mips32->inst_break_list; int retval; if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { int bp_num = breakpoint->set - 1; if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints)) { LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")", breakpoint->unique_id); return ERROR_OK; } LOG_DEBUG("bpid: %" PRIu32 " - releasing hw: %d", breakpoint->unique_id, bp_num); comparator_list[bp_num].used = 0; comparator_list[bp_num].bp_value = 0; target_write_u32(target, comparator_list[bp_num].reg_address + ejtag_info->ejtag_ibc_offs, 0); } else { /* restore original instruction (kept in target endianness) */ LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t current_instr; /* check that user program has not modified breakpoint instruction */ retval = target_read_memory(target, breakpoint->address, 4, 1, (uint8_t *)¤t_instr); if (retval != ERROR_OK) return retval; /** * target_read_memory() gets us data in _target_ endianess. * If we want to use this data on the host for comparisons with some macros * we must first transform it to _host_ endianess using target_buffer_get_u32(). */ current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); if (current_instr == MIPS32_SDBBP) { retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } else { uint16_t current_instr; /* check that user program has not modified breakpoint instruction */ retval = target_read_memory(target, breakpoint->address, 2, 1, (uint8_t *)¤t_instr); if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); if (current_instr == MIPS16_SDBBP) { retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } } breakpoint->set = 0; return ERROR_OK; } static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct mips32_common *mips32 = target_to_mips32(target); if (breakpoint->type == BKPT_HARD) { if (mips32->num_inst_bpoints_avail < 1) { LOG_INFO("no hardware breakpoint available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } mips32->num_inst_bpoints_avail--; } return mips_m4k_set_breakpoint(target, breakpoint); } static int mips_m4k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (breakpoint->set) mips_m4k_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) mips32->num_inst_bpoints_avail++; return ERROR_OK; } static int mips_m4k_set_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct mips32_comparator *comparator_list = mips32->data_break_list; int wp_num = 0; /* * watchpoint enabled, ignore all byte lanes in value register * and exclude both load and store accesses from watchpoint * condition evaluation */ int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE | (0xff << EJTAG_DBCn_BLM_SHIFT); if (watchpoint->set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } while (comparator_list[wp_num].used && (wp_num < mips32->num_data_bpoints)) wp_num++; if (wp_num >= mips32->num_data_bpoints) { LOG_ERROR("Can not find free FP Comparator"); return ERROR_FAIL; } if (watchpoint->length != 4) { LOG_ERROR("Only watchpoints of length 4 are supported"); return ERROR_TARGET_UNALIGNED_ACCESS; } if (watchpoint->address % 4) { LOG_ERROR("Watchpoints address should be word aligned"); return ERROR_TARGET_UNALIGNED_ACCESS; } switch (watchpoint->rw) { case WPT_READ: enable &= ~EJTAG_DBCn_NOLB; break; case WPT_WRITE: enable &= ~EJTAG_DBCn_NOSB; break; case WPT_ACCESS: enable &= ~(EJTAG_DBCn_NOLB | EJTAG_DBCn_NOSB); break; default: LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); } watchpoint->set = wp_num + 1; comparator_list[wp_num].used = 1; comparator_list[wp_num].bp_value = watchpoint->address; /* EJTAG 2.0 uses 29bit DBA. First 3 bits are reserved. * There is as well no ASID register support. */ if (ejtag_info->ejtag_version == EJTAG_VERSION_20) comparator_list[wp_num].bp_value &= 0xFFFFFFF8; else target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbasid_offs, 0x00000000); target_write_u32(target, comparator_list[wp_num].reg_address, comparator_list[wp_num].bp_value); target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbm_offs, 0x00000000); target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbc_offs, enable); /* TODO: probably this value is ignored on 2.0 */ target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbv_offs, 0); LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", wp_num, comparator_list[wp_num].bp_value); return ERROR_OK; } static int mips_m4k_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct mips32_comparator *comparator_list = mips32->data_break_list; if (!watchpoint->set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } int wp_num = watchpoint->set - 1; if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints)) { LOG_DEBUG("Invalid FP Comparator number in watchpoint"); return ERROR_OK; } comparator_list[wp_num].used = 0; comparator_list[wp_num].bp_value = 0; target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbc_offs, 0); watchpoint->set = 0; return ERROR_OK; } static int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct mips32_common *mips32 = target_to_mips32(target); if (mips32->num_data_bpoints_avail < 1) { LOG_INFO("no hardware watchpoints available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } mips32->num_data_bpoints_avail--; mips_m4k_set_watchpoint(target, watchpoint); return ERROR_OK; } static int mips_m4k_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (watchpoint->set) mips_m4k_unset_watchpoint(target, watchpoint); mips32->num_data_bpoints_avail++; return ERROR_OK; } static void mips_m4k_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; /* set any pending watchpoints */ while (watchpoint) { if (watchpoint->set == 0) mips_m4k_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } } static int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /* since we don't know if buffer is aligned, we allocate new mem that is always aligned */ void *t = NULL; if (size > 1) { t = malloc(count * size * sizeof(uint8_t)); if (t == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } } else t = buffer; /* if noDMA off, use DMAACC mode for memory read */ int retval; if (ejtag_info->impcode & EJTAG_IMP_NODMA) retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t); else retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, t); /* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */ /* endianness, but byte array should represent target endianness */ if (ERROR_OK == retval) { switch (size) { case 4: target_buffer_set_u32_array(target, buffer, count, t); break; case 2: target_buffer_set_u16_array(target, buffer, count, t); break; } } if ((size > 1) && (t != NULL)) free(t); return retval; } static int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (size == 4 && count > 32) { int retval = mips_m4k_bulk_write_memory(target, address, count, buffer); if (retval == ERROR_OK) return ERROR_OK; LOG_WARNING("Falling back to non-bulk write"); } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /** correct endianess if we have word or hword access */ void *t = NULL; if (size > 1) { /* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */ /* endianness, but byte array represents target endianness */ t = malloc(count * size * sizeof(uint8_t)); if (t == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } switch (size) { case 4: target_buffer_get_u32_array(target, buffer, count, (uint32_t *)t); break; case 2: target_buffer_get_u16_array(target, buffer, count, (uint16_t *)t); break; } buffer = t; } /* if noDMA off, use DMAACC mode for memory write */ int retval; if (ejtag_info->impcode & EJTAG_IMP_NODMA) retval = mips32_pracc_write_mem(ejtag_info, address, size, count, buffer); else retval = mips32_dmaacc_write_mem(ejtag_info, address, size, count, buffer); if (t != NULL) free(t); if (ERROR_OK != retval) return retval; return ERROR_OK; } static int mips_m4k_init_target(struct command_context *cmd_ctx, struct target *target) { mips32_build_reg_cache(target); return ERROR_OK; } static int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_m4k, struct jtag_tap *tap) { struct mips32_common *mips32 = &mips_m4k->mips32; mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC; /* initialize mips4k specific info */ mips32_init_arch_info(target, mips32, tap); mips32->arch_info = mips_m4k; return ERROR_OK; } static int mips_m4k_target_create(struct target *target, Jim_Interp *interp) { struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common)); mips_m4k_init_arch_info(target, mips_m4k, target->tap); return ERROR_OK; } static int mips_m4k_examine(struct target *target) { int retval; struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; uint32_t idcode = 0; if (!target_was_examined(target)) { retval = mips_ejtag_get_idcode(ejtag_info, &idcode); if (retval != ERROR_OK) return retval; ejtag_info->idcode = idcode; if (((idcode >> 1) & 0x7FF) == 0x29) { /* we are using a pic32mx so select ejtag port * as it is not selected by default */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); LOG_DEBUG("PIC32MX Detected - using EJTAG Interface"); mips_m4k->is_pic32mx = true; } } /* init rest of ejtag interface */ retval = mips_ejtag_init(ejtag_info); if (retval != ERROR_OK) return retval; retval = mips32_examine(target); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct working_area *fast_data_area; int retval; int write_t = 1; LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count); /* check alignment */ if (address & 0x3u) return ERROR_TARGET_UNALIGNED_ACCESS; if (mips32->fast_data_area == NULL) { /* Get memory for block write handler * we preserve this area between calls and gain a speed increase * of about 3kb/sec when writing flash * this will be released/nulled by the system when the target is resumed or reset */ retval = target_alloc_working_area(target, MIPS32_FASTDATA_HANDLER_SIZE, &mips32->fast_data_area); if (retval != ERROR_OK) { LOG_ERROR("No working area available"); return retval; } /* reset fastadata state so the algo get reloaded */ ejtag_info->fast_access_save = -1; } fast_data_area = mips32->fast_data_area; if (address <= fast_data_area->address + fast_data_area->size && fast_data_area->address <= address + count) { LOG_ERROR("fast_data (0x%8.8" PRIx32 ") is within write area " "(0x%8.8" PRIx32 "-0x%8.8" PRIx32 ").", fast_data_area->address, address, address + count); LOG_ERROR("Change work-area-phys or load_image address!"); return ERROR_FAIL; } /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */ /* but byte array represents target endianness */ uint32_t *t = NULL; t = malloc(count * sizeof(uint32_t)); if (t == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } target_buffer_get_u32_array(target, buffer, count, t); retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, count, t); if (t != NULL) free(t); if (retval != ERROR_OK) LOG_ERROR("Fastdata access Failed"); return retval; } static int mips_m4k_verify_pointer(struct command_context *cmd_ctx, struct mips_m4k_common *mips_m4k) { if (mips_m4k->common_magic != MIPSM4K_COMMON_MAGIC) { command_print(cmd_ctx, "target is not an MIPS_M4K"); return ERROR_TARGET_INVALID; } return ERROR_OK; } COMMAND_HANDLER(mips_m4k_handle_cp0_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; retval = mips_m4k_verify_pointer(CMD_CTX, mips_m4k); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } /* two or more argument, access a single register/select (write if third argument is given) */ if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; else { uint32_t cp0_reg, cp0_sel; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); if (CMD_ARGC == 2) { uint32_t value; retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %" PRIi32, cp0_reg); return ERROR_OK; } command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, cp0_reg, cp0_sel, value); } else if (CMD_ARGC == 3) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32, cp0_reg, cp0_sel); return ERROR_OK; } command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, cp0_reg, cp0_sel, value); } } return ERROR_OK; } COMMAND_HANDLER(mips_m4k_handle_smp_off_command) { struct target *target = get_current_target(CMD_CTX); /* check target is an smp target */ struct target_list *head; struct target *curr; head = target->head; target->smp = 0; if (head != (struct target_list *)NULL) { while (head != (struct target_list *)NULL) { curr = head->target; curr->smp = 0; head = head->next; } /* fixes the target display to the debugger */ target->gdb_service->target = target; } return ERROR_OK; } COMMAND_HANDLER(mips_m4k_handle_smp_on_command) { struct target *target = get_current_target(CMD_CTX); struct target_list *head; struct target *curr; head = target->head; if (head != (struct target_list *)NULL) { target->smp = 1; while (head != (struct target_list *)NULL) { curr = head->target; curr->smp = 1; head = head->next; } } return ERROR_OK; } COMMAND_HANDLER(mips_m4k_handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); int retval = ERROR_OK; struct target_list *head; head = target->head; if (head != (struct target_list *)NULL) { if (CMD_ARGC == 1) { int coreid = 0; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); if (ERROR_OK != retval) return retval; target->gdb_service->core[1] = coreid; } command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] , target->gdb_service->core[1]); } return ERROR_OK; } COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= 20000000) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { ejtag_info->mode = 1; command_print(CMD_CTX, "running in fast queued mode"); } return ERROR_OK; } static const struct command_registration mips_m4k_exec_command_handlers[] = { { .name = "cp0", .handler = mips_m4k_handle_cp0_command, .mode = COMMAND_EXEC, .usage = "regnum [value]", .help = "display/modify cp0 register", }, { .name = "smp_off", .handler = mips_m4k_handle_smp_off_command, .mode = COMMAND_EXEC, .help = "Stop smp handling", .usage = "",}, { .name = "smp_on", .handler = mips_m4k_handle_smp_on_command, .mode = COMMAND_EXEC, .help = "Restart smp handling", .usage = "", }, { .name = "smp_gdb", .handler = mips_m4k_handle_smp_gdb_command, .mode = COMMAND_EXEC, .help = "display/fix current core played to gdb", .usage = "", }, { .name = "scan_delay", .handler = mips_m4k_handle_scan_delay_command, .mode = COMMAND_ANY, .help = "display/set scan delay in nano seconds", .usage = "[value]", }, COMMAND_REGISTRATION_DONE }; const struct command_registration mips_m4k_command_handlers[] = { { .chain = mips32_command_handlers, }, { .name = "mips_m4k", .mode = COMMAND_ANY, .help = "mips_m4k command group", .usage = "", .chain = mips_m4k_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type mips_m4k_target = { .name = "mips_m4k", .poll = mips_m4k_poll, .arch_state = mips32_arch_state, .halt = mips_m4k_halt, .resume = mips_m4k_resume, .step = mips_m4k_step, .assert_reset = mips_m4k_assert_reset, .deassert_reset = mips_m4k_deassert_reset, .get_gdb_reg_list = mips32_get_gdb_reg_list, .read_memory = mips_m4k_read_memory, .write_memory = mips_m4k_write_memory, .checksum_memory = mips32_checksum_memory, .blank_check_memory = mips32_blank_check_memory, .run_algorithm = mips32_run_algorithm, .add_breakpoint = mips_m4k_add_breakpoint, .remove_breakpoint = mips_m4k_remove_breakpoint, .add_watchpoint = mips_m4k_add_watchpoint, .remove_watchpoint = mips_m4k_remove_watchpoint, .commands = mips_m4k_command_handlers, .target_create = mips_m4k_target_create, .init_target = mips_m4k_init_target, .examine = mips_m4k_examine, }; openocd-0.9.0/src/target/mips_m4k.h0000644000175000017500000000437112315575361014056 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MIPS_M4K_H #define MIPS_M4K_H struct target; #define MIPSM4K_COMMON_MAGIC 0xB321B321 struct mips_m4k_common { uint32_t common_magic; bool is_pic32mx; struct mips32_common mips32; }; static inline struct mips_m4k_common * target_to_m4k(struct target *target) { return container_of(target->arch_info, struct mips_m4k_common, mips32); } extern const struct command_registration mips_m4k_command_handlers[]; #endif /*MIPS_M4K_H*/ openocd-0.9.0/src/target/oocd_trace.c0000644000175000017500000003052312315575361014426 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "etm.h" #include "oocd_trace.h" /* * This is "proof of concept" code, for prototype hardware: * https://lists.berlios.de/pipermail/openocd-development/2007-September/000336.html */ static int oocd_trace_read_reg(struct oocd_trace *oocd_trace, int reg, uint32_t *value) { size_t bytes_written, bytes_read, bytes_to_read; uint8_t cmd; cmd = 0x10 | (reg & 0x7); bytes_written = write(oocd_trace->tty_fd, &cmd, 1); if (bytes_written < 1) return ERROR_FAIL; bytes_to_read = 4; while (bytes_to_read > 0) { bytes_read = read(oocd_trace->tty_fd, ((uint8_t *)value) + 4 - bytes_to_read, bytes_to_read); bytes_to_read -= bytes_read; } LOG_DEBUG("reg #%i: 0x%8.8x", reg, *value); return ERROR_OK; } static int oocd_trace_write_reg(struct oocd_trace *oocd_trace, int reg, uint32_t value) { size_t bytes_written; uint8_t data[5]; data[0] = 0x18 | (reg & 0x7); data[1] = value & 0xff; data[2] = (value & 0xff00) >> 8; data[3] = (value & 0xff0000) >> 16; data[4] = (value & 0xff000000) >> 24; bytes_written = write(oocd_trace->tty_fd, data, 5); if (bytes_written < 5) return ERROR_FAIL; LOG_DEBUG("reg #%i: 0x%8.8x", reg, value); return ERROR_OK; } static int oocd_trace_read_memory(struct oocd_trace *oocd_trace, uint8_t *data, uint32_t address, uint32_t size) { size_t bytes_written, bytes_to_read; ssize_t bytes_read; uint8_t cmd; oocd_trace_write_reg(oocd_trace, OOCD_TRACE_ADDRESS, address); oocd_trace_write_reg(oocd_trace, OOCD_TRACE_SDRAM_COUNTER, size); cmd = 0x20; bytes_written = write(oocd_trace->tty_fd, &cmd, 1); if (bytes_written < 1) return ERROR_FAIL; bytes_to_read = size * 16; while (bytes_to_read > 0) { bytes_read = read(oocd_trace->tty_fd, ((uint8_t *)data) + (size * 16) - bytes_to_read, bytes_to_read); if (bytes_read < 0) LOG_DEBUG("read() returned %zi (%s)", bytes_read, strerror(errno)); else bytes_to_read -= bytes_read; } return ERROR_OK; } static int oocd_trace_init(struct etm_context *etm_ctx) { uint8_t trash[256]; struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv; size_t bytes_read; oocd_trace->tty_fd = open(oocd_trace->tty, O_RDWR | O_NOCTTY | O_NONBLOCK); if (oocd_trace->tty_fd < 0) { LOG_ERROR("can't open tty"); return ERROR_ETM_CAPTURE_INIT_FAILED; } /* clear input & output buffers, then switch to "blocking mode" */ tcflush(oocd_trace->tty_fd, TCOFLUSH); tcflush(oocd_trace->tty_fd, TCIFLUSH); fcntl(oocd_trace->tty_fd, F_SETFL, fcntl(oocd_trace->tty_fd, F_GETFL) & ~O_NONBLOCK); tcgetattr(oocd_trace->tty_fd, &oocd_trace->oldtio); /* save current port settings */ bzero(&oocd_trace->newtio, sizeof(oocd_trace->newtio)); oocd_trace->newtio.c_cflag = CS8 | CLOCAL | CREAD | B2500000; oocd_trace->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF; oocd_trace->newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ oocd_trace->newtio.c_lflag = 0; cfmakeraw(&oocd_trace->newtio); oocd_trace->newtio.c_cc[VTIME] = 1; /* inter-character timer used */ oocd_trace->newtio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */ tcflush(oocd_trace->tty_fd, TCIFLUSH); tcsetattr(oocd_trace->tty_fd, TCSANOW, &oocd_trace->newtio); /* occasionally one bogus character is left in the input buffer * read up any leftover characters to ensure communication is in sync */ do { bytes_read = read(oocd_trace->tty_fd, trash, sizeof(trash)); if (bytes_read) LOG_DEBUG("%zi bytes read", bytes_read); } while (bytes_read > 0); return ERROR_OK; } static trace_status_t oocd_trace_status(struct etm_context *etm_ctx) { struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv; uint32_t status; oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status); /* if tracing is currently idle, return this information */ if (etm_ctx->capture_status == TRACE_IDLE) return etm_ctx->capture_status; else if (etm_ctx->capture_status & TRACE_RUNNING) { /* check Full bit to identify an overflow */ if (status & 0x4) etm_ctx->capture_status |= TRACE_OVERFLOWED; /* check Triggered bit to identify trigger condition */ if (status & 0x2) etm_ctx->capture_status |= TRACE_TRIGGERED; if (status & 0x1) { etm_ctx->capture_status &= ~TRACE_RUNNING; etm_ctx->capture_status |= TRACE_COMPLETED; } } return etm_ctx->capture_status; } static int oocd_trace_read_trace(struct etm_context *etm_ctx) { struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv; uint32_t status, address; uint32_t first_frame = 0x0; uint32_t num_frames = 1048576; uint8_t *trace_data; uint32_t i; oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status); oocd_trace_read_reg(oocd_trace, OOCD_TRACE_ADDRESS, &address); /* check if we overflowed, and adjust first frame of the trace accordingly * if we didn't overflow, read only up to the frame that would be written next, * i.e. don't read invalid entries */ if (status & 0x4) first_frame = address; else num_frames = address; /* read data into temporary array for unpacking * one frame from OpenOCD + trace corresponds to 16 trace cycles */ trace_data = malloc(sizeof(uint8_t) * num_frames * 16); oocd_trace_read_memory(oocd_trace, trace_data, first_frame, num_frames); if (etm_ctx->trace_depth > 0) free(etm_ctx->trace_data); etm_ctx->trace_depth = num_frames * 16; etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth); for (i = 0; i < num_frames * 16; i++) { etm_ctx->trace_data[i].pipestat = (trace_data[i] & 0x7); etm_ctx->trace_data[i].packet = (trace_data[i] & 0x78) >> 3; etm_ctx->trace_data[i].flags = 0; if ((trace_data[i] & 0x80) >> 7) etm_ctx->trace_data[i].flags |= ETMV1_TRACESYNC_CYCLE; if (etm_ctx->trace_data[i].pipestat == STAT_TR) { etm_ctx->trace_data[i].pipestat = etm_ctx->trace_data[i].packet & 0x7; etm_ctx->trace_data[i].flags |= ETMV1_TRIGGER_CYCLE; } } free(trace_data); return ERROR_OK; } static int oocd_trace_start_capture(struct etm_context *etm_ctx) { struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv; uint32_t control = 0x1; /* 0x1: enabled */ uint32_t trigger_count; if (((etm_ctx->control & ETM_PORT_MODE_MASK) != ETM_PORT_NORMAL) || ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_4BIT)) { LOG_DEBUG("OpenOCD + trace only supports normal 4-bit ETM mode"); return ERROR_ETM_PORTMODE_NOT_SUPPORTED; } if ((etm_ctx->control & ETM_PORT_CLOCK_MASK) == ETM_PORT_HALF_CLOCK) control |= 0x2; /* half rate clock, capture at twice the clock rate */ /* OpenOCD + trace holds up to 16 million samples, * but trigger counts is set in multiples of 16 */ trigger_count = (1048576 * /* trigger_percent */ 50) / 100; /* capturing always starts at address zero */ oocd_trace_write_reg(oocd_trace, OOCD_TRACE_ADDRESS, 0x0); oocd_trace_write_reg(oocd_trace, OOCD_TRACE_TRIGGER_COUNTER, trigger_count); oocd_trace_write_reg(oocd_trace, OOCD_TRACE_CONTROL, control); /* we're starting a new trace, initialize capture status */ etm_ctx->capture_status = TRACE_RUNNING; return ERROR_OK; } static int oocd_trace_stop_capture(struct etm_context *etm_ctx) { struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv; /* trace stopped, just clear running flag, but preserve others */ etm_ctx->capture_status &= ~TRACE_RUNNING; oocd_trace_write_reg(oocd_trace, OOCD_TRACE_CONTROL, 0x0); return ERROR_OK; } COMMAND_HANDLER(handle_oocd_trace_config_command) { struct target *target; struct arm *arm; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (arm->etm) { struct oocd_trace *oocd_trace = malloc(sizeof(struct oocd_trace)); arm->etm->capture_driver_priv = oocd_trace; oocd_trace->etm_ctx = arm->etm; /* copy name of TTY device used to communicate with OpenOCD + trace */ oocd_trace->tty = strndup(CMD_ARGV[1], 256); } else LOG_ERROR("target has no ETM defined, OpenOCD + trace left unconfigured"); return ERROR_OK; } COMMAND_HANDLER(handle_oocd_trace_status_command) { struct target *target; struct arm *arm; struct oocd_trace *oocd_trace; uint32_t status; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (!arm->etm) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) { command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'"); return ERROR_FAIL; } oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv; oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status); if (status & 0x8) command_print(CMD_CTX, "trace clock locked"); else command_print(CMD_CTX, "no trace clock"); return ERROR_OK; } COMMAND_HANDLER(handle_oocd_trace_resync_command) { struct target *target; struct arm *arm; struct oocd_trace *oocd_trace; size_t bytes_written; uint8_t cmd_array[1]; target = get_current_target(CMD_CTX); arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (!arm->etm) { command_print(CMD_CTX, "current target doesn't have an ETM configured"); return ERROR_FAIL; } if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) { command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'"); return ERROR_FAIL; } oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv; cmd_array[0] = 0xf0; bytes_written = write(oocd_trace->tty_fd, cmd_array, 1); if (bytes_written < 1) return ERROR_FAIL; command_print(CMD_CTX, "requesting traceclock resync"); LOG_DEBUG("resyncing traceclk pll"); return ERROR_OK; } static const struct command_registration oocd_trace_all_command_handlers[] = { { .name = "config", .handler = handle_oocd_trace_config_command, .mode = COMMAND_CONFIG, .usage = " ", }, { .name = "status", .handler = handle_oocd_trace_status_command, .mode = COMMAND_EXEC, .usage = "", .help = "display OpenOCD + trace status", }, { .name = "resync", .handler = handle_oocd_trace_resync_command, .mode = COMMAND_EXEC, .usage = "", .help = "resync OpenOCD + trace capture clock", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration oocd_trace_command_handlers[] = { { .name = "oocd_trace", .mode = COMMAND_ANY, .help = "OpenOCD trace capture driver command group", .usage = "", .chain = oocd_trace_all_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct etm_capture_driver oocd_trace_capture_driver = { .name = "oocd_trace", .commands = oocd_trace_command_handlers, .init = oocd_trace_init, .status = oocd_trace_status, .start_capture = oocd_trace_start_capture, .stop_capture = oocd_trace_stop_capture, .read_trace = oocd_trace_read_trace, }; openocd-0.9.0/src/target/oocd_trace.h0000644000175000017500000000412312315575361014430 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OOCD_TRACE_H #define OOCD_TRACE_H #include /* registers */ enum { OOCD_TRACE_ID = 0x7, OOCD_TRACE_ADDRESS = 0x0, OOCD_TRACE_TRIGGER_COUNTER = 0x01, OOCD_TRACE_CONTROL = 0x2, OOCD_TRACE_STATUS = 0x3, OOCD_TRACE_SDRAM_COUNTER = 0x4, }; /* commands */ enum { OOCD_TRACE_NOP = 0x0, OOCD_TRACE_READ_REG = 0x10, OOCD_TRACE_WRITE_REG = 0x18, OOCD_TRACE_READ_RAM = 0x20, /* OOCD_TRACE_WRITE_RAM = 0x28, */ OOCD_TRACE_RESYNC = 0xf0, }; struct oocd_trace { struct etm_context *etm_ctx; char *tty; int tty_fd; struct termios oldtio, newtio; }; extern struct etm_capture_driver oocd_trace_capture_driver; #endif /* OOCD_TRACE_TRACE_H */ openocd-0.9.0/src/target/mips_ejtag.c0000644000175000017500000003306312516456304014446 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2009 by David N. Claffey * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mips32.h" #include "mips_ejtag.h" #include "mips32_dmaacc.h" void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr) { struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) { struct scan_field field; uint8_t t[4]; field.num_bits = tap->ir_length; field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); } } int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode) { struct scan_field field; uint8_t r[4]; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE); field.num_bits = 32; field.out_value = NULL; field.in_value = r; jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); int retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } *idcode = buf_get_u32(field.in_value, 0, 32); return ERROR_OK; } static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode) { struct scan_field field; uint8_t r[4]; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE); field.num_bits = 32; field.out_value = NULL; field.in_value = r; jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); int retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } *impcode = buf_get_u32(field.in_value, 0, 32); return ERROR_OK; } void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf) { assert(ejtag_info->tap != NULL); struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; uint8_t out_scan[12]; /* processor access "all" register 96 bit */ field.num_bits = 96; field.out_value = out_scan; buf_set_u32(out_scan, 0, 32, ctrl); buf_set_u32(out_scan + 4, 0, 32, data); buf_set_u32(out_scan + 8, 0, 32, 0); field.in_value = in_scan_buf; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); keep_alive(); } int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) { struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); struct scan_field field; uint8_t t[4], r[4]; int retval; field.num_bits = 32; field.out_value = t; buf_set_u32(t, 0, field.num_bits, *data); field.in_value = r; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } *data = buf_get_u32(field.in_value, 0, 32); keep_alive(); return ERROR_OK; } void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data) { uint8_t t[4]; struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); struct scan_field field; field.num_bits = 32; field.out_value = t; buf_set_u32(t, 0, field.num_bits, data); field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data) { struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); struct scan_field field; uint8_t t[4] = {0, 0, 0, 0}, r[4]; int retval; field.num_bits = 8; field.out_value = t; buf_set_u32(t, 0, field.num_bits, *data); field.in_value = r; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } *data = buf_get_u32(field.in_value, 0, 32); return ERROR_OK; } void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) { struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); struct scan_field field; field.num_bits = 8; field.out_value = &data; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } /* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { struct pracc_queue_info ctx = {.max_code = 7}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ if (!enable_step) pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */ pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); exit: pracc_queue_free(&ctx); return ctx.retval; } /* * Disable memory protection for 0xFF20.0000–0xFF3F.FFFF * It is needed by EJTAG 1.5-2.0, especially for BMIPS CPUs * For example bcm7401 and others. At leas on some * CPUs, DebugMode wont start if this bit is not removed. */ static int disable_dcr_mp(struct mips_ejtag *ejtag_info) { uint32_t dcr; int retval; retval = mips32_dmaacc_read_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); if (retval != ERROR_OK) goto error; dcr &= ~EJTAG_DCR_MP; retval = mips32_dmaacc_write_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); if (retval != ERROR_OK) goto error; return ERROR_OK; error: LOG_ERROR("Failed to remove DCR MPbit!"); return retval; } int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info) { uint32_t ejtag_ctrl; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); if (ejtag_info->ejtag_version == EJTAG_VERSION_20) { if (disable_dcr_mp(ejtag_info) != ERROR_OK) goto error; } /* set debug break bit */ ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* break bit will be cleared by hardware */ ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl); if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0) goto error; return ERROR_OK; error: LOG_ERROR("Failed to enter Debug Mode!"); return ERROR_FAIL; } int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { uint32_t pracc_list[] = {MIPS32_DRET, 0}; struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); return ctx.retval; } /* mips_ejtag_init_mmr - asign Memory-Mapped Registers depending * on EJTAG version. */ static void mips_ejtag_init_mmr(struct mips_ejtag *ejtag_info) { if (ejtag_info->ejtag_version == EJTAG_VERSION_20) { ejtag_info->ejtag_ibs_addr = EJTAG_V20_IBS; ejtag_info->ejtag_iba0_addr = EJTAG_V20_IBA0; ejtag_info->ejtag_ibc_offs = EJTAG_V20_IBC_OFFS; ejtag_info->ejtag_ibm_offs = EJTAG_V20_IBM_OFFS; ejtag_info->ejtag_dbs_addr = EJTAG_V20_DBS; ejtag_info->ejtag_dba0_addr = EJTAG_V20_DBA0; ejtag_info->ejtag_dbc_offs = EJTAG_V20_DBC_OFFS; ejtag_info->ejtag_dbm_offs = EJTAG_V20_DBM_OFFS; ejtag_info->ejtag_dbv_offs = EJTAG_V20_DBV_OFFS; ejtag_info->ejtag_iba_step_size = EJTAG_V20_IBAn_STEP; ejtag_info->ejtag_dba_step_size = EJTAG_V20_DBAn_STEP; } else { ejtag_info->ejtag_ibs_addr = EJTAG_V25_IBS; ejtag_info->ejtag_iba0_addr = EJTAG_V25_IBA0; ejtag_info->ejtag_ibm_offs = EJTAG_V25_IBM_OFFS; ejtag_info->ejtag_ibasid_offs = EJTAG_V25_IBASID_OFFS; ejtag_info->ejtag_ibc_offs = EJTAG_V25_IBC_OFFS; ejtag_info->ejtag_dbs_addr = EJTAG_V25_DBS; ejtag_info->ejtag_dba0_addr = EJTAG_V25_DBA0; ejtag_info->ejtag_dbm_offs = EJTAG_V25_DBM_OFFS; ejtag_info->ejtag_dbasid_offs = EJTAG_V25_DBASID_OFFS; ejtag_info->ejtag_dbc_offs = EJTAG_V25_DBC_OFFS; ejtag_info->ejtag_dbv_offs = EJTAG_V25_DBV_OFFS; ejtag_info->ejtag_iba_step_size = EJTAG_V25_IBAn_STEP; ejtag_info->ejtag_dba_step_size = EJTAG_V25_DBAn_STEP; } } static void ejtag_v20_print_imp(struct mips_ejtag *ejtag_info) { LOG_DEBUG("EJTAG v2.0: features:%s%s%s%s%s%s%s%s", EJTAG_IMP_HAS(EJTAG_V20_IMP_SDBBP) ? " SDBBP_SPECIAL2" : " SDBBP", EJTAG_IMP_HAS(EJTAG_V20_IMP_EADDR_NO32BIT) ? " EADDR>32bit" : " EADDR=32bit", EJTAG_IMP_HAS(EJTAG_V20_IMP_COMPLEX_BREAK) ? " COMPLEX_BREAK" : "", EJTAG_IMP_HAS(EJTAG_V20_IMP_DCACHE_COH) ? " DCACHE_COH" : " DCACHE_NOT_COH", EJTAG_IMP_HAS(EJTAG_V20_IMP_ICACHE_COH) ? " ICACHE_COH" : " ICACHE_NOT_COH", EJTAG_IMP_HAS(EJTAG_V20_IMP_NOPB) ? " noPB" : " PB", EJTAG_IMP_HAS(EJTAG_V20_IMP_NODB) ? " noDB" : " DB", EJTAG_IMP_HAS(EJTAG_V20_IMP_NOIB) ? " noIB" : " IB"); LOG_DEBUG("EJTAG v2.0: Break Channels: %" PRIu8, (uint8_t)((ejtag_info->impcode >> EJTAG_V20_IMP_BCHANNELS_SHIFT) & EJTAG_V20_IMP_BCHANNELS_MASK)); } static void ejtag_v26_print_imp(struct mips_ejtag *ejtag_info) { LOG_DEBUG("EJTAG v2.6: features:%s%s", EJTAG_IMP_HAS(EJTAG_V26_IMP_R3K) ? " R3k" : " R4k", EJTAG_IMP_HAS(EJTAG_V26_IMP_DINT) ? " DINT" : ""); } static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) { LOG_DEBUG("EJTAG main: features:%s%s%s%s%s", EJTAG_IMP_HAS(EJTAG_IMP_ASID8) ? " ASID_8" : "", EJTAG_IMP_HAS(EJTAG_IMP_ASID6) ? " ASID_6" : "", EJTAG_IMP_HAS(EJTAG_IMP_MIPS16) ? " MIPS16" : "", EJTAG_IMP_HAS(EJTAG_IMP_NODMA) ? " noDMA" : " DMA", EJTAG_IMP_HAS(EJTAG_DCR_MIPS64) ? " MIPS64" : " MIPS32"); switch (ejtag_info->ejtag_version) { case EJTAG_VERSION_20: ejtag_v20_print_imp(ejtag_info); break; case EJTAG_VERSION_25: case EJTAG_VERSION_26: case EJTAG_VERSION_31: case EJTAG_VERSION_41: case EJTAG_VERSION_51: ejtag_v26_print_imp(ejtag_info); break; default: break; } } int mips_ejtag_init(struct mips_ejtag *ejtag_info) { int retval; retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode); if (retval != ERROR_OK) return retval; LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode); /* get ejtag version */ ejtag_info->ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); switch (ejtag_info->ejtag_version) { case EJTAG_VERSION_20: LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected"); break; case EJTAG_VERSION_25: LOG_DEBUG("EJTAG: Version 2.5 Detected"); break; case EJTAG_VERSION_26: LOG_DEBUG("EJTAG: Version 2.6 Detected"); break; case EJTAG_VERSION_31: LOG_DEBUG("EJTAG: Version 3.1 Detected"); break; case EJTAG_VERSION_41: LOG_DEBUG("EJTAG: Version 4.1 Detected"); break; case EJTAG_VERSION_51: LOG_DEBUG("EJTAG: Version 5.1 Detected"); break; default: LOG_DEBUG("EJTAG: Unknown Version Detected"); break; } ejtag_main_print_imp(ejtag_info); if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0) { LOG_DEBUG("EJTAG: DMA Access Mode detected. Disabling to " "workaround current broken code."); ejtag_info->impcode |= EJTAG_IMP_NODMA; } ejtag_info->ejtag_ctrl = EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN; if (ejtag_info->ejtag_version != EJTAG_VERSION_20) ejtag_info->ejtag_ctrl |= EJTAG_CTRL_ROCC | EJTAG_CTRL_SETDEV; ejtag_info->fast_access_save = -1; mips_ejtag_init_mmr(ejtag_info); return ERROR_OK; } int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data) { struct jtag_tap *tap; tap = ejtag_info->tap; assert(tap != NULL); struct scan_field fields[2]; uint8_t spracc = 0; uint8_t t[4] = {0, 0, 0, 0}; /* fastdata 1-bit register */ fields[0].num_bits = 1; fields[0].out_value = &spracc; fields[0].in_value = NULL; /* processor access data register 32 bit */ fields[1].num_bits = 32; fields[1].out_value = t; if (write_t) { fields[1].in_value = NULL; buf_set_u32(t, 0, 32, *data); } else fields[1].in_value = (uint8_t *) data; jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); if (!write_t && data) jtag_add_callback(mips_le_to_h_u32, (jtag_callback_data_t) data); keep_alive(); return ERROR_OK; } openocd-0.9.0/src/target/mips_ejtag.h0000644000175000017500000002211012516456304014442 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MIPS_EJTAG #define MIPS_EJTAG #include /* tap instructions */ #define EJTAG_INST_IDCODE 0x01 #define EJTAG_INST_IMPCODE 0x03 #define EJTAG_INST_ADDRESS 0x08 #define EJTAG_INST_DATA 0x09 #define EJTAG_INST_CONTROL 0x0A #define EJTAG_INST_ALL 0x0B #define EJTAG_INST_EJTAGBOOT 0x0C #define EJTAG_INST_NORMALBOOT 0x0D #define EJTAG_INST_FASTDATA 0x0E #define EJTAG_INST_TCBCONTROLA 0x10 #define EJTAG_INST_TCBCONTROLB 0x11 #define EJTAG_INST_TCBDATA 0x12 #define EJTAG_INST_BYPASS 0xFF /* microchip PIC32MX specific instructions */ #define MTAP_SW_MTAP 0x04 #define MTAP_SW_ETAP 0x05 #define MTAP_COMMAND 0x07 /* microchip specific cmds */ #define MCHP_ASERT_RST 0xd1 #define MCHP_DE_ASSERT_RST 0xd0 #define MCHP_ERASE 0xfc #define MCHP_STATUS 0x00 /* ejtag control register bits ECR */ #define EJTAG_CTRL_TOF (1 << 1) #define EJTAG_CTRL_TIF (1 << 2) #define EJTAG_CTRL_BRKST (1 << 3) #define EJTAG_CTRL_DLOCK (1 << 5) #define EJTAG_CTRL_DRWN (1 << 9) #define EJTAG_CTRL_DERR (1 << 10) #define EJTAG_CTRL_DSTRT (1 << 11) #define EJTAG_CTRL_JTAGBRK (1 << 12) #define EJTAG_CTRL_SETDEV (1 << 14) #define EJTAG_CTRL_PROBEN (1 << 15) #define EJTAG_CTRL_PRRST (1 << 16) #define EJTAG_CTRL_DMAACC (1 << 17) #define EJTAG_CTRL_PRACC (1 << 18) #define EJTAG_CTRL_PRNW (1 << 19) #define EJTAG_CTRL_PERRST (1 << 20) #define EJTAG_CTRL_SYNC (1 << 23) #define EJTAG_CTRL_DNM (1 << 28) #define EJTAG_CTRL_ROCC (1 << 31) /* Debug Register (CP0 Register 23, Select 0) */ #define EJTAG_DEBUG_DSS (1 << 0) #define EJTAG_DEBUG_DBP (1 << 1) #define EJTAG_DEBUG_DDBL (1 << 2) #define EJTAG_DEBUG_DDBS (1 << 3) #define EJTAG_DEBUG_DIB (1 << 4) #define EJTAG_DEBUG_DINT (1 << 5) #define EJTAG_DEBUG_OFFLINE (1 << 7) #define EJTAG_DEBUG_SST (1 << 8) #define EJTAG_DEBUG_NOSST (1 << 9) #define EJTAG_DEBUG_DDBLIMPR (1 << 18) #define EJTAG_DEBUG_DDBSIMPR (1 << 19) #define EJTAG_DEBUG_IEXI (1 << 20) #define EJTAG_DEBUG_DBUSEP (1 << 21) #define EJTAG_DEBUG_CACHEEP (1 << 22) #define EJTAG_DEBUG_MCHECKP (1 << 23) #define EJTAG_DEBUG_IBUSEP (1 << 24) #define EJTAG_DEBUG_COUNTDM (1 << 25) #define EJTAG_DEBUG_HALT (1 << 26) #define EJTAG_DEBUG_DOZE (1 << 27) #define EJTAG_DEBUG_LSNM (1 << 28) #define EJTAG_DEBUG_NODCR (1 << 29) #define EJTAG_DEBUG_DM (1 << 30) #define EJTAG_DEBUG_DBD (1 << 31) /* implementation MIPS register bits. * Bits marked with V20 or v2.0 mean that, this registers supported only * by EJTAG v2.0. Bits marked with Lexra or BMIPS are different from the * official EJATG. * NOTE: Lexra or BMIPS use EJTAG v2.0 */ #define EJTAG_IMP_HAS(x) (ejtag_info->impcode & (x)) /* v2.0(Lexra) 29 - 1’b1 - Lexra Internal Trace Buffer implemented. This bit * overlaps with version bit of MIPS EJTAG specification. */ #define EJTAG_V26_IMP_R3K (1 << 28) /* v2.0 - 24:25 - 2’b00- No profiling support */ #define EJTAG_V26_IMP_DINT (1 << 24) #define EJTAG_V20_IMP_SDBBP (1 << 23) /* 1’b1 - sdbbp is Special2 Opcode */ #define EJTAG_IMP_ASID8 (1 << 22) #define EJTAG_IMP_ASID6 (1 << 21) #define EJTAG_V20_IMP_COMPLEX_BREAK (1 << 20) /* Complex Breaks supported*/ #define EJTAG_V20_IMP_EADDR_NO32BIT (1 << 19) /* EJTAG_ADDR > 32 bits wide */ #define EJTAG_V20_IMP_DCACHE_COH (1 << 18) /* DCache does keep DMA coherent */ #define EJTAG_V20_IMP_ICACHE_COH (1 << 17) /* DCache does keep DMA coherent */ #define EJTAG_IMP_MIPS16 (1 << 16) #define EJTAG_IMP_NODMA (1 << 14) /* v2.0 - 11:13 external PC trace. Trace PC Width. */ /* v2.0 - 8:10 external PC trace. PCST Width and DCLK Division Factor */ #define EJTAG_V20_IMP_NOPB (1 << 7) /* no processor breaks */ #define EJTAG_V20_IMP_NODB (1 << 6) /* no data breaks */ #define EJTAG_V20_IMP_NOIB (1 << 5) /* no instruction breaks implemented */ /* v2.0 - 1:4 Number of Break Channels. */ #define EJTAG_V20_IMP_BCHANNELS_MASK 0xf #define EJTAG_V20_IMP_BCHANNELS_SHIFT 1 #define EJTAG_DCR_MIPS64 (1 << 0) /* Debug Control Register DCR */ #define EJTAG_DCR 0xFF300000 #define EJTAG_DCR_ENM (1 << 29) #define EJTAG_DCR_DB (1 << 17) #define EJTAG_DCR_IB (1 << 16) #define EJTAG_DCR_INTE (1 << 4) #define EJTAG_DCR_MP (1 << 2) /* breakpoint support */ /* EJTAG_V20_* was tested on Broadcom BCM7401 * and may or will differ with other hardware. For example EZ4021-FC. */ #define EJTAG_V20_IBS 0xFF300004 #define EJTAG_V20_IBA0 0xFF300100 #define EJTAG_V20_IBC_OFFS 0x4 /* IBC Offset */ #define EJTAG_V20_IBM_OFFS 0x8 #define EJTAG_V20_IBAn_STEP 0x10 /* Offset for next channel */ #define EJTAG_V20_DBS 0xFF30008 #define EJTAG_V20_DBA0 0xFF300200 #define EJTAG_V20_DBC_OFFS 0x4 #define EJTAG_V20_DBM_OFFS 0x8 #define EJTAG_V20_DBV_OFFS 0xc #define EJTAG_V20_DBAn_STEP 0x10 #define EJTAG_V25_IBS 0xFF301000 #define EJTAG_V25_IBA0 0xFF301100 #define EJTAG_V25_IBM_OFFS 0x8 #define EJTAG_V25_IBASID_OFFS 0x10 #define EJTAG_V25_IBC_OFFS 0x18 #define EJTAG_V25_IBAn_STEP 0x100 #define EJTAG_V25_DBS 0xFF302000 #define EJTAG_V25_DBA0 0xFF302100 #define EJTAG_V25_DBM_OFFS 0x8 #define EJTAG_V25_DBASID_OFFS 0x10 #define EJTAG_V25_DBC_OFFS 0x18 #define EJTAG_V25_DBV_OFFS 0x20 #define EJTAG_V25_DBAn_STEP 0x100 #define EJTAG_DBCn_NOSB (1 << 13) #define EJTAG_DBCn_NOLB (1 << 12) #define EJTAG_DBCn_BLM_MASK 0xff #define EJTAG_DBCn_BLM_SHIFT 4 #define EJTAG_DBCn_BE (1 << 0) #define EJTAG_VERSION_20 0 #define EJTAG_VERSION_25 1 #define EJTAG_VERSION_26 2 #define EJTAG_VERSION_31 3 #define EJTAG_VERSION_41 4 #define EJTAG_VERSION_51 5 struct mips_ejtag { struct jtag_tap *tap; uint32_t impcode; uint32_t idcode; uint32_t ejtag_ctrl; int fast_access_save; uint32_t reg8; uint32_t reg9; unsigned scan_delay; int mode; uint32_t pa_ctrl; uint32_t pa_addr; unsigned int ejtag_version; /* Memory-Mapped Registers. This addresses are not same on different * EJTAG versions. */ uint32_t debug_caps; uint32_t ejtag_ibs_addr; /* Instruction Address Break Status */ uint32_t ejtag_iba0_addr; /* IAB channel 0 */ uint32_t ejtag_ibc_offs; /* IAB Control offset */ uint32_t ejtag_ibm_offs; /* IAB Mask offset */ uint32_t ejtag_ibasid_offs; /* IAB ASID (4Kc) */ uint32_t ejtag_dbs_addr; /* Data Address Break Status Register */ uint32_t ejtag_dba0_addr; /* DAB channel 0 */ uint32_t ejtag_dbc_offs; /* DAB Control offset */ uint32_t ejtag_dbm_offs; /* DAB Mask offset */ uint32_t ejtag_dbv_offs; /* DAB Value offset */ uint32_t ejtag_dbasid_offs; /* DAB ASID (4Kc) */ uint32_t ejtag_iba_step_size; uint32_t ejtag_dba_step_size; /* size of step till next *DBAn register. */ }; void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr); int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode); void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf); void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data); int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data); void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data); int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data); int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data); int mips_ejtag_init(struct mips_ejtag *ejtag_info); int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step); static inline void mips_le_to_h_u32(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; *((uint32_t *)arg) = le_to_h_u32(in); } #endif /* MIPS_EJTAG */ openocd-0.9.0/src/target/target_request.c0000644000175000017500000002077712315575361015374 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "target.h" #include "target_request.h" #include "target_type.h" #include "trace.h" static bool got_message; bool target_got_message(void) { bool t = got_message; got_message = false; return t; } static int charmsg_mode; static int target_asciimsg(struct target *target, uint32_t length) { char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4); struct debug_msg_receiver *c = target->dbgmsg; target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg); msg[length] = 0; LOG_DEBUG("%s", msg); while (c) { command_print(c->cmd_ctx, "%s", msg); c = c->next; } return ERROR_OK; } static int target_charmsg(struct target *target, uint8_t msg) { LOG_USER_N("%c", msg); return ERROR_OK; } static int target_hexmsg(struct target *target, int size, uint32_t length) { uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4); char line[128]; int line_len; struct debug_msg_receiver *c = target->dbgmsg; uint32_t i; LOG_DEBUG("size: %i, length: %i", (int)size, (int)length); target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data); line_len = 0; for (i = 0; i < length; i++) { switch (size) { case 4: line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i))); break; case 2: line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i))); break; case 1: line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]); break; } if ((i%8 == 7) || (i == length - 1)) { LOG_DEBUG("%s", line); while (c) { command_print(c->cmd_ctx, "%s", line); c = c->next; } c = target->dbgmsg; line_len = 0; } } free(data); return ERROR_OK; } /* handle requests from the target received by a target specific * side-band channel (e.g. ARM7/9 DCC) */ int target_request(struct target *target, uint32_t request) { target_req_cmd_t target_req_cmd = request & 0xff; assert(target->type->target_request_data); /* Record that we got a target message for back-off algorithm */ got_message = true; if (charmsg_mode) { target_charmsg(target, target_req_cmd); return ERROR_OK; } switch (target_req_cmd) { case TARGET_REQ_TRACEMSG: trace_point(target, (request & 0xffffff00) >> 8); break; case TARGET_REQ_DEBUGMSG: if (((request & 0xff00) >> 8) == 0) target_asciimsg(target, (request & 0xffff0000) >> 16); else target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16); break; case TARGET_REQ_DEBUGCHAR: target_charmsg(target, (request & 0x00ff0000) >> 16); break; /* case TARGET_REQ_SEMIHOSTING: * break; */ default: LOG_ERROR("unknown target request: %2.2x", target_req_cmd); break; } return ERROR_OK; } static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target) { struct debug_msg_receiver **p = &target->dbgmsg; if (target == NULL) return ERROR_COMMAND_SYNTAX_ERROR; /* see if there's already a list */ if (*p) { /* find end of linked list */ while ((*p)->next) p = &((*p)->next); p = &((*p)->next); } /* add new debug message receiver */ (*p) = malloc(sizeof(struct debug_msg_receiver)); (*p)->cmd_ctx = cmd_ctx; (*p)->next = NULL; /* enable callback */ target->dbg_msg_enabled = 1; return ERROR_OK; } static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target) { int do_all_targets = 0; /* if no target has been specified search all of them */ if (target == NULL) { /* if no targets haven been specified */ if (all_targets == NULL) return NULL; target = all_targets; do_all_targets = 1; } /* so we target != null */ struct debug_msg_receiver **p = &target->dbgmsg; do { while (*p) { if ((*p)->cmd_ctx == cmd_ctx) return *p; p = &((*p)->next); } target = target->next; } while (target && do_all_targets); return NULL; } int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target) { struct debug_msg_receiver **p; struct debug_msg_receiver *c; int do_all_targets = 0; /* if no target has been specified search all of them */ if (target == NULL) { /* if no targets haven been specified */ if (all_targets == NULL) return ERROR_OK; target = all_targets; do_all_targets = 1; } do { p = &target->dbgmsg; c = *p; while (c) { struct debug_msg_receiver *next = c->next; if (c->cmd_ctx == cmd_ctx) { *p = next; free(c); if (*p == NULL) { /* disable callback */ target->dbg_msg_enabled = 0; } return ERROR_OK; } else p = &(c->next); c = next; } target = target->next; } while (target && do_all_targets); return ERROR_OK; } COMMAND_HANDLER(handle_target_request_debugmsgs_command) { struct target *target = get_current_target(CMD_CTX); int receiving = 0; if (target->type->target_request_data == NULL) { LOG_ERROR("Target %s does not support target requests", target_name(target)); return ERROR_OK; } /* see if reciever is already registered */ if (find_debug_msg_receiver(CMD_CTX, target) != NULL) receiving = 1; if (CMD_ARGC > 0) { if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) { /* don't register if this command context is already receiving */ if (!receiving) { receiving = 1; add_debug_msg_receiver(CMD_CTX, target); } charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg"); } else if (!strcmp(CMD_ARGV[0], "disable")) { /* no need to delete a receiver if none is registered */ if (receiving) { receiving = 0; delete_debug_msg_receiver(CMD_CTX, target); } } else return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "receiving debug messages from current target %s", (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled"); return ERROR_OK; } static const struct command_registration target_req_exec_command_handlers[] = { { .name = "debugmsgs", .handler = handle_target_request_debugmsgs_command, .mode = COMMAND_EXEC, .help = "display and/or modify reception of debug messages from target", .usage = "['enable'|'charmsg'|'disable']", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration target_req_command_handlers[] = { { .name = "target_request", .mode = COMMAND_ANY, .help = "target request command group", .usage = "", .chain = target_req_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; int target_request_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, target_req_command_handlers); } openocd-0.9.0/src/target/target_request.h0000644000175000017500000000521512315575361015367 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TARGET_REQUEST_H #define TARGET_REQUEST_H struct target; struct command_context; typedef enum target_req_cmd { TARGET_REQ_TRACEMSG, TARGET_REQ_DEBUGMSG, TARGET_REQ_DEBUGCHAR, /* TARGET_REQ_SEMIHOSTING, */ } target_req_cmd_t; struct debug_msg_receiver { struct command_context *cmd_ctx; struct debug_msg_receiver *next; }; int target_request(struct target *target, uint32_t request); int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target); int target_request_register_commands(struct command_context *cmd_ctx); /** * Read and clear the flag as to whether we got a message. * * This is used to implement the back-off algorithm on * sleeping in idle mode. */ bool target_got_message(void); #endif /* TARGET_REQUEST_H */ openocd-0.9.0/src/target/arm926ejs.c0000644000175000017500000006051212315575361014047 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008,2009 by Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm926ejs.h" #include #include "target_type.h" #include "register.h" #include "arm_opcodes.h" /* * The ARM926 is built around the ARM9EJ-S core, and most JTAG docs * are in the ARM9EJ-S Technical Reference Manual (ARM DDI 0222B) not * the ARM926 manual (ARM DDI 0198E). The scan chains are: * * 1 ... core debugging * 2 ... EmbeddedICE * 3 ... external boundary scan (SoC-specific, unused here) * 6 ... ETM * 15 ... coprocessor 15 */ #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif #define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0)) static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm); struct scan_field fields[4]; uint8_t address_buf[2] = {0, 0}; uint8_t nr_w_buf = 0; uint8_t access_t = 1; buf_set_u32(address_buf, 0, 14, address); retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = (uint8_t *)value; fields[1].num_bits = 1; fields[1].out_value = &access_t; fields[1].in_value = &access_t; fields[2].num_bits = 14; fields[2].out_value = address_buf; fields[2].in_value = NULL; fields[3].num_bits = 1; fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); long long then = timeval_ms(); for (;;) { /* rescan with NOP, to wait for the access to complete */ access_t = 0; nr_w_buf = 0; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (buf_get_u32(&access_t, 0, 1) == 1) break; /* 10ms timeout */ if ((timeval_ms()-then) > 10) { LOG_ERROR("cp15 read operation timed out"); return ERROR_FAIL; } } #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", address, *value); #endif retval = arm_jtag_set_instr(jtag_info, 0xc, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int arm926ejs_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } return arm926ejs_cp15_read(target, op1, op2, CRn, CRm, value); } static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm); struct scan_field fields[4]; uint8_t value_buf[4]; uint8_t address_buf[2] = {0, 0}; uint8_t nr_w_buf = 1; uint8_t access_t = 1; buf_set_u32(address_buf, 0, 14, address); buf_set_u32(value_buf, 0, 32, value); retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = value_buf; fields[0].in_value = NULL; fields[1].num_bits = 1; fields[1].out_value = &access_t; fields[1].in_value = &access_t; fields[2].num_bits = 14; fields[2].out_value = address_buf; fields[2].in_value = NULL; fields[3].num_bits = 1; fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); long long then = timeval_ms(); for (;;) { /* rescan with NOP, to wait for the access to complete */ access_t = 0; nr_w_buf = 0; jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (buf_get_u32(&access_t, 0, 1) == 1) break; /* 10ms timeout */ if ((timeval_ms()-then) > 10) { LOG_ERROR("cp15 write operation timed out"); return ERROR_FAIL; } } #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", address, value); #endif retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int arm926ejs_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { if (cpnum != 15) { LOG_ERROR("Only cp15 is supported"); return ERROR_FAIL; } return arm926ejs_cp15_write(target, op1, op2, CRn, CRm, value); } static int arm926ejs_examine_debug_reason(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; int debug_reason; int retval; embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* Method-Of-Entry (MOE) field */ debug_reason = buf_get_u32(dbg_stat->value, 6, 4); switch (debug_reason) { case 0: LOG_DEBUG("no *NEW* debug entry (?missed one?)"); /* ... since last restart or debug reset ... */ target->debug_reason = DBG_REASON_DBGRQ; break; case 1: LOG_DEBUG("breakpoint from EICE unit 0"); target->debug_reason = DBG_REASON_BREAKPOINT; break; case 2: LOG_DEBUG("breakpoint from EICE unit 1"); target->debug_reason = DBG_REASON_BREAKPOINT; break; case 3: LOG_DEBUG("soft breakpoint (BKPT instruction)"); target->debug_reason = DBG_REASON_BREAKPOINT; break; case 4: LOG_DEBUG("vector catch breakpoint"); target->debug_reason = DBG_REASON_BREAKPOINT; break; case 5: LOG_DEBUG("external breakpoint"); target->debug_reason = DBG_REASON_BREAKPOINT; break; case 6: LOG_DEBUG("watchpoint from EICE unit 0"); target->debug_reason = DBG_REASON_WATCHPOINT; break; case 7: LOG_DEBUG("watchpoint from EICE unit 1"); target->debug_reason = DBG_REASON_WATCHPOINT; break; case 8: LOG_DEBUG("external watchpoint"); target->debug_reason = DBG_REASON_WATCHPOINT; break; case 9: LOG_DEBUG("internal debug request"); target->debug_reason = DBG_REASON_DBGRQ; break; case 10: LOG_DEBUG("external debug request"); target->debug_reason = DBG_REASON_DBGRQ; break; case 11: LOG_DEBUG("debug re-entry from system speed access"); /* This is normal when connecting to something that's * already halted, or in some related code paths, but * otherwise is surprising (and presumably wrong). */ switch (target->debug_reason) { case DBG_REASON_DBGRQ: break; default: LOG_ERROR("unexpected -- debug re-entry"); /* FALLTHROUGH */ case DBG_REASON_UNDEFINED: target->debug_reason = DBG_REASON_DBGRQ; break; } break; case 12: /* FIX!!!! here be dragons!!! We need to fail here so * the target will interpreted as halted but we won't * try to talk to it right now... a resume + halt seems * to sync things up again. Please send an email to * openocd development mailing list if you have hardware * to donate to look into this problem.... */ LOG_WARNING("WARNING: mystery debug reason MOE = 0xc. Try issuing a resume + halt."); target->debug_reason = DBG_REASON_DBGRQ; break; default: LOG_WARNING("WARNING: unknown debug reason: 0x%x", debug_reason); /* Oh agony! should we interpret this as a halt request or * that the target stopped on it's own accord? */ target->debug_reason = DBG_REASON_DBGRQ; /* if we fail here, we won't talk to the target and it will * be reported to be in the halted state */ break; } return ERROR_OK; } static int arm926ejs_get_ttb(struct target *target, uint32_t *result) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); int retval; uint32_t ttb = 0x0; retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb); if (retval != ERROR_OK) return retval; *result = ttb; return ERROR_OK; } static int arm926ejs_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) { /* invalidate TLB */ retval = arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0); if (retval != ERROR_OK) return retval; cp15_control &= ~0x1U; } if (d_u_cache) { uint32_t debug_override; /* read-modify-write CP15 debug override register * to enable "test and clean all" */ retval = arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override); if (retval != ERROR_OK) return retval; debug_override |= 0x80000; retval = arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override); if (retval != ERROR_OK) return retval; /* clean and invalidate DCache */ retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0); if (retval != ERROR_OK) return retval; /* write CP15 debug override register * to disable "test and clean all" */ debug_override &= ~0x80000; retval = arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override); if (retval != ERROR_OK) return retval; cp15_control &= ~0x4U; } if (i_cache) { /* invalidate ICache */ retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0); if (retval != ERROR_OK) return retval; cp15_control &= ~0x1000U; } retval = arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control); return retval; } static int arm926ejs_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); uint32_t cp15_control; int retval; /* read cp15 control register */ retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (mmu) cp15_control |= 0x1U; if (d_u_cache) cp15_control |= 0x4U; if (i_cache) cp15_control |= 0x1000U; retval = arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control); return retval; } static int arm926ejs_post_debug_entry(struct target *target) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); int retval; /* examine cp15 control reg */ retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg); if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1) { uint32_t cache_type_reg; /* identify caches */ retval = arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache); } arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0; arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0; arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0; /* save i/d fault status and address register */ retval = arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr); if (retval != ERROR_OK) return retval; retval = arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr); if (retval != ERROR_OK) return retval; retval = arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far); if (retval != ERROR_OK) return retval; LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 "", arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr); uint32_t cache_dbg_ctrl; /* read-modify-write CP15 cache debug control register * to disable I/D-cache linefills and force WT */ retval = arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl); if (retval != ERROR_OK) return retval; cache_dbg_ctrl |= 0x7; retval = arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl); return retval; } static void arm926ejs_pre_restore_context(struct target *target) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); /* restore i/d fault status and address register */ arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr); arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr); arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far); uint32_t cache_dbg_ctrl; /* read-modify-write CP15 cache debug control register * to reenable I/D-cache linefills and disable WT */ arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl); cache_dbg_ctrl &= ~0x7; arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl); } static const char arm926_not[] = "target is not an ARM926"; static int arm926ejs_verify_pointer(struct command_context *cmd_ctx, struct arm926ejs_common *arm926) { if (arm926->common_magic != ARM926EJS_COMMON_MAGIC) { command_print(cmd_ctx, arm926_not); return ERROR_TARGET_INVALID; } return ERROR_OK; } /** Logs summary of ARM926 state for a halted target. */ int arm926ejs_arch_state(struct target *target) { static const char *state[] = { "disabled", "enabled" }; struct arm926ejs_common *arm926ejs = target_to_arm926(target); if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC) { LOG_ERROR("BUG: %s", arm926_not); return ERROR_TARGET_INVALID; } arm_arch_state(target); LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", state[arm926ejs->armv4_5_mmu.mmu_enabled], state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]); return ERROR_OK; } int arm926ejs_soft_reset_halt(struct target *target) { int retval = ERROR_OK; struct arm926ejs_common *arm926ejs = target_to_arm926(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; retval = target_halt(target); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; } else break; if (debug_level >= 1) { /* do not eat all CPU, time out after 1 se*/ alive_sleep(100); } else keep_alive(); } if (timeout) { LOG_ERROR("Failed to halt CPU after 1 sec"); return ERROR_TARGET_TIMEOUT; } target->state = TARGET_HALTED; /* SVC, ARM state, IRQ and FIQ disabled */ uint32_t cpsr; cpsr = buf_get_u32(arm->cpsr->value, 0, 32); cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); arm->pc->dirty = 1; arm->pc->valid = 1; retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1); if (retval != ERROR_OK) return retval; arm926ejs->armv4_5_mmu.mmu_enabled = 0; arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0; arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0; return target_call_event_callbacks(target, TARGET_EVENT_HALTED); } /** Writes a buffer, in the specified word size, with current MMU settings. */ int arm926ejs_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; struct arm926ejs_common *arm926ejs = target_to_arm926(target); /* FIX!!!! this should be cleaned up and made much more general. The * plan is to write up and test on arm926ejs specifically and * then generalize and clean up afterwards. * * * Also it should be moved to the callbacks that handle breakpoints * specifically and not the generic memory write fn's. See XScale code. **/ if (arm926ejs->armv4_5_mmu.mmu_enabled && (count == 1) && ((size == 2) || (size == 4))) { /* special case the handling of single word writes to bypass MMU * to allow implementation of breakpoints in memory marked read only * by MMU */ if (arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) { /* flush and invalidate data cache * * MCR p15,0,p,c7,c10,1 - clean cache line using virtual address * */ retval = arm926ejs->write_cp15(target, 0, 1, 7, 10, address&~0x3); if (retval != ERROR_OK) return retval; } uint32_t pa; retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) return retval; /* write directly to physical memory bypassing any read only MMU bits, etc. */ retval = armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, pa, size, count, buffer); if (retval != ERROR_OK) return retval; } else { retval = arm7_9_write_memory(target, address, size, count, buffer); if (retval != ERROR_OK) return retval; } /* If ICache is enabled, we have to invalidate affected ICache lines * the DCache is forced to write-through, so we don't have to clean it here */ if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled) { if (count <= 1) { /* invalidate ICache single entry with MVA */ arm926ejs->write_cp15(target, 0, 1, 7, 5, address); } else { /* invalidate ICache */ arm926ejs->write_cp15(target, 0, 0, 7, 5, address); } } return retval; } static int arm926ejs_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); return armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, address, size, count, buffer); } static int arm926ejs_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); return armv4_5_mmu_read_physical(target, &arm926ejs->armv4_5_mmu, address, size, count, buffer); } int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs, struct jtag_tap *tap) { struct arm7_9_common *arm7_9 = &arm926ejs->arm7_9_common; arm7_9->arm.mrc = arm926ejs_mrc; arm7_9->arm.mcr = arm926ejs_mcr; /* initialize arm7/arm9 specific info (including armv4_5) */ arm9tdmi_init_arch_info(target, arm7_9, tap); arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC; arm7_9->post_debug_entry = arm926ejs_post_debug_entry; arm7_9->pre_restore_context = arm926ejs_pre_restore_context; arm7_9->write_memory = arm926ejs_write_memory; arm926ejs->read_cp15 = arm926ejs_cp15_read; arm926ejs->write_cp15 = arm926ejs_cp15_write; arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1; arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb; arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory; arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory; arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches; arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches; arm926ejs->armv4_5_mmu.has_tiny_pages = 1; arm926ejs->armv4_5_mmu.mmu_enabled = 0; arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason; /* The ARM926EJ-S implements the ARMv5TE architecture which * has the BKPT instruction, so we don't have to use a watchpoint comparator */ arm7_9->arm_bkpt = ARMV5_BKPT(0x0); arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff; return ERROR_OK; } static int arm926ejs_target_create(struct target *target, Jim_Interp *interp) { struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common)); /* ARM9EJ-S core always reports 0x1 in Capture-IR */ target->tap->ir_capture_mask = 0x0f; return arm926ejs_init_arch_info(target, arm926ejs, target->tap); } COMMAND_HANDLER(arm926ejs_handle_cache_info_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm926ejs_common *arm926ejs = target_to_arm926(target); retval = arm926ejs_verify_pointer(CMD_CTX, arm926ejs); if (retval != ERROR_OK) return retval; return armv4_5_handle_cache_info_command(CMD_CTX, &arm926ejs->armv4_5_mmu.armv4_5_cache); } static int arm926ejs_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) { uint32_t cb; struct arm926ejs_common *arm926ejs = target_to_arm926(target); uint32_t ret; int retval = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &cb, &ret); if (retval != ERROR_OK) return retval; *physical = ret; return ERROR_OK; } static int arm926ejs_mmu(struct target *target, int *enabled) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_INVALID; } *enabled = arm926ejs->armv4_5_mmu.mmu_enabled; return ERROR_OK; } static const struct command_registration arm926ejs_exec_command_handlers[] = { { .name = "cache_info", .handler = arm926ejs_handle_cache_info_command, .mode = COMMAND_EXEC, .usage = "", .help = "display information about target caches", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm926ejs_command_handlers[] = { { .chain = arm9tdmi_command_handlers, }, { .name = "arm926ejs", .mode = COMMAND_ANY, .help = "arm926ejs command group", .usage = "", .chain = arm926ejs_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM926 targets. */ struct target_type arm926ejs_target = { .name = "arm926ejs", .poll = arm7_9_poll, .arch_state = arm926ejs_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm926ejs_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm926ejs_command_handlers, .target_create = arm926ejs_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, .virt2phys = arm926ejs_virt2phys, .mmu = arm926ejs_mmu, .read_phys_memory = arm926ejs_read_phys_memory, .write_phys_memory = arm926ejs_write_phys_memory, }; openocd-0.9.0/src/target/arm926ejs.h0000644000175000017500000000513312315575361014052 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM926EJS_H #define ARM926EJS_H #include "arm9tdmi.h" #include "armv4_5_mmu.h" #define ARM926EJS_COMMON_MAGIC 0xa926a926 struct arm926ejs_common { struct arm7_9_common arm7_9_common; uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value); int (*write_cp15)(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value); uint32_t cp15_control_reg; uint32_t d_fsr; uint32_t i_fsr; uint32_t d_far; }; static inline struct arm926ejs_common *target_to_arm926(struct target *target) { return container_of(target->arch_info, struct arm926ejs_common, arm7_9_common.arm); } int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs, struct jtag_tap *tap); int arm926ejs_arch_state(struct target *target); int arm926ejs_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm926ejs_soft_reset_halt(struct target *target); extern const struct command_registration arm926ejs_command_handlers[]; #endif /* ARM926EJS_H */ openocd-0.9.0/src/target/mips32.c0000644000175000017500000007511512516456304013445 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mips32.h" #include "breakpoints.h" #include "algorithm.h" #include "register.h" static const char *mips_isa_strings[] = { "MIPS32", "MIPS16e" }; #define MIPS32_GDB_DUMMY_FP_REG 1 /* * GDB registers * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml */ static const struct { unsigned id; const char *name; enum reg_type type; const char *group; const char *feature; int flag; } mips32_regs[] = { { 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 2, "r2", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 3, "r3", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 4, "r4", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 5, "r5", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 6, "r6", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 7, "r7", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 8, "r8", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 9, "r9", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 10, "r10", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 11, "r11", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 12, "r12", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 13, "r13", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 14, "r14", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 15, "r15", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 16, "r16", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 17, "r17", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 18, "r18", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 19, "r19", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 20, "r20", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 21, "r21", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 22, "r22", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 23, "r23", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 24, "r24", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 25, "r25", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 26, "r26", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 27, "r27", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 28, "r28", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, { 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, { 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, { 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 }, { 38, "f0", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 39, "f1", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 40, "f2", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 41, "f3", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 42, "f4", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 43, "f5", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 44, "f6", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 45, "f7", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 46, "f8", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 47, "f9", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 48, "f10", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 49, "f11", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 50, "f12", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 51, "f13", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 52, "f14", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 53, "f15", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 54, "f16", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 55, "f17", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 56, "f18", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 57, "f19", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 58, "f20", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 59, "f21", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 60, "f22", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 61, "f23", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 62, "f24", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 63, "f25", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 64, "f26", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 65, "f27", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 66, "f28", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 67, "f29", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 68, "f30", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 69, "f31", REG_TYPE_IEEE_SINGLE, NULL, "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 70, "fcsr", REG_TYPE_INT, "float", "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, { 71, "fir", REG_TYPE_INT, "float", "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG }, }; #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0}; static int mips32_get_core_reg(struct reg *reg) { int retval; struct mips32_core_reg *mips32_reg = reg->arch_info; struct target *target = mips32_reg->target; struct mips32_common *mips32_target = target_to_mips32(target); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; retval = mips32_target->read_core_reg(target, mips32_reg->num); return retval; } static int mips32_set_core_reg(struct reg *reg, uint8_t *buf) { struct mips32_core_reg *mips32_reg = reg->arch_info; struct target *target = mips32_reg->target; uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static int mips32_read_core_reg(struct target *target, unsigned int num) { uint32_t reg_value; /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = mips32->core_regs[num]; buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); mips32->core_cache->reg_list[num].valid = 1; mips32->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int mips32_write_core_reg(struct target *target, unsigned int num) { uint32_t reg_value; /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); mips32->core_regs[num] = reg_value; LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value); mips32->core_cache->reg_list[num].valid = 1; mips32->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); unsigned int i; /* include floating point registers */ *reg_list_size = MIPS32_NUM_REGS; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < MIPS32_NUM_REGS; i++) (*reg_list)[i] = &mips32->core_cache->reg_list[i]; return ERROR_OK; } int mips32_save_context(struct target *target) { unsigned int i; /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; /* read core registers */ mips32_pracc_read_regs(ejtag_info, mips32->core_regs); for (i = 0; i < MIPS32_NUM_REGS; i++) { if (!mips32->core_cache->reg_list[i].valid) mips32->read_core_reg(target, i); } return ERROR_OK; } int mips32_restore_context(struct target *target) { unsigned int i; /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; for (i = 0; i < MIPS32_NUM_REGS; i++) { if (mips32->core_cache->reg_list[i].dirty) mips32->write_core_reg(target, i); } /* write core regs */ mips32_pracc_write_regs(ejtag_info, mips32->core_regs); return ERROR_OK; } int mips32_arch_state(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "", mips_isa_strings[mips32->isa_mode], debug_reason_name(target), buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)); return ERROR_OK; } static const struct reg_arch_type mips32_reg_type = { .get = mips32_get_core_reg, .set = mips32_set_core_reg, }; struct reg_cache *mips32_build_reg_cache(struct target *target) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); int num_regs = MIPS32_NUM_REGS; struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs); struct reg_feature *feature; int i; /* Build the process context cache */ cache->name = "mips32 registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = num_regs; (*cache_p) = cache; mips32->core_cache = cache; for (i = 0; i < num_regs; i++) { arch_info[i].num = mips32_regs[i].id; arch_info[i].target = target; arch_info[i].mips32_common = mips32; reg_list[i].name = mips32_regs[i].name; reg_list[i].size = 32; if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) { reg_list[i].value = mips32_gdb_dummy_fp_value; reg_list[i].valid = 1; reg_list[i].arch_info = NULL; register_init_dummy(®_list[i]); } else { reg_list[i].value = calloc(1, 4); reg_list[i].valid = 0; reg_list[i].type = &mips32_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); if (reg_list[i].reg_data_type) reg_list[i].reg_data_type->type = mips32_regs[i].type; else LOG_ERROR("unable to allocate reg type list"); } reg_list[i].dirty = 0; reg_list[i].group = mips32_regs[i].group; reg_list[i].number = i; reg_list[i].exist = true; reg_list[i].caller_save = true; /* gdb defaults to true */ feature = calloc(1, sizeof(struct reg_feature)); if (feature) { feature->name = mips32_regs[i].feature; reg_list[i].feature = feature; } else LOG_ERROR("unable to allocate feature list"); } return cache; } int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap) { target->arch_info = mips32; mips32->common_magic = MIPS32_COMMON_MAGIC; mips32->fast_data_area = NULL; /* has breakpoint/watchpoint unit been scanned */ mips32->bp_scanned = 0; mips32->data_break_list = NULL; mips32->ejtag_info.tap = tap; mips32->read_core_reg = mips32_read_core_reg; mips32->write_core_reg = mips32_write_core_reg; mips32->ejtag_info.scan_delay = 2000000; /* Initial default value */ mips32->ejtag_info.mode = 0; /* Initial default value */ return ERROR_OK; } /* run to exit point. return error if exit point was not reached. */ static int mips32_run_and_wait(struct target *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, struct mips32_common *mips32) { uint32_t pc; int retval; /* This code relies on the target specific resume() and poll()->debug_entry() * sequence to write register values to the processor and the read them back */ retval = target_resume(target, 0, entry_point, 0, 1); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, timeout_ms); /* If the target fails to halt due to the breakpoint, force a halt */ if (retval != ERROR_OK || target->state != TARGET_HALTED) { retval = target_halt(target); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, 500); if (retval != ERROR_OK) return retval; return ERROR_TARGET_TIMEOUT; } pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); if (exit_point && (pc != exit_point)) { LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc); return ERROR_TARGET_TIMEOUT; } return ERROR_OK; } int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { struct mips32_common *mips32 = target_to_mips32(target); struct mips32_algorithm *mips32_algorithm_info = arch_info; enum mips32_isa_mode isa_mode = mips32->isa_mode; uint32_t context[MIPS32_NUM_REGS]; int retval = ERROR_OK; LOG_DEBUG("Running algorithm"); /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ if (mips32->common_magic != MIPS32_COMMON_MAGIC) { LOG_ERROR("current target isn't a MIPS32 target"); return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* refresh core register cache */ for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) { if (!mips32->core_cache->reg_list[i].valid) mips32->read_core_reg(target, i); context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32); } for (int i = 0; i < num_mem_params; i++) { retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } for (int i = 0; i < num_reg_params; i++) { struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } mips32_set_core_reg(reg, reg_params[i].value); } mips32->isa_mode = mips32_algorithm_info->isa_mode; retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32); if (retval != ERROR_OK) return retval; for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) { retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } } for (int i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } /* restore everything we saved before */ for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) { uint32_t regvalue; regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32); if (regvalue != context[i]) { LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, mips32->core_cache->reg_list[i].name, context[i]); buf_set_u32(mips32->core_cache->reg_list[i].value, 0, 32, context[i]); mips32->core_cache->reg_list[i].valid = 1; mips32->core_cache->reg_list[i].dirty = 1; } } mips32->isa_mode = isa_mode; return ERROR_OK; } int mips32_examine(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); if (!target_was_examined(target)) { target_set_examined(target); /* we will configure later */ mips32->bp_scanned = 0; mips32->num_inst_bpoints = 0; mips32->num_data_bpoints = 0; mips32->num_inst_bpoints_avail = 0; mips32->num_data_bpoints_avail = 0; } return ERROR_OK; } static int mips32_configure_ibs(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int retval, i; uint32_t bpinfo; /* get number of inst breakpoints */ retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo); if (retval != ERROR_OK) return retval; mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F; mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints; mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator)); for (i = 0; i < mips32->num_inst_bpoints; i++) mips32->inst_break_list[i].reg_address = ejtag_info->ejtag_iba0_addr + (ejtag_info->ejtag_iba_step_size * i); /* clear IBIS reg */ retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0); return retval; } static int mips32_configure_dbs(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int retval, i; uint32_t bpinfo; /* get number of data breakpoints */ retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo); if (retval != ERROR_OK) return retval; mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F; mips32->num_data_bpoints_avail = mips32->num_data_bpoints; mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator)); for (i = 0; i < mips32->num_data_bpoints; i++) mips32->data_break_list[i].reg_address = ejtag_info->ejtag_dba0_addr + (ejtag_info->ejtag_dba_step_size * i); /* clear DBIS reg */ retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0); return retval; } int mips32_configure_break_unit(struct target *target) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int retval; uint32_t dcr; if (mips32->bp_scanned) return ERROR_OK; /* get info about breakpoint support */ retval = target_read_u32(target, EJTAG_DCR, &dcr); if (retval != ERROR_OK) return retval; /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */ if (ejtag_info->ejtag_version == EJTAG_VERSION_20) { ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM; if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB)) ejtag_info->debug_caps |= EJTAG_DCR_IB; if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB)) ejtag_info->debug_caps |= EJTAG_DCR_DB; } else /* keep debug caps for later use */ ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM | EJTAG_DCR_IB | EJTAG_DCR_DB); if (ejtag_info->debug_caps & EJTAG_DCR_IB) { retval = mips32_configure_ibs(target); if (retval != ERROR_OK) return retval; } if (ejtag_info->debug_caps & EJTAG_DCR_DB) { retval = mips32_configure_dbs(target); if (retval != ERROR_OK) return retval; } /* check if target endianness settings matches debug control register */ if (((ejtag_info->debug_caps & EJTAG_DCR_ENM) && (target->endianness == TARGET_LITTLE_ENDIAN)) || (!(ejtag_info->debug_caps & EJTAG_DCR_ENM) && (target->endianness == TARGET_BIG_ENDIAN))) LOG_WARNING("DCR endianness settings does not match target settings"); LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints, mips32->num_data_bpoints); mips32->bp_scanned = 1; return ERROR_OK; } int mips32_enable_interrupts(struct target *target, int enable) { int retval; int update = 0; uint32_t dcr; /* read debug control register */ retval = target_read_u32(target, EJTAG_DCR, &dcr); if (retval != ERROR_OK) return retval; if (enable) { if (!(dcr & EJTAG_DCR_INTE)) { /* enable interrupts */ dcr |= EJTAG_DCR_INTE; update = 1; } } else { if (dcr & EJTAG_DCR_INTE) { /* disable interrupts */ dcr &= ~EJTAG_DCR_INTE; update = 1; } } if (update) { retval = target_write_u32(target, EJTAG_DCR, dcr); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int mips32_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct reg_param reg_params[2]; struct mips32_algorithm mips32_info; /* see contrib/loaders/checksum/mips32.s for src */ static const uint32_t mips_crc_code[] = { 0x248C0000, /* addiu $t4, $a0, 0 */ 0x24AA0000, /* addiu $t2, $a1, 0 */ 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */ 0x10000010, /* beq $zero, $zero, ncomp */ 0x240B0000, /* addiu $t3, $zero, 0 */ /* nbyte: */ 0x81850000, /* lb $a1, ($t4) */ 0x218C0001, /* addi $t4, $t4, 1 */ 0x00052E00, /* sll $a1, $a1, 24 */ 0x3C0204C1, /* lui $v0, 0x04c1 */ 0x00852026, /* xor $a0, $a0, $a1 */ 0x34471DB7, /* ori $a3, $v0, 0x1db7 */ 0x00003021, /* addu $a2, $zero, $zero */ /* loop: */ 0x00044040, /* sll $t0, $a0, 1 */ 0x24C60001, /* addiu $a2, $a2, 1 */ 0x28840000, /* slti $a0, $a0, 0 */ 0x01074826, /* xor $t1, $t0, $a3 */ 0x0124400B, /* movn $t0, $t1, $a0 */ 0x28C30008, /* slti $v1, $a2, 8 */ 0x1460FFF9, /* bne $v1, $zero, loop */ 0x01002021, /* addu $a0, $t0, $zero */ /* ncomp: */ 0x154BFFF0, /* bne $t2, $t3, nbyte */ 0x256B0001, /* addiu $t3, $t3, 1 */ 0x7000003F, /* sdbbp */ }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* convert mips crc code into a buffer in target endianness */ uint8_t mips_crc_code_8[sizeof(mips_crc_code)]; target_buffer_set_u32_array(target, mips_crc_code_8, ARRAY_SIZE(mips_crc_code), mips_crc_code); target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8); mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; init_reg_param(®_params[0], "r4", 32, PARAM_IN_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); init_reg_param(®_params[1], "r5", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, count); int timeout = 20000 * (1 + (count / (1024 * 1024))); int retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); target_free_working_area(target, crc_algorithm); return retval; } /** Checks whether a memory region is zeroed. */ int mips32_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct mips32_algorithm mips32_info; static const uint32_t erase_check_code[] = { /* nbyte: */ 0x80880000, /* lb $t0, ($a0) */ 0x00C83024, /* and $a2, $a2, $t0 */ 0x24A5FFFF, /* addiu $a1, $a1, -1 */ 0x14A0FFFC, /* bne $a1, $zero, nbyte */ 0x24840001, /* addiu $a0, $a0, 1 */ 0x7000003F /* sdbbp */ }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* convert erase check code into a buffer in target endianness */ uint8_t erase_check_code_8[sizeof(erase_check_code)]; target_buffer_set_u32_array(target, erase_check_code_8, ARRAY_SIZE(erase_check_code), erase_check_code); target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), erase_check_code_8); mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; init_reg_param(®_params[0], "r4", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); init_reg_param(®_params[1], "r5", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, 0xff); int retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info); if (retval == ERROR_OK) *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); target_free_working_area(target, erase_check_algorithm); return retval; } static int mips32_verify_pointer(struct command_context *cmd_ctx, struct mips32_common *mips32) { if (mips32->common_magic != MIPS32_COMMON_MAGIC) { command_print(cmd_ctx, "target is not an MIPS32"); return ERROR_TARGET_INVALID; } return ERROR_OK; } /** * MIPS32 targets expose command interface * to manipulate CP0 registers */ COMMAND_HANDLER(mips32_handle_cp0_command) { int retval; struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; retval = mips32_verify_pointer(CMD_CTX, mips32); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } /* two or more argument, access a single register/select (write if third argument is given) */ if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; else { uint32_t cp0_reg, cp0_sel; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); if (CMD_ARGC == 2) { uint32_t value; retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access reg %" PRIi32, cp0_reg); return ERROR_OK; } command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, cp0_reg, cp0_sel, value); } else if (CMD_ARGC == 3) { uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel); if (retval != ERROR_OK) { command_print(CMD_CTX, "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32, cp0_reg, cp0_sel); return ERROR_OK; } command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, cp0_reg, cp0_sel, value); } } return ERROR_OK; } COMMAND_HANDLER(mips32_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= 2000000) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { ejtag_info->mode = 1; command_print(CMD_CTX, "running in fast queued mode"); } return ERROR_OK; } static const struct command_registration mips32_exec_command_handlers[] = { { .name = "cp0", .handler = mips32_handle_cp0_command, .mode = COMMAND_EXEC, .usage = "regnum select [value]", .help = "display/modify cp0 register", }, { .name = "scan_delay", .handler = mips32_handle_scan_delay_command, .mode = COMMAND_ANY, .help = "display/set scan delay in nano seconds", .usage = "[value]", }, COMMAND_REGISTRATION_DONE }; const struct command_registration mips32_command_handlers[] = { { .name = "mips32", .mode = COMMAND_ANY, .help = "mips32 command group", .usage = "", .chain = mips32_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/mips32.h0000644000175000017500000002320412516456304013442 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MIPS32_H #define MIPS32_H #include "target.h" #include "mips32_pracc.h" #define MIPS32_COMMON_MAGIC 0xB320B320 /** * Memory segments (32bit kernel mode addresses) * These are the traditional names used in the 32-bit universe. */ #define KUSEG 0x00000000 #define KSEG0 0x80000000 #define KSEG1 0xa0000000 #define KSEG2 0xc0000000 #define KSEG3 0xe0000000 /** Returns the kernel segment base of a given address */ #define KSEGX(a) ((a) & 0xe0000000) /** CP0 CONFIG regites fields */ #define MIPS32_CONFIG0_KU_SHIFT 25 #define MIPS32_CONFIG0_KU_MASK (0x7 << MIPS32_CONFIG0_KU_SHIFT) #define MIPS32_CONFIG0_K0_SHIFT 0 #define MIPS32_CONFIG0_K0_MASK (0x7 << MIPS32_CONFIG0_K0_SHIFT) #define MIPS32_CONFIG0_K23_SHIFT 28 #define MIPS32_CONFIG0_K23_MASK (0x7 << MIPS32_CONFIG0_K23_SHIFT) #define MIPS32_CONFIG0_AR_SHIFT 10 #define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT) #define MIPS32_CONFIG1_DL_SHIFT 10 #define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT) #define MIPS32_ARCH_REL1 0x0 #define MIPS32_ARCH_REL2 0x1 /* offsets into mips32 core register cache */ enum { MIPS32_PC = 37, MIPS32_FIR = 71, MIPS32NUMCOREREGS }; enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, }; struct mips32_comparator { int used; uint32_t bp_value; uint32_t reg_address; }; struct mips32_common { uint32_t common_magic; void *arch_info; struct reg_cache *core_cache; struct mips_ejtag ejtag_info; uint32_t core_regs[MIPS32NUMCOREREGS]; enum mips32_isa_mode isa_mode; /* working area for fastdata access */ struct working_area *fast_data_area; int bp_scanned; int num_inst_bpoints; int num_data_bpoints; int num_inst_bpoints_avail; int num_data_bpoints_avail; struct mips32_comparator *inst_break_list; struct mips32_comparator *data_break_list; /* register cache to processor synchronization */ int (*read_core_reg)(struct target *target, unsigned int num); int (*write_core_reg)(struct target *target, unsigned int num); }; static inline struct mips32_common * target_to_mips32(struct target *target) { return target->arch_info; } struct mips32_core_reg { uint32_t num; struct target *target; struct mips32_common *mips32_common; }; struct mips32_algorithm { int common_magic; enum mips32_isa_mode isa_mode; }; #define MIPS32_OP_ADDIU 0x21 #define MIPS32_OP_ANDI 0x0C #define MIPS32_OP_BEQ 0x04 #define MIPS32_OP_BGTZ 0x07 #define MIPS32_OP_BNE 0x05 #define MIPS32_OP_ADDI 0x08 #define MIPS32_OP_AND 0x24 #define MIPS32_OP_CACHE 0x2F #define MIPS32_OP_COP0 0x10 #define MIPS32_OP_J 0x02 #define MIPS32_OP_JR 0x08 #define MIPS32_OP_LUI 0x0F #define MIPS32_OP_LW 0x23 #define MIPS32_OP_LBU 0x24 #define MIPS32_OP_LHU 0x25 #define MIPS32_OP_MFHI 0x10 #define MIPS32_OP_MTHI 0x11 #define MIPS32_OP_MFLO 0x12 #define MIPS32_OP_MTLO 0x13 #define MIPS32_OP_RDHWR 0x3B #define MIPS32_OP_SB 0x28 #define MIPS32_OP_SH 0x29 #define MIPS32_OP_SW 0x2B #define MIPS32_OP_ORI 0x0D #define MIPS32_OP_XORI 0x0E #define MIPS32_OP_XOR 0x26 #define MIPS32_OP_SLTU 0x2B #define MIPS32_OP_SRL 0x03 #define MIPS32_OP_SYNCI 0x1F #define MIPS32_OP_REGIMM 0x01 #define MIPS32_OP_SDBBP 0x3F #define MIPS32_OP_SPECIAL 0x00 #define MIPS32_OP_SPECIAL2 0x07 #define MIPS32_OP_SPECIAL3 0x1F #define MIPS32_COP0_MF 0x00 #define MIPS32_COP0_MT 0x04 #define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct)) #define MIPS32_I_INST(opcode, rs, rt, immd) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd)) #define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr)) #define MIPS32_NOP 0 #define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) #define MIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDIU) #define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND) #define MIPS32_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) #define MIPS32_B(off) MIPS32_BEQ(0, 0, off) #define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) #define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) #define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) #define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) #define MIPS32_J(tar) MIPS32_J_INST(MIPS32_OP_J, tar) #define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) #define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) #define MIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) #define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) #define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) #define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) #define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) #define MIPS32_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) #define MIPS32_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) #define MIPS32_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) #define MIPS32_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) #define MIPS32_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) #define MIPS32_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) #define MIPS32_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) #define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) #define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) #define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) #define MIPS32_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) #define MIPS32_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) #define MIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) #define MIPS32_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) #define MIPS32_SYNC 0xF #define MIPS32_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ /** * Cache operations definitions * Operation field is 5 bits long : * 1) bits 1..0 hold cache type * 2) bits 4..2 hold operation code */ #define MIPS32_CACHE_D_HIT_WRITEBACK ((0x1 << 0) | (0x6 << 2)) #define MIPS32_CACHE_I_HIT_INVALIDATE ((0x0 << 0) | (0x4 << 2)) /* ejtag specific instructions */ #define MIPS32_DRET 0x4200001F #define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */ #define MIPS16_SDBBP 0xE801 extern const struct command_registration mips32_command_handlers[]; int mips32_arch_state(struct target *target); int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap); int mips32_restore_context(struct target *target); int mips32_save_context(struct target *target); struct reg_cache *mips32_build_reg_cache(struct target *target); int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); int mips32_configure_break_unit(struct target *target); int mips32_enable_interrupts(struct target *target, int enable); int mips32_examine(struct target *target); int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); int mips32_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int mips32_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank); #endif /*MIPS32_H*/ openocd-0.9.0/src/target/mips32_pracc.c0000644000175000017500000011460012516456304014606 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2009 by David N. Claffey * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * This version has optimized assembly routines for 32 bit operations: * - read word * - write word * - write array of words * * One thing to be aware of is that the MIPS32 cpu will execute the * instruction after a branch instruction (one delay slot). * * For example: * LW $2, ($5 +10) * B foo * LW $1, ($2 +100) * * The LW $1, ($2 +100) instruction is also executed. If this is * not wanted a NOP can be inserted: * * LW $2, ($5 +10) * B foo * NOP * LW $1, ($2 +100) * * or the code can be changed to: * * B foo * LW $2, ($5 +10) * LW $1, ($2 +100) * * The original code contained NOPs. I have removed these and moved * the branches. * * These changes result in a 35% speed increase when programming an * external flash. * * More improvement could be gained if the registers do no need * to be preserved but in that case the routines should be aware * OpenOCD is used as a flash programmer or as a debug tool. * * Nico Coesel */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "mips32.h" #include "mips32_pracc.h" struct mips32_pracc_context { uint32_t *local_oparam; int num_oparam; const uint32_t *code; int code_len; uint32_t stack[32]; int stack_offset; struct mips_ejtag *ejtag_info; }; static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) { uint32_t ejtag_ctrl; long long then = timeval_ms(); /* wait for the PrAcc to become "1" */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); while (1) { ejtag_ctrl = ejtag_info->ejtag_ctrl; int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; if (ejtag_ctrl & EJTAG_CTRL_PRACC) break; int timeout = timeval_ms() - then; if (timeout > 1000) { LOG_DEBUG("DEBUGMODULE: No memory access in progress!"); return ERROR_JTAG_DEVICE_ERROR; } } *ctrl = ejtag_ctrl; return ERROR_OK; } /* Shift in control and address for a new processor access, save them in ejtag_info */ static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info) { int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); if (retval != ERROR_OK) return retval; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); ejtag_info->pa_addr = 0; retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr); return retval; } /* Finish processor access */ static int mips32_pracc_finish(struct mips_ejtag *ejtag_info) { uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ctrl); return jtag_execute_queue(); } int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) { uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2); int retval; /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */ for (int i = 0; i != 5; i++) { /* Wait for pracc */ retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); if (retval != ERROR_OK) return retval; /* Data or instruction out */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); uint32_t data = (i == 3) ? jt_code : MIPS32_NOP; mips_ejtag_drscan_32_out(ejtag_info, data); /* finish pa */ retval = mips32_pracc_finish(ejtag_info); if (retval != ERROR_OK) return retval; } if (ejtag_info->mode != 0) /* done, queued mode won't work with lexra cores */ return ERROR_OK; retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP); retval = mips32_pracc_finish(ejtag_info); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out) { int code_count = 0; int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */ uint32_t max_store_addr = 0; /* for store pa address testing */ bool restart = 0; /* restarting control */ int restart_count = 0; uint32_t instr = 0; bool final_check = 0; /* set to 1 if in final checks after function code shifted out */ bool pass = 0; /* to check the pass through pracc text after function code sent */ int retval; while (1) { if (restart) { if (restart_count < 3) { /* max 3 restarts allowed */ retval = mips32_pracc_clean_text_jump(ejtag_info); if (retval != ERROR_OK) return retval; } else return ERROR_JTAG_DEVICE_ERROR; restart_count++; restart = 0; code_count = 0; LOG_DEBUG("restarting code"); } retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */ if (retval != ERROR_OK) return retval; /* Check for read or write access */ if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */ /* Check for pending store from a previous store instruction at dmseg */ if (store_pending == 0) { LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr); if (code_count < 2) { /* allow for restart */ restart = 1; continue; } else return ERROR_JTAG_DEVICE_ERROR; } else { /* check address */ if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) { LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr); return ERROR_JTAG_DEVICE_ERROR; } } /* read data */ uint32_t data = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); retval = mips_ejtag_drscan_32(ejtag_info, &data); if (retval != ERROR_OK) return retval; /* store data at param out, address based offset */ param_out[(ejtag_info->pa_addr - MIPS32_PRACC_PARAM_OUT) / 4] = data; store_pending--; } else { /* read/fetch access */ if (!final_check) { /* executing function code */ /* check address */ if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x", ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); /* restart code execution only in some cases */ if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) { LOG_DEBUG("restarting, without clean jump"); restart_count++; code_count = 0; continue; } else if (code_count < 2) { restart = 1; continue; } return ERROR_JTAG_DEVICE_ERROR; } /* check for store instruction at dmseg */ uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count]; if (store_addr != 0) { if (store_addr > max_store_addr) max_store_addr = store_addr; store_pending++; } instr = ctx->pracc_list[code_count++]; if (code_count == ctx->code_count) /* last instruction, start final check */ final_check = 1; } else { /* final check after function code shifted out */ /* check address */ if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) { if (!pass) { /* first pass through pracc text */ if (store_pending == 0) /* done, normal exit */ return ERROR_OK; pass = 1; /* pracc text passed */ code_count = 0; /* restart code count */ } else { LOG_DEBUG("unexpected second pass through pracc text"); return ERROR_JTAG_DEVICE_ERROR; } } else { if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x", ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); return ERROR_JTAG_DEVICE_ERROR; } } if (!pass) { if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */ LOG_DEBUG("failed to jump back to pracc text"); return ERROR_JTAG_DEVICE_ERROR; } } else if (code_count > 10) { /* enough, abandone */ LOG_DEBUG("execution abandoned, store pending: %d", store_pending); return ERROR_JTAG_DEVICE_ERROR; } instr = MIPS32_NOP; /* shift out NOPs instructions */ code_count++; } /* Send instruction out */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32_out(ejtag_info, instr); } /* finish processor access, let the processor eat! */ retval = mips32_pracc_finish(ejtag_info); if (retval != ERROR_OK) return retval; if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */ return ERROR_OK; if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */ LOG_DEBUG("warning: store access pass pracc text"); return ERROR_OK; } } } inline void pracc_queue_init(struct pracc_queue_info *ctx) { ctx->retval = ERROR_OK; ctx->code_count = 0; ctx->store_count = 0; ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t)); if (ctx->pracc_list == NULL) { LOG_ERROR("Out of memory"); ctx->retval = ERROR_FAIL; } } inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) { ctx->pracc_list[ctx->max_code + ctx->code_count] = addr; ctx->pracc_list[ctx->code_count++] = instr; if (addr) ctx->store_count++; } inline void pracc_queue_free(struct pracc_queue_info *ctx) { if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */ LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code); if (ctx->pracc_list != NULL) free(ctx->pracc_list); } int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf) { if (ejtag_info->mode == 0) return mips32_pracc_exec(ejtag_info, ctx, buf); union scan_in { uint8_t scan_96[12]; struct { uint8_t ctrl[4]; uint8_t data[4]; uint8_t addr[4]; } scan_32; } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count)); if (scan_in == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } unsigned num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); int scan_count = 0; for (int i = 0; i != 2 * ctx->code_count; i++) { uint32_t data = 0; if (i & 1u) { /* Check store address from previous instruction, if not the first */ if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1]) continue; } else data = ctx->pracc_list[i / 2]; jtag_add_clocks(num_clocks); mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96); } int retval = jtag_execute_queue(); /* execute queued scans */ if (retval != ERROR_OK) goto exit; uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */ scan_count = 0; for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */ uint32_t store_addr = 0; if (i & 1u) { /* Read store addres from previous instruction, if not the first */ store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1]; if (i < 2 || 0 == store_addr) continue; } ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) { LOG_ERROR("Error: access not pending count: %d", scan_count); retval = ERROR_FAIL; goto exit; } uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); if (store_addr != 0) { if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) { LOG_ERROR("Not a store/write access, count: %d", scan_count); retval = ERROR_FAIL; goto exit; } if (addr != store_addr) { LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", addr, store_addr, scan_count); retval = ERROR_FAIL; goto exit; } int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4; buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32); } else { if (ejtag_ctrl & EJTAG_CTRL_PRNW) { LOG_ERROR("Not a fetch/read access, count: %d", scan_count); retval = ERROR_FAIL; goto exit; } if (addr != fetch_addr) { LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", addr, fetch_addr, scan_count); retval = ERROR_FAIL; goto exit; } fetch_addr += 4; } scan_count++; } exit: free(scan_in); return retval; } int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) { struct pracc_queue_info ctx = {.max_code = 8}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */ pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf); exit: pracc_queue_free(&ctx); return ctx.retval; } int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { if (count == 1 && size == 4) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf); uint32_t *data = NULL; struct pracc_queue_info ctx = {.max_code = 256 * 3 + 8 + 1}; /* alloc memory for the worst case */ pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; if (size != 4) { data = malloc(256 * sizeof(uint32_t)); if (data == NULL) { LOG_ERROR("Out of memory"); goto exit; } } uint32_t *buf32 = buf; uint16_t *buf16 = buf; uint8_t *buf8 = buf; while (count) { ctx.code_count = 0; ctx.store_count = 0; int this_round_count = (count > 256) ? 256 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */ for (int i = 0; i != this_round_count; i++) { /* Main code loop */ uint32_t upper_base_addr = UPPER16((addr + 0x8000)); if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */ pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr)); last_upper_base_addr = upper_base_addr; } if (size == 4) pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */ else if (size == 2) pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9)); else pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9)); pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ addr += size; } pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 bits of reg 9 */ pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 bits of reg 9 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ if (size == 4) { ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32); if (ctx.retval != ERROR_OK) goto exit; buf32 += this_round_count; } else { ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data); if (ctx.retval != ERROR_OK) goto exit; uint32_t *data_p = data; for (int i = 0; i != this_round_count; i++) { if (size == 2) *buf16++ = *data_p++; else *buf8++ = *data_p++; } } count -= this_round_count; } exit: pracc_queue_free(&ctx); if (data != NULL) free(data); return ctx.retval; } int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel) { struct pracc_queue_info ctx = {.max_code = 7}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg << 11) | cp0_sel); /* move COP0 [cp0_reg select] to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val); exit: pracc_queue_free(&ctx); return ctx.retval; /** * Note that our input parametes cp0_reg and cp0_sel * are numbers (not gprs) which make part of mfc0 instruction opcode. * * These are not fix, but can be different for each mips32_cp0_read() function call, * and that is why we must insert them directly into opcode, * i.e. we can not pass it on EJTAG microprogram stack (via param_in), * and put them into the gprs later from MIPS32_PRACC_STACK * because mfc0 do not use gpr as a parameter for the cp0_reg and select part, * but plain (immediate) number. * * MIPS32_MTC0 is implemented via MIPS32_R_INST macro. * In order to insert our parameters, we must change rd and funct fields. * * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro **/ } int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel) { struct pracc_queue_info ctx = {.max_code = 6}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */ pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val))); pracc_add(&ctx, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg << 11) | cp0_sel); /* write cp0 reg / sel */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); exit: pracc_queue_free(&ctx); return ctx.retval; /** * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro. * In order to insert our parameters, we must change rd and funct fields. * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro **/ } /** * \b mips32_pracc_sync_cache * * Synchronize Caches to Make Instruction Writes Effective * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set, * Document Number: MD00086, Revision 2.00, June 9, 2003) * * When the instruction stream is written, the SYNCI instruction should be used * in conjunction with other instructions to make the newly-written instructions effective. * * Explanation : * A program that loads another program into memory is actually writing the D- side cache. * The instructions it has loaded can't be executed until they reach the I-cache. * * After the instructions have been written, the loader should arrange * to write back any containing D-cache line and invalidate any locations * already in the I-cache. * * If the cache coherency attribute (CCA) is set to zero, it's a write through cache, there is no need * to write back. * * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction, * which does the whole job for a cache-line-sized chunk of the memory you just loaded: * That is, it arranges a D-cache write-back (if CCA = 3) and an I-cache invalidate. * * The line size is obtained with the rdhwr SYNCI_Step in release 2 or from cp0 config 1 register in release 1. */ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr, int cached, int rel) { struct pracc_queue_info ctx = {.max_code = 256 * 2 + 5}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; /** Find cache line size in bytes */ uint32_t clsiz; if (rel) { /* Release 2 (rel = 1) */ pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz); if (ctx.retval != ERROR_OK) goto exit; } else { /* Release 1 (rel = 0) */ uint32_t conf; ctx.retval = mips32_cp0_read(ejtag_info, &conf, 16, 1); if (ctx.retval != ERROR_OK) goto exit; uint32_t dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT; /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... max dl=6 => 128 bytes cache line size */ clsiz = 0x2 << dl; if (dl == 0) clsiz = 0; } if (clsiz == 0) goto exit; /* Nothing to do */ /* make sure clsiz is power of 2 */ if (clsiz & (clsiz - 1)) { LOG_DEBUG("clsiz must be power of 2"); ctx.retval = ERROR_FAIL; goto exit; } /* make sure start_addr and end_addr have the same offset inside de cache line */ start_addr |= clsiz - 1; end_addr |= clsiz - 1; ctx.code_count = 0; int count = 0; uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000)); pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load upper memory base address to $15 */ while (start_addr <= end_addr) { /* main loop */ uint32_t upper_base_addr = UPPER16((start_addr + 0x8000)); if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15 */ pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); last_upper_base_addr = upper_base_addr; } if (rel) pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15)); /* synci instruction, offset($15) */ else { if (cached == 3) pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, LOWER16(start_addr), 15)); /* cache Hit_Writeback_D, offset($15) */ pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, LOWER16(start_addr), 15)); /* cache Hit_Invalidate_I, offset($15) */ } start_addr += clsiz; count++; if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); if (ctx.retval != ERROR_OK) goto exit; ctx.code_count = 0; count = 0; } } pracc_add(&ctx, 0, MIPS32_SYNC); pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); exit: pracc_queue_free(&ctx); return ctx.retval; } static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { struct pracc_queue_info ctx = {.max_code = 128 * 3 + 5 + 1}; /* alloc memory for the worst case */ pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; const uint32_t *buf32 = buf; const uint16_t *buf16 = buf; const uint8_t *buf8 = buf; while (count) { ctx.code_count = 0; ctx.store_count = 0; int this_round_count = (count > 128) ? 128 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */ for (int i = 0; i != this_round_count; i++) { uint32_t upper_base_addr = UPPER16((addr + 0x8000)); if (last_upper_base_addr != upper_base_addr) { pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/ last_upper_base_addr = upper_base_addr; } if (size == 4) { /* for word writes check if one half word is 0 and load it accordingly */ if (LOWER16(*buf32) == 0) pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load only upper value */ else if (UPPER16(*buf32) == 0) pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32))); /* load only lower */ else { pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load upper and lower */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32))); } pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */ buf32++; } else if (size == 2) { pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */ pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */ buf16++; } else { pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */ pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */ buf8++; } addr += size; } pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); if (ctx.retval != ERROR_OK) goto exit; count -= this_round_count; } exit: pracc_queue_free(&ctx); return ctx.retval; } int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf); if (retval != ERROR_OK) return retval; /** * If we are in the cacheable region and cache is activated, * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write, * so that changes do not continue to live only in D$ (if CCA = 3), but to be * replicated in I$ also (maybe we wrote the istructions) */ uint32_t conf = 0; int cached = 0; if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff))) return retval; /*Nothing to do*/ mips32_cp0_read(ejtag_info, &conf, 16, 0); switch (KSEGX(addr)) { case KUSEG: cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT; break; case KSEG0: cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT; break; case KSEG2: case KSEG3: cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT; break; default: /* what ? */ break; } /** * Check cachablitiy bits coherency algorithm * is the region cacheable or uncached. * If cacheable we have to synchronize the cache */ if (cached == 3 || cached == 0) { /* Write back cache or write through cache */ uint32_t start_addr = addr; uint32_t end_addr = addr + count * size; uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; if (rel > 1) { LOG_DEBUG("Unknown release in cache code"); return ERROR_FAIL; } retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel); } return retval; } int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { static const uint32_t cp0_write_code[] = { MIPS32_MTC0(1, 12, 0), /* move $1 to status */ MIPS32_MTLO(1), /* move $1 to lo */ MIPS32_MTHI(1), /* move $1 to hi */ MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */ MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/ MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */ }; struct pracc_queue_info ctx = {.max_code = 37 * 2 + 7 + 1}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */ for (int i = 2; i < 32; i++) { if (LOWER16((regs[i])) == 0) /* if lower half word is 0, lui instruction only */ pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); else if (UPPER16((regs[i])) == 0) /* if upper half word is 0, ori with $0 only*/ pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i])))); else { /* default, load with lui and ori instructions */ pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i])))); } } for (int i = 0; i != 6; i++) { pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32])))); /* load CPO value in $1, with lui and ori */ pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32])))); pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ } pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); ejtag_info->reg8 = regs[8]; ejtag_info->reg9 = regs[9]; exit: pracc_queue_free(&ctx); return ctx.retval; } int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { static int cp0_read_code[] = { MIPS32_MFC0(8, 12, 0), /* move status to $8 */ MIPS32_MFLO(8), /* move lo to $8 */ MIPS32_MFHI(8), /* move hi to $8 */ MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */ MIPS32_MFC0(8, 13, 0), /* move cause to $8 */ MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */ }; struct pracc_queue_info ctx = {.max_code = 49}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4), MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1)); for (int i = 0; i != 6; i++) { pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */ MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1)); } pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */ MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1)); pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ if (ejtag_info->mode == 0) ctx.store_count++; /* Needed by legacy code, due to offset from reg0 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs); ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */ ejtag_info->reg9 = regs[9]; exit: pracc_queue_free(&ctx); return ctx.retval; } /* fastdata upload/download requires an initialized working area * to load the download code; it should not be called otherwise * fetch order from the fastdata area * 1. start addr * 2. end addr * 3. data ... */ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, int write_t, uint32_t addr, int count, uint32_t *buf) { uint32_t handler_code[] = { /* caution when editing, table is modified below */ /* r15 points to the start of this code */ MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), /* start of fastdata area in t0 */ MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_LW(9, 0, 8), /* start addr in t1 */ MIPS32_LW(10, 0, 8), /* end addr to t2 */ /* loop: */ /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */ /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */ MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)), MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)), MIPS32_JR(15), /* jr start */ MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ }; uint32_t jmp_code[] = { /* 0 */ MIPS32_LUI(15, 0), /* addr of working area added below */ /* 1 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */ MIPS32_JR(15), /* jump to ram program */ MIPS32_NOP, }; int retval, i; uint32_t val, ejtag_ctrl, address; if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (write_t) { handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */ handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */ } else { handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */ handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */ } /* write program into RAM */ if (write_t != ejtag_info->fast_access_save) { mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); /* save previous operation to speed to any consecutive read/writes */ ejtag_info->fast_access_save = write_t; } LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address); jmp_code[0] |= UPPER16(source->address); jmp_code[1] |= LOWER16(source->address); for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) { retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]); /* Clear the access pending bit (let the processor eat!) */ ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); } /* wait PrAcc pending bit for FASTDATA write */ retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; /* next fetch to dmseg should be in FASTDATA_AREA, check */ address = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); retval = mips_ejtag_drscan_32(ejtag_info, &address); if (retval != ERROR_OK) return retval; if (address != MIPS32_PRACC_FASTDATA_AREA) return ERROR_FAIL; /* Send the load start address */ val = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; /* Send the load end address */ val = addr + (count - 1) * 4; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); unsigned num_clocks = 0; /* like in legacy code */ if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; for (i = 0; i < count; i++) { jtag_add_clocks(num_clocks); retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); if (retval != ERROR_OK) return retval; } retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("fastdata load failed"); return retval; } retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); if (retval != ERROR_OK) return retval; address = 0; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); retval = mips_ejtag_drscan_32(ejtag_info, &address); if (retval != ERROR_OK) return retval; if (address != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); return retval; } openocd-0.9.0/src/target/mips32_pracc.h0000644000175000017500000001074712516456304014622 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * Copyright (C) 2011 by Drasko DRASKOVIC * * drasko.draskovic@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MIPS32_PRACC_H #define MIPS32_PRACC_H #include #include #define MIPS32_PRACC_FASTDATA_AREA 0xFF200000 #define MIPS32_PRACC_FASTDATA_SIZE 16 #define MIPS32_PRACC_BASE_ADDR 0xFF200000 #define MIPS32_PRACC_TEXT 0xFF200200 #define MIPS32_PRACC_PARAM_OUT 0xFF202000 #define PRACC_UPPER_BASE_ADDR (MIPS32_PRACC_BASE_ADDR >> 16) #define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR) #define MIPS32_FASTDATA_HANDLER_SIZE 0x80 #define UPPER16(uint32_t) (uint32_t >> 16) #define LOWER16(uint32_t) (uint32_t & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ struct pracc_queue_info { int retval; const int max_code; int code_count; int store_count; uint32_t *pracc_list; /* Code and store addresses */ }; void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); void pracc_queue_free(struct pracc_queue_info *ctx); int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf); int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf); int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf); int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, int write_t, uint32_t addr, int count, uint32_t *buf); int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out); /** * \b mips32_cp0_read * * Simulates mfc0 ASM instruction (Move From C0), * i.e. implements copro C0 Register read. * * @param[in] ejtag_info * @param[in] val Storage to hold read value * @param[in] cp0_reg Number of copro C0 register we want to read * @param[in] cp0_sel Select for the given C0 register * * @return ERROR_OK on Sucess, ERROR_FAIL otherwise */ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel); /** * \b mips32_cp0_write * * Simulates mtc0 ASM instruction (Move To C0), * i.e. implements copro C0 Register read. * * @param[in] ejtag_info * @param[in] val Value to be written * @param[in] cp0_reg Number of copro C0 register we want to write to * @param[in] cp0_sel Select for the given C0 register * * @return ERROR_OK on Sucess, ERROR_FAIL otherwise */ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); #endif openocd-0.9.0/src/target/armv4_5_cache.c0000644000175000017500000000776712315575361014742 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "armv4_5_cache.h" #include int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common *cache) { int size, assoc, M, len, multiplier; cache->ctype = (cache_type_reg & 0x1e000000U) >> 25; cache->separate = (cache_type_reg & 0x01000000U) >> 24; size = (cache_type_reg & 0x1c0000) >> 18; assoc = (cache_type_reg & 0x38000) >> 15; M = (cache_type_reg & 0x4000) >> 14; len = (cache_type_reg & 0x3000) >> 12; multiplier = 2 + M; if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ { /* cache is present */ cache->d_u_size.linelen = 1 << (len + 3); cache->d_u_size.associativity = multiplier << (assoc - 1); cache->d_u_size.nsets = 1 << (size + 6 - assoc - len); cache->d_u_size.cachesize = multiplier << (size + 8); } else { /* cache is absent */ cache->d_u_size.linelen = -1; cache->d_u_size.associativity = -1; cache->d_u_size.nsets = -1; cache->d_u_size.cachesize = -1; } if (cache->separate) { size = (cache_type_reg & 0x1c0) >> 6; assoc = (cache_type_reg & 0x38) >> 3; M = (cache_type_reg & 0x4) >> 2; len = (cache_type_reg & 0x3); multiplier = 2 + M; if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ { /* cache is present */ cache->i_size.linelen = 1 << (len + 3); cache->i_size.associativity = multiplier << (assoc - 1); cache->i_size.nsets = 1 << (size + 6 - assoc - len); cache->i_size.cachesize = multiplier << (size + 8); } else { /* cache is absent */ cache->i_size.linelen = -1; cache->i_size.associativity = -1; cache->i_size.nsets = -1; cache->i_size.cachesize = -1; } } else cache->i_size = cache->d_u_size; return ERROR_OK; } int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx, struct armv4_5_cache_common *armv4_5_cache) { if (armv4_5_cache->ctype == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } command_print(cmd_ctx, "cache type: 0x%1.1x, %s", armv4_5_cache->ctype, (armv4_5_cache->separate) ? "separate caches" : "unified cache"); command_print(cmd_ctx, "D-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x", armv4_5_cache->d_u_size.linelen, armv4_5_cache->d_u_size.associativity, armv4_5_cache->d_u_size.nsets, armv4_5_cache->d_u_size.cachesize); command_print(cmd_ctx, "I-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x", armv4_5_cache->i_size.linelen, armv4_5_cache->i_size.associativity, armv4_5_cache->i_size.nsets, armv4_5_cache->i_size.cachesize); return ERROR_OK; } openocd-0.9.0/src/target/armv4_5_cache.h0000644000175000017500000000455112315575361014733 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARMV4_5_CACHE_H #define ARMV4_5_CACHE_H struct command_context; struct armv4_5_cachesize { int linelen; int associativity; int nsets; int cachesize; }; struct armv4_5_cache_common { int ctype; /* specify supported cache operations */ int separate; /* separate caches or unified cache */ struct armv4_5_cachesize d_u_size; /* data cache */ struct armv4_5_cachesize i_size; /* instruction cache */ int i_cache_enabled; int d_u_cache_enabled; }; int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common *cache); int armv4_5_cache_state(uint32_t cp15_control_reg, struct armv4_5_cache_common *cache); int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx, struct armv4_5_cache_common *armv4_5_cache); enum { ARMV4_5_D_U_CACHE_ENABLED = 0x4, ARMV4_5_I_CACHE_ENABLED = 0x1000, ARMV4_5_WRITE_BUFFER_ENABLED = 0x8, ARMV4_5_CACHE_RR_BIT = 0x5000, }; #endif /* ARMV4_5_CACHE_H */ openocd-0.9.0/src/target/armv7m_trace.c0000644000175000017500000002310012516456303014701 00000000000000/*************************************************************************** * Copyright (C) 2015 Paul Fertser * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #define TRACE_BUF_SIZE 4096 static int armv7m_poll_trace(void *target) { struct armv7m_common *armv7m = target_to_armv7m(target); uint8_t buf[TRACE_BUF_SIZE]; size_t size = sizeof(buf); int retval; retval = adapter_poll_trace(buf, &size); if (retval != ERROR_OK || !size) return retval; if (fwrite(buf, 1, size, armv7m->trace_config.trace_file) == size) fflush(armv7m->trace_config.trace_file); else { LOG_ERROR("Error writing to the trace destination file"); return ERROR_FAIL; } return ERROR_OK; } int armv7m_trace_tpiu_config(struct target *target) { struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_trace_config *trace_config = &armv7m->trace_config; int prescaler; int retval; target_unregister_timer_callback(armv7m_poll_trace, target); retval = adapter_config_trace(trace_config->config_type == INTERNAL, trace_config->pin_protocol, trace_config->port_size, &trace_config->trace_freq); if (retval != ERROR_OK) return retval; if (!trace_config->trace_freq) { LOG_ERROR("Trace port frequency is 0, can't enable TPIU"); return ERROR_FAIL; } prescaler = trace_config->traceclkin_freq / trace_config->trace_freq; if (trace_config->traceclkin_freq % trace_config->trace_freq) { prescaler++; int trace_freq = trace_config->traceclkin_freq / prescaler; LOG_INFO("Can not obtain %u trace port frequency from %u TRACECLKIN frequency, using %u instead", trace_config->trace_freq, trace_config->traceclkin_freq, trace_freq); trace_config->trace_freq = trace_freq; retval = adapter_config_trace(trace_config->config_type == INTERNAL, trace_config->pin_protocol, trace_config->port_size, &trace_config->trace_freq); if (retval != ERROR_OK) return retval; } retval = target_write_u32(target, TPIU_CSPSR, 1 << trace_config->port_size); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, TPIU_ACPR, prescaler - 1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, TPIU_SPPR, trace_config->pin_protocol); if (retval != ERROR_OK) return retval; uint32_t ffcr; retval = target_read_u32(target, TPIU_FFCR, &ffcr); if (retval != ERROR_OK) return retval; if (trace_config->formatter) ffcr |= (1 << 1); else ffcr &= ~(1 << 1); retval = target_write_u32(target, TPIU_FFCR, ffcr); if (retval != ERROR_OK) return retval; if (trace_config->config_type == INTERNAL) target_register_timer_callback(armv7m_poll_trace, 1, 1, target); target_call_event_callbacks(target, TARGET_EVENT_TRACE_CONFIG); return ERROR_OK; } int armv7m_trace_itm_config(struct target *target) { struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_trace_config *trace_config = &armv7m->trace_config; int retval; retval = target_write_u32(target, ITM_LAR, ITM_LAR_KEY); if (retval != ERROR_OK) return retval; /* Enable ITM, TXENA, set TraceBusID and other parameters */ retval = target_write_u32(target, ITM_TCR, (1 << 0) | (1 << 3) | (trace_config->itm_diff_timestamps << 1) | (trace_config->itm_synchro_packets << 2) | (trace_config->itm_async_timestamps << 4) | (trace_config->itm_ts_prescale << 8) | (trace_config->trace_bus_id << 16)); if (retval != ERROR_OK) return retval; for (unsigned int i = 0; i < 8; i++) { retval = target_write_u32(target, ITM_TER0 + i * 4, trace_config->itm_ter[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static void close_trace_file(struct armv7m_common *armv7m) { if (armv7m->trace_config.trace_file) fclose(armv7m->trace_config.trace_file); armv7m->trace_config.trace_file = NULL; } COMMAND_HANDLER(handle_tpiu_config_command) { struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); unsigned int cmd_idx = 0; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; if (!strcmp(CMD_ARGV[cmd_idx], "disable")) { if (CMD_ARGC == cmd_idx + 1) { close_trace_file(armv7m); armv7m->trace_config.config_type = DISABLED; if (CMD_CTX->mode == COMMAND_EXEC) return armv7m_trace_tpiu_config(target); else return ERROR_OK; } } else if (!strcmp(CMD_ARGV[cmd_idx], "external") || !strcmp(CMD_ARGV[cmd_idx], "internal")) { close_trace_file(armv7m); armv7m->trace_config.config_type = EXTERNAL; if (!strcmp(CMD_ARGV[cmd_idx], "internal")) { cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; armv7m->trace_config.config_type = INTERNAL; armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab"); if (!armv7m->trace_config.trace_file) { LOG_ERROR("Can't open trace destination file"); return ERROR_FAIL; } } cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; if (!strcmp(CMD_ARGV[cmd_idx], "sync")) { armv7m->trace_config.pin_protocol = SYNC; cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[cmd_idx], armv7m->trace_config.port_size); } else { if (!strcmp(CMD_ARGV[cmd_idx], "manchester")) armv7m->trace_config.pin_protocol = ASYNC_MANCHESTER; else if (!strcmp(CMD_ARGV[cmd_idx], "uart")) armv7m->trace_config.pin_protocol = ASYNC_UART; else return ERROR_COMMAND_SYNTAX_ERROR; cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ON_OFF(CMD_ARGV[cmd_idx], armv7m->trace_config.formatter); } cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.traceclkin_freq); cmd_idx++; if (CMD_ARGC != cmd_idx) { COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.trace_freq); cmd_idx++; } else { if (armv7m->trace_config.config_type != INTERNAL) { LOG_ERROR("Trace port frequency can't be omitted in external capture mode"); return ERROR_COMMAND_SYNTAX_ERROR; } armv7m->trace_config.trace_freq = 0; } if (CMD_ARGC == cmd_idx) { if (CMD_CTX->mode == COMMAND_EXEC) return armv7m_trace_tpiu_config(target); else return ERROR_OK; } } return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(handle_itm_port_command) { struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); unsigned int reg_idx; uint8_t port; bool enable; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], port); COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable); reg_idx = port / 32; port = port % 32; if (enable) armv7m->trace_config.itm_ter[reg_idx] |= (1 << port); else armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port); if (CMD_CTX->mode == COMMAND_EXEC) return armv7m_trace_itm_config(target); else return ERROR_OK; } COMMAND_HANDLER(handle_itm_ports_command) { struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); bool enable; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0, sizeof(armv7m->trace_config.itm_ter)); if (CMD_CTX->mode == COMMAND_EXEC) return armv7m_trace_itm_config(target); else return ERROR_OK; } static const struct command_registration tpiu_command_handlers[] = { { .name = "config", .handler = handle_tpiu_config_command, .mode = COMMAND_ANY, .help = "Configure TPIU features", .usage = "(disable | " "((external | internal ) " "(sync | ((manchester | uart) )) " " []))", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration itm_command_handlers[] = { { .name = "port", .handler = handle_itm_port_command, .mode = COMMAND_ANY, .help = "Enable or disable ITM stimulus port", .usage = " (0|1|on|off)", }, { .name = "ports", .handler = handle_itm_ports_command, .mode = COMMAND_ANY, .help = "Enable or disable all ITM stimulus ports", .usage = "(0|1|on|off)", }, COMMAND_REGISTRATION_DONE }; const struct command_registration armv7m_trace_command_handlers[] = { { .name = "tpiu", .mode = COMMAND_ANY, .help = "tpiu command group", .usage = "", .chain = tpiu_command_handlers, }, { .name = "itm", .mode = COMMAND_ANY, .help = "itm command group", .usage = "", .chain = itm_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/armv7m_trace.h0000644000175000017500000000632312516456303014716 00000000000000/*************************************************************************** * Copyright (C) 2015 Paul Fertser * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifndef ARMV7M_TRACE_H #define ARMV7M_TRACE_H #include #include /** * @file * Holds the interface to TPIU, ITM and DWT configuration functions. */ enum trace_config_type { DISABLED, /**< tracing is disabled */ EXTERNAL, /**< trace output is captured externally */ INTERNAL /**< trace output is handled by OpenOCD adapter driver */ }; enum tpio_pin_protocol { SYNC, /**< synchronous trace output */ ASYNC_MANCHESTER, /**< asynchronous output with Manchester coding */ ASYNC_UART /**< asynchronous output with NRZ coding */ }; enum itm_ts_prescaler { ITM_TS_PRESCALE1, /**< no prescaling for the timestamp counter */ ITM_TS_PRESCALE4, /**< refclock divided by 4 for the timestamp counter */ ITM_TS_PRESCALE16, /**< refclock divided by 16 for the timestamp counter */ ITM_TS_PRESCALE64, /**< refclock divided by 64 for the timestamp counter */ }; struct armv7m_trace_config { /** Currently active trace capture mode */ enum trace_config_type config_type; /** Currently active trace output mode */ enum tpio_pin_protocol pin_protocol; /** TPIU formatter enable/disable (in async mode) */ bool formatter; /** Synchronous output port width */ uint32_t port_size; /** Bitmask of currenty enabled ITM stimuli */ uint32_t itm_ter[8]; /** Identifier for multi-source trace stream formatting */ unsigned int trace_bus_id; /** Prescaler for the timestamp counter */ enum itm_ts_prescaler itm_ts_prescale; /** Enable differential timestamps */ bool itm_diff_timestamps; /** Enable async timestamps model */ bool itm_async_timestamps; /** Enable synchronisation packet transmission (for sync port only) */ bool itm_synchro_packets; /** Current frequency of TRACECLKIN (usually matches HCLK) */ unsigned int traceclkin_freq; /** Current frequency of trace port */ unsigned int trace_freq; /** Handle to output trace data in INTERNAL capture mode */ FILE *trace_file; }; extern const struct command_registration armv7m_trace_command_handlers[]; /** * Configure hardware accordingly to the current TPIU target settings */ int armv7m_trace_tpiu_config(struct target *target); /** * Configure hardware accordingly to the current ITM target settings */ int armv7m_trace_itm_config(struct target *target); #endif openocd-0.9.0/src/target/openrisc/0000755000175000017500000000000012526202226014046 500000000000000openocd-0.9.0/src/target/openrisc/or1k_du_adv.c0000644000175000017500000007177512516456304016360 00000000000000/*************************************************************************** * Copyright (C) 2013-2014 by Franck Jullien * * elec4fun@gmail.com * * * * Inspired from adv_jtag_bridge which is: * * Copyright (C) 2008-2010 Nathan Yawn * * nyawn@opencores.net * * * * And the Mohor interface version of this file which is: * * Copyright (C) 2011 by Julius Baxter * * julius@opencores.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "or1k_tap.h" #include "or1k.h" #include "or1k_du.h" #include "jsp_server.h" #include #include #define JSP_BANNER "\n\r" \ "******************************\n\r" \ "** JTAG Serial Port **\n\r" \ "******************************\n\r" \ "\n\r" #define NO_OPTION 0 /* This an option to the adv debug unit. * If this is defined, status bits will be skipped on burst * reads and writes to improve download speeds. * This option must match the RTL configured option. */ #define ADBG_USE_HISPEED 1 /* This an option to the adv debug unit. * If this is defined, the JTAG Serial Port Server is started. * This option must match the RTL configured option. */ #define ENABLE_JSP_SERVER 2 /* Define this if you intend to use the JSP in a system with multiple * devices on the JTAG chain */ #define ENABLE_JSP_MULTI 4 /* Definitions for the top-level debug unit. This really just consists * of a single register, used to select the active debug module ("chain"). */ #define DBG_MODULE_SELECT_REG_SIZE 2 #define DBG_MAX_MODULES 4 #define DC_NONE -1 #define DC_WISHBONE 0 #define DC_CPU0 1 #define DC_CPU1 2 #define DC_JSP 3 /* CPU control register bits mask */ #define DBG_CPU_CR_STALL 0x01 #define DBG_CPU_CR_RESET 0x02 /* Polynomial for the CRC calculation * Yes, it's backwards. Yes, this is on purpose. * The hardware is designed this way to save on logic and routing, * and it's really all the same to us here. */ #define ADBG_CRC_POLY 0xedb88320 /* These are for the internal registers in the Wishbone module * The first is the length of the index register, * the indexes of the various registers are defined after that. */ #define DBG_WB_REG_SEL_LEN 1 #define DBG_WB_REG_ERROR 0 /* Opcode definitions for the Wishbone module. */ #define DBG_WB_OPCODE_LEN 4 #define DBG_WB_CMD_NOP 0x0 #define DBG_WB_CMD_BWRITE8 0x1 #define DBG_WB_CMD_BWRITE16 0x2 #define DBG_WB_CMD_BWRITE32 0x3 #define DBG_WB_CMD_BREAD8 0x5 #define DBG_WB_CMD_BREAD16 0x6 #define DBG_WB_CMD_BREAD32 0x7 #define DBG_WB_CMD_IREG_WR 0x9 #define DBG_WB_CMD_IREG_SEL 0xd /* Internal register definitions for the CPU0 module. */ #define DBG_CPU0_REG_SEL_LEN 1 #define DBG_CPU0_REG_STATUS 0 /* Opcode definitions for the first CPU module. */ #define DBG_CPU0_OPCODE_LEN 4 #define DBG_CPU0_CMD_NOP 0x0 #define DBG_CPU0_CMD_BWRITE32 0x3 #define DBG_CPU0_CMD_BREAD32 0x7 #define DBG_CPU0_CMD_IREG_WR 0x9 #define DBG_CPU0_CMD_IREG_SEL 0xd /* Internal register definitions for the CPU1 module. */ #define DBG_CPU1_REG_SEL_LEN 1 #define DBG_CPU1_REG_STATUS 0 /* Opcode definitions for the second CPU module. */ #define DBG_CPU1_OPCODE_LEN 4 #define DBG_CPU1_CMD_NOP 0x0 #define DBG_CPU1_CMD_BWRITE32 0x3 #define DBG_CPU1_CMD_BREAD32 0x7 #define DBG_CPU1_CMD_IREG_WR 0x9 #define DBG_CPU1_CMD_IREG_SEL 0xd #define MAX_READ_STATUS_WAIT 10 #define MAX_READ_BUSY_RETRY 2 #define MAX_READ_CRC_RETRY 2 #define MAX_WRITE_CRC_RETRY 2 #define BURST_READ_READY 1 #define MAX_BUS_ERRORS 2 #define MAX_BURST_SIZE (4 * 1024) #define STATUS_BYTES 1 #define CRC_LEN 4 static struct or1k_du or1k_du_adv; static const char * const chain_name[] = {"WISHBONE", "CPU0", "CPU1", "JSP"}; static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in, int length_bits) { for (int i = 0; i < length_bits; i++) { uint32_t d, c; d = ((data_in >> i) & 0x1) ? 0xffffffff : 0; c = (crc & 0x1) ? 0xffffffff : 0; crc = crc >> 1; crc = crc ^ ((d ^ c) & ADBG_CRC_POLY); } return crc; } static int find_status_bit(void *_buf, int len) { int i = 0; int count = 0; int ret = -1; uint8_t *buf = _buf; while (!(buf[i] & (1 << count++)) && (i < len)) { if (count == 8) { count = 0; i++; } } if (i < len) ret = (i * 8) + count; return ret; } static int or1k_adv_jtag_init(struct or1k_jtag *jtag_info) { struct or1k_tap_ip *tap_ip = jtag_info->tap_ip; int retval = tap_ip->init(jtag_info); if (retval != ERROR_OK) { LOG_ERROR("TAP initialization failed"); return retval; } /* TAP is now configured to communicate with debug interface */ jtag_info->or1k_jtag_inited = 1; /* TAP reset - not sure what state debug module chain is in now */ jtag_info->or1k_jtag_module_selected = DC_NONE; jtag_info->current_reg_idx = malloc(DBG_MAX_MODULES * sizeof(uint8_t)); memset(jtag_info->current_reg_idx, 0, DBG_MAX_MODULES * sizeof(uint8_t)); if (or1k_du_adv.options & ADBG_USE_HISPEED) LOG_INFO("adv debug unit is configured with option ADBG_USE_HISPEED"); if (or1k_du_adv.options & ENABLE_JSP_SERVER) { if (or1k_du_adv.options & ENABLE_JSP_MULTI) LOG_INFO("adv debug unit is configured with option ENABLE_JSP_MULTI"); LOG_INFO("adv debug unit is configured with option ENABLE_JSP_SERVER"); retval = jsp_init(jtag_info, JSP_BANNER); if (retval != ERROR_OK) { LOG_ERROR("Couldn't start the JSP server"); return retval; } } LOG_DEBUG("Init done"); return ERROR_OK; } /* Selects one of the modules in the debug unit * (e.g. wishbone unit, CPU0, etc.) */ static int adbg_select_module(struct or1k_jtag *jtag_info, int chain) { if (jtag_info->or1k_jtag_module_selected == chain) return ERROR_OK; /* MSB of the data out must be set to 1, indicating a module * select command */ uint8_t data = chain | (1 << DBG_MODULE_SELECT_REG_SIZE); LOG_DEBUG("Select module: %s", chain_name[chain]); struct scan_field field; field.num_bits = (DBG_MODULE_SELECT_REG_SIZE + 1); field.out_value = &data; field.in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE); int retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; jtag_info->or1k_jtag_module_selected = chain; return ERROR_OK; } /* Set the index of the desired register in the currently selected module * 1 bit module select command * 4 bits opcode * n bits index */ static int adbg_select_ctrl_reg(struct or1k_jtag *jtag_info, uint8_t regidx) { int index_len; uint32_t opcode; uint32_t opcode_len; /* If this reg is already selected, don't do a JTAG transaction */ if (jtag_info->current_reg_idx[jtag_info->or1k_jtag_module_selected] == regidx) return ERROR_OK; switch (jtag_info->or1k_jtag_module_selected) { case DC_WISHBONE: index_len = DBG_WB_REG_SEL_LEN; opcode = DBG_WB_CMD_IREG_SEL; opcode_len = DBG_WB_OPCODE_LEN; break; case DC_CPU0: index_len = DBG_CPU0_REG_SEL_LEN; opcode = DBG_CPU0_CMD_IREG_SEL; opcode_len = DBG_CPU0_OPCODE_LEN; break; case DC_CPU1: index_len = DBG_CPU1_REG_SEL_LEN; opcode = DBG_CPU1_CMD_IREG_SEL; opcode_len = DBG_CPU1_OPCODE_LEN; break; default: LOG_ERROR("Illegal debug chain selected (%i) while selecting control register", jtag_info->or1k_jtag_module_selected); return ERROR_FAIL; } /* MSB must be 0 to access modules */ uint32_t data = (opcode & ~(1 << opcode_len)) << index_len; data |= regidx; struct scan_field field; field.num_bits = (opcode_len + 1) + index_len; field.out_value = (uint8_t *)&data; field.in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE); int retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; jtag_info->current_reg_idx[jtag_info->or1k_jtag_module_selected] = regidx; return ERROR_OK; } /* Write control register (internal to the debug unit) */ static int adbg_ctrl_write(struct or1k_jtag *jtag_info, uint8_t regidx, uint32_t *cmd_data, int length_bits) { int index_len; uint32_t opcode; uint32_t opcode_len; LOG_DEBUG("Write control register %" PRId8 ": 0x%08" PRIx32, regidx, cmd_data[0]); int retval = adbg_select_ctrl_reg(jtag_info, regidx); if (retval != ERROR_OK) { LOG_ERROR("Error while calling adbg_select_ctrl_reg"); return retval; } switch (jtag_info->or1k_jtag_module_selected) { case DC_WISHBONE: index_len = DBG_WB_REG_SEL_LEN; opcode = DBG_WB_CMD_IREG_WR; opcode_len = DBG_WB_OPCODE_LEN; break; case DC_CPU0: index_len = DBG_CPU0_REG_SEL_LEN; opcode = DBG_CPU0_CMD_IREG_WR; opcode_len = DBG_CPU0_OPCODE_LEN; break; case DC_CPU1: index_len = DBG_CPU1_REG_SEL_LEN; opcode = DBG_CPU1_CMD_IREG_WR; opcode_len = DBG_CPU1_OPCODE_LEN; break; default: LOG_ERROR("Illegal debug chain selected (%i) while doing control write", jtag_info->or1k_jtag_module_selected); return ERROR_FAIL; } struct scan_field field[2]; /* MSB must be 0 to access modules */ uint32_t data = (opcode & ~(1 << opcode_len)) << index_len; data |= regidx; field[0].num_bits = length_bits; field[0].out_value = (uint8_t *)cmd_data; field[0].in_value = NULL; field[1].num_bits = (opcode_len + 1) + index_len; field[1].out_value = (uint8_t *)&data; field[1].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE); return jtag_execute_queue(); } /* Reads control register (internal to the debug unit) */ static int adbg_ctrl_read(struct or1k_jtag *jtag_info, uint32_t regidx, uint32_t *data, int length_bits) { int retval = adbg_select_ctrl_reg(jtag_info, regidx); if (retval != ERROR_OK) { LOG_ERROR("Error while calling adbg_select_ctrl_reg"); return retval; } int opcode_len; uint32_t opcode; /* There is no 'read' command, We write a NOP to read */ switch (jtag_info->or1k_jtag_module_selected) { case DC_WISHBONE: opcode = DBG_WB_CMD_NOP; opcode_len = DBG_WB_OPCODE_LEN; break; case DC_CPU0: opcode = DBG_CPU0_CMD_NOP; opcode_len = DBG_CPU0_OPCODE_LEN; break; case DC_CPU1: opcode = DBG_CPU1_CMD_NOP; opcode_len = DBG_CPU1_OPCODE_LEN; break; default: LOG_ERROR("Illegal debug chain selected (%i) while doing control read", jtag_info->or1k_jtag_module_selected); return ERROR_FAIL; } /* Zero MSB = op for module, not top-level debug unit */ uint32_t outdata = opcode & ~(0x1 << opcode_len); struct scan_field field[2]; field[0].num_bits = length_bits; field[0].out_value = NULL; field[0].in_value = (uint8_t *)data; field[1].num_bits = opcode_len + 1; field[1].out_value = (uint8_t *)&outdata; field[1].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE); return jtag_execute_queue(); } /* sends out a burst command to the selected module in the debug unit (MSB to LSB): * 1-bit module command * 4-bit opcode * 32-bit address * 16-bit length (of the burst, in words) */ static int adbg_burst_command(struct or1k_jtag *jtag_info, uint32_t opcode, uint32_t address, uint16_t length_words) { uint32_t data[2]; /* Set up the data */ data[0] = length_words | (address << 16); /* MSB must be 0 to access modules */ data[1] = ((address >> 16) | ((opcode & 0xf) << 16)) & ~(0x1 << 20); struct scan_field field; field.num_bits = 53; field.out_value = (uint8_t *)&data[0]; field.in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE); return jtag_execute_queue(); } static int adbg_wb_burst_read(struct or1k_jtag *jtag_info, int size, int count, uint32_t start_address, uint8_t *data) { int retry_full_crc = 0; int retry_full_busy = 0; int retval; uint8_t opcode; LOG_DEBUG("Doing burst read, word size %d, word count %d, start address 0x%08" PRIx32, size, count, start_address); /* Select the appropriate opcode */ switch (jtag_info->or1k_jtag_module_selected) { case DC_WISHBONE: if (size == 1) opcode = DBG_WB_CMD_BREAD8; else if (size == 2) opcode = DBG_WB_CMD_BREAD16; else if (size == 4) opcode = DBG_WB_CMD_BREAD32; else { LOG_WARNING("Tried burst read with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_WB_CMD_BREAD32; } break; case DC_CPU0: if (size == 4) opcode = DBG_CPU0_CMD_BREAD32; else { LOG_WARNING("Tried burst read with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_CPU0_CMD_BREAD32; } break; case DC_CPU1: if (size == 4) opcode = DBG_CPU1_CMD_BREAD32; else { LOG_WARNING("Tried burst read with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_CPU0_CMD_BREAD32; } break; default: LOG_ERROR("Illegal debug chain selected (%i) while doing burst read", jtag_info->or1k_jtag_module_selected); return ERROR_FAIL; } int total_size_bytes = count * size; struct scan_field field; uint8_t *in_buffer = malloc(total_size_bytes + CRC_LEN + STATUS_BYTES); retry_read_full: /* Send the BURST READ command, returns TAP to idle state */ retval = adbg_burst_command(jtag_info, opcode, start_address, count); if (retval != ERROR_OK) goto out; field.num_bits = (total_size_bytes + CRC_LEN + STATUS_BYTES) * 8; field.out_value = NULL; field.in_value = in_buffer; jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) goto out; /* Look for the start bit in the first (STATUS_BYTES * 8) bits */ int shift = find_status_bit(in_buffer, STATUS_BYTES); /* We expect the status bit to be in the first byte */ if (shift < 0) { if (retry_full_busy++ < MAX_READ_BUSY_RETRY) { LOG_WARNING("Burst read timed out"); goto retry_read_full; } else { LOG_ERROR("Burst read failed"); retval = ERROR_FAIL; goto out; } } buffer_shr(in_buffer, total_size_bytes + CRC_LEN + STATUS_BYTES, shift); uint32_t crc_read; memcpy(data, in_buffer, total_size_bytes); memcpy(&crc_read, &in_buffer[total_size_bytes], 4); uint32_t crc_calc = 0xffffffff; for (int i = 0; i < total_size_bytes; i++) crc_calc = adbg_compute_crc(crc_calc, data[i], 8); if (crc_calc != crc_read) { LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 0x%08" PRIx32, crc_calc, crc_read); if (retry_full_crc++ < MAX_READ_CRC_RETRY) goto retry_read_full; else { LOG_ERROR("Burst read failed"); retval = ERROR_FAIL; goto out; } } else LOG_DEBUG("CRC OK!"); /* Now, read the error register, and retry/recompute as necessary */ if (jtag_info->or1k_jtag_module_selected == DC_WISHBONE && !(or1k_du_adv.options & ADBG_USE_HISPEED)) { uint32_t err_data[2] = {0, 0}; uint32_t addr; int bus_error_retries = 0; /* First, just get 1 bit...read address only if necessary */ retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 1); if (retval != ERROR_OK) goto out; /* Then we have a problem */ if (err_data[0] & 0x1) { retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 33); if (retval != ERROR_OK) goto out; addr = (err_data[0] >> 1) | (err_data[1] << 31); LOG_WARNING("WB bus error during burst read, address 0x%08" PRIx32 ", retrying!", addr); bus_error_retries++; if (bus_error_retries > MAX_BUS_ERRORS) { LOG_ERROR("Max WB bus errors reached during burst read"); retval = ERROR_FAIL; goto out; } /* Don't call retry_do(), a JTAG reset won't help a WB bus error */ /* Write 1 bit, to reset the error register */ err_data[0] = 1; retval = adbg_ctrl_write(jtag_info, DBG_WB_REG_ERROR, err_data, 1); if (retval != ERROR_OK) goto out; goto retry_read_full; } } out: free(in_buffer); return retval; } /* Set up and execute a burst write to a contiguous set of addresses */ static int adbg_wb_burst_write(struct or1k_jtag *jtag_info, const uint8_t *data, int size, int count, unsigned long start_address) { int retry_full_crc = 0; int retval; uint8_t opcode; LOG_DEBUG("Doing burst write, word size %d, word count %d," "start address 0x%08lx", size, count, start_address); /* Select the appropriate opcode */ switch (jtag_info->or1k_jtag_module_selected) { case DC_WISHBONE: if (size == 1) opcode = DBG_WB_CMD_BWRITE8; else if (size == 2) opcode = DBG_WB_CMD_BWRITE16; else if (size == 4) opcode = DBG_WB_CMD_BWRITE32; else { LOG_DEBUG("Tried WB burst write with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_WB_CMD_BWRITE32; } break; case DC_CPU0: if (size == 4) opcode = DBG_CPU0_CMD_BWRITE32; else { LOG_DEBUG("Tried CPU0 burst write with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_CPU0_CMD_BWRITE32; } break; case DC_CPU1: if (size == 4) opcode = DBG_CPU1_CMD_BWRITE32; else { LOG_DEBUG("Tried CPU1 burst write with invalid word size (%d)," "defaulting to 4-byte words", size); opcode = DBG_CPU0_CMD_BWRITE32; } break; default: LOG_ERROR("Illegal debug chain selected (%i) while doing burst write", jtag_info->or1k_jtag_module_selected); return ERROR_FAIL; } retry_full_write: /* Send the BURST WRITE command, returns TAP to idle state */ retval = adbg_burst_command(jtag_info, opcode, start_address, count); if (retval != ERROR_OK) return retval; struct scan_field field[3]; /* Write a start bit so it knows when to start counting */ uint8_t value = 1; field[0].num_bits = 1; field[0].out_value = &value; field[0].in_value = NULL; uint32_t crc_calc = 0xffffffff; for (int i = 0; i < (count * size); i++) crc_calc = adbg_compute_crc(crc_calc, data[i], 8); field[1].num_bits = count * size * 8; field[1].out_value = data; field[1].in_value = NULL; field[2].num_bits = 32; field[2].out_value = (uint8_t *)&crc_calc; field[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, field, TAP_DRSHIFT); /* Read the 'CRC match' bit, and go to idle */ field[0].num_bits = 1; field[0].out_value = NULL; field[0].in_value = &value; jtag_add_dr_scan(jtag_info->tap, 1, field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (!value) { LOG_WARNING("CRC ERROR! match bit after write is %" PRIi8 " (computed CRC 0x%08" PRIx32 ")", value, crc_calc); if (retry_full_crc++ < MAX_WRITE_CRC_RETRY) goto retry_full_write; else return ERROR_FAIL; } else LOG_DEBUG("CRC OK!\n"); /* Now, read the error register, and retry/recompute as necessary */ if (jtag_info->or1k_jtag_module_selected == DC_WISHBONE && !(or1k_du_adv.options & ADBG_USE_HISPEED)) { uint32_t addr; int bus_error_retries = 0; uint32_t err_data[2] = {0, 0}; /* First, just get 1 bit...read address only if necessary */ retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 1); if (retval != ERROR_OK) return retval; /* Then we have a problem */ if (err_data[0] & 0x1) { retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 33); if (retval != ERROR_OK) return retval; addr = (err_data[0] >> 1) | (err_data[1] << 31); LOG_WARNING("WB bus error during burst write, address 0x%08" PRIx32 ", retrying!", addr); bus_error_retries++; if (bus_error_retries > MAX_BUS_ERRORS) { LOG_ERROR("Max WB bus errors reached during burst read"); retval = ERROR_FAIL; return retval; } /* Don't call retry_do(), a JTAG reset won't help a WB bus error */ /* Write 1 bit, to reset the error register */ err_data[0] = 1; retval = adbg_ctrl_write(jtag_info, DBG_WB_REG_ERROR, err_data, 1); if (retval != ERROR_OK) return retval; goto retry_full_write; } } return ERROR_OK; } /* Currently hard set in functions to 32-bits */ static int or1k_adv_jtag_read_cpu(struct or1k_jtag *jtag_info, uint32_t addr, int count, uint32_t *value) { int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; return adbg_wb_burst_read(jtag_info, 4, count, addr, (uint8_t *)value); } static int or1k_adv_jtag_write_cpu(struct or1k_jtag *jtag_info, uint32_t addr, int count, const uint32_t *value) { int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; return adbg_wb_burst_write(jtag_info, (uint8_t *)value, 4, count, addr); } static int or1k_adv_cpu_stall(struct or1k_jtag *jtag_info, int action) { int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; uint32_t cpu_cr; retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2); if (retval != ERROR_OK) return retval; if (action == CPU_STALL) cpu_cr |= DBG_CPU_CR_STALL; else cpu_cr &= ~DBG_CPU_CR_STALL; retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; return adbg_ctrl_write(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2); } static int or1k_adv_is_cpu_running(struct or1k_jtag *jtag_info, int *running) { int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } int current = jtag_info->or1k_jtag_module_selected; retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; uint32_t cpu_cr = 0; retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2); if (retval != ERROR_OK) return retval; if (cpu_cr & DBG_CPU_CR_STALL) *running = 0; else *running = 1; if (current != DC_NONE) { retval = adbg_select_module(jtag_info, current); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int or1k_adv_cpu_reset(struct or1k_jtag *jtag_info, int action) { int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; uint32_t cpu_cr; retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2); if (retval != ERROR_OK) return retval; if (action == CPU_RESET) cpu_cr |= DBG_CPU_CR_RESET; else cpu_cr &= ~DBG_CPU_CR_RESET; retval = adbg_select_module(jtag_info, DC_CPU0); if (retval != ERROR_OK) return retval; return adbg_ctrl_write(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2); } static int or1k_adv_jtag_read_memory(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size, int count, uint8_t *buffer) { LOG_DEBUG("Reading WB%" PRId32 " at 0x%08" PRIx32, size * 8, addr); int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_WISHBONE); if (retval != ERROR_OK) return retval; int block_count_left = count; uint32_t block_count_address = addr; uint8_t *block_count_buffer = buffer; while (block_count_left) { int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ? MAX_BURST_SIZE : block_count_left; retval = adbg_wb_burst_read(jtag_info, size, blocks_this_round, block_count_address, block_count_buffer); if (retval != ERROR_OK) return retval; block_count_left -= blocks_this_round; block_count_address += size * MAX_BURST_SIZE; block_count_buffer += size * MAX_BURST_SIZE; } /* The adv_debug_if always return words and half words in * little-endian order no matter what the target endian is. * So if the target endian is big, change the order. */ struct target *target = jtag_info->target; if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) { switch (size) { case 4: buf_bswap32(buffer, buffer, size * count); break; case 2: buf_bswap16(buffer, buffer, size * count); break; } } return ERROR_OK; } static int or1k_adv_jtag_write_memory(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size, int count, const uint8_t *buffer) { LOG_DEBUG("Writing WB%" PRId32 " at 0x%08" PRIx32, size * 8, addr); int retval; if (!jtag_info->or1k_jtag_inited) { retval = or1k_adv_jtag_init(jtag_info); if (retval != ERROR_OK) return retval; } retval = adbg_select_module(jtag_info, DC_WISHBONE); if (retval != ERROR_OK) return retval; /* The adv_debug_if wants words and half words in little-endian * order no matter what the target endian is. So if the target * endian is big, change the order. */ void *t = NULL; struct target *target = jtag_info->target; if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) { t = malloc(count * size * sizeof(uint8_t)); if (t == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } switch (size) { case 4: buf_bswap32(t, buffer, size * count); break; case 2: buf_bswap16(t, buffer, size * count); break; } buffer = t; } int block_count_left = count; uint32_t block_count_address = addr; uint8_t *block_count_buffer = (uint8_t *)buffer; while (block_count_left) { int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ? MAX_BURST_SIZE : block_count_left; retval = adbg_wb_burst_write(jtag_info, block_count_buffer, size, blocks_this_round, block_count_address); if (retval != ERROR_OK) { if (t != NULL) free(t); return retval; } block_count_left -= blocks_this_round; block_count_address += size * MAX_BURST_SIZE; block_count_buffer += size * MAX_BURST_SIZE; } if (t != NULL) free(t); return ERROR_OK; } int or1k_adv_jtag_jsp_xfer(struct or1k_jtag *jtag_info, int *out_len, unsigned char *out_buffer, int *in_len, unsigned char *in_buffer) { LOG_DEBUG("JSP transfert"); int retval; if (!jtag_info->or1k_jtag_inited) return ERROR_OK; retval = adbg_select_module(jtag_info, DC_JSP); if (retval != ERROR_OK) return retval; /* return nb char xmit */ int xmitsize; if (*out_len > 8) xmitsize = 8; else xmitsize = *out_len; uint8_t out_data[10]; uint8_t in_data[10]; struct scan_field field; int startbit, stopbit, wrapbit; memset(out_data, 0, 10); if (or1k_du_adv.options & ENABLE_JSP_MULTI) { startbit = 1; wrapbit = (xmitsize >> 3) & 0x1; out_data[0] = (xmitsize << 5) | 0x1; /* set the start bit */ int i; /* don't copy off the end of the input array */ for (i = 0; i < xmitsize; i++) { out_data[i + 1] = (out_buffer[i] << 1) | wrapbit; wrapbit = (out_buffer[i] >> 7) & 0x1; } if (i < 8) out_data[i + 1] = wrapbit; else out_data[9] = wrapbit; /* If the last data bit is a '1', then we need to append a '0' so the top-level module * won't treat the burst as a 'module select' command. */ stopbit = !!(out_data[9] & 0x01); } else { startbit = 0; /* First byte out has write count in upper nibble */ out_data[0] = 0x0 | (xmitsize << 4); if (xmitsize > 0) memcpy(&out_data[1], out_buffer, xmitsize); /* If the last data bit is a '1', then we need to append a '0' so the top-level module * won't treat the burst as a 'module select' command. */ stopbit = !!(out_data[8] & 0x80); } field.num_bits = 72 + startbit + stopbit; field.out_value = out_data; field.in_value = in_data; jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* bytes available is in the upper nibble */ *in_len = (in_data[0] >> 4) & 0xF; memcpy(in_buffer, &in_data[1], *in_len); int bytes_free = in_data[0] & 0x0F; *out_len = (bytes_free < xmitsize) ? bytes_free : xmitsize; return ERROR_OK; } static struct or1k_du or1k_du_adv = { .name = "adv", .options = NO_OPTION, .or1k_jtag_init = or1k_adv_jtag_init, .or1k_is_cpu_running = or1k_adv_is_cpu_running, .or1k_cpu_stall = or1k_adv_cpu_stall, .or1k_cpu_reset = or1k_adv_cpu_reset, .or1k_jtag_read_cpu = or1k_adv_jtag_read_cpu, .or1k_jtag_write_cpu = or1k_adv_jtag_write_cpu, .or1k_jtag_read_memory = or1k_adv_jtag_read_memory, .or1k_jtag_write_memory = or1k_adv_jtag_write_memory }; int or1k_du_adv_register(void) { list_add_tail(&or1k_du_adv.list, &du_list); return 0; } openocd-0.9.0/src/target/openrisc/or1k_tap.h0000644000175000017500000000277112516456304015675 00000000000000/*************************************************************************** * Copyright (C) 2012 by Franck Jullien * * elec4fun@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifndef _OR1K_TAP_H_ #define _OR1K_TAP_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "or1k.h" int or1k_tap_vjtag_register(void); int or1k_tap_xilinx_bscan_register(void); int or1k_tap_mohor_register(void); /* Linear list over all available or1k taps */ extern struct list_head tap_list; struct or1k_tap_ip { struct list_head list; int (*init)(struct or1k_jtag *jtag_info); const char *name; }; #endif openocd-0.9.0/src/target/openrisc/or1k_du.h0000644000175000017500000000507512516456304015521 00000000000000/*************************************************************************** * Copyright (C) 2013 Franck Jullien * * elec4fun@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifndef OR1K_DU #define OR1K_DU #ifdef HAVE_CONFIG_H #include "config.h" #endif #define CPU_STALL 0 #define CPU_UNSTALL 1 #define CPU_RESET 0 #define CPU_NOT_RESET 1 int or1k_du_adv_register(void); /* Linear list over all available or1k debug unit */ extern struct list_head du_list; struct or1k_du { const char *name; struct list_head list; int options; int (*or1k_jtag_init)(struct or1k_jtag *jtag_info); int (*or1k_is_cpu_running)(struct or1k_jtag *jtag_info, int *running); int (*or1k_cpu_stall)(struct or1k_jtag *jtag_info, int action); int (*or1k_cpu_reset)(struct or1k_jtag *jtag_info, int action); int (*or1k_jtag_read_cpu)(struct or1k_jtag *jtag_info, uint32_t addr, int count, uint32_t *value); int (*or1k_jtag_write_cpu)(struct or1k_jtag *jtag_info, uint32_t addr, int count, const uint32_t *value); int (*or1k_jtag_read_memory)(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size, int count, uint8_t *buffer); int (*or1k_jtag_write_memory)(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size, int count, const uint8_t *buffer); }; static inline struct or1k_du *or1k_jtag_to_du(struct or1k_jtag *jtag_info) { return (struct or1k_du *)jtag_info->du_core; } static inline struct or1k_du *or1k_to_du(struct or1k_common *or1k) { struct or1k_jtag *jtag = &or1k->jtag; return (struct or1k_du *)jtag->du_core; } int or1k_adv_jtag_jsp_xfer(struct or1k_jtag *jtag_info, int *out_len, unsigned char *out_buffer, int *in_len, unsigned char *in_buffer); #endif openocd-0.9.0/src/target/openrisc/jsp_server.c0000644000175000017500000001606012516456304016326 00000000000000/*************************************************************************** * Copyright (C) 2014 by Franck Jullien * * franck.jullien@gmail.com * * * * Based on ./src/server/telnet_server.c * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "or1k_tap.h" #include "or1k_du.h" #include "jsp_server.h" static char *jsp_port; /**A skim of the relevant RFCs suggests that if my application simply sent the * characters IAC DONT LINEMODE (\377\376\042) as soon as the client connects, * the client should be forced into character mode. However it doesn't make any difference. */ static const char * const negotiate = "\xFF\xFB\x03" /* IAC WILL Suppress Go Ahead */ "\xFF\xFB\x01" /* IAC WILL Echo */ "\xFF\xFD\x03" /* IAC DO Suppress Go Ahead */ "\xFF\xFE\x01"; /* IAC DON'T Echo */ /* The only way we can detect that the socket is closed is the first time * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ static int telnet_write(struct connection *connection, const void *data, int len) { struct telnet_connection *t_con = connection->priv; if (t_con->closed) return ERROR_SERVER_REMOTE_CLOSED; if (connection_write(connection, data, len) == len) return ERROR_OK; t_con->closed = 1; return ERROR_SERVER_REMOTE_CLOSED; } int jsp_poll_read(void *priv) { struct jsp_service *jsp_service = (struct jsp_service *)priv; unsigned char out_buffer[10]; unsigned char in_buffer[10]; int out_len = 0; int in_len; if (!jsp_service->connection) return ERROR_FAIL; memset(out_buffer, 0, 10); or1k_adv_jtag_jsp_xfer(jsp_service->jtag_info, &out_len, out_buffer, &in_len, in_buffer); if (in_len) telnet_write(jsp_service->connection, in_buffer, in_len); return ERROR_OK; } static int jsp_new_connection(struct connection *connection) { struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection)); struct jsp_service *jsp_service = connection->service->priv; connection->priv = telnet_connection; /* initialize telnet connection information */ telnet_connection->closed = 0; telnet_connection->line_size = 0; telnet_connection->line_cursor = 0; telnet_connection->option_size = 0; telnet_connection->state = TELNET_STATE_DATA; /* negotiate telnet options */ telnet_write(connection, negotiate, strlen(negotiate)); /* print connection banner */ if (jsp_service->banner) { telnet_write(connection, jsp_service->banner, strlen(jsp_service->banner)); telnet_write(connection, "\r\n", 2); } jsp_service->connection = connection; int retval = target_register_timer_callback(&jsp_poll_read, 1, 1, jsp_service); if (ERROR_OK != retval) return retval; return ERROR_OK; } static int jsp_input(struct connection *connection) { int bytes_read; unsigned char buffer[TELNET_BUFFER_SIZE]; unsigned char *buf_p; struct telnet_connection *t_con = connection->priv; struct jsp_service *jsp_service = connection->service->priv; bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE); if (bytes_read == 0) return ERROR_SERVER_REMOTE_CLOSED; else if (bytes_read == -1) { LOG_ERROR("error during read: %s", strerror(errno)); return ERROR_SERVER_REMOTE_CLOSED; } buf_p = buffer; while (bytes_read) { switch (t_con->state) { case TELNET_STATE_DATA: if (*buf_p == 0xff) t_con->state = TELNET_STATE_IAC; else { int out_len = 1; int in_len; unsigned char in_buffer[10]; or1k_adv_jtag_jsp_xfer(jsp_service->jtag_info, &out_len, buf_p, &in_len, in_buffer); if (in_len) telnet_write(connection, in_buffer, in_len); } break; case TELNET_STATE_IAC: switch (*buf_p) { case 0xfe: t_con->state = TELNET_STATE_DONT; break; case 0xfd: t_con->state = TELNET_STATE_DO; break; case 0xfc: t_con->state = TELNET_STATE_WONT; break; case 0xfb: t_con->state = TELNET_STATE_WILL; break; } break; case TELNET_STATE_SB: break; case TELNET_STATE_SE: break; case TELNET_STATE_WILL: case TELNET_STATE_WONT: case TELNET_STATE_DO: case TELNET_STATE_DONT: t_con->state = TELNET_STATE_DATA; break; default: LOG_ERROR("unknown telnet state"); exit(-1); } bytes_read--; buf_p++; } return ERROR_OK; } static int jsp_connection_closed(struct connection *connection) { struct telnet_connection *t_con = connection->priv; struct jsp_service *jsp_service = connection->service->priv; if (t_con->prompt) { free(t_con->prompt); t_con->prompt = NULL; } int retval = target_unregister_timer_callback(&jsp_poll_read, jsp_service); if (ERROR_OK != retval) return retval; if (connection->priv) { free(connection->priv); connection->priv = NULL; } else LOG_ERROR("BUG: connection->priv == NULL"); return ERROR_OK; } int jsp_init(struct or1k_jtag *jtag_info, char *banner) { struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service)); jsp_service->banner = banner; jsp_service->jtag_info = jtag_info; return add_service("jsp", jsp_port, 1, jsp_new_connection, jsp_input, jsp_connection_closed, jsp_service); } COMMAND_HANDLER(handle_jsp_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &jsp_port); } static const struct command_registration jsp_command_handlers[] = { { .name = "jsp_port", .handler = handle_jsp_port_command, .mode = COMMAND_ANY, .help = "Specify port on which to listen " "for incoming JSP telnet connections.", .usage = "[port_num]", }, COMMAND_REGISTRATION_DONE }; int jsp_register_commands(struct command_context *cmd_ctx) { jsp_port = strdup("7777"); return register_commands(cmd_ctx, NULL, jsp_command_handlers); } openocd-0.9.0/src/target/openrisc/jsp_server.h0000644000175000017500000000054512516456304016334 00000000000000#ifndef _JSP_SERVER_H_ #define _JSP_SERVER_H_ #include "or1k_tap.h" #include "or1k.h" #include "or1k_du.h" struct jsp_service { char *banner; struct or1k_jtag *jtag_info; struct connection *connection; }; int jsp_init(struct or1k_jtag *jtag_info, char *banner); int jsp_register_commands(struct command_context *cmd_ctx); #endif /* _JSP_SERVER_H_ */ openocd-0.9.0/src/target/openrisc/or1k_tap_mohor.c0000644000175000017500000000366312516456304017075 00000000000000/*************************************************************************** * Copyright (C) 2013 by Franck Jullien * * elec4fun@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "or1k_tap.h" #include "or1k.h" #include #define OR1K_TAP_INST_DEBUG 0x8 static int or1k_tap_mohor_init(struct or1k_jtag *jtag_info) { LOG_DEBUG("Initialising OpenCores JTAG TAP"); /* Put TAP into state where it can talk to the debug interface * by shifting in correct value to IR. */ /* Ensure TAP is reset - maybe not necessary*/ jtag_add_tlr(); struct jtag_tap *tap = jtag_info->tap; struct scan_field field; uint8_t ir_value = OR1K_TAP_INST_DEBUG; field.num_bits = tap->ir_length; field.out_value = &ir_value; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); return jtag_execute_queue(); } static struct or1k_tap_ip mohor_tap = { .name = "mohor", .init = or1k_tap_mohor_init, }; int or1k_tap_mohor_register(void) { list_add_tail(&mohor_tap.list, &tap_list); return 0; } openocd-0.9.0/src/target/openrisc/Makefile.am0000644000175000017500000000046312516456304016034 00000000000000include $(top_srcdir)/common.mk noinst_LTLIBRARIES = libopenrisc.la libopenrisc_la_SOURCES = $(OPENRISC_SRC) OPENRISC_SRC = \ or1k.c \ or1k_du_adv.c \ or1k_tap_mohor.c \ or1k_tap_vjtag.c \ or1k_tap_xilinx_bscan.c \ jsp_server.c noinst_HEADERS = \ or1k.h \ or1k_du.h \ or1k_tap.h \ jsp_server.h openocd-0.9.0/src/target/openrisc/Makefile.in0000644000175000017500000004476112526201652016051 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS) @INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \ @INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl subdir = src/target/openrisc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libopenrisc_la_LIBADD = am__objects_1 = or1k.lo or1k_du_adv.lo or1k_tap_mohor.lo \ or1k_tap_vjtag.lo or1k_tap_xilinx_bscan.lo jsp_server.lo am_libopenrisc_la_OBJECTS = $(am__objects_1) libopenrisc_la_OBJECTS = $(am_libopenrisc_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libopenrisc_la_SOURCES) DIST_SOURCES = $(libopenrisc_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" $(am__append_1) noinst_LTLIBRARIES = libopenrisc.la libopenrisc_la_SOURCES = $(OPENRISC_SRC) OPENRISC_SRC = \ or1k.c \ or1k_du_adv.c \ or1k_tap_mohor.c \ or1k_tap_vjtag.c \ or1k_tap_xilinx_bscan.c \ jsp_server.c noinst_HEADERS = \ or1k.h \ or1k_du.h \ or1k_tap.h \ jsp_server.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/target/openrisc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/target/openrisc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/common.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libopenrisc.la: $(libopenrisc_la_OBJECTS) $(libopenrisc_la_DEPENDENCIES) $(EXTRA_libopenrisc_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libopenrisc_la_OBJECTS) $(libopenrisc_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jsp_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or1k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or1k_du_adv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or1k_tap_mohor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or1k_tap_vjtag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or1k_tap_xilinx_bscan.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/src/target/openrisc/or1k.c0000644000175000017500000013261112516456304015021 00000000000000/*************************************************************************** * Copyright (C) 2011 by Julius Baxter * * julius@opencores.org * * * * Copyright (C) 2013 by Marek Czerski * * ma.czerski@gmail.com * * * * Copyright (C) 2013 by Franck Jullien * * elec4fun@gmail.com * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "or1k_tap.h" #include "or1k.h" #include "or1k_du.h" LIST_HEAD(tap_list); LIST_HEAD(du_list); static int or1k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); static int or1k_read_core_reg(struct target *target, int num); static int or1k_write_core_reg(struct target *target, int num); static struct or1k_core_reg *or1k_core_reg_list_arch_info; static const struct or1k_core_reg_init or1k_init_reg_list[] = { {"r0" , GROUP0 + 1024, "org.gnu.gdb.or1k.group0", NULL}, {"r1" , GROUP0 + 1025, "org.gnu.gdb.or1k.group0", NULL}, {"r2" , GROUP0 + 1026, "org.gnu.gdb.or1k.group0", NULL}, {"r3" , GROUP0 + 1027, "org.gnu.gdb.or1k.group0", NULL}, {"r4" , GROUP0 + 1028, "org.gnu.gdb.or1k.group0", NULL}, {"r5" , GROUP0 + 1029, "org.gnu.gdb.or1k.group0", NULL}, {"r6" , GROUP0 + 1030, "org.gnu.gdb.or1k.group0", NULL}, {"r7" , GROUP0 + 1031, "org.gnu.gdb.or1k.group0", NULL}, {"r8" , GROUP0 + 1032, "org.gnu.gdb.or1k.group0", NULL}, {"r9" , GROUP0 + 1033, "org.gnu.gdb.or1k.group0", NULL}, {"r10" , GROUP0 + 1034, "org.gnu.gdb.or1k.group0", NULL}, {"r11" , GROUP0 + 1035, "org.gnu.gdb.or1k.group0", NULL}, {"r12" , GROUP0 + 1036, "org.gnu.gdb.or1k.group0", NULL}, {"r13" , GROUP0 + 1037, "org.gnu.gdb.or1k.group0", NULL}, {"r14" , GROUP0 + 1038, "org.gnu.gdb.or1k.group0", NULL}, {"r15" , GROUP0 + 1039, "org.gnu.gdb.or1k.group0", NULL}, {"r16" , GROUP0 + 1040, "org.gnu.gdb.or1k.group0", NULL}, {"r17" , GROUP0 + 1041, "org.gnu.gdb.or1k.group0", NULL}, {"r18" , GROUP0 + 1042, "org.gnu.gdb.or1k.group0", NULL}, {"r19" , GROUP0 + 1043, "org.gnu.gdb.or1k.group0", NULL}, {"r20" , GROUP0 + 1044, "org.gnu.gdb.or1k.group0", NULL}, {"r21" , GROUP0 + 1045, "org.gnu.gdb.or1k.group0", NULL}, {"r22" , GROUP0 + 1046, "org.gnu.gdb.or1k.group0", NULL}, {"r23" , GROUP0 + 1047, "org.gnu.gdb.or1k.group0", NULL}, {"r24" , GROUP0 + 1048, "org.gnu.gdb.or1k.group0", NULL}, {"r25" , GROUP0 + 1049, "org.gnu.gdb.or1k.group0", NULL}, {"r26" , GROUP0 + 1050, "org.gnu.gdb.or1k.group0", NULL}, {"r27" , GROUP0 + 1051, "org.gnu.gdb.or1k.group0", NULL}, {"r28" , GROUP0 + 1052, "org.gnu.gdb.or1k.group0", NULL}, {"r29" , GROUP0 + 1053, "org.gnu.gdb.or1k.group0", NULL}, {"r30" , GROUP0 + 1054, "org.gnu.gdb.or1k.group0", NULL}, {"r31" , GROUP0 + 1055, "org.gnu.gdb.or1k.group0", NULL}, {"ppc" , GROUP0 + 18, "org.gnu.gdb.or1k.group0", NULL}, {"npc" , GROUP0 + 16, "org.gnu.gdb.or1k.group0", NULL}, {"sr" , GROUP0 + 17, "org.gnu.gdb.or1k.group0", NULL}, {"vr" , GROUP0 + 0, "org.gnu.gdb.or1k.group0", "system"}, {"upr" , GROUP0 + 1, "org.gnu.gdb.or1k.group0", "system"}, {"cpucfgr" , GROUP0 + 2, "org.gnu.gdb.or1k.group0", "system"}, {"dmmucfgr" , GROUP0 + 3, "org.gnu.gdb.or1k.group0", "system"}, {"immucfgr" , GROUP0 + 4, "org.gnu.gdb.or1k.group0", "system"}, {"dccfgr" , GROUP0 + 5, "org.gnu.gdb.or1k.group0", "system"}, {"iccfgr" , GROUP0 + 6, "org.gnu.gdb.or1k.group0", "system"}, {"dcfgr" , GROUP0 + 7, "org.gnu.gdb.or1k.group0", "system"}, {"pccfgr" , GROUP0 + 8, "org.gnu.gdb.or1k.group0", "system"}, {"fpcsr" , GROUP0 + 20, "org.gnu.gdb.or1k.group0", "system"}, {"epcr0" , GROUP0 + 32, "org.gnu.gdb.or1k.group0", "system"}, {"epcr1" , GROUP0 + 33, "org.gnu.gdb.or1k.group0", "system"}, {"epcr2" , GROUP0 + 34, "org.gnu.gdb.or1k.group0", "system"}, {"epcr3" , GROUP0 + 35, "org.gnu.gdb.or1k.group0", "system"}, {"epcr4" , GROUP0 + 36, "org.gnu.gdb.or1k.group0", "system"}, {"epcr5" , GROUP0 + 37, "org.gnu.gdb.or1k.group0", "system"}, {"epcr6" , GROUP0 + 38, "org.gnu.gdb.or1k.group0", "system"}, {"epcr7" , GROUP0 + 39, "org.gnu.gdb.or1k.group0", "system"}, {"epcr8" , GROUP0 + 40, "org.gnu.gdb.or1k.group0", "system"}, {"epcr9" , GROUP0 + 41, "org.gnu.gdb.or1k.group0", "system"}, {"epcr10" , GROUP0 + 42, "org.gnu.gdb.or1k.group0", "system"}, {"epcr11" , GROUP0 + 43, "org.gnu.gdb.or1k.group0", "system"}, {"epcr12" , GROUP0 + 44, "org.gnu.gdb.or1k.group0", "system"}, {"epcr13" , GROUP0 + 45, "org.gnu.gdb.or1k.group0", "system"}, {"epcr14" , GROUP0 + 46, "org.gnu.gdb.or1k.group0", "system"}, {"epcr15" , GROUP0 + 47, "org.gnu.gdb.or1k.group0", "system"}, {"eear0" , GROUP0 + 48, "org.gnu.gdb.or1k.group0", "system"}, {"eear1" , GROUP0 + 49, "org.gnu.gdb.or1k.group0", "system"}, {"eear2" , GROUP0 + 50, "org.gnu.gdb.or1k.group0", "system"}, {"eear3" , GROUP0 + 51, "org.gnu.gdb.or1k.group0", "system"}, {"eear4" , GROUP0 + 52, "org.gnu.gdb.or1k.group0", "system"}, {"eear5" , GROUP0 + 53, "org.gnu.gdb.or1k.group0", "system"}, {"eear6" , GROUP0 + 54, "org.gnu.gdb.or1k.group0", "system"}, {"eear7" , GROUP0 + 55, "org.gnu.gdb.or1k.group0", "system"}, {"eear8" , GROUP0 + 56, "org.gnu.gdb.or1k.group0", "system"}, {"eear9" , GROUP0 + 57, "org.gnu.gdb.or1k.group0", "system"}, {"eear10" , GROUP0 + 58, "org.gnu.gdb.or1k.group0", "system"}, {"eear11" , GROUP0 + 59, "org.gnu.gdb.or1k.group0", "system"}, {"eear12" , GROUP0 + 60, "org.gnu.gdb.or1k.group0", "system"}, {"eear13" , GROUP0 + 61, "org.gnu.gdb.or1k.group0", "system"}, {"eear14" , GROUP0 + 62, "org.gnu.gdb.or1k.group0", "system"}, {"eear15" , GROUP0 + 63, "org.gnu.gdb.or1k.group0", "system"}, {"esr0" , GROUP0 + 64, "org.gnu.gdb.or1k.group0", "system"}, {"esr1" , GROUP0 + 65, "org.gnu.gdb.or1k.group0", "system"}, {"esr2" , GROUP0 + 66, "org.gnu.gdb.or1k.group0", "system"}, {"esr3" , GROUP0 + 67, "org.gnu.gdb.or1k.group0", "system"}, {"esr4" , GROUP0 + 68, "org.gnu.gdb.or1k.group0", "system"}, {"esr5" , GROUP0 + 69, "org.gnu.gdb.or1k.group0", "system"}, {"esr6" , GROUP0 + 70, "org.gnu.gdb.or1k.group0", "system"}, {"esr7" , GROUP0 + 71, "org.gnu.gdb.or1k.group0", "system"}, {"esr8" , GROUP0 + 72, "org.gnu.gdb.or1k.group0", "system"}, {"esr9" , GROUP0 + 73, "org.gnu.gdb.or1k.group0", "system"}, {"esr10" , GROUP0 + 74, "org.gnu.gdb.or1k.group0", "system"}, {"esr11" , GROUP0 + 75, "org.gnu.gdb.or1k.group0", "system"}, {"esr12" , GROUP0 + 76, "org.gnu.gdb.or1k.group0", "system"}, {"esr13" , GROUP0 + 77, "org.gnu.gdb.or1k.group0", "system"}, {"esr14" , GROUP0 + 78, "org.gnu.gdb.or1k.group0", "system"}, {"esr15" , GROUP0 + 79, "org.gnu.gdb.or1k.group0", "system"}, {"dmmuucr" , GROUP1 + 0, "org.gnu.gdb.or1k.group1", "dmmu"}, {"dmmuupr" , GROUP1 + 1, "org.gnu.gdb.or1k.group1", "dmmu"}, {"dtlbeir" , GROUP1 + 2, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbmr0" , GROUP1 + 4, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbmr1" , GROUP1 + 5, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbmr2" , GROUP1 + 6, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbmr3" , GROUP1 + 7, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbtr0" , GROUP1 + 8, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbtr1" , GROUP1 + 9, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbtr2" , GROUP1 + 10, "org.gnu.gdb.or1k.group1", "dmmu"}, {"datbtr3" , GROUP1 + 11, "org.gnu.gdb.or1k.group1", "dmmu"}, {"immucr" , GROUP2 + 0, "org.gnu.gdb.or1k.group2", "immu"}, {"immupr" , GROUP2 + 1, "org.gnu.gdb.or1k.group2", "immu"}, {"itlbeir" , GROUP2 + 2, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbmr0" , GROUP2 + 4, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbmr1" , GROUP2 + 5, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbmr2" , GROUP2 + 6, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbmr3" , GROUP2 + 7, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbtr0" , GROUP2 + 8, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbtr1" , GROUP2 + 9, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbtr2" , GROUP2 + 10, "org.gnu.gdb.or1k.group2", "immu"}, {"iatbtr3" , GROUP2 + 11, "org.gnu.gdb.or1k.group2", "immu"}, {"dccr" , GROUP3 + 0, "org.gnu.gdb.or1k.group3", "dcache"}, {"dcbpr" , GROUP3 + 1, "org.gnu.gdb.or1k.group3", "dcache"}, {"dcbfr" , GROUP3 + 2, "org.gnu.gdb.or1k.group3", "dcache"}, {"dcbir" , GROUP3 + 3, "org.gnu.gdb.or1k.group3", "dcache"}, {"dcbwr" , GROUP3 + 4, "org.gnu.gdb.or1k.group3", "dcache"}, {"dcblr" , GROUP3 + 5, "org.gnu.gdb.or1k.group3", "dcache"}, {"iccr" , GROUP4 + 0, "org.gnu.gdb.or1k.group4", "icache"}, {"icbpr" , GROUP4 + 1, "org.gnu.gdb.or1k.group4", "icache"}, {"icbir" , GROUP4 + 2, "org.gnu.gdb.or1k.group4", "icache"}, {"icblr" , GROUP4 + 3, "org.gnu.gdb.or1k.group4", "icache"}, {"maclo" , GROUP5 + 0, "org.gnu.gdb.or1k.group5", "mac"}, {"machi" , GROUP5 + 1, "org.gnu.gdb.or1k.group5", "mac"}, {"dvr0" , GROUP6 + 0, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr1" , GROUP6 + 1, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr2" , GROUP6 + 2, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr3" , GROUP6 + 3, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr4" , GROUP6 + 4, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr5" , GROUP6 + 5, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr6" , GROUP6 + 6, "org.gnu.gdb.or1k.group6", "debug"}, {"dvr7" , GROUP6 + 7, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr0" , GROUP6 + 8, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr1" , GROUP6 + 9, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr2" , GROUP6 + 10, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr3" , GROUP6 + 11, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr4" , GROUP6 + 12, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr5" , GROUP6 + 13, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr6" , GROUP6 + 14, "org.gnu.gdb.or1k.group6", "debug"}, {"dcr7" , GROUP6 + 15, "org.gnu.gdb.or1k.group6", "debug"}, {"dmr1" , GROUP6 + 16, "org.gnu.gdb.or1k.group6", "debug"}, {"dmr2" , GROUP6 + 17, "org.gnu.gdb.or1k.group6", "debug"}, {"dcwr0" , GROUP6 + 18, "org.gnu.gdb.or1k.group6", "debug"}, {"dcwr1" , GROUP6 + 19, "org.gnu.gdb.or1k.group6", "debug"}, {"dsr" , GROUP6 + 20, "org.gnu.gdb.or1k.group6", "debug"}, {"drr" , GROUP6 + 21, "org.gnu.gdb.or1k.group6", "debug"}, {"pccr0" , GROUP7 + 0, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr1" , GROUP7 + 1, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr2" , GROUP7 + 2, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr3" , GROUP7 + 3, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr4" , GROUP7 + 4, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr5" , GROUP7 + 5, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr6" , GROUP7 + 6, "org.gnu.gdb.or1k.group7", "perf"}, {"pccr7" , GROUP7 + 7, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr0" , GROUP7 + 8, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr1" , GROUP7 + 9, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr2" , GROUP7 + 10, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr3" , GROUP7 + 11, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr4" , GROUP7 + 12, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr5" , GROUP7 + 13, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr6" , GROUP7 + 14, "org.gnu.gdb.or1k.group7", "perf"}, {"pcmr7" , GROUP7 + 15, "org.gnu.gdb.or1k.group7", "perf"}, {"pmr" , GROUP8 + 0, "org.gnu.gdb.or1k.group8", "power"}, {"picmr" , GROUP9 + 0, "org.gnu.gdb.or1k.group9", "pic"}, {"picsr" , GROUP9 + 2, "org.gnu.gdb.or1k.group9", "pic"}, {"ttmr" , GROUP10 + 0, "org.gnu.gdb.or1k.group10", "timer"}, {"ttcr" , GROUP10 + 1, "org.gnu.gdb.or1k.group10", "timer"}, }; static int or1k_add_reg(struct target *target, struct or1k_core_reg *new_reg) { struct or1k_common *or1k = target_to_or1k(target); int reg_list_size = or1k->nb_regs * sizeof(struct or1k_core_reg); or1k_core_reg_list_arch_info = realloc(or1k_core_reg_list_arch_info, reg_list_size + sizeof(struct or1k_core_reg)); memcpy(&or1k_core_reg_list_arch_info[or1k->nb_regs], new_reg, sizeof(struct or1k_core_reg)); or1k_core_reg_list_arch_info[or1k->nb_regs].list_num = or1k->nb_regs; or1k->nb_regs++; return ERROR_OK; } static int or1k_create_reg_list(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); LOG_DEBUG("-"); or1k_core_reg_list_arch_info = malloc(ARRAY_SIZE(or1k_init_reg_list) * sizeof(struct or1k_core_reg)); for (int i = 0; i < (int)ARRAY_SIZE(or1k_init_reg_list); i++) { or1k_core_reg_list_arch_info[i].name = or1k_init_reg_list[i].name; or1k_core_reg_list_arch_info[i].spr_num = or1k_init_reg_list[i].spr_num; or1k_core_reg_list_arch_info[i].group = or1k_init_reg_list[i].group; or1k_core_reg_list_arch_info[i].feature = or1k_init_reg_list[i].feature; or1k_core_reg_list_arch_info[i].list_num = i; or1k_core_reg_list_arch_info[i].target = NULL; or1k_core_reg_list_arch_info[i].or1k_common = NULL; } or1k->nb_regs = ARRAY_SIZE(or1k_init_reg_list); struct or1k_core_reg new_reg; new_reg.target = NULL; new_reg.or1k_common = NULL; char name[32]; for (int way = 0; way < 4; way++) { for (int i = 0; i < 128; i++) { sprintf(name, "dtlbw%dmr%d", way, i); new_reg.name = strdup(name); new_reg.spr_num = GROUP1 + 512 + i + (way * 256); new_reg.feature = "org.gnu.gdb.or1k.group1"; new_reg.group = "dmmu"; or1k_add_reg(target, &new_reg); sprintf(name, "dtlbw%dtr%d", way, i); new_reg.name = strdup(name); new_reg.spr_num = GROUP1 + 640 + i + (way * 256); new_reg.feature = "org.gnu.gdb.or1k.group1"; new_reg.group = "dmmu"; or1k_add_reg(target, &new_reg); sprintf(name, "itlbw%dmr%d", way, i); new_reg.name = strdup(name); new_reg.spr_num = GROUP2 + 512 + i + (way * 256); new_reg.feature = "org.gnu.gdb.or1k.group2"; new_reg.group = "immu"; or1k_add_reg(target, &new_reg); sprintf(name, "itlbw%dtr%d", way, i); new_reg.name = strdup(name); new_reg.spr_num = GROUP2 + 640 + i + (way * 256); new_reg.feature = "org.gnu.gdb.or1k.group2"; new_reg.group = "immu"; or1k_add_reg(target, &new_reg); } } return ERROR_OK; } static int or1k_jtag_read_regs(struct or1k_common *or1k, uint32_t *regs) { struct or1k_du *du_core = or1k_jtag_to_du(&or1k->jtag); LOG_DEBUG("-"); return du_core->or1k_jtag_read_cpu(&or1k->jtag, or1k->arch_info[OR1K_REG_R0].spr_num, OR1K_REG_R31 + 1, regs + OR1K_REG_R0); } static int or1k_jtag_write_regs(struct or1k_common *or1k, uint32_t *regs) { struct or1k_du *du_core = or1k_jtag_to_du(&or1k->jtag); LOG_DEBUG("-"); return du_core->or1k_jtag_write_cpu(&or1k->jtag, or1k->arch_info[OR1K_REG_R0].spr_num, OR1K_REG_R31 + 1, ®s[OR1K_REG_R0]); } static int or1k_save_context(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int regs_read = 0; int retval; LOG_DEBUG("-"); for (int i = 0; i < OR1KNUMCOREREGS; i++) { if (!or1k->core_cache->reg_list[i].valid) { if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) { retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, or1k->arch_info[i].spr_num, 1, &or1k->core_regs[i]); if (retval != ERROR_OK) return retval; } else if (!regs_read) { /* read gpr registers at once (but only one time in this loop) */ retval = or1k_jtag_read_regs(or1k, or1k->core_regs); if (retval != ERROR_OK) return retval; /* prevent next reads in this loop */ regs_read = 1; } /* We've just updated the core_reg[i], now update the core cache */ or1k_read_core_reg(target, i); } } return ERROR_OK; } static int or1k_restore_context(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int reg_write = 0; int retval; LOG_DEBUG("-"); for (int i = 0; i < OR1KNUMCOREREGS; i++) { if (or1k->core_cache->reg_list[i].dirty) { or1k_write_core_reg(target, i); if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) { retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, or1k->arch_info[i].spr_num, 1, &or1k->core_regs[i]); if (retval != ERROR_OK) { LOG_ERROR("Error while restoring context"); return retval; } } else reg_write = 1; } } if (reg_write) { /* read gpr registers at once (but only one time in this loop) */ retval = or1k_jtag_write_regs(or1k, or1k->core_regs); if (retval != ERROR_OK) { LOG_ERROR("Error while restoring context"); return retval; } } return ERROR_OK; } static int or1k_read_core_reg(struct target *target, int num) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint32_t reg_value; LOG_DEBUG("-"); if ((num < 0) || (num >= or1k->nb_regs)) return ERROR_COMMAND_SYNTAX_ERROR; if ((num >= 0) && (num < OR1KNUMCOREREGS)) { reg_value = or1k->core_regs[num]; buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value); LOG_DEBUG("Read core reg %i value 0x%08" PRIx32, num , reg_value); or1k->core_cache->reg_list[num].valid = 1; or1k->core_cache->reg_list[num].dirty = 0; } else { /* This is an spr, always read value from HW */ int retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, or1k->arch_info[num].spr_num, 1, ®_value); if (retval != ERROR_OK) { LOG_ERROR("Error while reading spr 0x%08" PRIx32, or1k->arch_info[num].spr_num); return retval; } buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value); LOG_DEBUG("Read spr reg %i value 0x%08" PRIx32, num , reg_value); } return ERROR_OK; } static int or1k_write_core_reg(struct target *target, int num) { struct or1k_common *or1k = target_to_or1k(target); LOG_DEBUG("-"); if ((num < 0) || (num >= OR1KNUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t reg_value = buf_get_u32(or1k->core_cache->reg_list[num].value, 0, 32); or1k->core_regs[num] = reg_value; LOG_DEBUG("Write core reg %i value 0x%08" PRIx32, num , reg_value); or1k->core_cache->reg_list[num].valid = 1; or1k->core_cache->reg_list[num].dirty = 0; return ERROR_OK; } static int or1k_get_core_reg(struct reg *reg) { struct or1k_core_reg *or1k_reg = reg->arch_info; struct target *target = or1k_reg->target; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; return or1k_read_core_reg(target, or1k_reg->list_num); } static int or1k_set_core_reg(struct reg *reg, uint8_t *buf) { struct or1k_core_reg *or1k_reg = reg->arch_info; struct target *target = or1k_reg->target; struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint32_t value = buf_get_u32(buf, 0, 32); LOG_DEBUG("-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; if (or1k_reg->list_num < OR1KNUMCOREREGS) { buf_set_u32(reg->value, 0, 32, value); reg->dirty = 1; reg->valid = 1; } else { /* This is an spr, write it to the HW */ int retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, or1k_reg->spr_num, 1, &value); if (retval != ERROR_OK) { LOG_ERROR("Error while writing spr 0x%08" PRIx32, or1k_reg->spr_num); return retval; } } return ERROR_OK; } static const struct reg_arch_type or1k_reg_type = { .get = or1k_get_core_reg, .set = or1k_set_core_reg, }; static struct reg_cache *or1k_build_reg_cache(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(or1k->nb_regs, sizeof(struct reg)); struct or1k_core_reg *arch_info = malloc((or1k->nb_regs) * sizeof(struct or1k_core_reg)); struct reg_feature *feature; LOG_DEBUG("-"); /* Build the process context cache */ cache->name = "OpenRISC 1000 registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = or1k->nb_regs; (*cache_p) = cache; or1k->core_cache = cache; or1k->arch_info = arch_info; for (int i = 0; i < or1k->nb_regs; i++) { arch_info[i] = or1k_core_reg_list_arch_info[i]; arch_info[i].target = target; arch_info[i].or1k_common = or1k; reg_list[i].name = or1k_core_reg_list_arch_info[i].name; feature = malloc(sizeof(struct reg_feature)); feature->name = or1k_core_reg_list_arch_info[i].feature; reg_list[i].feature = feature; reg_list[i].group = or1k_core_reg_list_arch_info[i].group; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &or1k_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].number = i; reg_list[i].exist = true; } return cache; } static int or1k_debug_entry(struct target *target) { LOG_DEBUG("-"); int retval = or1k_save_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_save_context"); return retval; } struct or1k_common *or1k = target_to_or1k(target); uint32_t addr = or1k->core_regs[OR1K_REG_NPC]; if (breakpoint_find(target, addr)) /* Halted on a breakpoint, step back to permit executing the instruction there */ retval = or1k_set_core_reg(&or1k->core_cache->reg_list[OR1K_REG_NPC], (uint8_t *)&addr); return retval; } static int or1k_halt(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("Target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("Target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { LOG_ERROR("Can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } } int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL); if (retval != ERROR_OK) { LOG_ERROR("Impossible to stall the CPU"); return retval; } target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int or1k_is_cpu_running(struct target *target, int *running) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int retval; int tries = 0; const int RETRIES_MAX = 5; /* Have a retry loop to determine of the CPU is running. If target has been hard reset for any reason, it might take a couple of goes before it's ready again. */ while (tries < RETRIES_MAX) { tries++; retval = du_core->or1k_is_cpu_running(&or1k->jtag, running); if (retval != ERROR_OK) { LOG_WARNING("Debug IF CPU control reg read failure."); /* Try once to restart the JTAG infrastructure - quite possibly the board has just been reset. */ LOG_WARNING("Resetting JTAG TAP state and reconnectiong to debug IF."); du_core->or1k_jtag_init(&or1k->jtag); LOG_WARNING("...attempt %d of %d", tries, RETRIES_MAX); alive_sleep(2); continue; } else return ERROR_OK; } LOG_ERROR("Could not re-establish communication with target"); return retval; } static int or1k_poll(struct target *target) { int retval; int running; retval = or1k_is_cpu_running(target, &running); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_is_cpu_running"); return retval; } /* check for processor halted */ if (!running) { /* It's actually stalled, so update our software's state */ if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { target->state = TARGET_HALTED; retval = or1k_debug_entry(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_debug_entry"); return retval; } target_call_event_callbacks(target, TARGET_EVENT_HALTED); } else if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; retval = or1k_debug_entry(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_debug_entry"); return retval; } target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } else { /* ... target is running */ /* If target was supposed to be stalled, stall it again */ if (target->state == TARGET_HALTED) { target->state = TARGET_RUNNING; retval = or1k_halt(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_halt"); return retval; } retval = or1k_debug_entry(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_debug_entry"); return retval; } target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } target->state = TARGET_RUNNING; } return ERROR_OK; } static int or1k_assert_reset(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("-"); int retval = du_core->or1k_cpu_reset(&or1k->jtag, CPU_RESET); if (retval != ERROR_OK) { LOG_ERROR("Error while asserting RESET"); return retval; } return ERROR_OK; } static int or1k_deassert_reset(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("-"); int retval = du_core->or1k_cpu_reset(&or1k->jtag, CPU_NOT_RESET); if (retval != ERROR_OK) { LOG_ERROR("Error while desasserting RESET"); return retval; } return ERROR_OK; } static int or1k_soft_reset_halt(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("-"); int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL); if (retval != ERROR_OK) { LOG_ERROR("Error while stalling the CPU"); return retval; } retval = or1k_assert_reset(target); if (retval != ERROR_OK) return retval; retval = or1k_deassert_reset(target); if (retval != ERROR_OK) return retval; return ERROR_OK; } static bool is_any_soft_breakpoint(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; LOG_DEBUG("-"); while (breakpoint) if (breakpoint->type == BKPT_SOFT) return true; return false; } static int or1k_resume_or_step(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution, int step) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; uint32_t debug_reg_list[OR1K_DEBUG_REG_NUM]; LOG_DEBUG("Addr: 0x%" PRIx32 ", stepping: %s, handle breakpoints %s\n", address, step ? "yes" : "no", handle_breakpoints ? "yes" : "no"); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) target_free_all_working_areas(target); /* current ? continue on current pc : continue at
*/ if (!current) buf_set_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32, address); int retval = or1k_restore_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_restore_context"); return retval; } /* read debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while reading debug registers"); return retval; } /* Clear Debug Reason Register (DRR) */ debug_reg_list[OR1K_DEBUG_REG_DRR] = 0; /* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) */ debug_reg_list[OR1K_DEBUG_REG_DMR2] &= ~OR1K_DMR2_WGB; if (step) /* Set the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] |= OR1K_DMR1_ST | OR1K_DMR1_BT; else /* Clear the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] &= ~(OR1K_DMR1_ST | OR1K_DMR1_BT); /* Set traps to be handled by the debug unit in the Debug Stop Register (DSR). Check if we have any software breakpoints in place before setting this value - the kernel, for instance, relies on l.trap instructions not stalling the processor ! */ if (is_any_soft_breakpoint(target) == true) debug_reg_list[OR1K_DEBUG_REG_DSR] |= OR1K_DSR_TE; /* Write debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while writing back debug registers"); return retval; } resume_pc = buf_get_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32); /* The front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address); retval = or1k_remove_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } } /* Unstall time */ retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_UNSTALL); if (retval != ERROR_OK) { LOG_ERROR("Error while unstalling the CPU"); return retval; } if (step) target->debug_reason = DBG_REASON_SINGLESTEP; else target->debug_reason = DBG_REASON_NOTHALTED; /* Registers are now invalid */ register_cache_invalidate(or1k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("Target resumed at 0x%08" PRIx32, resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("Target debug resumed at 0x%08" PRIx32, resume_pc); } return ERROR_OK; } static int or1k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { return or1k_resume_or_step(target, current, address, handle_breakpoints, debug_execution, NO_SINGLE_STEP); } static int or1k_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { return or1k_resume_or_step(target, current, address, handle_breakpoints, 0, SINGLE_STEP); } static int or1k_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint8_t data; LOG_DEBUG("Adding breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint."); /* Read and save the instruction */ int retval = du_core->or1k_jtag_read_memory(&or1k->jtag, breakpoint->address, 4, 1, &data); if (retval != ERROR_OK) { LOG_ERROR("Error while reading the instruction at 0x%08" PRIx32, breakpoint->address); return retval; } if (breakpoint->orig_instr != NULL) free(breakpoint->orig_instr); breakpoint->orig_instr = malloc(breakpoint->length); memcpy(breakpoint->orig_instr, &data, breakpoint->length); /* Sub in the OR1K trap instruction */ uint8_t or1k_trap_insn[4]; target_buffer_set_u32(target, or1k_trap_insn, OR1K_TRAP_INSTR); retval = du_core->or1k_jtag_write_memory(&or1k->jtag, breakpoint->address, 4, 1, or1k_trap_insn); if (retval != ERROR_OK) { LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" PRIx32, breakpoint->address); return retval; } /* invalidate instruction cache */ retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; } return ERROR_OK; } static int or1k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("Removing breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint."); /* Replace the removed instruction */ int retval = du_core->or1k_jtag_write_memory(&or1k->jtag, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) { LOG_ERROR("Error while writing back the instruction at 0x%08" PRIx32, breakpoint->address); return retval; } /* invalidate instruction cache */ retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; } return ERROR_OK; } static int or1k_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int or1k_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { LOG_ERROR("%s: implement me", __func__); return ERROR_OK; } static int or1k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("Read memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !buffer) { LOG_ERROR("Bad arguments"); return ERROR_COMMAND_SYNTAX_ERROR; } if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) { LOG_ERROR("Can't handle unaligned memory access"); return ERROR_TARGET_UNALIGNED_ACCESS; } return du_core->or1k_jtag_read_memory(&or1k->jtag, address, size, count, buffer); } static int or1k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("Write memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !buffer) { LOG_ERROR("Bad arguments"); return ERROR_COMMAND_SYNTAX_ERROR; } if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) { LOG_ERROR("Can't handle unaligned memory access"); return ERROR_TARGET_UNALIGNED_ACCESS; } return du_core->or1k_jtag_write_memory(&or1k->jtag, address, size, count, buffer); } static int or1k_init_target(struct command_context *cmd_ctx, struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); struct or1k_jtag *jtag = &or1k->jtag; if (du_core == NULL) { LOG_ERROR("No debug unit selected"); return ERROR_FAIL; } if (jtag->tap_ip == NULL) { LOG_ERROR("No tap selected"); return ERROR_FAIL; } or1k->jtag.tap = target->tap; or1k->jtag.or1k_jtag_inited = 0; or1k->jtag.or1k_jtag_module_selected = -1; or1k->jtag.target = target; or1k_build_reg_cache(target); return ERROR_OK; } static int or1k_target_create(struct target *target, Jim_Interp *interp) { if (target->tap == NULL) return ERROR_FAIL; struct or1k_common *or1k = calloc(1, sizeof(struct or1k_common)); target->arch_info = or1k; or1k_create_reg_list(target); or1k_tap_vjtag_register(); or1k_tap_xilinx_bscan_register(); or1k_tap_mohor_register(); or1k_du_adv_register(); return ERROR_OK; } static int or1k_examine(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); if (!target_was_examined(target)) { target_set_examined(target); int running; int retval = du_core->or1k_is_cpu_running(&or1k->jtag, &running); if (retval != ERROR_OK) { LOG_ERROR("Couldn't read the CPU state"); return retval; } else { if (running) target->state = TARGET_RUNNING; else { LOG_DEBUG("Target is halted"); /* This is the first time we examine the target, * it is stalled and we don't know why. Let's * assume this is because of a debug reason. */ if (target->state == TARGET_UNKNOWN) target->debug_reason = DBG_REASON_DBGRQ; target->state = TARGET_HALTED; } } } return ERROR_OK; } static int or1k_arch_state(struct target *target) { return ERROR_OK; } static int or1k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct or1k_common *or1k = target_to_or1k(target); if (reg_class == REG_CLASS_GENERAL) { /* We will have this called whenever GDB connects. */ int retval = or1k_save_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_save_context"); return retval; } *reg_list_size = OR1KNUMCOREREGS; /* this is free()'d back in gdb_server.c's gdb_get_register_packet() */ *reg_list = malloc((*reg_list_size) * sizeof(struct reg *)); for (int i = 0; i < OR1KNUMCOREREGS; i++) (*reg_list)[i] = &or1k->core_cache->reg_list[i]; } else { *reg_list_size = or1k->nb_regs; *reg_list = malloc((*reg_list_size) * sizeof(struct reg *)); for (int i = 0; i < or1k->nb_regs; i++) (*reg_list)[i] = &or1k->core_cache->reg_list[i]; } return ERROR_OK; } int or1k_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) { return ERROR_FAIL; } static int or1k_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { return ERROR_FAIL; } static int or1k_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { struct timeval timeout, now; struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int retval = ERROR_OK; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, seconds, 0); LOG_INFO("Starting or1k profiling. Sampling npc as fast as we can..."); /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) retval = target_resume(target, 1, 0, 0, 0); if (retval != ERROR_OK) { LOG_ERROR("Error while resuming target"); return retval; } uint32_t sample_count = 0; for (;;) { uint32_t reg_value; retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, GROUP0 + 16 /* NPC */, 1, ®_value); if (retval != ERROR_OK) { LOG_ERROR("Error while reading NPC"); return retval; } samples[sample_count++] = reg_value; gettimeofday(&now, NULL); if ((sample_count >= max_num_samples) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); break; } } *num_samples = sample_count; return retval; } COMMAND_HANDLER(or1k_tap_select_command_handler) { struct target *target = get_current_target(CMD_CTX); struct or1k_common *or1k = target_to_or1k(target); struct or1k_jtag *jtag = &or1k->jtag; struct or1k_tap_ip *or1k_tap; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(or1k_tap, &tap_list, list) { if (or1k_tap->name) { if (!strcmp(CMD_ARGV[0], or1k_tap->name)) { jtag->tap_ip = or1k_tap; LOG_INFO("%s tap selected", or1k_tap->name); return ERROR_OK; } } } LOG_ERROR("%s unknown, no tap selected", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(or1k_tap_list_command_handler) { struct or1k_tap_ip *or1k_tap; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(or1k_tap, &tap_list, list) { if (or1k_tap->name) command_print(CMD_CTX, "%s", or1k_tap->name); } return ERROR_OK; } COMMAND_HANDLER(or1k_du_select_command_handler) { struct target *target = get_current_target(CMD_CTX); struct or1k_common *or1k = target_to_or1k(target); struct or1k_jtag *jtag = &or1k->jtag; struct or1k_du *or1k_du; if (CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(or1k_du, &du_list, list) { if (or1k_du->name) { if (!strcmp(CMD_ARGV[0], or1k_du->name)) { jtag->du_core = or1k_du; LOG_INFO("%s debug unit selected", or1k_du->name); if (CMD_ARGC == 2) { int options; COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], options); or1k_du->options = options; LOG_INFO("Option %x is passed to %s debug unit" , options, or1k_du->name); } return ERROR_OK; } } } LOG_ERROR("%s unknown, no debug unit selected", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(or1k_du_list_command_handler) { struct or1k_du *or1k_du; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(or1k_du, &du_list, list) { if (or1k_du->name) command_print(CMD_CTX, "%s", or1k_du->name); } return ERROR_OK; } COMMAND_HANDLER(or1k_addreg_command_handler) { struct target *target = get_current_target(CMD_CTX); struct or1k_core_reg new_reg; if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; new_reg.target = NULL; new_reg.or1k_common = NULL; uint32_t addr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); new_reg.name = strdup(CMD_ARGV[0]); new_reg.spr_num = addr; new_reg.feature = strdup(CMD_ARGV[2]); new_reg.group = strdup(CMD_ARGV[3]); or1k_add_reg(target, &new_reg); LOG_DEBUG("Add reg \"%s\" @ 0x%08" PRIx32 ", group \"%s\", feature \"%s\"", new_reg.name, addr, new_reg.group, new_reg.feature); return ERROR_OK; } static const struct command_registration or1k_hw_ip_command_handlers[] = { { "tap_select", .handler = or1k_tap_select_command_handler, .mode = COMMAND_ANY, .usage = "tap_select name", .help = "Select the TAP core to use", }, { "tap_list", .handler = or1k_tap_list_command_handler, .mode = COMMAND_ANY, .usage = "tap_list", .help = "Display available TAP core", }, { "du_select", .handler = or1k_du_select_command_handler, .mode = COMMAND_ANY, .usage = "du_select name", .help = "Select the Debug Unit core to use", }, { "du_list", .handler = or1k_du_list_command_handler, .mode = COMMAND_ANY, .usage = "select_tap name", .help = "Display available Debug Unit core", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration or1k_reg_command_handlers[] = { { "addreg", .handler = or1k_addreg_command_handler, .mode = COMMAND_ANY, .usage = "addreg name addr feature group", .help = "Add a register to the register list", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration or1k_command_handlers[] = { { .chain = or1k_reg_command_handlers, }, { .chain = or1k_hw_ip_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type or1k_target = { .name = "or1k", .poll = or1k_poll, .arch_state = or1k_arch_state, .target_request_data = NULL, .halt = or1k_halt, .resume = or1k_resume, .step = or1k_step, .assert_reset = or1k_assert_reset, .deassert_reset = or1k_deassert_reset, .soft_reset_halt = or1k_soft_reset_halt, .get_gdb_reg_list = or1k_get_gdb_reg_list, .read_memory = or1k_read_memory, .write_memory = or1k_write_memory, .checksum_memory = or1k_checksum_memory, .commands = or1k_command_handlers, .add_breakpoint = or1k_add_breakpoint, .remove_breakpoint = or1k_remove_breakpoint, .add_watchpoint = or1k_add_watchpoint, .remove_watchpoint = or1k_remove_watchpoint, .target_create = or1k_target_create, .init_target = or1k_init_target, .examine = or1k_examine, .get_gdb_fileio_info = or1k_get_gdb_fileio_info, .profiling = or1k_profiling, }; openocd-0.9.0/src/target/openrisc/or1k.h0000644000175000017500000001126612516456304015030 00000000000000/*************************************************************************** * Copyright (C) 2011 by Julius Baxter * * julius@opencores.org * * * * Copyright (C) 2013 by Marek Czerski * * ma.czerski@gmail.com * * * * Copyright (C) 2013 by Franck Jullien * * elec4fun@gmail.com * * * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifndef OR1K_H #define OR1K_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* SPR groups start address */ #define GROUP0 (0 << 11) #define GROUP1 (1 << 11) #define GROUP2 (2 << 11) #define GROUP3 (3 << 11) #define GROUP4 (4 << 11) #define GROUP5 (5 << 11) #define GROUP6 (6 << 11) #define GROUP7 (7 << 11) #define GROUP8 (8 << 11) #define GROUP9 (9 << 11) #define GROUP10 (10 << 11) /* OR1K registers */ enum or1k_reg_nums { OR1K_REG_R0 = 0, OR1K_REG_R1, OR1K_REG_R2, OR1K_REG_R3, OR1K_REG_R4, OR1K_REG_R5, OR1K_REG_R6, OR1K_REG_R7, OR1K_REG_R8, OR1K_REG_R9, OR1K_REG_R10, OR1K_REG_R11, OR1K_REG_R12, OR1K_REG_R13, OR1K_REG_R14, OR1K_REG_R15, OR1K_REG_R16, OR1K_REG_R17, OR1K_REG_R18, OR1K_REG_R19, OR1K_REG_R20, OR1K_REG_R21, OR1K_REG_R22, OR1K_REG_R23, OR1K_REG_R24, OR1K_REG_R25, OR1K_REG_R26, OR1K_REG_R27, OR1K_REG_R28, OR1K_REG_R29, OR1K_REG_R30, OR1K_REG_R31, OR1K_REG_PPC, OR1K_REG_NPC, OR1K_REG_SR, OR1KNUMCOREREGS }; struct or1k_jtag { struct jtag_tap *tap; int or1k_jtag_inited; int or1k_jtag_module_selected; uint8_t *current_reg_idx; struct or1k_tap_ip *tap_ip; struct or1k_du *du_core; struct target *target; }; struct or1k_common { struct or1k_jtag jtag; struct reg_cache *core_cache; uint32_t core_regs[OR1KNUMCOREREGS]; int nb_regs; struct or1k_core_reg *arch_info; }; static inline struct or1k_common * target_to_or1k(struct target *target) { return (struct or1k_common *)target->arch_info; } struct or1k_core_reg { const char *name; uint32_t list_num; /* Index in register cache */ uint32_t spr_num; /* Number in architecture's SPR space */ struct target *target; struct or1k_common *or1k_common; const char *feature; /* feature name in XML tdesc file */ const char *group; /* register group in XML tdesc file */ }; struct or1k_core_reg_init { const char *name; uint32_t spr_num; /* Number in architecture's SPR space */ const char *feature; /* feature name in XML tdesc file */ const char *group; /* register group in XML tdesc file */ }; /* ORBIS32 Trap instruction */ #define OR1K_TRAP_INSTR 0x21000001 enum or1k_debug_reg_nums { OR1K_DEBUG_REG_DMR1 = 0, OR1K_DEBUG_REG_DMR2, OR1K_DEBUG_REG_DCWR0, OR1K_DEBUG_REG_DCWR1, OR1K_DEBUG_REG_DSR, OR1K_DEBUG_REG_DRR, OR1K_DEBUG_REG_NUM }; #define NO_SINGLE_STEP 0 #define SINGLE_STEP 1 /* OR1K Debug registers and bits needed for resuming */ #define OR1K_DEBUG_REG_BASE GROUP6 /* Debug registers Base address */ #define OR1K_DMR1_CPU_REG_ADD (OR1K_DEBUG_REG_BASE + 16) /* Debug Mode Register 1 0x3010 */ #define OR1K_DMR1_ST 0x00400000 /* Single-step trace */ #define OR1K_DMR1_BT 0x00800000 /* Branch trace */ #define OR1K_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */ #define OR1K_DSR_TE 0x00002000 /* Trap exception */ /* OR1K Instruction cache registers needed for invalidating instruction * memory during adding and removing breakpoints. */ #define OR1K_ICBIR_CPU_REG_ADD ((4 << 11) + 2) /* IC Block Invalidate Register 0x2002 */ #endif openocd-0.9.0/src/target/openrisc/or1k_tap_vjtag.c0000644000175000017500000002601412516456304017057 00000000000000/*************************************************************************** * Copyright (C) 2013 by Franck Jullien * * elec4fun@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "or1k_tap.h" #include "or1k.h" #include /* Contains constants relevant to the Altera Virtual JTAG * device, which are not included in the BSDL. * As of this writing, these are constant across every * device which supports virtual JTAG. */ /* These are commands for the FPGA's IR. */ #define ALTERA_CYCLONE_CMD_USER1 0x0E #define ALTERA_CYCLONE_CMD_USER0 0x0C /* These defines are for the virtual IR (not the FPGA's) * The virtual TAP was defined in hardware to match the OpenCores native * TAP in both IR size and DEBUG command. */ #define ALT_VJTAG_IR_SIZE 4 #define ALT_VJTAG_CMD_DEBUG 0x8 /* SLD node ID. */ #define JTAG_TO_AVALON_NODE_ID 0x84 #define VJTAG_NODE_ID 0x08 #define SIGNAL_TAP_NODE_ID 0x00 #define SERIAL_FLASH_LOADER_NODE_ID 0x04 #define VER(x) ((x >> 27) & 0x1f) #define NB_NODES(x) ((x >> 19) & 0xff) #define ID(x) ((x >> 19) & 0xff) #define MANUF(x) ((x >> 8) & 0x7ff) #define M_WIDTH(x) ((x >> 0) & 0xff) #define INST_ID(x) ((x >> 0) & 0xff) /* tap instructions - Mohor JTAG TAP */ #define OR1K_TAP_INST_IDCODE 0x2 #define OR1K_TAP_INST_DEBUG 0x8 static const char *id_to_string(unsigned char id) { switch (id) { case VJTAG_NODE_ID: return "Virtual JTAG"; case JTAG_TO_AVALON_NODE_ID: return "JTAG to avalon bridge"; case SIGNAL_TAP_NODE_ID: return "Signal TAP"; case SERIAL_FLASH_LOADER_NODE_ID: return "Serial Flash Loader"; } return "unknown"; } static unsigned char guess_addr_width(unsigned char number_of_nodes) { unsigned char width = 0; while (number_of_nodes) { number_of_nodes >>= 1; width++; } return width; } static int or1k_tap_vjtag_init(struct or1k_jtag *jtag_info) { LOG_DEBUG("Initialising Altera Virtual JTAG TAP"); /* Put TAP into state where it can talk to the debug interface * by shifting in correct value to IR. */ /* Ensure TAP is reset - maybe not necessary*/ jtag_add_tlr(); /* You can use a custom JTAG controller to discover transactions * necessary to enumerate all Virtual JTAG megafunction instances * from your design atruntime. All SLD nodes and the virtual JTAG * registers that they contain are targeted by two Instruction Register * values, USER0 and USER1. * * The USER1 instruction targets the virtual IR of either the sld_hub * or a SLD node. That is,when the USER1 instruction is issued to * the device, the subsequent DR scans target a specific virtual * IR chain based on an address field contained within the DR scan. * The table below shows how the virtual IR, the DR target of the * USER1 instruction is interpreted. * * The VIR_VALUE in the table below is the virtual IR value for the * target SLD node. The width of this field is m bits in length, * where m is the length of the largest VIR for all of the SLD nodes * in the design. All SLD nodes with VIR lengths of fewer than m * bits must pad VIR_VALUE with zeros up to a length of m. * * -------------------------------+------------------------------- * m + n - 1 m | m -1 0 * -------------------------------+------------------------------- * ADDR [(n – 1)..0] | VIR_VALUE [(m – 1)..0] * -------------------------------+------------------------------- * * The ADDR bits act as address values to signal the active SLD node * that the virtual IR shift targets. ADDR is n bits in length, where * n bits must be long enough to encode all SLD nodes within the design, * as shown below. * * n = CEIL(log2(Number of SLD_nodes +1)) * * The SLD hub is always 0 in the address map. * * Discovery and enumeration of the SLD instances within a design * requires interrogation of the sld_hub to determine the dimensions * of the USER1 DR (m and n) and associating each SLD instance, specifically * the Virtual JTAG megafunction instances, with an address value * contained within the ADDR bits of the USER1 DR. * * The SLD hub contains the HUB IP Configuration Register and SLD_NODE_INFO * register for each SLD node in the design. The HUB IP configuration register provides * information needed to determine the dimensions of the USER1 DR chain. The * SLD_NODE_INFO register is used to determine the address mapping for Virtual * JTAG instance in your design. This register set is shifted out by issuing the * HUB_INFO instruction. Both the ADDR bits for the SLD hub and the HUB_INFO * instruction is 0 × 0. * Because m and n are unknown at this point, the DR register * (ADDR bits + VIR_VALUE) must be filled with zeros. Shifting a sequence of 64 zeroes * into the USER1 DR is sufficient to cover the most conservative case for m and n. */ uint8_t t[4]; struct scan_field field; struct jtag_tap *tap = jtag_info->tap; /* Select VIR */ buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER1); field.num_bits = tap->ir_length; field.out_value = t; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); /* Select the SLD Hub */ field.num_bits = 64; field.out_value = NULL; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* HUB IP Configuration Register * * When the USER1 and HUB_INFO instruction sequence is issued, the * USER0 instruction must be applied to enable the target register * of the HUB_INFO instruction. The HUB IP configuration register * is shifted out using eight four-bit nibble scans of the DR register. * Each four-bit scan must pass through the UPDATE_DR state before * the next four-bit scan. The 8 scans are assembled into a 32-bit * value with the definitions shown in the table below. * * -------------------------------------------------------------------------------- * NIBBLE7 | NIBBLE6 | NIBBLE5 | NIBBLE4 | NIBBLE3 | NIBBLE2 | NIBBLE1 | NIBBLE0 * ----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----- * | | | | | | | | | | | | | | | * ----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----- * HUB IP version| N | ALTERA_MFG_ID (0x06E) | SUM (m, n) * --------------+-------------------+------------------------+-------------------- */ /* Select VDR */ buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER0); field.num_bits = tap->ir_length; field.out_value = t; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); int retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; uint8_t nibble; uint32_t hub_info = 0; for (int i = 0; i < 8; i++) { field.num_bits = 4; field.out_value = NULL; field.in_value = &nibble; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; hub_info = ((hub_info >> 4) | ((nibble & 0xf) << 28)); } int nb_nodes = NB_NODES(hub_info); int m_width = M_WIDTH(hub_info); LOG_DEBUG("SLD HUB Configuration register"); LOG_DEBUG("------------------------------"); LOG_DEBUG("m_width = %d", m_width); LOG_DEBUG("manufacturer_id = 0x%02" PRIx32, MANUF(hub_info)); LOG_DEBUG("nb_of_node = %d", nb_nodes); LOG_DEBUG("version = %" PRId32, VER(hub_info)); LOG_DEBUG("VIR length = %d", guess_addr_width(nb_nodes) + m_width); /* Because the number of SLD nodes is now known, the Nodes on the hub can be * enumerated by repeating the 8 four-bit nibble scans, once for each Node, * to yield the SLD_NODE_INFO register of each Node. The DR nibble shifts * are a continuation of the HUB_INFO DR shift used to shift out the Hub IP * Configuration register. * * The order of the Nodes as they are shifted out determines the ADDR * values for the Nodes, beginning with, for the first Node SLD_NODE_INFO * shifted out, up to and including, for the last node on the hub. The * tables below show the SLD_NODE_INFO register and a their functional descriptions. * * --------------+-----------+---------------+---------------- * 31 27 | 26 19 | 18 8 | 7 0 * --------------+-----------+---------------+---------------- * Node Version | NODE ID | NODE MFG_ID | NODE INST ID * */ int vjtag_node_address = -1; int node_index; uint32_t node_info = 0; for (node_index = 0; node_index < nb_nodes; node_index++) { for (int i = 0; i < 8; i++) { field.num_bits = 4; field.out_value = NULL; field.in_value = &nibble; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; node_info = ((node_info >> 4) | ((nibble & 0xf) << 28)); } LOG_DEBUG("Node info register"); LOG_DEBUG("--------------------"); LOG_DEBUG("instance_id = %" PRId32, ID(node_info)); LOG_DEBUG("manufacturer_id = 0x%02" PRIx32, MANUF(node_info)); LOG_DEBUG("node_id = %" PRId32 " (%s)", ID(node_info), id_to_string(ID(node_info))); LOG_DEBUG("version = %" PRId32, VER(node_info)); if (ID(node_info) == VJTAG_NODE_ID) vjtag_node_address = node_index + 1; } if (vjtag_node_address < 0) { LOG_ERROR("No VJTAG TAP instance found !"); return ERROR_FAIL; } /* Select VIR */ buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER1); field.num_bits = tap->ir_length; field.out_value = t; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); /* Send the DEBUG command to the VJTAG IR */ int dr_length = guess_addr_width(nb_nodes) + m_width; buf_set_u32(t, 0, dr_length, (vjtag_node_address << m_width) | ALT_VJTAG_CMD_DEBUG); field.num_bits = dr_length; field.out_value = t; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* Select the VJTAG DR */ buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER0); field.num_bits = tap->ir_length; field.out_value = t; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); return jtag_execute_queue(); } static struct or1k_tap_ip vjtag_tap = { .name = "vjtag", .init = or1k_tap_vjtag_init, }; int or1k_tap_vjtag_register(void) { list_add_tail(&vjtag_tap.list, &tap_list); return 0; } openocd-0.9.0/src/target/openrisc/or1k_tap_xilinx_bscan.c0000644000175000017500000000376212516456304020432 00000000000000/*************************************************************************** * Copyright (C) 2013 by Sergio Chico * * sergio.chico@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "or1k_tap.h" #include "or1k.h" #include #define OR1K_XILINX_TAP_INST_USER1 0x02 static int or1k_tap_xilinx_bscan_init(struct or1k_jtag *jtag_info) { LOG_DEBUG("Initialising Xilinx Internal JTAG TAP"); /* Put TAP into state where it can talk to the debug interface * by shifting in correct value to IR. */ /* Ensure TAP is reset - maybe not necessary*/ jtag_add_tlr(); struct jtag_tap *tap = jtag_info->tap; struct scan_field field; uint8_t ir_value = OR1K_XILINX_TAP_INST_USER1; field.num_bits = tap->ir_length; field.out_value = &ir_value; field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); return jtag_execute_queue(); } static struct or1k_tap_ip xilinx_bscan_tap = { .name = "xilinx_bscan", .init = or1k_tap_xilinx_bscan_init, }; int or1k_tap_xilinx_bscan_register(void) { list_add_tail(&xilinx_bscan_tap.list, &tap_list); return 0; } openocd-0.9.0/src/target/arm9tdmi.c0000644000175000017500000007215012315575361014054 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm9tdmi.h" #include "target_type.h" #include "register.h" #include "arm_opcodes.h" /* * NOTE: this holds code that's used with multiple ARM9 processors: * - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores * - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores * - ARM9EJS (ARMv5TEJ) ... in ARM926 core * * In short, the file name is a misnomer ... it is NOT specific to * that first generation ARM9 processor, or cores using it. */ #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif enum arm9tdmi_vector_bit { ARM9TDMI_RESET_VECTOR = 0x01, ARM9TDMI_UNDEF_VECTOR = 0x02, ARM9TDMI_SWI_VECTOR = 0x04, ARM9TDMI_PABT_VECTOR = 0x08, ARM9TDMI_DABT_VECTOR = 0x10, /* BIT(5) reserved -- must be zero */ ARM9TDMI_IRQ_VECTOR = 0x40, ARM9TDMI_FIQ_VECTOR = 0x80, }; static const struct arm9tdmi_vector { const char *name; uint32_t value; } arm9tdmi_vectors[] = { {"reset", ARM9TDMI_RESET_VECTOR}, {"undef", ARM9TDMI_UNDEF_VECTOR}, {"swi", ARM9TDMI_SWI_VECTOR}, {"pabt", ARM9TDMI_PABT_VECTOR}, {"dabt", ARM9TDMI_DABT_VECTOR}, {"irq", ARM9TDMI_IRQ_VECTOR}, {"fiq", ARM9TDMI_FIQ_VECTOR}, {0, 0}, }; int arm9tdmi_examine_debug_reason(struct target *target) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); /* only check the debug reason if we don't know it already */ if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { struct scan_field fields[3]; uint8_t databus[4]; uint8_t instructionbus[4]; uint8_t debug_reason; fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = databus; fields[1].num_bits = 3; fields[1].out_value = NULL; fields[1].in_value = &debug_reason; fields[2].num_bits = 32; fields[2].out_value = NULL; fields[2].in_value = instructionbus; retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; fields[0].in_value = NULL; fields[0].out_value = databus; fields[1].in_value = NULL; fields[1].out_value = &debug_reason; fields[2].in_value = NULL; fields[2].out_value = instructionbus; jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE); if (debug_reason & 0x4) if (debug_reason & 0x2) target->debug_reason = DBG_REASON_WPTANDBKPT; else target->debug_reason = DBG_REASON_WATCHPOINT; else target->debug_reason = DBG_REASON_BREAKPOINT; } return ERROR_OK; } /* put an instruction in the ARM9TDMI pipeline or write the data bus, * and optionally read data */ int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr, uint32_t out, uint32_t *in, int sysspeed) { int retval = ERROR_OK; struct scan_field fields[3]; uint8_t out_buf[4]; uint8_t instr_buf[4]; uint8_t sysspeed_buf = 0x0; /* prepare buffer */ buf_set_u32(out_buf, 0, 32, out); buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32)); if (sysspeed) buf_set_u32(&sysspeed_buf, 2, 1, 1); retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = out_buf; fields[0].in_value = NULL; fields[1].num_bits = 3; fields[1].out_value = &sysspeed_buf; fields[1].in_value = NULL; fields[2].num_bits = 32; fields[2].out_value = instr_buf; fields[2].in_value = NULL; if (in) { fields[0].in_value = (uint8_t *)in; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in); } else jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in); else LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out); } #endif return ERROR_OK; } /* just read data (instruction and data-out = don't care) */ int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in) { int retval = ERROR_OK; struct scan_field fields[3]; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = (uint8_t *)in; fields[1].num_bits = 3; fields[1].out_value = NULL; fields[1].in_value = NULL; fields[2].num_bits = 32; fields[2].out_value = NULL; fields[2].in_value = NULL; jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in); jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("in: 0x%8.8x", *in); else LOG_ERROR("BUG: called with in == NULL"); } #endif return ERROR_OK; } /* clock the target, and read the databus * the *in pointer points to a buffer where elements of 'size' bytes * are stored in big (be == 1) or little (be == 0) endianness */ int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info, void *in, int size, int be) { int retval = ERROR_OK; struct scan_field fields[2]; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE); if (retval != ERROR_OK) return retval; if (size == 4) { fields[0].num_bits = 32; fields[0].out_value = NULL; fields[0].in_value = in; fields[1].num_bits = 3 + 32; fields[1].out_value = NULL; fields[1].in_value = NULL; } else { /* Discard irrelevant bits of the scan, making sure we don't write more * than size bytes to in */ fields[0].num_bits = size * 8; fields[0].out_value = NULL; fields[0].in_value = in; fields[1].num_bits = 3 + 32 + 32 - size * 8; fields[1].out_value = NULL; fields[1].in_value = NULL; } jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback4(arm7_9_endianness_callback, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)0); jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (in) LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in); else LOG_ERROR("BUG: called with in == NULL"); } #endif return ERROR_OK; } static void arm9tdmi_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* save r0 before using it and put system in ARM state * to allow common handling of ARM and THUMB debugging */ /* fetch STR r0, [r0] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* STR r0, [r0] in Memory */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0); /* MOV r0, r15 fetched, STR in Decode */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* nothing fetched, STR r0, [r0] in Memory */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0); /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0); /* LDR in Decode */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* LDR in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* LDR in Memory (to account for interlock) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* fetch BX */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0); /* NOP fetched, BX in Decode, MOV in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* NOP fetched, BX in Execute (1) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return; /* fix program counter: * MOV r0, r15 was the 5th instruction (+8) * reading PC in Thumb state gives address of instruction + 4 */ *pc -= 0xc; } void arm9tdmi_read_core_regs(struct target *target, uint32_t mask, uint32_t *core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, STM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, STM in MEMORY (i'th cycle) */ arm9tdmi_clock_data_in(jtag_info, core_regs[i]); } } static void arm9tdmi_read_core_regs_target_buffer(struct target *target, uint32_t mask, void *buffer, int size) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0; uint32_t *buf_u32 = buffer; uint16_t *buf_u16 = buffer; uint8_t *buf_u8 = buffer; /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, STM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, STM in MEMORY (i'th cycle) */ switch (size) { case 4: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be); break; case 2: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be); break; case 1: arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be); break; } } } static void arm9tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* STR r0, [r15] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0); /* fetch NOP, STR in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, STR in MEMORY */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0); } static void arm9tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr); /* MSR1 fetched */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0); /* MSR2 fetched, MSR1 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0); /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0); /* nothing fetched, MSR1 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR1 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0); /* nothing fetched, MSR2 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR2 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR3 in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR3 in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR4 in EXECUTE (1) */ /* last MSR writes flags, which takes only one cycle */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } static void arm9tdmi_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr); /* MSR fetched */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0); /* NOP fetched, MSR in DECODE */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* NOP fetched, MSR in EXECUTE (1) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* rot == 4 writes flags, which takes only one cycle */ if (rot != 4) { /* nothing fetched, MSR in EXECUTE (2) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, MSR in EXECUTE (3) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } } void arm9tdmi_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16]) { int i; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0); } arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } void arm9tdmi_load_word_regs(struct target *target, uint32_t mask) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load-multiple into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } void arm9tdmi_load_hword_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load half-word into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } void arm9tdmi_load_byte_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load byte into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } void arm9tdmi_store_word_regs(struct target *target, uint32_t mask) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store-multiple into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } void arm9tdmi_store_hword_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store half-word into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } void arm9tdmi_store_byte_reg(struct target *target, int num) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store byte into the pipeline */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } static void arm9tdmi_write_pc(struct target *target, uint32_t pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (4th cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (5th cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); } void arm9tdmi_branch_resume(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); } static void arm9tdmi_branch_resume_thumb(struct target *target) { LOG_DEBUG("-"); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0); /* fetch NOP, LDM in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* Branch and eXchange */ arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0); embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* target is now in Thumb state */ embeddedice_read_reg(dbg_stat); /* load r0 value, MOV_IM in Decode*/ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0); /* fetch NOP, LDR in Decode, MOV_IM in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* fetch NOP, LDR in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0); /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); embeddedice_read_reg(dbg_stat); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); } void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (arm7_9->has_single_step) { buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); } else arm7_9_enable_eice_step(target, next_pc); } void arm9tdmi_disable_single_step(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (arm7_9->has_single_step) { buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]); } else arm7_9_disable_eice_step(target); } static void arm9tdmi_build_reg_cache(struct target *target) { struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct arm *arm = target_to_arm(target); (*cache_p) = arm_build_reg_cache(target, arm); } int arm9tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm9tdmi_build_reg_cache(target); return ERROR_OK; } int arm9tdmi_init_arch_info(struct target *target, struct arm7_9_common *arm7_9, struct jtag_tap *tap) { /* prepare JTAG information for the new target */ arm7_9->jtag_info.tap = tap; arm7_9->jtag_info.scann_size = 5; /* register arch-specific functions */ arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason; arm7_9->change_to_arm = arm9tdmi_change_to_arm; arm7_9->read_core_regs = arm9tdmi_read_core_regs; arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer; arm7_9->read_xpsr = arm9tdmi_read_xpsr; arm7_9->write_xpsr = arm9tdmi_write_xpsr; arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8; arm7_9->write_core_regs = arm9tdmi_write_core_regs; arm7_9->load_word_regs = arm9tdmi_load_word_regs; arm7_9->load_hword_reg = arm9tdmi_load_hword_reg; arm7_9->load_byte_reg = arm9tdmi_load_byte_reg; arm7_9->store_word_regs = arm9tdmi_store_word_regs; arm7_9->store_hword_reg = arm9tdmi_store_hword_reg; arm7_9->store_byte_reg = arm9tdmi_store_byte_reg; arm7_9->write_pc = arm9tdmi_write_pc; arm7_9->branch_resume = arm9tdmi_branch_resume; arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb; arm7_9->enable_single_step = arm9tdmi_enable_single_step; arm7_9->disable_single_step = arm9tdmi_disable_single_step; arm7_9->write_memory = arm7_9_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; arm7_9->pre_restore_context = NULL; /* initialize arch-specific breakpoint handling */ arm7_9->arm_bkpt = 0xdeeedeee; arm7_9->thumb_bkpt = 0xdeee; arm7_9->dbgreq_adjust_pc = 3; arm7_9_init_arch_info(target, arm7_9); /* override use of DBGRQ, this is safe on ARM9TDMI */ arm7_9->use_dbgrq = 1; /* all ARM9s have the vector catch register */ arm7_9->has_vector_catch = 1; return ERROR_OK; } static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp) { struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common)); arm9tdmi_init_arch_info(target, arm7_9, target->tap); arm7_9->arm.is_armv4 = true; return ERROR_OK; } COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command) { struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *vector_catch; uint32_t vector_catch_value; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } /* it's uncommon, but some ARM7 chips can support this */ if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC || !arm7_9->has_vector_catch) { command_print(CMD_CTX, "target doesn't have EmbeddedICE " "with vector_catch"); return ERROR_TARGET_INVALID; } vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]; /* read the vector catch register if necessary */ if (!vector_catch->valid) embeddedice_read_reg(vector_catch); /* get the current setting */ vector_catch_value = buf_get_u32(vector_catch->value, 0, 8); if (CMD_ARGC > 0) { vector_catch_value = 0x0; if (strcmp(CMD_ARGV[0], "all") == 0) vector_catch_value = 0xdf; else if (strcmp(CMD_ARGV[0], "none") == 0) { /* do nothing */ } else { for (unsigned i = 0; i < CMD_ARGC; i++) { /* go through list of vectors */ unsigned j; for (j = 0; arm9tdmi_vectors[j].name; j++) { if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) { vector_catch_value |= arm9tdmi_vectors[j].value; break; } } /* complain if vector wasn't found */ if (!arm9tdmi_vectors[j].name) { command_print(CMD_CTX, "vector '%s' not found, leaving current setting unchanged", CMD_ARGV[i]); /* reread current setting */ vector_catch_value = buf_get_u32( vector_catch->value, 0, 8); break; } } } /* store new settings */ buf_set_u32(vector_catch->value, 0, 8, vector_catch_value); embeddedice_store_reg(vector_catch); } /* output current settings */ for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) { command_print(CMD_CTX, "%s: %s", arm9tdmi_vectors[i].name, (vector_catch_value & arm9tdmi_vectors[i].value) ? "catch" : "don't catch"); } return ERROR_OK; } static const struct command_registration arm9tdmi_exec_command_handlers[] = { { .name = "vector_catch", .handler = handle_arm9tdmi_catch_vectors_command, .mode = COMMAND_EXEC, .help = "Display, after optionally updating, configuration " "of vector catch unit.", .usage = "[all|none|(reset|undef|swi|pabt|dabt|irq|fiq)*]", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm9tdmi_command_handlers[] = { { .chain = arm7_9_command_handlers, }, { .name = "arm9", .mode = COMMAND_ANY, .help = "arm9 command group", .usage = "", .chain = arm9tdmi_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM9TDMI targets. */ struct target_type arm9tdmi_target = { .name = "arm9tdmi", .poll = arm7_9_poll, .arch_state = arm_arch_state, .target_request_data = arm7_9_target_request_data, .halt = arm7_9_halt, .resume = arm7_9_resume, .step = arm7_9_step, .assert_reset = arm7_9_assert_reset, .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = arm7_9_add_breakpoint, .remove_breakpoint = arm7_9_remove_breakpoint, .add_watchpoint = arm7_9_add_watchpoint, .remove_watchpoint = arm7_9_remove_watchpoint, .commands = arm9tdmi_command_handlers, .target_create = arm9tdmi_target_create, .init_target = arm9tdmi_init_target, .examine = arm7_9_examine, .check_reset = arm7_9_check_reset, }; openocd-0.9.0/src/target/arm9tdmi.h0000644000175000017500000000611312315575361014055 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM9TDMI_H #define ARM9TDMI_H #include "embeddedice.h" int arm9tdmi_init_target(struct command_context *cmd_ctx, struct target *target); int arm9tdmi_init_arch_info(struct target *target, struct arm7_9_common *arm7_9, struct jtag_tap *tap); extern const struct command_registration arm9tdmi_command_handlers[]; int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr, uint32_t out, uint32_t *in, int sysspeed); int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in); int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info, void *in, int size, int be); void arm9tdmi_read_core_regs(struct target *target, uint32_t mask, uint32_t *core_regs[16]); void arm9tdmi_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16]); int arm9tdmi_examine_debug_reason(struct target *target); void arm9tdmi_load_word_regs(struct target *target, uint32_t mask); void arm9tdmi_load_hword_reg(struct target *target, int num); void arm9tdmi_load_byte_reg(struct target *target, int num); void arm9tdmi_store_word_regs(struct target *target, uint32_t mask); void arm9tdmi_store_hword_reg(struct target *target, int num); void arm9tdmi_store_byte_reg(struct target *target, int num); void arm9tdmi_branch_resume(struct target *target); void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc); void arm9tdmi_disable_single_step(struct target *target); #endif /* ARM9TDMI_H */ openocd-0.9.0/src/target/armv7a.c0000644000175000017500000006142712516456303013525 00000000000000/*************************************************************************** * Copyright (C) 2009 by David Brownell * * * * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "armv7a.h" #include "arm_disassembler.h" #include "register.h" #include #include #include #include #include #include "arm_opcodes.h" #include "target.h" #include "target_type.h" static void armv7a_show_fault_registers(struct target *target) { uint32_t dfsr, ifsr, dfar, ifar; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; int retval; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return; /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */ /* c5/c0 - {data, instruction} fault status registers */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 5, 0, 0), &dfsr); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 5, 0, 1), &ifsr); if (retval != ERROR_OK) goto done; /* c6/c0 - {data, instruction} fault address registers */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 6, 0, 0), &dfar); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 6, 0, 2), &ifar); if (retval != ERROR_OK) goto done; LOG_USER("Data fault registers DFSR: %8.8" PRIx32 ", DFAR: %8.8" PRIx32, dfsr, dfar); LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32 ", IFAR: %8.8" PRIx32, ifsr, ifar); done: /* (void) */ dpm->finish(dpm); } /* retrieve main id register */ static int armv7a_read_midr(struct target *target) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t midr; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* MRC p15,0,,c0,c0,0; read main id register*/ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 0, 0, 0), &midr); if (retval != ERROR_OK) goto done; armv7a->rev = (midr & 0xf); armv7a->partnum = (midr >> 4) & 0xfff; armv7a->arch = (midr >> 16) & 0xf; armv7a->variant = (midr >> 20) & 0xf; armv7a->implementor = (midr >> 24) & 0xff; LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 ", variant %" PRIx32 ", implementor %" PRIx32, target->cmd_name, armv7a->rev, armv7a->partnum, armv7a->arch, armv7a->variant, armv7a->implementor); done: dpm->finish(dpm); return retval; } static int armv7a_read_ttbcr(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t ttbcr; uint32_t ttbr0, ttbr1; int retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 2, 0, 2), &ttbcr); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 2, 0, 0), &ttbr0); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 2, 0, 1), &ttbr1); if (retval != ERROR_OK) goto done; LOG_INFO("ttbcr %" PRIx32 "ttbr0 %" PRIx32 "ttbr1 %" PRIx32, ttbcr, ttbr0, ttbr1); armv7a->armv7a_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0; armv7a->armv7a_mmu.ttbr0_mask = 0; retval = armv7a_read_midr(target); if (retval != ERROR_OK) goto done; if (armv7a->partnum & 0xf) { /* * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition), * document # ARM DDI 0406C */ armv7a->armv7a_mmu.ttbr0_mask = 1 << (14 - ((ttbcr & 0x7))); } else { /* ARM DDI 0344H , ARM DDI 0407F */ armv7a->armv7a_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7))); /* fix me , default is hard coded LINUX border */ armv7a->armv7a_mmu.os_border = 0xc0000000; } LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32, armv7a->armv7a_mmu.ttbr1_used ? "used" : "not used", armv7a->armv7a_mmu.ttbr0_mask); if (armv7a->armv7a_mmu.ttbr1_used == 1) { LOG_INFO("SVC access above %" PRIx32, (0xffffffff & armv7a->armv7a_mmu.ttbr0_mask)); armv7a->armv7a_mmu.os_border = 0xffffffff & armv7a->armv7a_mmu.ttbr0_mask; } done: dpm->finish(dpm); return retval; } /* method adapted to cortex A : reused arm v4 v5 method*/ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) { uint32_t first_lvl_descriptor = 0x0; uint32_t second_lvl_descriptor = 0x0; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t ttb = 0; /* default ttb0 */ if (armv7a->armv7a_mmu.ttbr1_used == -1) armv7a_read_ttbcr(target); if ((armv7a->armv7a_mmu.ttbr1_used) && (va > (0xffffffff & armv7a->armv7a_mmu.ttbr0_mask))) { /* select ttb 1 */ ttb = 1; } retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* MRC p15,0,,c2,c0,ttb */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 2, 0, ttb), &ttb); if (retval != ERROR_OK) return retval; retval = armv7a->armv7a_mmu.read_physical_memory(target, (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18), 4, 1, (uint8_t *)&first_lvl_descriptor); if (retval != ERROR_OK) return retval; first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) &first_lvl_descriptor); /* reuse armv4_5 piece of code, specific armv7a changes may come later */ LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor); if ((first_lvl_descriptor & 0x3) == 0) { LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } if ((first_lvl_descriptor & 0x40002) == 2) { /* section descriptor */ *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff); return ERROR_OK; } else if ((first_lvl_descriptor & 0x40002) == 0x40002) { /* supersection descriptor */ if (first_lvl_descriptor & 0x00f001e0) { LOG_ERROR("Physical address does not fit into 32 bits"); return ERROR_TARGET_TRANSLATION_FAULT; } *val = (first_lvl_descriptor & 0xff000000) | (va & 0x00ffffff); return ERROR_OK; } /* page table */ retval = armv7a->armv7a_mmu.read_physical_memory(target, (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10), 4, 1, (uint8_t *)&second_lvl_descriptor); if (retval != ERROR_OK) return retval; second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) &second_lvl_descriptor); LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor); if ((second_lvl_descriptor & 0x3) == 0) { LOG_ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } if ((second_lvl_descriptor & 0x3) == 1) { /* large page descriptor */ *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff); } else { /* small page descriptor */ *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff); } return ERROR_OK; done: return retval; } /* V7 method VA TO PA */ int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va, uint32_t *val, int meminfo) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t virt = va & ~0xfff; uint32_t NOS, NS, INNER, OUTER; *val = 0xdeadbeef; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* mmu must be enable in order to get a correct translation * use VA to PA CP15 register for conversion */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 8, 0), virt); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 7, 4, 0), val); /* decode memory attribute */ NOS = (*val >> 10) & 1; /* Not Outer shareable */ NS = (*val >> 9) & 1; /* Non secure */ INNER = (*val >> 4) & 0x7; OUTER = (*val >> 2) & 0x3; if (retval != ERROR_OK) goto done; *val = (*val & ~0xfff) + (va & 0xfff); if (*val == va) LOG_WARNING("virt = phys : MMU disable !!"); if (meminfo) { LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured", va, *val, NOS == 1 ? "not" : " ", NS == 1 ? "not" : ""); switch (OUTER) { case 0: LOG_INFO("outer: Non-Cacheable"); break; case 1: LOG_INFO("outer: Write-Back, Write-Allocate"); break; case 2: LOG_INFO("outer: Write-Through, No Write-Allocate"); break; case 3: LOG_INFO("outer: Write-Back, no Write-Allocate"); break; } switch (INNER) { case 0: LOG_INFO("inner: Non-Cacheable"); break; case 1: LOG_INFO("inner: Strongly-ordered"); break; case 3: LOG_INFO("inner: Device"); break; case 5: LOG_INFO("inner: Write-Back, Write-Allocate"); break; case 6: LOG_INFO("inner: Write-Through"); break; case 7: LOG_INFO("inner: Write-Back, no Write-Allocate"); default: LOG_INFO("inner: %" PRIx32 " ???", INNER); } } done: dpm->finish(dpm); return retval; } static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache) { if (armv7a_cache->ctype == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } command_print(cmd_ctx, "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", armv7a_cache->d_u_size.linelen, armv7a_cache->d_u_size.associativity, armv7a_cache->d_u_size.nsets, armv7a_cache->d_u_size.cachesize); command_print(cmd_ctx, "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", armv7a_cache->i_size.linelen, armv7a_cache->i_size.associativity, armv7a_cache->i_size.nsets, armv7a_cache->i_size.cachesize); return ERROR_OK; } static int _armv7a_flush_all_data(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; struct armv7a_cachesize *d_u_size = &(armv7a->armv7a_mmu.armv7a_cache.d_u_size); int32_t c_way, c_index = d_u_size->index; int retval; /* check that cache data is on at target halt */ if (!armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled) { LOG_INFO("flushed not performed :cache not on at target halt"); return ERROR_OK; } retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; do { c_way = d_u_size->way; do { uint32_t value = (c_index << d_u_size->index_shift) | (c_way << d_u_size->way_shift); /* DCCISW */ /* LOG_INFO ("%d %d %x",c_way,c_index,value); */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 14, 2), value); if (retval != ERROR_OK) goto done; c_way -= 1; } while (c_way >= 0); c_index -= 1; } while (c_index >= 0); return retval; done: LOG_ERROR("flushed failed"); dpm->finish(dpm); return retval; } static int armv7a_flush_all_data(struct target *target) { int retval = ERROR_FAIL; /* check that armv7a_cache is correctly identify */ struct armv7a_common *armv7a = target_to_armv7a(target); if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1) { LOG_ERROR("trying to flush un-identified cache"); return retval; } if (target->smp) { /* look if all the other target have been flushed in order to flush level * 2 */ struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if (curr->state == TARGET_HALTED) { LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); retval = _armv7a_flush_all_data(curr); } head = head->next; } } else retval = _armv7a_flush_all_data(target); return retval; } /* L2 is not specific to armv7a a specific file is needed */ static int armv7a_l2x_flush_all_data(struct target *target) { #define L2X0_CLEAN_INV_WAY 0x7FC int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) (armv7a->armv7a_mmu.armv7a_cache.l2_cache); uint32_t base = l2x_cache->base; uint32_t l2_way = l2x_cache->way; uint32_t l2_way_val = (1 << l2_way) - 1; retval = armv7a_flush_all_data(target); if (retval != ERROR_OK) return retval; retval = target->type->write_phys_memory(target, (uint32_t)(base+(uint32_t)L2X0_CLEAN_INV_WAY), (uint32_t)4, (uint32_t)1, (uint8_t *)&l2_way_val); return retval; } static int armv7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache) { struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) (armv7a_cache->l2_cache); if (armv7a_cache->ctype == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } command_print(cmd_ctx, "L1 D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", armv7a_cache->d_u_size.linelen, armv7a_cache->d_u_size.associativity, armv7a_cache->d_u_size.nsets, armv7a_cache->d_u_size.cachesize); command_print(cmd_ctx, "L1 I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", armv7a_cache->i_size.linelen, armv7a_cache->i_size.associativity, armv7a_cache->i_size.nsets, armv7a_cache->i_size.cachesize); command_print(cmd_ctx, "L2 unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways", l2x_cache->base, l2x_cache->way); return ERROR_OK; } static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) { struct armv7a_l2x_cache *l2x_cache; struct target_list *head = target->head; struct target *curr; struct armv7a_common *armv7a = target_to_armv7a(target); l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache)); l2x_cache->base = base; l2x_cache->way = way; /*LOG_INFO("cache l2 initialized base %x way %d", l2x_cache->base,l2x_cache->way);*/ if (armv7a->armv7a_mmu.armv7a_cache.l2_cache) LOG_INFO("cache l2 already initialized\n"); armv7a->armv7a_mmu.armv7a_cache.l2_cache = l2x_cache; /* initialize l1 / l2x cache function */ armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = armv7a_l2x_flush_all_data; armv7a->armv7a_mmu.armv7a_cache.display_cache_info = armv7a_handle_l2x_cache_info_command; /* initialize all target in this cluster (smp target) * l2 cache must be configured after smp declaration */ while (head != (struct target_list *)NULL) { curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); if (armv7a->armv7a_mmu.armv7a_cache.l2_cache) LOG_ERROR("smp target : cache l2 already initialized\n"); armv7a->armv7a_mmu.armv7a_cache.l2_cache = l2x_cache; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = armv7a_l2x_flush_all_data; armv7a->armv7a_mmu.armv7a_cache.display_cache_info = armv7a_handle_l2x_cache_info_command; } head = head->next; } return JIM_OK; } COMMAND_HANDLER(handle_cache_l2x) { struct target *target = get_current_target(CMD_CTX); uint32_t base, way; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way); /* AP address is in bits 31:24 of DP_SELECT */ armv7a_l2x_cache_init(target, base, way); return ERROR_OK; } int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache) { if (armv7a_cache->ctype == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } if (armv7a_cache->display_cache_info) armv7a_cache->display_cache_info(cmd_ctx, armv7a_cache); return ERROR_OK; } /* retrieve core id cluster id */ static int armv7a_read_mpidr(struct target *target) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t mpidr; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* MRC p15,0,,c0,c0,5; read Multiprocessor ID register*/ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 0, 0, 0, 0, 5), &mpidr); if (retval != ERROR_OK) goto done; /* ARMv7R uses a different format for MPIDR. * When configured uniprocessor (most R cores) it reads as 0. * This will need to be implemented for multiprocessor ARMv7R cores. */ if (armv7a->is_armv7r) { if (mpidr) LOG_ERROR("MPIDR nonzero in ARMv7-R target"); goto done; } if (mpidr & 1<<31) { armv7a->multi_processor_system = (mpidr >> 30) & 1; armv7a->cluster_id = (mpidr >> 8) & 0xf; armv7a->cpu_id = mpidr & 0x3; LOG_INFO("%s cluster %x core %x %s", target_name(target), armv7a->cluster_id, armv7a->cpu_id, armv7a->multi_processor_system == 0 ? "multi core" : "mono core"); } else LOG_ERROR("MPIDR not in multiprocessor format"); done: dpm->finish(dpm); return retval; } int armv7a_identify_cache(struct target *target) { /* read cache descriptor */ int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; uint32_t cache_selected, clidr; uint32_t cache_i_reg, cache_d_reg; struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache); if (!armv7a->is_armv7r) armv7a_read_ttbcr(target); retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* retrieve CLIDR * mrc p15, 1, r0, c0, c0, 1 @ read clidr */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 1, 0, 0, 0, 1), &clidr); if (retval != ERROR_OK) goto done; clidr = (clidr & 0x7000000) >> 23; LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2)); if ((clidr / 2) > 1) { /* FIXME not supported present in cortex A8 and later */ /* in cortex A7, A15 */ LOG_ERROR("cache l2 present :not supported"); } /* retrieve selected cache * MRC p15, 2,, c0, c0, 0; Read CSSELR */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 2, 0, 0, 0, 0), &cache_selected); if (retval != ERROR_OK) goto done; retval = armv7a->arm.mrc(target, 15, 2, 0, /* op1, op2 */ 0, 0, /* CRn, CRm */ &cache_selected); if (retval != ERROR_OK) goto done; /* select instruction cache * MCR p15, 2,, c0, c0, 0; Write CSSELR * [0] : 1 instruction cache selection , 0 data cache selection */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MRC(15, 2, 0, 0, 0, 0), 1); if (retval != ERROR_OK) goto done; /* read CCSIDR * MRC P15,1,,C0, C0,0 ;on cortex A9 read CCSIDR * [2:0] line size 001 eight word per line * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 1, 0, 0, 0, 0), &cache_i_reg); if (retval != ERROR_OK) goto done; /* select data cache*/ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MRC(15, 2, 0, 0, 0, 0), 0); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(15, 1, 0, 0, 0, 0), &cache_d_reg); if (retval != ERROR_OK) goto done; /* restore selected cache */ dpm->instr_write_data_r0(dpm, ARMV4_5_MRC(15, 2, 0, 0, 0, 0), cache_selected); if (retval != ERROR_OK) goto done; dpm->finish(dpm); /* put fake type */ cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7); cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8; cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff; cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1; /* compute info for set way operation on cache */ cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4; cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff; cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff); cache->d_u_size.way_shift = cache->d_u_size.way + 1; { int i = 0; while (((cache->d_u_size.way_shift >> i) & 1) != 1) i++; cache->d_u_size.way_shift = 32-i; } #if 0 LOG_INFO("data cache index %d << %d, way %d << %d", cache->d_u_size.index, cache->d_u_size.index_shift, cache->d_u_size.way, cache->d_u_size.way_shift); LOG_INFO("data cache %d bytes %d KBytes asso %d ways", cache->d_u_size.linelen, cache->d_u_size.cachesize, cache->d_u_size.associativity); #endif cache->i_size.linelen = 16 << (cache_i_reg & 0x7); cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1; cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff; cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8; /* compute info for set way operation on cache */ cache->i_size.index_shift = (cache_i_reg & 0x7) + 4; cache->i_size.index = (cache_i_reg >> 13) & 0x7fff; cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff); cache->i_size.way_shift = cache->i_size.way + 1; { int i = 0; while (((cache->i_size.way_shift >> i) & 1) != 1) i++; cache->i_size.way_shift = 32-i; } #if 0 LOG_INFO("instruction cache index %d << %d, way %d << %d", cache->i_size.index, cache->i_size.index_shift, cache->i_size.way, cache->i_size.way_shift); LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways", cache->i_size.linelen, cache->i_size.cachesize, cache->i_size.associativity); #endif /* if no l2 cache initialize l1 data cache flush function function */ if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) { armv7a->armv7a_mmu.armv7a_cache.display_cache_info = armv7a_handle_inner_cache_info_command; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = armv7a_flush_all_data; } armv7a->armv7a_mmu.armv7a_cache.ctype = 0; done: dpm->finish(dpm); armv7a_read_mpidr(target); return retval; } int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) { struct arm *arm = &armv7a->arm; arm->arch_info = armv7a; target->arch_info = &armv7a->arm; /* target is useful in all function arm v4 5 compatible */ armv7a->arm.target = target; armv7a->arm.common_magic = ARM_COMMON_MAGIC; armv7a->common_magic = ARMV7_COMMON_MAGIC; armv7a->armv7a_mmu.armv7a_cache.l2_cache = NULL; armv7a->armv7a_mmu.armv7a_cache.ctype = -1; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL; armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL; return ERROR_OK; } int armv7a_arch_state(struct target *target) { static const char *state[] = { "disabled", "enabled" }; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; if (armv7a->common_magic != ARMV7_COMMON_MAGIC) { LOG_ERROR("BUG: called for a non-ARMv7A target"); return ERROR_COMMAND_SYNTAX_ERROR; } arm_arch_state(target); if (armv7a->is_armv7r) { LOG_USER("D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]); } else { LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.mmu_enabled], state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]); } if (arm->core_mode == ARM_MODE_ABT) armv7a_show_fault_registers(target); if (target->debug_reason == DBG_REASON_WATCHPOINT) LOG_USER("Watchpoint triggered at PC %#08x", (unsigned) armv7a->dpm.wp_pc); return ERROR_OK; } static const struct command_registration l2_cache_commands[] = { { .name = "l2x", .handler = handle_cache_l2x, .mode = COMMAND_EXEC, .help = "configure l2x cache " "", .usage = "[base_addr] [number_of_way]", }, COMMAND_REGISTRATION_DONE }; const struct command_registration l2x_cache_command_handlers[] = { { .name = "cache_config", .mode = COMMAND_EXEC, .help = "cache configuration for a target", .usage = "", .chain = l2_cache_commands, }, COMMAND_REGISTRATION_DONE }; const struct command_registration armv7a_command_handlers[] = { { .chain = dap_command_handlers, }, { .chain = l2x_cache_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/armv7a.h0000644000175000017500000001250212516456303013520 00000000000000/*************************************************************************** * Copyright (C) 2009 by David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARMV7A_H #define ARMV7A_H #include "arm_adi_v5.h" #include "arm.h" #include "armv4_5_mmu.h" #include "armv4_5_cache.h" #include "arm_dpm.h" enum { ARM_PC = 15, ARM_CPSR = 16 }; #define ARMV7_COMMON_MAGIC 0x0A450999 /* VA to PA translation operations opc2 values*/ #define V2PCWPR 0 #define V2PCWPW 1 #define V2PCWUR 2 #define V2PCWUW 3 #define V2POWPR 4 #define V2POWPW 5 #define V2POWUR 6 #define V2POWUW 7 /* L210/L220 cache controller support */ struct armv7a_l2x_cache { uint32_t base; uint32_t way; }; struct armv7a_cachesize { uint32_t level_num; /* cache dimensionning */ uint32_t linelen; uint32_t associativity; uint32_t nsets; uint32_t cachesize; /* info for set way operation on cache */ uint32_t index; uint32_t index_shift; uint32_t way; uint32_t way_shift; }; struct armv7a_cache_common { int ctype; struct armv7a_cachesize d_u_size; /* data cache */ struct armv7a_cachesize i_size; /* instruction cache */ int i_cache_enabled; int d_u_cache_enabled; /* l2 external unified cache if some */ void *l2_cache; int (*flush_all_data_cache)(struct target *target); int (*display_cache_info)(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache); }; struct armv7a_mmu_common { /* following field mmu working way */ int32_t ttbr0_used; int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */ uint32_t ttbr0_mask;/* masked to be used */ uint32_t os_border; int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); struct armv7a_cache_common armv7a_cache; uint32_t mmu_enabled; }; struct armv7a_common { struct arm arm; int common_magic; struct reg_cache *core_cache; struct adiv5_dap dap; /* Core Debug Unit */ struct arm_dpm dpm; uint32_t debug_base; uint8_t debug_ap; uint8_t memory_ap; bool memory_ap_available; /* mdir */ uint8_t multi_processor_system; uint8_t cluster_id; uint8_t cpu_id; bool is_armv7r; uint32_t rev; uint32_t partnum; uint32_t arch; uint32_t variant; uint32_t implementor; /* cache specific to V7 Memory Management Unit compatible with v4_5*/ struct armv7a_mmu_common armv7a_mmu; int (*examine_debug_reason)(struct target *target); int (*post_debug_entry)(struct target *target); void (*pre_restore_context)(struct target *target); }; static inline struct armv7a_common * target_to_armv7a(struct target *target) { return container_of(target->arch_info, struct armv7a_common, arm); } /* register offsets from armv7a.debug_base */ /* See ARMv7a arch spec section C10.2 */ #define CPUDBG_DIDR 0x000 /* See ARMv7a arch spec section C10.3 */ #define CPUDBG_WFAR 0x018 /* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */ #define CPUDBG_DSCR 0x088 #define CPUDBG_DRCR 0x090 #define CPUDBG_PRCR 0x310 #define CPUDBG_PRSR 0x314 /* See ARMv7a arch spec section C10.4 */ #define CPUDBG_DTRRX 0x080 #define CPUDBG_ITR 0x084 #define CPUDBG_DTRTX 0x08c /* See ARMv7a arch spec section C10.5 */ #define CPUDBG_BVR_BASE 0x100 #define CPUDBG_BCR_BASE 0x140 #define CPUDBG_WVR_BASE 0x180 #define CPUDBG_WCR_BASE 0x1C0 #define CPUDBG_VCR 0x01C /* See ARMv7a arch spec section C10.6 */ #define CPUDBG_OSLAR 0x300 #define CPUDBG_OSLSR 0x304 #define CPUDBG_OSSRR 0x308 #define CPUDBG_ECR 0x024 /* See ARMv7a arch spec section C10.7 */ #define CPUDBG_DSCCR 0x028 /* See ARMv7a arch spec section C10.8 */ #define CPUDBG_AUTHSTATUS 0xFB8 int armv7a_arch_state(struct target *target); int armv7a_identify_cache(struct target *target); int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a); int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va, uint32_t *val, int meminfo); int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val); int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache); extern const struct command_registration armv7a_command_handlers[]; #endif /* ARMV4_5_H */ openocd-0.9.0/src/target/armv7m.c0000644000175000017500000006731012516456303013536 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * ARMv7-M Architecture, Application Level Reference Manual * * ARM DDI 0405C (September 2008) * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "armv7m.h" #include "algorithm.h" #include "register.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif static const char * const armv7m_exception_strings[] = { "", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "SVCall", "DebugMonitor", "RESERVED", "PendSV", "SysTick" }; /* PSP is used in some thread modes */ const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = { ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3, ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7, ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11, ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC, ARMV7M_xPSR, }; /* MSP is used in handler and some thread modes */ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = { ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3, ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7, ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11, ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC, ARMV7M_xPSR, }; /* * These registers are not memory-mapped. The ARMv7-M profile includes * memory mapped registers too, such as for the NVIC (interrupt controller) * and SysTick (timer) modules; those can mostly be treated as peripherals. * * The ARMv6-M profile is almost identical in this respect, except that it * doesn't include basepri or faultmask registers. */ static const struct { unsigned id; const char *name; unsigned bits; enum reg_type type; const char *group; const char *feature; } armv7m_regs[] = { { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" }, }; #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs) /** * Restores target context using the cache of core registers set up * by armv7m_build_reg_cache(), calling optional core-specific hooks. */ int armv7m_restore_context(struct target *target) { int i; struct armv7m_common *armv7m = target_to_armv7m(target); struct reg_cache *cache = armv7m->arm.core_cache; LOG_DEBUG(" "); if (armv7m->pre_restore_context) armv7m->pre_restore_context(target); for (i = cache->num_regs - 1; i >= 0; i--) { if (cache->reg_list[i].dirty) { armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, cache->reg_list[i].value); } } return ERROR_OK; } /* Core state functions */ /** * Maps ISR number (from xPSR) to name. * Note that while names and meanings for the first sixteen are standardized * (with zero not a true exception), external interrupts are only numbered. * They are assigned by vendors, which generally assign different numbers to * peripherals (such as UART0 or a USB peripheral controller). */ const char *armv7m_exception_string(int number) { static char enamebuf[32]; if ((number < 0) | (number > 511)) return "Invalid exception"; if (number < 16) return armv7m_exception_strings[number]; sprintf(enamebuf, "External Interrupt(%i)", number - 16); return enamebuf; } static int armv7m_get_core_reg(struct reg *reg) { int retval; struct arm_reg *armv7m_reg = reg->arch_info; struct target *target = armv7m_reg->target; struct arm *arm = target_to_arm(target); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode); return retval; } static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) { struct arm_reg *armv7m_reg = reg->arch_info; struct target *target = armv7m_reg->target; if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; buf_cpy(buf, reg->value, reg->size); reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static int armv7m_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { uint32_t reg_value; int retval; struct arm_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { /* map D0..D15 to S0..S31 */ size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0); retval = armv7m->load_core_reg_u32(target, regidx, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); retval = armv7m->load_core_reg_u32(target, regidx + 1, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4, 0, 32, reg_value); } else { retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->num, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); } armv7m->arm.core_cache->reg_list[num].valid = 1; armv7m->arm.core_cache->reg_list[num].dirty = 0; return retval; } static int armv7m_write_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode, uint8_t *value) { int retval; struct arm_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { /* map D0..D15 to S0..S31 */ size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0); uint32_t t = buf_get_u32(value, 0, 32); retval = armv7m->store_core_reg_u32(target, regidx, t); if (retval != ERROR_OK) goto out_error; t = buf_get_u32(value + 4, 0, 32); retval = armv7m->store_core_reg_u32(target, regidx + 1, t); if (retval != ERROR_OK) goto out_error; } else { uint32_t t = buf_get_u32(value, 0, 32); LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t); retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->num, t); if (retval != ERROR_OK) goto out_error; } armv7m->arm.core_cache->reg_list[num].valid = 1; armv7m->arm.core_cache->reg_list[num].dirty = 0; return ERROR_OK; out_error: LOG_ERROR("Error setting register"); armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid; return ERROR_JTAG_DEVICE_ERROR; } /** * Returns generic ARM userspace registers to GDB. */ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct armv7m_common *armv7m = target_to_armv7m(target); int i; if (reg_class == REG_CLASS_ALL) *reg_list_size = armv7m->arm.core_cache->num_regs; else *reg_list_size = ARMV7M_NUM_CORE_REGS; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); if (*reg_list == NULL) return ERROR_FAIL; for (i = 0; i < *reg_list_size; i++) (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i]; return ERROR_OK; } /** Runs a Thumb algorithm in the target. */ int armv7m_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval; retval = armv7m_start_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, arch_info); if (retval == ERROR_OK) retval = armv7m_wait_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, exit_point, timeout_ms, arch_info); return retval; } /** Starts a Thumb algorithm in the target. */ int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_algorithm *armv7m_algorithm_info = arch_info; enum arm_mode core_mode = armv7m->arm.core_mode; int retval = ERROR_OK; /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { LOG_ERROR("current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* refresh core register cache * Not needed if core register cache is always consistent with target process state */ for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) { armv7m_algorithm_info->context[i] = buf_get_u32( armv7m->arm.core_cache->reg_list[i].value, 0, 32); } for (int i = 0; i < num_mem_params; i++) { /* TODO: Write only out params */ retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } for (int i = 0; i < num_reg_params; i++) { struct reg *reg = register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0); /* uint32_t regvalue; */ if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } /* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */ armv7m_set_core_reg(reg, reg_params[i].value); } if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY && armv7m_algorithm_info->core_mode != core_mode) { /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */ if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) { armv7m_algorithm_info->core_mode = ARM_MODE_THREAD; LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); } LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; } /* save previous core mode */ armv7m_algorithm_info->core_mode = core_mode; retval = target_resume(target, 0, entry_point, 1, 1); return retval; } /** Waits for an algorithm in the target. */ int armv7m_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t exit_point, int timeout_ms, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_algorithm *armv7m_algorithm_info = arch_info; int retval = ERROR_OK; uint32_t pc; /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { LOG_ERROR("current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } retval = target_wait_state(target, TARGET_HALTED, timeout_ms); /* If the target fails to halt due to the breakpoint, force a halt */ if (retval != ERROR_OK || target->state != TARGET_HALTED) { retval = target_halt(target); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, 500); if (retval != ERROR_OK) return retval; return ERROR_TARGET_TIMEOUT; } armv7m->load_core_reg_u32(target, 15, &pc); if (exit_point && (pc != exit_point)) { LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32, pc, exit_point); return ERROR_TARGET_TIMEOUT; } /* Read memory values to mem_params[] */ for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) { retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } } /* Copy core register values to reg_params[] */ for (int i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { struct reg *reg = register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { LOG_ERROR( "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } for (int i = armv7m->arm.core_cache->num_regs - 1; i >= 0; i--) { uint32_t regvalue; regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32); if (regvalue != armv7m_algorithm_info->context[i]) { LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, armv7m->arm.core_cache->reg_list[i].name, armv7m_algorithm_info->context[i]); buf_set_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32, armv7m_algorithm_info->context[i]); armv7m->arm.core_cache->reg_list[i].valid = 1; armv7m->arm.core_cache->reg_list[i].dirty = 1; } } /* restore previous core mode */ if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) { LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; } armv7m->arm.core_mode = armv7m_algorithm_info->core_mode; return retval; } /** Logs summary of ARMv7-M state for a halted target. */ int armv7m_arch_state(struct target *target) { struct armv7m_common *armv7m = target_to_armv7m(target); struct arm *arm = &armv7m->arm; uint32_t ctrl, sp; ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32); LOG_USER("target halted due to %s, current mode: %s %s\n" "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s", debug_reason_name(target), arm_mode_name(arm->core_mode), armv7m_exception_string(armv7m->exception_number), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), (ctrl & 0x02) ? 'p' : 'm', sp, arm->is_semihosting ? ", semihosting" : ""); return ERROR_OK; } static const struct reg_arch_type armv7m_reg_type = { .get = armv7m_get_core_reg, .set = armv7m_set_core_reg, }; /** Builds cache of architecturally defined registers. */ struct reg_cache *armv7m_build_reg_cache(struct target *target) { struct armv7m_common *armv7m = target_to_armv7m(target); struct arm *arm = &armv7m->arm; int num_regs = ARMV7M_NUM_REGS; struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg)); struct reg_feature *feature; int i; /* Build the process context cache */ cache->name = "arm v7m registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = num_regs; (*cache_p) = cache; for (i = 0; i < num_regs; i++) { arch_info[i].num = armv7m_regs[i].id; arch_info[i].target = target; arch_info[i].arm = arm; reg_list[i].name = armv7m_regs[i].name; reg_list[i].size = armv7m_regs[i].bits; size_t storage_size = DIV_ROUND_UP(armv7m_regs[i].bits, 8); if (storage_size < 4) storage_size = 4; reg_list[i].value = calloc(1, storage_size); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &armv7m_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].group = armv7m_regs[i].group; reg_list[i].number = i; reg_list[i].exist = true; reg_list[i].caller_save = true; /* gdb defaults to true */ feature = calloc(1, sizeof(struct reg_feature)); if (feature) { feature->name = armv7m_regs[i].feature; reg_list[i].feature = feature; } else LOG_ERROR("unable to allocate feature list"); reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); if (reg_list[i].reg_data_type) reg_list[i].reg_data_type->type = armv7m_regs[i].type; else LOG_ERROR("unable to allocate reg type list"); } arm->cpsr = reg_list + ARMV7M_xPSR; arm->pc = reg_list + ARMV7M_PC; arm->core_cache = cache; return cache; } static int armv7m_setup_semihosting(struct target *target, int enable) { /* nothing todo for armv7m */ return ERROR_OK; } /** Sets up target as a generic ARMv7-M core */ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) { struct arm *arm = &armv7m->arm; armv7m->common_magic = ARMV7M_COMMON_MAGIC; armv7m->fp_feature = FP_NONE; armv7m->trace_config.trace_bus_id = 1; /* Enable stimulus port #0 by default */ armv7m->trace_config.itm_ter[0] = 1; arm->core_type = ARM_MODE_THREAD; arm->arch_info = armv7m; arm->setup_semihosting = armv7m_setup_semihosting; arm->read_core_reg = armv7m_read_core_reg; arm->write_core_reg = armv7m_write_core_reg; return arm_init_arch_info(target, arm); } /** Generates a CRC32 checksum of a memory region. */ int armv7m_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct armv7m_algorithm armv7m_info; struct reg_param reg_params[2]; int retval; /* see contrib/loaders/checksum/armv7m_crc.s for src */ static const uint8_t cortex_m_crc_code[] = { /* main: */ 0x02, 0x46, /* mov r2, r0 */ 0x00, 0x20, /* movs r0, #0 */ 0xC0, 0x43, /* mvns r0, r0 */ 0x0A, 0x4E, /* ldr r6, CRC32XOR */ 0x0B, 0x46, /* mov r3, r1 */ 0x00, 0x24, /* movs r4, #0 */ 0x0D, 0xE0, /* b ncomp */ /* nbyte: */ 0x11, 0x5D, /* ldrb r1, [r2, r4] */ 0x09, 0x06, /* lsls r1, r1, #24 */ 0x48, 0x40, /* eors r0, r0, r1 */ 0x00, 0x25, /* movs r5, #0 */ /* loop: */ 0x00, 0x28, /* cmp r0, #0 */ 0x02, 0xDA, /* bge notset */ 0x40, 0x00, /* lsls r0, r0, #1 */ 0x70, 0x40, /* eors r0, r0, r6 */ 0x00, 0xE0, /* b cont */ /* notset: */ 0x40, 0x00, /* lsls r0, r0, #1 */ /* cont: */ 0x01, 0x35, /* adds r5, r5, #1 */ 0x08, 0x2D, /* cmp r5, #8 */ 0xF6, 0xD1, /* bne loop */ 0x01, 0x34, /* adds r4, r4, #1 */ /* ncomp: */ 0x9C, 0x42, /* cmp r4, r3 */ 0xEF, 0xD1, /* bne nbyte */ 0x00, 0xBE, /* bkpt #0 */ 0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */ }; retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm); if (retval != ERROR_OK) return retval; retval = target_write_buffer(target, crc_algorithm->address, sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code); if (retval != ERROR_OK) goto cleanup; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); buf_set_u32(reg_params[1].value, 0, 32, count); int timeout = 20000 * (1 + (count / (1024 * 1024))); retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6), timeout, &armv7m_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); else LOG_ERROR("error executing cortex_m crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); cleanup: target_free_working_area(target, crc_algorithm); return retval; } /** Checks whether a memory region is zeroed. */ int armv7m_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; int retval; /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */ static const uint8_t erase_check_code[] = { /* loop: */ 0x03, 0x78, /* ldrb r3, [r0] */ 0x01, 0x30, /* adds r0, #1 */ 0x1A, 0x40, /* ands r2, r2, r3 */ 0x01, 0x39, /* subs r1, r1, #1 */ 0xFA, 0xD1, /* bne loop */ 0x00, 0xBE /* bkpt #0 */ }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; retval = target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), (uint8_t *)erase_check_code); if (retval != ERROR_OK) return retval; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, 0xff); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 2), 10000, &armv7m_info); if (retval == ERROR_OK) *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); target_free_working_area(target, erase_check_algorithm); return retval; } int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found) { struct armv7m_common *armv7m = target_to_armv7m(target); struct reg *r = armv7m->arm.pc; bool result = false; /* if we halted last time due to a bkpt instruction * then we have to manually step over it, otherwise * the core will break again */ if (target->debug_reason == DBG_REASON_BREAKPOINT) { uint16_t op; uint32_t pc = buf_get_u32(r->value, 0, 32); pc &= ~1; if (target_read_u16(target, pc, &op) == ERROR_OK) { if ((op & 0xFF00) == 0xBE00) { pc = buf_get_u32(r->value, 0, 32) + 2; buf_set_u32(r->value, 0, 32, pc); r->dirty = true; r->valid = true; result = true; LOG_DEBUG("Skipping over BKPT instruction"); } } } if (inst_found) *inst_found = result; return ERROR_OK; } const struct command_registration armv7m_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = dap_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/armv7m.h0000644000175000017500000001423712516456303013543 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARMV7M_COMMON_H #define ARMV7M_COMMON_H #include "arm_adi_v5.h" #include "arm.h" #include "armv7m_trace.h" extern const int armv7m_psp_reg_map[]; extern const int armv7m_msp_reg_map[]; const char *armv7m_exception_string(int number); /* offsets into armv7m core register cache */ enum { /* for convenience, the first set of indices match * the Cortex-M3/-M4 DCRSR selectors */ ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3, ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7, ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11, ARMV7M_R12, ARMV7M_R13, ARMV7M_R14, ARMV7M_PC = 15, ARMV7M_xPSR = 16, ARMV7M_MSP, ARMV7M_PSP, /* this next set of indices is arbitrary */ ARMV7M_PRIMASK, ARMV7M_BASEPRI, ARMV7M_FAULTMASK, ARMV7M_CONTROL, /* 32bit Floating-point registers */ ARMV7M_S0, ARMV7M_S1, ARMV7M_S2, ARMV7M_S3, ARMV7M_S4, ARMV7M_S5, ARMV7M_S6, ARMV7M_S7, ARMV7M_S8, ARMV7M_S9, ARMV7M_S10, ARMV7M_S11, ARMV7M_S12, ARMV7M_S13, ARMV7M_S14, ARMV7M_S15, ARMV7M_S16, ARMV7M_S17, ARMV7M_S18, ARMV7M_S19, ARMV7M_S20, ARMV7M_S21, ARMV7M_S22, ARMV7M_S23, ARMV7M_S24, ARMV7M_S25, ARMV7M_S26, ARMV7M_S27, ARMV7M_S28, ARMV7M_S29, ARMV7M_S30, ARMV7M_S31, /* 64bit Floating-point registers */ ARMV7M_D0, ARMV7M_D1, ARMV7M_D2, ARMV7M_D3, ARMV7M_D4, ARMV7M_D5, ARMV7M_D6, ARMV7M_D7, ARMV7M_D8, ARMV7M_D9, ARMV7M_D10, ARMV7M_D11, ARMV7M_D12, ARMV7M_D13, ARMV7M_D14, ARMV7M_D15, /* Floating-point status registers */ ARMV7M_FPSID, ARMV7M_FPSCR, ARMV7M_FPEXC, ARMV7M_LAST_REG, }; enum { FP_NONE = 0, FPv4_SP, }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) #define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_NUM_CORE_REGS + 6) #define ARMV7M_COMMON_MAGIC 0x2A452A45 struct armv7m_common { struct arm arm; int common_magic; int exception_number; struct adiv5_dap dap; int fp_feature; uint32_t demcr; /* stlink is a high level adapter, does not support all functions */ bool stlink; struct armv7m_trace_config trace_config; /* Direct processor core register read and writes */ int (*load_core_reg_u32)(struct target *target, uint32_t num, uint32_t *value); int (*store_core_reg_u32)(struct target *target, uint32_t num, uint32_t value); int (*examine_debug_reason)(struct target *target); int (*post_debug_entry)(struct target *target); void (*pre_restore_context)(struct target *target); }; static inline struct armv7m_common * target_to_armv7m(struct target *target) { return container_of(target->arch_info, struct armv7m_common, arm); } static inline bool is_armv7m(struct armv7m_common *armv7m) { return armv7m->common_magic == ARMV7M_COMMON_MAGIC; } struct armv7m_algorithm { int common_magic; enum arm_mode core_mode; uint32_t context[ARMV7M_LAST_REG]; /* ARMV7M_NUM_REGS */ }; struct reg_cache *armv7m_build_reg_cache(struct target *target); enum armv7m_mode armv7m_number_to_mode(int number); int armv7m_mode_to_number(enum armv7m_mode mode); int armv7m_arch_state(struct target *target); int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m); int armv7m_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, void *arch_info); int armv7m_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t exit_point, int timeout_ms, void *arch_info); int armv7m_invalidate_core_regs(struct target *target); int armv7m_restore_context(struct target *target); int armv7m_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int armv7m_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank); int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found); extern const struct command_registration armv7m_command_handlers[]; #endif /* ARMV7M_H */ openocd-0.9.0/src/target/arm_dpm.c0000644000175000017500000006140312516456303013741 00000000000000/* * Copyright (C) 2009 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "arm_dpm.h" #include #include "register.h" #include "breakpoints.h" #include "target_type.h" #include "arm_opcodes.h" /** * @file * Implements various ARM DPM operations using architectural debug registers. * These routines layer over core-specific communication methods to cope with * implementation differences between cores like ARM1136 and Cortex-A8. * * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by * Part C (Debug Architecture) of the ARM Architecture Reference Manual, * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations * are abstracted through internal programming interfaces to share code and * to minimize needless differences in debug behavior between cores. */ /*----------------------------------------------------------------------*/ /* * Coprocessor support */ /* Read coprocessor */ static int dpm_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum, (int) op1, (int) CRn, (int) CRm, (int) op2); /* read coprocessor register into R0; return via DCC */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2), value); /* (void) */ dpm->finish(dpm); return retval; } static int dpm_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum, (int) op1, (int) CRn, (int) CRm, (int) op2); /* read DCC into r0; then write coprocessor register from R0 */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2), value); /* (void) */ dpm->finish(dpm); return retval; } /*----------------------------------------------------------------------*/ /* * Register access utilities */ /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one. * Routines *must* restore the original mode before returning!! */ int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) { int retval; uint32_t cpsr; /* restore previous mode */ if (mode == ARM_MODE_ANY) cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32); /* else force to the specified mode */ else cpsr = mode; retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr); if (retval != ERROR_OK) return retval; if (dpm->instr_cpsr_sync) retval = dpm->instr_cpsr_sync(dpm); return retval; } /* just read the register -- rely on the core mode being right */ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { uint32_t value; int retval; switch (regnum) { case 0 ... 14: /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ retval = dpm->instr_read_data_dcc(dpm, ARMV4_5_MCR(14, 0, regnum, 0, 5, 0), &value); break; case 15:/* PC * "MOV r0, pc"; then return via DCC */ retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value); /* NOTE: this seems like a slightly awkward place to update * this value ... but if the PC gets written (the only way * to change what we compute), the arch spec says subsequent * reads return values which are "unpredictable". So this * is always right except in those broken-by-intent cases. */ switch (dpm->arm->core_state) { case ARM_STATE_ARM: value -= 8; break; case ARM_STATE_THUMB: case ARM_STATE_THUMB_EE: value -= 4; break; case ARM_STATE_JAZELLE: /* core-specific ... ? */ LOG_WARNING("Jazelle PC adjustment unknown"); break; } break; default: /* 16: "MRS r0, CPSR"; then return via DCC * 17: "MRS r0, SPSR"; then return via DCC */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, regnum & 1), &value); break; } if (retval == ERROR_OK) { buf_set_u32(r->value, 0, 32, value); r->valid = true; r->dirty = false; LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); } return retval; } /* just write the register -- rely on the core mode being right */ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { int retval; uint32_t value = buf_get_u32(r->value, 0, 32); switch (regnum) { case 0 ... 14: /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */ retval = dpm->instr_write_data_dcc(dpm, ARMV4_5_MRC(14, 0, regnum, 0, 5, 0), value); break; case 15:/* PC * read r0 from DCC; then "MOV pc, r0" */ retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value); break; default: /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf" * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf" */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MSR_GP(0, 0xf, regnum & 1), value); if (retval != ERROR_OK) return retval; if (regnum == 16 && dpm->instr_cpsr_sync) retval = dpm->instr_cpsr_sync(dpm); break; } if (retval == ERROR_OK) { r->dirty = false; LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); } return retval; } /** * Read basic registers of the the current context: R0 to R15, and CPSR; * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). * In normal operation this is called on entry to halting debug state, * possibly after some other operations supporting restore of debug state * or making sure the CPU is fully idle (drain write buffer, etc). */ int arm_dpm_read_current_registers(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; uint32_t cpsr; int retval; struct reg *r; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; /* read R0 first (it's used for scratch), then CPSR */ r = arm->core_cache->reg_list + 0; if (!r->valid) { retval = dpm_read_reg(dpm, r, 0); if (retval != ERROR_OK) goto fail; } r->dirty = true; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr); if (retval != ERROR_OK) goto fail; /* update core mode and state, plus shadow mapping for R8..R14 */ arm_set_cpsr(arm, cpsr); /* REVISIT we can probably avoid reading R1..R14, saving time... */ for (unsigned i = 1; i < 16; i++) { r = arm_reg_current(arm, i); if (r->valid) continue; retval = dpm_read_reg(dpm, r, i); if (retval != ERROR_OK) goto fail; } /* NOTE: SPSR ignored (if it's even relevant). */ /* REVISIT the debugger can trigger various exceptions. See the * ARMv7A architecture spec, section C5.7, for more info about * what defenses are needed; v6 debug has the most issues. */ fail: /* (void) */ dpm->finish(dpm); return retval; } /* Avoid needless I/O ... leave breakpoints and watchpoints alone * unless they're removed, or need updating because of single-stepping * or running debugger code. */ static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, struct dpm_bpwp *xp, int *set_p) { int retval = ERROR_OK; bool disable; if (!set_p) { if (!xp->dirty) goto done; xp->dirty = false; /* removed or startup; we must disable it */ disable = true; } else if (bpwp) { if (!xp->dirty) goto done; /* disabled, but we must set it */ xp->dirty = disable = false; *set_p = true; } else { if (!*set_p) goto done; /* set, but we must temporarily disable it */ xp->dirty = disable = true; *set_p = false; } if (disable) retval = dpm->bpwp_disable(dpm, xp->number); else retval = dpm->bpwp_enable(dpm, xp->number, xp->address, xp->control); if (retval != ERROR_OK) LOG_ERROR("%s: can't %s HW %spoint %d", disable ? "disable" : "enable", target_name(dpm->arm->target), (xp->number < 16) ? "break" : "watch", xp->number & 0xf); done: return retval; } static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp); /** * Writes all modified core registers for all processor modes. In normal * operation this is called on exit from halting debug state. * * @param dpm: represents the processor * @param bpwp: true ensures breakpoints and watchpoints are set, * false ensures they are cleared */ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) { struct arm *arm = dpm->arm; struct reg_cache *cache = arm->core_cache; int retval; bool did_write; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* If we're managing hardware breakpoints for this core, enable * or disable them as requested. * * REVISIT We don't yet manage them for ANY cores. Eventually * we should be able to assume we handle them; but until then, * cope with the hand-crafted breakpoint code. */ if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { for (unsigned i = 0; i < dpm->nbp; i++) { struct dpm_bp *dbp = dpm->dbp + i; struct breakpoint *bp = dbp->bp; retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, bp ? &bp->set : NULL); if (retval != ERROR_OK) goto done; } } /* enable/disable watchpoints */ for (unsigned i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, wp ? &wp->set : NULL); if (retval != ERROR_OK) goto done; } /* NOTE: writes to breakpoint and watchpoint registers might * be queued, and need (efficient/batched) flushing later. */ /* Scan the registers until we find one that's both dirty and * eligible for flushing. Flush that and everything else that * shares the same core mode setting. Typically this won't * actually find anything to do... */ do { enum arm_mode mode = ARM_MODE_ANY; did_write = false; /* check everything except our scratch register R0 */ for (unsigned i = 1; i < cache->num_regs; i++) { struct arm_reg *r; unsigned regnum; /* also skip PC, CPSR, and non-dirty */ if (i == 15) continue; if (arm->cpsr == cache->reg_list + i) continue; if (!cache->reg_list[i].dirty) continue; r = cache->reg_list[i].arch_info; regnum = r->num; /* may need to pick and set a mode */ if (!did_write) { enum arm_mode tmode; did_write = true; mode = tmode = r->mode; /* cope with special cases */ switch (regnum) { case 8 ... 12: /* r8..r12 "anything but FIQ" case; * we "know" core mode is accurate * since we haven't changed it yet */ if (arm->core_mode == ARM_MODE_FIQ && ARM_MODE_ANY != mode) tmode = ARM_MODE_USR; break; case 16: /* SPSR */ regnum++; break; } /* REVISIT error checks */ if (tmode != ARM_MODE_ANY) { retval = dpm_modeswitch(dpm, tmode); if (retval != ERROR_OK) goto done; } } if (r->mode != mode) continue; retval = dpm_write_reg(dpm, &cache->reg_list[i], regnum); if (retval != ERROR_OK) goto done; } } while (did_write); /* Restore original CPSR ... assuming either that we changed it, * or it's dirty. Must write PC to ensure the return address is * defined, and must not write it before CPSR. */ retval = dpm_modeswitch(dpm, ARM_MODE_ANY); if (retval != ERROR_OK) goto done; arm->cpsr->dirty = false; retval = dpm_write_reg(dpm, arm->pc, 15); if (retval != ERROR_OK) goto done; arm->pc->dirty = false; /* flush R0 -- it's *very* dirty by now */ retval = dpm_write_reg(dpm, &cache->reg_list[0], 0); if (retval != ERROR_OK) goto done; cache->reg_list[0].dirty = false; /* (void) */ dpm->finish(dpm); done: return retval; } /* Returns ARM_MODE_ANY or temporary mode to use while reading the * specified register ... works around flakiness from ARM core calls. * Caller already filtered out SPSR access; mode is never MODE_SYS * or MODE_ANY. */ static enum arm_mode dpm_mapmode(struct arm *arm, unsigned num, enum arm_mode mode) { enum arm_mode amode = arm->core_mode; /* don't switch if the mode is already correct */ if (amode == ARM_MODE_SYS) amode = ARM_MODE_USR; if (mode == amode) return ARM_MODE_ANY; switch (num) { /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */ case 0 ... 7: case 15: case 16: break; /* r8..r12 aren't shadowed for anything except FIQ */ case 8 ... 12: if (mode == ARM_MODE_FIQ) return mode; break; /* r13/sp, and r14/lr are always shadowed */ case 13: case 14: return mode; default: LOG_WARNING("invalid register #%u", num); break; } return ARM_MODE_ANY; } /* * Standard ARM register accessors ... there are three methods * in "struct arm", to support individual read/write and bulk read * of registers. */ static int arm_dpm_read_core_reg(struct target *target, struct reg *r, int regnum, enum arm_mode mode) { struct arm_dpm *dpm = target_to_arm(target)->dpm; int retval; if (regnum < 0 || regnum > 16) return ERROR_COMMAND_SYNTAX_ERROR; if (regnum == 16) { if (mode != ARM_MODE_ANY) regnum = 17; } else mode = dpm_mapmode(dpm->arm, regnum, mode); /* REVISIT what happens if we try to read SPSR in a core mode * which has no such register? */ retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; if (mode != ARM_MODE_ANY) { retval = dpm_modeswitch(dpm, mode); if (retval != ERROR_OK) goto fail; } retval = dpm_read_reg(dpm, r, regnum); if (retval != ERROR_OK) goto fail; /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY); fail: /* (void) */ dpm->finish(dpm); return retval; } static int arm_dpm_write_core_reg(struct target *target, struct reg *r, int regnum, enum arm_mode mode, uint8_t *value) { struct arm_dpm *dpm = target_to_arm(target)->dpm; int retval; if (regnum < 0 || regnum > 16) return ERROR_COMMAND_SYNTAX_ERROR; if (regnum == 16) { if (mode != ARM_MODE_ANY) regnum = 17; } else mode = dpm_mapmode(dpm->arm, regnum, mode); /* REVISIT what happens if we try to write SPSR in a core mode * which has no such register? */ retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; if (mode != ARM_MODE_ANY) { retval = dpm_modeswitch(dpm, mode); if (retval != ERROR_OK) goto fail; } retval = dpm_write_reg(dpm, r, regnum); /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY); fail: /* (void) */ dpm->finish(dpm); return retval; } static int arm_dpm_full_context(struct target *target) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; struct reg_cache *cache = arm->core_cache; int retval; bool did_read; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; do { enum arm_mode mode = ARM_MODE_ANY; did_read = false; /* We "know" arm_dpm_read_current_registers() was called so * the unmapped registers (R0..R7, PC, AND CPSR) and some * view of R8..R14 are current. We also "know" oddities of * register mapping: special cases for R8..R12 and SPSR. * * Pick some mode with unread registers and read them all. * Repeat until done. */ for (unsigned i = 0; i < cache->num_regs; i++) { struct arm_reg *r; if (cache->reg_list[i].valid) continue; r = cache->reg_list[i].arch_info; /* may need to pick a mode and set CPSR */ if (!did_read) { did_read = true; mode = r->mode; /* For regular (ARM_MODE_ANY) R8..R12 * in case we've entered debug state * in FIQ mode we need to patch mode. */ if (mode != ARM_MODE_ANY) retval = dpm_modeswitch(dpm, mode); else retval = dpm_modeswitch(dpm, ARM_MODE_USR); if (retval != ERROR_OK) goto done; } if (r->mode != mode) continue; /* CPSR was read, so "R16" must mean SPSR */ retval = dpm_read_reg(dpm, &cache->reg_list[i], (r->num == 16) ? 17 : r->num); if (retval != ERROR_OK) goto done; } } while (did_read); retval = dpm_modeswitch(dpm, ARM_MODE_ANY); /* (void) */ dpm->finish(dpm); done: return retval; } /*----------------------------------------------------------------------*/ /* * Breakpoint and Watchpoint support. * * Hardware {break,watch}points are usually left active, to minimize * debug entry/exit costs. When they are set or cleared, it's done in * batches. Also, DPM-conformant hardware can update debug registers * regardless of whether the CPU is running or halted ... though that * fact isn't currently leveraged. */ static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp, uint32_t addr, uint32_t length) { uint32_t control; control = (1 << 0) /* enable */ | (3 << 1); /* both user and privileged access */ /* Match 1, 2, or all 4 byte addresses in this word. * * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP. * Support larger length, when addr is suitably aligned. In * particular, allow watchpoints on 8 byte "double" values. * * REVISIT allow watchpoints on unaligned 2-bit values; and on * v7 hardware, unaligned 4-byte ones too. */ switch (length) { case 1: control |= (1 << (addr & 3)) << 5; break; case 2: /* require 2-byte alignment */ if (!(addr & 1)) { control |= (3 << (addr & 2)) << 5; break; } /* FALL THROUGH */ case 4: /* require 4-byte alignment */ if (!(addr & 3)) { control |= 0xf << 5; break; } /* FALL THROUGH */ default: LOG_ERROR("unsupported {break,watch}point length/alignment"); return ERROR_COMMAND_SYNTAX_ERROR; } /* other shared control bits: * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only) * bit 20 == 0 ... not linked to a context ID * bit 28:24 == 0 ... not ignoring N LSBs (v7 only) */ xp->address = addr & ~3; xp->control = control; xp->dirty = true; LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d", xp->address, control, xp->number); /* hardware is updated in write_dirty_registers() */ return ERROR_OK; } static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (bp->length < 2) return ERROR_COMMAND_SYNTAX_ERROR; if (!dpm->bpwp_enable) return retval; /* FIXME we need a generic solution for software breakpoints. */ if (bp->type == BKPT_SOFT) LOG_DEBUG("using HW bkpt, not SW..."); for (unsigned i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { retval = dpm_bpwp_setup(dpm, &dpm->dbp[i].bpwp, bp->address, bp->length); if (retval == ERROR_OK) dpm->dbp[i].bp = bp; break; } } return retval; } static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; for (unsigned i = 0; i < dpm->nbp; i++) { if (dpm->dbp[i].bp == bp) { dpm->dbp[i].bp = NULL; dpm->dbp[i].bpwp.dirty = true; /* hardware is updated in write_dirty_registers() */ retval = ERROR_OK; break; } } return retval; } static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, struct watchpoint *wp) { int retval; struct dpm_wp *dwp = dpm->dwp + index_t; uint32_t control; /* this hardware doesn't support data value matching or masking */ if (wp->value || wp->mask != ~(uint32_t)0) { LOG_DEBUG("watchpoint values and masking not supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = dpm_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length); if (retval != ERROR_OK) return retval; control = dwp->bpwp.control; switch (wp->rw) { case WPT_READ: control |= 1 << 3; break; case WPT_WRITE: control |= 2 << 3; break; case WPT_ACCESS: control |= 3 << 3; break; } dwp->bpwp.control = control; dpm->dwp[index_t].wp = wp; return retval; } static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (dpm->bpwp_enable) { for (unsigned i = 0; i < dpm->nwp; i++) { if (!dpm->dwp[i].wp) { retval = dpm_watchpoint_setup(dpm, i, wp); break; } } } return retval; } static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp) { struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; for (unsigned i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; dpm->dwp[i].bpwp.dirty = true; /* hardware is updated in write_dirty_registers() */ retval = ERROR_OK; break; } } return retval; } void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr) { switch (dpm->arm->core_state) { case ARM_STATE_ARM: addr -= 8; break; case ARM_STATE_THUMB: case ARM_STATE_THUMB_EE: addr -= 4; break; case ARM_STATE_JAZELLE: /* ?? */ break; } dpm->wp_pc = addr; } /*----------------------------------------------------------------------*/ /* * Other debug and support utilities */ void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) { struct target *target = dpm->arm->target; dpm->dscr = dscr; /* Examine debug reason */ switch (DSCR_ENTRY(dscr)) { case 6: /* Data abort (v6 only) */ case 7: /* Prefetch abort (v6 only) */ /* FALL THROUGH -- assume a v6 core in abort mode */ case 0: /* HALT request from debugger */ case 4: /* EDBGRQ */ target->debug_reason = DBG_REASON_DBGRQ; break; case 1: /* HW breakpoint */ case 3: /* SW BKPT */ case 5: /* vector catch */ target->debug_reason = DBG_REASON_BREAKPOINT; break; case 2: /* asynch watchpoint */ case 10:/* precise watchpoint */ target->debug_reason = DBG_REASON_WATCHPOINT; break; default: target->debug_reason = DBG_REASON_UNDEFINED; break; } } /*----------------------------------------------------------------------*/ /* * Setup and management support. */ /** * Hooks up this DPM to its associated target; call only once. * Initially this only covers the register cache. * * Oh, and watchpoints. Yeah. */ int arm_dpm_setup(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct target *target = arm->target; struct reg_cache *cache; arm->dpm = dpm; /* register access setup */ arm->full_context = arm_dpm_full_context; arm->read_core_reg = arm_dpm_read_core_reg; arm->write_core_reg = arm_dpm_write_core_reg; cache = arm_build_reg_cache(target, arm); if (!cache) return ERROR_FAIL; *register_get_last_cache_p(&target->reg_cache) = cache; /* coprocessor access setup */ arm->mrc = dpm_mrc; arm->mcr = dpm_mcr; /* breakpoint setup -- optional until it works everywhere */ if (!target->type->add_breakpoint) { target->type->add_breakpoint = dpm_add_breakpoint; target->type->remove_breakpoint = dpm_remove_breakpoint; } /* watchpoint setup */ target->type->add_watchpoint = dpm_add_watchpoint; target->type->remove_watchpoint = dpm_remove_watchpoint; /* FIXME add vector catch support */ dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); if (!dpm->dbp || !dpm->dwp) { free(dpm->dbp); free(dpm->dwp); return ERROR_FAIL; } LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", target_name(target), dpm->nbp, dpm->nwp); /* REVISIT ... and some of those breakpoints could match * execution context IDs... */ return ERROR_OK; } /** * Reinitializes DPM state at the beginning of a new debug session * or after a reset which may have affected the debug module. */ int arm_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { unsigned i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; (void) dpm->bpwp_disable(dpm, i); } for (i = 0; i < dpm->nwp; i++) { dpm->dwp[i].bpwp.number = 16 + i; (void) dpm->bpwp_disable(dpm, 16 + i); } } else LOG_WARNING("%s: can't disable breakpoints and watchpoints", target_name(dpm->arm->target)); return ERROR_OK; } openocd-0.9.0/src/target/arm_dpm.h0000644000175000017500000001513312315575361013750 00000000000000/* * Copyright (C) 2009 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __ARM_DPM_H #define __ARM_DPM_H /** * @file * This is the interface to the Debug Programmers Model for ARMv6 and * ARMv7 processors. ARMv6 processors (such as ARM11xx implementations) * introduced a model which became part of the ARMv7-AR architecture * which is most familiar through the Cortex-A series parts. While * specific details differ (like how to write the instruction register), * the high level models easily support shared code because those * registers are compatible. */ struct dpm_bpwp { unsigned number; uint32_t address; uint32_t control; /* true if hardware state needs flushing */ bool dirty; }; struct dpm_bp { struct breakpoint *bp; struct dpm_bpwp bpwp; }; struct dpm_wp { struct watchpoint *wp; struct dpm_bpwp bpwp; }; /** * This wraps an implementation of DPM primitives. Each interface * provider supplies a structure like this, which is the glue between * upper level code and the lower level hardware access. * * It is a PRELIMINARY AND INCOMPLETE set of primitives, starting with * support for CPU register access. */ struct arm_dpm { struct arm *arm; /** Cache of DIDR */ uint32_t didr; /** Invoke before a series of instruction operations */ int (*prepare)(struct arm_dpm *); /** Invoke after a series of instruction operations */ int (*finish)(struct arm_dpm *); /* WRITE TO CPU */ /** Runs one instruction, writing data to DCC before execution. */ int (*instr_write_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t data); /** Runs one instruction, writing data to R0 before execution. */ int (*instr_write_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t data); /** Optional core-specific operation invoked after CPSR writes. */ int (*instr_cpsr_sync)(struct arm_dpm *dpm); /* READ FROM CPU */ /** Runs one instruction, reading data from dcc after execution. */ int (*instr_read_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t *data); /** Runs one instruction, reading data from r0 after execution. */ int (*instr_read_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t *data); /* BREAKPOINT/WATCHPOINT SUPPORT */ /** * Enables one breakpoint or watchpoint by writing to the * hardware registers. The specified breakpoint/watchpoint * must currently be disabled. Indices 0..15 are used for * breakpoints; indices 16..31 are for watchpoints. */ int (*bpwp_enable)(struct arm_dpm *, unsigned index_value, uint32_t addr, uint32_t control); /** * Disables one breakpoint or watchpoint by clearing its * hardware control registers. Indices are the same ones * accepted by bpwp_enable(). */ int (*bpwp_disable)(struct arm_dpm *, unsigned index_value); /* The breakpoint and watchpoint arrays are private to the * DPM infrastructure. There are nbp indices in the dbp * array. There are nwp indices in the dwp array. */ unsigned nbp; unsigned nwp; struct dpm_bp *dbp; struct dpm_wp *dwp; /** Address of the instruction which triggered a watchpoint. */ uint32_t wp_pc; /** Recent value of DSCR. */ uint32_t dscr; /* FIXME -- read/write DCSR methods and symbols */ }; int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); int arm_dpm_read_current_registers(struct arm_dpm *); int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); int arm_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp); void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); /* DSCR bits; see ARMv7a arch spec section C10.3.1. * Not all v7 bits are valid in v6. */ #define DSCR_CORE_HALTED (0x1 << 0) #define DSCR_CORE_RESTARTED (0x1 << 1) #define DSCR_ENTRY_MASK (0xF << 2) #define DSCR_STICKY_ABORT_PRECISE (0x1 << 6) #define DSCR_STICKY_ABORT_IMPRECISE (0x1 << 7) #define DSCR_STICKY_UNDEFINED (0x1 << 8) #define DSCR_DBG_NOPWRDWN (0x1 << 9) /* v6 only */ #define DSCR_DBG_ACK (0x1 << 10) #define DSCR_INT_DIS (0x1 << 11) #define DSCR_CP14_USR_COMMS (0x1 << 12) #define DSCR_ITR_EN (0x1 << 13) #define DSCR_HALT_DBG_MODE (0x1 << 14) #define DSCR_MON_DBG_MODE (0x1 << 15) #define DSCR_SEC_PRIV_INVASV_DIS (0x1 << 16) #define DSCR_SEC_PRIV_NINVASV_DIS (0x1 << 17) #define DSCR_NON_SECURE (0x1 << 18) #define DSCR_DSCRD_IMPRECISE_ABORT (0x1 << 19) #define DSCR_EXT_DCC_MASK (0x3 << 20) /* DTR mode */ /* bits 22, 23 are reserved */ #define DSCR_INSTR_COMP (0x1 << 24) #define DSCR_PIPE_ADVANCE (0x1 << 25) #define DSCR_DTRTX_FULL_LATCHED (0x1 << 26) #define DSCR_DTRRX_FULL_LATCHED (0x1 << 27) /* bit 28 is reserved */ #define DSCR_DTR_TX_FULL (0x1 << 29) #define DSCR_DTR_RX_FULL (0x1 << 30) /* bit 31 is reserved */ #define DSCR_ENTRY(dscr) (((dscr) >> 2) & 0xf) #define DSCR_RUN_MODE(dscr) ((dscr) & (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) /* Methods of entry into debug mode */ #define DSCR_ENTRY_HALT_REQ (0x0 << 2) #define DSCR_ENTRY_BREAKPOINT (0x1 << 2) #define DSCR_ENTRY_IMPRECISE_WATCHPT (0x2 << 2) #define DSCR_ENTRY_BKPT_INSTR (0x3 << 2) #define DSCR_ENTRY_EXT_DBG_REQ (0x4 << 2) #define DSCR_ENTRY_VECT_CATCH (0x5 << 2) #define DSCR_ENTRY_D_SIDE_ABORT (0x6 << 2) /* v6 only */ #define DSCR_ENTRY_I_SIDE_ABORT (0x7 << 2) /* v6 only */ #define DSCR_ENTRY_OS_UNLOCK (0x8 << 2) #define DSCR_ENTRY_PRECISE_WATCHPT (0xA << 2) /* DTR modes */ #define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20) #define DSCR_EXT_DCC_STALL_MODE (0x1 << 20) #define DSCR_EXT_DCC_FAST_MODE (0x2 << 20) /* bits 22, 23 are reserved */ /* DRCR (debug run control register) bits */ #define DRCR_HALT (1 << 0) #define DRCR_RESTART (1 << 1) #define DRCR_CLEAR_EXCEPTIONS (1 << 2) void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); #endif /* __ARM_DPM_H */ openocd-0.9.0/src/target/xscale/0000755000175000017500000000000012526202225013502 500000000000000openocd-0.9.0/src/target/xscale/debug_handler.S0000644000175000017500000003241412315575361016347 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "protocol.h" .text .align 4 @ Disable thumb mode .code 32 @ send word to debugger .macro m_send_to_debugger reg 1: mrc p14, 0, r15, c14, c0, 0 bvs 1b mcr p14, 0, \reg, c8, c0, 0 .endm @ receive word from debugger .macro m_receive_from_debugger reg 1: mrc p14, 0, r15, c14, c0, 0 bpl 1b mrc p14, 0, \reg, c9, c0, 0 .endm @ save register on debugger, small .macro m_small_save_reg reg mov r0, \reg bl send_to_debugger .endm @ save status register on debugger, small .macro m_small_save_psr mrs r0, spsr bl send_to_debugger .endm @ wait for all outstanding coprocessor accesses to complete .macro m_cpwait mrc p15, 0, r0, c2, c0, 0 mov r0, r0 sub pc, pc, #4 .endm .global reset_handler .global undef_handler .global swi_handler .global prefetch_abort_handler .global data_abort_handler .global irq_handler .global fiq_handler .section .part1 , "ax" reset_handler: @ read DCSR mrc p14, 0, r13, c10, c0 @ check if global enable bit (GE) is set ands r13, r13, #0x80000000 bne debug_handler @ set global enable bit (GE) mov r13, #0xc0000000 mcr p14, 0, r13, c10, c0 debug_handler: @ save r0 without modifying other registers m_send_to_debugger r0 @ save lr (program PC) without branching (use macro) m_send_to_debugger r14 @ save non-banked registers and spsr (program CPSR) m_small_save_reg r1 m_small_save_reg r2 m_small_save_reg r3 m_small_save_reg r4 m_small_save_reg r5 m_small_save_reg r6 m_small_save_reg r7 m_small_save_psr mrs r0, spsr @ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts) bic r0, r0, #PSR_T orr r0, r0, #(PSR_I | PSR_F) @ examine mode bits and r1, r0, #MODE_MASK cmp r1, #MODE_USR bne not_user_mode @ replace USR mode with SYS bic r0, r0, #MODE_MASK orr r0, r0, #MODE_SYS not_user_mode: b save_banked_registers @ command loop @ wait for command from debugger, than execute desired function get_command: bl receive_from_debugger @ 0x0n - register access cmp r0, #0x0 beq get_banked_registers cmp r0, #0x1 beq set_banked_registers @ 0x1n - read memory cmp r0, #0x11 beq read_byte cmp r0, #0x12 beq read_half_word cmp r0, #0x14 beq read_word @ 0x2n - write memory cmp r0, #0x21 beq write_byte cmp r0, #0x22 beq write_half_word cmp r0, #0x24 beq write_word @ 0x3n - program execution cmp r0, #0x30 beq resume cmp r0, #0x31 beq resume_w_trace @ 0x4n - coprocessor access cmp r0, #0x40 beq read_cp_reg cmp r0, #0x41 beq write_cp_reg @ 0x5n - cache and mmu functions cmp r0, #0x50 beq clean_d_cache cmp r0, #0x51 beq invalidate_d_cache cmp r0, #0x52 beq invalidate_i_cache cmp r0, #0x53 beq cpwait @ 0x6n - misc functions cmp r0, #0x60 beq clear_sa cmp r0, #0x61 beq read_trace_buffer cmp r0, #0x62 beq clean_trace_buffer @ return (back to get_command) b get_command @ ---- @ resume program execution resume: @ restore CPSR (SPSR_dbg) bl receive_from_debugger msr spsr, r0 @ restore registers (r7 - r0) bl receive_from_debugger @ r7 mov r7, r0 bl receive_from_debugger @ r6 mov r6, r0 bl receive_from_debugger @ r5 mov r5, r0 bl receive_from_debugger @ r4 mov r4, r0 bl receive_from_debugger @ r3 mov r3, r0 bl receive_from_debugger @ r2 mov r2, r0 bl receive_from_debugger @ r1 mov r1, r0 bl receive_from_debugger @ r0 @ resume addresss m_receive_from_debugger lr @ branch back to application code, restoring CPSR subs pc, lr, #0 @ get banked registers @ receive mode bits from host, then run into save_banked_registers to get_banked_registers: bl receive_from_debugger @ save banked registers @ r0[4:0]: desired mode bits save_banked_registers: @ backup CPSR mrs r7, cpsr msr cpsr_c, r0 nop @ keep current mode bits in r1 for later use and r1, r0, #MODE_MASK @ backup banked registers m_send_to_debugger r8 m_send_to_debugger r9 m_send_to_debugger r10 m_send_to_debugger r11 m_send_to_debugger r12 m_send_to_debugger r13 m_send_to_debugger r14 @ if not in SYS mode (or USR, which we replaced with SYS before) cmp r1, #MODE_SYS beq no_spsr_to_save @ backup SPSR mrs r0, spsr m_send_to_debugger r0 no_spsr_to_save: @ restore CPSR for SDS msr cpsr_c, r7 nop @ return b get_command @ ---- @ set banked registers @ receive mode bits from host, then run into save_banked_registers to set_banked_registers: bl receive_from_debugger @ restore banked registers @ r0[4:0]: desired mode bits restore_banked_registers: @ backup CPSR mrs r7, cpsr msr cpsr_c, r0 nop @ keep current mode bits in r1 for later use and r1, r0, #MODE_MASK @ set banked registers m_receive_from_debugger r8 m_receive_from_debugger r9 m_receive_from_debugger r10 m_receive_from_debugger r11 m_receive_from_debugger r12 m_receive_from_debugger r13 m_receive_from_debugger r14 @ if not in SYS mode (or USR, which we replaced with SYS before) cmp r1, #MODE_SYS beq no_spsr_to_restore @ set SPSR m_receive_from_debugger r0 msr spsr, r0 no_spsr_to_restore: @ restore CPSR for SDS msr cpsr_c, r7 nop @ return b get_command @ ---- read_byte: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 rb_loop: ldrb r0, [r2], #1 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 bl send_to_debugger subs r1, r1, #1 bne rb_loop @ return b get_command @ ---- read_half_word: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 rh_loop: ldrh r0, [r2], #2 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 bl send_to_debugger subs r1, r1, #1 bne rh_loop @ return b get_command @ ---- read_word: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 rw_loop: ldr r0, [r2], #4 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 bl send_to_debugger subs r1, r1, #1 bne rw_loop @ return b get_command @ ---- write_byte: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 wb_loop: bl receive_from_debugger strb r0, [r2], #1 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 subs r1, r1, #1 bne wb_loop @ return b get_command @ ---- write_half_word: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 wh_loop: bl receive_from_debugger strh r0, [r2], #2 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 subs r1, r1, #1 bne wh_loop @ return b get_command @ ---- write_word: @ r2: address bl receive_from_debugger mov r2, r0 @ r1: count bl receive_from_debugger mov r1, r0 ww_loop: bl receive_from_debugger str r0, [r2], #4 @ drain write- (and fill-) buffer to work around XScale errata mcr p15, 0, r8, c7, c10, 4 subs r1, r1, #1 bne ww_loop @ return b get_command @ ---- clear_sa: @ read DCSR mrc p14, 0, r0, c10, c0 @ clear SA bit bic r0, r0, #0x20 @ write DCSR mcr p14, 0, r0, c10, c0 @ return b get_command @ ---- clean_d_cache: @ r0: cache clean area bl receive_from_debugger mov r1, #1024 clean_loop: mcr p15, 0, r0, c7, c2, 5 add r0, r0, #32 subs r1, r1, #1 bne clean_loop @ return b get_command @ ---- invalidate_d_cache: mcr p15, 0, r0, c7, c6, 0 @ return b get_command @ ---- invalidate_i_cache: mcr p15, 0, r0, c7, c5, 0 @ return b get_command @ ---- cpwait: m_cpwait @return b get_command @ ---- .section .part2 , "ax" read_cp_reg: @ requested cp register bl receive_from_debugger adr r1, read_cp_table add pc, r1, r0, lsl #3 read_cp_table: mrc p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID b read_cp_reg_reply mrc p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE b read_cp_reg_reply mrc p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL b read_cp_reg_reply mrc p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL b read_cp_reg_reply mrc p15, 0, r0, c2, c0, 0 @ XSCALE_TTB b read_cp_reg_reply mrc p15, 0, r0, c3, c0, 0 @ XSCALE_DAC b read_cp_reg_reply mrc p15, 0, r0, c5, c0, 0 @ XSCALE_FSR b read_cp_reg_reply mrc p15, 0, r0, c6, c0, 0 @ XSCALE_FAR b read_cp_reg_reply mrc p15, 0, r0, c13, c0, 0 @ XSCALE_PID b read_cp_reg_reply mrc p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS b read_cp_reg_reply mrc p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 b read_cp_reg_reply mrc p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 b read_cp_reg_reply mrc p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 b read_cp_reg_reply mrc p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 b read_cp_reg_reply mrc p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON b read_cp_reg_reply mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG b read_cp_reg_reply mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 b read_cp_reg_reply mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 b read_cp_reg_reply mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR b read_cp_reg_reply read_cp_reg_reply: bl send_to_debugger @ return b get_command @ ---- write_cp_reg: @ requested cp register bl receive_from_debugger mov r1, r0 @ value to be written bl receive_from_debugger adr r2, write_cp_table add pc, r2, r1, lsl #3 write_cp_table: mcr p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID (0x0) b get_command mcr p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE (0x1) b get_command mcr p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL (0x2) b get_command mcr p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL (0x3) b get_command mcr p15, 0, r0, c2, c0, 0 @ XSCALE_TTB (0x4) b get_command mcr p15, 0, r0, c3, c0, 0 @ XSCALE_DAC (0x5) b get_command mcr p15, 0, r0, c5, c0, 0 @ XSCALE_FSR (0x6) b get_command mcr p15, 0, r0, c6, c0, 0 @ XSCALE_FAR (0x7) b get_command mcr p15, 0, r0, c13, c0, 0 @ XSCALE_PID (0x8) b get_command mcr p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS (0x9) b get_command mcr p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 (0xa) b get_command mcr p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 (0xb) b get_command mcr p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 (0xc) b get_command mcr p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 (0xd) b get_command mcr p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON (0xe) b get_command mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf) b get_command mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) b get_command mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) b get_command mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12) b get_command @ ---- read_trace_buffer: @ dump 256 entries from trace buffer mov r1, #256 read_tb_loop: mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG bl send_to_debugger subs r1, r1, #1 bne read_tb_loop @ dump checkpoint register 0 mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) bl send_to_debugger @ dump checkpoint register 1 mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) bl send_to_debugger @ return b get_command @ ---- clean_trace_buffer: @ clean 256 entries from trace buffer mov r1, #256 clean_tb_loop: mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG subs r1, r1, #1 bne clean_tb_loop @ return b get_command @ ---- @ resume program execution with trace buffer enabled resume_w_trace: @ restore CPSR (SPSR_dbg) bl receive_from_debugger msr spsr, r0 @ restore registers (r7 - r0) bl receive_from_debugger @ r7 mov r7, r0 bl receive_from_debugger @ r6 mov r6, r0 bl receive_from_debugger @ r5 mov r5, r0 bl receive_from_debugger @ r4 mov r4, r0 bl receive_from_debugger @ r3 mov r3, r0 bl receive_from_debugger @ r2 mov r2, r0 bl receive_from_debugger @ r1 mov r1, r0 bl receive_from_debugger @ r0 @ resume addresss m_receive_from_debugger lr mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR orr r13, r13, #1 mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR @ branch back to application code, restoring CPSR subs pc, lr, #0 undef_handler: swi_handler: prefetch_abort_handler: data_abort_handler: irq_handler: fiq_handler: 1: b 1b send_to_debugger: m_send_to_debugger r0 mov pc, lr receive_from_debugger: m_receive_from_debugger r0 mov pc, lr openocd-0.9.0/src/target/xscale/protocol.h0000644000175000017500000000471312315575361015453 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #define REG_R0 0 #define REG_R1 1 #define REG_R2 2 #define REG_R3 3 #define REG_R4 4 #define REG_R5 5 #define REG_R6 6 #define REG_R7 7 #define REG_R8 8 #define REG_R9 9 #define REG_R10 10 #define REG_R11 11 #define REG_R12 12 #define REG_R13 13 #define REG_R14 14 #define REG_R15 15 #define REG_CPSR 16 #define REG_SPSR 17 #define MODE_USR 0x10 #define MODE_FIQ 0x11 #define MODE_IRQ 0x12 #define MODE_SVC 0x13 #define MODE_ABT 0x17 #define MODE_UND 0x1b #define MODE_SYS 0x1f #define MODE_ANY 0x40 #define MODE_CURRENT 0x80 #define MODE_MASK 0x1f #define PSR_I 0x80 #define PSR_F 0x40 #define PSR_T 0x20 #define XSCALE_DBG_MAINID 0x0 #define XSCALE_DBG_CACHETYPE 0x1 #define XSCALE_DBG_CTRL 0x2 #define XSCALE_DBG_AUXCTRL 0x3 #define XSCALE_DBG_TTB 0x4 #define XSCALE_DBG_DAC 0x5 #define XSCALE_DBG_FSR 0x6 #define XSCALE_DBG_FAR 0x7 #define XSCALE_DBG_PID 0x8 #define XSCALE_DBG_CPACCESS 0x9 #define XSCALE_DBG_IBCR0 0xa #define XSCALE_DBG_IBCR1 0xb #define XSCALE_DBG_DBR0 0xc #define XSCALE_DBG_DBR1 0xd #define XSCALE_DBG_DBCON 0xe openocd-0.9.0/src/target/xscale/build.sh0000755000175000017500000000067212315575361015077 00000000000000arm-none-eabi-gcc -c debug_handler.S -o debug_handler.o arm-none-eabi-ld -EL -n -Tdebug_handler.cmd debug_handler.o -o debug_handler.out arm-none-eabi-objcopy -O binary debug_handler.out debug_handler.bin #arm-none-eabi-gcc -mbig-endian -c debug_handler.S -o debug_handler_be.o #arm-none-eabi-ld -EB -n -Tdebug_handler.cmd debug_handler_be.o -o debug_handler_be.out #arm-none-eabi-objcopy -O binary debug_handler_be.out debug_handler_be.bin openocd-0.9.0/src/target/xscale/debug_handler.bin0000755000175000017500000000307012315575361016714 00000000000000ÞîÑâÑ ãÞ îþîýÿÿjîþîýÿÿjîî ápë ánë álë ájë áhë áfë ádëOábëOá ÀãÀ€ãâQãÀã€ã=ê\ëPã9 PãZ Pã{ PムPã‹ !Pã“ "Pã› $P㣠0Pã 1Pã+ @PãÄ APãí PPã§ QP㬠RP㬠SP㬠`Pã› aPã  bPã ×ÿÿê4ëðiá2ëp á0ë` á.ëP á,ë@ á*ë0 á(ë  á&ë á$ëþîýÿÿZîîð^âëpáð!á áâþîýÿÿjŽîþîýÿÿjžîþîýÿÿj®îþîýÿÿj¾îþîýÿÿjÎîþîýÿÿjÞîþîýÿÿjîîQã Oáþîýÿÿjîð!á áŸÿÿêüëpáð!á áâþîýÿÿZŽîþîýÿÿZžîþîýÿÿZ®îþîýÿÿZ¾îþîýÿÿZÎîþîýÿÿZÞîþîýÿÿZîîQã þîýÿÿZîðiáð!á á|ÿÿêÙë  á×ë áÒäšîÏëQâúÿÿrÿÿêÏë  áÍë á²ÒàšîÅëQâúÿÿhÿÿêÅë  áÃë á’äšî»ëQâúÿÿ^ÿÿê»ë  á¹ë á·ëÂäšîQâúÿÿTÿÿê±ë  á¯ë á­ë²ÂàšîQâúÿÿJÿÿê§ë  á¥ë á£ë‚äšîQâúÿÿ@ÿÿêî Àã î<ÿÿê™ë ã²î €âQâûÿÿ5ÿÿêî3ÿÿêî1ÿÿêî áðOâ-ÿÿê€ëâ€ñàî#ê0î!êîê0îêîêîêîêîêîêîêîêî êî êî êîêîêîêîêîÿÿÿêSëøþÿêUë áSë âñ‚àîñþÿê0îïþÿêîíþÿê0îëþÿêîéþÿêîçþÿêîåþÿêîãþÿê îáþÿêîßþÿêîÝþÿêîÛþÿêîÙþÿêî×þÿêîÕþÿê îÓþÿê îÑþÿê îÏþÿê îÍþÿê ãî$ëQâûÿÿî ëîëÃþÿê ãîQâüÿÿ¾þÿêëðiáëp áë` áëP áë@ áë0 áë  á ë á ëþîýÿÿZîîÞîÐãÞ îð^âþÿÿêþîýÿÿjîð áþîýÿÿZîð áopenocd-0.9.0/src/target/xscale/debug_handler.cmd0000644000175000017500000000127212315575361016706 00000000000000/* identify the Entry Point */ ENTRY(reset_handler) /* specify the mini-ICache memory areas */ MEMORY { mini_icache_0 (x) : ORIGIN = 0x0, LENGTH = 1024 /* first part of mini icache (sets 0-31) */ mini_icache_1 (x) : ORIGIN = 0x400, LENGTH = 1024 /* second part of mini icache (sets 0-31) */ } /* now define the output sections */ SECTIONS { .part1 : { LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) *(.part1) } >mini_icache_0 .part2 : { LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) *(.part2) FILL(0x0) } >mini_icache_1 /DISCARD/ : { *(.text) *(.glue_7) *(.glue_7t) *(.data) *(.bss) } } openocd-0.9.0/src/target/breakpoints.c0000644000175000017500000003500312516456303014640 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include #include "breakpoints.h" static const char * const breakpoint_type_strings[] = { "hardware", "software" }; static const char * const watchpoint_rw_strings[] = { "read", "write", "access" }; /* monotonic counter/id-number for breakpoints and watch points */ static int bpwp_unique_id; int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; const char *reason; int retval; int n; n = 0; while (breakpoint) { n++; if (breakpoint->address == address) { /* FIXME don't assume "same address" means "same * breakpoint" ... check all the parameters before * succeeding. */ LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %" PRIu32 ")", address, breakpoint->unique_id); return ERROR_OK; } breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; } (*breakpoint_p) = malloc(sizeof(struct breakpoint)); (*breakpoint_p)->address = address; (*breakpoint_p)->asid = 0; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; (*breakpoint_p)->set = 0; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; retval = target_add_breakpoint(target, *breakpoint_p); switch (retval) { case ERROR_OK: break; case ERROR_TARGET_RESOURCE_NOT_AVAILABLE: reason = "resource not available"; goto fail; case ERROR_TARGET_NOT_HALTED: reason = "target running"; goto fail; default: reason = "unknown reason"; fail: LOG_ERROR("can't add breakpoint: %s", reason); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); return ERROR_OK; } int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; int retval; int n; n = 0; while (breakpoint) { n++; if (breakpoint->asid == asid) { /* FIXME don't assume "same address" means "same * breakpoint" ... check all the parameters before * succeeding. */ LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); return -1; } breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; } (*breakpoint_p) = malloc(sizeof(struct breakpoint)); (*breakpoint_p)->address = 0; (*breakpoint_p)->asid = asid; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; (*breakpoint_p)->set = 0; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; retval = target_add_context_breakpoint(target, *breakpoint_p); if (retval != ERROR_OK) { LOG_ERROR("could not add breakpoint"); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->asid, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); return ERROR_OK; } int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; int retval; int n; n = 0; while (breakpoint) { n++; if ((breakpoint->asid == asid) && (breakpoint->address == address)) { /* FIXME don't assume "same address" means "same * breakpoint" ... check all the parameters before * succeeding. */ LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); return -1; } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) { LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %" PRIu32 ")", address, breakpoint->unique_id); return -1; } breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; } (*breakpoint_p) = malloc(sizeof(struct breakpoint)); (*breakpoint_p)->address = address; (*breakpoint_p)->asid = asid; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; (*breakpoint_p)->set = 0; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; retval = target_add_hybrid_breakpoint(target, *breakpoint_p); if (retval != ERROR_OK) { LOG_ERROR("could not add breakpoint"); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } LOG_DEBUG( "added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); return ERROR_OK; } int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type) { int retval = ERROR_OK; if (target->smp) { struct target_list *head; struct target *curr; head = target->head; if (type == BKPT_SOFT) return breakpoint_add_internal(head->target, address, length, type); while (head != (struct target_list *)NULL) { curr = head->target; retval = breakpoint_add_internal(curr, address, length, type); if (retval != ERROR_OK) return retval; head = head->next; } return retval; } else return breakpoint_add_internal(target, address, length, type); } int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type) { int retval = ERROR_OK; if (target->smp) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; retval = context_breakpoint_add_internal(curr, asid, length, type); if (retval != ERROR_OK) return retval; head = head->next; } return retval; } else return context_breakpoint_add_internal(target, asid, length, type); } int hybrid_breakpoint_add(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) { int retval = ERROR_OK; if (target->smp) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type); if (retval != ERROR_OK) return retval; head = head->next; } return retval; } else return hybrid_breakpoint_add_internal(target, address, asid, length, type); } /* free up a breakpoint */ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; int retval; while (breakpoint) { if (breakpoint == breakpoint_to_remove) break; breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; } if (breakpoint == NULL) return; retval = target_remove_breakpoint(target, breakpoint); LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval); (*breakpoint_p) = breakpoint->next; free(breakpoint->orig_instr); free(breakpoint); } int breakpoint_remove_internal(struct target *target, uint32_t address) { struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { if ((breakpoint->address == address) && (breakpoint->asid == 0)) break; else if ((breakpoint->address == 0) && (breakpoint->asid == address)) break; else if ((breakpoint->address == address) && (breakpoint->asid != 0)) break; breakpoint = breakpoint->next; } if (breakpoint) { breakpoint_free(target, breakpoint); return 1; } else { if (!target->smp) LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); return 0; } } void breakpoint_remove(struct target *target, uint32_t address) { int found = 0; if (target->smp) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; found += breakpoint_remove_internal(curr, address); head = head->next; } if (found == 0) LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); } else breakpoint_remove_internal(target, address); } void breakpoint_clear_target_internal(struct target *target) { LOG_DEBUG("Delete all breakpoints for target: %s", target_name(target)); while (target->breakpoints != NULL) breakpoint_free(target, target->breakpoints); } void breakpoint_clear_target(struct target *target) { if (target->smp) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; breakpoint_clear_target_internal(curr); head = head->next; } } else breakpoint_clear_target_internal(target); } struct breakpoint *breakpoint_find(struct target *target, uint32_t address) { struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { if (breakpoint->address == address) return breakpoint; breakpoint = breakpoint->next; } return NULL; } int watchpoint_add(struct target *target, uint32_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; int retval; const char *reason; while (watchpoint) { if (watchpoint->address == address) { if (watchpoint->length != length || watchpoint->value != value || watchpoint->mask != mask || watchpoint->rw != rw) { LOG_ERROR("address 0x%8.8" PRIx32 "already has watchpoint %d", address, watchpoint->unique_id); return ERROR_FAIL; } /* ignore duplicate watchpoint */ return ERROR_OK; } watchpoint_p = &watchpoint->next; watchpoint = watchpoint->next; } (*watchpoint_p) = calloc(1, sizeof(struct watchpoint)); (*watchpoint_p)->address = address; (*watchpoint_p)->length = length; (*watchpoint_p)->value = value; (*watchpoint_p)->mask = mask; (*watchpoint_p)->rw = rw; (*watchpoint_p)->unique_id = bpwp_unique_id++; retval = target_add_watchpoint(target, *watchpoint_p); switch (retval) { case ERROR_OK: break; case ERROR_TARGET_RESOURCE_NOT_AVAILABLE: reason = "resource not available"; goto bye; case ERROR_TARGET_NOT_HALTED: reason = "target running"; goto bye; default: reason = "unrecognized error"; bye: LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s", watchpoint_rw_strings[(*watchpoint_p)->rw], address, reason); free(*watchpoint_p); *watchpoint_p = NULL; return retval; } LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 " of length 0x%8.8" PRIx32 " (WPID: %d)", watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, (*watchpoint_p)->length, (*watchpoint_p)->unique_id); return ERROR_OK; } static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; int retval; while (watchpoint) { if (watchpoint == watchpoint_to_remove) break; watchpoint_p = &watchpoint->next; watchpoint = watchpoint->next; } if (watchpoint == NULL) return; retval = target_remove_watchpoint(target, watchpoint); LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval); (*watchpoint_p) = watchpoint->next; free(watchpoint); } void watchpoint_remove(struct target *target, uint32_t address) { struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { if (watchpoint->address == address) break; watchpoint = watchpoint->next; } if (watchpoint) watchpoint_free(target, watchpoint); else LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address); } void watchpoint_clear_target(struct target *target) { LOG_DEBUG("Delete all watchpoints for target: %s", target_name(target)); while (target->watchpoints != NULL) watchpoint_free(target, target->watchpoints); } int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address) { int retval; struct watchpoint *hit_watchpoint; retval = target_hit_watchpoint(target, &hit_watchpoint); if (retval != ERROR_OK) return ERROR_FAIL; *rw = hit_watchpoint->rw; *address = hit_watchpoint->address; LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)", hit_watchpoint->address, hit_watchpoint->unique_id); return ERROR_OK; } openocd-0.9.0/src/target/breakpoints.h0000644000175000017500000000564412315575361014660 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef BREAKPOINTS_H #define BREAKPOINTS_H struct target; enum breakpoint_type { BKPT_HARD, BKPT_SOFT, }; enum watchpoint_rw { WPT_READ = 0, WPT_WRITE = 1, WPT_ACCESS = 2 }; struct breakpoint { uint32_t address; uint32_t asid; int length; enum breakpoint_type type; int set; uint8_t *orig_instr; struct breakpoint *next; uint32_t unique_id; int linked_BRP; }; struct watchpoint { uint32_t address; uint32_t length; uint32_t mask; uint32_t value; enum watchpoint_rw rw; int set; struct watchpoint *next; int unique_id; }; void breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); void breakpoint_remove(struct target *target, uint32_t address); struct breakpoint *breakpoint_find(struct target *target, uint32_t address); void watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, uint32_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask); void watchpoint_remove(struct target *target, uint32_t address); /* report type and address of just hit watchpoint */ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address); #endif /* BREAKPOINTS_H */ openocd-0.9.0/src/target/target.c0000644000175000017500000050040112526201110013565 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008, Duane Ellis * * openocd@duaneeellis.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by Rick Altherr * * kc8apf@kc8apf.net> * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * * Copyright (C) 2011 Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "target.h" #include "target_type.h" #include "target_request.h" #include "breakpoints.h" #include "register.h" #include "trace.h" #include "image.h" #include "rtos/rtos.h" #include "transport/transport.h" /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer); static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj * const *argv); static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj * const *argv); static int target_register_user_commands(struct command_context *cmd_ctx); static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info); static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c); static int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); /* targets */ extern struct target_type arm7tdmi_target; extern struct target_type arm720t_target; extern struct target_type arm9tdmi_target; extern struct target_type arm920t_target; extern struct target_type arm966e_target; extern struct target_type arm946e_target; extern struct target_type arm926ejs_target; extern struct target_type fa526_target; extern struct target_type feroceon_target; extern struct target_type dragonite_target; extern struct target_type xscale_target; extern struct target_type cortexm_target; extern struct target_type cortexa_target; extern struct target_type cortexr4_target; extern struct target_type arm11_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; extern struct target_type dsp563xx_target; extern struct target_type dsp5680xx_target; extern struct target_type testee_target; extern struct target_type avr32_ap7k_target; extern struct target_type hla_target; extern struct target_type nds32_v2_target; extern struct target_type nds32_v3_target; extern struct target_type nds32_v3m_target; extern struct target_type or1k_target; extern struct target_type quark_x10xx_target; static struct target_type *target_types[] = { &arm7tdmi_target, &arm9tdmi_target, &arm920t_target, &arm720t_target, &arm966e_target, &arm946e_target, &arm926ejs_target, &fa526_target, &feroceon_target, &dragonite_target, &xscale_target, &cortexm_target, &cortexa_target, &cortexr4_target, &arm11_target, &mips_m4k_target, &avr_target, &dsp563xx_target, &dsp5680xx_target, &testee_target, &avr32_ap7k_target, &hla_target, &nds32_v2_target, &nds32_v3_target, &nds32_v3m_target, &or1k_target, &quark_x10xx_target, NULL, }; struct target *all_targets; static struct target_event_callback *target_event_callbacks; static struct target_timer_callback *target_timer_callbacks; LIST_HEAD(target_reset_callback_list); static const int polling_interval = 100; static const Jim_Nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, { .name = "deassert", NVP_DEASSERT }, { .name = "T", NVP_ASSERT }, { .name = "F", NVP_DEASSERT }, { .name = "t", NVP_ASSERT }, { .name = "f", NVP_DEASSERT }, { .name = NULL, .value = -1 } }; static const Jim_Nvp nvp_error_target[] = { { .value = ERROR_TARGET_INVALID, .name = "err-invalid" }, { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" }, { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" }, { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" }, { .value = ERROR_TARGET_FAILURE, .name = "err-failure" }, { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" }, { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" }, { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" }, { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" }, { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" }, { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" }, { .value = -1, .name = NULL } }; static const char *target_strerror_safe(int err) { const Jim_Nvp *n; n = Jim_Nvp_value2name_simple(nvp_error_target, err); if (n->name == NULL) return "unknown"; else return n->name; } static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, { .value = TARGET_EVENT_HALTED, .name = "halted" }, { .value = TARGET_EVENT_RESUMED, .name = "resumed" }, { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" }, { .name = "gdb-start", .value = TARGET_EVENT_GDB_START }, { .name = "gdb-end", .value = TARGET_EVENT_GDB_END }, { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" }, { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" }, { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" }, { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" }, { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" }, { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" }, { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" }, { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" }, { .name = NULL, .value = -1 } }; static const Jim_Nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, { .name = "halted", .value = TARGET_HALTED }, { .name = "reset", .value = TARGET_RESET }, { .name = "debug-running", .value = TARGET_DEBUG_RUNNING }, { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_target_debug_reason[] = { { .name = "debug-request" , .value = DBG_REASON_DBGRQ }, { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT }, { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT }, { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT }, { .name = "single-step" , .value = DBG_REASON_SINGLESTEP }, { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED }, { .name = "program-exit" , .value = DBG_REASON_EXIT }, { .name = "undefined" , .value = DBG_REASON_UNDEFINED }, { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_target_endian[] = { { .name = "big", .value = TARGET_BIG_ENDIAN }, { .name = "little", .value = TARGET_LITTLE_ENDIAN }, { .name = "be", .value = TARGET_BIG_ENDIAN }, { .name = "le", .value = TARGET_LITTLE_ENDIAN }, { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_reset_modes[] = { { .name = "unknown", .value = RESET_UNKNOWN }, { .name = "run" , .value = RESET_RUN }, { .name = "halt" , .value = RESET_HALT }, { .name = "init" , .value = RESET_INIT }, { .name = NULL , .value = -1 }, }; const char *debug_reason_name(struct target *t) { const char *cp; cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason, t->debug_reason)->name; if (!cp) { LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason)); cp = "(*BUG*unknown*BUG*)"; } return cp; } const char *target_state_name(struct target *t) { const char *cp; cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name; if (!cp) { LOG_ERROR("Invalid target state: %d", (int)(t->state)); cp = "(*BUG*unknown*BUG*)"; } return cp; } const char *target_event_name(enum target_event event) { const char *cp; cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name; if (!cp) { LOG_ERROR("Invalid target event: %d", (int)(event)); cp = "(*BUG*unknown*BUG*)"; } return cp; } const char *target_reset_mode_name(enum target_reset_mode reset_mode) { const char *cp; cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name; if (!cp) { LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode)); cp = "(*BUG*unknown*BUG*)"; } return cp; } /* determine the number of the new target */ static int new_target_number(void) { struct target *t; int x; /* number is 0 based */ x = -1; t = all_targets; while (t) { if (x < t->target_number) x = t->target_number; t = t->next; } return x + 1; } /* read a uint64_t from a buffer in target memory endianness */ uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u64(buffer); else return be_to_h_u64(buffer); } /* read a uint32_t from a buffer in target memory endianness */ uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u32(buffer); else return be_to_h_u32(buffer); } /* read a uint24_t from a buffer in target memory endianness */ uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u24(buffer); else return be_to_h_u24(buffer); } /* read a uint16_t from a buffer in target memory endianness */ uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u16(buffer); else return be_to_h_u16(buffer); } /* read a uint8_t from a buffer in target memory endianness */ static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) { return *buffer & 0x0ff; } /* write a uint64_t to a buffer in target memory endianness */ void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u64_to_le(buffer, value); else h_u64_to_be(buffer, value); } /* write a uint32_t to a buffer in target memory endianness */ void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u32_to_le(buffer, value); else h_u32_to_be(buffer, value); } /* write a uint24_t to a buffer in target memory endianness */ void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u24_to_le(buffer, value); else h_u24_to_be(buffer, value); } /* write a uint16_t to a buffer in target memory endianness */ void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u16_to_le(buffer, value); else h_u16_to_be(buffer, value); } /* write a uint8_t to a buffer in target memory endianness */ static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) { *buffer = value; } /* write a uint64_t array to a buffer in target memory endianness */ void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf) { uint32_t i; for (i = 0; i < count; i++) dstbuf[i] = target_buffer_get_u64(target, &buffer[i * 8]); } /* write a uint32_t array to a buffer in target memory endianness */ void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf) { uint32_t i; for (i = 0; i < count; i++) dstbuf[i] = target_buffer_get_u32(target, &buffer[i * 4]); } /* write a uint16_t array to a buffer in target memory endianness */ void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf) { uint32_t i; for (i = 0; i < count; i++) dstbuf[i] = target_buffer_get_u16(target, &buffer[i * 2]); } /* write a uint64_t array to a buffer in target memory endianness */ void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf) { uint32_t i; for (i = 0; i < count; i++) target_buffer_set_u64(target, &buffer[i * 8], srcbuf[i]); } /* write a uint32_t array to a buffer in target memory endianness */ void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf) { uint32_t i; for (i = 0; i < count; i++) target_buffer_set_u32(target, &buffer[i * 4], srcbuf[i]); } /* write a uint16_t array to a buffer in target memory endianness */ void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf) { uint32_t i; for (i = 0; i < count; i++) target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]); } /* return a pointer to a configured target; id is name or number */ struct target *get_target(const char *id) { struct target *target; /* try as tcltarget name */ for (target = all_targets; target; target = target->next) { if (target_name(target) == NULL) continue; if (strcmp(id, target_name(target)) == 0) return target; } /* It's OK to remove this fallback sometime after August 2010 or so */ /* no match, try as number */ unsigned num; if (parse_uint(id, &num) != ERROR_OK) return NULL; for (target = all_targets; target; target = target->next) { if (target->target_number == (int)num) { LOG_WARNING("use '%s' as target identifier, not '%u'", target_name(target), num); return target; } } return NULL; } /* returns a pointer to the n-th configured target */ struct target *get_target_by_num(int num) { struct target *target = all_targets; while (target) { if (target->target_number == num) return target; target = target->next; } return NULL; } struct target *get_current_target(struct command_context *cmd_ctx) { struct target *target = get_target_by_num(cmd_ctx->current_target); if (target == NULL) { LOG_ERROR("BUG: current_target out of bounds"); exit(-1); } return target; } int target_poll(struct target *target) { int retval; /* We can't poll until after examine */ if (!target_was_examined(target)) { /* Fail silently lest we pollute the log */ return ERROR_FAIL; } retval = target->type->poll(target); if (retval != ERROR_OK) return retval; if (target->halt_issued) { if (target->state == TARGET_HALTED) target->halt_issued = false; else { long long t = timeval_ms() - target->halt_issued_time; if (t > DEFAULT_HALT_TIMEOUT) { target->halt_issued = false; LOG_INFO("Halt timed out, wake up GDB."); target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } } } return ERROR_OK; } int target_halt(struct target *target) { int retval; /* We can't poll until after examine */ if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } retval = target->type->halt(target); if (retval != ERROR_OK) return retval; target->halt_issued = true; target->halt_issued_time = timeval_ms(); return ERROR_OK; } /** * Make the target (re)start executing using its saved execution * context (possibly with some modifications). * * @param target Which target should start executing. * @param current True to use the target's saved program counter instead * of the address parameter * @param address Optionally used as the program counter. * @param handle_breakpoints True iff breakpoints at the resumption PC * should be skipped. (For example, maybe execution was stopped by * such a breakpoint, in which case it would be counterprodutive to * let it re-trigger. * @param debug_execution False if all working areas allocated by OpenOCD * should be released and/or restored to their original contents. * (This would for example be true to run some downloaded "helper" * algorithm code, which resides in one such working buffer and uses * another for data storage.) * * @todo Resolve the ambiguity about what the "debug_execution" flag * signifies. For example, Target implementations don't agree on how * it relates to invalidation of the register cache, or to whether * breakpoints and watchpoints should be enabled. (It would seem wrong * to enable breakpoints when running downloaded "helper" algorithms * (debug_execution true), since the breakpoints would be set to match * target firmware being debugged, not the helper algorithm.... and * enabling them could cause such helpers to malfunction (for example, * by overwriting data with a breakpoint instruction. On the other * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval; /* We can't poll until after examine */ if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } target_call_event_callbacks(target, TARGET_EVENT_RESUME_START); /* note that resume *must* be asynchronous. The CPU can halt before * we poll. The CPU can even halt at the current PC as a result of * a software breakpoint being inserted by (a bug?) the application. */ retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_RESUME_END); return retval; } static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) { char buf[100]; int retval; Jim_Nvp *n; n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode); if (n->name == NULL) { LOG_ERROR("invalid reset mode"); return ERROR_FAIL; } struct target *target; for (target = all_targets; target; target = target->next) target_call_reset_callbacks(target, reset_mode); /* disable polling during reset to make reset event scripts * more predictable, i.e. dr/irscan & pathmove in events will * not have JTAG operations injected into the middle of a sequence. */ bool save_poll = jtag_poll_get_enabled(); jtag_poll_set_enabled(false); sprintf(buf, "ocd_process_reset %s", n->name); retval = Jim_Eval(cmd_ctx->interp, buf); jtag_poll_set_enabled(save_poll); if (retval != JIM_OK) { Jim_MakeErrorMessage(cmd_ctx->interp); command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); return ERROR_FAIL; } /* We want any events to be processed before the prompt */ retval = target_call_timer_callbacks_now(); for (target = all_targets; target; target = target->next) { target->type->check_reset(target); target->running_alg = false; } return retval; } static int identity_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) { *physical = virtual; return ERROR_OK; } static int no_mmu(struct target *target, int *enabled) { *enabled = 0; return ERROR_OK; } static int default_examine(struct target *target) { target_set_examined(target); return ERROR_OK; } /* no check by default */ static int default_check_reset(struct target *target) { return ERROR_OK; } int target_examine_one(struct target *target) { target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); int retval = target->type->examine(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); return ERROR_OK; } static int jtag_enable_callback(enum jtag_event event, void *priv) { struct target *target = priv; if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled) return ERROR_OK; jtag_unregister_event_callback(jtag_enable_callback, target); return target_examine_one(target); } /* Targets that correctly implement init + examine, i.e. * no communication with target during init: * * XScale */ int target_examine(void) { int retval = ERROR_OK; struct target *target; for (target = all_targets; target; target = target->next) { /* defer examination, but don't skip it */ if (!target->tap->enabled) { jtag_register_event_callback(jtag_enable_callback, target); continue; } retval = target_examine_one(target); if (retval != ERROR_OK) return retval; } return retval; } const char *target_type_name(struct target *target) { return target->type->name; } static int target_soft_reset_halt(struct target *target) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } if (!target->type->soft_reset_halt) { LOG_ERROR("Target %s does not support soft_reset_halt", target_name(target)); return ERROR_FAIL; } return target->type->soft_reset_halt(target); } /** * Downloads a target-specific native code algorithm to the target, * and executes it. * Note that some targets may need to set up, enable, * and tear down a breakpoint (hard or * soft) to detect algorithm * termination, while others may support lower overhead schemes where * soft breakpoints embedded in the algorithm automatically terminate the * algorithm. * * @param target used to run the algorithm * @param arch_info target-specific description of the algorithm. */ int target_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_FAIL; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); goto done; } if (!target->type->run_algorithm) { LOG_ERROR("Target type '%s' does not support %s", target_type_name(target), __func__); goto done; } target->running_alg = true; retval = target->type->run_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info); target->running_alg = false; done: return retval; } /** * Downloads a target-specific native code algorithm to the target, * executes and leaves it running. * * @param target used to run the algorithm * @param arch_info target-specific description of the algorithm. */ int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, void *arch_info) { int retval = ERROR_FAIL; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); goto done; } if (!target->type->start_algorithm) { LOG_ERROR("Target type '%s' does not support %s", target_type_name(target), __func__); goto done; } if (target->running_alg) { LOG_ERROR("Target is already running an algorithm"); goto done; } target->running_alg = true; retval = target->type->start_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, arch_info); done: return retval; } /** * Waits for an algorithm started with target_start_algorithm() to complete. * * @param target used to run the algorithm * @param arch_info target-specific description of the algorithm. */ int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_FAIL; if (!target->type->wait_algorithm) { LOG_ERROR("Target type '%s' does not support %s", target_type_name(target), __func__); goto done; } if (!target->running_alg) { LOG_ERROR("Target is not running an algorithm"); goto done; } retval = target->type->wait_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, exit_point, timeout_ms, arch_info); if (retval != ERROR_TARGET_TIMEOUT) target->running_alg = false; done: return retval; } /** * Executes a target-specific native code algorithm in the target. * It differs from target_run_algorithm in that the algorithm is asynchronous. * Because of this it requires an compliant algorithm: * see contrib/loaders/flash/stm32f1x.S for example. * * @param target used to run the algorithm */ int target_run_flash_async_algorithm(struct target *target, const uint8_t *buffer, uint32_t count, int block_size, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t buffer_start, uint32_t buffer_size, uint32_t entry_point, uint32_t exit_point, void *arch_info) { int retval; int timeout = 0; const uint8_t *buffer_orig = buffer; /* Set up working area. First word is write pointer, second word is read pointer, * rest is fifo data area. */ uint32_t wp_addr = buffer_start; uint32_t rp_addr = buffer_start + 4; uint32_t fifo_start_addr = buffer_start + 8; uint32_t fifo_end_addr = buffer_start + buffer_size; uint32_t wp = fifo_start_addr; uint32_t rp = fifo_start_addr; /* validate block_size is 2^n */ assert(!block_size || !(block_size & (block_size - 1))); retval = target_write_u32(target, wp_addr, wp); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, rp_addr, rp); if (retval != ERROR_OK) return retval; /* Start up algorithm on target and let it idle while writing the first chunk */ retval = target_start_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, arch_info); if (retval != ERROR_OK) { LOG_ERROR("error starting target flash write algorithm"); return retval; } while (count > 0) { retval = target_read_u32(target, rp_addr, &rp); if (retval != ERROR_OK) { LOG_ERROR("failed to get read pointer"); break; } LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, (size_t) (buffer - buffer_orig), count, wp, rp); if (rp == 0) { LOG_ERROR("flash write algorithm aborted by target"); retval = ERROR_FLASH_OPERATION_FAILED; break; } if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) { LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp); break; } /* Count the number of bytes available in the fifo without * crossing the wrap around. Make sure to not fill it completely, * because that would make wp == rp and that's the empty condition. */ uint32_t thisrun_bytes; if (rp > wp) thisrun_bytes = rp - wp - block_size; else if (rp > fifo_start_addr) thisrun_bytes = fifo_end_addr - wp; else thisrun_bytes = fifo_end_addr - wp - block_size; if (thisrun_bytes == 0) { /* Throttle polling a bit if transfer is (much) faster than flash * programming. The exact delay shouldn't matter as long as it's * less than buffer size / flash speed. This is very unlikely to * run when using high latency connections such as USB. */ alive_sleep(10); /* to stop an infinite loop on some targets check and increment a timeout * this issue was observed on a stellaris using the new ICDI interface */ if (timeout++ >= 500) { LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); return ERROR_FLASH_OPERATION_FAILED; } continue; } /* reset our timeout */ timeout = 0; /* Limit to the amount of data we actually want to write */ if (thisrun_bytes > count * block_size) thisrun_bytes = count * block_size; /* Write data to fifo */ retval = target_write_buffer(target, wp, thisrun_bytes, buffer); if (retval != ERROR_OK) break; /* Update counters and wrap write pointer */ buffer += thisrun_bytes; count -= thisrun_bytes / block_size; wp += thisrun_bytes; if (wp >= fifo_end_addr) wp = fifo_start_addr; /* Store updated write pointer to target */ retval = target_write_u32(target, wp_addr, wp); if (retval != ERROR_OK) break; } if (retval != ERROR_OK) { /* abort flash write algorithm on target */ target_write_u32(target, wp_addr, 0); } int retval2 = target_wait_algorithm(target, num_mem_params, mem_params, num_reg_params, reg_params, exit_point, 10000, arch_info); if (retval2 != ERROR_OK) { LOG_ERROR("error waiting for target flash write algorithm"); retval = retval2; } return retval; } int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } return target->type->read_memory(target, address, size, count, buffer); } int target_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } return target->type->read_phys_memory(target, address, size, count, buffer); } int target_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } return target->type->write_memory(target, address, size, count, buffer); } int target_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } return target->type->write_phys_memory(target, address, size, count, buffer); } int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) { LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_breakpoint(target, breakpoint); } int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_context_breakpoint(target, breakpoint); } int target_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_hybrid_breakpoint(target, breakpoint); } int target_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { return target->type->remove_breakpoint(target, breakpoint); } int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_watchpoint(target, watchpoint); } int target_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { return target->type->remove_watchpoint(target, watchpoint); } int target_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } if (target->type->hit_watchpoint == NULL) { /* For backward compatible, if hit_watchpoint is not implemented, * return ERROR_FAIL such that gdb_server will not take the nonsense * information. */ return ERROR_FAIL; } return target->type->hit_watchpoint(target, hit_watchpoint); } int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } int target_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { return target->type->step(target, current, address, handle_breakpoints); } int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->get_gdb_fileio_info(target, fileio_info); } int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); } int target_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { if (target->state != TARGET_HALTED) { LOG_WARNING("target %s is not halted", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->profiling(target, samples, max_num_samples, num_samples, seconds); } /** * Reset the @c examined flag for the given target. * Pure paranoia -- targets are zeroed on allocation. */ static void target_reset_examined(struct target *target) { target->examined = false; } static int err_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { LOG_ERROR("Not implemented: %s", __func__); return ERROR_FAIL; } static int err_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { LOG_ERROR("Not implemented: %s", __func__); return ERROR_FAIL; } static int handle_target(void *priv); static int target_init_one(struct command_context *cmd_ctx, struct target *target) { target_reset_examined(target); struct target_type *type = target->type; if (type->examine == NULL) type->examine = default_examine; if (type->check_reset == NULL) type->check_reset = default_check_reset; assert(type->init_target != NULL); int retval = type->init_target(cmd_ctx, target); if (ERROR_OK != retval) { LOG_ERROR("target '%s' init failed", target_name(target)); return retval; } /* Sanity-check MMU support ... stub in what we must, to help * implement it in stages, but warn if we need to do so. */ if (type->mmu) { if (type->write_phys_memory == NULL) { LOG_ERROR("type '%s' is missing write_phys_memory", type->name); type->write_phys_memory = err_write_phys_memory; } if (type->read_phys_memory == NULL) { LOG_ERROR("type '%s' is missing read_phys_memory", type->name); type->read_phys_memory = err_read_phys_memory; } if (type->virt2phys == NULL) { LOG_ERROR("type '%s' is missing virt2phys", type->name); type->virt2phys = identity_virt2phys; } } else { /* Make sure no-MMU targets all behave the same: make no * distinction between physical and virtual addresses, and * ensure that virt2phys() is always an identity mapping. */ if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) LOG_WARNING("type '%s' has bad MMU hooks", type->name); type->mmu = no_mmu; type->write_phys_memory = type->write_memory; type->read_phys_memory = type->read_memory; type->virt2phys = identity_virt2phys; } if (target->type->read_buffer == NULL) target->type->read_buffer = target_read_buffer_default; if (target->type->write_buffer == NULL) target->type->write_buffer = target_write_buffer_default; if (target->type->get_gdb_fileio_info == NULL) target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; if (target->type->gdb_fileio_end == NULL) target->type->gdb_fileio_end = target_gdb_fileio_end_default; if (target->type->profiling == NULL) target->type->profiling = target_profiling_default; return ERROR_OK; } static int target_init(struct command_context *cmd_ctx) { struct target *target; int retval; for (target = all_targets; target; target = target->next) { retval = target_init_one(cmd_ctx, target); if (ERROR_OK != retval) return retval; } if (!all_targets) return ERROR_OK; retval = target_register_user_commands(cmd_ctx); if (ERROR_OK != retval) return retval; retval = target_register_timer_callback(&handle_target, polling_interval, 1, cmd_ctx->interp); if (ERROR_OK != retval) return retval; return ERROR_OK; } COMMAND_HANDLER(handle_target_init_command) { int retval; if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; static bool target_initialized; if (target_initialized) { LOG_INFO("'target init' has already been called"); return ERROR_OK; } target_initialized = true; retval = command_run_line(CMD_CTX, "init_targets"); if (ERROR_OK != retval) return retval; retval = command_run_line(CMD_CTX, "init_target_events"); if (ERROR_OK != retval) return retval; retval = command_run_line(CMD_CTX, "init_board"); if (ERROR_OK != retval) return retval; LOG_DEBUG("Initializing targets..."); return target_init(CMD_CTX); } int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv) { struct target_event_callback **callbacks_p = &target_event_callbacks; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; if (*callbacks_p) { while ((*callbacks_p)->next) callbacks_p = &((*callbacks_p)->next); callbacks_p = &((*callbacks_p)->next); } (*callbacks_p) = malloc(sizeof(struct target_event_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; return ERROR_OK; } int target_register_reset_callback(int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv), void *priv) { struct target_reset_callback *entry; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; entry = malloc(sizeof(struct target_reset_callback)); if (entry == NULL) { LOG_ERROR("error allocating buffer for reset callback entry"); return ERROR_COMMAND_SYNTAX_ERROR; } entry->callback = callback; entry->priv = priv; list_add(&entry->list, &target_reset_callback_list); return ERROR_OK; } int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) { struct target_timer_callback **callbacks_p = &target_timer_callbacks; struct timeval now; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; if (*callbacks_p) { while ((*callbacks_p)->next) callbacks_p = &((*callbacks_p)->next); callbacks_p = &((*callbacks_p)->next); } (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->periodic = periodic; (*callbacks_p)->time_ms = time_ms; (*callbacks_p)->removed = false; gettimeofday(&now, NULL); (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; time_ms -= (time_ms % 1000); (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000); if ((*callbacks_p)->when.tv_usec > 1000000) { (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000; (*callbacks_p)->when.tv_sec += 1; } (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; return ERROR_OK; } int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv) { struct target_event_callback **p = &target_event_callbacks; struct target_event_callback *c = target_event_callbacks; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; while (c) { struct target_event_callback *next = c->next; if ((c->callback == callback) && (c->priv == priv)) { *p = next; free(c); return ERROR_OK; } else p = &(c->next); c = next; } return ERROR_OK; } int target_unregister_reset_callback(int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv), void *priv) { struct target_reset_callback *entry; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(entry, &target_reset_callback_list, list) { if (entry->callback == callback && entry->priv == priv) { list_del(&entry->list); free(entry); break; } } return ERROR_OK; } int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; for (struct target_timer_callback *c = target_timer_callbacks; c; c = c->next) { if ((c->callback == callback) && (c->priv == priv)) { c->removed = true; return ERROR_OK; } } return ERROR_FAIL; } int target_call_event_callbacks(struct target *target, enum target_event event) { struct target_event_callback *callback = target_event_callbacks; struct target_event_callback *next_callback; if (event == TARGET_EVENT_HALTED) { /* execute early halted first */ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } LOG_DEBUG("target event %i (%s)", event, Jim_Nvp_value2name_simple(nvp_target_event, event)->name); target_handle_event(target, event); while (callback) { next_callback = callback->next; callback->callback(target, event, callback->priv); callback = next_callback; } return ERROR_OK; } int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode) { struct target_reset_callback *callback; LOG_DEBUG("target reset %i (%s)", reset_mode, Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name); list_for_each_entry(callback, &target_reset_callback_list, list) callback->callback(target, reset_mode, callback->priv); return ERROR_OK; } static int target_timer_callback_periodic_restart( struct target_timer_callback *cb, struct timeval *now) { int time_ms = cb->time_ms; cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000; time_ms -= (time_ms % 1000); cb->when.tv_sec = now->tv_sec + time_ms / 1000; if (cb->when.tv_usec > 1000000) { cb->when.tv_usec = cb->when.tv_usec - 1000000; cb->when.tv_sec += 1; } return ERROR_OK; } static int target_call_timer_callback(struct target_timer_callback *cb, struct timeval *now) { cb->callback(cb->priv); if (cb->periodic) return target_timer_callback_periodic_restart(cb, now); return target_unregister_timer_callback(cb->callback, cb->priv); } static int target_call_timer_callbacks_check_time(int checktime) { static bool callback_processing; /* Do not allow nesting */ if (callback_processing) return ERROR_OK; callback_processing = true; keep_alive(); struct timeval now; gettimeofday(&now, NULL); /* Store an address of the place containing a pointer to the * next item; initially, that's a standalone "root of the * list" variable. */ struct target_timer_callback **callback = &target_timer_callbacks; while (*callback) { if ((*callback)->removed) { struct target_timer_callback *p = *callback; *callback = (*callback)->next; free(p); continue; } bool call_it = (*callback)->callback && ((!checktime && (*callback)->periodic) || now.tv_sec > (*callback)->when.tv_sec || (now.tv_sec == (*callback)->when.tv_sec && now.tv_usec >= (*callback)->when.tv_usec)); if (call_it) target_call_timer_callback(*callback, &now); callback = &(*callback)->next; } callback_processing = false; return ERROR_OK; } int target_call_timer_callbacks(void) { return target_call_timer_callbacks_check_time(1); } /* invoke periodic callbacks immediately */ int target_call_timer_callbacks_now(void) { return target_call_timer_callbacks_check_time(0); } /* Prints the working area layout for debug purposes */ static void print_wa_layout(struct target *target) { struct working_area *c = target->working_areas; while (c) { LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)", c->backup ? 'b' : ' ', c->free ? ' ' : '*', c->address, c->address + c->size - 1, c->size); c = c->next; } } /* Reduce area to size bytes, create a new free area from the remaining bytes, if any. */ static void target_split_working_area(struct working_area *area, uint32_t size) { assert(area->free); /* Shouldn't split an allocated area */ assert(size <= area->size); /* Caller should guarantee this */ /* Split only if not already the right size */ if (size < area->size) { struct working_area *new_wa = malloc(sizeof(*new_wa)); if (new_wa == NULL) return; new_wa->next = area->next; new_wa->size = area->size - size; new_wa->address = area->address + size; new_wa->backup = NULL; new_wa->user = NULL; new_wa->free = true; area->next = new_wa; area->size = size; /* If backup memory was allocated to this area, it has the wrong size * now so free it and it will be reallocated if/when needed */ if (area->backup) { free(area->backup); area->backup = NULL; } } } /* Merge all adjacent free areas into one */ static void target_merge_working_areas(struct target *target) { struct working_area *c = target->working_areas; while (c && c->next) { assert(c->next->address == c->address + c->size); /* This is an invariant */ /* Find two adjacent free areas */ if (c->free && c->next->free) { /* Merge the last into the first */ c->size += c->next->size; /* Remove the last */ struct working_area *to_be_freed = c->next; c->next = c->next->next; if (to_be_freed->backup) free(to_be_freed->backup); free(to_be_freed); /* If backup memory was allocated to the remaining area, it's has * the wrong size now */ if (c->backup) { free(c->backup); c->backup = NULL; } } else { c = c->next; } } } int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area) { /* Reevaluate working area address based on MMU state*/ if (target->working_areas == NULL) { int retval; int enabled; retval = target->type->mmu(target, &enabled); if (retval != ERROR_OK) return retval; if (!enabled) { if (target->working_area_phys_spec) { LOG_DEBUG("MMU disabled, using physical " "address for working memory 0x%08"PRIx32, target->working_area_phys); target->working_area = target->working_area_phys; } else { LOG_ERROR("No working memory available. " "Specify -work-area-phys to target."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } else { if (target->working_area_virt_spec) { LOG_DEBUG("MMU enabled, using virtual " "address for working memory 0x%08"PRIx32, target->working_area_virt); target->working_area = target->working_area_virt; } else { LOG_ERROR("No working memory available. " "Specify -work-area-virt to target."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } /* Set up initial working area on first call */ struct working_area *new_wa = malloc(sizeof(*new_wa)); if (new_wa) { new_wa->next = NULL; new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */ new_wa->address = target->working_area; new_wa->backup = NULL; new_wa->user = NULL; new_wa->free = true; } target->working_areas = new_wa; } /* only allocate multiples of 4 byte */ if (size % 4) size = (size + 3) & (~3UL); struct working_area *c = target->working_areas; /* Find the first large enough working area */ while (c) { if (c->free && c->size >= size) break; c = c->next; } if (c == NULL) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* Split the working area into the requested size */ target_split_working_area(c, size); LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address); if (target->backup_working_area) { if (c->backup == NULL) { c->backup = malloc(c->size); if (c->backup == NULL) return ERROR_FAIL; } int retval = target_read_memory(target, c->address, 4, c->size / 4, c->backup); if (retval != ERROR_OK) return retval; } /* mark as used, and return the new (reused) area */ c->free = false; *area = c; /* user pointer */ c->user = area; print_wa_layout(target); return ERROR_OK; } int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) { int retval; retval = target_alloc_working_area_try(target, size, area); if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) LOG_WARNING("not enough working area available(requested %"PRIu32")", size); return retval; } static int target_restore_working_area(struct target *target, struct working_area *area) { int retval = ERROR_OK; if (target->backup_working_area && area->backup != NULL) { retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); if (retval != ERROR_OK) LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32, area->size, area->address); } return retval; } /* Restore the area's backup memory, if any, and return the area to the allocation pool */ static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) { int retval = ERROR_OK; if (area->free) return retval; if (restore) { retval = target_restore_working_area(target, area); /* REVISIT: Perhaps the area should be freed even if restoring fails. */ if (retval != ERROR_OK) return retval; } area->free = true; LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32, area->size, area->address); /* mark user pointer invalid */ /* TODO: Is this really safe? It points to some previous caller's memory. * How could we know that the area pointer is still in that place and not * some other vital data? What's the purpose of this, anyway? */ *area->user = NULL; area->user = NULL; target_merge_working_areas(target); print_wa_layout(target); return retval; } int target_free_working_area(struct target *target, struct working_area *area) { return target_free_working_area_restore(target, area, 1); } void target_quit(void) { struct target_event_callback *pe = target_event_callbacks; while (pe) { struct target_event_callback *t = pe->next; free(pe); pe = t; } target_event_callbacks = NULL; struct target_timer_callback *pt = target_timer_callbacks; while (pt) { struct target_timer_callback *t = pt->next; free(pt); pt = t; } target_timer_callbacks = NULL; for (struct target *target = all_targets; target; target = target->next) { if (target->type->deinit_target) target->type->deinit_target(target); } } /* free resources and restore memory, if restoring memory fails, * free up resources anyway */ static void target_free_all_working_areas_restore(struct target *target, int restore) { struct working_area *c = target->working_areas; LOG_DEBUG("freeing all working areas"); /* Loop through all areas, restoring the allocated ones and marking them as free */ while (c) { if (!c->free) { if (restore) target_restore_working_area(target, c); c->free = true; *c->user = NULL; /* Same as above */ c->user = NULL; } c = c->next; } /* Run a merge pass to combine all areas into one */ target_merge_working_areas(target); print_wa_layout(target); } void target_free_all_working_areas(struct target *target) { target_free_all_working_areas_restore(target, 1); } /* Find the largest number of bytes that can be allocated */ uint32_t target_get_working_area_avail(struct target *target) { struct working_area *c = target->working_areas; uint32_t max_size = 0; if (c == NULL) return target->working_area_size; while (c) { if (c->free && max_size < c->size) max_size = c->size; c = c->next; } return max_size; } int target_arch_state(struct target *target) { int retval; if (target == NULL) { LOG_USER("No target has been configured"); return ERROR_OK; } LOG_USER("target state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) return ERROR_OK; retval = target->type->arch_state(target); return retval; } static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info) { /* If target does not support semi-hosting function, target has no need to provide .get_gdb_fileio_info callback. It just return ERROR_FAIL and gdb_server will return "Txx" as target halted every time. */ return ERROR_FAIL; } static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { return ERROR_OK; } static int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { struct timeval timeout, now; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, seconds, 0); LOG_INFO("Starting profiling. Halting and resuming the" " target as often as we can..."); uint32_t sample_count = 0; /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); int retval = ERROR_OK; for (;;) { target_poll(target); if (target->state == TARGET_HALTED) { uint32_t t = buf_get_u32(reg->value, 0, 32); samples[sample_count++] = t; /* current pc, addr = 0, do not handle breakpoints, not debugging */ retval = target_resume(target, 1, 0, 0, 0); target_poll(target); alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */ } else if (target->state == TARGET_RUNNING) { /* We want to quickly sample the PC. */ retval = target_halt(target); } else { LOG_INFO("Target not halted or running"); retval = ERROR_OK; break; } if (retval != ERROR_OK) break; gettimeofday(&now, NULL); if ((sample_count >= max_num_samples) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); break; } } *num_samples = sample_count; return retval; } /* Single aligned words are guaranteed to use 16 or 32 bit access * mode respectively, otherwise data is handled as quickly as * possible */ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", (int)size, (unsigned)address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } if (size == 0) return ERROR_OK; if ((address + size - 1) < address) { /* GDB can request this when e.g. PC is 0xfffffffc*/ LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)", (unsigned)address, (unsigned)size); return ERROR_FAIL; } return target->type->write_buffer(target, address, size, buffer); } static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; /* Align up to maximum 4 bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; count -= size; buffer += size; } } /* Write the data with as large access size as possible. */ for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { int retval = target_write_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; count -= aligned; buffer += aligned; } } return ERROR_OK; } /* Single aligned words are guaranteed to use 16 or 32 bit access * mode respectively, otherwise data is handled as quickly as * possible */ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", (int)size, (unsigned)address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } if (size == 0) return ERROR_OK; if ((address + size - 1) < address) { /* GDB can request this when e.g. PC is 0xfffffffc*/ LOG_ERROR("address + size wrapped(0x%08" PRIx32 ", 0x%08" PRIx32 ")", address, size); return ERROR_FAIL; } return target->type->read_buffer(target, address, size, buffer); } static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) { uint32_t size; /* Align up to maximum 4 bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { int retval = target_read_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; count -= size; buffer += size; } } /* Read the data with as large access size as possible. */ for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { int retval = target_read_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; count -= aligned; buffer += aligned; } } return ERROR_OK; } int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc) { uint8_t *buffer; int retval; uint32_t i; uint32_t checksum = 0; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } retval = target->type->checksum_memory(target, address, size, &checksum); if (retval != ERROR_OK) { buffer = malloc(size); if (buffer == NULL) { LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size); return ERROR_COMMAND_SYNTAX_ERROR; } retval = target_read_buffer(target, address, size, buffer); if (retval != ERROR_OK) { free(buffer); return retval; } /* convert to target endianness */ for (i = 0; i < (size/sizeof(uint32_t)); i++) { uint32_t target_data; target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]); target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data); } retval = image_calculate_checksum(buffer, size, &checksum); free(buffer); } *crc = checksum; return retval; } int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank) { int retval; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } if (target->type->blank_check_memory == 0) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; retval = target->type->blank_check_memory(target, address, size, blank); return retval; } int target_read_u64(struct target *target, uint64_t address, uint64_t *value) { uint8_t value_buf[8]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } int retval = target_read_memory(target, address, 8, 1, value_buf); if (retval == ERROR_OK) { *value = target_buffer_get_u64(target, value_buf); LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", address, *value); } else { *value = 0x0; LOG_DEBUG("address: 0x%" PRIx64 " failed", address); } return retval; } int target_read_u32(struct target *target, uint32_t address, uint32_t *value) { uint8_t value_buf[4]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } int retval = target_read_memory(target, address, 4, 1, value_buf); if (retval == ERROR_OK) { *value = target_buffer_get_u32(target, value_buf); LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", address, *value); } else { *value = 0x0; LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", address); } return retval; } int target_read_u16(struct target *target, uint32_t address, uint16_t *value) { uint8_t value_buf[2]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } int retval = target_read_memory(target, address, 2, 1, value_buf); if (retval == ERROR_OK) { *value = target_buffer_get_u16(target, value_buf); LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x", address, *value); } else { *value = 0x0; LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", address); } return retval; } int target_read_u8(struct target *target, uint32_t address, uint8_t *value) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } int retval = target_read_memory(target, address, 1, 1, value); if (retval == ERROR_OK) { LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", address, *value); } else { *value = 0x0; LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", address); } return retval; } int target_write_u64(struct target *target, uint64_t address, uint64_t value) { int retval; uint8_t value_buf[8]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", address, value); target_buffer_set_u64(target, value_buf, value); retval = target_write_memory(target, address, 8, 1, value_buf); if (retval != ERROR_OK) LOG_DEBUG("failed: %i", retval); return retval; } int target_write_u32(struct target *target, uint32_t address, uint32_t value) { int retval; uint8_t value_buf[4]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", address, value); target_buffer_set_u32(target, value_buf, value); retval = target_write_memory(target, address, 4, 1, value_buf); if (retval != ERROR_OK) LOG_DEBUG("failed: %i", retval); return retval; } int target_write_u16(struct target *target, uint32_t address, uint16_t value) { int retval; uint8_t value_buf[2]; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x", address, value); target_buffer_set_u16(target, value_buf, value); retval = target_write_memory(target, address, 2, 1, value_buf); if (retval != ERROR_OK) LOG_DEBUG("failed: %i", retval); return retval; } int target_write_u8(struct target *target, uint32_t address, uint8_t value) { int retval; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", address, value); retval = target_write_memory(target, address, 1, 1, &value); if (retval != ERROR_OK) LOG_DEBUG("failed: %i", retval); return retval; } static int find_target(struct command_context *cmd_ctx, const char *name) { struct target *target = get_target(name); if (target == NULL) { LOG_ERROR("Target: %s is unknown, try one of:\n", name); return ERROR_FAIL; } if (!target->tap->enabled) { LOG_USER("Target: TAP %s is disabled, " "can't be the current target\n", target->tap->dotted_name); return ERROR_FAIL; } cmd_ctx->current_target = target->target_number; return ERROR_OK; } COMMAND_HANDLER(handle_targets_command) { int retval = ERROR_OK; if (CMD_ARGC == 1) { retval = find_target(CMD_CTX, CMD_ARGV[0]); if (retval == ERROR_OK) { /* we're done! */ return retval; } } struct target *target = all_targets; command_print(CMD_CTX, " TargetName Type Endian TapName State "); command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); while (target) { const char *state; char marker = ' '; if (target->tap->enabled) state = target_state_name(target); else state = "tap-disabled"; if (CMD_CTX->current_target == target->target_number) marker = '*'; /* keep columns lined up to match the headers above */ command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s", target->target_number, marker, target_name(target), target_type_name(target), Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness)->name, target->tap->dotted_name, state); target = target->next; } return retval; } /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ static int powerDropout; static int srstAsserted; static int runPowerRestore; static int runPowerDropout; static int runSrstAsserted; static int runSrstDeasserted; static int sense_handler(void) { static int prevSrstAsserted; static int prevPowerdropout; int retval = jtag_power_dropout(&powerDropout); if (retval != ERROR_OK) return retval; int powerRestored; powerRestored = prevPowerdropout && !powerDropout; if (powerRestored) runPowerRestore = 1; long long current = timeval_ms(); static long long lastPower; int waitMore = lastPower + 2000 > current; if (powerDropout && !waitMore) { runPowerDropout = 1; lastPower = current; } retval = jtag_srst_asserted(&srstAsserted); if (retval != ERROR_OK) return retval; int srstDeasserted; srstDeasserted = prevSrstAsserted && !srstAsserted; static long long lastSrst; waitMore = lastSrst + 2000 > current; if (srstDeasserted && !waitMore) { runSrstDeasserted = 1; lastSrst = current; } if (!prevSrstAsserted && srstAsserted) runSrstAsserted = 1; prevSrstAsserted = srstAsserted; prevPowerdropout = powerDropout; if (srstDeasserted || powerRestored) { /* Other than logging the event we can't do anything here. * Issuing a reset is a particularly bad idea as we might * be inside a reset already. */ } return ERROR_OK; } /* process target state changes */ static int handle_target(void *priv) { Jim_Interp *interp = (Jim_Interp *)priv; int retval = ERROR_OK; if (!is_jtag_poll_safe()) { /* polling is disabled currently */ return ERROR_OK; } /* we do not want to recurse here... */ static int recursive; if (!recursive) { recursive = 1; sense_handler(); /* danger! running these procedures can trigger srst assertions and power dropouts. * We need to avoid an infinite loop/recursion here and we do that by * clearing the flags after running these events. */ int did_something = 0; if (runSrstAsserted) { LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); did_something = 1; } if (runSrstDeasserted) { Jim_Eval(interp, "srst_deasserted"); did_something = 1; } if (runPowerDropout) { LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); did_something = 1; } if (runPowerRestore) { Jim_Eval(interp, "power_restore"); did_something = 1; } if (did_something) { /* clear detect flags */ sense_handler(); } /* clear action flags */ runSrstAsserted = 0; runSrstDeasserted = 0; runPowerRestore = 0; runPowerDropout = 0; recursive = 0; } /* Poll targets for state changes unless that's globally disabled. * Skip targets that are currently disabled. */ for (struct target *target = all_targets; is_jtag_poll_safe() && target; target = target->next) { if (!target_was_examined(target)) continue; if (!target->tap->enabled) continue; if (target->backoff.times > target->backoff.count) { /* do not poll this time as we failed previously */ target->backoff.count++; continue; } target->backoff.count = 0; /* only poll target if we've got power and srst isn't asserted */ if (!powerDropout && !srstAsserted) { /* polling may fail silently until the target has been examined */ retval = target_poll(target); if (retval != ERROR_OK) { /* 100ms polling interval. Increase interval between polling up to 5000ms */ if (target->backoff.times * polling_interval < 5000) { target->backoff.times *= 2; target->backoff.times++; } /* Tell GDB to halt the debugger. This allows the user to * run monitor commands to handle the situation. */ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } if (target->backoff.times > 0) { LOG_USER("Polling target %s failed, trying to reexamine", target_name(target)); target_reset_examined(target); retval = target_examine_one(target); /* Target examination could have failed due to unstable connection, * but we set the examined flag anyway to repoll it later */ if (retval != ERROR_OK) { target->examined = true; LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", target->backoff.times * polling_interval); return retval; } } /* Since we succeeded, we reset backoff count */ target->backoff.times = 0; } } return retval; } COMMAND_HANDLER(handle_reg_command) { struct target *target; struct reg *reg = NULL; unsigned count = 0; char *value; LOG_DEBUG("-"); target = get_current_target(CMD_CTX); /* list all available registers for the current target */ if (CMD_ARGC == 0) { struct reg_cache *cache = target->reg_cache; count = 0; while (cache) { unsigned i; command_print(CMD_CTX, "===== %s", cache->name); for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { /* only print cached values if they are valid */ if (reg->valid) { value = buf_to_str(reg->value, reg->size, 16); command_print(CMD_CTX, "(%i) %s (/%" PRIu32 "): 0x%s%s", count, reg->name, reg->size, value, reg->dirty ? " (dirty)" : ""); free(value); } else { command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")", count, reg->name, reg->size) ; } } cache = cache->next; } return ERROR_OK; } /* access a single register by its ordinal number */ if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { unsigned num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct reg_cache *cache = target->reg_cache; count = 0; while (cache) { unsigned i; for (i = 0; i < cache->num_regs; i++) { if (count++ == num) { reg = &cache->reg_list[i]; break; } } if (reg) break; cache = cache->next; } if (!reg) { command_print(CMD_CTX, "%i is out of bounds, the current target " "has only %i registers (0 - %i)", num, count, count - 1); return ERROR_OK; } } else { /* access a single register by its name */ reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); if (!reg) { command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); return ERROR_OK; } } assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) reg->valid = 0; if (reg->valid == 0) reg->type->get(reg); value = buf_to_str(reg->value, reg->size, 16); command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); free(value); return ERROR_OK; } /* set register value */ if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); if (buf == NULL) return ERROR_FAIL; str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); reg->type->set(reg, buf); value = buf_to_str(reg->value, reg->size, 16); command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); free(value); free(buf); return ERROR_OK; } return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(handle_poll_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC == 0) { command_print(CMD_CTX, "background polling: %s", jtag_poll_get_enabled() ? "on" : "off"); command_print(CMD_CTX, "TAP: %s (%s)", target->tap->dotted_name, target->tap->enabled ? "enabled" : "disabled"); if (!target->tap->enabled) return ERROR_OK; retval = target_poll(target); if (retval != ERROR_OK) return retval; retval = target_arch_state(target); if (retval != ERROR_OK) return retval; } else if (CMD_ARGC == 1) { bool enable; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); jtag_poll_set_enabled(enable); } else return ERROR_COMMAND_SYNTAX_ERROR; return retval; } COMMAND_HANDLER(handle_wait_halt_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; unsigned ms = DEFAULT_HALT_TIMEOUT; if (1 == CMD_ARGC) { int retval = parse_uint(CMD_ARGV[0], &ms); if (ERROR_OK != retval) return ERROR_COMMAND_SYNTAX_ERROR; } struct target *target = get_current_target(CMD_CTX); return target_wait_state(target, TARGET_HALTED, ms); } /* wait for target state to change. The trick here is to have a low * latency for short waits and not to suck up all the CPU time * on longer waits. * * After 500ms, keep_alive() is invoked */ int target_wait_state(struct target *target, enum target_state state, int ms) { int retval; long long then = 0, cur; int once = 1; for (;;) { retval = target_poll(target); if (retval != ERROR_OK) return retval; if (target->state == state) break; cur = timeval_ms(); if (once) { once = 0; then = timeval_ms(); LOG_DEBUG("waiting for target %s...", Jim_Nvp_value2name_simple(nvp_target_state, state)->name); } if (cur-then > 500) keep_alive(); if ((cur-then) > ms) { LOG_ERROR("timed out while waiting for target %s", Jim_Nvp_value2name_simple(nvp_target_state, state)->name); return ERROR_FAIL; } } return ERROR_OK; } COMMAND_HANDLER(handle_halt_command) { LOG_DEBUG("-"); struct target *target = get_current_target(CMD_CTX); int retval = target_halt(target); if (ERROR_OK != retval) return retval; if (CMD_ARGC == 1) { unsigned wait_local; retval = parse_uint(CMD_ARGV[0], &wait_local); if (ERROR_OK != retval) return ERROR_COMMAND_SYNTAX_ERROR; if (!wait_local) return ERROR_OK; } return CALL_COMMAND_HANDLER(handle_wait_halt_command); } COMMAND_HANDLER(handle_soft_reset_halt_command) { struct target *target = get_current_target(CMD_CTX); LOG_USER("requesting target halt and executing a soft reset"); target_soft_reset_halt(target); return ERROR_OK; } COMMAND_HANDLER(handle_reset_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; enum target_reset_mode reset_mode = RESET_RUN; if (CMD_ARGC == 1) { const Jim_Nvp *n; n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]); if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) return ERROR_COMMAND_SYNTAX_ERROR; reset_mode = n->value; } /* reset *all* targets */ return target_process_reset(CMD_CTX, reset_mode); } COMMAND_HANDLER(handle_resume_command) { int current = 1; if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; struct target *target = get_current_target(CMD_CTX); /* with no CMD_ARGV, resume from current pc, addr = 0, * with one arguments, addr = CMD_ARGV[0], * handle breakpoints, not debugging */ uint32_t addr = 0; if (CMD_ARGC == 1) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); current = 0; } return target_resume(target, current, addr, 1, 0); } COMMAND_HANDLER(handle_step_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; LOG_DEBUG("-"); /* with no CMD_ARGV, step from current pc, addr = 0, * with one argument addr = CMD_ARGV[0], * handle breakpoints, debugging */ uint32_t addr = 0; int current_pc = 1; if (CMD_ARGC == 1) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); current_pc = 0; } struct target *target = get_current_target(CMD_CTX); return target->type->step(target, current_pc, addr, 1); } static void handle_md_output(struct command_context *cmd_ctx, struct target *target, uint32_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; unsigned line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; unsigned output_len = 0; const char *value_fmt; switch (size) { case 4: value_fmt = "%8.8x "; break; case 2: value_fmt = "%4.4x "; break; case 1: value_fmt = "%2.2x "; break; default: /* "can't happen", caller checked */ LOG_ERROR("invalid memory read size: %u", size); return; } for (unsigned i = 0; i < count; i++) { if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, "0x%8.8x: ", (unsigned)(address + (i*size))); } uint32_t value = 0; const uint8_t *value_ptr = buffer + i * size; switch (size) { case 4: value = target_buffer_get_u32(target, value_ptr); break; case 2: value = target_buffer_get_u16(target, value_ptr); break; case 1: value = *value_ptr; } output_len += snprintf(output + output_len, sizeof(output) - output_len, value_fmt, value); if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { command_print(cmd_ctx, "%s", output); output_len = 0; } } } COMMAND_HANDLER(handle_md_command) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; unsigned size = 0; switch (CMD_NAME[2]) { case 'w': size = 4; break; case 'h': size = 2; break; case 'b': size = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } bool physical = strcmp(CMD_ARGV[0], "phys") == 0; int (*fn)(struct target *target, uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); if (physical) { CMD_ARGC--; CMD_ARGV++; fn = target_read_phys_memory; } else fn = target_read_memory; if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); unsigned count = 1; if (CMD_ARGC == 2) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); uint8_t *buffer = calloc(count, size); struct target *target = get_current_target(CMD_CTX); int retval = fn(target, address, size, count, buffer); if (ERROR_OK == retval) handle_md_output(CMD_CTX, target, address, size, count, buffer); free(buffer); return retval; } typedef int (*target_write_fn)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); static int target_fill_mem(struct target *target, uint32_t address, target_write_fn fn, unsigned data_size, /* value */ uint32_t b, /* count */ unsigned c) { /* We have to write in reasonably large chunks to be able * to fill large memory areas with any sane speed */ const unsigned chunk_size = 16384; uint8_t *target_buf = malloc(chunk_size * data_size); if (target_buf == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } for (unsigned i = 0; i < chunk_size; i++) { switch (data_size) { case 4: target_buffer_set_u32(target, target_buf + i * data_size, b); break; case 2: target_buffer_set_u16(target, target_buf + i * data_size, b); break; case 1: target_buffer_set_u8(target, target_buf + i * data_size, b); break; default: exit(-1); } } int retval = ERROR_OK; for (unsigned x = 0; x < c; x += chunk_size) { unsigned current; current = c - x; if (current > chunk_size) current = chunk_size; retval = fn(target, address + x * data_size, data_size, current, target_buf); if (retval != ERROR_OK) break; /* avoid GDB timeouts */ keep_alive(); } free(target_buf); return retval; } COMMAND_HANDLER(handle_mw_command) { if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; bool physical = strcmp(CMD_ARGV[0], "phys") == 0; target_write_fn fn; if (physical) { CMD_ARGC--; CMD_ARGV++; fn = target_write_phys_memory; } else fn = target_write_memory; if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); unsigned count = 1; if (CMD_ARGC == 3) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); struct target *target = get_current_target(CMD_CTX); unsigned wordsize; switch (CMD_NAME[2]) { case 'w': wordsize = 4; break; case 'h': wordsize = 2; break; case 'b': wordsize = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return target_fill_mem(target, address, fn, wordsize, value, count); } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, uint32_t *min_address, uint32_t *max_address) { if (CMD_ARGC < 1 || CMD_ARGC > 5) return ERROR_COMMAND_SYNTAX_ERROR; /* a base address isn't always necessary, * default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { uint32_t addr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); image->base_address = addr; image->base_address_set = 1; } else image->base_address_set = 0; image->start_address_set = 0; if (CMD_ARGC >= 4) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address); if (CMD_ARGC == 5) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address); /* use size (given) to find max (required) */ *max_address += *min_address; } if (*min_address > *max_address) return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_OK; } COMMAND_HANDLER(handle_load_image_command) { uint8_t *buffer; size_t buf_cnt; uint32_t image_size; uint32_t min_address = 0; uint32_t max_address = 0xffffffff; int i; struct image image; int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, &image, &min_address, &max_address); if (ERROR_OK != retval) return retval; struct target *target = get_current_target(CMD_CTX); struct duration bench; duration_start(&bench); if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) return ERROR_OK; image_size = 0x0; retval = ERROR_OK; for (i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); break; } retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); if (retval != ERROR_OK) { free(buffer); break; } uint32_t offset = 0; uint32_t length = buf_cnt; /* DANGER!!! beware of unsigned comparision here!!! */ if ((image.sections[i].base_address + buf_cnt >= min_address) && (image.sections[i].base_address < max_address)) { if (image.sections[i].base_address < min_address) { /* clip addresses below */ offset += min_address-image.sections[i].base_address; length -= offset; } if (image.sections[i].base_address + buf_cnt > max_address) length -= (image.sections[i].base_address + buf_cnt)-max_address; retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset); if (retval != ERROR_OK) { free(buffer); break; } image_size += length; command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "", (unsigned int)length, image.sections[i].base_address + offset); } free(buffer); } if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } image_close(&image); return retval; } COMMAND_HANDLER(handle_dump_image_command) { struct fileio fileio; uint8_t *buffer; int retval, retvaltemp; uint32_t address, size; struct duration bench; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); uint32_t buf_size = (size > 4096) ? 4096 : size; buffer = malloc(buf_size); if (!buffer) return ERROR_FAIL; retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); if (retval != ERROR_OK) { free(buffer); return retval; } duration_start(&bench); while (size > 0) { size_t size_written; uint32_t this_run_size = (size > buf_size) ? buf_size : size; retval = target_read_buffer(target, address, this_run_size, buffer); if (retval != ERROR_OK) break; retval = fileio_write(&fileio, this_run_size, buffer, &size_written); if (retval != ERROR_OK) break; size -= this_run_size; address += this_run_size; } free(buffer); if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { int filesize; retval = fileio_size(&fileio, &filesize); if (retval != ERROR_OK) return retval; command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)", (long)filesize, duration_elapsed(&bench), duration_kbps(&bench, filesize)); } retvaltemp = fileio_close(&fileio); if (retvaltemp != ERROR_OK) return retvaltemp; return retval; } static COMMAND_HELPER(handle_verify_image_command_internal, int verify) { uint8_t *buffer; size_t buf_cnt; uint32_t image_size; int i; int retval; uint32_t checksum = 0; uint32_t mem_checksum = 0; struct image image; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; if (!target) { LOG_ERROR("no target selected"); return ERROR_FAIL; } struct duration bench; duration_start(&bench); if (CMD_ARGC >= 2) { uint32_t addr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); image.base_address = addr; image.base_address_set = 1; } else { image.base_address_set = 0; image.base_address = 0x0; } image.start_address_set = 0; retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) return retval; image_size = 0x0; int diffs = 0; retval = ERROR_OK; for (i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); break; } retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); if (retval != ERROR_OK) { free(buffer); break; } if (verify) { /* calculate checksum of image */ retval = image_calculate_checksum(buffer, buf_cnt, &checksum); if (retval != ERROR_OK) { free(buffer); break; } retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); if (retval != ERROR_OK) { free(buffer); break; } if (checksum != mem_checksum) { /* failed crc checksum, fall back to a binary compare */ uint8_t *data; if (diffs == 0) LOG_ERROR("checksum mismatch - attempting binary compare"); data = malloc(buf_cnt); /* Can we use 32bit word accesses? */ int size = 1; int count = buf_cnt; if ((count % 4) == 0) { size *= 4; count /= 4; } retval = target_read_memory(target, image.sections[i].base_address, size, count, data); if (retval == ERROR_OK) { uint32_t t; for (t = 0; t < buf_cnt; t++) { if (data[t] != buffer[t]) { command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", diffs, (unsigned)(t + image.sections[i].base_address), data[t], buffer[t]); if (diffs++ >= 127) { command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); free(data); free(buffer); goto done; } } keep_alive(); } } free(data); } } else { command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx", image.sections[i].base_address, buf_cnt); } free(buffer); image_size += buf_cnt; } if (diffs > 0) command_print(CMD_CTX, "No more differences found."); done: if (diffs > 0) retval = ERROR_FAIL; if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "verified %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } image_close(&image); return retval; } COMMAND_HANDLER(handle_verify_image_command) { return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1); } COMMAND_HANDLER(handle_test_image_command) { return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0); } static int handle_bp_command_list(struct command_context *cmd_ctx) { struct target *target = get_current_target(cmd_ctx); struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16); command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); free(buf); } else { if ((breakpoint->address == 0) && (breakpoint->asid != 0)) command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", breakpoint->asid, breakpoint->length, breakpoint->set); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); } breakpoint = breakpoint->next; } return ERROR_OK; } static int handle_bp_command_set(struct command_context *cmd_ctx, uint32_t addr, uint32_t asid, uint32_t length, int hw) { struct target *target = get_current_target(cmd_ctx); int retval; if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); if (ERROR_OK == retval) command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); else { LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); return retval; } } else if (addr == 0) { if (target->type->add_context_breakpoint == NULL) { LOG_WARNING("Context breakpoint not available"); return ERROR_OK; } retval = context_breakpoint_add(target, asid, length, hw); if (ERROR_OK == retval) command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); else { LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); return retval; } } else { if (target->type->add_hybrid_breakpoint == NULL) { LOG_WARNING("Hybrid breakpoint not available"); return ERROR_OK; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); if (ERROR_OK == retval) command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); else { LOG_ERROR("Failure setting breakpoint, the same address is already used"); return retval; } } return ERROR_OK; } COMMAND_HANDLER(handle_bp_command) { uint32_t addr; uint32_t asid; uint32_t length; int hw = BKPT_SOFT; switch (CMD_ARGC) { case 0: return handle_bp_command_list(CMD_CTX); case 2: asid = 0; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); case 3: if (strcmp(CMD_ARGV[2], "hw") == 0) { hw = BKPT_HARD; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); asid = 0; return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { hw = BKPT_HARD; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); addr = 0; return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); } case 4: hw = BKPT_HARD; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); default: return ERROR_COMMAND_SYNTAX_ERROR; } } COMMAND_HANDLER(handle_rbp_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t addr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); breakpoint_remove(target, addr); return ERROR_OK; } COMMAND_HANDLER(handle_wp_command) { struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC == 0) { struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { command_print(CMD_CTX, "address: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 ", r/w/a: %i, value: 0x%8.8" PRIx32 ", mask: 0x%8.8" PRIx32, watchpoint->address, watchpoint->length, (int)watchpoint->rw, watchpoint->value, watchpoint->mask); watchpoint = watchpoint->next; } return ERROR_OK; } enum watchpoint_rw type = WPT_ACCESS; uint32_t addr = 0; uint32_t length = 0; uint32_t data_value = 0x0; uint32_t data_mask = 0xffffffff; switch (CMD_ARGC) { case 5: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask); /* fall through */ case 4: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value); /* fall through */ case 3: switch (CMD_ARGV[2][0]) { case 'r': type = WPT_READ; break; case 'w': type = WPT_WRITE; break; case 'a': type = WPT_ACCESS; break; default: LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); return ERROR_COMMAND_SYNTAX_ERROR; } /* fall through */ case 2: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } int retval = watchpoint_add(target, addr, length, type, data_value, data_mask); if (ERROR_OK != retval) LOG_ERROR("Failure setting watchpoints"); return retval; } COMMAND_HANDLER(handle_rwp_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t addr; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); watchpoint_remove(target, addr); return ERROR_OK; } /** * Translate a virtual address to a physical address. * * The low-level target implementation must have logged a detailed error * which is forwarded to telnet/GDB session. */ COMMAND_HANDLER(handle_virt2phys_command) { if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t va; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va); uint32_t pa; struct target *target = get_current_target(CMD_CTX); int retval = target->type->virt2phys(target, va, &pa); if (retval == ERROR_OK) command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa); return retval; } static void writeData(FILE *f, const void *data, size_t len) { size_t written = fwrite(data, 1, len, f); if (written != len) LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno)); } static void writeLong(FILE *f, int l, struct target *target) { uint8_t val[4]; target_buffer_set_u32(target, val, l); writeData(f, val, 4); } static void writeString(FILE *f, char *s) { writeData(f, s, strlen(s)); } typedef unsigned char UNIT[2]; /* unit of profiling */ /* Dump a gmon.out histogram file. */ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range, uint32_t start_address, uint32_t end_address, struct target *target) { uint32_t i; FILE *f = fopen(filename, "w"); if (f == NULL) return; writeString(f, "gmon"); writeLong(f, 0x00000001, target); /* Version */ writeLong(f, 0, target); /* padding */ writeLong(f, 0, target); /* padding */ writeLong(f, 0, target); /* padding */ uint8_t zero = 0; /* GMON_TAG_TIME_HIST */ writeData(f, &zero, 1); /* figure out bucket size */ uint32_t min; uint32_t max; if (with_range) { min = start_address; max = end_address; } else { min = samples[0]; max = samples[0]; for (i = 0; i < sampleNum; i++) { if (min > samples[i]) min = samples[i]; if (max < samples[i]) max = samples[i]; } /* max should be (largest sample + 1) * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ max++; } int addressSpace = max - min; assert(addressSpace >= 2); /* FIXME: What is the reasonable number of buckets? * The profiling result will be more accurate if there are enough buckets. */ static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */ uint32_t numBuckets = addressSpace / sizeof(UNIT); if (numBuckets > maxBuckets) numBuckets = maxBuckets; int *buckets = malloc(sizeof(int) * numBuckets); if (buckets == NULL) { fclose(f); return; } memset(buckets, 0, sizeof(int) * numBuckets); for (i = 0; i < sampleNum; i++) { uint32_t address = samples[i]; if ((address < min) || (max <= address)) continue; long long a = address - min; long long b = numBuckets; long long c = addressSpace; int index_t = (a * b) / c; /* danger!!!! int32 overflows */ buckets[index_t]++; } /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ writeLong(f, min, target); /* low_pc */ writeLong(f, max, target); /* high_pc */ writeLong(f, numBuckets, target); /* # of buckets */ writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */ writeString(f, "seconds"); for (i = 0; i < (15-strlen("seconds")); i++) writeData(f, &zero, 1); writeString(f, "s"); /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ char *data = malloc(2 * numBuckets); if (data != NULL) { for (i = 0; i < numBuckets; i++) { int val; val = buckets[i]; if (val > 65535) val = 65535; data[i * 2] = val&0xff; data[i * 2 + 1] = (val >> 8) & 0xff; } free(buckets); writeData(f, data, numBuckets * 2); free(data); } else free(buckets); fclose(f); } /* profiling samples the CPU PC as quickly as OpenOCD is able, * which will be used as a random sampling of PC */ COMMAND_HANDLER(handle_profile_command) { struct target *target = get_current_target(CMD_CTX); if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) return ERROR_COMMAND_SYNTAX_ERROR; const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; uint32_t offset; uint32_t num_of_samples; int retval = ERROR_OK; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset); uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM); if (samples == NULL) { LOG_ERROR("No memory to store samples."); return ERROR_FAIL; } /** * Some cores let us sample the PC without the * annoying halt/resume step; for example, ARMv7 PCSR. * Provide a way to use that more efficient mechanism. */ retval = target_profiling(target, samples, MAX_PROFILE_SAMPLE_NUM, &num_of_samples, offset); if (retval != ERROR_OK) { free(samples); return retval; } assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM); retval = target_poll(target); if (retval != ERROR_OK) { free(samples); return retval; } if (target->state == TARGET_RUNNING) { retval = target_halt(target); if (retval != ERROR_OK) { free(samples); return retval; } } retval = target_poll(target); if (retval != ERROR_OK) { free(samples); return retval; } uint32_t start_address = 0; uint32_t end_address = 0; bool with_range = false; if (CMD_ARGC == 4) { with_range = true; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address); } write_gmon(samples, num_of_samples, CMD_ARGV[1], with_range, start_address, end_address, target); command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); free(samples); return retval; } static int new_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t val) { char *namebuf; Jim_Obj *nameObjPtr, *valObjPtr; int result; namebuf = alloc_printf("%s(%d)", varname, idx); if (!namebuf) return JIM_ERR; nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); valObjPtr = Jim_NewIntObj(interp, val); if (!nameObjPtr || !valObjPtr) { free(namebuf); return JIM_ERR; } Jim_IncrRefCount(nameObjPtr); Jim_IncrRefCount(valObjPtr); result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); Jim_DecrRefCount(interp, nameObjPtr); Jim_DecrRefCount(interp, valObjPtr); free(namebuf); /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ return result; } static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *context; struct target *target; context = current_command_context(interp); assert(context != NULL); target = get_current_target(context); if (target == NULL) { LOG_ERROR("mem2array: no current target"); return JIM_ERR; } return target_mem2array(interp, target, argc - 1, argv + 1); } static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { long l; uint32_t width; int len; uint32_t addr; uint32_t count; uint32_t v; const char *varname; int n, e, retval; uint32_t i; /* argv[1] = name of array to receive the data * argv[2] = desired width * argv[3] = memory address * argv[4] = count of times to read */ if (argc != 4) { Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); /* given "foo" get space for worse case "foo(%d)" .. add 20 */ e = Jim_GetLong(interp, argv[1], &l); width = l; if (e != JIM_OK) return e; e = Jim_GetLong(interp, argv[2], &l); addr = l; if (e != JIM_OK) return e; e = Jim_GetLong(interp, argv[3], &l); len = l; if (e != JIM_OK) return e; switch (width) { case 8: width = 1; break; case 16: width = 2; break; case 32: width = 4; break; default: Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL); return JIM_ERR; } if (len == 0) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); return JIM_ERR; } if ((addr + (len * width)) < addr) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); return JIM_ERR; } /* absurd transfer size? */ if (len > 65536) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL); return JIM_ERR; } if ((width == 1) || ((width == 2) && ((addr & 1) == 0)) || ((width == 4) && ((addr & 3) == 0))) { /* all is well */ } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", addr, width); Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); return JIM_ERR; } /* Transfer loop */ /* index counter */ n = 0; size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); if (buffer == NULL) return JIM_ERR; /* assume ok */ e = JIM_OK; while (len) { /* Slurp... in buffer size chunks */ count = len; /* in objects.. */ if (count > (buffersize / width)) count = (buffersize / width); retval = target_read_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", (unsigned int)addr, (int)width, (int)count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); e = JIM_ERR; break; } else { v = 0; /* shut up gcc */ for (i = 0; i < count ; i++, n++) { switch (width) { case 4: v = target_buffer_get_u32(target, &buffer[i*width]); break; case 2: v = target_buffer_get_u16(target, &buffer[i*width]); break; case 1: v = buffer[i] & 0x0ff; break; } new_int_array_element(interp, varname, n, v); } len -= count; addr += count * width; } } free(buffer); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); return e; } static int get_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t *val) { char *namebuf; Jim_Obj *nameObjPtr, *valObjPtr; int result; long l; namebuf = alloc_printf("%s(%d)", varname, idx); if (!namebuf) return JIM_ERR; nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); if (!nameObjPtr) { free(namebuf); return JIM_ERR; } Jim_IncrRefCount(nameObjPtr); valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); Jim_DecrRefCount(interp, nameObjPtr); free(namebuf); if (valObjPtr == NULL) return JIM_ERR; result = Jim_GetLong(interp, valObjPtr, &l); /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ *val = l; return result; } static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *context; struct target *target; context = current_command_context(interp); assert(context != NULL); target = get_current_target(context); if (target == NULL) { LOG_ERROR("array2mem: no current target"); return JIM_ERR; } return target_array2mem(interp, target, argc-1, argv + 1); } static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { long l; uint32_t width; int len; uint32_t addr; uint32_t count; uint32_t v; const char *varname; int n, e, retval; uint32_t i; /* argv[1] = name of array to get the data * argv[2] = desired width * argv[3] = memory address * argv[4] = count to write */ if (argc != 4) { Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); /* given "foo" get space for worse case "foo(%d)" .. add 20 */ e = Jim_GetLong(interp, argv[1], &l); width = l; if (e != JIM_OK) return e; e = Jim_GetLong(interp, argv[2], &l); addr = l; if (e != JIM_OK) return e; e = Jim_GetLong(interp, argv[3], &l); len = l; if (e != JIM_OK) return e; switch (width) { case 8: width = 1; break; case 16: width = 2; break; case 32: width = 4; break; default: Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL); return JIM_ERR; } if (len == 0) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL); return JIM_ERR; } if ((addr + (len * width)) < addr) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL); return JIM_ERR; } /* absurd transfer size? */ if (len > 65536) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL); return JIM_ERR; } if ((width == 1) || ((width == 2) && ((addr & 1) == 0)) || ((width == 4) && ((addr & 3) == 0))) { /* all is well */ } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", (unsigned int)addr, (int)width); Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); return JIM_ERR; } /* Transfer loop */ /* index counter */ n = 0; /* assume ok */ e = JIM_OK; size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); if (buffer == NULL) return JIM_ERR; while (len) { /* Slurp... in buffer size chunks */ count = len; /* in objects.. */ if (count > (buffersize / width)) count = (buffersize / width); v = 0; /* shut up gcc */ for (i = 0; i < count; i++, n++) { get_int_array_element(interp, varname, n, &v); switch (width) { case 4: target_buffer_set_u32(target, &buffer[i * width], v); break; case 2: target_buffer_set_u16(target, &buffer[i * width], v); break; case 1: buffer[i] = v & 0x0ff; break; } } len -= count; retval = target_write_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", (unsigned int)addr, (int)width, (int)count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); e = JIM_ERR; break; } addr += count * width; } free(buffer); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); return e; } /* FIX? should we propagate errors here rather than printing them * and continuing? */ void target_handle_event(struct target *target, enum target_event e) { struct target_event_action *teap; for (teap = target->event_action; teap != NULL; teap = teap->next) { if (teap->event == e) { LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", target->target_number, target_name(target), target_type_name(target), e, Jim_Nvp_value2name_simple(nvp_target_event, e)->name, Jim_GetString(teap->body, NULL)); if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { Jim_MakeErrorMessage(teap->interp); command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); } } } } /** * Returns true only if the target has a handler for the specified event. */ bool target_has_event_action(struct target *target, enum target_event event) { struct target_event_action *teap; for (teap = target->event_action; teap != NULL; teap = teap->next) { if (teap->event == event) return true; } return false; } enum target_cfg_param { TCFG_TYPE, TCFG_EVENT, TCFG_WORK_AREA_VIRT, TCFG_WORK_AREA_PHYS, TCFG_WORK_AREA_SIZE, TCFG_WORK_AREA_BACKUP, TCFG_ENDIAN, TCFG_COREID, TCFG_CHAIN_POSITION, TCFG_DBGBASE, TCFG_RTOS, }; static Jim_Nvp nvp_config_opts[] = { { .name = "-type", .value = TCFG_TYPE }, { .name = "-event", .value = TCFG_EVENT }, { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS }, { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE }, { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP }, { .name = "-endian" , .value = TCFG_ENDIAN }, { .name = "-coreid", .value = TCFG_COREID }, { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, { .name = "-rtos", .value = TCFG_RTOS }, { .name = NULL, .value = -1 } }; static int target_configure(Jim_GetOptInfo *goi, struct target *target) { Jim_Nvp *n; Jim_Obj *o; jim_wide w; int e; /* parse config or cget options ... */ while (goi->argc > 0) { Jim_SetEmptyResult(goi->interp); /* Jim_GetOpt_Debug(goi); */ if (target->type->target_jim_configure) { /* target defines a configure function */ /* target gets first dibs on parameters */ e = (*(target->type->target_jim_configure))(target, goi); if (e == JIM_OK) { /* more? */ continue; } if (e == JIM_ERR) { /* An error */ return e; } /* otherwise we 'continue' below */ } e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); return e; } switch (n->value) { case TCFG_TYPE: /* not setable */ if (goi->isconfigure) { Jim_SetResultFormatted(goi->interp, "not settable: %s", n->name); return JIM_ERR; } else { no_params: if (goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); return JIM_ERR; } } Jim_SetResultString(goi->interp, target_type_name(target), -1); /* loop for more */ break; case TCFG_EVENT: if (goi->argc == 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); return JIM_ERR; } e = Jim_GetOpt_Nvp(goi, nvp_target_event, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, nvp_target_event, 1); return e; } if (goi->isconfigure) { if (goi->argc != 1) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; } } else { if (goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); return JIM_ERR; } } { struct target_event_action *teap; teap = target->event_action; /* replace existing? */ while (teap) { if (teap->event == (enum target_event)n->value) break; teap = teap->next; } if (goi->isconfigure) { bool replace = true; if (teap == NULL) { /* create new */ teap = calloc(1, sizeof(*teap)); replace = false; } teap->event = n->value; teap->interp = goi->interp; Jim_GetOpt_Obj(goi, &o); if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); teap->body = Jim_DuplicateObj(goi->interp, o); /* * FIXME: * Tcl/TK - "tk events" have a nice feature. * See the "BIND" command. * We should support that here. * You can specify %X and %Y in the event code. * The idea is: %T - target name. * The idea is: %N - target number * The idea is: %E - event name. */ Jim_IncrRefCount(teap->body); if (!replace) { /* add to head of event list */ teap->next = target->event_action; target->event_action = teap; } Jim_SetEmptyResult(goi->interp); } else { /* get */ if (teap == NULL) Jim_SetEmptyResult(goi->interp); else Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); } } /* loop for more */ break; case TCFG_WORK_AREA_VIRT: if (goi->isconfigure) { target_free_all_working_areas(target); e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; target->working_area_virt = w; target->working_area_virt_spec = true; } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); /* loop for more */ break; case TCFG_WORK_AREA_PHYS: if (goi->isconfigure) { target_free_all_working_areas(target); e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; target->working_area_phys = w; target->working_area_phys_spec = true; } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); /* loop for more */ break; case TCFG_WORK_AREA_SIZE: if (goi->isconfigure) { target_free_all_working_areas(target); e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; target->working_area_size = w; } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); /* loop for more */ break; case TCFG_WORK_AREA_BACKUP: if (goi->isconfigure) { target_free_all_working_areas(target); e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; /* make this exactly 1 or 0 */ target->backup_working_area = (!!w); } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); /* loop for more e*/ break; case TCFG_ENDIAN: if (goi->isconfigure) { e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(goi, nvp_target_endian, 1); return e; } target->endianness = n->value; } else { if (goi->argc != 0) goto no_params; } n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); if (n->name == NULL) { target->endianness = TARGET_LITTLE_ENDIAN; n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); } Jim_SetResultString(goi->interp, n->name, -1); /* loop for more */ break; case TCFG_COREID: if (goi->isconfigure) { e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; target->coreid = (int32_t)w; } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); /* loop for more */ break; case TCFG_CHAIN_POSITION: if (goi->isconfigure) { Jim_Obj *o_t; struct jtag_tap *tap; target_free_all_working_areas(target); e = Jim_GetOpt_Obj(goi, &o_t); if (e != JIM_OK) return e; tap = jtag_tap_by_jim_obj(goi->interp, o_t); if (tap == NULL) return JIM_ERR; /* make this exactly 1 or 0 */ target->tap = tap; } else { if (goi->argc != 0) goto no_params; } Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); /* loop for more e*/ break; case TCFG_DBGBASE: if (goi->isconfigure) { e = Jim_GetOpt_Wide(goi, &w); if (e != JIM_OK) return e; target->dbgbase = (uint32_t)w; target->dbgbase_set = true; } else { if (goi->argc != 0) goto no_params; } Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); /* loop for more */ break; case TCFG_RTOS: /* RTOS */ { int result = rtos_create(goi, target); if (result != JIM_OK) return result; } /* loop for more */ break; } } /* while (goi->argc) */ /* done - we return */ return JIM_OK; } static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); int need_args = 1 + goi.isconfigure; if (goi.argc < need_args) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, goi.isconfigure ? "missing: -option VALUE ..." : "missing: -option ..."); return JIM_ERR; } struct target *target = Jim_CmdPrivData(goi.interp); return target_configure(&goi, target); } static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 2 || goi.argc > 4) { Jim_SetResultFormatted(goi.interp, "usage: %s [phys]
[]", cmd_name); return JIM_ERR; } target_write_fn fn; fn = target_write_memory; int e; if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { /* consume it */ struct Jim_Obj *obj; e = Jim_GetOpt_Obj(&goi, &obj); if (e != JIM_OK) return e; fn = target_write_phys_memory; } jim_wide a; e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; jim_wide b; e = Jim_GetOpt_Wide(&goi, &b); if (e != JIM_OK) return e; jim_wide c = 1; if (goi.argc == 1) { e = Jim_GetOpt_Wide(&goi, &c); if (e != JIM_OK) return e; } /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; struct target *target = Jim_CmdPrivData(goi.interp); unsigned data_size; if (strcasecmp(cmd_name, "mww") == 0) data_size = 4; else if (strcasecmp(cmd_name, "mwh") == 0) data_size = 2; else if (strcasecmp(cmd_name, "mwb") == 0) data_size = 1; else { LOG_ERROR("command '%s' unknown: ", cmd_name); return JIM_ERR; } return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; } /** * @brief Reads an array of words/halfwords/bytes from target memory starting at specified address. * * Usage: mdw [phys]
[] - for 32 bit reads * mdh [phys]
[] - for 16 bit reads * mdb [phys]
[] - for 8 bit reads * * Count defaults to 1. * * Calls target_read_memory or target_read_phys_memory depending on * the presence of the "phys" argument * Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted * to int representation in base16. * Also outputs read data in a human readable form using command_print * * @param phys if present target_read_phys_memory will be used instead of target_read_memory * @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix * @param count optional count parameter to read an array of values. If not specified, defaults to 1. * @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers * on success, with [] number of elements. * * In case of little endian target: * Example1: "mdw 0x00000000" returns "10123456" * Exmaple2: "mdh 0x00000000 1" returns "3456" * Example3: "mdb 0x00000000" returns "56" * Example4: "mdh 0x00000000 2" returns "3456 1012" * Example5: "mdb 0x00000000 3" returns "56 34 12" **/ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if ((goi.argc < 1) || (goi.argc > 3)) { Jim_SetResultFormatted(goi.interp, "usage: %s [phys]
[]", cmd_name); return JIM_ERR; } int (*fn)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); fn = target_read_memory; int e; if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { /* consume it */ struct Jim_Obj *obj; e = Jim_GetOpt_Obj(&goi, &obj); if (e != JIM_OK) return e; fn = target_read_phys_memory; } /* Read address parameter */ jim_wide addr; e = Jim_GetOpt_Wide(&goi, &addr); if (e != JIM_OK) return JIM_ERR; /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */ jim_wide count; if (goi.argc == 1) { e = Jim_GetOpt_Wide(&goi, &count); if (e != JIM_OK) return JIM_ERR; } else count = 1; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; jim_wide dwidth = 1; /* shut up gcc */ if (strcasecmp(cmd_name, "mdw") == 0) dwidth = 4; else if (strcasecmp(cmd_name, "mdh") == 0) dwidth = 2; else if (strcasecmp(cmd_name, "mdb") == 0) dwidth = 1; else { LOG_ERROR("command '%s' unknown: ", cmd_name); return JIM_ERR; } /* convert count to "bytes" */ int bytes = count * dwidth; struct target *target = Jim_CmdPrivData(goi.interp); uint8_t target_buf[32]; jim_wide x, y, z; while (bytes > 0) { y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */ /* Try to read out next block */ e = fn(target, addr, dwidth, y / dwidth, target_buf); if (e != ERROR_OK) { Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); return JIM_ERR; } command_print_sameline(NULL, "0x%08x ", (int)(addr)); switch (dwidth) { case 4: for (x = 0; x < 16 && x < y; x += 4) { z = target_buffer_get_u32(target, &(target_buf[x])); command_print_sameline(NULL, "%08x ", (int)(z)); } for (; (x < 16) ; x += 4) command_print_sameline(NULL, " "); break; case 2: for (x = 0; x < 16 && x < y; x += 2) { z = target_buffer_get_u16(target, &(target_buf[x])); command_print_sameline(NULL, "%04x ", (int)(z)); } for (; (x < 16) ; x += 2) command_print_sameline(NULL, " "); break; case 1: default: for (x = 0 ; (x < 16) && (x < y) ; x += 1) { z = target_buffer_get_u8(target, &(target_buf[x])); command_print_sameline(NULL, "%02x ", (int)(z)); } for (; (x < 16) ; x += 1) command_print_sameline(NULL, " "); break; } /* ascii-ify the bytes */ for (x = 0 ; x < y ; x++) { if ((target_buf[x] >= 0x20) && (target_buf[x] <= 0x7e)) { /* good */ } else { /* smack it */ target_buf[x] = '.'; } } /* space pad */ while (x < 16) { target_buf[x] = ' '; x++; } /* terminate */ target_buf[16] = 0; /* print - with a newline */ command_print_sameline(NULL, "%s\n", target_buf); /* NEXT... */ bytes -= 16; addr += 16; } return JIM_OK; } static int jim_target_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct target *target = Jim_CmdPrivData(interp); return target_mem2array(interp, target, argc - 1, argv + 1); } static int jim_target_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct target *target = Jim_CmdPrivData(interp); return target_array2mem(interp, target, argc - 1, argv + 1); } static int jim_target_tap_disabled(Jim_Interp *interp) { Jim_SetResultFormatted(interp, "[TAP is disabled]"); return JIM_ERR; } static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e = target->type->examine(target); if (e != ERROR_OK) return JIM_ERR; return JIM_OK; } static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } struct target *target = Jim_CmdPrivData(interp); if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) return JIM_ERR; return JIM_OK; } static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e; if (!(target_was_examined(target))) e = ERROR_TARGET_NOT_EXAMINED; else e = target->type->poll(target); if (e != ERROR_OK) return JIM_ERR; return JIM_OK; } static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc != 2) { Jim_WrongNumArgs(interp, 0, argv, "([tT]|[fF]|assert|deassert) BOOL"); return JIM_ERR; } Jim_Nvp *n; int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); return e; } /* the halt or not param */ jim_wide a; e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; struct target *target = Jim_CmdPrivData(goi.interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); if (!(target_was_examined(target))) { LOG_ERROR("Target not examined yet"); return ERROR_TARGET_NOT_EXAMINED; } if (!target->type->assert_reset || !target->type->deassert_reset) { Jim_SetResultFormatted(interp, "No target-specific reset for %s", target_name(target)); return JIM_ERR; } /* determine if we should halt or not. */ target->reset_halt = !!a; /* When this happens - all workareas are invalid. */ target_free_all_working_areas_restore(target, 0); /* do the assert */ if (n->value == NVP_ASSERT) e = target->type->assert_reset(target); else e = target->type->deassert_reset(target); return (e == ERROR_OK) ? JIM_OK : JIM_ERR; } static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e = target->type->halt(target); return (e == ERROR_OK) ? JIM_OK : JIM_ERR; } static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); /* params: statename timeoutmsecs */ if (goi.argc != 2) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); return JIM_ERR; } Jim_Nvp *n; int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(&goi, nvp_target_state, 1); return e; } jim_wide a; e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); e = target_wait_state(target, n->value, a); if (e != ERROR_OK) { Jim_Obj *eObj = Jim_NewIntObj(interp, e); Jim_SetResultFormatted(goi.interp, "target: %s wait %s fails (%#s) %s", target_name(target), n->name, eObj, target_strerror_safe(e)); Jim_FreeNewObj(interp, eObj); return JIM_ERR; } return JIM_OK; } /* List for human, Events defined for this target. * scripts/programs should use 'name cget -event NAME' */ static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *cmd_ctx = current_command_context(interp); assert(cmd_ctx != NULL); struct target *target = Jim_CmdPrivData(interp); struct target_event_action *teap = target->event_action; command_print(cmd_ctx, "Event actions for target (%d) %s\n", target->target_number, target_name(target)); command_print(cmd_ctx, "%-25s | Body", "Event"); command_print(cmd_ctx, "------------------------- | " "----------------------------------------"); while (teap) { Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event); command_print(cmd_ctx, "%-25s | %s", opt->name, Jim_GetString(teap->body, NULL)); teap = teap->next; } command_print(cmd_ctx, "***END***"); return JIM_OK; } static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } struct target *target = Jim_CmdPrivData(interp); Jim_SetResultString(interp, target_state_name(target), -1); return JIM_OK; } static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc != 1) { const char *cmd_name = Jim_GetString(argv[0], NULL); Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); return JIM_ERR; } Jim_Nvp *n; int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n); if (e != JIM_OK) { Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); return e; } struct target *target = Jim_CmdPrivData(interp); target_handle_event(target, n->value); return JIM_OK; } static const struct command_registration target_instance_command_handlers[] = { { .name = "configure", .mode = COMMAND_CONFIG, .jim_handler = jim_target_configure, .help = "configure a new target for use", .usage = "[target_attribute ...]", }, { .name = "cget", .mode = COMMAND_ANY, .jim_handler = jim_target_configure, .help = "returns the specified target attribute", .usage = "target_attribute", }, { .name = "mww", .mode = COMMAND_EXEC, .jim_handler = jim_target_mw, .help = "Write 32-bit word(s) to target memory", .usage = "address data [count]", }, { .name = "mwh", .mode = COMMAND_EXEC, .jim_handler = jim_target_mw, .help = "Write 16-bit half-word(s) to target memory", .usage = "address data [count]", }, { .name = "mwb", .mode = COMMAND_EXEC, .jim_handler = jim_target_mw, .help = "Write byte(s) to target memory", .usage = "address data [count]", }, { .name = "mdw", .mode = COMMAND_EXEC, .jim_handler = jim_target_md, .help = "Display target memory as 32-bit words", .usage = "address [count]", }, { .name = "mdh", .mode = COMMAND_EXEC, .jim_handler = jim_target_md, .help = "Display target memory as 16-bit half-words", .usage = "address [count]", }, { .name = "mdb", .mode = COMMAND_EXEC, .jim_handler = jim_target_md, .help = "Display target memory as 8-bit bytes", .usage = "address [count]", }, { .name = "array2mem", .mode = COMMAND_EXEC, .jim_handler = jim_target_array2mem, .help = "Writes Tcl array of 8/16/32 bit numbers " "to target memory", .usage = "arrayname bitwidth address count", }, { .name = "mem2array", .mode = COMMAND_EXEC, .jim_handler = jim_target_mem2array, .help = "Loads Tcl array of 8/16/32 bit numbers " "from target memory", .usage = "arrayname bitwidth address count", }, { .name = "eventlist", .mode = COMMAND_EXEC, .jim_handler = jim_target_event_list, .help = "displays a table of events defined for this target", }, { .name = "curstate", .mode = COMMAND_EXEC, .jim_handler = jim_target_current_state, .help = "displays the current state of this target", }, { .name = "arp_examine", .mode = COMMAND_EXEC, .jim_handler = jim_target_examine, .help = "used internally for reset processing", }, { .name = "arp_halt_gdb", .mode = COMMAND_EXEC, .jim_handler = jim_target_halt_gdb, .help = "used internally for reset processing to halt GDB", }, { .name = "arp_poll", .mode = COMMAND_EXEC, .jim_handler = jim_target_poll, .help = "used internally for reset processing", }, { .name = "arp_reset", .mode = COMMAND_EXEC, .jim_handler = jim_target_reset, .help = "used internally for reset processing", }, { .name = "arp_halt", .mode = COMMAND_EXEC, .jim_handler = jim_target_halt, .help = "used internally for reset processing", }, { .name = "arp_waitstate", .mode = COMMAND_EXEC, .jim_handler = jim_target_wait_state, .help = "used internally for reset processing", }, { .name = "invoke-event", .mode = COMMAND_EXEC, .jim_handler = jim_target_invoke_event, .help = "invoke handler for specified event", .usage = "event_name", }, COMMAND_REGISTRATION_DONE }; static int target_create(Jim_GetOptInfo *goi) { Jim_Obj *new_cmd; Jim_Cmd *cmd; const char *cp; char *cp2; int e; int x; struct target *target; struct command_context *cmd_ctx; cmd_ctx = current_command_context(goi->interp); assert(cmd_ctx != NULL); if (goi->argc < 3) { Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); return JIM_ERR; } /* COMMAND */ Jim_GetOpt_Obj(goi, &new_cmd); /* does this command exist? */ cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); if (cmd) { cp = Jim_GetString(new_cmd, NULL); Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); return JIM_ERR; } /* TYPE */ e = Jim_GetOpt_String(goi, &cp2, NULL); if (e != JIM_OK) return e; cp = cp2; struct transport *tr = get_current_transport(); if (tr->override_target) { e = tr->override_target(&cp); if (e != ERROR_OK) { LOG_ERROR("The selected transport doesn't support this target"); return JIM_ERR; } LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD"); } /* now does target type exist */ for (x = 0 ; target_types[x] ; x++) { if (0 == strcmp(cp, target_types[x]->name)) { /* found */ break; } /* check for deprecated name */ if (target_types[x]->deprecated_name) { if (0 == strcmp(cp, target_types[x]->deprecated_name)) { /* found */ LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name); break; } } } if (target_types[x] == NULL) { Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); for (x = 0 ; target_types[x] ; x++) { if (target_types[x + 1]) { Jim_AppendStrings(goi->interp, Jim_GetResult(goi->interp), target_types[x]->name, ", ", NULL); } else { Jim_AppendStrings(goi->interp, Jim_GetResult(goi->interp), " or ", target_types[x]->name, NULL); } } return JIM_ERR; } /* Create it */ target = calloc(1, sizeof(struct target)); /* set target number */ target->target_number = new_target_number(); cmd_ctx->current_target = target->target_number; /* allocate memory for each unique target type */ target->type = calloc(1, sizeof(struct target_type)); memcpy(target->type, target_types[x], sizeof(struct target_type)); /* will be set by "-endian" */ target->endianness = TARGET_ENDIAN_UNKNOWN; /* default to first core, override with -coreid */ target->coreid = 0; target->working_area = 0x0; target->working_area_size = 0x0; target->working_areas = NULL; target->backup_working_area = 0; target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; target->reg_cache = NULL; target->breakpoints = NULL; target->watchpoints = NULL; target->next = NULL; target->arch_info = NULL; target->display = 1; target->halt_issued = false; /* initialize trace information */ target->trace_info = malloc(sizeof(struct trace)); target->trace_info->num_trace_points = 0; target->trace_info->trace_points_size = 0; target->trace_info->trace_points = NULL; target->trace_info->trace_history_size = 0; target->trace_info->trace_history = NULL; target->trace_info->trace_history_pos = 0; target->trace_info->trace_history_overflowed = 0; target->dbgmsg = NULL; target->dbg_msg_enabled = 0; target->endianness = TARGET_ENDIAN_UNKNOWN; target->rtos = NULL; target->rtos_auto_detect = false; /* Do the rest as "configure" options */ goi->isconfigure = 1; e = target_configure(goi, target); if (target->tap == NULL) { Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1); e = JIM_ERR; } if (e != JIM_OK) { free(target->type); free(target); return e; } if (target->endianness == TARGET_ENDIAN_UNKNOWN) { /* default endian to little if not specified */ target->endianness = TARGET_LITTLE_ENDIAN; } cp = Jim_GetString(new_cmd, NULL); target->cmd_name = strdup(cp); /* create the target specific commands */ if (target->type->commands) { e = register_commands(cmd_ctx, NULL, target->type->commands); if (ERROR_OK != e) LOG_ERROR("unable to register '%s' commands", cp); } if (target->type->target_create) (*(target->type->target_create))(target, goi->interp); /* append to end of list */ { struct target **tpp; tpp = &(all_targets); while (*tpp) tpp = &((*tpp)->next); *tpp = target; } /* now - create the new target name command */ const struct command_registration target_subcommands[] = { { .chain = target_instance_command_handlers, }, { .chain = target->type->commands, }, COMMAND_REGISTRATION_DONE }; const struct command_registration target_commands[] = { { .name = cp, .mode = COMMAND_ANY, .help = "target command group", .usage = "", .chain = target_subcommands, }, COMMAND_REGISTRATION_DONE }; e = register_commands(cmd_ctx, NULL, target_commands); if (ERROR_OK != e) return JIM_ERR; struct command *c = command_find_in_context(cmd_ctx, cp); assert(c); command_set_handler_data(c, target); return (ERROR_OK == e) ? JIM_OK : JIM_ERR; } static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); return JIM_ERR; } struct command_context *cmd_ctx = current_command_context(interp); assert(cmd_ctx != NULL); Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1); return JIM_OK; } static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); return JIM_ERR; } Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); for (unsigned x = 0; NULL != target_types[x]; x++) { Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, target_types[x]->name, -1)); } return JIM_OK; } static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); return JIM_ERR; } Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); struct target *target = all_targets; while (target) { Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, target_name(target), -1)); target = target->next; } return JIM_OK; } static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; const char *targetname; int retval, len; struct target *target = (struct target *) NULL; struct target_list *head, *curr, *new; curr = (struct target_list *) NULL; head = (struct target_list *) NULL; retval = 0; LOG_DEBUG("%d", argc); /* argv[1] = target to associate in smp * argv[2] = target to assoicate in smp * argv[3] ... */ for (i = 1; i < argc; i++) { targetname = Jim_GetString(argv[i], &len); target = get_target(targetname); LOG_DEBUG("%s ", targetname); if (target) { new = malloc(sizeof(struct target_list)); new->target = target; new->next = (struct target_list *)NULL; if (head == (struct target_list *)NULL) { head = new; curr = head; } else { curr->next = new; curr = new; } } } /* now parse the list of cpu and put the target in smp mode*/ curr = head; while (curr != (struct target_list *)NULL) { target = curr->target; target->smp = 1; target->head = head; curr = curr->next; } if (target && target->rtos) retval = rtos_smp_init(head->target); return retval; } static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 3) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, " [ ...]"); return JIM_ERR; } return target_create(&goi); } static const struct command_registration target_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_CONFIG, .handler = handle_target_init_command, .help = "initialize targets", }, { .name = "create", /* REVISIT this should be COMMAND_CONFIG ... */ .mode = COMMAND_ANY, .jim_handler = jim_target_create, .usage = "name type '-chain-position' name [options ...]", .help = "Creates and selects a new target", }, { .name = "current", .mode = COMMAND_ANY, .jim_handler = jim_target_current, .help = "Returns the currently selected target", }, { .name = "types", .mode = COMMAND_ANY, .jim_handler = jim_target_types, .help = "Returns the available target types as " "a list of strings", }, { .name = "names", .mode = COMMAND_ANY, .jim_handler = jim_target_names, .help = "Returns the names of all targets as a list of strings", }, { .name = "smp", .mode = COMMAND_ANY, .jim_handler = jim_target_smp, .usage = "targetname1 targetname2 ...", .help = "gather several target in a smp list" }, COMMAND_REGISTRATION_DONE }; struct FastLoad { uint32_t address; uint8_t *data; int length; }; static int fastload_num; static struct FastLoad *fastload; static void free_fastload(void) { if (fastload != NULL) { int i; for (i = 0; i < fastload_num; i++) { if (fastload[i].data) free(fastload[i].data); } free(fastload); fastload = NULL; } } COMMAND_HANDLER(handle_fast_load_image_command) { uint8_t *buffer; size_t buf_cnt; uint32_t image_size; uint32_t min_address = 0; uint32_t max_address = 0xffffffff; int i; struct image image; int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, &image, &min_address, &max_address); if (ERROR_OK != retval) return retval; struct duration bench; duration_start(&bench); retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) return retval; image_size = 0x0; retval = ERROR_OK; fastload_num = image.num_sections; fastload = malloc(sizeof(struct FastLoad)*image.num_sections); if (fastload == NULL) { command_print(CMD_CTX, "out of memory"); image_close(&image); return ERROR_FAIL; } memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); for (i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); retval = ERROR_FAIL; break; } retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); if (retval != ERROR_OK) { free(buffer); break; } uint32_t offset = 0; uint32_t length = buf_cnt; /* DANGER!!! beware of unsigned comparision here!!! */ if ((image.sections[i].base_address + buf_cnt >= min_address) && (image.sections[i].base_address < max_address)) { if (image.sections[i].base_address < min_address) { /* clip addresses below */ offset += min_address-image.sections[i].base_address; length -= offset; } if (image.sections[i].base_address + buf_cnt > max_address) length -= (image.sections[i].base_address + buf_cnt)-max_address; fastload[i].address = image.sections[i].base_address + offset; fastload[i].data = malloc(length); if (fastload[i].data == NULL) { free(buffer); command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)", length); retval = ERROR_FAIL; break; } memcpy(fastload[i].data, buffer + offset, length); fastload[i].length = length; image_size += length; command_print(CMD_CTX, "%u bytes written at address 0x%8.8x", (unsigned int)length, ((unsigned int)(image.sections[i].base_address + offset))); } free(buffer); } if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); command_print(CMD_CTX, "WARNING: image has not been loaded to target!" "You can issue a 'fast_load' to finish loading."); } image_close(&image); if (retval != ERROR_OK) free_fastload(); return retval; } COMMAND_HANDLER(handle_fast_load_command) { if (CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; if (fastload == NULL) { LOG_ERROR("No image in memory"); return ERROR_FAIL; } int i; int ms = timeval_ms(); int size = 0; int retval = ERROR_OK; for (i = 0; i < fastload_num; i++) { struct target *target = get_current_target(CMD_CTX); command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x", (unsigned int)(fastload[i].address), (unsigned int)(fastload[i].length)); retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data); if (retval != ERROR_OK) break; size += fastload[i].length; } if (retval == ERROR_OK) { int after = timeval_ms(); command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); } return retval; } static const struct command_registration target_command_handlers[] = { { .name = "targets", .handler = handle_targets_command, .mode = COMMAND_ANY, .help = "change current default target (one parameter) " "or prints table of all targets (no parameters)", .usage = "[target]", }, { .name = "target", .mode = COMMAND_CONFIG, .help = "configure target", .chain = target_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; int target_register_commands(struct command_context *cmd_ctx) { return register_commands(cmd_ctx, NULL, target_command_handlers); } static bool target_reset_nag = true; bool get_target_reset_nag(void) { return target_reset_nag; } COMMAND_HANDLER(handle_target_reset_nag) { return CALL_COMMAND_HANDLER(handle_command_parse_bool, &target_reset_nag, "Nag after each reset about options to improve " "performance"); } COMMAND_HANDLER(handle_ps_command) { struct target *target = get_current_target(CMD_CTX); char *display; if (target->state != TARGET_HALTED) { LOG_INFO("target not halted !!"); return ERROR_OK; } if ((target->rtos) && (target->rtos->type) && (target->rtos->type->ps_command)) { display = target->rtos->type->ps_command(target); command_print(CMD_CTX, "%s", display); free(display); return ERROR_OK; } else { LOG_INFO("failed"); return ERROR_TARGET_FAILURE; } } static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size) { if (text != NULL) command_print_sameline(cmd_ctx, "%s", text); for (int i = 0; i < size; i++) command_print_sameline(cmd_ctx, " %02x", buf[i]); command_print(cmd_ctx, " "); } COMMAND_HANDLER(handle_test_mem_access_command) { struct target *target = get_current_target(CMD_CTX); uint32_t test_size; int retval = ERROR_OK; if (target->state != TARGET_HALTED) { LOG_INFO("target not halted !!"); return ERROR_FAIL; } if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size); /* Test reads */ size_t num_bytes = test_size + 4; struct working_area *wa = NULL; retval = target_alloc_working_area(target, num_bytes, &wa); if (retval != ERROR_OK) { LOG_ERROR("Not enough working area"); return ERROR_FAIL; } uint8_t *test_pattern = malloc(num_bytes); for (size_t i = 0; i < num_bytes; i++) test_pattern[i] = rand(); retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); if (retval != ERROR_OK) { LOG_ERROR("Test pattern write failed"); goto out; } for (int host_offset = 0; host_offset <= 1; host_offset++) { for (int size = 1; size <= 4; size *= 2) { for (int offset = 0; offset < 4; offset++) { uint32_t count = test_size / size; size_t host_bufsiz = (count + 2) * size + host_offset; uint8_t *read_ref = malloc(host_bufsiz); uint8_t *read_buf = malloc(host_bufsiz); for (size_t i = 0; i < host_bufsiz; i++) { read_ref[i] = rand(); read_buf[i] = read_ref[i]; } command_print_sameline(CMD_CTX, "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count, size, offset, host_offset ? "un" : ""); struct duration bench; duration_start(&bench); retval = target_read_memory(target, wa->address + offset, size, count, read_buf + size + host_offset); duration_measure(&bench); if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { command_print(CMD_CTX, "Unsupported alignment"); goto next; } else if (retval != ERROR_OK) { command_print(CMD_CTX, "Memory read failed"); goto next; } /* replay on host */ memcpy(read_ref + size + host_offset, test_pattern + offset, count * size); /* check result */ int result = memcmp(read_ref, read_buf, host_bufsiz); if (result == 0) { command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", duration_elapsed(&bench), duration_kbps(&bench, count * size)); } else { command_print(CMD_CTX, "Compare failed"); binprint(CMD_CTX, "ref:", read_ref, host_bufsiz); binprint(CMD_CTX, "buf:", read_buf, host_bufsiz); } next: free(read_ref); free(read_buf); } } } out: free(test_pattern); if (wa != NULL) target_free_working_area(target, wa); /* Test writes */ num_bytes = test_size + 4 + 4 + 4; retval = target_alloc_working_area(target, num_bytes, &wa); if (retval != ERROR_OK) { LOG_ERROR("Not enough working area"); return ERROR_FAIL; } test_pattern = malloc(num_bytes); for (size_t i = 0; i < num_bytes; i++) test_pattern[i] = rand(); for (int host_offset = 0; host_offset <= 1; host_offset++) { for (int size = 1; size <= 4; size *= 2) { for (int offset = 0; offset < 4; offset++) { uint32_t count = test_size / size; size_t host_bufsiz = count * size + host_offset; uint8_t *read_ref = malloc(num_bytes); uint8_t *read_buf = malloc(num_bytes); uint8_t *write_buf = malloc(host_bufsiz); for (size_t i = 0; i < host_bufsiz; i++) write_buf[i] = rand(); command_print_sameline(CMD_CTX, "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count, size, offset, host_offset ? "un" : ""); retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); if (retval != ERROR_OK) { command_print(CMD_CTX, "Test pattern write failed"); goto nextw; } /* replay on host */ memcpy(read_ref, test_pattern, num_bytes); memcpy(read_ref + size + offset, write_buf + host_offset, count * size); struct duration bench; duration_start(&bench); retval = target_write_memory(target, wa->address + size + offset, size, count, write_buf + host_offset); duration_measure(&bench); if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { command_print(CMD_CTX, "Unsupported alignment"); goto nextw; } else if (retval != ERROR_OK) { command_print(CMD_CTX, "Memory write failed"); goto nextw; } /* read back */ retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf); if (retval != ERROR_OK) { command_print(CMD_CTX, "Test pattern write failed"); goto nextw; } /* check result */ int result = memcmp(read_ref, read_buf, num_bytes); if (result == 0) { command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", duration_elapsed(&bench), duration_kbps(&bench, count * size)); } else { command_print(CMD_CTX, "Compare failed"); binprint(CMD_CTX, "ref:", read_ref, num_bytes); binprint(CMD_CTX, "buf:", read_buf, num_bytes); } nextw: free(read_ref); free(read_buf); } } } free(test_pattern); if (wa != NULL) target_free_working_area(target, wa); return retval; } static const struct command_registration target_exec_command_handlers[] = { { .name = "fast_load_image", .handler = handle_fast_load_image_command, .mode = COMMAND_ANY, .help = "Load image into server memory for later use by " "fast_load; primarily for profiling", .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " "[min_address [max_length]]", }, { .name = "fast_load", .handler = handle_fast_load_command, .mode = COMMAND_EXEC, .help = "loads active fast load image to current target " "- mainly for profiling purposes", .usage = "", }, { .name = "profile", .handler = handle_profile_command, .mode = COMMAND_EXEC, .usage = "seconds filename [start end]", .help = "profiling samples the CPU PC", }, /** @todo don't register virt2phys() unless target supports it */ { .name = "virt2phys", .handler = handle_virt2phys_command, .mode = COMMAND_ANY, .help = "translate a virtual address into a physical address", .usage = "virtual_address", }, { .name = "reg", .handler = handle_reg_command, .mode = COMMAND_EXEC, .help = "display (reread from target with \"force\") or set a register; " "with no arguments, displays all registers and their values", .usage = "[(register_number|register_name) [(value|'force')]]", }, { .name = "poll", .handler = handle_poll_command, .mode = COMMAND_EXEC, .help = "poll target state; or reconfigure background polling", .usage = "['on'|'off']", }, { .name = "wait_halt", .handler = handle_wait_halt_command, .mode = COMMAND_EXEC, .help = "wait up to the specified number of milliseconds " "(default 5000) for a previously requested halt", .usage = "[milliseconds]", }, { .name = "halt", .handler = handle_halt_command, .mode = COMMAND_EXEC, .help = "request target to halt, then wait up to the specified" "number of milliseconds (default 5000) for it to complete", .usage = "[milliseconds]", }, { .name = "resume", .handler = handle_resume_command, .mode = COMMAND_EXEC, .help = "resume target execution from current PC or address", .usage = "[address]", }, { .name = "reset", .handler = handle_reset_command, .mode = COMMAND_EXEC, .usage = "[run|halt|init]", .help = "Reset all targets into the specified mode." "Default reset mode is run, if not given.", }, { .name = "soft_reset_halt", .handler = handle_soft_reset_halt_command, .mode = COMMAND_EXEC, .usage = "", .help = "halt the target and do a soft reset", }, { .name = "step", .handler = handle_step_command, .mode = COMMAND_EXEC, .help = "step one instruction from current PC or address", .usage = "[address]", }, { .name = "mdw", .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory words", .usage = "['phys'] address [count]", }, { .name = "mdh", .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory half-words", .usage = "['phys'] address [count]", }, { .name = "mdb", .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory bytes", .usage = "['phys'] address [count]", }, { .name = "mww", .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory word", .usage = "['phys'] address value [count]", }, { .name = "mwh", .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory half-word", .usage = "['phys'] address value [count]", }, { .name = "mwb", .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory byte", .usage = "['phys'] address value [count]", }, { .name = "bp", .handler = handle_bp_command, .mode = COMMAND_EXEC, .help = "list or set hardware or software breakpoint", .usage = "
[] ['hw'|'hw_ctx']", }, { .name = "rbp", .handler = handle_rbp_command, .mode = COMMAND_EXEC, .help = "remove breakpoint", .usage = "address", }, { .name = "wp", .handler = handle_wp_command, .mode = COMMAND_EXEC, .help = "list (no params) or create watchpoints", .usage = "[address length [('r'|'w'|'a') value [mask]]]", }, { .name = "rwp", .handler = handle_rwp_command, .mode = COMMAND_EXEC, .help = "remove watchpoint", .usage = "address", }, { .name = "load_image", .handler = handle_load_image_command, .mode = COMMAND_EXEC, .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " "[min_address] [max_length]", }, { .name = "dump_image", .handler = handle_dump_image_command, .mode = COMMAND_EXEC, .usage = "filename address size", }, { .name = "verify_image", .handler = handle_verify_image_command, .mode = COMMAND_EXEC, .usage = "filename [offset [type]]", }, { .name = "test_image", .handler = handle_test_image_command, .mode = COMMAND_EXEC, .usage = "filename [offset [type]]", }, { .name = "mem2array", .mode = COMMAND_EXEC, .jim_handler = jim_mem2array, .help = "read 8/16/32 bit memory and return as a TCL array " "for script processing", .usage = "arrayname bitwidth address count", }, { .name = "array2mem", .mode = COMMAND_EXEC, .jim_handler = jim_array2mem, .help = "convert a TCL array to memory locations " "and write the 8/16/32 bit values", .usage = "arrayname bitwidth address count", }, { .name = "reset_nag", .handler = handle_target_reset_nag, .mode = COMMAND_ANY, .help = "Nag after each reset about options that could have been " "enabled to improve performance. ", .usage = "['enable'|'disable']", }, { .name = "ps", .handler = handle_ps_command, .mode = COMMAND_EXEC, .help = "list all tasks ", .usage = " ", }, { .name = "test_mem_access", .handler = handle_test_mem_access_command, .mode = COMMAND_EXEC, .help = "Test the target's memory access functions", .usage = "size", }, COMMAND_REGISTRATION_DONE }; static int target_register_user_commands(struct command_context *cmd_ctx) { int retval = ERROR_OK; retval = target_request_register_commands(cmd_ctx); if (retval != ERROR_OK) return retval; retval = trace_register_commands(cmd_ctx); if (retval != ERROR_OK) return retval; return register_commands(cmd_ctx, NULL, target_exec_command_handlers); } openocd-0.9.0/src/target/target.h0000644000175000017500000006076412526201110013607 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef TARGET_H #define TARGET_H #include struct reg; struct trace; struct command_context; struct breakpoint; struct watchpoint; struct mem_param; struct reg_param; struct target_list; struct gdb_fileio_info; /* * TARGET_UNKNOWN = 0: we don't know anything about the target yet * TARGET_RUNNING = 1: the target is executing user code * TARGET_HALTED = 2: the target is not executing code, and ready to talk to the * debugger. on an xscale it means that the debug handler is executing * TARGET_RESET = 3: the target is being held in reset (only a temporary state, * not sure how this is used with all the recent changes) * TARGET_DEBUG_RUNNING = 4: the target is running, but it is executing code on * behalf of the debugger (e.g. algorithm for flashing) * * also see: target_state_name(); */ enum target_state { TARGET_UNKNOWN = 0, TARGET_RUNNING = 1, TARGET_HALTED = 2, TARGET_RESET = 3, TARGET_DEBUG_RUNNING = 4, }; enum nvp_assert { NVP_DEASSERT, NVP_ASSERT, }; enum target_reset_mode { RESET_UNKNOWN = 0, RESET_RUN = 1, /* reset and let target run */ RESET_HALT = 2, /* reset and halt target out of reset */ RESET_INIT = 3, /* reset and halt target out of reset, then run init script */ }; enum target_debug_reason { DBG_REASON_DBGRQ = 0, DBG_REASON_BREAKPOINT = 1, DBG_REASON_WATCHPOINT = 2, DBG_REASON_WPTANDBKPT = 3, DBG_REASON_SINGLESTEP = 4, DBG_REASON_NOTHALTED = 5, DBG_REASON_EXIT = 6, DBG_REASON_UNDEFINED = 7, }; enum target_endianness { TARGET_ENDIAN_UNKNOWN = 0, TARGET_BIG_ENDIAN = 1, TARGET_LITTLE_ENDIAN = 2 }; struct working_area { uint32_t address; uint32_t size; bool free; uint8_t *backup; struct working_area **user; struct working_area *next; }; struct gdb_service { struct target *target; /* field for smp display */ /* element 0 coreid currently displayed ( 1 till n) */ /* element 1 coreid to be displayed at next resume 1 till n 0 means resume * all cores core displayed */ int32_t core[2]; }; /* target back off timer */ struct backoff_timer { int times; int count; }; /* split target registers into multiple class */ enum target_register_class { REG_CLASS_ALL, REG_CLASS_GENERAL, }; /* target_type.h contains the full definition of struct target_type */ struct target { struct target_type *type; /* target type definition (name, access functions) */ const char *cmd_name; /* tcl Name of target */ int target_number; /* DO NOT USE! field to be removed in 2010 */ struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ /** * Indicates whether this target has been examined. * * Do @b not access this field directly, use target_was_examined() * or target_set_examined(). */ bool examined; /** * true if the target is currently running a downloaded * "algorithm" instead of arbitrary user code. OpenOCD code * invoking algorithms is trusted to maintain correctness of * any cached state (e.g. for flash status), which arbitrary * code will have no reason to know about. */ bool running_alg; struct target_event_action *event_action; int reset_halt; /* attempt resetting the CPU into the halted mode? */ uint32_t working_area; /* working area (initialised RAM). Evaluated * upon first allocation from virtual/physical address. */ bool working_area_virt_spec; /* virtual address specified? */ uint32_t working_area_virt; /* virtual address */ bool working_area_phys_spec; /* virtual address specified? */ uint32_t working_area_phys; /* physical address */ uint32_t working_area_size; /* size in bytes */ uint32_t backup_working_area; /* whether the content of the working area has to be preserved */ struct working_area *working_areas;/* list of allocated working areas */ enum target_debug_reason debug_reason;/* reason why the target entered debug state */ enum target_endianness endianness; /* target endianness */ /* also see: target_state_name() */ enum target_state state; /* the current backend-state (running, halted, ...) */ struct reg_cache *reg_cache; /* the first register cache of the target (core regs) */ struct breakpoint *breakpoints; /* list of breakpoints */ struct watchpoint *watchpoints; /* list of watchpoints */ struct trace *trace_info; /* generic trace information */ struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */ uint32_t dbg_msg_enabled; /* debug message status */ void *arch_info; /* architecture specific information */ struct target *next; /* next target in list */ int display; /* display async info in telnet session. Do not display * lots of halted/resumed info when stepping in debugger. */ bool halt_issued; /* did we transition to halted state? */ long long halt_issued_time; /* Note time when halt was issued */ bool dbgbase_set; /* By default the debug base is not set */ uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no * system in place to support target specific options * currently. */ struct rtos *rtos; /* Instance of Real Time Operating System support */ bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto" * and must be detected when symbols are offered */ struct backoff_timer backoff; int smp; /* add some target attributes for smp support */ struct target_list *head; /* the gdb service is there in case of smp, we have only one gdb server * for all smp target * the target attached to the gdb is changing dynamically by changing * gdb_service->target pointer */ struct gdb_service *gdb_service; /* file-I/O information for host to do syscall */ struct gdb_fileio_info *fileio_info; }; struct target_list { struct target *target; struct target_list *next; }; struct gdb_fileio_info { char *identifier; uint32_t param_1; uint32_t param_2; uint32_t param_3; uint32_t param_4; }; /** Returns the instance-specific name of the specified target. */ static inline const char *target_name(struct target *target) { return target->cmd_name; } const char *debug_reason_name(struct target *t); enum target_event { /* allow GDB to do stuff before others handle the halted event, * this is in lieu of defining ordering of invocation of events, * which would be more complicated * * Telling GDB to halt does not mean that the target stopped running, * simply that we're dropping out of GDB's waiting for step or continue. * * This can be useful when e.g. detecting power dropout. */ TARGET_EVENT_GDB_HALT, TARGET_EVENT_HALTED, /* target entered debug state from normal execution or reset */ TARGET_EVENT_RESUMED, /* target resumed to normal execution */ TARGET_EVENT_RESUME_START, TARGET_EVENT_RESUME_END, TARGET_EVENT_GDB_START, /* debugger started execution (step/run) */ TARGET_EVENT_GDB_END, /* debugger stopped execution (step/run) */ TARGET_EVENT_RESET_START, TARGET_EVENT_RESET_ASSERT_PRE, TARGET_EVENT_RESET_ASSERT, /* C code uses this instead of SRST */ TARGET_EVENT_RESET_ASSERT_POST, TARGET_EVENT_RESET_DEASSERT_PRE, TARGET_EVENT_RESET_DEASSERT_POST, TARGET_EVENT_RESET_HALT_PRE, TARGET_EVENT_RESET_HALT_POST, TARGET_EVENT_RESET_WAIT_PRE, TARGET_EVENT_RESET_WAIT_POST, TARGET_EVENT_RESET_INIT, TARGET_EVENT_RESET_END, TARGET_EVENT_DEBUG_HALTED, /* target entered debug state, but was executing on behalf of the debugger */ TARGET_EVENT_DEBUG_RESUMED, /* target resumed to execute on behalf of the debugger */ TARGET_EVENT_EXAMINE_START, TARGET_EVENT_EXAMINE_END, TARGET_EVENT_GDB_ATTACH, TARGET_EVENT_GDB_DETACH, TARGET_EVENT_GDB_FLASH_ERASE_START, TARGET_EVENT_GDB_FLASH_ERASE_END, TARGET_EVENT_GDB_FLASH_WRITE_START, TARGET_EVENT_GDB_FLASH_WRITE_END, TARGET_EVENT_TRACE_CONFIG, }; struct target_event_action { enum target_event event; struct Jim_Interp *interp; struct Jim_Obj *body; int has_percent; struct target_event_action *next; }; bool target_has_event_action(struct target *target, enum target_event event); struct target_event_callback { int (*callback)(struct target *target, enum target_event event, void *priv); void *priv; struct target_event_callback *next; }; struct target_reset_callback { struct list_head list; void *priv; int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv); }; struct target_timer_callback { int (*callback)(void *priv); int time_ms; int periodic; bool removed; struct timeval when; void *priv; struct target_timer_callback *next; }; int target_register_commands(struct command_context *cmd_ctx); int target_examine(void); int target_register_event_callback( int (*callback)(struct target *target, enum target_event event, void *priv), void *priv); int target_unregister_event_callback( int (*callback)(struct target *target, enum target_event event, void *priv), void *priv); int target_register_reset_callback( int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv), void *priv); int target_unregister_reset_callback( int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv), void *priv); /* Poll the status of the target, detect any error conditions and report them. * * Also note that this fn will clear such error conditions, so a subsequent * invocation will then succeed. * * These error conditions can be "sticky" error conditions. E.g. writing * to memory could be implemented as an open loop and if memory writes * fails, then a note is made of it, the error is sticky, but the memory * write loop still runs to completion. This improves performance in the * normal case as there is no need to verify that every single write succeed, * yet it is possible to detect error conditions. */ int target_poll(struct target *target); int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); int target_halt(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode); /** * The period is very approximate, the callback can happen much more often * or much more rarely than specified */ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv); int target_unregister_timer_callback(int (*callback)(void *priv), void *priv); int target_call_timer_callbacks(void); /** * Invoke this to ensure that e.g. polling timer callbacks happen before * a synchronous command completes. */ int target_call_timer_callbacks_now(void); struct target *get_target_by_num(int num); struct target *get_current_target(struct command_context *cmd_ctx); struct target *get_target(const char *id); /** * Get the target type name. * * This routine is a wrapper for the target->type->name field. * Note that this is not an instance-specific name for his target. */ const char *target_type_name(struct target *target); /** * Examine the specified @a target, letting it perform any * Initialisation that requires JTAG access. * * This routine is a wrapper for target->type->examine. */ int target_examine_one(struct target *target); /** @returns @c true if target_set_examined() has been called. */ static inline bool target_was_examined(struct target *target) { return target->examined; } /** Sets the @c examined flag for the given target. */ /** Use in target->type->examine() after one-time setup is done. */ static inline void target_set_examined(struct target *target) { target->examined = true; } /** * Add the @a breakpoint for @a target. * * This routine is a wrapper for target->type->add_breakpoint. */ int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint); /** * Add the @a ContextID breakpoint for @a target. * * This routine is a wrapper for target->type->add_context_breakpoint. */ int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint); /** * Add the @a ContextID & IVA breakpoint for @a target. * * This routine is a wrapper for target->type->add_hybrid_breakpoint. */ int target_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint); /** * Remove the @a breakpoint for @a target. * * This routine is a wrapper for target->type->remove_breakpoint. */ int target_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); /** * Add the @a watchpoint for @a target. * * This routine is a wrapper for target->type->add_watchpoint. */ int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint); /** * Remove the @a watchpoint for @a target. * * This routine is a wrapper for target->type->remove_watchpoint. */ int target_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); /** * Find out the just hit @a watchpoint for @a target. * * This routine is a wrapper for target->type->hit_watchpoint. */ int target_hit_watchpoint(struct target *target, struct watchpoint **watchpoint); /** * Obtain the registers for GDB. * * This routine is a wrapper for target->type->get_gdb_reg_list. */ int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); /** * Step the target. * * This routine is a wrapper for target->type->step. */ int target_step(struct target *target, int current, uint32_t address, int handle_breakpoints); /** * Run an algorithm on the @a target given. * * This routine is a wrapper for target->type->run_algorithm. */ int target_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); /** * Starts an algorithm in the background on the @a target given. * * This routine is a wrapper for target->type->start_algorithm. */ int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, void *arch_info); /** * Wait for an algorithm on the @a target given. * * This routine is a wrapper for target->type->wait_algorithm. */ int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t exit_point, int timeout_ms, void *arch_info); /** * This routine is a wrapper for asynchronous algorithms. * */ int target_run_flash_async_algorithm(struct target *target, const uint8_t *buffer, uint32_t count, int block_size, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t buffer_start, uint32_t buffer_size, uint32_t entry_point, uint32_t exit_point, void *arch_info); /** * Read @a count items of @a size bytes from the memory of @a target at * the @a address given. * * This routine is a wrapper for target->type->read_memory. */ int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int target_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Write @a count items of @a size bytes to the memory of @a target at * the @a address given. @a address must be aligned to @a size * in target memory. * * The endianness is the same in the host and target memory for this * function. * * \todo TODO: * Really @a buffer should have been defined as "const void *" and * @a buffer should have been aligned to @a size in the host memory. * * This is not enforced via e.g. assert's today and e.g. the * target_write_buffer fn breaks this assumption. * * This routine is wrapper for target->type->write_memory. */ int target_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int target_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* * Write to target memory using the virtual address. * * Note that this fn is used to implement software breakpoints. Targets * can implement support for software breakpoints to memory marked as read * only by making this fn write to ram even if it is read only(MMU or * MPUs). * * It is sufficient to implement for writing a single word(16 or 32 in * ARM32/16 bit case) to write the breakpoint to ram. * * The target should also take care of "other things" to make sure that * software breakpoints can be written using this function. E.g. * when there is a separate instruction and data cache, this fn must * make sure that the instruction cache is synced up to the potential * code change that can happen as a result of the memory write(typically * by invalidating the cache). * * The high level wrapper fn in target.c will break down this memory write * request to multiple write requests to the target driver to e.g. guarantee * that writing 4 bytes to an aligned address happens with a single 32 bit * write operation, thus making this fn suitable to e.g. write to special * peripheral registers which do not support byte operations. */ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer); int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer); int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *crc); int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *blank); int target_wait_state(struct target *target, enum target_state state, int ms); /** * Obtain file-I/O information from target for GDB to do syscall. * * This routine is a wrapper for target->type->get_gdb_fileio_info. */ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); /** * Pass GDB file-I/O response to target after finishing host syscall. * * This routine is a wrapper for target->type->gdb_fileio_end. */ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c); /** Return the *name* of this targets current state */ const char *target_state_name(struct target *target); /** Return the *name* of a target event enumeration value */ const char *target_event_name(enum target_event event); /** Return the *name* of a target reset reason enumeration value */ const char *target_reset_mode_name(enum target_reset_mode reset_mode); /* DANGER!!!!! * * if "area" passed in to target_alloc_working_area() points to a memory * location that goes out of scope (e.g. a pointer on the stack), then * the caller of target_alloc_working_area() is responsible for invoking * target_free_working_area() before "area" goes out of scope. * * target_free_all_working_areas() will NULL out the "area" pointer * upon resuming or resetting the CPU. * */ int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area); /* Same as target_alloc_working_area, except that no error is logged * when ERROR_TARGET_RESOURCE_NOT_AVAILABLE is returned. * * This allows the calling code to *try* to allocate target memory * and have a fallback to another behaviour(slower?). */ int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area); int target_free_working_area(struct target *target, struct working_area *area); void target_free_all_working_areas(struct target *target); uint32_t target_get_working_area_avail(struct target *target); /** * Free all the resources allocated by targets and the target layer */ void target_quit(void); extern struct target *all_targets; uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer); uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer); uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer); uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer); void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value); void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value); void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value); void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value); void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf); void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf); void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf); void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf); void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf); void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf); int target_read_u64(struct target *target, uint64_t address, uint64_t *value); int target_read_u32(struct target *target, uint32_t address, uint32_t *value); int target_read_u16(struct target *target, uint32_t address, uint16_t *value); int target_read_u8(struct target *target, uint32_t address, uint8_t *value); int target_write_u64(struct target *target, uint64_t address, uint64_t value); int target_write_u32(struct target *target, uint32_t address, uint32_t value); int target_write_u16(struct target *target, uint32_t address, uint16_t value); int target_write_u8(struct target *target, uint32_t address, uint8_t value); /* Issues USER() statements with target state information */ int target_arch_state(struct target *target); void target_handle_event(struct target *t, enum target_event e); #define ERROR_TARGET_INVALID (-300) #define ERROR_TARGET_INIT_FAILED (-301) #define ERROR_TARGET_TIMEOUT (-302) #define ERROR_TARGET_NOT_HALTED (-304) #define ERROR_TARGET_FAILURE (-305) #define ERROR_TARGET_UNALIGNED_ACCESS (-306) #define ERROR_TARGET_DATA_ABORT (-307) #define ERROR_TARGET_RESOURCE_NOT_AVAILABLE (-308) #define ERROR_TARGET_TRANSLATION_FAULT (-309) #define ERROR_TARGET_NOT_RUNNING (-310) #define ERROR_TARGET_NOT_EXAMINED (-311) extern bool get_target_reset_nag(void); #endif /* TARGET_H */ openocd-0.9.0/src/target/arm_disassembler.c0000644000175000017500000032446412516456303015647 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2009 by David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "arm_disassembler.h" #include /* * This disassembler supports two main functions for OpenOCD: * * - Various "disassemble" commands. OpenOCD can serve as a * machine-language debugger, without help from GDB. * * - Single stepping. Not all ARM cores support hardware single * stepping. To work without that support, the debugger must * be able to decode instructions to find out where to put a * "next instruction" breakpoint. * * In addition, interpretation of ETM trace data needs some of the * decoding mechanisms. * * At this writing (September 2009) neither function is complete. * * - ARM decoding * * Old-style syntax (not UAL) is generally used * * VFP instructions are not understood (ARMv5 and later) * except as coprocessor 10/11 operations * * Most ARM instructions through ARMv6 are decoded, but some * of the post-ARMv4 opcodes may not be handled yet * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ... * * NEON instructions are not understood (ARMv7-A) * * - Thumb/Thumb2 decoding * * UAL syntax should be consistently used * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should * be handled properly. Accordingly, so should the subset * used in Cortex-M0/M1; and "original" 16-bit Thumb from * ARMv4T and ARMv5T. * * Conditional effects of Thumb2 "IT" (if-then) instructions * are not handled: the affected instructions are not shown * with their now-conditional suffixes. * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be * handled (minimally for coprocessor access). * * SIMD instructions, and some other Thumb2 instructions * from ARMv7-A, are not understood. * * - ThumbEE decoding * * As a Thumb2 variant, the Thumb2 comments (above) apply. * * Opcodes changed by ThumbEE mode are not handled; these * instructions wrongly decode as LDM and STM. * * - Jazelle decoding ... no support whatsoever for Jazelle mode * or decoding. ARM encourages use of the more generic ThumbEE * mode, instead of Jazelle mode, in current chips. * * - Single-step/emulation ... spotty support, which is only weakly * tested. Thumb2 is not supported. (Arguably a full simulator * is not needed to support just single stepping. Recognizing * branch vs non-branch instructions suffices, except when the * instruction faults and triggers a synchronous exception which * can be intercepted using other means.) * * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and * ARM v7-R edition" gives the most complete coverage of the various * generations of ARM instructions. At this writing it is publicly * accessible to anyone willing to create an account at the ARM * web site; see http://www.arm.com/documentation/ for information. * * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides * more details relevant to the Thumb2-only processors (such as * the Cortex-M implementations). */ /* textual represenation of the condition field * ALways (default) is ommitted (empty string) */ static const char *arm_condition_strings[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV" }; /* make up for C's missing ROR */ static uint32_t ror(uint32_t value, int places) { return (value >> places) | (value << (32 - places)); } static int evaluate_unknown(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } static int evaluate_pld(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* PLD */ if ((opcode & 0x0d70f000) == 0x0550f000) { instruction->type = ARM_PLD; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode); return ERROR_OK; } return evaluate_unknown(opcode, address, instruction); } static int evaluate_srs(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { const char *wback = (opcode & (1 << 21)) ? "!" : ""; const char *mode = ""; switch ((opcode >> 23) & 0x3) { case 0: mode = "DA"; break; case 1: /* "IA" is default */ break; case 2: mode = "DB"; break; case 3: mode = "IB"; break; } switch (opcode & 0x0e500000) { case 0x08400000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRS%s\tSP%s, #%d", address, opcode, mode, wback, (unsigned)(opcode & 0x1f)); break; case 0x08100000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tRFE%s\tr%d%s", address, opcode, mode, (unsigned)((opcode >> 16) & 0xf), wback); break; default: return evaluate_unknown(opcode, address, instruction); } return ERROR_OK; } static int evaluate_swi(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { instruction->type = ARM_SWI; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32, address, opcode, (opcode & 0xffffff)); return ERROR_OK; } static int evaluate_blx_imm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { int offset; uint32_t immediate; uint32_t target_address; instruction->type = ARM_BLX; immediate = opcode & 0x00ffffff; /* sign extend 24-bit immediate */ if (immediate & 0x00800000) offset = 0xff000000 | immediate; else offset = immediate; /* shift two bits left */ offset <<= 2; /* odd/event halfword */ if (opcode & 0x01000000) offset |= 0x2; target_address = address + 8 + offset; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address); instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = target_address; return ERROR_OK; } static int evaluate_b_bl(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t L; uint32_t immediate; int offset; uint32_t target_address; immediate = opcode & 0x00ffffff; L = (opcode & 0x01000000) >> 24; /* sign extend 24-bit immediate */ if (immediate & 0x00800000) offset = 0xff000000 | immediate; else offset = immediate; /* shift two bits left */ offset <<= 2; target_address = address + 8 + offset; if (L) instruction->type = ARM_BL; else instruction->type = ARM_B; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32, address, opcode, (L) ? "L" : "", COND(opcode), target_address); instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = target_address; return ERROR_OK; } /* Coprocessor load/store and double register transfers * both normal and extended instruction space (condition field b1111) */ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t cp_num = (opcode & 0xf00) >> 8; /* MCRR or MRRC */ if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000)) { uint8_t cp_opcode, Rd, Rn, CRm; char *mnemonic; cp_opcode = (opcode & 0xf0) >> 4; Rd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; CRm = (opcode & 0xf); /* MCRR */ if ((opcode & 0x0ff00000) == 0x0c400000) { instruction->type = ARM_MCRR; mnemonic = "MCRR"; } else if ((opcode & 0x0ff00000) == 0x0c500000) { /* MRRC */ instruction->type = ARM_MRRC; mnemonic = "MRRC"; } else { LOG_ERROR("Unknown instruction"); return ERROR_FAIL; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, %x, r%i, r%i, c%i", address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode), COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm); } else {/* LDC or STC */ uint8_t CRd, Rn, offset; uint8_t U; char *mnemonic; char addressing_mode[32]; CRd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; offset = (opcode & 0xff) << 2; /* load/store */ if (opcode & 0x00100000) { instruction->type = ARM_LDC; mnemonic = "LDC"; } else { instruction->type = ARM_STC; mnemonic = "STC"; } U = (opcode & 0x00800000) >> 23; /* addressing modes */ if ((opcode & 0x01200000) == 0x01000000)/* offset */ snprintf(addressing_mode, 32, "[r%i, #%s%d]", Rn, U ? "" : "-", offset); else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */ snprintf(addressing_mode, 32, "[r%i, #%s%d]!", Rn, U ? "" : "-", offset); else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */ snprintf(addressing_mode, 32, "[r%i], #%s%d", Rn, U ? "" : "-", offset); else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */ snprintf(addressing_mode, 32, "[r%i], {%d}", Rn, offset >> 2); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s", address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode), (opcode & (1 << 22)) ? "L" : "", cp_num, CRd, addressing_mode); } return ERROR_OK; } /* Coprocessor data processing instructions * Coprocessor register transfer instructions * both normal and extended instruction space (condition field b1111) */ static int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { const char *cond; char *mnemonic; uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2; cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode); cp_num = (opcode & 0xf00) >> 8; CRd_Rd = (opcode & 0xf000) >> 12; CRn = (opcode & 0xf0000) >> 16; CRm = (opcode & 0xf); opcode_2 = (opcode & 0xe0) >> 5; /* CDP or MRC/MCR */ if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */ if (opcode & 0x00100000) { /* bit 20 set -> MRC */ instruction->type = ARM_MRC; mnemonic = "MRC"; } else {/* bit 20 not set -> MCR */ instruction->type = ARM_MCR; mnemonic = "MCR"; } opcode_1 = (opcode & 0x00e00000) >> 21; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x", address, opcode, mnemonic, cond, cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2); } else {/* bit 4 not set -> CDP */ instruction->type = ARM_CDP; mnemonic = "CDP"; opcode_1 = (opcode & 0x00f00000) >> 20; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x", address, opcode, mnemonic, cond, cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2); } return ERROR_OK; } /* Load/store instructions */ static int evaluate_load_store(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t I, P, U, B, W, L; uint8_t Rn, Rd; char *operation;/* "LDR" or "STR" */ char *suffix; /* "", "B", "T", "BT" */ char offset[32]; /* examine flags */ I = (opcode & 0x02000000) >> 25; P = (opcode & 0x01000000) >> 24; U = (opcode & 0x00800000) >> 23; B = (opcode & 0x00400000) >> 22; W = (opcode & 0x00200000) >> 21; L = (opcode & 0x00100000) >> 20; /* target register */ Rd = (opcode & 0xf000) >> 12; /* base register */ Rn = (opcode & 0xf0000) >> 16; instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = Rn; instruction->info.load_store.U = U; /* determine operation */ if (L) operation = "LDR"; else operation = "STR"; /* determine instruction type and suffix */ if (B) { if ((P == 0) && (W == 1)) { if (L) instruction->type = ARM_LDRBT; else instruction->type = ARM_STRBT; suffix = "BT"; } else { if (L) instruction->type = ARM_LDRB; else instruction->type = ARM_STRB; suffix = "B"; } } else { if ((P == 0) && (W == 1)) { if (L) instruction->type = ARM_LDRT; else instruction->type = ARM_STRT; suffix = "T"; } else { if (L) instruction->type = ARM_LDR; else instruction->type = ARM_STR; suffix = ""; } } if (!I) { /* #+- */ uint32_t offset_12 = (opcode & 0xfff); if (offset_12) snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12); else snprintf(offset, 32, "%s", ""); instruction->info.load_store.offset_mode = 0; instruction->info.load_store.offset.offset = offset_12; } else {/* either +- or +-, , # */ uint8_t shift_imm, shift; uint8_t Rm; shift_imm = (opcode & 0xf80) >> 7; shift = (opcode & 0x60) >> 5; Rm = (opcode & 0xf); /* LSR encodes a shift by 32 bit as 0x0 */ if ((shift == 0x1) && (shift_imm == 0x0)) shift_imm = 0x20; /* ASR encodes a shift by 32 bit as 0x0 */ if ((shift == 0x2) && (shift_imm == 0x0)) shift_imm = 0x20; /* ROR by 32 bit is actually a RRX */ if ((shift == 0x3) && (shift_imm == 0x0)) shift = 0x4; instruction->info.load_store.offset_mode = 1; instruction->info.load_store.offset.reg.Rm = Rm; instruction->info.load_store.offset.reg.shift = shift; instruction->info.load_store.offset.reg.shift_imm = shift_imm; if ((shift_imm == 0x0) && (shift == 0x0)) /* +- */ snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm); else { /* +-, , # */ switch (shift) { case 0x0: /* LSL */ snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm); break; case 0x1: /* LSR */ snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm); break; case 0x2: /* ASR */ snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm); break; case 0x3: /* ROR */ snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm); break; case 0x4: /* RRX */ snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm); break; } } } if (P == 1) { if (W == 0) { /* offset */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 0; } else {/* pre-indexed */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 1; } } else {/* post-indexed */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 2; } return ERROR_OK; } static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp) { unsigned rm = (opcode >> 0) & 0xf; unsigned rd = (opcode >> 12) & 0xf; unsigned rn = (opcode >> 16) & 0xf; char *type, *rot; switch ((opcode >> 24) & 0x3) { case 0: type = "B16"; break; case 1: sprintf(cp, "UNDEFINED"); return ARM_UNDEFINED_INSTRUCTION; case 2: type = "B"; break; default: type = "H"; break; } switch ((opcode >> 10) & 0x3) { case 0: rot = ""; break; case 1: rot = ", ROR #8"; break; case 2: rot = ", ROR #16"; break; default: rot = ", ROR #24"; break; } if (rn == 0xf) { sprintf(cp, "%cXT%s%s\tr%d, r%d%s", (opcode & (1 << 22)) ? 'U' : 'S', type, COND(opcode), rd, rm, rot); return ARM_MOV; } else { sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s", (opcode & (1 << 22)) ? 'U' : 'S', type, COND(opcode), rd, rn, rm, rot); return ARM_ADD; } } static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp) { char *prefix; char *op; int type; switch ((opcode >> 20) & 0x7) { case 1: prefix = "S"; break; case 2: prefix = "Q"; break; case 3: prefix = "SH"; break; case 5: prefix = "U"; break; case 6: prefix = "UQ"; break; case 7: prefix = "UH"; break; default: goto undef; } switch ((opcode >> 5) & 0x7) { case 0: op = "ADD16"; type = ARM_ADD; break; case 1: op = "ADDSUBX"; type = ARM_ADD; break; case 2: op = "SUBADDX"; type = ARM_SUB; break; case 3: op = "SUB16"; type = ARM_SUB; break; case 4: op = "ADD8"; type = ARM_ADD; break; case 7: op = "SUB8"; type = ARM_SUB; break; default: goto undef; } sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); return type; undef: /* these opcodes might be used someday */ sprintf(cp, "UNDEFINED"); return ARM_UNDEFINED_INSTRUCTION; } /* ARMv6 and later support "media" instructions (includes SIMD) */ static int evaluate_media(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { char *cp = instruction->text; char *mnemonic = NULL; sprintf(cp, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t", address, opcode); cp = strchr(cp, 0); /* parallel add/subtract */ if ((opcode & 0x01800000) == 0x00000000) { instruction->type = evaluate_p_add_sub(opcode, address, cp); return ERROR_OK; } /* halfword pack */ if ((opcode & 0x01f00020) == 0x00800000) { char *type, *shift; unsigned imm = (unsigned) (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { type = "TB"; shift = "ASR"; if (imm == 0) imm = 32; } else { type = "BT"; shift = "LSL"; } sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d", type, COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, shift, imm); return ERROR_OK; } /* word saturate */ if ((opcode & 0x01a00020) == 0x00a00000) { char *shift; unsigned imm = (unsigned) (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { shift = "ASR"; if (imm == 0) imm = 32; } else shift = "LSL"; sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d", (opcode & (1 << 22)) ? 'U' : 'S', COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0x1f, (int) (opcode >> 0) & 0xf, shift, imm); return ERROR_OK; } /* sign extension */ if ((opcode & 0x018000f0) == 0x00800070) { instruction->type = evaluate_extend(opcode, address, cp); return ERROR_OK; } /* multiplies */ if ((opcode & 0x01f00080) == 0x01000000) { unsigned rn = (opcode >> 12) & 0xf; if (rn != 0xf) sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d", (opcode & (1 << 6)) ? 'S' : 'A', (opcode & (1 << 5)) ? "X" : "", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf, rn); else sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d", (opcode & (1 << 6)) ? 'S' : 'A', (opcode & (1 << 5)) ? "X" : "", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf); return ERROR_OK; } if ((opcode & 0x01f00000) == 0x01400000) { sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d", (opcode & (1 << 6)) ? 'S' : 'A', (opcode & (1 << 5)) ? "X" : "", COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf); return ERROR_OK; } if ((opcode & 0x01f00000) == 0x01500000) { unsigned rn = (opcode >> 12) & 0xf; switch (opcode & 0xc0) { case 3: if (rn == 0xf) goto undef; /* FALL THROUGH */ case 0: break; default: goto undef; } if (rn != 0xf) sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d", (opcode & (1 << 6)) ? 'S' : 'A', (opcode & (1 << 5)) ? "R" : "", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf, rn); else sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d", (opcode & (1 << 5)) ? "R" : "", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf); return ERROR_OK; } /* simple matches against the remaining decode bits */ switch (opcode & 0x01f000f0) { case 0x00a00030: case 0x00e00030: /* parallel halfword saturate */ sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d", (opcode & (1 << 22)) ? 'U' : 'S', COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); return ERROR_OK; case 0x00b00030: mnemonic = "REV"; break; case 0x00b000b0: mnemonic = "REV16"; break; case 0x00f000b0: mnemonic = "REVSH"; break; case 0x008000b0: /* select bytes */ sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode), (int) (opcode >> 12) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); return ERROR_OK; case 0x01800010: /* unsigned sum of absolute differences */ if (((opcode >> 12) & 0xf) == 0xf) sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf); else sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode), (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, (int) (opcode >> 8) & 0xf, (int) (opcode >> 12) & 0xf); return ERROR_OK; } if (mnemonic) { unsigned rm = (opcode >> 0) & 0xf; unsigned rd = (opcode >> 12) & 0xf; sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd); return ERROR_OK; } undef: /* these opcodes might be used someday */ sprintf(cp, "UNDEFINED"); return ERROR_OK; } /* Miscellaneous load/store instructions */ static int evaluate_misc_load_store(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t P, U, I, W, L, S, H; uint8_t Rn, Rd; char *operation;/* "LDR" or "STR" */ char *suffix; /* "H", "SB", "SH", "D" */ char offset[32]; /* examine flags */ P = (opcode & 0x01000000) >> 24; U = (opcode & 0x00800000) >> 23; I = (opcode & 0x00400000) >> 22; W = (opcode & 0x00200000) >> 21; L = (opcode & 0x00100000) >> 20; S = (opcode & 0x00000040) >> 6; H = (opcode & 0x00000020) >> 5; /* target register */ Rd = (opcode & 0xf000) >> 12; /* base register */ Rn = (opcode & 0xf0000) >> 16; instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = Rn; instruction->info.load_store.U = U; /* determine instruction type and suffix */ if (S) {/* signed */ if (L) {/* load */ if (H) { operation = "LDR"; instruction->type = ARM_LDRSH; suffix = "SH"; } else { operation = "LDR"; instruction->type = ARM_LDRSB; suffix = "SB"; } } else {/* there are no signed stores, so this is used to encode double-register *load/stores */ suffix = "D"; if (H) { operation = "STR"; instruction->type = ARM_STRD; } else { operation = "LDR"; instruction->type = ARM_LDRD; } } } else {/* unsigned */ suffix = "H"; if (L) {/* load */ operation = "LDR"; instruction->type = ARM_LDRH; } else {/* store */ operation = "STR"; instruction->type = ARM_STRH; } } if (I) {/* Immediate offset/index (#+-)*/ uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf); snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8); instruction->info.load_store.offset_mode = 0; instruction->info.load_store.offset.offset = offset_8; } else {/* Register offset/index (+-) */ uint8_t Rm; Rm = (opcode & 0xf); snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm); instruction->info.load_store.offset_mode = 1; instruction->info.load_store.offset.reg.Rm = Rm; instruction->info.load_store.offset.reg.shift = 0x0; instruction->info.load_store.offset.reg.shift_imm = 0x0; } if (P == 1) { if (W == 0) { /* offset */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 0; } else {/* pre-indexed */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 1; } } else {/* post-indexed */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s", address, opcode, operation, COND(opcode), suffix, Rd, Rn, offset); instruction->info.load_store.index_mode = 2; } return ERROR_OK; } /* Load/store multiples instructions */ static int evaluate_ldm_stm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t P, U, S, W, L, Rn; uint32_t register_list; char *addressing_mode; char *mnemonic; char reg_list[69]; char *reg_list_p; int i; int first_reg = 1; P = (opcode & 0x01000000) >> 24; U = (opcode & 0x00800000) >> 23; S = (opcode & 0x00400000) >> 22; W = (opcode & 0x00200000) >> 21; L = (opcode & 0x00100000) >> 20; register_list = (opcode & 0xffff); Rn = (opcode & 0xf0000) >> 16; instruction->info.load_store_multiple.Rn = Rn; instruction->info.load_store_multiple.register_list = register_list; instruction->info.load_store_multiple.S = S; instruction->info.load_store_multiple.W = W; if (L) { instruction->type = ARM_LDM; mnemonic = "LDM"; } else { instruction->type = ARM_STM; mnemonic = "STM"; } if (P) { if (U) { instruction->info.load_store_multiple.addressing_mode = 1; addressing_mode = "IB"; } else { instruction->info.load_store_multiple.addressing_mode = 3; addressing_mode = "DB"; } } else { if (U) { instruction->info.load_store_multiple.addressing_mode = 0; /* "IA" is the default in UAL syntax */ addressing_mode = ""; } else { instruction->info.load_store_multiple.addressing_mode = 2; addressing_mode = "DA"; } } reg_list_p = reg_list; for (i = 0; i <= 15; i++) { if ((register_list >> i) & 1) { if (first_reg) { first_reg = 0; reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i); } else reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i); } } snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s", address, opcode, mnemonic, addressing_mode, COND(opcode), Rn, (W) ? "!" : "", reg_list, (S) ? "^" : ""); return ERROR_OK; } /* Multiplies, extra load/stores */ static int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* Multiply (accumulate) (long) and Swap/swap byte */ if ((opcode & 0x000000f0) == 0x00000090) { /* Multiply (accumulate) */ if ((opcode & 0x0f800000) == 0x00000000) { uint8_t Rm, Rs, Rn, Rd, S; Rm = opcode & 0xf; Rs = (opcode & 0xf00) >> 8; Rn = (opcode & 0xf000) >> 12; Rd = (opcode & 0xf0000) >> 16; S = (opcode & 0x00100000) >> 20; /* examine A bit (accumulate) */ if (opcode & 0x00200000) { instruction->type = ARM_MLA; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i", address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn); } else { instruction->type = ARM_MUL; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i", address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs); } return ERROR_OK; } /* Multiply (accumulate) long */ if ((opcode & 0x0f800000) == 0x00800000) { char *mnemonic = NULL; uint8_t Rm, Rs, RdHi, RdLow, S; Rm = opcode & 0xf; Rs = (opcode & 0xf00) >> 8; RdHi = (opcode & 0xf000) >> 12; RdLow = (opcode & 0xf0000) >> 16; S = (opcode & 0x00100000) >> 20; switch ((opcode & 0x00600000) >> 21) { case 0x0: instruction->type = ARM_UMULL; mnemonic = "UMULL"; break; case 0x1: instruction->type = ARM_UMLAL; mnemonic = "UMLAL"; break; case 0x2: instruction->type = ARM_SMULL; mnemonic = "SMULL"; break; case 0x3: instruction->type = ARM_SMLAL; mnemonic = "SMLAL"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i", address, opcode, mnemonic, COND(opcode), (S) ? "S" : "", RdLow, RdHi, Rm, Rs); return ERROR_OK; } /* Swap/swap byte */ if ((opcode & 0x0f800000) == 0x01000000) { uint8_t Rm, Rd, Rn; Rm = opcode & 0xf; Rd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; /* examine B flag */ instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]", address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn); return ERROR_OK; } } return evaluate_misc_load_store(opcode, address, instruction); } static int evaluate_mrs_msr(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { int R = (opcode & 0x00400000) >> 22; char *PSR = (R) ? "SPSR" : "CPSR"; /* Move register to status register (MSR) */ if (opcode & 0x00200000) { instruction->type = ARM_MSR; /* immediate variant */ if (opcode & 0x02000000) { uint8_t immediate = (opcode & 0xff); uint8_t rotate = (opcode & 0xf00); snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32, address, opcode, COND(opcode), PSR, (opcode & 0x10000) ? "c" : "", (opcode & 0x20000) ? "x" : "", (opcode & 0x40000) ? "s" : "", (opcode & 0x80000) ? "f" : "", ror(immediate, (rotate * 2)) ); } else {/* register variant */ uint8_t Rm = opcode & 0xf; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i", address, opcode, COND(opcode), PSR, (opcode & 0x10000) ? "c" : "", (opcode & 0x20000) ? "x" : "", (opcode & 0x40000) ? "s" : "", (opcode & 0x80000) ? "f" : "", Rm ); } } else {/* Move status register to register (MRS) */ uint8_t Rd; instruction->type = ARM_MRS; Rd = (opcode & 0x0000f000) >> 12; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s", address, opcode, COND(opcode), Rd, PSR); } return ERROR_OK; } /* Miscellaneous instructions */ static int evaluate_misc_instr(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* MRS/MSR */ if ((opcode & 0x000000f0) == 0x00000000) evaluate_mrs_msr(opcode, address, instruction); /* BX */ if ((opcode & 0x006000f0) == 0x00200010) { uint8_t Rm; instruction->type = ARM_BX; Rm = opcode & 0xf; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i", address, opcode, COND(opcode), Rm); instruction->info.b_bl_bx_blx.reg_operand = Rm; instruction->info.b_bl_bx_blx.target_address = -1; } /* BXJ - "Jazelle" support (ARMv5-J) */ if ((opcode & 0x006000f0) == 0x00200020) { uint8_t Rm; instruction->type = ARM_BX; Rm = opcode & 0xf; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i", address, opcode, COND(opcode), Rm); instruction->info.b_bl_bx_blx.reg_operand = Rm; instruction->info.b_bl_bx_blx.target_address = -1; } /* CLZ */ if ((opcode & 0x006000f0) == 0x00600010) { uint8_t Rm, Rd; instruction->type = ARM_CLZ; Rm = opcode & 0xf; Rd = (opcode & 0xf000) >> 12; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i", address, opcode, COND(opcode), Rd, Rm); } /* BLX(2) */ if ((opcode & 0x006000f0) == 0x00200030) { uint8_t Rm; instruction->type = ARM_BLX; Rm = opcode & 0xf; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i", address, opcode, COND(opcode), Rm); instruction->info.b_bl_bx_blx.reg_operand = Rm; instruction->info.b_bl_bx_blx.target_address = -1; } /* Enhanced DSP add/subtracts */ if ((opcode & 0x0000000f0) == 0x00000050) { uint8_t Rm, Rd, Rn; char *mnemonic = NULL; Rm = opcode & 0xf; Rd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; switch ((opcode & 0x00600000) >> 21) { case 0x0: instruction->type = ARM_QADD; mnemonic = "QADD"; break; case 0x1: instruction->type = ARM_QSUB; mnemonic = "QSUB"; break; case 0x2: instruction->type = ARM_QDADD; mnemonic = "QDADD"; break; case 0x3: instruction->type = ARM_QDSUB; mnemonic = "QDSUB"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i", address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn); } /* exception return */ if ((opcode & 0x0000000f0) == 0x00000060) { if (((opcode & 0x600000) >> 21) == 3) instruction->type = ARM_ERET; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET", address, opcode); } /* exception generate instructions */ if ((opcode & 0x0000000f0) == 0x00000070) { uint32_t immediate = 0; char *mnemonic = NULL; switch ((opcode & 0x600000) >> 21) { case 0x1: instruction->type = ARM_BKPT; mnemonic = "BRKT"; immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf); break; case 0x2: instruction->type = ARM_HVC; mnemonic = "HVC"; immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf); break; case 0x3: instruction->type = ARM_SMC; mnemonic = "SMC"; immediate = (opcode & 0xf); break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "", address, opcode, mnemonic, immediate); } /* Enhanced DSP multiplies */ if ((opcode & 0x000000090) == 0x00000080) { int x = (opcode & 0x20) >> 5; int y = (opcode & 0x40) >> 6; /* SMLA < x> */ if ((opcode & 0x00600000) == 0x00000000) { uint8_t Rd, Rm, Rs, Rn; instruction->type = ARM_SMLAxy; Rd = (opcode & 0xf0000) >> 16; Rm = (opcode & 0xf); Rs = (opcode & 0xf00) >> 8; Rn = (opcode & 0xf000) >> 12; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i", address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode), Rd, Rm, Rs, Rn); } /* SMLAL < x> */ if ((opcode & 0x00600000) == 0x00400000) { uint8_t RdLow, RdHi, Rm, Rs; instruction->type = ARM_SMLAxy; RdHi = (opcode & 0xf0000) >> 16; RdLow = (opcode & 0xf000) >> 12; Rm = (opcode & 0xf); Rs = (opcode & 0xf00) >> 8; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i", address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode), RdLow, RdHi, Rm, Rs); } /* SMLAW < y> */ if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) { uint8_t Rd, Rm, Rs, Rn; instruction->type = ARM_SMLAWy; Rd = (opcode & 0xf0000) >> 16; Rm = (opcode & 0xf); Rs = (opcode & 0xf00) >> 8; Rn = (opcode & 0xf000) >> 12; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i", address, opcode, (y) ? "T" : "B", COND(opcode), Rd, Rm, Rs, Rn); } /* SMUL < x> */ if ((opcode & 0x00600000) == 0x00300000) { uint8_t Rd, Rm, Rs; instruction->type = ARM_SMULxy; Rd = (opcode & 0xf0000) >> 16; Rm = (opcode & 0xf); Rs = (opcode & 0xf00) >> 8; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i", address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode), Rd, Rm, Rs); } /* SMULW < y> */ if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) { uint8_t Rd, Rm, Rs; instruction->type = ARM_SMULWy; Rd = (opcode & 0xf0000) >> 16; Rm = (opcode & 0xf); Rs = (opcode & 0xf00) >> 8; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i", address, opcode, (y) ? "T" : "B", COND(opcode), Rd, Rm, Rs); } } return ERROR_OK; } static int evaluate_data_proc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t I, op, S, Rn, Rd; char *mnemonic = NULL; char shifter_operand[32]; I = (opcode & 0x02000000) >> 25; op = (opcode & 0x01e00000) >> 21; S = (opcode & 0x00100000) >> 20; Rd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = Rn; instruction->info.data_proc.S = S; switch (op) { case 0x0: instruction->type = ARM_AND; mnemonic = "AND"; break; case 0x1: instruction->type = ARM_EOR; mnemonic = "EOR"; break; case 0x2: instruction->type = ARM_SUB; mnemonic = "SUB"; break; case 0x3: instruction->type = ARM_RSB; mnemonic = "RSB"; break; case 0x4: instruction->type = ARM_ADD; mnemonic = "ADD"; break; case 0x5: instruction->type = ARM_ADC; mnemonic = "ADC"; break; case 0x6: instruction->type = ARM_SBC; mnemonic = "SBC"; break; case 0x7: instruction->type = ARM_RSC; mnemonic = "RSC"; break; case 0x8: instruction->type = ARM_TST; mnemonic = "TST"; break; case 0x9: instruction->type = ARM_TEQ; mnemonic = "TEQ"; break; case 0xa: instruction->type = ARM_CMP; mnemonic = "CMP"; break; case 0xb: instruction->type = ARM_CMN; mnemonic = "CMN"; break; case 0xc: instruction->type = ARM_ORR; mnemonic = "ORR"; break; case 0xd: instruction->type = ARM_MOV; mnemonic = "MOV"; break; case 0xe: instruction->type = ARM_BIC; mnemonic = "BIC"; break; case 0xf: instruction->type = ARM_MVN; mnemonic = "MVN"; break; } if (I) {/* immediate shifter operand (#)*/ uint8_t immed_8 = opcode & 0xff; uint8_t rotate_imm = (opcode & 0xf00) >> 8; uint32_t immediate; immediate = ror(immed_8, rotate_imm * 2); snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate); instruction->info.data_proc.variant = 0; instruction->info.data_proc.shifter_operand.immediate.immediate = immediate; } else {/* register-based shifter operand */ uint8_t shift, Rm; shift = (opcode & 0x60) >> 5; Rm = (opcode & 0xf); if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("" or ", *#") */ uint8_t shift_imm; shift_imm = (opcode & 0xf80) >> 7; instruction->info.data_proc.variant = 1; instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm; instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm; instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift; /* LSR encodes a shift by 32 bit as 0x0 */ if ((shift == 0x1) && (shift_imm == 0x0)) shift_imm = 0x20; /* ASR encodes a shift by 32 bit as 0x0 */ if ((shift == 0x2) && (shift_imm == 0x0)) shift_imm = 0x20; /* ROR by 32 bit is actually a RRX */ if ((shift == 0x3) && (shift_imm == 0x0)) shift = 0x4; if ((shift_imm == 0x0) && (shift == 0x0)) snprintf(shifter_operand, 32, "r%i", Rm); else { if (shift == 0x0) /* LSL */ snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm); else if (shift == 0x1) /* LSR */ snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm); else if (shift == 0x2) /* ASR */ snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm); else if (shift == 0x3) /* ROR */ snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm); else if (shift == 0x4) /* RRX */ snprintf(shifter_operand, 32, "r%i, RRX", Rm); } } else {/* Register shifts (", ") */ uint8_t Rs = (opcode & 0xf00) >> 8; instruction->info.data_proc.variant = 2; instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm; instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs; instruction->info.data_proc.shifter_operand.register_shift.shift = shift; if (shift == 0x0) /* LSL */ snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs); else if (shift == 0x1) /* LSR */ snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs); else if (shift == 0x2) /* ASR */ snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs); else if (shift == 0x3) /* ROR */ snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs); } } if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* {}{S} , , * */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s", address, opcode, mnemonic, COND(opcode), (S) ? "S" : "", Rd, Rn, shifter_operand); } else if ((op == 0xd) || (op == 0xf)) { /* {}{S} , * */ if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP", address, opcode); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s", address, opcode, mnemonic, COND(opcode), (S) ? "S" : "", Rd, shifter_operand); } else {/* {} , */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s", address, opcode, mnemonic, COND(opcode), Rn, shifter_operand); } return ERROR_OK; } int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* clear fields, to avoid confusion */ memset(instruction, 0, sizeof(struct arm_instruction)); instruction->opcode = opcode; instruction->instruction_size = 4; /* catch opcodes with condition field [31:28] = b1111 */ if ((opcode & 0xf0000000) == 0xf0000000) { /* Undefined instruction (or ARMv5E cache preload PLD) */ if ((opcode & 0x08000000) == 0x00000000) return evaluate_pld(opcode, address, instruction); /* Undefined instruction (or ARMv6+ SRS/RFE) */ if ((opcode & 0x0e000000) == 0x08000000) return evaluate_srs(opcode, address, instruction); /* Branch and branch with link and change to Thumb */ if ((opcode & 0x0e000000) == 0x0a000000) return evaluate_blx_imm(opcode, address, instruction); /* Extended coprocessor opcode space (ARMv5 and higher) * Coprocessor load/store and double register transfers */ if ((opcode & 0x0e000000) == 0x0c000000) return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction); /* Coprocessor data processing */ if ((opcode & 0x0f000100) == 0x0c000000) return evaluate_cdp_mcr_mrc(opcode, address, instruction); /* Coprocessor register transfers */ if ((opcode & 0x0f000010) == 0x0c000010) return evaluate_cdp_mcr_mrc(opcode, address, instruction); /* Undefined instruction */ if ((opcode & 0x0f000000) == 0x0f000000) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } } /* catch opcodes with [27:25] = b000 */ if ((opcode & 0x0e000000) == 0x00000000) { /* Multiplies, extra load/stores */ if ((opcode & 0x00000090) == 0x00000090) return evaluate_mul_and_extra_ld_st(opcode, address, instruction); /* Miscellaneous instructions */ if ((opcode & 0x0f900000) == 0x01000000) return evaluate_misc_instr(opcode, address, instruction); return evaluate_data_proc(opcode, address, instruction); } /* catch opcodes with [27:25] = b001 */ if ((opcode & 0x0e000000) == 0x02000000) { /* Undefined instruction */ if ((opcode & 0x0fb00000) == 0x03000000) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } /* Move immediate to status register */ if ((opcode & 0x0fb00000) == 0x03200000) return evaluate_mrs_msr(opcode, address, instruction); return evaluate_data_proc(opcode, address, instruction); } /* catch opcodes with [27:25] = b010 */ if ((opcode & 0x0e000000) == 0x04000000) { /* Load/store immediate offset */ return evaluate_load_store(opcode, address, instruction); } /* catch opcodes with [27:25] = b011 */ if ((opcode & 0x0e000000) == 0x06000000) { /* Load/store register offset */ if ((opcode & 0x00000010) == 0x00000000) return evaluate_load_store(opcode, address, instruction); /* Architecturally Undefined instruction * ... don't expect these to ever be used */ if ((opcode & 0x07f000f0) == 0x07f000f0) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF", address, opcode); return ERROR_OK; } /* "media" instructions */ return evaluate_media(opcode, address, instruction); } /* catch opcodes with [27:25] = b100 */ if ((opcode & 0x0e000000) == 0x08000000) { /* Load/store multiple */ return evaluate_ldm_stm(opcode, address, instruction); } /* catch opcodes with [27:25] = b101 */ if ((opcode & 0x0e000000) == 0x0a000000) { /* Branch and branch with link */ return evaluate_b_bl(opcode, address, instruction); } /* catch opcodes with [27:25] = b110 */ if ((opcode & 0x0e000000) == 0x0c000000) { /* Coprocessor load/store and double register transfers */ return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction); } /* catch opcodes with [27:25] = b111 */ if ((opcode & 0x0e000000) == 0x0e000000) { /* Software interrupt */ if ((opcode & 0x0f000000) == 0x0f000000) return evaluate_swi(opcode, address, instruction); /* Coprocessor data processing */ if ((opcode & 0x0f000010) == 0x0e000000) return evaluate_cdp_mcr_mrc(opcode, address, instruction); /* Coprocessor register transfers */ if ((opcode & 0x0f000010) == 0x0e000010) return evaluate_cdp_mcr_mrc(opcode, address, instruction); } LOG_ERROR("ARM: should never reach this point (opcode=%08x)", (unsigned) opcode); return -1; } static int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t offset = opcode & 0x7ff; uint32_t opc = (opcode >> 11) & 0x3; uint32_t target_address; char *mnemonic = NULL; /* sign extend 11-bit offset */ if (((opc == 0) || (opc == 2)) && (offset & 0x00000400)) offset = 0xfffff800 | offset; target_address = address + 4 + (offset << 1); switch (opc) { /* unconditional branch */ case 0: instruction->type = ARM_B; mnemonic = "B"; break; /* BLX suffix */ case 1: instruction->type = ARM_BLX; mnemonic = "BLX"; target_address &= 0xfffffffc; break; /* BL/BLX prefix */ case 2: instruction->type = ARM_UNKNOWN_INSTUCTION; mnemonic = "prefix"; target_address = offset << 12; break; /* BL suffix */ case 3: instruction->type = ARM_BL; mnemonic = "BL"; break; } /* TODO: deal correctly with dual opcode (prefixed) BL/BLX; * these are effectively 32-bit instructions even in Thumb1. For * disassembly, it's simplest to always use the Thumb2 decoder. * * But some cores will evidently handle them as two instructions, * where exceptions may occur between the two. The ETMv3.2+ ID * register has a bit which exposes this behavior. */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32, address, opcode, mnemonic, target_address); instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = target_address; return ERROR_OK; } static int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t Rd = (opcode >> 0) & 0x7; uint8_t Rn = (opcode >> 3) & 0x7; uint8_t Rm_imm = (opcode >> 6) & 0x7; uint32_t opc = opcode & (1 << 9); uint32_t reg_imm = opcode & (1 << 10); char *mnemonic; if (opc) { instruction->type = ARM_SUB; mnemonic = "SUBS"; } else { /* REVISIT: if reg_imm == 0, display as "MOVS" */ instruction->type = ARM_ADD; mnemonic = "ADDS"; } instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = Rn; instruction->info.data_proc.S = 1; if (reg_imm) { instruction->info.data_proc.variant = 0;/*immediate*/ instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d", address, opcode, mnemonic, Rd, Rn, Rm_imm); } else { instruction->info.data_proc.variant = 1;/*immediate shift*/ instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i", address, opcode, mnemonic, Rd, Rn, Rm_imm); } return ERROR_OK; } static int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t Rd = (opcode >> 0) & 0x7; uint8_t Rm = (opcode >> 3) & 0x7; uint8_t imm = (opcode >> 6) & 0x1f; uint8_t opc = (opcode >> 11) & 0x3; char *mnemonic = NULL; switch (opc) { case 0: instruction->type = ARM_MOV; mnemonic = "LSLS"; instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0; break; case 1: instruction->type = ARM_MOV; mnemonic = "LSRS"; instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1; break; case 2: instruction->type = ARM_MOV; mnemonic = "ASRS"; instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2; break; } if ((imm == 0) && (opc != 0)) imm = 32; instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = -1; instruction->info.data_proc.S = 1; instruction->info.data_proc.variant = 1;/*immediate_shift*/ instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm; instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x", address, opcode, mnemonic, Rd, Rm, imm); return ERROR_OK; } static int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t imm = opcode & 0xff; uint8_t Rd = (opcode >> 8) & 0x7; uint32_t opc = (opcode >> 11) & 0x3; char *mnemonic = NULL; instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = Rd; instruction->info.data_proc.S = 1; instruction->info.data_proc.variant = 0;/*immediate*/ instruction->info.data_proc.shifter_operand.immediate.immediate = imm; switch (opc) { case 0: instruction->type = ARM_MOV; mnemonic = "MOVS"; instruction->info.data_proc.Rn = -1; break; case 1: instruction->type = ARM_CMP; mnemonic = "CMP"; instruction->info.data_proc.Rd = -1; break; case 2: instruction->type = ARM_ADD; mnemonic = "ADDS"; break; case 3: instruction->type = ARM_SUB; mnemonic = "SUBS"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x", address, opcode, mnemonic, Rd, imm); return ERROR_OK; } static int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t high_reg, op, Rm, Rd, H1, H2; char *mnemonic = NULL; bool nop = false; high_reg = (opcode & 0x0400) >> 10; op = (opcode & 0x03C0) >> 6; Rd = (opcode & 0x0007); Rm = (opcode & 0x0038) >> 3; H1 = (opcode & 0x0080) >> 7; H2 = (opcode & 0x0040) >> 6; instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = Rd; instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP)); instruction->info.data_proc.variant = 1 /*immediate shift*/; instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm; if (high_reg) { Rd |= H1 << 3; Rm |= H2 << 3; op >>= 2; switch (op) { case 0x0: instruction->type = ARM_ADD; mnemonic = "ADD"; break; case 0x1: instruction->type = ARM_CMP; mnemonic = "CMP"; break; case 0x2: instruction->type = ARM_MOV; mnemonic = "MOV"; if (Rd == Rm) nop = true; break; case 0x3: if ((opcode & 0x7) == 0x0) { instruction->info.b_bl_bx_blx.reg_operand = Rm; if (H1) { instruction->type = ARM_BLX; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tBLX\tr%i", address, opcode, Rm); } else { instruction->type = ARM_BX; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tBX\tr%i", address, opcode, Rm); } } else { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t" "UNDEFINED INSTRUCTION", address, opcode); } return ERROR_OK; break; } } else { switch (op) { case 0x0: instruction->type = ARM_AND; mnemonic = "ANDS"; break; case 0x1: instruction->type = ARM_EOR; mnemonic = "EORS"; break; case 0x2: instruction->type = ARM_MOV; mnemonic = "LSLS"; instruction->info.data_proc.variant = 2 /*register shift*/; instruction->info.data_proc.shifter_operand.register_shift.shift = 0; instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd; instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm; break; case 0x3: instruction->type = ARM_MOV; mnemonic = "LSRS"; instruction->info.data_proc.variant = 2 /*register shift*/; instruction->info.data_proc.shifter_operand.register_shift.shift = 1; instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd; instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm; break; case 0x4: instruction->type = ARM_MOV; mnemonic = "ASRS"; instruction->info.data_proc.variant = 2 /*register shift*/; instruction->info.data_proc.shifter_operand.register_shift.shift = 2; instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd; instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm; break; case 0x5: instruction->type = ARM_ADC; mnemonic = "ADCS"; break; case 0x6: instruction->type = ARM_SBC; mnemonic = "SBCS"; break; case 0x7: instruction->type = ARM_MOV; mnemonic = "RORS"; instruction->info.data_proc.variant = 2 /*register shift*/; instruction->info.data_proc.shifter_operand.register_shift.shift = 3; instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd; instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm; break; case 0x8: instruction->type = ARM_TST; mnemonic = "TST"; break; case 0x9: instruction->type = ARM_RSB; mnemonic = "RSBS"; instruction->info.data_proc.variant = 0 /*immediate*/; instruction->info.data_proc.shifter_operand.immediate.immediate = 0; instruction->info.data_proc.Rn = Rm; break; case 0xA: instruction->type = ARM_CMP; mnemonic = "CMP"; break; case 0xB: instruction->type = ARM_CMN; mnemonic = "CMN"; break; case 0xC: instruction->type = ARM_ORR; mnemonic = "ORRS"; break; case 0xD: instruction->type = ARM_MUL; mnemonic = "MULS"; break; case 0xE: instruction->type = ARM_BIC; mnemonic = "BICS"; break; case 0xF: instruction->type = ARM_MVN; mnemonic = "MVNS"; break; } } if (nop) snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t" "; (%s r%i, r%i)", address, opcode, mnemonic, Rd, Rm); else snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i", address, opcode, mnemonic, Rd, Rm); return ERROR_OK; } /* PC-relative data addressing is word-aligned even with Thumb */ static inline uint32_t thumb_alignpc4(uint32_t addr) { return (addr + 4) & ~3; } static int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t immediate; uint8_t Rd = (opcode >> 8) & 0x7; instruction->type = ARM_LDR; immediate = opcode & 0x000000ff; immediate *= 4; instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = 15 /*PC*/; instruction->info.load_store.index_mode = 0; /*offset*/ instruction->info.load_store.offset_mode = 0; /*immediate*/ instruction->info.load_store.offset.offset = immediate; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t" "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32, address, opcode, Rd, immediate, thumb_alignpc4(address) + immediate); return ERROR_OK; } static int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint8_t Rd = (opcode >> 0) & 0x7; uint8_t Rn = (opcode >> 3) & 0x7; uint8_t Rm = (opcode >> 6) & 0x7; uint8_t opc = (opcode >> 9) & 0x7; char *mnemonic = NULL; switch (opc) { case 0: instruction->type = ARM_STR; mnemonic = "STR"; break; case 1: instruction->type = ARM_STRH; mnemonic = "STRH"; break; case 2: instruction->type = ARM_STRB; mnemonic = "STRB"; break; case 3: instruction->type = ARM_LDRSB; mnemonic = "LDRSB"; break; case 4: instruction->type = ARM_LDR; mnemonic = "LDR"; break; case 5: instruction->type = ARM_LDRH; mnemonic = "LDRH"; break; case 6: instruction->type = ARM_LDRB; mnemonic = "LDRB"; break; case 7: instruction->type = ARM_LDRSH; mnemonic = "LDRSH"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]", address, opcode, mnemonic, Rd, Rn, Rm); instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = Rn; instruction->info.load_store.index_mode = 0; /*offset*/ instruction->info.load_store.offset_mode = 1; /*register*/ instruction->info.load_store.offset.reg.Rm = Rm; return ERROR_OK; } static int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t offset = (opcode >> 6) & 0x1f; uint8_t Rd = (opcode >> 0) & 0x7; uint8_t Rn = (opcode >> 3) & 0x7; uint32_t L = opcode & (1 << 11); uint32_t B = opcode & (1 << 12); char *mnemonic; char suffix = ' '; uint32_t shift = 2; if (L) { instruction->type = ARM_LDR; mnemonic = "LDR"; } else { instruction->type = ARM_STR; mnemonic = "STR"; } if ((opcode&0xF000) == 0x8000) { suffix = 'H'; shift = 1; } else if (B) { suffix = 'B'; shift = 0; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]", address, opcode, mnemonic, suffix, Rd, Rn, offset << shift); instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = Rn; instruction->info.load_store.index_mode = 0; /*offset*/ instruction->info.load_store.offset_mode = 0; /*immediate*/ instruction->info.load_store.offset.offset = offset << shift; return ERROR_OK; } static int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t offset = opcode & 0xff; uint8_t Rd = (opcode >> 8) & 0x7; uint32_t L = opcode & (1 << 11); char *mnemonic; if (L) { instruction->type = ARM_LDR; mnemonic = "LDR"; } else { instruction->type = ARM_STR; mnemonic = "STR"; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]", address, opcode, mnemonic, Rd, offset*4); instruction->info.load_store.Rd = Rd; instruction->info.load_store.Rn = 13 /*SP*/; instruction->info.load_store.index_mode = 0; /*offset*/ instruction->info.load_store.offset_mode = 0; /*immediate*/ instruction->info.load_store.offset.offset = offset*4; return ERROR_OK; } static int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t imm = opcode & 0xff; uint8_t Rd = (opcode >> 8) & 0x7; uint8_t Rn; uint32_t SP = opcode & (1 << 11); const char *reg_name; instruction->type = ARM_ADD; if (SP) { reg_name = "SP"; Rn = 13; } else { reg_name = "PC"; Rn = 15; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32, address, opcode, Rd, reg_name, imm * 4); instruction->info.data_proc.variant = 0 /* immediate */; instruction->info.data_proc.Rd = Rd; instruction->info.data_proc.Rn = Rn; instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4; return ERROR_OK; } static int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t imm = opcode & 0x7f; uint8_t opc = opcode & (1 << 7); char *mnemonic; if (opc) { instruction->type = ARM_SUB; mnemonic = "SUB"; } else { instruction->type = ARM_ADD; mnemonic = "ADD"; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32, address, opcode, mnemonic, imm*4); instruction->info.data_proc.variant = 0 /* immediate */; instruction->info.data_proc.Rd = 13 /*SP*/; instruction->info.data_proc.Rn = 13 /*SP*/; instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4; return ERROR_OK; } static int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t imm = opcode & 0xff; instruction->type = ARM_BKPT; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "", address, opcode, imm); return ERROR_OK; } static int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t reg_list = opcode & 0xff; uint32_t L = opcode & (1 << 11); uint32_t R = opcode & (1 << 8); uint8_t Rn = (opcode >> 8) & 7; uint8_t addr_mode = 0 /* IA */; char reg_names[40]; char *reg_names_p; char *mnemonic; char ptr_name[7] = ""; int i; /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions. * The STMIA and LDMIA opcodes are used for other instructions. */ if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */ char *wback = "!"; if (L) { instruction->type = ARM_LDM; mnemonic = "LDM"; if (opcode & (1 << Rn)) wback = ""; } else { instruction->type = ARM_STM; mnemonic = "STM"; } snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback); } else {/* push/pop */ Rn = 13;/* SP */ if (L) { instruction->type = ARM_LDM; mnemonic = "POP"; if (R) reg_list |= (1 << 15) /*PC*/; } else { instruction->type = ARM_STM; mnemonic = "PUSH"; addr_mode = 3; /*DB*/ if (R) reg_list |= (1 << 14) /*LR*/; } } reg_names_p = reg_names; for (i = 0; i <= 15; i++) { if (reg_list & (1 << i)) reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i); } if (reg_names_p > reg_names) reg_names_p[-2] = '\0'; else /* invalid op : no registers */ reg_names[0] = '\0'; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}", address, opcode, mnemonic, ptr_name, reg_names); instruction->info.load_store_multiple.register_list = reg_list; instruction->info.load_store_multiple.Rn = Rn; instruction->info.load_store_multiple.addressing_mode = addr_mode; return ERROR_OK; } static int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { uint32_t offset = opcode & 0xff; uint8_t cond = (opcode >> 8) & 0xf; uint32_t target_address; if (cond == 0xf) { instruction->type = ARM_SWI; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32, address, opcode, offset); return ERROR_OK; } else if (cond == 0xe) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } /* sign extend 8-bit offset */ if (offset & 0x00000080) offset = 0xffffff00 | offset; target_address = address + 4 + (offset << 1); snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32, address, opcode, arm_condition_strings[cond], target_address); instruction->type = ARM_B; instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = target_address; return ERROR_OK; } static int evaluate_cb_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { unsigned offset; /* added in Thumb2 */ offset = (opcode >> 3) & 0x1f; offset |= (opcode & 0x0200) >> 4; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32, address, opcode, (opcode & 0x0800) ? "N" : "", opcode & 0x7, address + 4 + (offset << 1)); return ERROR_OK; } static int evaluate_extend_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { /* added in ARMv6 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d", address, opcode, (opcode & 0x0080) ? 'U' : 'S', (opcode & 0x0040) ? 'B' : 'H', opcode & 0x7, (opcode >> 3) & 0x7); return ERROR_OK; } static int evaluate_cps_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { /* added in ARMv6 */ if ((opcode & 0x0ff0) == 0x0650) snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s", address, opcode, (opcode & 0x80) ? "BE" : "LE"); else /* ASSUME (opcode & 0x0fe0) == 0x0660 */ snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s", address, opcode, (opcode & 0x0010) ? 'D' : 'E', (opcode & 0x0004) ? "A" : "", (opcode & 0x0002) ? "I" : "", (opcode & 0x0001) ? "F" : ""); return ERROR_OK; } static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { char *suffix; /* added in ARMv6 */ switch ((opcode >> 6) & 3) { case 0: suffix = ""; break; case 1: suffix = "16"; break; default: suffix = "SH"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d", address, opcode, suffix, opcode & 0x7, (opcode >> 3) & 0x7); return ERROR_OK; } static int evaluate_hint_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { char *hint; switch ((opcode >> 4) & 0x0f) { case 0: hint = "NOP"; break; case 1: hint = "YIELD"; break; case 2: hint = "WFE"; break; case 3: hint = "WFI"; break; case 4: hint = "SEV"; break; default: hint = "HINT (UNRECOGNIZED)"; break; } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \t%s", address, opcode, hint); return ERROR_OK; } static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { unsigned cond = (opcode >> 4) & 0x0f; char *x = "", *y = "", *z = ""; if (opcode & 0x01) z = (opcode & 0x02) ? "T" : "E"; if (opcode & 0x03) y = (opcode & 0x04) ? "T" : "E"; if (opcode & 0x07) x = (opcode & 0x08) ? "T" : "E"; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s", address, opcode, x, y, z, arm_condition_strings[cond]); /* NOTE: strictly speaking, the next 1-4 instructions should * now be displayed with the relevant conditional suffix... */ return ERROR_OK; } int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { /* clear fields, to avoid confusion */ memset(instruction, 0, sizeof(struct arm_instruction)); instruction->opcode = opcode; instruction->instruction_size = 2; if ((opcode & 0xe000) == 0x0000) { /* add/substract register or immediate */ if ((opcode & 0x1800) == 0x1800) return evaluate_add_sub_thumb(opcode, address, instruction); /* shift by immediate */ else return evaluate_shift_imm_thumb(opcode, address, instruction); } /* Add/substract/compare/move immediate */ if ((opcode & 0xe000) == 0x2000) return evaluate_data_proc_imm_thumb(opcode, address, instruction); /* Data processing instructions */ if ((opcode & 0xf800) == 0x4000) return evaluate_data_proc_thumb(opcode, address, instruction); /* Load from literal pool */ if ((opcode & 0xf800) == 0x4800) return evaluate_load_literal_thumb(opcode, address, instruction); /* Load/Store register offset */ if ((opcode & 0xf000) == 0x5000) return evaluate_load_store_reg_thumb(opcode, address, instruction); /* Load/Store immediate offset */ if (((opcode & 0xe000) == 0x6000) || ((opcode & 0xf000) == 0x8000)) return evaluate_load_store_imm_thumb(opcode, address, instruction); /* Load/Store from/to stack */ if ((opcode & 0xf000) == 0x9000) return evaluate_load_store_stack_thumb(opcode, address, instruction); /* Add to SP/PC */ if ((opcode & 0xf000) == 0xa000) return evaluate_add_sp_pc_thumb(opcode, address, instruction); /* Misc */ if ((opcode & 0xf000) == 0xb000) { switch ((opcode >> 8) & 0x0f) { case 0x0: return evaluate_adjust_stack_thumb(opcode, address, instruction); case 0x1: case 0x3: case 0x9: case 0xb: return evaluate_cb_thumb(opcode, address, instruction); case 0x2: return evaluate_extend_thumb(opcode, address, instruction); case 0x4: case 0x5: case 0xc: case 0xd: return evaluate_load_store_multiple_thumb(opcode, address, instruction); case 0x6: return evaluate_cps_thumb(opcode, address, instruction); case 0xa: if ((opcode & 0x00c0) == 0x0080) break; return evaluate_byterev_thumb(opcode, address, instruction); case 0xe: return evaluate_breakpoint_thumb(opcode, address, instruction); case 0xf: if (opcode & 0x000f) return evaluate_ifthen_thumb(opcode, address, instruction); else return evaluate_hint_thumb(opcode, address, instruction); } instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } /* Load/Store multiple */ if ((opcode & 0xf000) == 0xc000) return evaluate_load_store_multiple_thumb(opcode, address, instruction); /* Conditional branch + SWI */ if ((opcode & 0xf000) == 0xd000) return evaluate_cond_branch_thumb(opcode, address, instruction); if ((opcode & 0xe000) == 0xe000) { /* Undefined instructions */ if ((opcode & 0xf801) == 0xe801) { instruction->type = ARM_UNDEFINED_INSTRUCTION; snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%8.8x\t" "UNDEFINED INSTRUCTION", address, opcode); return ERROR_OK; } else /* Branch to offset */ return evaluate_b_bl_blx_thumb(opcode, address, instruction); } LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode); return -1; } static int t2ev_b_bl(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { unsigned offset; unsigned b21 = 1 << 21; unsigned b22 = 1 << 22; /* instead of combining two smaller 16-bit branch instructions, * Thumb2 uses only one larger 32-bit instruction. */ offset = opcode & 0x7ff; offset |= (opcode & 0x03ff0000) >> 5; if (opcode & (1 << 26)) { offset |= 0xff << 23; if ((opcode & (1 << 11)) == 0) b21 = 0; if ((opcode & (1 << 13)) == 0) b22 = 0; } else { if (opcode & (1 << 11)) b21 = 0; if (opcode & (1 << 13)) b22 = 0; } offset |= b21; offset |= b22; address += 4; address += offset << 1; instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B; instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = address; sprintf(cp, "%s\t%#8.8" PRIx32, (opcode & (1 << 14)) ? "BL" : "B.W", address); return ERROR_OK; } static int t2ev_cond_b(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { unsigned offset; unsigned b17 = 1 << 17; unsigned b18 = 1 << 18; unsigned cond = (opcode >> 22) & 0x0f; offset = opcode & 0x7ff; offset |= (opcode & 0x003f0000) >> 5; if (opcode & (1 << 26)) { offset |= 0x1fff << 19; if ((opcode & (1 << 11)) == 0) b17 = 0; if ((opcode & (1 << 13)) == 0) b18 = 0; } else { if (opcode & (1 << 11)) b17 = 0; if (opcode & (1 << 13)) b18 = 0; } offset |= b17; offset |= b18; address += 4; address += offset << 1; instruction->type = ARM_B; instruction->info.b_bl_bx_blx.reg_operand = -1; instruction->info.b_bl_bx_blx.target_address = address; sprintf(cp, "B%s.W\t%#8.8" PRIx32, arm_condition_strings[cond], address); return ERROR_OK; } static const char *special_name(int number) { char *special = "(RESERVED)"; switch (number) { case 0: special = "apsr"; break; case 1: special = "iapsr"; break; case 2: special = "eapsr"; break; case 3: special = "xpsr"; break; case 5: special = "ipsr"; break; case 6: special = "epsr"; break; case 7: special = "iepsr"; break; case 8: special = "msp"; break; case 9: special = "psp"; break; case 16: special = "primask"; break; case 17: special = "basepri"; break; case 18: special = "basepri_max"; break; case 19: special = "faultmask"; break; case 20: special = "control"; break; } return special; } static int t2ev_hint(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { const char *mnemonic; if (opcode & 0x0700) { instruction->type = ARM_UNDEFINED_INSTRUCTION; strcpy(cp, "UNDEFINED"); return ERROR_OK; } if (opcode & 0x00f0) { sprintf(cp, "DBG\t#%d", (int) opcode & 0xf); return ERROR_OK; } switch (opcode & 0x0f) { case 0: mnemonic = "NOP.W"; break; case 1: mnemonic = "YIELD.W"; break; case 2: mnemonic = "WFE.W"; break; case 3: mnemonic = "WFI.W"; break; case 4: mnemonic = "SEV.W"; break; default: mnemonic = "HINT.W (UNRECOGNIZED)"; break; } strcpy(cp, mnemonic); return ERROR_OK; } static int t2ev_misc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { const char *mnemonic; switch ((opcode >> 4) & 0x0f) { case 0: mnemonic = "LEAVEX"; break; case 1: mnemonic = "ENTERX"; break; case 2: mnemonic = "CLREX"; break; case 4: mnemonic = "DSB"; break; case 5: mnemonic = "DMB"; break; case 6: mnemonic = "ISB"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } strcpy(cp, mnemonic); return ERROR_OK; } static int t2ev_b_misc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { /* permanently undefined */ if ((opcode & 0x07f07000) == 0x07f02000) { instruction->type = ARM_UNDEFINED_INSTRUCTION; strcpy(cp, "UNDEFINED"); return ERROR_OK; } switch ((opcode >> 12) & 0x5) { case 0x1: case 0x5: return t2ev_b_bl(opcode, address, instruction, cp); case 0x4: goto undef; case 0: if (((opcode >> 23) & 0x07) != 0x07) return t2ev_cond_b(opcode, address, instruction, cp); if (opcode & (1 << 26)) goto undef; break; } switch ((opcode >> 20) & 0x7f) { case 0x38: case 0x39: sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff), (int) (opcode >> 16) & 0x0f); return ERROR_OK; case 0x3a: return t2ev_hint(opcode, address, instruction, cp); case 0x3b: return t2ev_misc(opcode, address, instruction, cp); case 0x3c: sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f); return ERROR_OK; case 0x3e: case 0x3f: sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f, special_name(opcode & 0xff)); return ERROR_OK; } undef: return ERROR_COMMAND_SYNTAX_ERROR; } static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { char *mnemonic = NULL; int rn = (opcode >> 16) & 0xf; int rd = (opcode >> 8) & 0xf; unsigned immed = opcode & 0xff; unsigned func; bool one = false; char *suffix = ""; char *suffix2 = ""; /* ARMv7-M: A5.3.2 Modified immediate constants */ func = (opcode >> 11) & 0x0e; if (immed & 0x80) func |= 1; if (opcode & (1 << 26)) func |= 0x10; /* "Modified" immediates */ switch (func >> 1) { case 0: break; case 2: immed <<= 8; /* FALLTHROUGH */ case 1: immed += immed << 16; break; case 3: immed += immed << 8; immed += immed << 16; break; default: immed |= 0x80; immed = ror(immed, func); } if (opcode & (1 << 20)) suffix = "S"; switch ((opcode >> 21) & 0xf) { case 0: if (rd == 0xf) { instruction->type = ARM_TST; mnemonic = "TST"; one = true; suffix = ""; rd = rn; } else { instruction->type = ARM_AND; mnemonic = "AND"; } break; case 1: instruction->type = ARM_BIC; mnemonic = "BIC"; break; case 2: if (rn == 0xf) { instruction->type = ARM_MOV; mnemonic = "MOV"; one = true; suffix2 = ".W"; } else { instruction->type = ARM_ORR; mnemonic = "ORR"; } break; case 3: if (rn == 0xf) { instruction->type = ARM_MVN; mnemonic = "MVN"; one = true; } else { /* instruction->type = ARM_ORN; */ mnemonic = "ORN"; } break; case 4: if (rd == 0xf) { instruction->type = ARM_TEQ; mnemonic = "TEQ"; one = true; suffix = ""; rd = rn; } else { instruction->type = ARM_EOR; mnemonic = "EOR"; } break; case 8: if (rd == 0xf) { instruction->type = ARM_CMN; mnemonic = "CMN"; one = true; suffix = ""; rd = rn; } else { instruction->type = ARM_ADD; mnemonic = "ADD"; suffix2 = ".W"; } break; case 10: instruction->type = ARM_ADC; mnemonic = "ADC"; suffix2 = ".W"; break; case 11: instruction->type = ARM_SBC; mnemonic = "SBC"; break; case 13: if (rd == 0xf) { instruction->type = ARM_CMP; mnemonic = "CMP"; one = true; suffix = ""; rd = rn; } else { instruction->type = ARM_SUB; mnemonic = "SUB"; } suffix2 = ".W"; break; case 14: instruction->type = ARM_RSB; mnemonic = "RSB"; suffix2 = ".W"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } if (one) sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x", mnemonic, suffix2, rd, immed, immed); else sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x", mnemonic, suffix, suffix2, rd, rn, immed, immed); return ERROR_OK; } static int t2ev_data_immed(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { char *mnemonic = NULL; int rn = (opcode >> 16) & 0xf; int rd = (opcode >> 8) & 0xf; unsigned immed; bool add = false; bool is_signed = false; immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4); if (opcode & (1 << 26)) immed |= (1 << 11); switch ((opcode >> 20) & 0x1f) { case 0: if (rn == 0xf) { add = true; goto do_adr; } mnemonic = "ADDW"; break; case 4: immed |= (opcode >> 4) & 0xf000; sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed); return ERROR_OK; case 0x0a: if (rn == 0xf) goto do_adr; mnemonic = "SUBW"; break; case 0x0c: /* move constant to top 16 bits of register */ immed |= (opcode >> 4) & 0xf000; sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed); return ERROR_OK; case 0x10: case 0x12: is_signed = true; case 0x18: case 0x1a: /* signed/unsigned saturated add */ immed = (opcode >> 6) & 0x03; immed |= (opcode >> 10) & 0x1c; sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t", is_signed ? "S" : "U", rd, (int) (opcode & 0x1f) + is_signed, rn, (opcode & (1 << 21)) ? "ASR" : "LSL", immed ? immed : 32); return ERROR_OK; case 0x14: is_signed = true; /* FALLTHROUGH */ case 0x1c: /* signed/unsigned bitfield extract */ immed = (opcode >> 6) & 0x03; immed |= (opcode >> 10) & 0x1c; sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t", is_signed ? "S" : "U", rd, rn, immed, (int) (opcode & 0x1f) + 1); return ERROR_OK; case 0x16: immed = (opcode >> 6) & 0x03; immed |= (opcode >> 10) & 0x1c; if (rn == 0xf) /* bitfield clear */ sprintf(cp, "BFC\tr%d, #%d, #%d\t", rd, immed, (int) (opcode & 0x1f) + 1 - immed); else /* bitfield insert */ sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t", rd, rn, immed, (int) (opcode & 0x1f) + 1 - immed); return ERROR_OK; default: return ERROR_COMMAND_SYNTAX_ERROR; } sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic, rd, rn, immed, immed); return ERROR_OK; do_adr: address = thumb_alignpc4(address); if (add) address += immed; else address -= immed; /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better; * not hiding the pc-relative stuff will sometimes be useful. */ sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address); return ERROR_OK; } static int t2ev_store_single(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { unsigned op = (opcode >> 20) & 0xf; char *size = ""; char *suffix = ""; char *p1 = ""; char *p2 = "]"; unsigned immed; unsigned rn = (opcode >> 16) & 0x0f; unsigned rt = (opcode >> 12) & 0x0f; if (rn == 0xf) return ERROR_COMMAND_SYNTAX_ERROR; if (opcode & 0x0800) op |= 1; switch (op) { /* byte */ case 0x8: case 0x9: size = "B"; goto imm12; case 0x1: size = "B"; goto imm8; case 0x0: size = "B"; break; /* halfword */ case 0xa: case 0xb: size = "H"; goto imm12; case 0x3: size = "H"; goto imm8; case 0x2: size = "H"; break; /* word */ case 0xc: case 0xd: goto imm12; case 0x5: goto imm8; case 0x4: break; /* error */ default: return ERROR_COMMAND_SYNTAX_ERROR; } sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]", size, rt, rn, (int) opcode & 0x0f, (int) (opcode >> 4) & 0x03); return ERROR_OK; imm12: immed = opcode & 0x0fff; sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x", size, rt, rn, immed, immed); return ERROR_OK; imm8: immed = opcode & 0x00ff; switch (opcode & 0x700) { case 0x600: suffix = "T"; break; case 0x000: case 0x200: return ERROR_COMMAND_SYNTAX_ERROR; } /* two indexed modes will write back rn */ if (opcode & 0x100) { if (opcode & 0x400) /* pre-indexed */ p2 = "]!"; else { /* post-indexed */ p1 = "]"; p2 = ""; } } sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x", size, suffix, rt, rn, p1, (opcode & 0x200) ? "" : "-", immed, p2, immed); return ERROR_OK; } static int t2ev_mul32(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int ra = (opcode >> 12) & 0xf; switch (opcode & 0x007000f0) { case 0: if (ra == 0xf) sprintf(cp, "MUL\tr%d, r%d, r%d", (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); else sprintf(cp, "MLA\tr%d, r%d, r%d, r%d", (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, ra); break; case 0x10: sprintf(cp, "MLS\tr%d, r%d, r%d, r%d", (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf, ra); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int t2ev_mul64_div(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int op = (opcode >> 4) & 0xf; char *infix = "MUL"; op += (opcode >> 16) & 0x70; switch (op) { case 0x40: case 0x60: infix = "MLA"; /* FALLTHROUGH */ case 0: case 0x20: sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d", (op & 0x20) ? 'U' : 'S', infix, (int) (opcode >> 12) & 0xf, (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); break; case 0x1f: case 0x3f: sprintf(cp, "%cDIV\tr%d, r%d, r%d", (op & 0x20) ? 'U' : 'S', (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int t2ev_ldm_stm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int rn = (opcode >> 16) & 0xf; int op = (opcode >> 22) & 0x6; int t = (opcode >> 21) & 1; unsigned registers = opcode & 0xffff; char *mode = ""; if (opcode & (1 << 20)) op |= 1; switch (op) { case 0: mode = "DB"; /* FALL THROUGH */ case 6: sprintf(cp, "SRS%s\tsp%s, #%d", mode, t ? "!" : "", (unsigned) (opcode & 0x1f)); return ERROR_OK; case 1: mode = "DB"; /* FALL THROUGH */ case 7: sprintf(cp, "RFE%s\tr%d%s", mode, (unsigned) ((opcode >> 16) & 0xf), t ? "!" : ""); return ERROR_OK; case 2: sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : ""); break; case 3: if (rn == 13 && t) sprintf(cp, "POP.W\t"); else sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : ""); break; case 4: if (rn == 13 && t) sprintf(cp, "PUSH.W\t"); else sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : ""); break; case 5: sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : ""); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } cp = strchr(cp, 0); *cp++ = '{'; for (t = 0; registers; t++, registers >>= 1) { if ((registers & 1) == 0) continue; registers &= ~1; sprintf(cp, "r%d%s", t, registers ? ", " : ""); cp = strchr(cp, 0); } *cp++ = '}'; *cp++ = 0; return ERROR_OK; } /* load/store dual or exclusive, table branch */ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { unsigned op1op2 = (opcode >> 20) & 0x3; unsigned op3 = (opcode >> 4) & 0xf; char *mnemonic; unsigned rn = (opcode >> 16) & 0xf; unsigned rt = (opcode >> 12) & 0xf; unsigned rd = (opcode >> 8) & 0xf; unsigned imm = opcode & 0xff; char *p1 = ""; char *p2 = "]"; op1op2 |= (opcode >> 21) & 0xc; switch (op1op2) { case 0: mnemonic = "STREX"; goto strex; case 1: mnemonic = "LDREX"; goto ldrex; case 2: case 6: case 8: case 10: case 12: case 14: mnemonic = "STRD"; goto immediate; case 3: case 7: case 9: case 11: case 13: case 15: mnemonic = "LDRD"; if (rn == 15) goto literal; else goto immediate; case 4: switch (op3) { case 4: mnemonic = "STREXB"; break; case 5: mnemonic = "STREXH"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } rd = opcode & 0xf; imm = 0; goto strex; case 5: switch (op3) { case 0: sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf); return ERROR_OK; case 1: sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf); return ERROR_OK; case 4: mnemonic = "LDREXB"; break; case 5: mnemonic = "LDREXH"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } imm = 0; goto ldrex; } return ERROR_COMMAND_SYNTAX_ERROR; strex: imm <<= 2; if (imm) sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x", mnemonic, rd, rt, rn, imm, imm); else sprintf(cp, "%s\tr%u, r%u, [r%u]", mnemonic, rd, rt, rn); return ERROR_OK; ldrex: imm <<= 2; if (imm) sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x", mnemonic, rt, rn, imm, imm); else sprintf(cp, "%s\tr%u, [r%u]", mnemonic, rt, rn); return ERROR_OK; immediate: /* two indexed modes will write back rn */ if (opcode & (1 << 21)) { if (opcode & (1 << 24)) /* pre-indexed */ p2 = "]!"; else { /* post-indexed */ p1 = "]"; p2 = ""; } } imm <<= 2; sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x", mnemonic, rt, rd, rn, p1, (opcode & (1 << 23)) ? "" : "-", imm, p2, imm); return ERROR_OK; literal: address = thumb_alignpc4(address); imm <<= 2; if (opcode & (1 << 23)) address += imm; else address -= imm; sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32, mnemonic, rt, rd, address); return ERROR_OK; } static int t2ev_data_shift(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int op = (opcode >> 21) & 0xf; int rd = (opcode >> 8) & 0xf; int rn = (opcode >> 16) & 0xf; int type = (opcode >> 4) & 0x3; int immed = (opcode >> 6) & 0x3; char *mnemonic; char *suffix = ""; immed |= (opcode >> 10) & 0x1c; if (opcode & (1 << 20)) suffix = "S"; switch (op) { case 0: if (rd == 0xf) { if (!(opcode & (1 << 20))) return ERROR_COMMAND_SYNTAX_ERROR; instruction->type = ARM_TST; mnemonic = "TST"; suffix = ""; goto two; } instruction->type = ARM_AND; mnemonic = "AND"; break; case 1: instruction->type = ARM_BIC; mnemonic = "BIC"; break; case 2: if (rn == 0xf) { instruction->type = ARM_MOV; switch (type) { case 0: if (immed == 0) { sprintf(cp, "MOV%s.W\tr%d, r%d", suffix, rd, (int) (opcode & 0xf)); return ERROR_OK; } mnemonic = "LSL"; break; case 1: mnemonic = "LSR"; break; case 2: mnemonic = "ASR"; break; default: if (immed == 0) { sprintf(cp, "RRX%s\tr%d, r%d", suffix, rd, (int) (opcode & 0xf)); return ERROR_OK; } mnemonic = "ROR"; break; } goto immediate; } else { instruction->type = ARM_ORR; mnemonic = "ORR"; } break; case 3: if (rn == 0xf) { instruction->type = ARM_MVN; mnemonic = "MVN"; rn = rd; goto two; } else { /* instruction->type = ARM_ORN; */ mnemonic = "ORN"; } break; case 4: if (rd == 0xf) { if (!(opcode & (1 << 20))) return ERROR_COMMAND_SYNTAX_ERROR; instruction->type = ARM_TEQ; mnemonic = "TEQ"; suffix = ""; goto two; } instruction->type = ARM_EOR; mnemonic = "EOR"; break; case 8: if (rd == 0xf) { if (!(opcode & (1 << 20))) return ERROR_COMMAND_SYNTAX_ERROR; instruction->type = ARM_CMN; mnemonic = "CMN"; suffix = ""; goto two; } instruction->type = ARM_ADD; mnemonic = "ADD"; break; case 0xa: instruction->type = ARM_ADC; mnemonic = "ADC"; break; case 0xb: instruction->type = ARM_SBC; mnemonic = "SBC"; break; case 0xd: if (rd == 0xf) { if (!(opcode & (1 << 21))) return ERROR_COMMAND_SYNTAX_ERROR; instruction->type = ARM_CMP; mnemonic = "CMP"; suffix = ""; goto two; } instruction->type = ARM_SUB; mnemonic = "SUB"; break; case 0xe: instruction->type = ARM_RSB; mnemonic = "RSB"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } sprintf(cp, "%s%s.W\tr%d, r%d, r%d", mnemonic, suffix, rd, rn, (int) (opcode & 0xf)); shift: cp = strchr(cp, 0); switch (type) { case 0: if (immed == 0) return ERROR_OK; suffix = "LSL"; break; case 1: suffix = "LSR"; if (immed == 32) immed = 0; break; case 2: suffix = "ASR"; if (immed == 32) immed = 0; break; case 3: if (immed == 0) { strcpy(cp, ", RRX"); return ERROR_OK; } suffix = "ROR"; break; } sprintf(cp, ", %s #%d", suffix, immed ? immed : 32); return ERROR_OK; two: sprintf(cp, "%s%s.W\tr%d, r%d", mnemonic, suffix, rn, (int) (opcode & 0xf)); goto shift; immediate: sprintf(cp, "%s%s.W\tr%d, r%d, #%d", mnemonic, suffix, rd, (int) (opcode & 0xf), immed ? immed : 32); return ERROR_OK; } static int t2ev_data_reg(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { char *mnemonic; char *suffix = ""; if (((opcode >> 4) & 0xf) == 0) { switch ((opcode >> 21) & 0x7) { case 0: mnemonic = "LSL"; break; case 1: mnemonic = "LSR"; break; case 2: mnemonic = "ASR"; break; case 3: mnemonic = "ROR"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } instruction->type = ARM_MOV; if (opcode & (1 << 20)) suffix = "S"; sprintf(cp, "%s%s.W\tr%d, r%d, r%d", mnemonic, suffix, (int) (opcode >> 8) & 0xf, (int) (opcode >> 16) & 0xf, (int) (opcode >> 0) & 0xf); } else if (opcode & (1 << 7)) { switch ((opcode >> 20) & 0xf) { case 0: case 1: case 4: case 5: switch ((opcode >> 4) & 0x3) { case 1: suffix = ", ROR #8"; break; case 2: suffix = ", ROR #16"; break; case 3: suffix = ", ROR #24"; break; } sprintf(cp, "%cXT%c.W\tr%d, r%d%s", (opcode & (1 << 24)) ? 'U' : 'S', (opcode & (1 << 26)) ? 'B' : 'H', (int) (opcode >> 8) & 0xf, (int) (opcode >> 0) & 0xf, suffix); break; case 8: case 9: case 0xa: case 0xb: if (opcode & (1 << 6)) return ERROR_COMMAND_SYNTAX_ERROR; if (((opcode >> 12) & 0xf) != 0xf) return ERROR_COMMAND_SYNTAX_ERROR; if (!(opcode & (1 << 20))) return ERROR_COMMAND_SYNTAX_ERROR; switch (((opcode >> 19) & 0x04) | ((opcode >> 4) & 0x3)) { case 0: mnemonic = "REV.W"; break; case 1: mnemonic = "REV16.W"; break; case 2: mnemonic = "RBIT"; break; case 3: mnemonic = "REVSH.W"; break; case 4: mnemonic = "CLZ"; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } sprintf(cp, "%s\tr%d, r%d", mnemonic, (int) (opcode >> 8) & 0xf, (int) (opcode >> 0) & 0xf); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } } return ERROR_OK; } static int t2ev_load_word(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int rn = (opcode >> 16) & 0xf; int immed; instruction->type = ARM_LDR; if (rn == 0xf) { immed = opcode & 0x0fff; if ((opcode & (1 << 23)) == 0) immed = -immed; sprintf(cp, "LDR\tr%d, %#8.8" PRIx32, (int) (opcode >> 12) & 0xf, thumb_alignpc4(address) + immed); return ERROR_OK; } if (opcode & (1 << 23)) { immed = opcode & 0x0fff; sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x", (int) (opcode >> 12) & 0xf, rn, immed, immed); return ERROR_OK; } if (!(opcode & (0x3f << 6))) { sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]", (int) (opcode >> 12) & 0xf, rn, (int) (opcode >> 0) & 0xf, (int) (opcode >> 4) & 0x3); return ERROR_OK; } if (((opcode >> 8) & 0xf) == 0xe) { immed = opcode & 0x00ff; sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x", (int) (opcode >> 12) & 0xf, rn, immed, immed); return ERROR_OK; } if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) { char *p1 = "]", *p2 = ""; if (!(opcode & 0x0500)) return ERROR_COMMAND_SYNTAX_ERROR; immed = opcode & 0x00ff; /* two indexed modes will write back rn */ if (opcode & 0x100) { if (opcode & 0x400) /* pre-indexed */ p2 = "]!"; else { /* post-indexed */ p1 = "]"; p2 = ""; } } sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x", (int) (opcode >> 12) & 0xf, rn, p1, (opcode & 0x200) ? "" : "-", immed, p2, immed); return ERROR_OK; } return ERROR_COMMAND_SYNTAX_ERROR; } static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int rn = (opcode >> 16) & 0xf; int rt = (opcode >> 12) & 0xf; int op2 = (opcode >> 6) & 0x3f; unsigned immed; char *p1 = "", *p2 = "]"; char *mnemonic; switch ((opcode >> 23) & 0x3) { case 0: if ((rn & rt) == 0xf) { pld_literal: immed = opcode & 0xfff; address = thumb_alignpc4(address); if (opcode & (1 << 23)) address += immed; else address -= immed; sprintf(cp, "PLD\tr%d, %#8.8" PRIx32, rt, address); return ERROR_OK; } if (rn == 0x0f && rt != 0x0f) { ldrb_literal: immed = opcode & 0xfff; address = thumb_alignpc4(address); if (opcode & (1 << 23)) address += immed; else address -= immed; sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32, rt, address); return ERROR_OK; } if (rn == 0x0f) break; if ((op2 & 0x3c) == 0x38) { immed = opcode & 0xff; sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x", rt, rn, immed, immed); return ERROR_OK; } if ((op2 & 0x3c) == 0x30) { if (rt == 0x0f) { immed = opcode & 0xff; immed = -immed; preload_immediate: p1 = (opcode & (1 << 21)) ? "W" : ""; sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x", p1, rn, immed, immed); return ERROR_OK; } mnemonic = "LDRB"; ldrxb_immediate_t3: immed = opcode & 0xff; if (!(opcode & 0x200)) immed = -immed; /* two indexed modes will write back rn */ if (opcode & 0x100) { if (opcode & 0x400) /* pre-indexed */ p2 = "]!"; else { /* post-indexed */ p1 = "]"; p2 = ""; } } ldrxb_immediate_t2: sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x", mnemonic, rt, rn, p1, immed, p2, immed); return ERROR_OK; } if ((op2 & 0x24) == 0x24) { mnemonic = "LDRB"; goto ldrxb_immediate_t3; } if (op2 == 0) { int rm = opcode & 0xf; if (rt == 0x0f) sprintf(cp, "PLD\t"); else sprintf(cp, "LDRB.W\tr%d, ", rt); immed = (opcode >> 4) & 0x3; cp = strchr(cp, 0); sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed); return ERROR_OK; } break; case 1: if ((rn & rt) == 0xf) goto pld_literal; if (rt == 0xf) { immed = opcode & 0xfff; goto preload_immediate; } if (rn == 0x0f) goto ldrb_literal; mnemonic = "LDRB.W"; immed = opcode & 0xfff; goto ldrxb_immediate_t2; case 2: if ((rn & rt) == 0xf) { immed = opcode & 0xfff; address = thumb_alignpc4(address); if (opcode & (1 << 23)) address += immed; else address -= immed; sprintf(cp, "PLI\t%#8.8" PRIx32, address); return ERROR_OK; } if (rn == 0xf && rt != 0xf) { ldrsb_literal: immed = opcode & 0xfff; address = thumb_alignpc4(address); if (opcode & (1 << 23)) address += immed; else address -= immed; sprintf(cp, "LDRSB\t%#8.8" PRIx32, address); return ERROR_OK; } if (rn == 0xf) break; if ((op2 & 0x3c) == 0x38) { immed = opcode & 0xff; sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x", rt, rn, immed, immed); return ERROR_OK; } if ((op2 & 0x3c) == 0x30) { if (rt == 0xf) { immed = opcode & 0xff; immed = -immed; /* pli */ sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x", rn, immed, -immed); return ERROR_OK; } mnemonic = "LDRSB"; goto ldrxb_immediate_t3; } if ((op2 & 0x24) == 0x24) { mnemonic = "LDRSB"; goto ldrxb_immediate_t3; } if (op2 == 0) { int rm = opcode & 0xf; if (rt == 0x0f) sprintf(cp, "PLI\t"); else sprintf(cp, "LDRSB.W\tr%d, ", rt); immed = (opcode >> 4) & 0x3; cp = strchr(cp, 0); sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed); return ERROR_OK; } break; case 3: if (rt == 0xf) { immed = opcode & 0xfff; sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x", rn, immed, immed); return ERROR_OK; } if (rn == 0xf) goto ldrsb_literal; immed = opcode & 0xfff; mnemonic = "LDRSB"; goto ldrxb_immediate_t2; } return ERROR_COMMAND_SYNTAX_ERROR; } static int t2ev_load_halfword(uint32_t opcode, uint32_t address, struct arm_instruction *instruction, char *cp) { int rn = (opcode >> 16) & 0xf; int rt = (opcode >> 12) & 0xf; int op2 = (opcode >> 6) & 0x3f; char *sign = ""; unsigned immed; if (rt == 0xf) { sprintf(cp, "HINT (UNALLOCATED)"); return ERROR_OK; } if (opcode & (1 << 24)) sign = "S"; if ((opcode & (1 << 23)) == 0) { if (rn == 0xf) { ldrh_literal: immed = opcode & 0xfff; address = thumb_alignpc4(address); if (opcode & (1 << 23)) address += immed; else address -= immed; sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32, sign, rt, address); return ERROR_OK; } if (op2 == 0) { int rm = opcode & 0xf; immed = (opcode >> 4) & 0x3; sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]", sign, rt, rn, rm, immed); return ERROR_OK; } if ((op2 & 0x3c) == 0x38) { immed = opcode & 0xff; sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x", sign, rt, rn, immed, immed); return ERROR_OK; } if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) { char *p1 = "", *p2 = "]"; immed = opcode & 0xff; if (!(opcode & 0x200)) immed = -immed; /* two indexed modes will write back rn */ if (opcode & 0x100) { if (opcode & 0x400) /* pre-indexed */ p2 = "]!"; else { /* post-indexed */ p1 = "]"; p2 = ""; } } sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x", sign, rt, rn, p1, immed, p2, immed); return ERROR_OK; } } else { if (rn == 0xf) goto ldrh_literal; immed = opcode & 0xfff; sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x", sign, *sign ? "" : ".W", rt, rn, immed, immed); return ERROR_OK; } return ERROR_COMMAND_SYNTAX_ERROR; } /* * REVISIT for Thumb2 instructions, instruction->type and friends aren't * always set. That means eventual arm_simulate_step() support for Thumb2 * will need work in this area. */ int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction) { int retval; uint16_t op; uint32_t opcode; char *cp; /* clear low bit ... it's set on function pointers */ address &= ~1; /* clear fields, to avoid confusion */ memset(instruction, 0, sizeof(struct arm_instruction)); /* read first halfword, see if this is the only one */ retval = target_read_u16(target, address, &op); if (retval != ERROR_OK) return retval; switch (op & 0xf800) { case 0xf800: case 0xf000: case 0xe800: /* 32-bit instructions */ instruction->instruction_size = 4; opcode = op << 16; retval = target_read_u16(target, address + 2, &op); if (retval != ERROR_OK) return retval; opcode |= op; instruction->opcode = opcode; break; default: /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */ return thumb_evaluate_opcode(op, address, instruction); } snprintf(instruction->text, 128, "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t", address, opcode); cp = strchr(instruction->text, 0); retval = ERROR_FAIL; /* ARMv7-M: A5.3.1 Data processing (modified immediate) */ if ((opcode & 0x1a008000) == 0x10000000) retval = t2ev_data_mod_immed(opcode, address, instruction, cp); /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */ else if ((opcode & 0x1a008000) == 0x12000000) retval = t2ev_data_immed(opcode, address, instruction, cp); /* ARMv7-M: A5.3.4 Branches and miscellaneous control */ else if ((opcode & 0x18008000) == 0x10008000) retval = t2ev_b_misc(opcode, address, instruction, cp); /* ARMv7-M: A5.3.5 Load/store multiple */ else if ((opcode & 0x1e400000) == 0x08000000) retval = t2ev_ldm_stm(opcode, address, instruction, cp); /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */ else if ((opcode & 0x1e400000) == 0x08400000) retval = t2ev_ldrex_strex(opcode, address, instruction, cp); /* ARMv7-M: A5.3.7 Load word */ else if ((opcode & 0x1f700000) == 0x18500000) retval = t2ev_load_word(opcode, address, instruction, cp); /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */ else if ((opcode & 0x1e700000) == 0x18300000) retval = t2ev_load_halfword(opcode, address, instruction, cp); /* ARMv7-M: A5.3.9 Load byte, memory hints */ else if ((opcode & 0x1e700000) == 0x18100000) retval = t2ev_load_byte_hints(opcode, address, instruction, cp); /* ARMv7-M: A5.3.10 Store single data item */ else if ((opcode & 0x1f100000) == 0x18000000) retval = t2ev_store_single(opcode, address, instruction, cp); /* ARMv7-M: A5.3.11 Data processing (shifted register) */ else if ((opcode & 0x1e000000) == 0x0a000000) retval = t2ev_data_shift(opcode, address, instruction, cp); /* ARMv7-M: A5.3.12 Data processing (register) * and A5.3.13 Miscellaneous operations */ else if ((opcode & 0x1f000000) == 0x1a000000) retval = t2ev_data_reg(opcode, address, instruction, cp); /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */ else if ((opcode & 0x1f800000) == 0x1b000000) retval = t2ev_mul32(opcode, address, instruction, cp); /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */ else if ((opcode & 0x1f800000) == 0x1b800000) retval = t2ev_mul64_div(opcode, address, instruction, cp); if (retval == ERROR_OK) return retval; /* * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD) * instructions; not yet handled here. */ if (retval == ERROR_COMMAND_SYNTAX_ERROR) { instruction->type = ARM_UNDEFINED_INSTRUCTION; strcpy(cp, "UNDEFINED OPCODE"); return ERROR_OK; } LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")", opcode); strcpy(cp, "(32-bit Thumb2 ...)"); return ERROR_OK; } int arm_access_size(struct arm_instruction *instruction) { if ((instruction->type == ARM_LDRB) || (instruction->type == ARM_LDRBT) || (instruction->type == ARM_LDRSB) || (instruction->type == ARM_STRB) || (instruction->type == ARM_STRBT)) return 1; else if ((instruction->type == ARM_LDRH) || (instruction->type == ARM_LDRSH) || (instruction->type == ARM_STRH)) return 2; else if ((instruction->type == ARM_LDR) || (instruction->type == ARM_LDRT) || (instruction->type == ARM_STR) || (instruction->type == ARM_STRT)) return 4; else if ((instruction->type == ARM_LDRD) || (instruction->type == ARM_STRD)) return 8; else { LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type); return 0; } } openocd-0.9.0/src/target/arm_disassembler.h0000644000175000017500000001105012516456303015634 00000000000000/*************************************************************************** * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM_DISASSEMBLER_H #define ARM_DISASSEMBLER_H enum arm_instruction_type { ARM_UNKNOWN_INSTUCTION, /* Branch instructions */ ARM_B, ARM_BL, ARM_BX, ARM_BLX, /* Data processing instructions */ ARM_AND, ARM_EOR, ARM_SUB, ARM_RSB, ARM_ADD, ARM_ADC, ARM_SBC, ARM_RSC, ARM_TST, ARM_TEQ, ARM_CMP, ARM_CMN, ARM_ORR, ARM_MOV, ARM_BIC, ARM_MVN, /* Load/store instructions */ ARM_LDR, ARM_LDRB, ARM_LDRT, ARM_LDRBT, ARM_LDRH, ARM_LDRSB, ARM_LDRSH, ARM_LDM, ARM_STR, ARM_STRB, ARM_STRT, ARM_STRBT, ARM_STRH, ARM_STM, /* Status register access instructions */ ARM_MRS, ARM_MSR, /* Multiply instructions */ ARM_MUL, ARM_MLA, ARM_SMULL, ARM_SMLAL, ARM_UMULL, ARM_UMLAL, /* Miscellaneous instructions */ ARM_CLZ, /* Exception return instructions */ ARM_ERET, /* Exception generating instructions */ ARM_BKPT, ARM_SWI, ARM_HVC, ARM_SMC, /* Coprocessor instructions */ ARM_CDP, ARM_LDC, ARM_STC, ARM_MCR, ARM_MRC, /* Semaphore instructions */ ARM_SWP, ARM_SWPB, /* Enhanced DSP extensions */ ARM_MCRR, ARM_MRRC, ARM_PLD, ARM_QADD, ARM_QDADD, ARM_QSUB, ARM_QDSUB, ARM_SMLAxy, ARM_SMLALxy, ARM_SMLAWy, ARM_SMULxy, ARM_SMULWy, ARM_LDRD, ARM_STRD, ARM_UNDEFINED_INSTRUCTION = 0xffffffff, }; struct arm_b_bl_bx_blx_instr { int reg_operand; uint32_t target_address; }; union arm_shifter_operand { struct { uint32_t immediate; } immediate; struct { uint8_t Rm; uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */ uint8_t shift_imm; } immediate_shift; struct { uint8_t Rm; uint8_t shift; uint8_t Rs; } register_shift; }; struct arm_data_proc_instr { int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */ uint8_t S; uint8_t Rn; uint8_t Rd; union arm_shifter_operand shifter_operand; }; struct arm_load_store_instr { uint8_t Rd; uint8_t Rn; uint8_t U; int index_mode; /* 0: offset, 1: pre-indexed, 2: post-indexed */ int offset_mode; /* 0: immediate, 1: (scaled) register */ union { uint32_t offset; struct { uint8_t Rm; uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */ uint8_t shift_imm; } reg; } offset; }; struct arm_load_store_multiple_instr { uint8_t Rn; uint32_t register_list; uint8_t addressing_mode; /* 0: IA, 1: IB, 2: DA, 3: DB */ uint8_t S; uint8_t W; }; struct arm_instruction { enum arm_instruction_type type; char text[128]; uint32_t opcode; /* return value ... Thumb-2 sizes vary */ unsigned instruction_size; union { struct arm_b_bl_bx_blx_instr b_bl_bx_blx; struct arm_data_proc_instr data_proc; struct arm_load_store_instr load_store; struct arm_load_store_multiple_instr load_store_multiple; } info; }; int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction); int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction); int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction); int arm_access_size(struct arm_instruction *instruction); #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000) >> 28]) #endif /* ARM_DISASSEMBLER_H */ openocd-0.9.0/src/target/arm11.c0000644000175000017500000010703612516456303013246 00000000000000/*************************************************************************** * Copyright (C) 2008 digenius technology GmbH. * * Michael Bruck * * * * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com * * * * Copyright (C) 2008 Georg Acher * * * * Copyright (C) 2009 David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "etm.h" #include "breakpoints.h" #include "arm11_dbgtap.h" #include "arm_simulator.h" #include #include "target_type.h" #include "algorithm.h" #include "register.h" #include "arm_opcodes.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ #endif static int arm11_step(struct target *target, int current, uint32_t address, int handle_breakpoints); /** Check and if necessary take control of the system * * \param arm11 Target state variable. */ static int arm11_check_init(struct arm11_common *arm11) { CHECK_RETVAL(arm11_read_DSCR(arm11)); if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) { LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); LOG_DEBUG("Bringing target into debug mode"); arm11->dscr |= DSCR_HALT_DBG_MODE; CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr)); /* add further reset initialization here */ arm11->simulate_reset_on_next_halt = true; if (arm11->dscr & DSCR_CORE_HALTED) { /** \todo TODO: this needs further scrutiny because * arm11_debug_entry() never gets called. (WHY NOT?) * As a result we don't read the actual register states from * the target. */ arm11->arm.target->state = TARGET_HALTED; arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr); } else { arm11->arm.target->state = TARGET_RUNNING; arm11->arm.target->debug_reason = DBG_REASON_NOTHALTED; } CHECK_RETVAL(arm11_sc7_clear_vbw(arm11)); } return ERROR_OK; } /** * Save processor state. This is called after a HALT instruction * succeeds, and on other occasions the processor enters debug mode * (breakpoint, watchpoint, etc). Caller has updated arm11->dscr. */ static int arm11_debug_entry(struct arm11_common *arm11) { int retval; arm11->arm.target->state = TARGET_HALTED; arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr); /* REVISIT entire cache should already be invalid !!! */ register_cache_invalidate(arm11->arm.core_cache); /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */ /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */ arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL); if (arm11->is_wdtr_saved) { arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; arm11_setup_field(arm11, 32, NULL, &arm11->saved_wdtr, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, TAP_DRPAUSE); } /* DSCR: set the Execute ARM instruction enable bit. * * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", * but not to issue ITRs(?). The ARMv7 arch spec says it's required * for executing instructions via ITR. */ CHECK_RETVAL(arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr)); /* From the spec: Before executing any instruction in debug state you have to drain the write buffer. This ensures that no imprecise Data Aborts can return at a later point:*/ /** \todo TODO: Test drain write buffer. */ #if 0 while (1) { /* MRC p14,0,R0,c5,c10,0 */ /* arm11_run_instr_no_data1(arm11, / *0xee150e1a* /0xe320f000); */ /* mcr 15, 0, r0, cr7, cr10, {4} */ arm11_run_instr_no_data1(arm11, 0xee070f9a); uint32_t dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x", dscr); if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) { arm11_run_instr_no_data1(arm11, 0xe320f000); dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr); break; } } #endif /* Save registers. * * NOTE: ARM1136 TRM suggests saving just R0 here now, then * CPSR and PC after the rDTR stuff. We do it all at once. */ retval = arm_dpm_read_current_registers(&arm11->dpm); if (retval != ERROR_OK) LOG_ERROR("DPM REG READ -- fail"); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */ arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL); if (arm11->is_rdtr_saved) { /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */ retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &arm11->saved_rdtr); if (retval != ERROR_OK) return retval; } /* REVISIT Now that we've saved core state, there's may also * be MMU and cache state to care about ... */ if (arm11->simulate_reset_on_next_halt) { arm11->simulate_reset_on_next_halt = false; LOG_DEBUG("Reset c1 Control Register"); /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */ /* MCR p15,0,R0,c1,c0,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0); if (retval != ERROR_OK) return retval; } if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) { uint32_t wfar; /* MRC p15, 0, , c6, c0, 1 ; Read WFAR */ retval = arm11_run_instr_data_from_core_via_r0(arm11, ARMV4_5_MRC(15, 0, 0, 6, 0, 1), &wfar); if (retval != ERROR_OK) return retval; arm_dpm_report_wfar(arm11->arm.dpm, wfar); } retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; return ERROR_OK; } /** * Restore processor state. This is called in preparation for * the RESTART function. */ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp) { int retval; /* See e.g. ARM1136 TRM, "14.8.5 Leaving Debug state" */ /* NOTE: the ARM1136 TRM suggests restoring all registers * except R0/PC/CPSR right now. Instead, we do them all * at once, just a bit later on. */ /* REVISIT once we start caring about MMU and cache state, * address it here ... */ /* spec says clear wDTR and rDTR; we assume they are clear as otherwise our programming would be sloppy */ { CHECK_RETVAL(arm11_read_DSCR(arm11)); if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL)) { /* The wDTR/rDTR two registers that are used to send/receive data to/from the core in tandem with corresponding instruction codes that are written into the core. The RDTR FULL/WDTR FULL flag indicates that the registers hold data that was written by one side (CPU or JTAG) and not read out by the other side. */ LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)", (unsigned) arm11->dscr); return ERROR_FAIL; } } /* maybe restore original wDTR */ if (arm11->is_wdtr_saved) { retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* MCR p14,0,R0,c0,c5,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, arm11->saved_wdtr); if (retval != ERROR_OK) return retval; retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; } /* restore CPSR, PC, and R0 ... after flushing any modified * registers. */ CHECK_RETVAL(arm_dpm_write_dirty_registers(&arm11->dpm, bpwp)); CHECK_RETVAL(arm11_bpwp_flush(arm11)); register_cache_invalidate(arm11->arm.core_cache); /* restore DSCR */ CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr)); /* maybe restore rDTR */ if (arm11->is_rdtr_saved) { arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; uint8_t Ready = 0; /* ignored */ uint8_t Valid = 0; /* ignored */ arm11_setup_field(arm11, 32, &arm11->saved_rdtr, NULL, chain5_fields + 0); arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1); arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain5_fields), chain5_fields, TAP_DRPAUSE); } /* now processor is ready to RESTART */ return ERROR_OK; } /* poll current target status */ static int arm11_poll(struct target *target) { int retval; struct arm11_common *arm11 = target_to_arm11(target); CHECK_RETVAL(arm11_check_init(arm11)); if (arm11->dscr & DSCR_CORE_HALTED) { if (target->state != TARGET_HALTED) { enum target_state old_state = target->state; LOG_DEBUG("enter TARGET_HALTED"); retval = arm11_debug_entry(arm11); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, (old_state == TARGET_DEBUG_RUNNING) ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED); } } else { if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) { LOG_DEBUG("enter TARGET_RUNNING"); target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; } } return ERROR_OK; } /* architecture specific status reply */ static int arm11_arch_state(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); int retval; retval = arm_arch_state(target); /* REVISIT also display ARM11-specific MMU and cache status ... */ if (target->debug_reason == DBG_REASON_WATCHPOINT) LOG_USER("Watchpoint triggered at PC %#08x", (unsigned) arm11->dpm.wp_pc); return retval; } /* target execution control */ static int arm11_halt(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_UNKNOWN) arm11->simulate_reset_on_next_halt = true; if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); int i = 0; while (1) { CHECK_RETVAL(arm11_read_DSCR(arm11)); if (arm11->dscr & DSCR_CORE_HALTED) break; long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } enum target_state old_state = target->state; CHECK_RETVAL(arm11_debug_entry(arm11)); CHECK_RETVAL( target_call_event_callbacks(target, old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED)); return ERROR_OK; } static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address) { void *value = arm11->arm.pc->value; if (!current) buf_set_u32(value, 0, 32, address); else address = buf_get_u32(value, 0, 32); return address; } static int arm11_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */ /* current, address, handle_breakpoints, debug_execution); */ struct arm11_common *arm11 = target_to_arm11(target); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } address = arm11_nextpc(arm11, current, address); LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); /* clear breakpoints/watchpoints and VCR*/ CHECK_RETVAL(arm11_sc7_clear_vbw(arm11)); if (!debug_execution) target_free_all_working_areas(target); /* Should we skip over breakpoints matching the PC? */ if (handle_breakpoints) { struct breakpoint *bp; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { LOG_DEBUG("must step over %08" PRIx32 "", bp->address); arm11_step(target, 1, 0, 0); break; } } } /* activate all breakpoints */ if (true) { struct breakpoint *bp; unsigned brp_num = 0; for (bp = target->breakpoints; bp; bp = bp->next) { struct arm11_sc7_action brp[2]; brp[0].write = 1; brp[0].address = ARM11_SC7_BVR0 + brp_num; brp[0].value = bp->address; brp[1].write = 1; brp[1].address = ARM11_SC7_BCR0 + brp_num; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21); CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp))); LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num, bp->address); brp_num++; } if (arm11->vcr) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr)); } /* activate all watchpoints and breakpoints */ CHECK_RETVAL(arm11_leave_debug_state(arm11, true)); arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); int i = 0; while (1) { CHECK_RETVAL(arm11_read_DSCR(arm11)); LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); if (arm11->dscr & DSCR_CORE_RESTARTED) break; long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) target->state = TARGET_RUNNING; else target->state = TARGET_DEBUG_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); return ERROR_OK; } static int arm11_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } struct arm11_common *arm11 = target_to_arm11(target); address = arm11_nextpc(arm11, current, address); LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); /** \todo TODO: Thumb not supported here */ uint32_t next_instruction; CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction)); /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping BKPT %08" PRIx32, address); } /* skip over Wait for interrupt / Standby * mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping WFI %08" PRIx32, address); } /* ignore B to self */ else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe) LOG_DEBUG("Not stepping jump to self"); else { /** \todo TODO: check if break-/watchpoints make any sense at all in combination * with this. */ /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively * the VCR might be something worth looking into. */ /* Set up breakpoint for stepping */ struct arm11_sc7_action brp[2]; brp[0].write = 1; brp[0].address = ARM11_SC7_BVR0; brp[1].write = 1; brp[1].address = ARM11_SC7_BCR0; if (arm11->hardware_step) { /* Hardware single stepping ("instruction address * mismatch") is used if enabled. It's not quite * exactly "run one instruction"; "branch to here" * loops won't break, neither will some other cases, * but it's probably the best default. * * Hardware single stepping isn't supported on v6 * debug modules. ARM1176 and v7 can support it... * * FIXME Thumb stepping likely needs to use 0x03 * or 0xc0 byte masks, not 0x0f. */ brp[0].value = address; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21); } else { /* Sets a breakpoint on the next PC, as calculated * by instruction set simulation. * * REVISIT stepping Thumb on ARM1156 requires Thumb2 * support from the simulator. */ uint32_t next_pc; int retval; retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) return retval; brp[0].value = next_pc; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21); } CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp))); /* resume */ if (arm11->step_irq_enable) /* this disable should be redundant ... */ arm11->dscr &= ~DSCR_INT_DIS; else arm11->dscr |= DSCR_INT_DIS; CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints)); arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); /* wait for halt */ int i = 0; while (1) { const uint32_t mask = DSCR_CORE_RESTARTED | DSCR_CORE_HALTED; CHECK_RETVAL(arm11_read_DSCR(arm11)); LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr); if ((arm11->dscr & mask) == mask) break; long long then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING( "Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } /* clear breakpoint */ CHECK_RETVAL(arm11_sc7_clear_vbw(arm11)); /* save state */ CHECK_RETVAL(arm11_debug_entry(arm11)); /* restore default state */ arm11->dscr &= ~DSCR_INT_DIS; } target->debug_reason = DBG_REASON_SINGLESTEP; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); return ERROR_OK; } static int arm11_assert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); /* optionally catch reset vector */ if (target->reset_halt && !(arm11->vcr & 1)) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); else if (jtag_get_reset_config() & RESET_HAS_SRST) { /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ jtag_add_reset(0, 1); } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* registers are now invalid */ register_cache_invalidate(arm11->arm.core_cache); target->state = TARGET_RESET; return ERROR_OK; } /* * - There is another bug in the arm11 core. (iMX31 specific again?) * When you generate an access to external logic (for example DDR * controller via AHB bus) and that block is not configured (perhaps * it is still held in reset), that transaction will never complete. * This will hang arm11 core but it will also hang JTAG controller. * Nothing short of srst assertion will bring it out of this. */ static int arm11_deassert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); int retval; /* be certain SRST is off */ jtag_add_reset(0, 0); /* WORKAROUND i.MX31 problems: SRST goofs the TAP, and resets * at least DSCR. OMAP24xx doesn't show that problem, though * SRST-only reset seems to be problematic for other reasons. * (Secure boot sequences being one likelihood!) */ jtag_add_tlr(); CHECK_RETVAL(arm11_poll(target)); if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } } /* maybe restore vector catch config */ if (target->reset_halt && !(arm11->vcr & 1)) CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr)); return ERROR_OK; } /* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) * count: number of items of * * arm11_config_memrw_no_increment - in the future we may want to be able * to read/write a range of data to a "port". a "port" is an action on * read memory address for some peripheral. */ static int arm11_read_memory_inner(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer, bool arm11_config_memrw_no_increment) { /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment *problems */ int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count); struct arm11_common *arm11 = target_to_arm11(target); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* MRC p14,0,r0,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); if (retval != ERROR_OK) return retval; switch (size) { case 1: arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* ldrb r1, [r0], #1 */ /* ldrb r1, [r0] */ CHECK_RETVAL(arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000)); uint32_t res; /* MCR p14,0,R1,c0,c5,0 */ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1)); *buffer++ = res; } break; case 2: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* ldrh r1, [r0], #2 */ CHECK_RETVAL(arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0)); uint32_t res; /* MCR p14,0,R1,c0,c5,0 */ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1)); uint16_t svalue = res; memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t)); } break; } case 4: { uint32_t instr = !arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00; /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t *)(void *)buffer; /* LDC p14,c5,[R0],#4 */ /* LDC p14,c5,[R0] */ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, instr, words, count)); break; } } return arm11_run_instr_data_finish(arm11); } static int arm11_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return arm11_read_memory_inner(target, address, size, count, buffer, false); } /* * no_increment - in the future we may want to be able * to read/write a range of data to a "port". a "port" is an action on * read memory address for some peripheral. */ static int arm11_write_memory_inner(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer, bool no_increment) { int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count); struct arm11_common *arm11 = target_to_arm11(target); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* load r0 with buffer address * MRC p14,0,r0,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); if (retval != ERROR_OK) return retval; /* burst writes are not used for single words as those may well be * reset init script writes. * * The other advantage is that as burst writes are default, we'll * now exercise both burst and non-burst code paths with the * default settings, increasing code coverage. */ bool burst = arm11->memwrite_burst && (count > 1); switch (size) { case 1: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* load r1 from DCC with byte data */ /* MRC p14,0,r1,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++); if (retval != ERROR_OK) return retval; /* write r1 to memory */ /* strb r1, [r0], #1 */ /* strb r1, [r0] */ retval = arm11_run_instr_no_data1(arm11, !no_increment ? 0xe4c01001 : 0xe5c01000); if (retval != ERROR_OK) return retval; } break; } case 2: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { uint16_t value; memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t)); /* load r1 from DCC with halfword data */ /* MRC p14,0,r1,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value); if (retval != ERROR_OK) return retval; /* write r1 to memory */ /* strh r1, [r0], #2 */ /* strh r1, [r0] */ retval = arm11_run_instr_no_data1(arm11, !no_increment ? 0xe0c010b2 : 0xe1c010b0); if (retval != ERROR_OK) return retval; } break; } case 4: { /* stream word data through DCC directly to memory */ /* increment: STC p14,c5,[R0],#4 */ /* no increment: STC p14,c5,[R0]*/ uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00; /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t *)(void *)buffer; /* "burst" here just means trusting each instruction executes * fully before we run the next one: per-word roundtrips, to * check the Ready flag, are not used. */ if (!burst) retval = arm11_run_instr_data_to_core(arm11, instr, words, count); else retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count); if (retval != ERROR_OK) return retval; break; } } /* r0 verification */ if (!no_increment) { uint32_t r0; /* MCR p14,0,R0,c0,c5,0 */ retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1); if (retval != ERROR_OK) return retval; if (address + size * count != r0) { LOG_ERROR("Data transfer failed. Expected end " "address 0x%08x, got 0x%08x", (unsigned) (address + size * count), (unsigned) r0); if (burst) LOG_ERROR( "use 'arm11 memwrite burst disable' to disable fast burst mode"); if (arm11->memwrite_error_fatal) return ERROR_FAIL; } } return arm11_run_instr_data_finish(arm11); } static int arm11_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { /* pointer increment matters only for multi-unit writes ... * not e.g. to a "reset the chip" controller. */ return arm11_write_memory_inner(target, address, size, count, buffer, count == 1); } /* target break-/watchpoint control * rw: 0 = write, 1 = read, 2 = access */ static int arm11_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm11_common *arm11 = target_to_arm11(target); #if 0 if (breakpoint->type == BKPT_SOFT) { LOG_INFO("sw breakpoint requested, but software breakpoints not enabled"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } #endif if (!arm11->free_brps) { LOG_DEBUG("no breakpoint unit available for hardware breakpoint"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->length != 4) { LOG_DEBUG("only breakpoints of four bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } arm11->free_brps--; return ERROR_OK; } static int arm11_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm11_common *arm11 = target_to_arm11(target); arm11->free_brps++; return ERROR_OK; } static int arm11_target_create(struct target *target, Jim_Interp *interp) { struct arm11_common *arm11; if (target->tap == NULL) return ERROR_FAIL; if (target->tap->ir_length != 5) { LOG_ERROR("'target arm11' expects IR LENGTH = 5"); return ERROR_COMMAND_SYNTAX_ERROR; } arm11 = calloc(1, sizeof *arm11); if (!arm11) return ERROR_FAIL; arm11->arm.core_type = ARM_MODE_ANY; arm_init_arch_info(target, &arm11->arm); arm11->jtag_info.tap = target->tap; arm11->jtag_info.scann_size = 5; arm11->jtag_info.scann_instr = ARM11_SCAN_N; arm11->jtag_info.cur_scan_chain = ~0; /* invalid/unknown */ arm11->jtag_info.intest_instr = ARM11_INTEST; arm11->memwrite_burst = true; arm11->memwrite_error_fatal = true; return ERROR_OK; } static int arm11_init_target(struct command_context *cmd_ctx, struct target *target) { /* Initialize anything we can set up without talking to the target */ return ERROR_OK; } /* talk to the target and set things up */ static int arm11_examine(struct target *target) { int retval; char *type; struct arm11_common *arm11 = target_to_arm11(target); uint32_t didr, device_id; uint8_t implementor; /* FIXME split into do-first-time and do-every-time logic ... */ /* check IDCODE */ arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT); struct scan_field idcode_field; arm11_setup_field(arm11, 32, NULL, &device_id, &idcode_field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &idcode_field, TAP_DRPAUSE); /* check DIDR */ arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain0_fields[2]; arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0); arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE( chain0_fields), chain0_fields, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); /* assume the manufacturer id is ok; check the part # */ switch ((device_id >> 12) & 0xFFFF) { case 0x7B36: type = "ARM1136"; break; case 0x7B37: type = "ARM11 MPCore"; break; case 0x7B56: type = "ARM1156"; break; case 0x7B76: arm11->arm.core_type = ARM_MODE_MON; /* NOTE: could default arm11->hardware_step to true */ type = "ARM1176"; break; default: LOG_ERROR("unexpected ARM11 ID code"); return ERROR_FAIL; } LOG_INFO("found %s", type); /* unlikely this could ever fail, but ... */ switch ((didr >> 16) & 0x0F) { case ARM11_DEBUG_V6: case ARM11_DEBUG_V61: /* supports security extensions */ break; default: LOG_ERROR("Only ARM v6 and v6.1 debug supported."); return ERROR_FAIL; } arm11->brp = ((didr >> 24) & 0x0F) + 1; /** \todo TODO: reserve one brp slot if we allow breakpoints during step */ arm11->free_brps = arm11->brp; LOG_DEBUG("IDCODE %08" PRIx32 " IMPLEMENTOR %02x DIDR %08" PRIx32, device_id, implementor, didr); /* Build register cache "late", after target_init(), since we * want to know if this core supports Secure Monitor mode. */ if (!target_was_examined(target)) CHECK_RETVAL(arm11_dpm_init(arm11, didr)); /* as a side-effect this reads DSCR and thus * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag * as suggested by the spec. */ retval = arm11_check_init(arm11); if (retval != ERROR_OK) return retval; /* ETM on ARM11 still uses original scanchain 6 access mode */ if (arm11->arm.etm && !target_was_examined(target)) { *register_get_last_cache_p(&target->reg_cache) = etm_build_reg_cache(target, &arm11->jtag_info, arm11->arm.etm); CHECK_RETVAL(etm_setup(target)); } target_set_examined(target); return ERROR_OK; } #define ARM11_BOOL_WRAPPER(name, print_name) \ COMMAND_HANDLER(arm11_handle_bool_ ## name) \ { \ struct target *target = get_current_target(CMD_CTX); \ struct arm11_common *arm11 = target_to_arm11(target); \ \ return CALL_COMMAND_HANDLER(handle_command_parse_bool, \ &arm11->name, print_name); \ } ARM11_BOOL_WRAPPER(memwrite_burst, "memory write burst mode") ARM11_BOOL_WRAPPER(memwrite_error_fatal, "fatal error mode for memory writes") ARM11_BOOL_WRAPPER(step_irq_enable, "IRQs while stepping") ARM11_BOOL_WRAPPER(hardware_step, "hardware single step") /* REVISIT handle the VCR bits like other ARMs: use symbols for * input and output values. */ COMMAND_HANDLER(arm11_handle_vcr) { struct target *target = get_current_target(CMD_CTX); struct arm11_common *arm11 = target_to_arm11(target); switch (CMD_ARGC) { case 0: break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11->vcr); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } LOG_INFO("VCR 0x%08" PRIx32 "", arm11->vcr); return ERROR_OK; } static const struct command_registration arm11_mw_command_handlers[] = { { .name = "burst", .handler = arm11_handle_bool_memwrite_burst, .mode = COMMAND_ANY, .help = "Display or modify flag controlling potentially " "risky fast burst mode (default: enabled)", .usage = "['enable'|'disable']", }, { .name = "error_fatal", .handler = arm11_handle_bool_memwrite_error_fatal, .mode = COMMAND_ANY, .help = "Display or modify flag controlling transfer " "termination on transfer errors" " (default: enabled)", .usage = "['enable'|'disable']", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration arm11_any_command_handlers[] = { { /* "hardware_step" is only here to check if the default * simulate + breakpoint implementation is broken. * TEMPORARY! NOT DOCUMENTED! */ .name = "hardware_step", .handler = arm11_handle_bool_hardware_step, .mode = COMMAND_ANY, .help = "DEBUG ONLY - Hardware single stepping" " (default: disabled)", .usage = "['enable'|'disable']", }, { .name = "memwrite", .mode = COMMAND_ANY, .help = "memwrite command group", .usage = "", .chain = arm11_mw_command_handlers, }, { .name = "step_irq_enable", .handler = arm11_handle_bool_step_irq_enable, .mode = COMMAND_ANY, .help = "Display or modify flag controlling interrupt " "enable while stepping (default: disabled)", .usage = "['enable'|'disable']", }, { .name = "vcr", .handler = arm11_handle_vcr, .mode = COMMAND_ANY, .help = "Display or modify Vector Catch Register", .usage = "[value]", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration arm11_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = etm_command_handlers, }, { .name = "arm11", .mode = COMMAND_ANY, .help = "ARM11 command group", .usage = "", .chain = arm11_any_command_handlers, }, COMMAND_REGISTRATION_DONE }; /** Holds methods for ARM11xx targets. */ struct target_type arm11_target = { .name = "arm11", .poll = arm11_poll, .arch_state = arm11_arch_state, .halt = arm11_halt, .resume = arm11_resume, .step = arm11_step, .assert_reset = arm11_assert_reset, .deassert_reset = arm11_deassert_reset, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm11_read_memory, .write_memory = arm11_write_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .add_breakpoint = arm11_add_breakpoint, .remove_breakpoint = arm11_remove_breakpoint, .run_algorithm = armv4_5_run_algorithm, .commands = arm11_command_handlers, .target_create = arm11_target_create, .init_target = arm11_init_target, .examine = arm11_examine, }; openocd-0.9.0/src/target/arm11.h0000644000175000017500000000752012315575361013253 00000000000000/*************************************************************************** * Copyright (C) 2008 digenius technology GmbH. * * Michael Bruck * * * * Copyright (C) 2008 Georg Acher * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM11_H #define ARM11_H #include "arm.h" #include "arm_dpm.h" #define ARM11_TAP_DEFAULT TAP_INVALID #define CHECK_RETVAL(action) \ do { \ int __retval = (action); \ if (__retval != ERROR_OK) { \ LOG_DEBUG("error while calling \"%s\"", \ # action); \ return __retval; \ } \ } while (0) /* bits from ARMv7 DIDR */ enum arm11_debug_version { ARM11_DEBUG_V6 = 0x01, ARM11_DEBUG_V61 = 0x02, ARM11_DEBUG_V7 = 0x03, ARM11_DEBUG_V7_CP14 = 0x04, }; struct arm11_common { struct arm arm; /** Debug module state. */ struct arm_dpm dpm; struct arm11_sc7_action *bpwp_actions; unsigned bpwp_n; size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */ size_t free_brps; /**< Number of breakpoints allocated */ uint32_t dscr; /**< Last retrieved DSCR value. */ uint32_t saved_rdtr; uint32_t saved_wdtr; bool is_rdtr_saved; bool is_wdtr_saved; bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt **/ /* Per-core configurable options. * NOTE that several of these boolean options should not exist * once the relevant code is known to work correctly. */ bool memwrite_burst; bool memwrite_error_fatal; bool step_irq_enable; bool hardware_step; /** Configured Vector Catch Register settings. */ uint32_t vcr; struct arm_jtag jtag_info; }; static inline struct arm11_common *target_to_arm11(struct target *target) { return container_of(target->arch_info, struct arm11_common, arm); } /** * ARM11 DBGTAP instructions * * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html */ enum arm11_instructions { ARM11_EXTEST = 0x00, ARM11_SCAN_N = 0x02, ARM11_RESTART = 0x04, ARM11_HALT = 0x08, ARM11_INTEST = 0x0C, ARM11_ITRSEL = 0x1D, ARM11_IDCODE = 0x1E, ARM11_BYPASS = 0x1F, }; enum arm11_sc7 { ARM11_SC7_NULL = 0, ARM11_SC7_VCR = 7, ARM11_SC7_PC = 8, ARM11_SC7_BVR0 = 64, ARM11_SC7_BCR0 = 80, ARM11_SC7_WVR0 = 96, ARM11_SC7_WCR0 = 112, }; #endif /* ARM11_H */ openocd-0.9.0/src/target/nds32_v2.c0000644000175000017500000005452712315575361013676 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "breakpoints.h" #include "nds32_insn.h" #include "nds32_reg.h" #include "nds32_edm.h" #include "nds32_cmd.h" #include "nds32_v2.h" #include "nds32_aice.h" #include "target_type.h" static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no) { uint32_t max_level = nds32->max_interrupt_level; uint32_t cur_level = nds32->current_interrupt_level; if ((1 <= cur_level) && (cur_level < max_level)) { if (IR0 == reg_no) { LOG_DEBUG("Map PSW to IPSW"); return IR1; } else if (PC == reg_no) { LOG_DEBUG("Map PC to IPC"); return IR9; } } else if ((2 <= cur_level) && (cur_level < max_level)) { if (R26 == reg_no) { LOG_DEBUG("Mapping P0 to P_P0"); return IR12; } else if (R27 == reg_no) { LOG_DEBUG("Mapping P1 to P_P1"); return IR13; } else if (IR1 == reg_no) { LOG_DEBUG("Mapping IPSW to P_IPSW"); return IR2; } else if (IR4 == reg_no) { LOG_DEBUG("Mapping EVA to P_EVA"); return IR5; } else if (IR6 == reg_no) { LOG_DEBUG("Mapping ITYPE to P_ITYPE"); return IR7; } else if (IR9 == reg_no) { LOG_DEBUG("Mapping IPC to P_IPC"); return IR10; } } else if (cur_level == max_level) { if (PC == reg_no) { LOG_DEBUG("Mapping PC to O_IPC"); return IR11; } } return reg_no; } static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason) { uint32_t val_itype; struct aice_port_s *aice = target_to_aice(nds32->target); aice_read_register(aice, IR6, &val_itype); *reason = val_itype & 0x0F; return ERROR_OK; } static int nds32_v2_activate_hardware_breakpoint(struct target *target) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; int32_t hbr_index = 0; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) { /* already set at nds32_v2_add_breakpoint() */ continue; } else if (bp->type == BKPT_HARD) { /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0); /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0); if (nds32_v2->nds32.memory.address_translation) /* enable breakpoint (virtual address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2); else /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, bp->address); hbr_index++; } else { return ERROR_FAIL; } } return ERROR_OK; } static int nds32_v2_deactivate_hardware_breakpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; int32_t hbr_index = 0; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) continue; else if (bp->type == BKPT_HARD) /* disable breakpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0); else return ERROR_FAIL; LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, bp->address); hbr_index++; } return ERROR_OK; } static int nds32_v2_activate_hardware_watchpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); struct watchpoint *wp; int32_t wp_num = nds32_v2->next_hbr_index; uint32_t wp_config = 0; for (wp = target->watchpoints; wp; wp = wp->next) { wp_num--; wp->mask = wp->length - 1; if ((wp->address % wp->length) != 0) wp->mask = (wp->mask << 1) + 1; if (wp->rw == WPT_READ) wp_config = 0x3; else if (wp->rw == WPT_WRITE) wp_config = 0x5; else if (wp->rw == WPT_ACCESS) wp_config = 0x7; /* set/unset physical address bit of BPCn according to PSW.DT */ if (nds32_v2->nds32.memory.address_translation == false) wp_config |= 0x8; /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num, wp->address - (wp->address % wp->length)); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask); /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); } return ERROR_OK; } static int nds32_v2_deactivate_hardware_watchpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); int32_t wp_num = nds32_v2->next_hbr_index; struct watchpoint *wp; for (wp = target->watchpoints; wp; wp = wp->next) { wp_num--; /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); } return ERROR_OK; } static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2) { struct nds32 *nds32 = &(nds32_v2->nds32); struct aice_port_s *aice = target_to_aice(nds32->target); uint32_t val_ir0; uint32_t val_ir1; uint32_t val_ir2; uint32_t modified_psw; /* Save interrupt level */ aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */ /* backup $IR0 */ nds32_v2->backup_ir0 = val_ir0; nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3; if (nds32_reach_max_interrupt_level(nds32)) { LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->", nds32->current_interrupt_level); /* decrease interrupt level */ modified_psw = val_ir0 - 0x2; /* disable GIE, IT, DT, HSS */ modified_psw &= (~0x8C1); aice_write_register(aice, IR0, modified_psw); return ERROR_OK; } /* There is a case that single step also trigger another interrupt, then HSS bit in psw(ir0) will push to ipsw(ir1). Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2 Therefore, HSS bit in p_ipsw(ir2) also need clear. Only update $ir2 as current interrupt level is 2, because $ir2 will be random value if the target never reaches interrupt level 2. */ if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) { aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */ val_ir2 &= ~(0x01 << 11); aice_write_register(aice, IR2, val_ir2); } /* get origianl DT bit and set to current state let debugger has same memory view PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */ aice_read_register(aice, IR1, &val_ir1); modified_psw = val_ir0 | (val_ir1 & 0x80); aice_write_register(aice, IR0, modified_psw); return ERROR_OK; } static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2) { struct nds32 *nds32 = &(nds32_v2->nds32); struct aice_port_s *aice = target_to_aice(nds32->target); /* restore origin $IR0 */ aice_write_register(aice, IR0, nds32_v2->backup_ir0); return ERROR_OK; } /** * Save processor state. This is called after a HALT instruction * succeeds, and on other occasions the processor enters debug mode * (breakpoint, watchpoint, etc). */ static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint) { LOG_DEBUG("nds32_v2_debug_entry"); if (nds32->virtual_hosting) LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported " "under V1/V2 architecture. -->"); enum target_state backup_state = nds32->target->state; nds32->target->state = TARGET_HALTED; if (nds32->init_arch_info_after_halted == false) { /* init architecture info according to config registers */ CHECK_RETVAL(nds32_config(nds32)); nds32->init_arch_info_after_halted = true; } /* REVISIT entire cache should already be invalid !!! */ register_cache_invalidate(nds32->core_cache); /* deactivate all hardware breakpoints */ CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target)); if (enable_watchpoint) CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target)); if (ERROR_OK != nds32_examine_debug_reason(nds32)) { nds32->target->state = backup_state; /* re-activate all hardware breakpoints & watchpoints */ CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target)); if (enable_watchpoint) { /* activate all watchpoints */ CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target)); } return ERROR_FAIL; } /* check interrupt level before .full_context(), because * get_mapped_reg() in nds32_full_context() needs current_interrupt_level * information */ struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target); nds32_v2_check_interrupt_stack(nds32_v2); /* Save registers. */ nds32_full_context(nds32); return ERROR_OK; } /* target request support */ static int nds32_v2_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { /* AndesCore could use DTR register to communicate with OpenOCD * to output messages * Target data will be put in buffer * The format of DTR is as follow * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd * target_req_cmd has three possible values: * TARGET_REQ_TRACEMSG * TARGET_REQ_DEBUGMSG * TARGET_REQ_DEBUGCHAR * if size == 0, target will call target_asciimsg(), * else call target_hexmsg() */ LOG_WARNING("Not implemented: %s", __func__); return ERROR_OK; } /** * Restore processor state. */ static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint) { LOG_DEBUG("nds32_v2_leave_debug_state"); struct target *target = nds32->target; /* activate all hardware breakpoints */ CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target)); if (enable_watchpoint) { /* activate all watchpoints */ CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target)); } /* restore interrupt stack */ struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target); nds32_v2_restore_interrupt_stack(nds32_v2); /* restore PSW, PC, and R0 ... after flushing any modified * registers. */ CHECK_RETVAL(nds32_restore_context(target)); register_cache_invalidate(nds32->core_cache); return ERROR_OK; } static int nds32_v2_deassert_reset(struct target *target) { int retval; CHECK_RETVAL(nds32_poll(target)); if (target->state != TARGET_HALTED) { /* reset only */ LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int nds32_v2_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } static int nds32_v2_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); struct nds32 *nds32 = &(nds32_v2->nds32); int result; if (breakpoint->type == BKPT_HARD) { /* check hardware resource */ if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) { LOG_WARNING("<-- TARGET WARNING! Insert too many hardware " "breakpoints/watchpoints! The limit of " "combined hardware breakpoints/watchpoints " "is %" PRId32 ". -->", nds32_v2->n_hbr); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware breakpoint */ nds32_v2->next_hbr_index++; /* hardware breakpoint insertion occurs before 'continue' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { result = nds32_add_software_breakpoint(target, breakpoint); if (ERROR_OK != result) { /* auto convert to hardware breakpoint if failed */ if (nds32->auto_convert_hw_bp) { /* convert to hardware breakpoint */ breakpoint->type = BKPT_HARD; return nds32_v2_add_breakpoint(target, breakpoint); } } return result; } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v2_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); if (breakpoint->type == BKPT_HARD) { if (nds32_v2->next_hbr_index <= 0) return ERROR_FAIL; /* update next place to put hardware breakpoint */ nds32_v2->next_hbr_index--; /* hardware breakpoint removal occurs after 'halted' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { return nds32_remove_software_breakpoint(target, breakpoint); } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v2_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); /* check hardware resource */ if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) { LOG_WARNING("<-- TARGET WARNING! Insert too many hardware " "breakpoints/watchpoints! The limit of " "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware watchpoint */ nds32_v2->next_hbr_index++; return ERROR_OK; } static int nds32_v2_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); if (nds32_v2->next_hbr_index <= 0) return ERROR_FAIL; /* update next place to put hardware breakpoint */ nds32_v2->next_hbr_index--; return ERROR_OK; } static int nds32_v2_get_exception_address(struct nds32 *nds32, uint32_t *address, uint32_t reason) { struct aice_port_s *aice = target_to_aice(nds32->target); aice_read_register(aice, IR4, address); /* read $EVA directly */ /* TODO: hit multiple watchpoints */ return ERROR_OK; } /** * find out which watchpoint hits * get exception address and compare the address to watchpoints */ static int nds32_v2_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) { uint32_t exception_address; struct watchpoint *wp; static struct watchpoint scan_all_watchpoint; struct nds32 *nds32 = target_to_nds32(target); scan_all_watchpoint.address = 0; scan_all_watchpoint.rw = WPT_WRITE; scan_all_watchpoint.next = 0; scan_all_watchpoint.unique_id = 0x5CA8; exception_address = nds32->watched_address; if (exception_address == 0) { /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */ *hit_watchpoint = &scan_all_watchpoint; return ERROR_OK; } for (wp = target->watchpoints; wp; wp = wp->next) { if (((exception_address ^ wp->address) & (~wp->mask)) == 0) { /* TODO: dispel false match */ *hit_watchpoint = wp; return ERROR_OK; } } return ERROR_FAIL; } static int nds32_v2_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } static int nds32_v2_target_create(struct target *target, Jim_Interp *interp) { struct nds32_v2_common *nds32_v2; nds32_v2 = calloc(1, sizeof(*nds32_v2)); if (!nds32_v2) return ERROR_FAIL; nds32_v2->nds32.register_map = nds32_v2_register_mapping; nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason; nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry; nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state; nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address; nds32_init_arch_info(target, &(nds32_v2->nds32)); return ERROR_OK; } static int nds32_v2_init_target(struct command_context *cmd_ctx, struct target *target) { /* Initialize anything we can set up without talking to the target */ struct nds32 *nds32 = target_to_nds32(target); nds32_init(nds32); return ERROR_OK; } /* talk to the target and set things up */ static int nds32_v2_examine(struct target *target) { struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target); struct nds32 *nds32 = &(nds32_v2->nds32); struct aice_port_s *aice = target_to_aice(target); if (!target_was_examined(target)) { CHECK_RETVAL(nds32_edm_config(nds32)); if (nds32->reset_halt_as_examine) CHECK_RETVAL(nds32_reset_halt(nds32)); } uint32_t edm_cfg; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); /* get the number of hardware breakpoints */ nds32_v2->n_hbr = (edm_cfg & 0x7) + 1; nds32_v2->next_hbr_index = 0; LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target), nds32_v2->n_hbr); nds32->target->state = TARGET_RUNNING; nds32->target->debug_reason = DBG_REASON_NOTHALTED; target_set_examined(target); return ERROR_OK; } static int nds32_v2_translate_address(struct target *target, uint32_t *address) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); uint32_t physical_address; /* Following conditions need to do address translation * 1. BUS mode * 2. CPU mode under maximum interrupt level */ if ((NDS_MEMORY_ACC_BUS == memory->access_channel) || ((NDS_MEMORY_ACC_CPU == memory->access_channel) && nds32_reach_max_interrupt_level(nds32))) { if (ERROR_OK == target->type->virt2phys(target, *address, &physical_address)) *address = physical_address; else return ERROR_FAIL; } return ERROR_OK; } static int nds32_v2_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ nds32_v2_translate_address(target, &address); return nds32_read_buffer(target, address, size, buffer); } static int nds32_v2_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ nds32_v2_translate_address(target, &address); return nds32_write_buffer(target, address, size, buffer); } static int nds32_v2_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ nds32_v2_translate_address(target, &address); return nds32_read_memory(target, address, size, count, buffer); } static int nds32_v2_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); if ((NDS_MEMORY_ACC_CPU == memory->access_channel) && (target->state != TARGET_HALTED)) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ nds32_v2_translate_address(target, &address); return nds32_write_memory(target, address, size, count, buffer); } /** Holds methods for V2 targets. */ struct target_type nds32_v2_target = { .name = "nds32_v2", .poll = nds32_poll, .arch_state = nds32_arch_state, .target_request_data = nds32_v2_target_request_data, .halt = nds32_halt, .resume = nds32_resume, .step = nds32_step, .assert_reset = nds32_assert_reset, .deassert_reset = nds32_v2_deassert_reset, /* register access */ .get_gdb_reg_list = nds32_get_gdb_reg_list, /* memory access */ .read_buffer = nds32_v2_read_buffer, .write_buffer = nds32_v2_write_buffer, .read_memory = nds32_v2_read_memory, .write_memory = nds32_v2_write_memory, .checksum_memory = nds32_v2_checksum_memory, /* breakpoint/watchpoint */ .add_breakpoint = nds32_v2_add_breakpoint, .remove_breakpoint = nds32_v2_remove_breakpoint, .add_watchpoint = nds32_v2_add_watchpoint, .remove_watchpoint = nds32_v2_remove_watchpoint, .hit_watchpoint = nds32_v2_hit_watchpoint, /* MMU */ .mmu = nds32_mmu, .virt2phys = nds32_virtual_to_physical, .read_phys_memory = nds32_read_phys_memory, .write_phys_memory = nds32_write_phys_memory, .run_algorithm = nds32_v2_run_algorithm, .commands = nds32_command_handlers, .target_create = nds32_v2_target_create, .init_target = nds32_v2_init_target, .examine = nds32_v2_examine, }; openocd-0.9.0/src/target/nds32_v2.h0000644000175000017500000000364512315575361013676 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_V2_H__ #define __NDS32_V2_H__ #include "nds32.h" struct nds32_v2_common { struct nds32 nds32; uint32_t backup_ir0; /** number of hardware breakpoints */ int32_t n_hbr; /** next hardware breakpoint index */ /** increase from low index to high index */ int32_t next_hbr_index; }; static inline struct nds32_v2_common *target_to_nds32_v2(struct target *target) { return container_of(target->arch_info, struct nds32_v2_common, nds32); } #endif /* __NDS32_V2_H__ */ openocd-0.9.0/src/target/nds32_v3.c0000644000175000017500000003644212315575361013673 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "nds32_cmd.h" #include "nds32_aice.h" #include "nds32_v3.h" #include "nds32_v3_common.h" static int nds32_v3_activate_hardware_breakpoint(struct target *target) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; int32_t hbr_index = nds32_v3->next_hbr_index; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) { /* already set at nds32_v3_add_breakpoint() */ continue; } else if (bp->type == BKPT_HARD) { hbr_index--; /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0); /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0); if (nds32_v3->nds32.memory.address_translation) /* enable breakpoint (virtual address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2); else /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, bp->address); } else { return ERROR_FAIL; } } return ERROR_OK; } static int nds32_v3_deactivate_hardware_breakpoint(struct target *target) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct aice_port_s *aice = target_to_aice(target); struct breakpoint *bp; int32_t hbr_index = nds32_v3->next_hbr_index; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->type == BKPT_SOFT) { continue; } else if (bp->type == BKPT_HARD) { hbr_index--; /* disable breakpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0); } else { return ERROR_FAIL; } LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, bp->address); } return ERROR_OK; } static int nds32_v3_activate_hardware_watchpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct watchpoint *wp; int32_t wp_num = 0; uint32_t wp_config = 0; bool ld_stop, st_stop; if (nds32_v3->nds32.global_stop) ld_stop = st_stop = false; for (wp = target->watchpoints; wp; wp = wp->next) { if (wp_num < nds32_v3->used_n_wp) { wp->mask = wp->length - 1; if ((wp->address % wp->length) != 0) wp->mask = (wp->mask << 1) + 1; if (wp->rw == WPT_READ) wp_config = 0x3; else if (wp->rw == WPT_WRITE) wp_config = 0x5; else if (wp->rw == WPT_ACCESS) wp_config = 0x7; /* set/unset physical address bit of BPCn according to PSW.DT */ if (nds32_v3->nds32.memory.address_translation == false) wp_config |= 0x8; /* set address */ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num, wp->address - (wp->address % wp->length)); /* set mask */ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask); /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3->nds32.global_stop) { if (wp->rw == WPT_READ) ld_stop = true; else if (wp->rw == WPT_WRITE) st_stop = true; else if (wp->rw == WPT_ACCESS) ld_stop = st_stop = true; } } if (nds32_v3->nds32.global_stop) { uint32_t edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl); if (ld_stop) edm_ctl |= 0x10; if (st_stop) edm_ctl |= 0x20; aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl); } return ERROR_OK; } static int nds32_v3_deactivate_hardware_watchpoint(struct target *target) { struct aice_port_s *aice = target_to_aice(target); struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); int32_t wp_num = 0; struct watchpoint *wp; bool clean_global_stop = false; for (wp = target->watchpoints; wp; wp = wp->next) { if (wp_num < nds32_v3->used_n_wp) { /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3->nds32.global_stop) { clean_global_stop = true; } } if (clean_global_stop) { uint32_t edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl); edm_ctl = edm_ctl & (~0x30); aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl); } return ERROR_OK; } static int nds32_v3_check_interrupt_stack(struct nds32 *nds32) { uint32_t val_ir0; uint32_t value; /* Save interrupt level */ nds32_get_mapped_reg(nds32, IR0, &val_ir0); nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3; if (nds32_reach_max_interrupt_level(nds32)) LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->", nds32->current_interrupt_level); /* backup $ir4 & $ir6 to avoid suppressed exception overwrite */ nds32_get_mapped_reg(nds32, IR4, &value); nds32_get_mapped_reg(nds32, IR6, &value); return ERROR_OK; } static int nds32_v3_restore_interrupt_stack(struct nds32 *nds32) { uint32_t value; /* get backup value from cache */ /* then set back to make the register dirty */ nds32_get_mapped_reg(nds32, IR0, &value); nds32_set_mapped_reg(nds32, IR0, value); nds32_get_mapped_reg(nds32, IR4, &value); nds32_set_mapped_reg(nds32, IR4, value); nds32_get_mapped_reg(nds32, IR6, &value); nds32_set_mapped_reg(nds32, IR6, value); return ERROR_OK; } static int nds32_v3_deassert_reset(struct target *target) { int retval; struct aice_port_s *aice = target_to_aice(target); bool switch_to_v3_stack = false; uint32_t value_edm_ctl; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl); if (((value_edm_ctl >> 6) & 0x1) == 0) { /* reset to V2 EDM mode */ aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, value_edm_ctl | (0x1 << 6)); aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl); if (((value_edm_ctl >> 6) & 0x1) == 1) switch_to_v3_stack = true; } else switch_to_v3_stack = false; CHECK_RETVAL(nds32_poll(target)); if (target->state != TARGET_HALTED) { /* reset only */ LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } else { /* reset-halt */ struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct nds32 *nds32 = &(nds32_v3->nds32); uint32_t value; uint32_t interrupt_level; if (switch_to_v3_stack == true) { /* PSW.INTL-- */ nds32_get_mapped_reg(nds32, IR0, &value); interrupt_level = (value >> 1) & 0x3; interrupt_level--; value &= ~(0x6); value |= (interrupt_level << 1); value |= 0x400; /* set PSW.DEX */ nds32_set_mapped_reg(nds32, IR0, value); /* copy IPC to OIPC */ if ((interrupt_level + 1) < nds32->max_interrupt_level) { nds32_get_mapped_reg(nds32, IR9, &value); nds32_set_mapped_reg(nds32, IR11, value); } } } return ERROR_OK; } static int nds32_v3_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct nds32 *nds32 = &(nds32_v3->nds32); int result; if (breakpoint->type == BKPT_HARD) { /* check hardware resource */ if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) { LOG_WARNING("<-- TARGET WARNING! Insert too many " "hardware breakpoints/watchpoints! " "The limit of combined hardware " "breakpoints/watchpoints is %" PRId32 ". -->", nds32_v3->n_hbr); LOG_WARNING("<-- TARGET STATUS: Inserted number of " "hardware breakpoint: %" PRId32 ", hardware " "watchpoints: %" PRId32 ". -->", nds32_v3->next_hbr_index - nds32_v3->used_n_wp, nds32_v3->used_n_wp); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware breakpoint */ nds32_v3->next_hbr_index++; /* hardware breakpoint insertion occurs before 'continue' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { result = nds32_add_software_breakpoint(target, breakpoint); if (ERROR_OK != result) { /* auto convert to hardware breakpoint if failed */ if (nds32->auto_convert_hw_bp) { /* convert to hardware breakpoint */ breakpoint->type = BKPT_HARD; return nds32_v3_add_breakpoint(target, breakpoint); } } return result; } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v3_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); if (breakpoint->type == BKPT_HARD) { if (nds32_v3->next_hbr_index <= 0) return ERROR_FAIL; /* update next place to put hardware breakpoint */ nds32_v3->next_hbr_index--; /* hardware breakpoint removal occurs after 'halted' actually */ return ERROR_OK; } else if (breakpoint->type == BKPT_SOFT) { return nds32_remove_software_breakpoint(target, breakpoint); } else /* unrecognized breakpoint type */ return ERROR_FAIL; return ERROR_OK; } static int nds32_v3_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); /* check hardware resource */ if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) { /* No hardware resource */ if (nds32_v3->nds32.global_stop) { LOG_WARNING("<-- TARGET WARNING! The number of " "watchpoints exceeds the hardware " "resources. Stop at every load/store " "instruction to check for watchpoint matches. -->"); return ERROR_OK; } LOG_WARNING("<-- TARGET WARNING! Insert too many hardware " "breakpoints/watchpoints! The limit of combined " "hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v3->n_hbr); LOG_WARNING("<-- TARGET STATUS: Inserted number of " "hardware breakpoint: %" PRId32 ", hardware " "watchpoints: %" PRId32 ". -->", nds32_v3->next_hbr_index - nds32_v3->used_n_wp, nds32_v3->used_n_wp); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* update next place to put hardware watchpoint */ nds32_v3->next_hbr_index++; nds32_v3->used_n_wp++; return ERROR_OK; } static int nds32_v3_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); if (nds32_v3->next_hbr_index <= 0) { if (nds32_v3->nds32.global_stop) return ERROR_OK; return ERROR_FAIL; } /* update next place to put hardware breakpoint */ nds32_v3->next_hbr_index--; nds32_v3->used_n_wp--; return ERROR_OK; } struct nds32_v3_common_callback nds32_v3_common_callback = { .check_interrupt_stack = nds32_v3_check_interrupt_stack, .restore_interrupt_stack = nds32_v3_restore_interrupt_stack, .activate_hardware_breakpoint = nds32_v3_activate_hardware_breakpoint, .activate_hardware_watchpoint = nds32_v3_activate_hardware_watchpoint, .deactivate_hardware_breakpoint = nds32_v3_deactivate_hardware_breakpoint, .deactivate_hardware_watchpoint = nds32_v3_deactivate_hardware_watchpoint, }; static int nds32_v3_target_create(struct target *target, Jim_Interp *interp) { struct nds32_v3_common *nds32_v3; nds32_v3 = calloc(1, sizeof(*nds32_v3)); if (!nds32_v3) return ERROR_FAIL; nds32_v3_common_register_callback(&nds32_v3_common_callback); nds32_v3_target_create_common(target, &(nds32_v3->nds32)); return ERROR_OK; } /* talk to the target and set things up */ static int nds32_v3_examine(struct target *target) { struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target); struct nds32 *nds32 = &(nds32_v3->nds32); struct aice_port_s *aice = target_to_aice(target); if (!target_was_examined(target)) { CHECK_RETVAL(nds32_edm_config(nds32)); if (nds32->reset_halt_as_examine) CHECK_RETVAL(nds32_reset_halt(nds32)); } uint32_t edm_cfg; aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); /* get the number of hardware breakpoints */ nds32_v3->n_hbr = (edm_cfg & 0x7) + 1; /* low interference profiling */ if (edm_cfg & 0x100) nds32_v3->low_interference_profile = true; else nds32_v3->low_interference_profile = false; nds32_v3->next_hbr_index = 0; nds32_v3->used_n_wp = 0; LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target), nds32_v3->n_hbr); nds32->target->state = TARGET_RUNNING; nds32->target->debug_reason = DBG_REASON_NOTHALTED; target_set_examined(target); return ERROR_OK; } /** Holds methods for Andes1337 targets. */ struct target_type nds32_v3_target = { .name = "nds32_v3", .poll = nds32_poll, .arch_state = nds32_arch_state, .target_request_data = nds32_v3_target_request_data, .halt = nds32_halt, .resume = nds32_resume, .step = nds32_step, .assert_reset = nds32_assert_reset, .deassert_reset = nds32_v3_deassert_reset, /* register access */ .get_gdb_reg_list = nds32_get_gdb_reg_list, /* memory access */ .read_buffer = nds32_v3_read_buffer, .write_buffer = nds32_v3_write_buffer, .read_memory = nds32_v3_read_memory, .write_memory = nds32_v3_write_memory, .checksum_memory = nds32_v3_checksum_memory, /* breakpoint/watchpoint */ .add_breakpoint = nds32_v3_add_breakpoint, .remove_breakpoint = nds32_v3_remove_breakpoint, .add_watchpoint = nds32_v3_add_watchpoint, .remove_watchpoint = nds32_v3_remove_watchpoint, .hit_watchpoint = nds32_v3_hit_watchpoint, /* MMU */ .mmu = nds32_mmu, .virt2phys = nds32_virtual_to_physical, .read_phys_memory = nds32_read_phys_memory, .write_phys_memory = nds32_write_phys_memory, .run_algorithm = nds32_v3_run_algorithm, .commands = nds32_command_handlers, .target_create = nds32_v3_target_create, .init_target = nds32_v3_init_target, .examine = nds32_v3_examine, .get_gdb_fileio_info = nds32_get_gdb_fileio_info, .gdb_fileio_end = nds32_gdb_fileio_end, .profiling = nds32_profiling, }; openocd-0.9.0/src/target/nds32_v3.h0000644000175000017500000000374412315575361013677 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes Technology * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_V3_H__ #define __NDS32_V3_H__ #include "nds32.h" struct nds32_v3_common { struct nds32 nds32; /** number of hardware breakpoints */ int32_t n_hbr; /** number of used hardware watchpoints */ int32_t used_n_wp; /** next hardware breakpoint index */ int32_t next_hbr_index; /** low interference profiling */ bool low_interference_profile; }; static inline struct nds32_v3_common *target_to_nds32_v3(struct target *target) { return container_of(target->arch_info, struct nds32_v3_common, nds32); } #endif /* __NDS32_V3_H__ */ openocd-0.9.0/src/target/lakemont.c0000644000175000017500000011502512516456304014135 00000000000000/* * Copyright(c) 2013 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation */ /* * @file * This implements the probemode operations for Lakemont 1 (LMT1). */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "target_type.h" #include "lakemont.h" #include "register.h" #include "breakpoints.h" #include "x86_32_common.h" static int irscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t ir_len); static int drscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t len); static int save_context(struct target *target); static int restore_context(struct target *target); static uint32_t get_tapstatus(struct target *t); static int enter_probemode(struct target *t); static int exit_probemode(struct target *t); static int halt_prep(struct target *t); static int do_halt(struct target *t); static int do_resume(struct target *t); static int read_all_core_hw_regs(struct target *t); static int write_all_core_hw_regs(struct target *t); static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cache); static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cache); static struct reg_cache *lakemont_build_reg_cache (struct target *target); static int submit_reg_pir(struct target *t, int num); static int submit_instruction_pir(struct target *t, int num); static int submit_pir(struct target *t, uint64_t op); static int lakemont_get_core_reg(struct reg *reg); static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf); static struct scan_blk scan; /* registers and opcodes for register access, pm_idx is used to identify the * registers that are modified for lakemont probemode specific operations */ static const struct { uint8_t id; const char *name; uint64_t op; uint8_t pm_idx; unsigned bits; enum reg_type type; const char *group; const char *feature; } regs[] = { /* general purpose registers */ { EAX, "eax", 0x000000D01D660000, 0, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ECX, "ecx", 0x000000501D660000, 1, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { EDX, "edx", 0x000000901D660000, 2, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { EBX, "ebx", 0x000000101D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ESP, "esp", 0x000000E01D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" }, { EBP, "ebp", 0x000000601D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" }, { ESI, "esi", 0x000000A01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { EDI, "edi", 0x000000201D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, /* instruction pointer & flags */ { EIP, "eip", 0x000000C01D660000, 3, 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.i386.core" }, { EFLAGS, "eflags", 0x000000401D660000, 4, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, /* segment registers */ { CS, "cs", 0x000000281D660000, 5, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { SS, "ss", 0x000000C81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { DS, "ds", 0x000000481D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ES, "es", 0x000000A81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FS, "fs", 0x000000881D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { GS, "gs", 0x000000081D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, /* floating point unit registers - not accessible via JTAG - here to satisfy GDB */ { ST0, "st0", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST1, "st1", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST2, "st2", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST3, "st3", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST4, "st4", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST5, "st5", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST6, "st6", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { ST7, "st7", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FCTRL, "fctrl", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FSTAT, "fstat", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FTAG, "ftag", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FISEG, "fiseg", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FIOFF, "fioff", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FOSEG, "foseg", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FOOFF, "fooff", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, { FOP, "fop", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" }, /* control registers */ { CR0, "cr0", 0x000000001D660000, 6, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { CR2, "cr2", 0x000000BC1D660000, 7, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { CR3, "cr3", 0x000000801D660000, 8, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { CR4, "cr4", 0x0000002C1D660000, 9, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, /* debug registers */ { DR0, "dr0", 0x0000007C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DR1, "dr1", 0x000000FC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DR2, "dr2", 0x000000021D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DR3, "dr3", 0x000000821D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DR6, "dr6", 0x000000301D660000, 10, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DR7, "dr7", 0x000000B01D660000, 11, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, /* descriptor tables */ { IDTB, "idtbase", 0x000000581D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { IDTL, "idtlimit", 0x000000D81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { IDTAR, "idtar", 0x000000981D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GDTB, "gdtbase", 0x000000B81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GDTL, "gdtlimit", 0x000000781D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GDTAR, "gdtar", 0x000000381D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { TR, "tr", 0x000000701D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { LDTR, "ldtr", 0x000000F01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { LDTB, "ldbase", 0x000000041D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { LDTL, "ldlimit", 0x000000841D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { LDTAR, "ldtar", 0x000000F81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, /* segment registers */ { CSB, "csbase", 0x000000F41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { CSL, "cslimit", 0x0000000C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { CSAR, "csar", 0x000000741D660000, 12, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DSB, "dsbase", 0x000000941D660000, 13, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DSL, "dslimit", 0x000000541D660000, 14, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { DSAR, "dsar", 0x000000141D660000, 15, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { ESB, "esbase", 0x0000004C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { ESL, "eslimit", 0x000000CC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { ESAR, "esar", 0x0000008C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { FSB, "fsbase", 0x000000641D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { FSL, "fslimit", 0x000000E41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { FSAR, "fsar", 0x000000A41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GSB, "gsbase", 0x000000C41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GSL, "gslimit", 0x000000241D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { GSAR, "gsar", 0x000000441D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { SSB, "ssbase", 0x000000341D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { SSL, "sslimit", 0x000000B41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { SSAR, "ssar", 0x000000D41D660000, 16, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { TSSB, "tssbase", 0x000000E81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { TSSL, "tsslimit", 0x000000181D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, { TSSAR, "tssar", 0x000000681D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, /* probemode control register */ { PMCR, "pmcr", 0x000000421D660000, 17, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" }, }; static const struct { uint8_t id; const char *name; uint64_t op; } instructions[] = { /* memory read/write */ { MEMRDB32, "MEMRDB32", 0x0909090909090851 }, { MEMRDB16, "MEMRDB16", 0x09090909090851E6 }, { MEMRDH32, "MEMRDH32", 0x090909090908D166 }, { MEMRDH16, "MEMRDH16", 0x090909090908D1E6 }, { MEMRDW32, "MEMRDW32", 0x09090909090908D1 }, { MEMRDW16, "MEMRDW16", 0x0909090908D1E666 }, { MEMWRB32, "MEMWRB32", 0x0909090909090811 }, { MEMWRB16, "MEMWRB16", 0x09090909090811E6 }, { MEMWRH32, "MEMWRH32", 0x0909090909089166 }, { MEMWRH16, "MEMWRH16", 0x09090909090891E6 }, { MEMWRW32, "MEMWRW32", 0x0909090909090891 }, { MEMWRW16, "MEMWRW16", 0x090909090891E666 }, /* IO read/write */ { IORDB32, "IORDB32", 0x0909090909090937 }, { IORDB16, "IORDB16", 0x09090909090937E6 }, { IORDH32, "IORDH32", 0x090909090909B766 }, { IORDH16, "IORDH16", 0x090909090909B7E6 }, { IORDW32, "IORDW32", 0x09090909090909B7 }, { IORDW16, "IORDW16", 0x0909090909B7E666 }, { IOWRB32, "IOWRB32", 0x0909090909090977 }, { IOWRB16, "IOWRB16", 0x09090909090977E6 }, { IOWRH32, "IOWRH32", 0x090909090909F766 }, { IOWRH16, "IOWRH16", 0x090909090909F7E6 }, { IOWRW32, "IOWRW32", 0x09090909090909F7 }, { IOWRW16, "IOWRW16", 0x0909090909F7E666 }, /* lakemont1 core shadow ram access opcodes */ { SRAMACCESS, "SRAMACCESS", 0x0000000E9D660000 }, { SRAM2PDR, "SRAM2PDR", 0x4CF0000000000000 }, { PDR2SRAM, "PDR2SRAM", 0x0CF0000000000000 }, { WBINVD, "WBINVD", 0x09090909090990F0 }, }; bool check_not_halted(const struct target *t) { bool halted = t->state == TARGET_HALTED; if (!halted) LOG_ERROR("target running, halt it first"); return !halted; } static int irscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t ir_len) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); if (NULL == t->tap) { retval = ERROR_FAIL; LOG_ERROR("%s invalid target tap", __func__); return retval; } if (ir_len != t->tap->ir_length) { retval = ERROR_FAIL; if (t->tap->enabled) LOG_ERROR("%s tap enabled but tap irlen=%d", __func__, t->tap->ir_length); else LOG_ERROR("%s tap not enabled and irlen=%d", __func__, t->tap->ir_length); return retval; } struct scan_field *fields = &scan.field; fields->num_bits = ir_len; fields->out_value = out; fields->in_value = in; jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE); if (x86_32->flush) { retval = jtag_execute_queue(); if (retval != ERROR_OK) LOG_ERROR("%s failed to execute queue", __func__); } return retval; } static int drscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t len) { int retval = ERROR_OK; uint64_t data = 0; struct x86_32_common *x86_32 = target_to_x86_32(t); if (NULL == t->tap) { retval = ERROR_FAIL; LOG_ERROR("%s invalid target tap", __func__); return retval; } if (len > MAX_SCAN_SIZE || 0 == len) { retval = ERROR_FAIL; LOG_ERROR("%s data len is %d bits, max is %d bits", __func__, len, MAX_SCAN_SIZE); return retval; } struct scan_field *fields = &scan.field; fields->out_value = out; fields->in_value = in; fields->num_bits = len; jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE); if (x86_32->flush) { retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("%s drscan failed to execute queue", __func__); return retval; } } if (in != NULL) { if (len >= 8) { for (int n = (len / 8) - 1 ; n >= 0; n--) data = (data << 8) + *(in+n); } else LOG_DEBUG("dr in 0x%02" PRIx8, *in); } else { LOG_ERROR("%s no drscan data", __func__); retval = ERROR_FAIL; } return retval; } static int save_context(struct target *t) { int err; /* read core registers from lakemont sram */ err = read_all_core_hw_regs(t); if (err != ERROR_OK) { LOG_ERROR("%s error reading regs", __func__); return err; } return ERROR_OK; } static int restore_context(struct target *t) { int err = ERROR_OK; uint32_t i; struct x86_32_common *x86_32 = target_to_x86_32(t); /* write core regs into the core PM SRAM from the reg_cache */ err = write_all_core_hw_regs(t); if (err != ERROR_OK) { LOG_ERROR("%s error writing regs", __func__); return err; } for (i = 0; i < (x86_32->cache->num_regs); i++) { x86_32->cache->reg_list[i].dirty = 0; x86_32->cache->reg_list[i].valid = 0; } return err; } /* * we keep reg_cache in sync with hardware at halt/resume time, we avoid * writing to real hardware here bacause pm_regs reflects the hardware * while we are halted then reg_cache syncs with hw on resume * TODO - in order for "reg eip force" to work it assume get/set reads * and writes from hardware, may be other reasons also because generally * other openocd targets read/write from hardware in get/set - watch this! */ static int lakemont_get_core_reg(struct reg *reg) { int retval = ERROR_OK; struct lakemont_core_reg *lakemont_reg = reg->arch_info; struct target *t = lakemont_reg->target; if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; LOG_DEBUG("reg=%s, value=0x%08" PRIx32, reg->name, buf_get_u32(reg->value, 0, 32)); return retval; } static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf) { struct lakemont_core_reg *lakemont_reg = reg->arch_info; struct target *t = lakemont_reg->target; uint32_t value = buf_get_u32(buf, 0, 32); LOG_DEBUG("reg=%s, newval=0x%08" PRIx32, reg->name, value); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static const struct reg_arch_type lakemont_reg_type = { /* these get called if reg_cache doesnt have a "valid" value * of an individual reg eg "reg eip" but not for "reg" block */ .get = lakemont_get_core_reg, .set = lakemont_set_core_reg, }; struct reg_cache *lakemont_build_reg_cache(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); int num_regs = ARRAY_SIZE(regs); struct reg_cache **cache_p = register_get_last_cache_p(&t->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); struct lakemont_core_reg *arch_info = malloc(sizeof(struct lakemont_core_reg) * num_regs); struct reg_feature *feature; int i; if (cache == NULL || reg_list == NULL || arch_info == NULL) { free(cache); free(reg_list); free(arch_info); LOG_ERROR("%s out of memory", __func__); return NULL; } /* Build the process context cache */ cache->name = "lakemont registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = num_regs; (*cache_p) = cache; x86_32->cache = cache; for (i = 0; i < num_regs; i++) { arch_info[i].target = t; arch_info[i].x86_32_common = x86_32; arch_info[i].op = regs[i].op; arch_info[i].pm_idx = regs[i].pm_idx; reg_list[i].name = regs[i].name; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &lakemont_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].group = regs[i].group; reg_list[i].number = i; reg_list[i].exist = true; reg_list[i].caller_save = true; /* gdb defaults to true */ feature = calloc(1, sizeof(struct reg_feature)); if (feature) { feature->name = regs[i].feature; reg_list[i].feature = feature; } else LOG_ERROR("%s unable to allocate feature list", __func__); reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); if (reg_list[i].reg_data_type) reg_list[i].reg_data_type->type = regs[i].type; else LOG_ERROR("%s unable to allocate reg type list", __func__); } return cache; } static uint32_t get_tapstatus(struct target *t) { scan.out[0] = TAPSTATUS; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return 0; if (drscan(t, NULL, scan.out, TS_SIZE) != ERROR_OK) return 0; return buf_get_u32(scan.out, 0, 32); } static int enter_probemode(struct target *t) { uint32_t tapstatus = 0; tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus); if (tapstatus & TS_PM_BIT) { LOG_DEBUG("core already in probemode"); return ERROR_OK; } scan.out[0] = PROBEMODE; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; scan.out[0] = 1; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; tapstatus = get_tapstatus(t); LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus); if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT))) return ERROR_OK; else { LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32 , __func__, tapstatus); return ERROR_FAIL; } } static int exit_probemode(struct target *t) { uint32_t tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM exit = 0x%08" PRIx32, tapstatus); if (!(tapstatus & TS_PM_BIT)) { LOG_USER("core not in PM"); return ERROR_OK; } scan.out[0] = PROBEMODE; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; scan.out[0] = 0; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } /* do whats needed to properly enter probemode for debug on lakemont */ static int halt_prep(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); if (write_hw_reg(t, DSB, PM_DSB, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write %s 0x%08" PRIx32, regs[DSB].name, PM_DSB); if (write_hw_reg(t, DSL, PM_DSL, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write %s 0x%08" PRIx32, regs[DSL].name, PM_DSL); if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR); if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); uint32_t csar = buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32); uint32_t ssar = buf_get_u32(x86_32->cache->reg_list[SSAR].value, 0, 32); uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32); /* clear VM86 and IF bits if they are set */ LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags, eflags & EFLAGS_VM86 ? 1 : 0, eflags & EFLAGS_IF ? 1 : 0); if (eflags & EFLAGS_VM86 || eflags & EFLAGS_IF) { x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF); if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("EFLAGS now = 0x%08" PRIx32 ", VM86 = %d, IF = %d", x86_32->pm_regs[I(EFLAGS)], x86_32->pm_regs[I(EFLAGS)] & EFLAGS_VM86 ? 1 : 0, x86_32->pm_regs[I(EFLAGS)] & EFLAGS_IF ? 1 : 0); } /* set CPL to 0 for memory access */ if (csar & CSAR_DPL) { x86_32->pm_regs[I(CSAR)] = csar & ~CSAR_DPL; if (write_hw_reg(t, CSAR, x86_32->pm_regs[I(CSAR)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]); } if (ssar & SSAR_DPL) { x86_32->pm_regs[I(SSAR)] = ssar & ~CSAR_DPL; if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]); } /* if cache's are enabled, disable and flush */ if (!(cr0 & CR0_CD)) { LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0); if (cr0 & CR0_PG) { x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG; if (write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("cleared paging CR0_PG = 0x%08" PRIx32, x86_32->pm_regs[I(CR0)]); /* submit wbinvd to flush cache */ if (submit_reg_pir(t, WBINVD) != ERROR_OK) return ERROR_FAIL; x86_32->pm_regs[I(CR0)] = x86_32->pm_regs[I(CR0)] | (CR0_CD | CR0_NW | CR0_PG); if (write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("set CD, NW and PG, CR0 = 0x%08" PRIx32, x86_32->pm_regs[I(CR0)]); } } return ERROR_OK; } static int do_halt(struct target *t) { /* needs proper handling later if doing a halt errors out */ t->state = TARGET_DEBUG_RUNNING; if (enter_probemode(t) != ERROR_OK) return ERROR_FAIL; if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_HALTED; return target_call_event_callbacks(t, TARGET_EVENT_HALTED); } static int do_resume(struct target *t) { /* needs proper handling later */ t->state = TARGET_DEBUG_RUNNING; if (restore_context(t) != ERROR_OK) return ERROR_FAIL; if (exit_probemode(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_RUNNING; t->debug_reason = DBG_REASON_NOTHALTED; LOG_USER("target running"); return target_call_event_callbacks(t, TARGET_EVENT_RESUMED); } static int read_all_core_hw_regs(struct target *t) { int err; uint32_t regval; unsigned i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (NOT_AVAIL_REG == regs[i].pm_idx) continue; err = read_hw_reg(t, regs[i].id, ®val, 1); if (err != ERROR_OK) { LOG_ERROR("%s error saving reg %s", __func__, x86_32->cache->reg_list[i].name); return err; } } LOG_DEBUG("read_all_core_hw_regs read %u registers ok", i); return ERROR_OK; } static int write_all_core_hw_regs(struct target *t) { int err; unsigned i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (NOT_AVAIL_REG == regs[i].pm_idx) continue; err = write_hw_reg(t, i, 0, 1); if (err != ERROR_OK) { LOG_ERROR("%s error restoring reg %s", __func__, x86_32->cache->reg_list[i].name); return err; } } LOG_DEBUG("write_all_core_hw_regs wrote %u registers ok", i); return ERROR_OK; } /* read reg from lakemont core shadow ram, update reg cache if needed */ static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cache) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct lakemont_core_reg *arch_info; arch_info = x86_32->cache->reg_list[reg].arch_info; x86_32->flush = 0; /* dont flush scans till we have a batch */ if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAM2PDR) != ERROR_OK) return ERROR_FAIL; x86_32->flush = 1; scan.out[0] = RDWRPDR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, NULL, scan.out, PDR_SIZE) != ERROR_OK) return ERROR_FAIL; jtag_add_sleep(DELAY_SUBMITPIR); *regval = buf_get_u32(scan.out, 0, 32); if (cache) { buf_set_u32(x86_32->cache->reg_list[reg].value, 0, 32, *regval); x86_32->cache->reg_list[reg].valid = 1; x86_32->cache->reg_list[reg].dirty = 0; } LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32, x86_32->cache->reg_list[reg].name, arch_info->op, *regval); return ERROR_OK; } /* write lakemont core shadow ram reg, update reg cache if needed */ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cache) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct lakemont_core_reg *arch_info; arch_info = x86_32->cache->reg_list[reg].arch_info; uint8_t reg_buf[4]; if (cache) regval = buf_get_u32(x86_32->cache->reg_list[reg].value, 0, 32); buf_set_u32(reg_buf, 0, 32, regval); LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32, x86_32->cache->reg_list[reg].name, arch_info->op, regval); scan.out[0] = RDWRPDR; x86_32->flush = 0; /* dont flush scans till we have a batch */ if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) return ERROR_FAIL; if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; x86_32->flush = 1; if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK) return ERROR_FAIL; /* we are writing from the cache so ensure we reset flags */ if (cache) { x86_32->cache->reg_list[reg].dirty = 0; x86_32->cache->reg_list[reg].valid = 0; } return ERROR_OK; } static bool is_paging_enabled(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); if (x86_32->pm_regs[I(CR0)] & CR0_PG) return true; else return false; } static uint8_t get_num_user_regs(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); return x86_32->cache->num_regs; } /* value of the CR0.PG (paging enabled) bit influences memory reads/writes */ static int disable_paging(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); x86_32->pm_regs[I(CR0)] = x86_32->pm_regs[I(CR0)] & ~CR0_PG; int err = x86_32->write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0); if (err != ERROR_OK) { LOG_ERROR("%s error disabling paging", __func__); return err; } return err; } static int enable_paging(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); x86_32->pm_regs[I(CR0)] = (x86_32->pm_regs[I(CR0)] | CR0_PG); int err = x86_32->write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0); if (err != ERROR_OK) { LOG_ERROR("%s error enabling paging", __func__); return err; } return err; } static bool sw_bpts_supported(struct target *t) { uint32_t tapstatus = get_tapstatus(t); if (tapstatus & TS_SBP_BIT) return true; else return false; } static int transaction_status(struct target *t) { uint32_t tapstatus = get_tapstatus(t); if ((TS_EN_PM_BIT | TS_PRDY_BIT) & tapstatus) { LOG_ERROR("%s transaction error tapstatus = 0x%08" PRIx32 , __func__, tapstatus); return ERROR_FAIL; } else { return ERROR_OK; } } static int submit_instruction(struct target *t, int num) { int err = submit_instruction_pir(t, num); if (err != ERROR_OK) { LOG_ERROR("%s error submitting pir", __func__); return err; } return err; } static int submit_reg_pir(struct target *t, int num) { LOG_DEBUG("reg %s op=0x%016" PRIx64, regs[num].name, regs[num].op); int err = submit_pir(t, regs[num].op); if (err != ERROR_OK) { LOG_ERROR("%s error submitting pir", __func__); return err; } return err; } static int submit_instruction_pir(struct target *t, int num) { LOG_DEBUG("%s op=0x%016" PRIx64, instructions[num].name, instructions[num].op); int err = submit_pir(t, instructions[num].op); if (err != ERROR_OK) { LOG_ERROR("%s error submitting pir", __func__); return err; } return err; } /* * PIR (Probe Mode Instruction Register), SUBMITPIR is an "IR only" TAP * command; there is no corresponding data register */ static int submit_pir(struct target *t, uint64_t op) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint8_t op_buf[8]; buf_set_u64(op_buf, 0, 64, op); int flush = x86_32->flush; x86_32->flush = 0; scan.out[0] = WRPIR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, op_buf, scan.out, PIR_SIZE) != ERROR_OK) return ERROR_FAIL; scan.out[0] = SUBMITPIR; x86_32->flush = flush; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; jtag_add_sleep(DELAY_SUBMITPIR); return ERROR_OK; } int lakemont_init_target(struct command_context *cmd_ctx, struct target *t) { lakemont_build_reg_cache(t); t->state = TARGET_RUNNING; t->debug_reason = DBG_REASON_NOTHALTED; return ERROR_OK; } int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32) { x86_32->submit_instruction = submit_instruction; x86_32->transaction_status = transaction_status; x86_32->read_hw_reg = read_hw_reg; x86_32->write_hw_reg = write_hw_reg; x86_32->sw_bpts_supported = sw_bpts_supported; x86_32->get_num_user_regs = get_num_user_regs; x86_32->is_paging_enabled = is_paging_enabled; x86_32->disable_paging = disable_paging; x86_32->enable_paging = enable_paging; return ERROR_OK; } int lakemont_poll(struct target *t) { /* LMT1 PMCR register currently allows code breakpoints, data breakpoints, * single stepping and shutdowns to be redirected to PM but does not allow * redirecting into PM as a result of SMM enter and SMM exit */ uint32_t ts = get_tapstatus(t); if (ts == 0xFFFFFFFF && t->state != TARGET_DEBUG_RUNNING) { /* something is wrong here */ LOG_ERROR("tapstatus invalid - scan_chain serialization or locked JTAG access issues"); /* TODO: Give a hint that unlocking is wrong or maybe a * 'jtag arp_init' helps */ t->state = TARGET_DEBUG_RUNNING; return ERROR_OK; } if (t->state == TARGET_HALTED && (!(ts & TS_PM_BIT))) { LOG_INFO("target running for unknown reason"); t->state = TARGET_RUNNING; } if (t->state == TARGET_RUNNING && t->state != TARGET_DEBUG_RUNNING) { if ((ts & TS_PM_BIT) && (ts & TS_PMCR_BIT)) { LOG_DEBUG("redirect to PM, tapstatus=0x%08" PRIx32, get_tapstatus(t)); t->state = TARGET_DEBUG_RUNNING; if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_HALTED; t->debug_reason = DBG_REASON_UNDEFINED; struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); uint32_t dr6 = buf_get_u32(x86_32->cache->reg_list[DR6].value, 0, 32); uint32_t hwbreakpoint = (uint32_t)-1; if (dr6 & DR6_BRKDETECT_0) hwbreakpoint = 0; if (dr6 & DR6_BRKDETECT_1) hwbreakpoint = 1; if (dr6 & DR6_BRKDETECT_2) hwbreakpoint = 2; if (dr6 & DR6_BRKDETECT_3) hwbreakpoint = 3; if (hwbreakpoint != (uint32_t)-1) { uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32); uint32_t type = dr7 & (0x03 << (DR7_RW_SHIFT + hwbreakpoint*DR7_RW_LEN_SIZE)); if (type == DR7_BP_EXECUTE) { LOG_USER("hit hardware breakpoint (hwreg=%" PRIu32 ") at 0x%08" PRIx32, hwbreakpoint, eip); } else { uint32_t address = 0; switch (hwbreakpoint) { default: case 0: address = buf_get_u32(x86_32->cache->reg_list[DR0].value, 0, 32); break; case 1: address = buf_get_u32(x86_32->cache->reg_list[DR1].value, 0, 32); break; case 2: address = buf_get_u32(x86_32->cache->reg_list[DR2].value, 0, 32); break; case 3: address = buf_get_u32(x86_32->cache->reg_list[DR3].value, 0, 32); break; } LOG_USER("hit '%s' watchpoint for 0x%08" PRIx32 " (hwreg=%" PRIu32 ") at 0x%08" PRIx32, type == DR7_BP_WRITE ? "write" : "access", address, hwbreakpoint, eip); } t->debug_reason = DBG_REASON_BREAKPOINT; } else { /* Check if the target hit a software breakpoint. * ! Watch out: EIP is currently pointing after the breakpoint opcode */ struct breakpoint *bp = NULL; bp = breakpoint_find(t, eip-1); if (bp != NULL) { t->debug_reason = DBG_REASON_BREAKPOINT; if (bp->type == BKPT_SOFT) { /* The EIP is now pointing the the next byte after the * breakpoint instruction. This needs to be corrected. */ buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1); x86_32->cache->reg_list[EIP].dirty = 1; x86_32->cache->reg_list[EIP].valid = 1; LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1); } else { /* it's not a hardware breakpoint (checked already in DR6 state) * and it's also not a software breakpoint ... */ LOG_USER("hit unknown breakpoint at 0x%08" PRIx32, eip); } } else { /* There is also the case that we hit an breakpoint instruction, * which was not set by us. This needs to be handled be the * application that introduced the breakpoint. */ LOG_USER("unknown break reason at 0x%08" PRIx32, eip); } } return target_call_event_callbacks(t, TARGET_EVENT_HALTED); } } return ERROR_OK; } int lakemont_arch_state(struct target *t) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_USER("target halted due to %s at 0x%08" PRIx32 " in %s mode", debug_reason_name(t), buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32), (buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32) & CR0_PE) ? "protected" : "real"); return ERROR_OK; } int lakemont_halt(struct target *t) { if (t->state == TARGET_RUNNING) { t->debug_reason = DBG_REASON_DBGRQ; if (do_halt(t) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } else { LOG_ERROR("%s target not running", __func__); return ERROR_FAIL; } } int lakemont_resume(struct target *t, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct breakpoint *bp = NULL; struct x86_32_common *x86_32 = target_to_x86_32(t); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; /* TODO lakemont_enable_breakpoints(t); */ if (t->state == TARGET_HALTED) { /* running away for a software breakpoint needs some special handling */ uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); bp = breakpoint_find(t, eip); if (bp != NULL /*&& bp->type == BKPT_SOFT*/) { /* the step will step over the breakpoint */ if (lakemont_step(t, 0, 0, 1) != ERROR_OK) { LOG_ERROR("%s stepping over a software breakpoint at 0x%08" PRIx32 " " "failed to resume the target", __func__, eip); return ERROR_FAIL; } } /* if breakpoints are enabled, we need to redirect these into probe mode */ struct breakpoint *activeswbp = t->breakpoints; while (activeswbp != NULL && activeswbp->set == 0) activeswbp = activeswbp->next; struct watchpoint *activehwbp = t->watchpoints; while (activehwbp != NULL && activehwbp->set == 0) activehwbp = activehwbp->next; if (activeswbp != NULL || activehwbp != NULL) buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); if (do_resume(t) != ERROR_OK) return ERROR_FAIL; } else { LOG_USER("target not halted"); return ERROR_FAIL; } return ERROR_OK; } int lakemont_step(struct target *t, int current, uint32_t address, int handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); uint32_t pmcr = buf_get_u32(x86_32->cache->reg_list[PMCR].value, 0, 32); struct breakpoint *bp = NULL; int retval = ERROR_OK; uint32_t tapstatus = 0; if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; bp = breakpoint_find(t, eip); if (retval == ERROR_OK && bp != NULL/*&& bp->type == BKPT_SOFT*/) { /* TODO: This should only be done for software breakpoints. * Stepping from hardware breakpoints should be possible with the resume flag * Needs testing. */ retval = x86_32_common_remove_breakpoint(t, bp); } /* Set EFLAGS[TF] and PMCR[IR], exit pm and wait for PRDY# */ LOG_DEBUG("modifying PMCR = 0x%08" PRIx32 " and EFLAGS = 0x%08" PRIx32, pmcr, eflags); eflags = eflags | (EFLAGS_TF | EFLAGS_RF); buf_set_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32, eflags); buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); LOG_DEBUG("EFLAGS [TF] [RF] bits set=0x%08" PRIx32 ", PMCR=0x%08" PRIx32 ", EIP=0x%08" PRIx32, eflags, pmcr, eip); tapstatus = get_tapstatus(t); t->debug_reason = DBG_REASON_SINGLESTEP; t->state = TARGET_DEBUG_RUNNING; if (restore_context(t) != ERROR_OK) return ERROR_FAIL; if (exit_probemode(t) != ERROR_OK) return ERROR_FAIL; target_call_event_callbacks(t, TARGET_EVENT_RESUMED); tapstatus = get_tapstatus(t); if (tapstatus & (TS_PM_BIT | TS_EN_PM_BIT | TS_PRDY_BIT | TS_PMCR_BIT)) { /* target has stopped */ if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_HALTED; LOG_USER("step done from EIP 0x%08" PRIx32 " to 0x%08" PRIx32, eip, buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32)); target_call_event_callbacks(t, TARGET_EVENT_HALTED); } else { /* target didn't stop * I hope the poll() will catch it, but the deleted breakpoint is gone */ LOG_ERROR("%s target didn't stop after executing a single step", __func__); t->state = TARGET_RUNNING; return ERROR_FAIL; } /* try to re-apply the breakpoint, even of step failed * TODO: When a bp was set, we should try to stop the target - fix the return above */ if (bp != NULL/*&& bp->type == BKPT_SOFT*/) { /* TODO: This should only be done for software breakpoints. * Stepping from hardware breakpoints should be possible with the resume flag * Needs testing. */ retval = x86_32_common_add_breakpoint(t, bp); } return retval; } /* TODO - implement resetbreak fully through CLTAP registers */ int lakemont_reset_assert(struct target *t) { LOG_DEBUG("-"); return ERROR_OK; } int lakemont_reset_deassert(struct target *t) { LOG_DEBUG("-"); return ERROR_OK; } openocd-0.9.0/src/target/lakemont.h0000644000175000017500000000614012516456304014137 00000000000000/* * Copyright(c) 2013 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation */ /* * @file * This is the interface to the probemode operations for Lakemont 1 (LMT1). */ #ifndef LAKEMONT_H #define LAKEMONT_H #include #include /* The Intel Quark SoC X1000 Core is codenamed lakemont */ #define LMT_IRLEN 8 /* lakemont tap instruction opcodes */ #define IDCODE 2 #define SUBMITPIR 3 #define PROBEMODE 4 #define WRPIR 6 #define RDWRPDR 8 #define TAPSTATUS 11 #define BYPASS 255 #define NOT_NULL 2 /* DR sizes */ #define ID_SIZE 32 #define PM_SIZE 1 #define PIR_SIZE 64 #define PDR_SIZE 32 #define TS_SIZE 32 #define BP_SIZE 1 #define MAX_SCAN_SIZE PIR_SIZE /* needed during lakemont probemode */ #define NOT_PMREG 0xfe #define NOT_AVAIL_REG 0xff #define PM_DSB ((uint32_t)0x00000000) #define PM_DSL ((uint32_t)0xFFFFFFFF) #define PM_DSAR ((uint32_t)0x004F9300) #define PM_DR7 ((uint32_t)0x00000400) #define DELAY_SUBMITPIR 0 /* for now 0 is working */ /* lakemont tapstatus bits */ #define TS_PRDY_BIT ((uint32_t)0x00000001) #define TS_EN_PM_BIT ((uint32_t)0x00000002) #define TS_PM_BIT ((uint32_t)0x00000004) #define TS_PMCR_BIT ((uint32_t)0x00000008) #define TS_SBP_BIT ((uint32_t)0x00000010) struct lakemont_core_reg { uint32_t num; struct target *target; struct x86_32_common *x86_32_common; uint64_t op; uint8_t pm_idx; }; struct scan_blk { uint8_t out[MAX_SCAN_SIZE]; /* scanned out to the tap */ uint8_t in[MAX_SCAN_SIZE]; /* in to our capture buf */ struct scan_field field; }; #define I(name) (((struct lakemont_core_reg *)x86_32->cache->reg_list[name].arch_info)->pm_idx) int lakemont_init_target(struct command_context *cmd_ctx, struct target *t); int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32); int lakemont_poll(struct target *t); int lakemont_arch_state(struct target *t); int lakemont_halt(struct target *t); int lakemont_resume(struct target *t, int current, uint32_t address, int handle_breakpoints, int debug_execution); int lakemont_step(struct target *t, int current, uint32_t address, int handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); #endif /* LAKEMONT_H */ openocd-0.9.0/src/target/image.c0000644000175000017500000007714112516456304013413 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009 by Franck Hereson * * franck.hereson@secad.fr * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "image.h" #include "target.h" #include /* convert ELF header field to host endianness */ #define field16(elf, field) \ ((elf->endianness == ELFDATA2LSB) ? \ le_to_h_u16((uint8_t *)&field) : be_to_h_u16((uint8_t *)&field)) #define field32(elf, field) \ ((elf->endianness == ELFDATA2LSB) ? \ le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field)) static int autodetect_image_type(struct image *image, const char *url) { int retval; struct fileio fileio; size_t read_bytes; uint8_t buffer[9]; /* read the first 4 bytes of image */ retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) return retval; retval = fileio_read(&fileio, 9, buffer, &read_bytes); if (retval == ERROR_OK) { if (read_bytes != 9) retval = ERROR_FILEIO_OPERATION_FAILED; } fileio_close(&fileio); if (retval != ERROR_OK) return retval; /* check header against known signatures */ if (strncmp((char *)buffer, ELFMAG, SELFMAG) == 0) { LOG_DEBUG("ELF image detected."); image->type = IMAGE_ELF; } else if ((buffer[0] == ':') /* record start byte */ && (isxdigit(buffer[1])) && (isxdigit(buffer[2])) && (isxdigit(buffer[3])) && (isxdigit(buffer[4])) && (isxdigit(buffer[5])) && (isxdigit(buffer[6])) && (buffer[7] == '0') /* record type : 00 -> 05 */ && (buffer[8] >= '0') && (buffer[8] < '6')) { LOG_DEBUG("IHEX image detected."); image->type = IMAGE_IHEX; } else if ((buffer[0] == 'S') /* record start byte */ && (isxdigit(buffer[1])) && (isxdigit(buffer[2])) && (isxdigit(buffer[3])) && (buffer[1] >= '0') && (buffer[1] < '9')) { LOG_DEBUG("S19 image detected."); image->type = IMAGE_SRECORD; } else image->type = IMAGE_BINARY; return ERROR_OK; } static int identify_image_type(struct image *image, const char *type_string, const char *url) { if (type_string) { if (!strcmp(type_string, "bin")) image->type = IMAGE_BINARY; else if (!strcmp(type_string, "ihex")) image->type = IMAGE_IHEX; else if (!strcmp(type_string, "elf")) image->type = IMAGE_ELF; else if (!strcmp(type_string, "mem")) image->type = IMAGE_MEMORY; else if (!strcmp(type_string, "s19")) image->type = IMAGE_SRECORD; else if (!strcmp(type_string, "build")) image->type = IMAGE_BUILDER; else return ERROR_IMAGE_TYPE_UNKNOWN; } else return autodetect_image_type(image, url); return ERROR_OK; } static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section) { struct image_ihex *ihex = image->type_private; struct fileio *fileio = &ihex->fileio; uint32_t full_address = 0x0; uint32_t cooked_bytes; int i; /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ int filesize; int retval; retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) return retval; ihex->buffer = malloc(filesize >> 1); cooked_bytes = 0x0; image->num_sections = 0; section[image->num_sections].private = &ihex->buffer[cooked_bytes]; section[image->num_sections].base_address = 0x0; section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) { uint32_t count; uint32_t address; uint32_t record_type; uint32_t checksum; uint8_t cal_checksum = 0; size_t bytes_read = 0; if (lpszLine[0] == '#') continue; if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32, &count, &address, &record_type) != 3) return ERROR_IMAGE_FORMAT_ERROR; bytes_read += 9; cal_checksum += (uint8_t)count; cal_checksum += (uint8_t)(address >> 8); cal_checksum += (uint8_t)address; cal_checksum += (uint8_t)record_type; if (record_type == 0) { /* Data Record */ if ((full_address & 0xffff) != address) { /* we encountered a nonconsecutive location, create a new section, * unless the current section has zero size, in which case this specifies * the current section's base address */ if (section[image->num_sections].size != 0) { image->num_sections++; if (image->num_sections >= IMAGE_MAX_SECTIONS) { /* too many sections */ LOG_ERROR("Too many sections found in IHEX file"); return ERROR_IMAGE_FORMAT_ERROR; } section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; section[image->num_sections].private = &ihex->buffer[cooked_bytes]; } section[image->num_sections].base_address = (full_address & 0xffff0000) | address; full_address = (full_address & 0xffff0000) | address; } while (count-- > 0) { unsigned value; sscanf(&lpszLine[bytes_read], "%2x", &value); ihex->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)ihex->buffer[cooked_bytes]; bytes_read += 2; cooked_bytes += 1; section[image->num_sections].size += 1; full_address++; } } else if (record_type == 1) { /* End of File Record */ /* finish the current section */ image->num_sections++; /* copy section information */ image->sections = malloc(sizeof(struct imagesection) * image->num_sections); for (i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; image->sections[i].base_address = section[i].base_address; image->sections[i].size = section[i].size; image->sections[i].flags = section[i].flags; } return ERROR_OK; } else if (record_type == 2) { /* Linear Address Record */ uint16_t upper_address; sscanf(&lpszLine[bytes_read], "%4hx", &upper_address); cal_checksum += (uint8_t)(upper_address >> 8); cal_checksum += (uint8_t)upper_address; bytes_read += 4; if ((full_address >> 4) != upper_address) { /* we encountered a nonconsecutive location, create a new section, * unless the current section has zero size, in which case this specifies * the current section's base address */ if (section[image->num_sections].size != 0) { image->num_sections++; if (image->num_sections >= IMAGE_MAX_SECTIONS) { /* too many sections */ LOG_ERROR("Too many sections found in IHEX file"); return ERROR_IMAGE_FORMAT_ERROR; } section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; section[image->num_sections].private = &ihex->buffer[cooked_bytes]; } section[image->num_sections].base_address = (full_address & 0xffff) | (upper_address << 4); full_address = (full_address & 0xffff) | (upper_address << 4); } } else if (record_type == 3) { /* Start Segment Address Record */ uint32_t dummy; /* "Start Segment Address Record" will not be supported * but we must consume it, and do not create an error. */ while (count-- > 0) { sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy); cal_checksum += (uint8_t)dummy; bytes_read += 2; } } else if (record_type == 4) { /* Extended Linear Address Record */ uint16_t upper_address; sscanf(&lpszLine[bytes_read], "%4hx", &upper_address); cal_checksum += (uint8_t)(upper_address >> 8); cal_checksum += (uint8_t)upper_address; bytes_read += 4; if ((full_address >> 16) != upper_address) { /* we encountered a nonconsecutive location, create a new section, * unless the current section has zero size, in which case this specifies * the current section's base address */ if (section[image->num_sections].size != 0) { image->num_sections++; if (image->num_sections >= IMAGE_MAX_SECTIONS) { /* too many sections */ LOG_ERROR("Too many sections found in IHEX file"); return ERROR_IMAGE_FORMAT_ERROR; } section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; section[image->num_sections].private = &ihex->buffer[cooked_bytes]; } section[image->num_sections].base_address = (full_address & 0xffff) | (upper_address << 16); full_address = (full_address & 0xffff) | (upper_address << 16); } } else if (record_type == 5) { /* Start Linear Address Record */ uint32_t start_address; sscanf(&lpszLine[bytes_read], "%8" SCNx32, &start_address); cal_checksum += (uint8_t)(start_address >> 24); cal_checksum += (uint8_t)(start_address >> 16); cal_checksum += (uint8_t)(start_address >> 8); cal_checksum += (uint8_t)start_address; bytes_read += 8; image->start_address_set = 1; image->start_address = be_to_h_u32((uint8_t *)&start_address); } else { LOG_ERROR("unhandled IHEX record type: %i", (int)record_type); return ERROR_IMAGE_FORMAT_ERROR; } sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum); if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) { /* checksum failed */ LOG_ERROR("incorrect record checksum found in IHEX file"); return ERROR_IMAGE_CHECKSUM; } } LOG_ERROR("premature end of IHEX file, no end-of-file record found"); return ERROR_IMAGE_FORMAT_ERROR; } /** * Allocate memory dynamically instead of on the stack. This * is important w/embedded hosts. */ static int image_ihex_buffer_complete(struct image *image) { char *lpszLine = malloc(1023); if (lpszLine == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS); if (section == NULL) { free(lpszLine); LOG_ERROR("Out of memory"); return ERROR_FAIL; } int retval; retval = image_ihex_buffer_complete_inner(image, lpszLine, section); free(section); free(lpszLine); return retval; } static int image_elf_read_headers(struct image *image) { struct image_elf *elf = image->type_private; size_t read_bytes; uint32_t i, j; int retval; uint32_t nload, load_to_vaddr = 0; elf->header = malloc(sizeof(Elf32_Ehdr)); if (elf->header == NULL) { LOG_ERROR("insufficient memory to perform operation "); return ERROR_FILEIO_OPERATION_FAILED; } retval = fileio_read(&elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF file header, read failed"); return ERROR_FILEIO_OPERATION_FAILED; } if (read_bytes != sizeof(Elf32_Ehdr)) { LOG_ERROR("cannot read ELF file header, only partially read"); return ERROR_FILEIO_OPERATION_FAILED; } if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) { LOG_ERROR("invalid ELF file, bad magic number"); return ERROR_IMAGE_FORMAT_ERROR; } if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) { LOG_ERROR("invalid ELF file, only 32bits files are supported"); return ERROR_IMAGE_FORMAT_ERROR; } elf->endianness = elf->header->e_ident[EI_DATA]; if ((elf->endianness != ELFDATA2LSB) && (elf->endianness != ELFDATA2MSB)) { LOG_ERROR("invalid ELF file, unknown endianness setting"); return ERROR_IMAGE_FORMAT_ERROR; } elf->segment_count = field16(elf, elf->header->e_phnum); if (elf->segment_count == 0) { LOG_ERROR("invalid ELF file, no program headers"); return ERROR_IMAGE_FORMAT_ERROR; } retval = fileio_seek(&elf->fileio, field32(elf, elf->header->e_phoff)); if (retval != ERROR_OK) { LOG_ERROR("cannot seek to ELF program header table, read failed"); return retval; } elf->segments = malloc(elf->segment_count*sizeof(Elf32_Phdr)); if (elf->segments == NULL) { LOG_ERROR("insufficient memory to perform operation "); return ERROR_FILEIO_OPERATION_FAILED; } retval = fileio_read(&elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), (uint8_t *)elf->segments, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF segment headers, read failed"); return retval; } if (read_bytes != elf->segment_count*sizeof(Elf32_Phdr)) { LOG_ERROR("cannot read ELF segment headers, only partially read"); return ERROR_FILEIO_OPERATION_FAILED; } /* count useful segments (loadable), ignore BSS section */ image->num_sections = 0; for (i = 0; i < elf->segment_count; i++) if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) image->num_sections++; assert(image->num_sections > 0); /** * some ELF linkers produce binaries with *all* the program header * p_paddr fields zero (there can be however one loadable segment * that has valid physical address 0x0). * If we have such a binary with more than * one PT_LOAD header, then use p_vaddr instead of p_paddr * (ARM ELF standard demands p_paddr = 0 anyway, and BFD * library uses this approach to workaround zero-initialized p_paddrs * when obtaining lma - look at elf.c of BDF) */ for (nload = 0, i = 0; i < elf->segment_count; i++) if (elf->segments[i].p_paddr != 0) break; else if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_memsz) != 0)) ++nload; if (i >= elf->segment_count && nload > 1) load_to_vaddr = 1; /* alloc and fill sections array with loadable segments */ image->sections = malloc(image->num_sections * sizeof(struct imagesection)); for (i = 0, j = 0; i < elf->segment_count; i++) { if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) { image->sections[j].size = field32(elf, elf->segments[i].p_filesz); if (load_to_vaddr) image->sections[j].base_address = field32(elf, elf->segments[i].p_vaddr); else image->sections[j].base_address = field32(elf, elf->segments[i].p_paddr); image->sections[j].private = &elf->segments[i]; image->sections[j].flags = field32(elf, elf->segments[i].p_flags); j++; } } image->start_address_set = 1; image->start_address = field32(elf, elf->header->e_entry); return ERROR_OK; } static int image_elf_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, size_t *size_read) { struct image_elf *elf = image->type_private; Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private; size_t read_size, really_read; int retval; *size_read = 0; LOG_DEBUG("load segment %d at 0x%" PRIx32 " (sz = 0x%" PRIx32 ")", section, offset, size); /* read initialized data in current segment if any */ if (offset < field32(elf, segment->p_filesz)) { /* maximal size present in file for the current segment */ read_size = MIN(size, field32(elf, segment->p_filesz) - offset); LOG_DEBUG("read elf: size = 0x%zu at 0x%" PRIx32 "", read_size, field32(elf, segment->p_offset) + offset); /* read initialized area of the segment */ retval = fileio_seek(&elf->fileio, field32(elf, segment->p_offset) + offset); if (retval != ERROR_OK) { LOG_ERROR("cannot find ELF segment content, seek failed"); return retval; } retval = fileio_read(&elf->fileio, read_size, buffer, &really_read); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF segment content, read failed"); return retval; } size -= read_size; *size_read += read_size; /* need more data ? */ if (!size) return ERROR_OK; } return ERROR_OK; } static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section) { struct image_mot *mot = image->type_private; struct fileio *fileio = &mot->fileio; uint32_t full_address = 0x0; uint32_t cooked_bytes; int i; /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ int retval; int filesize; retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) return retval; mot->buffer = malloc(filesize >> 1); cooked_bytes = 0x0; image->num_sections = 0; section[image->num_sections].private = &mot->buffer[cooked_bytes]; section[image->num_sections].base_address = 0x0; section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) { uint32_t count; uint32_t address; uint32_t record_type; uint32_t checksum; uint8_t cal_checksum = 0; uint32_t bytes_read = 0; /* get record type and record length */ if (sscanf(&lpszLine[bytes_read], "S%1" SCNx32 "%2" SCNx32, &record_type, &count) != 2) return ERROR_IMAGE_FORMAT_ERROR; bytes_read += 4; cal_checksum += (uint8_t)count; /* skip checksum byte */ count -= 1; if (record_type == 0) { /* S0 - starting record (optional) */ int iValue; while (count-- > 0) { sscanf(&lpszLine[bytes_read], "%2x", &iValue); cal_checksum += (uint8_t)iValue; bytes_read += 2; } } else if (record_type >= 1 && record_type <= 3) { switch (record_type) { case 1: /* S1 - 16 bit address data record */ sscanf(&lpszLine[bytes_read], "%4" SCNx32, &address); cal_checksum += (uint8_t)(address >> 8); cal_checksum += (uint8_t)address; bytes_read += 4; count -= 2; break; case 2: /* S2 - 24 bit address data record */ sscanf(&lpszLine[bytes_read], "%6" SCNx32, &address); cal_checksum += (uint8_t)(address >> 16); cal_checksum += (uint8_t)(address >> 8); cal_checksum += (uint8_t)address; bytes_read += 6; count -= 3; break; case 3: /* S3 - 32 bit address data record */ sscanf(&lpszLine[bytes_read], "%8" SCNx32, &address); cal_checksum += (uint8_t)(address >> 24); cal_checksum += (uint8_t)(address >> 16); cal_checksum += (uint8_t)(address >> 8); cal_checksum += (uint8_t)address; bytes_read += 8; count -= 4; break; } if (full_address != address) { /* we encountered a nonconsecutive location, create a new section, * unless the current section has zero size, in which case this specifies * the current section's base address */ if (section[image->num_sections].size != 0) { image->num_sections++; section[image->num_sections].size = 0x0; section[image->num_sections].flags = 0; section[image->num_sections].private = &mot->buffer[cooked_bytes]; } section[image->num_sections].base_address = address; full_address = address; } while (count-- > 0) { unsigned value; sscanf(&lpszLine[bytes_read], "%2x", &value); mot->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)mot->buffer[cooked_bytes]; bytes_read += 2; cooked_bytes += 1; section[image->num_sections].size += 1; full_address++; } } else if (record_type == 5) { /* S5 is the data count record, we ignore it */ uint32_t dummy; while (count-- > 0) { sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy); cal_checksum += (uint8_t)dummy; bytes_read += 2; } } else if (record_type >= 7 && record_type <= 9) { /* S7, S8, S9 - ending records for 32, 24 and 16bit */ image->num_sections++; /* copy section information */ image->sections = malloc(sizeof(struct imagesection) * image->num_sections); for (i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; image->sections[i].base_address = section[i].base_address; image->sections[i].size = section[i].size; image->sections[i].flags = section[i].flags; } return ERROR_OK; } else { LOG_ERROR("unhandled S19 record type: %i", (int)(record_type)); return ERROR_IMAGE_FORMAT_ERROR; } /* account for checksum, will always be 0xFF */ sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum); cal_checksum += (uint8_t)checksum; if (cal_checksum != 0xFF) { /* checksum failed */ LOG_ERROR("incorrect record checksum found in S19 file"); return ERROR_IMAGE_CHECKSUM; } } LOG_ERROR("premature end of S19 file, no end-of-file record found"); return ERROR_IMAGE_FORMAT_ERROR; } /** * Allocate memory dynamically instead of on the stack. This * is important w/embedded hosts. */ static int image_mot_buffer_complete(struct image *image) { char *lpszLine = malloc(1023); if (lpszLine == NULL) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS); if (section == NULL) { free(lpszLine); LOG_ERROR("Out of memory"); return ERROR_FAIL; } int retval; retval = image_mot_buffer_complete_inner(image, lpszLine, section); free(section); free(lpszLine); return retval; } int image_open(struct image *image, const char *url, const char *type_string) { int retval = ERROR_OK; retval = identify_image_type(image, type_string, url); if (retval != ERROR_OK) return retval; if (image->type == IMAGE_BINARY) { struct image_binary *image_binary; image_binary = image->type_private = malloc(sizeof(struct image_binary)); retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) return retval; int filesize; retval = fileio_size(&image_binary->fileio, &filesize); if (retval != ERROR_OK) { fileio_close(&image_binary->fileio); return retval; } image->num_sections = 1; image->sections = malloc(sizeof(struct imagesection)); image->sections[0].base_address = 0x0; image->sections[0].size = filesize; image->sections[0].flags = 0; } else if (image->type == IMAGE_IHEX) { struct image_ihex *image_ihex; image_ihex = image->type_private = malloc(sizeof(struct image_ihex)); retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT); if (retval != ERROR_OK) return retval; retval = image_ihex_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( "failed buffering IHEX image, check daemon output for additional information"); fileio_close(&image_ihex->fileio); return retval; } } else if (image->type == IMAGE_ELF) { struct image_elf *image_elf; image_elf = image->type_private = malloc(sizeof(struct image_elf)); retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) return retval; retval = image_elf_read_headers(image); if (retval != ERROR_OK) { fileio_close(&image_elf->fileio); return retval; } } else if (image->type == IMAGE_MEMORY) { struct target *target = get_target(url); if (target == NULL) { LOG_ERROR("target '%s' not defined", url); return ERROR_FAIL; } struct image_memory *image_memory; image->num_sections = 1; image->sections = malloc(sizeof(struct imagesection)); image->sections[0].base_address = 0x0; image->sections[0].size = 0xffffffff; image->sections[0].flags = 0; image_memory = image->type_private = malloc(sizeof(struct image_memory)); image_memory->target = target; image_memory->cache = NULL; image_memory->cache_address = 0x0; } else if (image->type == IMAGE_SRECORD) { struct image_mot *image_mot; image_mot = image->type_private = malloc(sizeof(struct image_mot)); retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT); if (retval != ERROR_OK) return retval; retval = image_mot_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( "failed buffering S19 image, check daemon output for additional information"); fileio_close(&image_mot->fileio); return retval; } } else if (image->type == IMAGE_BUILDER) { image->num_sections = 0; image->base_address_set = 0; image->sections = NULL; image->type_private = NULL; } if (image->base_address_set) { /* relocate */ int section; for (section = 0; section < image->num_sections; section++) image->sections[section].base_address += image->base_address; /* we're done relocating. The two statements below are mainly * for documenation purposes: stop anyone from empirically * thinking they should use these values henceforth. */ image->base_address = 0; image->base_address_set = 0; } return retval; }; int image_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, size_t *size_read) { int retval; /* don't read past the end of a section */ if (offset + size > image->sections[section].size) { LOG_DEBUG( "read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "", offset, size, image->sections[section].size); return ERROR_COMMAND_SYNTAX_ERROR; } if (image->type == IMAGE_BINARY) { struct image_binary *image_binary = image->type_private; /* only one section in a plain binary */ if (section != 0) return ERROR_COMMAND_SYNTAX_ERROR; /* seek to offset */ retval = fileio_seek(&image_binary->fileio, offset); if (retval != ERROR_OK) return retval; /* return requested bytes */ retval = fileio_read(&image_binary->fileio, size, buffer, size_read); if (retval != ERROR_OK) return retval; } else if (image->type == IMAGE_IHEX) { memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size); *size_read = size; return ERROR_OK; } else if (image->type == IMAGE_ELF) return image_elf_read_section(image, section, offset, size, buffer, size_read); else if (image->type == IMAGE_MEMORY) { struct image_memory *image_memory = image->type_private; uint32_t address = image->sections[section].base_address + offset; *size_read = 0; while ((size - *size_read) > 0) { uint32_t size_in_cache; if (!image_memory->cache || (address < image_memory->cache_address) || (address >= (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE))) { if (!image_memory->cache) image_memory->cache = malloc(IMAGE_MEMORY_CACHE_SIZE); if (target_read_buffer(image_memory->target, address & ~(IMAGE_MEMORY_CACHE_SIZE - 1), IMAGE_MEMORY_CACHE_SIZE, image_memory->cache) != ERROR_OK) { free(image_memory->cache); image_memory->cache = NULL; return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE; } image_memory->cache_address = address & ~(IMAGE_MEMORY_CACHE_SIZE - 1); } size_in_cache = (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE) - address; memcpy(buffer + *size_read, image_memory->cache + (address - image_memory->cache_address), (size_in_cache > size) ? size : size_in_cache ); *size_read += (size_in_cache > size) ? size : size_in_cache; address += (size_in_cache > size) ? size : size_in_cache; } } else if (image->type == IMAGE_SRECORD) { memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size); *size_read = size; return ERROR_OK; } else if (image->type == IMAGE_BUILDER) { memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size); *size_read = size; return ERROR_OK; } return ERROR_OK; } int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t const *data) { struct imagesection *section; /* only image builder supports adding sections */ if (image->type != IMAGE_BUILDER) return ERROR_COMMAND_SYNTAX_ERROR; /* see if there's a previous section */ if (image->num_sections) { section = &image->sections[image->num_sections - 1]; /* see if it's enough to extend the last section, * adding data to previous sections or merging is not supported */ if (((section->base_address + section->size) == base) && (section->flags == flags)) { section->private = realloc(section->private, section->size + size); memcpy((uint8_t *)section->private + section->size, data, size); section->size += size; return ERROR_OK; } } /* allocate new section */ image->num_sections++; image->sections = realloc(image->sections, sizeof(struct imagesection) * image->num_sections); section = &image->sections[image->num_sections - 1]; section->base_address = base; section->size = size; section->flags = flags; section->private = malloc(sizeof(uint8_t) * size); memcpy((uint8_t *)section->private, data, size); return ERROR_OK; } void image_close(struct image *image) { if (image->type == IMAGE_BINARY) { struct image_binary *image_binary = image->type_private; fileio_close(&image_binary->fileio); } else if (image->type == IMAGE_IHEX) { struct image_ihex *image_ihex = image->type_private; fileio_close(&image_ihex->fileio); if (image_ihex->buffer) { free(image_ihex->buffer); image_ihex->buffer = NULL; } } else if (image->type == IMAGE_ELF) { struct image_elf *image_elf = image->type_private; fileio_close(&image_elf->fileio); if (image_elf->header) { free(image_elf->header); image_elf->header = NULL; } if (image_elf->segments) { free(image_elf->segments); image_elf->segments = NULL; } } else if (image->type == IMAGE_MEMORY) { struct image_memory *image_memory = image->type_private; if (image_memory->cache) { free(image_memory->cache); image_memory->cache = NULL; } } else if (image->type == IMAGE_SRECORD) { struct image_mot *image_mot = image->type_private; fileio_close(&image_mot->fileio); if (image_mot->buffer) { free(image_mot->buffer); image_mot->buffer = NULL; } } else if (image->type == IMAGE_BUILDER) { int i; for (i = 0; i < image->num_sections; i++) { free(image->sections[i].private); image->sections[i].private = NULL; } } if (image->type_private) { free(image->type_private); image->type_private = NULL; } if (image->sections) { free(image->sections); image->sections = NULL; } } int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes, uint32_t *checksum) { uint32_t crc = 0xffffffff; LOG_DEBUG("Calculating checksum"); static uint32_t crc32_table[256]; static bool first_init; if (!first_init) { /* Initialize the CRC table and the decoding table. */ int i, j; unsigned int c; for (i = 0; i < 256; i++) { /* as per gdb */ for (c = i << 24, j = 8; j > 0; --j) c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); crc32_table[i] = c; } first_init = true; } while (nbytes > 0) { int run = nbytes; if (run > 32768) run = 32768; nbytes -= run; while (run--) { /* as per gdb */ crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255]; } keep_alive(); } LOG_DEBUG("Calculating checksum done"); *checksum = crc; return ERROR_OK; } openocd-0.9.0/src/target/image.h0000644000175000017500000001003512315575361013407 00000000000000/*************************************************************************** * Copyright (C) 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef IMAGE_H #define IMAGE_H #include #ifdef HAVE_ELF_H #include #endif #define IMAGE_MAX_ERROR_STRING (256) #define IMAGE_MAX_SECTIONS (512) #define IMAGE_MEMORY_CACHE_SIZE (2048) enum image_type { IMAGE_BINARY, /* plain binary */ IMAGE_IHEX, /* intel hex-record format */ IMAGE_MEMORY, /* target-memory pseudo-image */ IMAGE_ELF, /* ELF binary */ IMAGE_SRECORD, /* motorola s19 */ IMAGE_BUILDER, /* when building a new image */ }; struct imagesection { uint32_t base_address; uint32_t size; int flags; void *private; /* private data */ }; struct image { enum image_type type; /* image type (plain, ihex, ...) */ void *type_private; /* type private data */ int num_sections; /* number of sections contained in the image */ struct imagesection *sections; /* array of sections */ int base_address_set; /* whether the image has a base address set (for relocation purposes) */ long long base_address; /* base address, if one is set */ int start_address_set; /* whether the image has a start address (entry point) associated */ uint32_t start_address; /* start address, if one is set */ }; struct image_binary { struct fileio fileio; }; struct image_ihex { struct fileio fileio; uint8_t *buffer; }; struct image_memory { struct target *target; uint8_t *cache; uint32_t cache_address; }; struct image_elf { struct fileio fileio; Elf32_Ehdr *header; Elf32_Phdr *segments; uint32_t segment_count; uint8_t endianness; }; struct image_mot { struct fileio fileio; uint8_t *buffer; }; int image_open(struct image *image, const char *url, const char *type_string); int image_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, size_t *size_read); void image_close(struct image *image); int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t const *data); int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes, uint32_t *checksum); #define ERROR_IMAGE_FORMAT_ERROR (-1400) #define ERROR_IMAGE_TYPE_UNKNOWN (-1401) #define ERROR_IMAGE_TEMPORARILY_UNAVAILABLE (-1402) #define ERROR_IMAGE_CHECKSUM (-1403) #endif /* IMAGE_H */ openocd-0.9.0/src/target/mips32_dmaacc.c0000644000175000017500000003346512315575361014741 00000000000000/*************************************************************************** * Copyright (C) 2008 by John McCarthy * * jgmcc@magma.ca * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mips32_dmaacc.h" #include static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf); static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf); static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf); static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint8_t *buf); static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint16_t *buf); static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint32_t *buf); /* * The following logic shamelessly cloned from HairyDairyMaid's wrt54g_debrick * to support the Broadcom BCM5352 SoC in the Linksys WRT54GL wireless router * (and any others that support EJTAG DMA transfers). * Note: This only supports memory read/write. Since the BCM5352 doesn't * appear to support PRACC accesses, all debug functions except halt * do not work. Still, this does allow erasing/writing flash as well as * displaying/modifying memory and memory mapped registers. */ static int ejtag_dma_dstrt_poll(struct mips_ejtag *ejtag_info) { uint32_t ejtag_ctrl; int64_t start = timeval_ms(); do { if (timeval_ms() - start > 1000) { LOG_ERROR("DMA time out"); return -ETIMEDOUT; } ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); } while (ejtag_ctrl & EJTAG_CTRL_DSTRT); return 0; } static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; begin_ejtag_dma_read: /* Setup Address */ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Read & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Read Data */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, data); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr); goto begin_ejtag_dma_read; } else LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; begin_ejtag_dma_read_h: /* Setup Address */ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Read & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Read Data */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, &v); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr); goto begin_ejtag_dma_read_h; } else LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr); return ERROR_JTAG_DEVICE_ERROR; } /* Handle the bigendian/littleendian */ if (addr & 0x2) *data = (v >> 16) & 0xffff; else *data = (v & 0x0000ffff); return ERROR_OK; } static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; begin_ejtag_dma_read_b: /* Setup Address */ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Read & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Read Data */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, &v); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr); goto begin_ejtag_dma_read_b; } else LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr); return ERROR_JTAG_DEVICE_ERROR; } /* Handle the bigendian/littleendian */ switch (addr & 0x3) { case 0: *data = v & 0xff; break; case 1: *data = (v >> 8) & 0xff; break; case 2: *data = (v >> 16) & 0xff; break; case 3: *data = (v >> 24) & 0xff; break; } return ERROR_OK; } static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; begin_ejtag_dma_write: /* Setup Address */ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Setup Data */ v = data; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Write & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr); goto begin_ejtag_dma_write; } else LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; /* Handle the bigendian/littleendian */ data &= 0xffff; data |= data << 16; begin_ejtag_dma_write_h: /* Setup Address */ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Setup Data */ v = data; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Write & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr); goto begin_ejtag_dma_write_h; } else LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data) { uint32_t v; uint32_t ejtag_ctrl; int retries = RETRY_ATTEMPTS; /* Handle the bigendian/littleendian */ data &= 0xff; data |= data << 8; data |= data << 16; begin_ejtag_dma_write_b: /* Setup Address*/ v = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); mips_ejtag_drscan_32(ejtag_info, &v); /* Setup Data */ v = data; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32(ejtag_info, &v); /* Initiate DMA Write & set DSTRT */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); /* Wait for DSTRT to Clear */ ejtag_dma_dstrt_poll(ejtag_info); /* Clear DMA & Check DERR */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); if (ejtag_ctrl & EJTAG_CTRL_DERR) { if (retries--) { LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr); goto begin_ejtag_dma_write_b; } else LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; } int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { switch (size) { case 1: return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf); case 2: return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf); case 4: return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf); } return ERROR_OK; } static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_read_h(ejtag_info, addr + i * sizeof(*buf), &buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_read_b(ejtag_info, addr + i * sizeof(*buf), &buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { switch (size) { case 1: return mips32_dmaacc_write_mem8(ejtag_info, addr, count, buf); case 2: return mips32_dmaacc_write_mem16(ejtag_info, addr, count, buf); case 4: return mips32_dmaacc_write_mem32(ejtag_info, addr, count, buf); } return ERROR_OK; } static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint32_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint16_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_write_h(ejtag_info, addr + i * sizeof(*buf), buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint8_t *buf) { int i; int retval; for (i = 0; i < count; i++) { retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]); if (retval != ERROR_OK) return retval; } return ERROR_OK; } openocd-0.9.0/src/target/mips32_dmaacc.h0000644000175000017500000000446112315575361014740 00000000000000/*************************************************************************** * Copyright (C) 2008 by John McCarthy * * jgmcc@magma.ca * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by David T.L. Wong * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef MIPS32_DMAACC_H #define MIPS32_DMAACC_H #include "mips_ejtag.h" #define EJTAG_CTRL_DMA_BYTE 0x00000000 #define EJTAG_CTRL_DMA_HALFWORD 0x00000080 #define EJTAG_CTRL_DMA_WORD 0x00000100 #define EJTAG_CTRL_DMA_TRIPLEBYTE 0x00000180 #define RETRY_ATTEMPTS 0 int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf); int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf); #endif openocd-0.9.0/src/target/dsp563xx_once.c0000644000175000017500000001747512315575361014747 00000000000000/*************************************************************************** * Copyright (C) 2009 by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "target.h" #include "target_type.h" #include "register.h" #include "dsp563xx.h" #include "dsp563xx_once.h" #define JTAG_STATUS_STATIC_MASK 0x03 #define JTAG_STATUS_STATIC_VALUE 0x01 #define JTAG_STATUS_NORMAL 0x01 #define JTAG_STATUS_STOPWAIT 0x05 #define JTAG_STATUS_BUSY 0x09 #define JTAG_STATUS_DEBUG 0x0d #define JTAG_INSTR_EXTEST 0x00 #define JTAG_INSTR_SAMPLE_PRELOAD 0x01 #define JTAG_INSTR_IDCODE 0x02 #define JTAG_INSTR_HIZ 0x04 #define JTAG_INSTR_CLAMP 0x05 #define JTAG_INSTR_ENABLE_ONCE 0x06 #define JTAG_INSTR_DEBUG_REQUEST 0x07 #define JTAG_INSTR_BYPASS 0x0F /** */ static inline int dsp563xx_write_dr(struct jtag_tap *tap, uint8_t * dr_in, uint8_t * dr_out, int dr_len, int rti) { jtag_add_plain_dr_scan(dr_len, dr_out, dr_in, TAP_IDLE); return ERROR_OK; } /** */ static inline int dsp563xx_write_dr_u8(struct jtag_tap *tap, uint8_t * dr_in, uint8_t dr_out, int dr_len, int rti) { return dsp563xx_write_dr(tap, dr_in, &dr_out, dr_len, rti); } /** */ static inline int dsp563xx_write_dr_u32(struct jtag_tap *tap, uint32_t * dr_in, uint32_t dr_out, int dr_len, int rti) { return dsp563xx_write_dr(tap, (uint8_t *) dr_in, (uint8_t *) &dr_out, dr_len, rti); } /** single word instruction */ static inline int dsp563xx_once_ir_exec(struct jtag_tap *tap, int flush, uint8_t instr, uint8_t rw, uint8_t go, uint8_t ex) { int err; err = dsp563xx_write_dr_u8(tap, 0, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0); if (err != ERROR_OK) return err; if (flush) err = jtag_execute_queue(); return err; } /* IR and DR functions */ static inline int dsp563xx_write_ir(struct jtag_tap *tap, uint8_t * ir_in, uint8_t * ir_out, int ir_len, int rti) { jtag_add_plain_ir_scan(tap->ir_length, ir_out, ir_in, TAP_IDLE); return ERROR_OK; } static inline int dsp563xx_write_ir_u8(struct jtag_tap *tap, uint8_t * ir_in, uint8_t ir_out, int ir_len, int rti) { return dsp563xx_write_ir(tap, ir_in, &ir_out, ir_len, rti); } static inline int dsp563xx_jtag_sendinstr(struct jtag_tap *tap, uint8_t * ir_in, uint8_t ir_out) { return dsp563xx_write_ir_u8(tap, ir_in, ir_out, tap->ir_length, 1); } /** */ int dsp563xx_once_target_status(struct jtag_tap *tap) { int err; uint8_t jtag_status; err = dsp563xx_jtag_sendinstr(tap, &jtag_status, JTAG_INSTR_ENABLE_ONCE); if (err != ERROR_OK) return TARGET_UNKNOWN; err = jtag_execute_queue(); if (err != ERROR_OK) return TARGET_UNKNOWN; /* verify correct static status pattern */ if ((jtag_status & JTAG_STATUS_STATIC_MASK) != JTAG_STATUS_STATIC_VALUE) return TARGET_UNKNOWN; if (jtag_status != JTAG_STATUS_DEBUG) return TARGET_RUNNING; return TARGET_HALTED; } /** */ int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state) { int err; uint8_t ir_in = 0, pattern = 0; uint32_t retry = 0; /* in reset state we only get a ACK * from the interface */ if (reset_state) pattern = 1; else pattern = JTAG_STATUS_DEBUG; /* wait until we get the ack */ while (ir_in != pattern) { err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_DEBUG_REQUEST); if (err != ERROR_OK) return err; err = jtag_execute_queue(); if (err != ERROR_OK) return err; LOG_DEBUG("debug request: %02X", ir_in); if (retry++ == 100) return ERROR_TARGET_FAILURE; } /* we cant enable the once in reset state */ if (pattern == 1) return ERROR_OK; /* try to enable once */ retry = 0; ir_in = 0; while (ir_in != pattern) { err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_ENABLE_ONCE); if (err != ERROR_OK) return err; err = jtag_execute_queue(); if (err != ERROR_OK) return err; LOG_DEBUG("enable once: %02X", ir_in); if (retry++ == 100) { LOG_DEBUG("error"); return ERROR_TARGET_FAILURE; } } if (ir_in != JTAG_STATUS_DEBUG) return ERROR_TARGET_FAILURE; return ERROR_OK; } /** once read registers */ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len) { int i; int err = ERROR_OK; for (i = 0; i < len; i++) { err = dsp563xx_once_reg_read_ex(tap, flush, regs[i].addr, regs[i].len, ®s[i].reg); if (err != ERROR_OK) return err; } if (flush) err = jtag_execute_queue(); return err; } /** once read register with register len */ int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t * data) { int err; err = dsp563xx_once_ir_exec(tap, 1, reg, 1, 0, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, data, 0x00, len, 0); if (err != ERROR_OK) return err; if (flush) err = jtag_execute_queue(); return err; } /** once read register */ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t * data) { int err; err = dsp563xx_once_ir_exec(tap, flush, reg, 1, 0, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, data, 0x00, 24, 0); if (err != ERROR_OK) return err; if (flush) err = jtag_execute_queue(); return err; } /** once write register */ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data) { int err; err = dsp563xx_once_ir_exec(tap, flush, reg, 0, 0, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, 0x00, data, 24, 0); if (err != ERROR_OK) return err; if (flush) err = jtag_execute_queue(); return err; } /** single word instruction */ int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode) { int err; err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0); if (err != ERROR_OK) return err; if (flush) err = jtag_execute_queue(); return err; } /** double word instruction */ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode, uint32_t operand) { int err; err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 0, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0); if (err != ERROR_OK) return err; if (flush) { err = jtag_execute_queue(); if (err != ERROR_OK) return err; } err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0); if (err != ERROR_OK) return err; err = dsp563xx_write_dr_u32(tap, 0, operand, 24, 0); if (err != ERROR_OK) return err; if (flush) { err = jtag_execute_queue(); if (err != ERROR_OK) return err; } return ERROR_OK; } openocd-0.9.0/src/target/dsp563xx_once.h0000644000175000017500000001006312516456303014733 00000000000000/*************************************************************************** * Copyright (C) 2009 by Mathias Kuester * * mkdorg@users.sourceforge.net * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef DSP563XX_ONCE_H #define DSP563XX_ONCE_H #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #define DSP563XX_ONCE_OCR_EX (1<<5) #define DSP563XX_ONCE_OCR_GO (1<<6) #define DSP563XX_ONCE_OCR_RW (1<<7) #define DSP563XX_ONCE_OSCR_OS1 (1<<7) #define DSP563XX_ONCE_OSCR_OS0 (1<<6) #define DSP563XX_ONCE_OSCR_HIT (1<<5) #define DSP563XX_ONCE_OSCR_TO (1<<4) #define DSP563XX_ONCE_OSCR_MBO (1<<3) #define DSP563XX_ONCE_OSCR_SWO (1<<2) #define DSP563XX_ONCE_OSCR_IME (1<<1) #define DSP563XX_ONCE_OSCR_TME (1<<0) #define DSP563XX_ONCE_OSCR_NORMAL_M (0) #define DSP563XX_ONCE_OSCR_STOPWAIT_M (DSP563XX_ONCE_OSCR_OS0) #define DSP563XX_ONCE_OSCR_BUSY_M (DSP563XX_ONCE_OSCR_OS1) #define DSP563XX_ONCE_OSCR_DEBUG_M (DSP563XX_ONCE_OSCR_OS0|DSP563XX_ONCE_OSCR_OS1) #define DSP563XX_ONCE_OSCR 0x000 /* status/ctrl reg. */ #define DSP563XX_ONCE_OMBC 0x001 /* memory breakp. reg. */ #define DSP563XX_ONCE_OBCR 0x002 /* breakp. ctrl reg */ #define DSP563XX_ONCE_OMLR0 0x005 /* memory limit reg */ #define DSP563XX_ONCE_OMLR1 0x006 /* memory limit reg */ #define DSP563XX_ONCE_OGDBR 0x009 /* gdb reg */ #define DSP563XX_ONCE_OPDBR 0x00A /* pdb reg */ #define DSP563XX_ONCE_OPILR 0x00B /* pil reg */ #define DSP563XX_ONCE_PDBGOTO 0x00C /* pdb to go reg */ #define DSP563XX_ONCE_OTC 0x00D /* trace cnt */ #define DSP563XX_ONCE_TAGB 0x00E /* tags buffer */ #define DSP563XX_ONCE_OPABFR 0x00F /* pab fetch reg */ #define DSP563XX_ONCE_OPABDR 0x010 /* pab decode reg */ #define DSP563XX_ONCE_OPABEX 0x011 /* pab exec reg */ #define DSP563XX_ONCE_OPABF11 0x012 /* trace buffer/inc ptr */ #define DSP563XX_ONCE_NOREG 0x01F /* no register selected */ struct once_reg { const uint8_t num; const uint8_t addr; const uint8_t len; const char *name; uint32_t reg; }; /** */ int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state); /** */ int dsp563xx_once_target_status(struct jtag_tap *tap); /** once read registers */ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len); /** once read register */ int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t * data); /** once read register */ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t * data); /** once write register */ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data); /** single word instruction */ int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode); /** double word instruction */ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode, uint32_t operand); #endif /* DSP563XX_ONCE_H */ openocd-0.9.0/src/target/cortex_a.c0000644000175000017500000030661512516456303014135 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009 by Dirk Behme * * dirk.behme@gmail.com - copy from cortex_m3 * * * * Copyright (C) 2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * * Copyright (C) Broadcom 2012 * * ehunter@broadcom.com : Cortex R4 support * * * * Copyright (C) 2013 Kamal Dasu * * kdasu.kdev@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * Cortex-A8(tm) TRM, ARM DDI 0344H * * Cortex-A9(tm) TRM, ARM DDI 0407F * * Cortex-A4(tm) TRM, ARM DDI 0363E * * Cortex-A15(tm)TRM, ARM DDI 0438C * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "cortex_a.h" #include "register.h" #include "target_request.h" #include "target_type.h" #include "arm_opcodes.h" #include static int cortex_a_poll(struct target *target); static int cortex_a_debug_entry(struct target *target); static int cortex_a_restore_context(struct target *target, bool bpwp); static int cortex_a_set_breakpoint(struct target *target, struct breakpoint *breakpoint, uint8_t matchmode); static int cortex_a_set_context_breakpoint(struct target *target, struct breakpoint *breakpoint, uint8_t matchmode); static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint); static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); static int cortex_a_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum); static int cortex_a_dap_write_coreregister_u32(struct target *target, uint32_t value, int regnum); static int cortex_a_mmu(struct target *target, int *enabled); static int cortex_a_virt2phys(struct target *target, uint32_t virt, uint32_t *phys); static int cortex_a_read_apb_ab_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); /* restore cp15_control_reg at resume */ static int cortex_a_restore_cp15_control_reg(struct target *target) { int retval = ERROR_OK; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); if (cortex_a->cp15_control_reg != cortex_a->cp15_control_reg_curr) { cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg; /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg); */ retval = armv7a->arm.mcr(target, 15, 0, 0, /* op1, op2 */ 1, 0, /* CRn, CRm */ cortex_a->cp15_control_reg); } return retval; } /* check address before cortex_a_apb read write access with mmu on * remove apb predictible data abort */ static int cortex_a_check_address(struct target *target, uint32_t address) { struct armv7a_common *armv7a = target_to_armv7a(target); struct cortex_a_common *cortex_a = target_to_cortex_a(target); uint32_t os_border = armv7a->armv7a_mmu.os_border; if ((address < os_border) && (armv7a->arm.core_mode == ARM_MODE_SVC)) { LOG_ERROR("%" PRIx32 " access in userspace and target in supervisor", address); return ERROR_FAIL; } if ((address >= os_border) && (cortex_a->curr_mode != ARM_MODE_SVC)) { dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); cortex_a->curr_mode = ARM_MODE_SVC; LOG_INFO("%" PRIx32 " access in kernel space and target not in supervisor", address); return ERROR_OK; } if ((address < os_border) && (cortex_a->curr_mode == ARM_MODE_SVC)) { dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); cortex_a->curr_mode = ARM_MODE_ANY; } return ERROR_OK; } /* modify cp15_control_reg in order to enable or disable mmu for : * - virt2phys address conversion * - read or write memory in phys or virt address */ static int cortex_a_mmu_modify(struct target *target, int enable) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); int retval = ERROR_OK; if (enable) { /* if mmu enabled at target stop and mmu not enable */ if (!(cortex_a->cp15_control_reg & 0x1U)) { LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); return ERROR_FAIL; } if (!(cortex_a->cp15_control_reg_curr & 0x1U)) { cortex_a->cp15_control_reg_curr |= 0x1U; retval = armv7a->arm.mcr(target, 15, 0, 0, /* op1, op2 */ 1, 0, /* CRn, CRm */ cortex_a->cp15_control_reg_curr); } } else { if ((cortex_a->cp15_control_reg_curr & 0x1U)) { if (cortex_a->cp15_control_reg_curr & 0x4U) { /* data cache is active */ cortex_a->cp15_control_reg_curr &= ~0x4U; /* flush data cache armv7 function to be called */ if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache) armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache(target); } cortex_a->cp15_control_reg_curr &= ~0x1U; retval = armv7a->arm.mcr(target, 15, 0, 0, /* op1, op2 */ 1, 0, /* CRn, CRm */ cortex_a->cp15_control_reg_curr); } } return retval; } /* * Cortex-A Basic debug access, very low level assumes state is saved */ static int cortex_a8_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; LOG_DEBUG(" "); /* Unlocking the debug registers for modification * The debugport might be uninitialised so try twice */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); if (retval != ERROR_OK) { /* try again */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); if (retval == ERROR_OK) LOG_USER( "Locking debug access failed on first, but succeeded on second try."); } return retval; } /* * Cortex-A Basic debug access, very low level assumes state is saved */ static int cortex_a_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; uint32_t dbg_osreg; uint32_t cortex_part_num; struct cortex_a_common *cortex_a = target_to_cortex_a(target); LOG_DEBUG(" "); cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT; switch (cortex_part_num) { case CORTEX_A7_PARTNUM: case CORTEX_A15_PARTNUM: retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); if (retval != ERROR_OK) return retval; LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg); if (dbg_osreg & CPUDBG_OSLAR_LK_MASK) /* Unlocking the DEBUG OS registers for modification */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLAR, 0); break; case CORTEX_A5_PARTNUM: case CORTEX_A8_PARTNUM: case CORTEX_A9_PARTNUM: default: retval = cortex_a8_init_debug_access(target); } if (retval != ERROR_OK) return retval; /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); if (retval != ERROR_OK) return retval; /* Enabling of instruction execution in debug mode is done in debug_entry code */ /* Resync breakpoint registers */ /* Since this is likely called from init or reset, update target state information*/ return cortex_a_poll(target); } static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool force) { /* Waits until InstrCmpl_l becomes 1, indicating instruction is done. * Writes final value of DSCR into *dscr. Pass force to force always * reading DSCR at least once. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; long long then = timeval_ms(); while ((*dscr & DSCR_INSTR_COMP) == 0 || force) { force = false; int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register"); return retval; } if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for InstrCompl=1"); return ERROR_FAIL; } } return ERROR_OK; } /* To reduce needless round-trips, pass in a pointer to the current * DSCR value. Initialize it to zero if you just need to know the * value on return from this function; or DSCR_INSTR_COMP if you * happen to know that no instruction is pending. */ static int cortex_a_exec_opcode(struct target *target, uint32_t opcode, uint32_t *dscr_p) { uint32_t dscr; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; dscr = dscr_p ? *dscr_p : 0; LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); /* Wait for InstrCompl bit to be set */ retval = cortex_a_wait_instrcmpl(target, dscr_p, false); if (retval != ERROR_OK) return retval; retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_ITR, opcode); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); do { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register"); return retval; } if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for cortex_a_exec_opcode"); return ERROR_FAIL; } } while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */ if (dscr_p) *dscr_p = dscr; return retval; } /************************************************************************** Read core register with very few exec_opcode, fast but needs work_area. This can cause problems with MMU active. **************************************************************************/ static int cortex_a_read_regs_through_mem(struct target *target, uint32_t address, uint32_t *regfile) { int retval = ERROR_OK; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; retval = cortex_a_dap_read_coreregister_u32(target, regfile, 0); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_coreregister_u32(target, address, 0); if (retval != ERROR_OK) return retval; retval = cortex_a_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL); if (retval != ERROR_OK) return retval; retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, (uint8_t *)(®file[1]), 4, 15, address); return retval; } static int cortex_a_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum) { int retval = ERROR_OK; uint8_t reg = regnum&0xFF; uint32_t dscr = 0; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; if (reg > 17) return retval; if (reg < 15) { /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */ retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, reg, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } else if (reg == 15) { /* "MOV r0, r15"; then move r0 to DCCTX */ retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr); if (retval != ERROR_OK) return retval; retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } else { /* "MRS r0, CPSR" or "MRS r0, SPSR" * then move r0 to DCCTX */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr); if (retval != ERROR_OK) return retval; retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } /* Wait for DTRRXfull then read DTRRTX */ long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for cortex_a_exec_opcode"); return ERROR_FAIL; } } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, value); LOG_DEBUG("read DCC 0x%08" PRIx32, *value); return retval; } static int cortex_a_dap_write_coreregister_u32(struct target *target, uint32_t value, int regnum) { int retval = ERROR_OK; uint8_t Rd = regnum&0xFF; uint32_t dscr; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value); /* Check that DCCRX is not full */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if (dscr & DSCR_DTR_RX_FULL) { LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode 0xEE100E15 */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } if (Rd > 17) return retval; /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */ LOG_DEBUG("write DCC 0x%08" PRIx32, value); retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, value); if (retval != ERROR_OK) return retval; if (Rd < 15) { /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } else if (Rd == 15) { /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 * then "mov r15, r0" */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr); if (retval != ERROR_OK) return retval; } else { /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields) */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; retval = cortex_a_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1), &dscr); if (retval != ERROR_OK) return retval; /* "Prefetch flush" after modifying execution status in CPSR */ if (Rd == 16) { retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 4), &dscr); if (retval != ERROR_OK) return retval; } } return retval; } /* Write to memory mapped registers directly with no cache or mmu handling */ static int cortex_a_dap_write_memap_register_u32(struct target *target, uint32_t address, uint32_t value) { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, address, value); return retval; } /* * Cortex-A implementation of Debug Programmer's Model * * NOTE the invariant: these routines return with DSCR_INSTR_COMP set, * so there's no need to poll for it before executing an instruction. * * NOTE that in several of these cases the "stall" mode might be useful. * It'd let us queue a few operations together... prepare/finish might * be the places to enable/disable that mode. */ static inline struct cortex_a_common *dpm_to_a(struct arm_dpm *dpm) { return container_of(dpm, struct cortex_a_common, armv7a_common.dpm); } static int cortex_a_write_dcc(struct cortex_a_common *a, uint32_t data) { LOG_DEBUG("write DCC 0x%08" PRIx32, data); return mem_ap_sel_write_u32(a->armv7a_common.arm.dap, a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DTRRX, data); } static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, uint32_t *dscr_p) { struct adiv5_dap *swjdp = a->armv7a_common.arm.dap; uint32_t dscr = DSCR_INSTR_COMP; int retval; if (dscr_p) dscr = *dscr_p; /* Wait for DTRRXfull */ long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for read dcc"); return ERROR_FAIL; } } retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DTRTX, data); if (retval != ERROR_OK) return retval; /* LOG_DEBUG("read DCC 0x%08" PRIx32, *data); */ if (dscr_p) *dscr_p = dscr; return retval; } static int cortex_a_dpm_prepare(struct arm_dpm *dpm) { struct cortex_a_common *a = dpm_to_a(dpm); struct adiv5_dap *swjdp = a->armv7a_common.arm.dap; uint32_t dscr; int retval; /* set up invariant: INSTR_COMP is set after ever DPM operation */ long long then = timeval_ms(); for (;; ) { retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_INSTR_COMP) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for dpm prepare"); return ERROR_FAIL; } } /* this "should never happen" ... */ if (dscr & DSCR_DTR_RX_FULL) { LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); /* Clear DCCRX */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; } return retval; } static int cortex_a_dpm_finish(struct arm_dpm *dpm) { /* REVISIT what could be done here? */ return ERROR_OK; } static int cortex_a_instr_write_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { struct cortex_a_common *a = dpm_to_a(dpm); int retval; uint32_t dscr = DSCR_INSTR_COMP; retval = cortex_a_write_dcc(a, data); if (retval != ERROR_OK) return retval; return cortex_a_exec_opcode( a->armv7a_common.arm.target, opcode, &dscr); } static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t dscr = DSCR_INSTR_COMP; int retval; retval = cortex_a_write_dcc(a, data); if (retval != ERROR_OK) return retval; /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; /* then the opcode, taking data from R0 */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, opcode, &dscr); return retval; } static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm) { struct target *target = dpm->arm->target; uint32_t dscr = DSCR_INSTR_COMP; /* "Prefetch flush" after modifying execution status in CPSR */ return cortex_a_exec_opcode(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 4), &dscr); } static int cortex_a_instr_read_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { struct cortex_a_common *a = dpm_to_a(dpm); int retval; uint32_t dscr = DSCR_INSTR_COMP; /* the opcode, writing data to DCC */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, opcode, &dscr); if (retval != ERROR_OK) return retval; return cortex_a_read_dcc(a, data, &dscr); } static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t dscr = DSCR_INSTR_COMP; int retval; /* the opcode, writing data to R0 */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, opcode, &dscr); if (retval != ERROR_OK) return retval; /* write R0 to DCC */ retval = cortex_a_exec_opcode( a->armv7a_common.arm.target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) return retval; return cortex_a_read_dcc(a, data, &dscr); } static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, uint32_t addr, uint32_t control) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t vr = a->armv7a_common.debug_base; uint32_t cr = a->armv7a_common.debug_base; int retval; switch (index_t) { case 0 ... 15: /* breakpoints */ vr += CPUDBG_BVR_BASE; cr += CPUDBG_BCR_BASE; break; case 16 ... 31: /* watchpoints */ vr += CPUDBG_WVR_BASE; cr += CPUDBG_WCR_BASE; index_t -= 16; break; default: return ERROR_FAIL; } vr += 4 * index_t; cr += 4 * index_t; LOG_DEBUG("A: bpwp enable, vr %08x cr %08x", (unsigned) vr, (unsigned) cr); retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, vr, addr); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, control); return retval; } static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t cr; switch (index_t) { case 0 ... 15: cr = a->armv7a_common.debug_base + CPUDBG_BCR_BASE; break; case 16 ... 31: cr = a->armv7a_common.debug_base + CPUDBG_WCR_BASE; index_t -= 16; break; default: return ERROR_FAIL; } cr += 4 * index_t; LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); /* clear control register */ return cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, 0); } static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr) { struct arm_dpm *dpm = &a->armv7a_common.dpm; int retval; dpm->arm = &a->armv7a_common.arm; dpm->didr = didr; dpm->prepare = cortex_a_dpm_prepare; dpm->finish = cortex_a_dpm_finish; dpm->instr_write_data_dcc = cortex_a_instr_write_data_dcc; dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0; dpm->instr_cpsr_sync = cortex_a_instr_cpsr_sync; dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc; dpm->instr_read_data_r0 = cortex_a_instr_read_data_r0; dpm->bpwp_enable = cortex_a_bpwp_enable; dpm->bpwp_disable = cortex_a_bpwp_disable; retval = arm_dpm_setup(dpm); if (retval == ERROR_OK) retval = arm_dpm_initialize(dpm); return retval; } static struct target *get_cortex_a(struct target *target, int32_t coreid) { struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; head = head->next; } return target; } static int cortex_a_halt(struct target *target); static int cortex_a_halt_smp(struct target *target) { int retval = 0; struct target_list *head; struct target *curr; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED)) retval += cortex_a_halt(curr); head = head->next; } return retval; } static int update_halt_gdb(struct target *target) { int retval = 0; if (target->gdb_service && target->gdb_service->core[0] == -1) { target->gdb_service->target = target; target->gdb_service->core[0] = target->coreid; retval += cortex_a_halt_smp(target); } return retval; } /* * Cortex-A Run control */ static int cortex_a_poll(struct target *target) { int retval = ERROR_OK; uint32_t dscr; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *swjdp = armv7a->arm.dap; enum target_state prev_target_state = target->state; /* toggle to another core is done by gdb as follow */ /* maint packet J core_id */ /* continue */ /* the next polling trigger an halt event sent to gdb */ if ((target->state == TARGET_HALTED) && (target->smp) && (target->gdb_service) && (target->gdb_service->target == NULL)) { target->gdb_service->target = get_cortex_a(target, target->gdb_service->core[1]); target_call_event_callbacks(target, TARGET_EVENT_HALTED); return retval; } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; cortex_a->cpudbg_dscr = dscr; if (DSCR_RUN_MODE(dscr) == (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) { if (prev_target_state != TARGET_HALTED) { /* We have a halting debug event */ LOG_DEBUG("Target halted"); target->state = TARGET_HALTED; if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_UNKNOWN) || (prev_target_state == TARGET_RESET)) { retval = cortex_a_debug_entry(target); if (retval != ERROR_OK) return retval; if (target->smp) { retval = update_halt_gdb(target); if (retval != ERROR_OK) return retval; } target_call_event_callbacks(target, TARGET_EVENT_HALTED); } if (prev_target_state == TARGET_DEBUG_RUNNING) { LOG_DEBUG(" "); retval = cortex_a_debug_entry(target); if (retval != ERROR_OK) return retval; if (target->smp) { retval = update_halt_gdb(target); if (retval != ERROR_OK) return retval; } target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) target->state = TARGET_RUNNING; else { LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); target->state = TARGET_UNKNOWN; } return retval; } static int cortex_a_halt(struct target *target) { int retval = ERROR_OK; uint32_t dscr; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; /* * Tell the core to be halted by writing DRCR with 0x1 * and then wait for the core to be halted. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT); if (retval != ERROR_OK) return retval; /* * enter halting debug mode */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); for (;; ) { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_CORE_HALTED) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for halt"); return ERROR_FAIL; } } target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int cortex_a_internal_restore(struct target *target, int current, uint32_t *address, int handle_breakpoints, int debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; int retval; uint32_t resume_pc; if (!debug_execution) target_free_all_working_areas(target); #if 0 if (debug_execution) { /* Disable interrupts */ /* We disable interrupts in the PRIMASK register instead of * masking with C_MASKINTS, * This is probably the same issue as Cortex-M3 Errata 377493: * C_MASKINTS in parallel with disabled interrupts can cause * local faults to not be taken. */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1); armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1; armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1; /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24)); armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1; } #endif /* current = 1: continue on current pc, otherwise continue at
*/ resume_pc = buf_get_u32(arm->pc->value, 0, 32); if (!current) resume_pc = *address; else *address = resume_pc; /* Make sure that the Armv7 gdb thumb fixups does not * kill the return address */ switch (arm->core_state) { case ARM_STATE_ARM: resume_pc &= 0xFFFFFFFC; break; case ARM_STATE_THUMB: case ARM_STATE_THUMB_EE: /* When the return address is loaded into PC * bit 0 must be 1 to stay in Thumb state */ resume_pc |= 0x1; break; case ARM_STATE_JAZELLE: LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(arm->pc->value, 0, 32, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; /* restore dpm_mode at system halt */ dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); /* called it now before restoring context because it uses cpu * register r0 for restoring cp15 control register */ retval = cortex_a_restore_cp15_control_reg(target); if (retval != ERROR_OK) return retval; retval = cortex_a_restore_context(target, handle_breakpoints); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_NOTHALTED; target->state = TARGET_RUNNING; /* registers are now invalid */ register_cache_invalidate(arm->core_cache); #if 0 /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address); cortex_m3_unset_breakpoint(target, breakpoint); cortex_m3_single_step_core(target); cortex_m3_set_breakpoint(target, breakpoint); } } #endif return retval; } static int cortex_a_internal_restart(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; struct adiv5_dap *swjdp = arm->dap; int retval; uint32_t dscr; /* * * Restart core and wait for it to be started. Clear ITRen and sticky * * exception flags: see ARMv7 ARM, C5.9. * * REVISIT: for single stepping, we probably want to * disable IRQs by default, with optional override... */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_INSTR_COMP) == 0) LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN); if (retval != ERROR_OK) return retval; retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART | DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); for (;; ) { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_CORE_RESTARTED) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for resume"); return ERROR_FAIL; } } target->debug_reason = DBG_REASON_NOTHALTED; target->state = TARGET_RUNNING; /* registers are now invalid */ register_cache_invalidate(arm->core_cache); return ERROR_OK; } static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) { int retval = 0; struct target_list *head; struct target *curr; uint32_t address; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { /* resume current address , not in step mode */ retval += cortex_a_internal_restore(curr, 1, &address, handle_breakpoints, 0); retval += cortex_a_internal_restart(curr); } head = head->next; } return retval; } static int cortex_a_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ if ((target->smp) && (target->gdb_service->core[1] != -1)) { /* simulate a start and halt of target */ target->gdb_service->target = NULL; target->gdb_service->core[0] = target->gdb_service->core[1]; /* fake resume at next poll we play the target core[1], see poll*/ target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } cortex_a_internal_restore(target, current, &address, handle_breakpoints, debug_execution); if (target->smp) { target->gdb_service->core[0] = -1; retval = cortex_a_restore_smp(target, handle_breakpoints); if (retval != ERROR_OK) return retval; } cortex_a_internal_restart(target); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32, address); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32, address); } return ERROR_OK; } static int cortex_a_debug_entry(struct target *target) { int i; uint32_t regfile[16], cpsr, dscr; int retval = ERROR_OK; struct working_area *regfile_working_area = NULL; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; struct adiv5_dap *swjdp = armv7a->arm.dap; struct reg *reg; LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr); /* REVISIT surely we should not re-read DSCR !! */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; /* REVISIT see A TRM 12.11.4 steps 2..3 -- make sure that any * imprecise data aborts get discarded by issuing a Data * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4). */ /* Enable the ITR execution once we are in debug mode */ dscr |= DSCR_ITR_EN; retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) return retval; /* Examine debug reason */ arm_dpm_report_dscr(&armv7a->dpm, cortex_a->cpudbg_dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { uint32_t wfar; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_WFAR, &wfar); if (retval != ERROR_OK) return retval; arm_dpm_report_wfar(&armv7a->dpm, wfar); } /* REVISIT fast_reg_read is never set ... */ /* Examine target state and mode */ if (cortex_a->fast_reg_read) target_alloc_working_area(target, 64, ®file_working_area); /* First load register acessible through core debug port*/ if (!regfile_working_area) retval = arm_dpm_read_current_registers(&armv7a->dpm); else { retval = cortex_a_read_regs_through_mem(target, regfile_working_area->address, regfile); target_free_working_area(target, regfile_working_area); if (retval != ERROR_OK) return retval; /* read Current PSR */ retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16); /* store current cpsr */ if (retval != ERROR_OK) return retval; LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr); arm_set_cpsr(arm, cpsr); /* update cache */ for (i = 0; i <= ARM_PC; i++) { reg = arm_reg_current(arm, i); buf_set_u32(reg->value, 0, 32, regfile[i]); reg->valid = 1; reg->dirty = 0; } /* Fixup PC Resume Address */ if (cpsr & (1 << 5)) { /* T bit set for Thumb or ThumbEE state */ regfile[ARM_PC] -= 4; } else { /* ARM state */ regfile[ARM_PC] -= 8; } reg = arm->pc; buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]); reg->dirty = reg->valid; } #if 0 /* TODO, Move this */ uint32_t cp15_control_register, cp15_cacr, cp15_nacr; cortex_a_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0); LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register); cortex_a_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2); LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr); cortex_a_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2); LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr); #endif /* Are we in an exception handler */ /* armv4_5->exception_number = 0; */ if (armv7a->post_debug_entry) { retval = armv7a->post_debug_entry(target); if (retval != ERROR_OK) return retval; } return retval; } static int cortex_a_post_debug_entry(struct target *target) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; int retval; /* MRC p15,0,,c1,c0,0 ; Read CP15 System Control Register */ retval = armv7a->arm.mrc(target, 15, 0, 0, /* op1, op2 */ 1, 0, /* CRn, CRm */ &cortex_a->cp15_control_reg); if (retval != ERROR_OK) return retval; LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg); cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg; if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1) armv7a_identify_cache(target); if (armv7a->is_armv7r) { armv7a->armv7a_mmu.mmu_enabled = 0; } else { armv7a->armv7a_mmu.mmu_enabled = (cortex_a->cp15_control_reg & 0x1U) ? 1 : 0; } armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled = (cortex_a->cp15_control_reg & 0x4U) ? 1 : 0; armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled = (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0; cortex_a->curr_mode = armv7a->arm.core_mode; return ERROR_OK; } static int cortex_a_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; struct breakpoint *breakpoint = NULL; struct breakpoint stepbreakpoint; struct reg *r; int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ r = arm->pc; if (!current) buf_set_u32(r->value, 0, 32, address); else address = buf_get_u32(r->value, 0, 32); /* The front-end may request us not to handle breakpoints. * But since Cortex-A uses breakpoint for single step, * we MUST handle breakpoints. */ handle_breakpoints = 1; if (handle_breakpoints) { breakpoint = breakpoint_find(target, address); if (breakpoint) cortex_a_unset_breakpoint(target, breakpoint); } /* Setup single step breakpoint */ stepbreakpoint.address = address; stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB) ? 2 : 4; stepbreakpoint.type = BKPT_HARD; stepbreakpoint.set = 0; /* Break on IVA mismatch */ cortex_a_set_breakpoint(target, &stepbreakpoint, 0x04); target->debug_reason = DBG_REASON_SINGLESTEP; retval = cortex_a_resume(target, 1, address, 0, 0); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); while (target->state != TARGET_HALTED) { retval = cortex_a_poll(target); if (retval != ERROR_OK) return retval; if (timeval_ms() > then + 1000) { LOG_ERROR("timeout waiting for target halt"); return ERROR_FAIL; } } cortex_a_unset_breakpoint(target, &stepbreakpoint); target->debug_reason = DBG_REASON_BREAKPOINT; if (breakpoint) cortex_a_set_breakpoint(target, breakpoint, 0); if (target->state != TARGET_HALTED) LOG_DEBUG("target stepped"); return ERROR_OK; } static int cortex_a_restore_context(struct target *target, bool bpwp) { struct armv7a_common *armv7a = target_to_armv7a(target); LOG_DEBUG(" "); if (armv7a->pre_restore_context) armv7a->pre_restore_context(target); return arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp); } /* * Cortex-A Breakpoint and watchpoint functions */ /* Setup hardware Breakpoint Register Pair */ static int cortex_a_set_breakpoint(struct target *target, struct breakpoint *breakpoint, uint8_t matchmode) { int retval; int brp_i = 0; uint32_t control; uint8_t byte_addr_select = 0x0F; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { while (brp_list[brp_i].used && (brp_i < cortex_a->brp_num)) brp_i++; if (brp_i >= cortex_a->brp_num) { LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } breakpoint->set = brp_i + 1; if (breakpoint->length == 2) byte_addr_select = (3 << (breakpoint->address & 0x02)); control = ((matchmode & 0x7) << 20) | (byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_i].used = 1; brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_i].control = control; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i, brp_list[brp_i].control, brp_list[brp_i].value); } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; if (breakpoint->length == 2) buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); else buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code); if (retval != ERROR_OK) return retval; breakpoint->set = 0x11; /* Any nice value but 0 */ } return ERROR_OK; } static int cortex_a_set_context_breakpoint(struct target *target, struct breakpoint *breakpoint, uint8_t matchmode) { int retval = ERROR_FAIL; int brp_i = 0; uint32_t control; uint8_t byte_addr_select = 0x0F; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); return retval; } /*check available context BRPs*/ while ((brp_list[brp_i].used || (brp_list[brp_i].type != BRP_CONTEXT)) && (brp_i < cortex_a->brp_num)) brp_i++; if (brp_i >= cortex_a->brp_num) { LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_FAIL; } breakpoint->set = brp_i + 1; control = ((matchmode & 0x7) << 20) | (byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_i].used = 1; brp_list[brp_i].value = (breakpoint->asid); brp_list[brp_i].control = control; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i, brp_list[brp_i].control, brp_list[brp_i].value); return ERROR_OK; } static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval = ERROR_FAIL; int brp_1 = 0; /* holds the contextID pair */ int brp_2 = 0; /* holds the IVA pair */ uint32_t control_CTX, control_IVA; uint8_t CTX_byte_addr_select = 0x0F; uint8_t IVA_byte_addr_select = 0x0F; uint8_t CTX_machmode = 0x03; uint8_t IVA_machmode = 0x01; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); return retval; } /*check available context BRPs*/ while ((brp_list[brp_1].used || (brp_list[brp_1].type != BRP_CONTEXT)) && (brp_1 < cortex_a->brp_num)) brp_1++; printf("brp(CTX) found num: %d\n", brp_1); if (brp_1 >= cortex_a->brp_num) { LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_FAIL; } while ((brp_list[brp_2].used || (brp_list[brp_2].type != BRP_NORMAL)) && (brp_2 < cortex_a->brp_num)) brp_2++; printf("brp(IVA) found num: %d\n", brp_2); if (brp_2 >= cortex_a->brp_num) { LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_FAIL; } breakpoint->set = brp_1 + 1; breakpoint->linked_BRP = brp_2; control_CTX = ((CTX_machmode & 0x7) << 20) | (brp_2 << 16) | (0 << 14) | (CTX_byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_1].used = 1; brp_list[brp_1].value = (breakpoint->asid); brp_list[brp_1].control = control_CTX; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, brp_list[brp_1].value); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn, brp_list[brp_1].control); if (retval != ERROR_OK) return retval; control_IVA = ((IVA_machmode & 0x7) << 20) | (brp_1 << 16) | (IVA_byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_2].used = 1; brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_2].control = control_IVA; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, brp_list[brp_2].value); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn, brp_list[brp_2].control); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { int brp_i = breakpoint->set - 1; int brp_j = breakpoint->linked_BRP; if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i, brp_list[brp_i].control, brp_list[brp_i].value); brp_list[brp_i].used = 0; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; if ((brp_j < 0) || (brp_j >= cortex_a->brp_num)) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j, brp_list[brp_j].control, brp_list[brp_j].value); brp_list[brp_j].used = 0; brp_list[brp_j].value = 0; brp_list[brp_j].control = 0; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].BRPn, brp_list[brp_j].control); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].BRPn, brp_list[brp_j].value); if (retval != ERROR_OK) return retval; breakpoint->linked_BRP = 0; breakpoint->set = 0; return ERROR_OK; } else { int brp_i = breakpoint->set - 1; if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i, brp_list[brp_i].control, brp_list[brp_i].value); brp_list[brp_i].used = 0; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; breakpoint->set = 0; return ERROR_OK; } } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } else { retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } breakpoint->set = 0; return ERROR_OK; } static int cortex_a_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) { LOG_INFO("no hardware breakpoint available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) cortex_a->brp_num_available--; return cortex_a_set_breakpoint(target, breakpoint, 0x00); /* Exact match */ } static int cortex_a_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) { LOG_INFO("no hardware breakpoint available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) cortex_a->brp_num_available--; return cortex_a_set_context_breakpoint(target, breakpoint, 0x02); /* asid match */ } static int cortex_a_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) { LOG_INFO("no hardware breakpoint available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) cortex_a->brp_num_available--; return cortex_a_set_hybrid_breakpoint(target, breakpoint); /* ??? */ } static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); #if 0 /* It is perfectly possible to remove breakpoints while the target is running */ if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } #endif if (breakpoint->set) { cortex_a_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) cortex_a->brp_num_available++; } return ERROR_OK; } /* * Cortex-A Reset functions */ static int cortex_a_assert_reset(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); LOG_DEBUG(" "); /* FIXME when halt is requested, make it work somehow... */ /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); else if (jtag_get_reset_config() & RESET_HAS_SRST) { /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ jtag_add_reset(0, 1); } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* registers are now invalid */ register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; return ERROR_OK; } static int cortex_a_deassert_reset(struct target *target) { int retval; LOG_DEBUG(" "); /* be certain SRST is off */ jtag_add_reset(0, 0); retval = cortex_a_poll(target); if (retval != ERROR_OK) return retval; if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); if (retval != ERROR_OK) return retval; } } return ERROR_OK; } static int cortex_a_set_dcc_mode(struct target *target, uint32_t mode, uint32_t *dscr) { /* Changes the mode of the DCC between non-blocking, stall, and fast mode. * New desired mode must be in mode. Current value of DSCR must be in * *dscr, which is updated with new value. * * This function elides actually sending the mode-change over the debug * interface if the mode is already set as desired. */ uint32_t new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | mode; if (new_dscr != *dscr) { struct armv7a_common *armv7a = target_to_armv7a(target); int retval = mem_ap_sel_write_atomic_u32(armv7a->arm.dap, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, new_dscr); if (retval == ERROR_OK) *dscr = new_dscr; return retval; } else { return ERROR_OK; } } static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask, uint32_t value, uint32_t *dscr) { /* Waits until the specified bit(s) of DSCR take on a specified value. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; long long then = timeval_ms(); int retval; while ((*dscr & mask) != value) { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) return retval; if (timeval_ms() > then + 1000) { LOG_ERROR("timeout waiting for DSCR bit change"); return ERROR_FAIL; } } return ERROR_OK; } static int cortex_a_read_copro(struct target *target, uint32_t opcode, uint32_t *data, uint32_t *dscr) { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; /* Move from coprocessor to R0. */ retval = cortex_a_exec_opcode(target, opcode, dscr); if (retval != ERROR_OK) return retval; /* Move from R0 to DTRTX. */ retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0), dscr); if (retval != ERROR_OK) return retval; /* Wait until DTRTX is full (according to ARMv7-A/-R architecture * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one * must also check TXfull_l). Most of the time this will be free * because TXfull_l will be set immediately and cached in dscr. */ retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED, DSCR_DTRTX_FULL_LATCHED, dscr); if (retval != ERROR_OK) return retval; /* Read the value transferred to DTRTX. */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, data); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int cortex_a_read_dfar_dfsr(struct target *target, uint32_t *dfar, uint32_t *dfsr, uint32_t *dscr) { int retval; if (dfar) { retval = cortex_a_read_copro(target, ARMV4_5_MRC(15, 0, 0, 6, 0, 0), dfar, dscr); if (retval != ERROR_OK) return retval; } if (dfsr) { retval = cortex_a_read_copro(target, ARMV4_5_MRC(15, 0, 0, 5, 0, 0), dfsr, dscr); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int cortex_a_write_copro(struct target *target, uint32_t opcode, uint32_t data, uint32_t *dscr) { int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; /* Write the value into DTRRX. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, data); if (retval != ERROR_OK) return retval; /* Move from DTRRX to R0. */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), dscr); if (retval != ERROR_OK) return retval; /* Move from R0 to coprocessor. */ retval = cortex_a_exec_opcode(target, opcode, dscr); if (retval != ERROR_OK) return retval; /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also * check RXfull_l). Most of the time this will be free because RXfull_l * will be cleared immediately and cached in dscr. */ retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, dscr); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int cortex_a_write_dfar_dfsr(struct target *target, uint32_t dfar, uint32_t dfsr, uint32_t *dscr) { int retval; retval = cortex_a_write_copro(target, ARMV4_5_MCR(15, 0, 0, 6, 0, 0), dfar, dscr); if (retval != ERROR_OK) return retval; retval = cortex_a_write_copro(target, ARMV4_5_MCR(15, 0, 0, 5, 0, 0), dfsr, dscr); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int cortex_a_dfsr_to_error_code(uint32_t dfsr) { uint32_t status, upper4; if (dfsr & (1 << 9)) { /* LPAE format. */ status = dfsr & 0x3f; upper4 = status >> 2; if (upper4 == 1 || upper4 == 2 || upper4 == 3 || upper4 == 15) return ERROR_TARGET_TRANSLATION_FAULT; else if (status == 33) return ERROR_TARGET_UNALIGNED_ACCESS; else return ERROR_TARGET_DATA_ABORT; } else { /* Normal format. */ status = ((dfsr >> 6) & 0x10) | (dfsr & 0xf); if (status == 1) return ERROR_TARGET_UNALIGNED_ACCESS; else if (status == 5 || status == 7 || status == 3 || status == 6 || status == 9 || status == 11 || status == 13 || status == 15) return ERROR_TARGET_TRANSLATION_FAULT; else return ERROR_TARGET_DATA_ABORT; } } static int cortex_a_write_apb_ab_memory_slow(struct target *target, uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size size from *buffer. Old value of DSCR must * be in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and * the address is aligned, cortex_a_write_apb_ab_memory_fast should be * preferred. * Preconditions: * - Address is in R0. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; int retval; /* Mark register R1 as dirty, to use for transferring data. */ arm_reg_current(arm, 1)->dirty = true; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr); if (retval != ERROR_OK) return retval; /* Go through the objects. */ while (count) { /* Write the value to store into DTRRX. */ uint32_t data, opcode; if (size == 1) data = *buffer; else if (size == 2) data = target_buffer_get_u16(target, buffer); else data = target_buffer_get_u32(target, buffer); retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, data); if (retval != ERROR_OK) return retval; /* Transfer the value from DTRRX to R1. */ retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), dscr); if (retval != ERROR_OK) return retval; /* Write the value transferred to R1 into memory. */ if (size == 1) opcode = ARMV4_5_STRB_IP(1, 0); else if (size == 2) opcode = ARMV4_5_STRH_IP(1, 0); else opcode = ARMV4_5_STRW_IP(1, 0); retval = cortex_a_exec_opcode(target, opcode, dscr); if (retval != ERROR_OK) return retval; /* Check for faults and return early. */ if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) return ERROR_OK; /* A data fault is not considered a system failure. */ /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one * must also check RXfull_l). Most of the time this will be free * because RXfull_l will be cleared immediately and cached in dscr. */ retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, dscr); if (retval != ERROR_OK) return retval; /* Advance. */ buffer += size; --count; } return ERROR_OK; } static int cortex_a_write_apb_ab_memory_fast(struct target *target, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size 4 from *buffer. Old value of DSCR must be * in *dscr; updated to new value. This is fast but only works for * word-sized objects at aligned addresses. * Preconditions: * - Address is in R0 and must be a multiple of 4. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; /* Switch to fast mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_FAST_MODE, dscr); if (retval != ERROR_OK) return retval; /* Latch STC instruction. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_ITR, ARMV4_5_STC(0, 1, 0, 1, 14, 5, 0, 4)); if (retval != ERROR_OK) return retval; /* Transfer all the data and issue all the instructions. */ return mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap, buffer, 4, count, armv7a->debug_base + CPUDBG_DTRRX); } static int cortex_a_write_apb_ab_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { /* Write memory through APB-AP. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!count) return ERROR_OK; /* Clear any abort. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; /* Read DSCR. */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr); if (retval != ERROR_OK) goto out; /* Mark R0 as dirty. */ arm_reg_current(arm, 0)->dirty = true; /* Read DFAR and DFSR, as they will be modified in the event of a fault. */ retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr); if (retval != ERROR_OK) goto out; /* Get the memory address into R0. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, address); if (retval != ERROR_OK) goto out; retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) goto out; if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ retval = cortex_a_write_apb_ab_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ retval = cortex_a_write_apb_ab_memory_slow(target, size, count, buffer, &dscr); } out: final_retval = retval; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr); if (final_retval == ERROR_OK) final_retval = retval; /* Wait for last issued instruction to complete. */ retval = cortex_a_wait_instrcmpl(target, &dscr, true); if (final_retval == ERROR_OK) final_retval = retval; /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also * check RXfull_l). Most of the time this will be free because RXfull_l * will be cleared immediately and cached in dscr. However, don’t do this * if there is fault, because then the instruction might not have completed * successfully. */ if (!(dscr & DSCR_STICKY_ABORT_PRECISE)) { retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, &dscr); if (retval != ERROR_OK) return retval; } /* If there were any sticky abort flags, clear them. */ if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { fault_dscr = dscr; mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE); } else { fault_dscr = 0; } /* Handle synchronous data faults. */ if (fault_dscr & DSCR_STICKY_ABORT_PRECISE) { if (final_retval == ERROR_OK) { /* Final return value will reflect cause of fault. */ retval = cortex_a_read_dfar_dfsr(target, &fault_dfar, &fault_dfsr, &dscr); if (retval == ERROR_OK) { LOG_ERROR("data abort at 0x%08" PRIx32 ", dfsr = 0x%08" PRIx32, fault_dfar, fault_dfsr); final_retval = cortex_a_dfsr_to_error_code(fault_dfsr); } else final_retval = retval; } /* Fault destroyed DFAR/DFSR; restore them. */ retval = cortex_a_write_dfar_dfsr(target, orig_dfar, orig_dfsr, &dscr); if (retval != ERROR_OK) LOG_ERROR("error restoring dfar/dfsr - dscr = 0x%08" PRIx32, dscr); } /* Handle asynchronous data faults. */ if (fault_dscr & DSCR_STICKY_ABORT_IMPRECISE) { if (final_retval == ERROR_OK) /* No other error has been recorded so far, so keep this one. */ final_retval = ERROR_TARGET_DATA_ABORT; } /* If the DCC is nonempty, clear it. */ if (dscr & DSCR_DTRTX_FULL_LATCHED) { uint32_t dummy; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &dummy); if (final_retval == ERROR_OK) final_retval = retval; } if (dscr & DSCR_DTRRX_FULL_LATCHED) { retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), &dscr); if (final_retval == ERROR_OK) final_retval = retval; } /* Done. */ return final_retval; } static int cortex_a_read_apb_ab_memory_slow(struct target *target, uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size size into *buffer. Old value of DSCR must be * in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and * the address is aligned, cortex_a_read_apb_ab_memory_fast should be * preferred. * Preconditions: * - Address is in R0. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; int retval; /* Mark register R1 as dirty, to use for transferring data. */ arm_reg_current(arm, 1)->dirty = true; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr); if (retval != ERROR_OK) return retval; /* Go through the objects. */ while (count) { /* Issue a load of the appropriate size to R1. */ uint32_t opcode, data; if (size == 1) opcode = ARMV4_5_LDRB_IP(1, 0); else if (size == 2) opcode = ARMV4_5_LDRH_IP(1, 0); else opcode = ARMV4_5_LDRW_IP(1, 0); retval = cortex_a_exec_opcode(target, opcode, dscr); if (retval != ERROR_OK) return retval; /* Issue a write of R1 to DTRTX. */ retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 1, 0, 5, 0), dscr); if (retval != ERROR_OK) return retval; /* Check for faults and return early. */ if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) return ERROR_OK; /* A data fault is not considered a system failure. */ /* Wait until DTRTX is full (according to ARMv7-A/-R architecture * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one * must also check TXfull_l). Most of the time this will be free * because TXfull_l will be set immediately and cached in dscr. */ retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED, DSCR_DTRTX_FULL_LATCHED, dscr); if (retval != ERROR_OK) return retval; /* Read the value transferred to DTRTX into the buffer. */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &data); if (retval != ERROR_OK) return retval; if (size == 1) *buffer = (uint8_t) data; else if (size == 2) target_buffer_set_u16(target, buffer, (uint16_t) data); else target_buffer_set_u32(target, buffer, data); /* Advance. */ buffer += size; --count; } return ERROR_OK; } static int cortex_a_read_apb_ab_memory_fast(struct target *target, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size 4 into *buffer. Old value of DSCR must be in * *dscr; updated to new value. This is fast but only works for word-sized * objects at aligned addresses. * Preconditions: * - Address is in R0 and must be a multiple of 4. * - R0 is marked dirty. */ struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint32_t new_dscr, u32; int retval; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr); if (retval != ERROR_OK) return retval; if (count > 1) { /* Consecutively issue the LDC instruction via a write to ITR and * change to fast mode, in a single bulk copy since DSCR == ITR + 4. * The instruction is issued into the core before the mode switch. */ uint8_t command[8]; target_buffer_set_u32(target, command, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4)); new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_FAST_MODE; target_buffer_set_u32(target, command + 4, new_dscr); retval = mem_ap_sel_write_buf(swjdp, armv7a->debug_ap, command, 4, 2, armv7a->debug_base + CPUDBG_ITR); if (retval != ERROR_OK) return retval; *dscr = new_dscr; /* Read the value transferred to DTRTX into the buffer. Due to fast * mode rules, this blocks until the instruction finishes executing and * then reissues the read instruction to read the next word from * memory. The last read of DTRTX in this call reads the second-to-last * word from memory and issues the read instruction for the last word. */ retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, buffer, 4, count - 1, armv7a->debug_base + CPUDBG_DTRTX); if (retval != ERROR_OK) return retval; /* Advance. */ buffer += (count - 1) * 4; } else { /* Issue the LDC instruction via a write to ITR. */ retval = cortex_a_exec_opcode(target, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4), dscr); if (retval != ERROR_OK) return retval; } /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr); if (retval != ERROR_OK) return retval; /* Wait for last issued instruction to complete. */ retval = cortex_a_wait_instrcmpl(target, dscr, false); if (retval != ERROR_OK) return retval; /* Check for faults and return early. */ if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) return ERROR_OK; /* A data fault is not considered a system failure. */ /* Wait until DTRTX is full (according to ARMv7-A/-R architecture manual * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also * check TXfull_l). Most of the time this will be free because TXfull_l * will be set immediately and cached in dscr. */ retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED, DSCR_DTRTX_FULL_LATCHED, dscr); if (retval != ERROR_OK) return retval; /* Read the value transferred to DTRTX into the buffer. This is the last * word. */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &u32); if (retval != ERROR_OK) return retval; target_buffer_set_u32(target, buffer, u32); return ERROR_OK; } static int cortex_a_read_apb_ab_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { /* Read memory through APB-AP. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!count) return ERROR_OK; /* Clear any abort. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; /* Read DSCR */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr); if (retval != ERROR_OK) goto out; /* Mark R0 as dirty. */ arm_reg_current(arm, 0)->dirty = true; /* Read DFAR and DFSR, as they will be modified in the event of a fault. */ retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr); if (retval != ERROR_OK) goto out; /* Get the memory address into R0. */ retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, address); if (retval != ERROR_OK) goto out; retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); if (retval != ERROR_OK) goto out; if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ retval = cortex_a_read_apb_ab_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ retval = cortex_a_read_apb_ab_memory_slow(target, size, count, buffer, &dscr); } out: final_retval = retval; /* Switch to non-blocking mode if not already in that mode. */ retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr); if (final_retval == ERROR_OK) final_retval = retval; /* Wait for last issued instruction to complete. */ retval = cortex_a_wait_instrcmpl(target, &dscr, true); if (final_retval == ERROR_OK) final_retval = retval; /* If there were any sticky abort flags, clear them. */ if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { fault_dscr = dscr; mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS); dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE); } else { fault_dscr = 0; } /* Handle synchronous data faults. */ if (fault_dscr & DSCR_STICKY_ABORT_PRECISE) { if (final_retval == ERROR_OK) { /* Final return value will reflect cause of fault. */ retval = cortex_a_read_dfar_dfsr(target, &fault_dfar, &fault_dfsr, &dscr); if (retval == ERROR_OK) { LOG_ERROR("data abort at 0x%08" PRIx32 ", dfsr = 0x%08" PRIx32, fault_dfar, fault_dfsr); final_retval = cortex_a_dfsr_to_error_code(fault_dfsr); } else final_retval = retval; } /* Fault destroyed DFAR/DFSR; restore them. */ retval = cortex_a_write_dfar_dfsr(target, orig_dfar, orig_dfsr, &dscr); if (retval != ERROR_OK) LOG_ERROR("error restoring dfar/dfsr - dscr = 0x%08" PRIx32, dscr); } /* Handle asynchronous data faults. */ if (fault_dscr & DSCR_STICKY_ABORT_IMPRECISE) { if (final_retval == ERROR_OK) /* No other error has been recorded so far, so keep this one. */ final_retval = ERROR_TARGET_DATA_ABORT; } /* If the DCC is nonempty, clear it. */ if (dscr & DSCR_DTRTX_FULL_LATCHED) { uint32_t dummy; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &dummy); if (final_retval == ERROR_OK) final_retval = retval; } if (dscr & DSCR_DTRRX_FULL_LATCHED) { retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), &dscr); if (final_retval == ERROR_OK) final_retval = retval; } /* Done. */ return final_retval; } /* * Cortex-A Memory access * * This is same Cortex M3 but we must also use the correct * ap number for every access. */ static int cortex_a_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval = ERROR_COMMAND_SYNTAX_ERROR; uint8_t apsel = swjdp->apsel; LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* read memory through AHB-AP */ retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { /* read memory through APB-AP */ if (!armv7a->is_armv7r) { /* disable mmu */ retval = cortex_a_mmu_modify(target, 0); if (retval != ERROR_OK) return retval; } retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); } } return retval; } static int cortex_a_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int mmu_enabled = 0; uint32_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; /* cortex_a handles unaligned memory access */ LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { retval = cortex_a_mmu(target, &mmu_enabled); if (retval != ERROR_OK) return retval; } if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { if (mmu_enabled) { virt = address; retval = cortex_a_virt2phys(target, virt, &phys); if (retval != ERROR_OK) return retval; LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, virt, phys); address = phys; } retval = cortex_a_read_phys_memory(target, address, size, count, buffer); } else { if (mmu_enabled) { retval = cortex_a_check_address(target, address); if (retval != ERROR_OK) return retval; /* enable MMU as we could have disabled it for phys access */ retval = cortex_a_mmu_modify(target, 1); if (retval != ERROR_OK) return retval; } retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); } return retval; } static int cortex_a_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval = ERROR_COMMAND_SYNTAX_ERROR; uint8_t apsel = swjdp->apsel; LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* write memory through AHB-AP */ retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { /* write memory through APB-AP */ if (!armv7a->is_armv7r) { retval = cortex_a_mmu_modify(target, 0); if (retval != ERROR_OK) return retval; } return cortex_a_write_apb_ab_memory(target, address, size, count, buffer); } } /* REVISIT this op is generic ARMv7-A/R stuff */ if (retval == ERROR_OK && target->state == TARGET_HALTED) { struct arm_dpm *dpm = armv7a->arm.dpm; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; /* The Cache handling will NOT work with MMU active, the * wrong addresses will be invalidated! * * For both ICache and DCache, walk all cache lines in the * address range. Cortex-A has fixed 64 byte line length. * * REVISIT per ARMv7, these may trigger watchpoints ... */ /* invalidate I-Cache */ if (armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled) { /* ICIMVAU - Invalidate Cache single entry * with MVA to PoU * MCR p15, 0, r0, c7, c5, 1 */ for (uint32_t cacheline = 0; cacheline < size * count; cacheline += 64) { retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), address + cacheline); if (retval != ERROR_OK) return retval; } } /* invalidate D-Cache */ if (armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled) { /* DCIMVAC - Invalidate data Cache line * with MVA to PoC * MCR p15, 0, r0, c7, c6, 1 */ for (uint32_t cacheline = 0; cacheline < size * count; cacheline += 64) { retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 6, 1), address + cacheline); if (retval != ERROR_OK) return retval; } } /* (void) */ dpm->finish(dpm); } return retval; } static int cortex_a_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int mmu_enabled = 0; uint32_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; /* cortex_a handles unaligned memory access */ LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { retval = cortex_a_mmu(target, &mmu_enabled); if (retval != ERROR_OK) return retval; } if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { LOG_DEBUG("Writing memory to address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (mmu_enabled) { virt = address; retval = cortex_a_virt2phys(target, virt, &phys); if (retval != ERROR_OK) return retval; LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, virt, phys); address = phys; } retval = cortex_a_write_phys_memory(target, address, size, count, buffer); } else { if (mmu_enabled) { retval = cortex_a_check_address(target, address); if (retval != ERROR_OK) return retval; /* enable MMU as we could have disabled it for phys access */ retval = cortex_a_mmu_modify(target, 1); if (retval != ERROR_OK) return retval; } retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); } return retval; } static int cortex_a_handle_target_request(void *priv) { struct target *target = priv; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; int retval; if (!target_was_examined(target)) return ERROR_OK; if (!target->dbg_msg_enabled) return ERROR_OK; if (target->state == TARGET_RUNNING) { uint32_t request; uint32_t dscr; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); /* check if we have data */ while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) { retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &request); if (retval == ERROR_OK) { target_request(target, request); retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); } } } return ERROR_OK; } /* * Cortex-A target information and configuration */ static int cortex_a_examine_first(struct target *target) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *swjdp = armv7a->arm.dap; int i; int retval = ERROR_OK; uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg; /* We do one extra read to ensure DAP is configured, * we call ahbap_debugport_init(swjdp) instead */ retval = ahbap_debugport_init(swjdp); if (retval != ERROR_OK) return retval; /* Search for the APB-AB - it is needed for access to debug registers */ retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } /* Search for the AHB-AB */ retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap); if (retval != ERROR_OK) { /* AHB-AP not found - use APB-AP */ LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access"); armv7a->memory_ap_available = false; } else { armv7a->memory_ap_available = true; } if (!target->dbgbase_set) { uint32_t dbgbase; /* Get ROM Table base */ uint32_t apid; int32_t coreidx = target->coreid; LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table", target->cmd_name); retval = dap_get_debugbase(swjdp, 1, &dbgbase, &apid); if (retval != ERROR_OK) return retval; /* Lookup 0x15 -- Processor DAP */ retval = dap_lookup_cs_component(swjdp, 1, dbgbase, 0x15, &armv7a->debug_base, &coreidx); if (retval != ERROR_OK) { LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.", target->cmd_name); return retval; } LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32, coreidx, armv7a->debug_base); } else armv7a->debug_base = target->dbgbase; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_CPUID, &cpuid); if (retval != ERROR_OK) return retval; retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_CPUID, &cpuid); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "CPUID"); return retval; } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_CTYPR, &ctypr); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "CTYPR"); return retval; } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_TTYPR, &ttypr); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "TTYPR"); return retval; } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DIDR, &didr); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "DIDR"); return retval; } LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); LOG_DEBUG("didr = 0x%08" PRIx32, didr); cortex_a->cpuid = cpuid; cortex_a->ctypr = ctypr; cortex_a->ttypr = ttypr; cortex_a->didr = didr; /* Unlocking the debug registers */ if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == CORTEX_A15_PARTNUM) { retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLAR, 0); if (retval != ERROR_OK) return retval; } /* Unlocking the debug registers */ if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == CORTEX_A7_PARTNUM) { retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLAR, 0); if (retval != ERROR_OK) return retval; } retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); if (retval != ERROR_OK) return retval; LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); armv7a->arm.core_type = ARM_MODE_MON; retval = cortex_a_dpm_setup(cortex_a, didr); if (retval != ERROR_OK) return retval; /* Setup Breakpoint Register Pairs */ cortex_a->brp_num = ((didr >> 24) & 0x0F) + 1; cortex_a->brp_num_context = ((didr >> 20) & 0x0F) + 1; cortex_a->brp_num_available = cortex_a->brp_num; free(cortex_a->brp_list); cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp)); /* cortex_a->brb_enabled = ????; */ for (i = 0; i < cortex_a->brp_num; i++) { cortex_a->brp_list[i].used = 0; if (i < (cortex_a->brp_num-cortex_a->brp_num_context)) cortex_a->brp_list[i].type = BRP_NORMAL; else cortex_a->brp_list[i].type = BRP_CONTEXT; cortex_a->brp_list[i].value = 0; cortex_a->brp_list[i].control = 0; cortex_a->brp_list[i].BRPn = i; } LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num); target_set_examined(target); return ERROR_OK; } static int cortex_a_examine(struct target *target) { int retval = ERROR_OK; /* Reestablish communication after target reset */ retval = cortex_a_examine_first(target); /* Configure core debug access */ if (retval == ERROR_OK) retval = cortex_a_init_debug_access(target); return retval; } /* * Cortex-A target creation and initialization */ static int cortex_a_init_target(struct command_context *cmd_ctx, struct target *target) { /* examine_first() does a bunch of this */ return ERROR_OK; } static int cortex_a_init_arch_info(struct target *target, struct cortex_a_common *cortex_a, struct jtag_tap *tap) { struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *dap = &armv7a->dap; armv7a->arm.dap = dap; /* Setup struct cortex_a_common */ cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; /* tap has no dap initialized */ if (!tap->dap) { armv7a->arm.dap = dap; /* Setup struct cortex_a_common */ /* prepare JTAG information for the new target */ cortex_a->jtag_info.tap = tap; cortex_a->jtag_info.scann_size = 4; /* Leave (only) generic DAP stuff for debugport_init() */ dap->jtag_info = &cortex_a->jtag_info; /* Number of bits for tar autoincrement, impl. dep. at least 10 */ dap->tar_autoincr_block = (1 << 10); dap->memaccess_tck = 80; tap->dap = dap; } else armv7a->arm.dap = tap->dap; cortex_a->fast_reg_read = 0; /* register arch-specific functions */ armv7a->examine_debug_reason = NULL; armv7a->post_debug_entry = cortex_a_post_debug_entry; armv7a->pre_restore_context = NULL; armv7a->armv7a_mmu.read_physical_memory = cortex_a_read_phys_memory; /* arm7_9->handle_target_request = cortex_a_handle_target_request; */ /* REVISIT v7a setup should be in a v7a-specific routine */ armv7a_init_arch_info(target, armv7a); target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target); return ERROR_OK; } static int cortex_a_target_create(struct target *target, Jim_Interp *interp) { struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); cortex_a->armv7a_common.is_armv7r = false; return cortex_a_init_arch_info(target, cortex_a, target->tap); } static int cortex_r4_target_create(struct target *target, Jim_Interp *interp) { struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); cortex_a->armv7a_common.is_armv7r = true; return cortex_a_init_arch_info(target, cortex_a, target->tap); } static int cortex_a_mmu(struct target *target, int *enabled) { if (target->state != TARGET_HALTED) { LOG_ERROR("%s: target not halted", __func__); return ERROR_TARGET_INVALID; } *enabled = target_to_cortex_a(target)->armv7a_common.armv7a_mmu.mmu_enabled; return ERROR_OK; } static int cortex_a_virt2phys(struct target *target, uint32_t virt, uint32_t *phys) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { uint32_t ret; retval = armv7a_mmu_translate_va(target, virt, &ret); if (retval != ERROR_OK) goto done; *phys = ret; } else {/* use this method if armv7a->memory_ap not selected * mmu must be enable in order to get a correct translation */ retval = cortex_a_mmu_modify(target, 1); if (retval != ERROR_OK) goto done; retval = armv7a_mmu_translate_va_pa(target, virt, phys, 1); } done: return retval; } COMMAND_HANDLER(cortex_a_handle_cache_info_command) { struct target *target = get_current_target(CMD_CTX); struct armv7a_common *armv7a = target_to_armv7a(target); return armv7a_handle_cache_info_command(CMD_CTX, &armv7a->armv7a_mmu.armv7a_cache); } COMMAND_HANDLER(cortex_a_handle_dbginit_command) { struct target *target = get_current_target(CMD_CTX); if (!target_was_examined(target)) { LOG_ERROR("target not examined yet"); return ERROR_FAIL; } return cortex_a_init_debug_access(target); } COMMAND_HANDLER(cortex_a_handle_smp_off_command) { struct target *target = get_current_target(CMD_CTX); /* check target is an smp target */ struct target_list *head; struct target *curr; head = target->head; target->smp = 0; if (head != (struct target_list *)NULL) { while (head != (struct target_list *)NULL) { curr = head->target; curr->smp = 0; head = head->next; } /* fixes the target display to the debugger */ target->gdb_service->target = target; } return ERROR_OK; } COMMAND_HANDLER(cortex_a_handle_smp_on_command) { struct target *target = get_current_target(CMD_CTX); struct target_list *head; struct target *curr; head = target->head; if (head != (struct target_list *)NULL) { target->smp = 1; while (head != (struct target_list *)NULL) { curr = head->target; curr->smp = 1; head = head->next; } } return ERROR_OK; } COMMAND_HANDLER(cortex_a_handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); int retval = ERROR_OK; struct target_list *head; head = target->head; if (head != (struct target_list *)NULL) { if (CMD_ARGC == 1) { int coreid = 0; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); if (ERROR_OK != retval) return retval; target->gdb_service->core[1] = coreid; } command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] , target->gdb_service->core[1]); } return ERROR_OK; } static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "cache_info", .handler = cortex_a_handle_cache_info_command, .mode = COMMAND_EXEC, .help = "display information about target caches", .usage = "", }, { .name = "dbginit", .handler = cortex_a_handle_dbginit_command, .mode = COMMAND_EXEC, .help = "Initialize core debug", .usage = "", }, { .name = "smp_off", .handler = cortex_a_handle_smp_off_command, .mode = COMMAND_EXEC, .help = "Stop smp handling", .usage = "",}, { .name = "smp_on", .handler = cortex_a_handle_smp_on_command, .mode = COMMAND_EXEC, .help = "Restart smp handling", .usage = "", }, { .name = "smp_gdb", .handler = cortex_a_handle_smp_gdb_command, .mode = COMMAND_EXEC, .help = "display/fix current core played to gdb", .usage = "", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration cortex_a_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = armv7a_command_handlers, }, { .name = "cortex_a", .mode = COMMAND_ANY, .help = "Cortex-A command group", .usage = "", .chain = cortex_a_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type cortexa_target = { .name = "cortex_a", .deprecated_name = "cortex_a8", .poll = cortex_a_poll, .arch_state = armv7a_arch_state, .halt = cortex_a_halt, .resume = cortex_a_resume, .step = cortex_a_step, .assert_reset = cortex_a_assert_reset, .deassert_reset = cortex_a_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_memory, .write_memory = cortex_a_write_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = cortex_a_add_breakpoint, .add_context_breakpoint = cortex_a_add_context_breakpoint, .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint, .remove_breakpoint = cortex_a_remove_breakpoint, .add_watchpoint = NULL, .remove_watchpoint = NULL, .commands = cortex_a_command_handlers, .target_create = cortex_a_target_create, .init_target = cortex_a_init_target, .examine = cortex_a_examine, .read_phys_memory = cortex_a_read_phys_memory, .write_phys_memory = cortex_a_write_phys_memory, .mmu = cortex_a_mmu, .virt2phys = cortex_a_virt2phys, }; static const struct command_registration cortex_r4_exec_command_handlers[] = { { .name = "cache_info", .handler = cortex_a_handle_cache_info_command, .mode = COMMAND_EXEC, .help = "display information about target caches", .usage = "", }, { .name = "dbginit", .handler = cortex_a_handle_dbginit_command, .mode = COMMAND_EXEC, .help = "Initialize core debug", .usage = "", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration cortex_r4_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = armv7a_command_handlers, }, { .name = "cortex_r4", .mode = COMMAND_ANY, .help = "Cortex-R4 command group", .usage = "", .chain = cortex_r4_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type cortexr4_target = { .name = "cortex_r4", .poll = cortex_a_poll, .arch_state = armv7a_arch_state, .halt = cortex_a_halt, .resume = cortex_a_resume, .step = cortex_a_step, .assert_reset = cortex_a_assert_reset, .deassert_reset = cortex_a_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_memory, .write_memory = cortex_a_write_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, .add_breakpoint = cortex_a_add_breakpoint, .add_context_breakpoint = cortex_a_add_context_breakpoint, .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint, .remove_breakpoint = cortex_a_remove_breakpoint, .add_watchpoint = NULL, .remove_watchpoint = NULL, .commands = cortex_r4_command_handlers, .target_create = cortex_r4_target_create, .init_target = cortex_a_init_target, .examine = cortex_a_examine, }; openocd-0.9.0/src/target/cortex_a.h0000644000175000017500000000723412516456303014135 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009 by Dirk Behme * * dirk.behme@gmail.com - copy from cortex_m3 * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef CORTEX_A_H #define CORTEX_A_H #include "armv7a.h" #define CORTEX_A_COMMON_MAGIC 0x411fc082 #define CORTEX_A15_COMMON_MAGIC 0x413fc0f1 #define CORTEX_A5_PARTNUM 0xc05 #define CORTEX_A7_PARTNUM 0xc07 #define CORTEX_A8_PARTNUM 0xc08 #define CORTEX_A9_PARTNUM 0xc09 #define CORTEX_A15_PARTNUM 0xc0f #define CORTEX_A_MIDR_PARTNUM_MASK 0x0000fff0 #define CORTEX_A_MIDR_PARTNUM_SHIFT 4 #define CPUDBG_CPUID 0xD00 #define CPUDBG_CTYPR 0xD04 #define CPUDBG_TTYPR 0xD0C #define CPUDBG_LOCKACCESS 0xFB0 #define CPUDBG_LOCKSTATUS 0xFB4 #define CPUDBG_OSLAR_LK_MASK (1 << 1) #define BRP_NORMAL 0 #define BRP_CONTEXT 1 #define CORTEX_A_PADDRDBG_CPU_SHIFT 13 struct cortex_a_brp { int used; int type; uint32_t value; uint32_t control; uint8_t BRPn; }; struct cortex_a_common { int common_magic; struct arm_jtag jtag_info; /* Context information */ uint32_t cpudbg_dscr; /* Saved cp15 registers */ uint32_t cp15_control_reg; /* latest cp15 register value written and cpsr processor mode */ uint32_t cp15_control_reg_curr; enum arm_mode curr_mode; /* Breakpoint register pairs */ int brp_num_context; int brp_num; int brp_num_available; struct cortex_a_brp *brp_list; /* Use cortex_a_read_regs_through_mem for fast register reads */ int fast_reg_read; uint32_t cpuid; uint32_t ctypr; uint32_t ttypr; uint32_t didr; struct armv7a_common armv7a_common; }; static inline struct cortex_a_common * target_to_cortex_a(struct target *target) { return container_of(target->arch_info, struct cortex_a_common, armv7a_common.arm); } #endif /* CORTEX_A_H */ openocd-0.9.0/src/target/cortex_m.c0000644000175000017500000020762512516456303014152 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * * * Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "jtag/interface.h" #include "breakpoints.h" #include "cortex_m.h" #include "target_request.h" #include "target_type.h" #include "arm_disassembler.h" #include "register.h" #include "arm_opcodes.h" #include "arm_semihosting.h" #include /* NOTE: most of this should work fine for the Cortex-M1 and * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M. * Some differences: M0/M1 doesn't have FBP remapping or the * DWT tracing/profiling support. (So the cycle counter will * not be usable; the other stuff isn't currently used here.) * * Although there are some workarounds for errata seen only in r0p0 * silicon, such old parts are hard to find and thus not much tested * any longer. */ /** * Returns the type of a break point required by address location */ #define BKPT_TYPE_BY_ADDR(addr) ((addr) < 0x20000000 ? BKPT_HARD : BKPT_SOFT) /* forward declarations */ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); static void cortex_m_dwt_free(struct target *target); static int cortexm_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum) { struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; int retval; uint32_t dcrdr; /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ if (target->dbg_msg_enabled) { retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); if (retval != ERROR_OK) return retval; } retval = mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); if (retval != ERROR_OK) return retval; retval = mem_ap_read_atomic_u32(swjdp, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; if (target->dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a separate * transaction otherwise the emulated DCC channel breaks */ if (retval == ERROR_OK) retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); } return retval; } static int cortexm_dap_write_coreregister_u32(struct target *target, uint32_t value, int regnum) { struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; int retval; uint32_t dcrdr; /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ if (target->dbg_msg_enabled) { retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); if (retval != ERROR_OK) return retval; } retval = mem_ap_write_u32(swjdp, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRSR, regnum | DCRSR_WnR); if (retval != ERROR_OK) return retval; if (target->dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a seperate * transaction otherwise the emulated DCC channel breaks */ if (retval == ERROR_OK) retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); } return retval; } static int cortex_m_write_debug_halt_mask(struct target *target, uint32_t mask_on, uint32_t mask_off) { struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; /* mask off status bits */ cortex_m->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off); /* create new register mask */ cortex_m->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on; return mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, cortex_m->dcb_dhcsr); } static int cortex_m_clear_halt(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; int retval; /* clear step if any */ cortex_m_write_debug_halt_mask(target, C_HALT, C_STEP); /* Read Debug Fault Status Register */ retval = mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m->nvic_dfsr); if (retval != ERROR_OK) return retval; /* Clear Debug Fault Status */ retval = mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m->nvic_dfsr); if (retval != ERROR_OK) return retval; LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr); return ERROR_OK; } static int cortex_m_single_step_core(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; uint32_t dhcsr_save; int retval; /* backup dhcsr reg */ dhcsr_save = cortex_m->dcb_dhcsr; /* Mask interrupts before clearing halt, if done already. This avoids * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing * HALT can put the core into an unknown state. */ if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) { retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN); if (retval != ERROR_OK) return retval; } retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN); if (retval != ERROR_OK) return retval; LOG_DEBUG(" "); /* restore dhcsr reg */ cortex_m->dcb_dhcsr = dhcsr_save; cortex_m_clear_halt(target); return ERROR_OK; } static int cortex_m_enable_fpb(struct target *target) { int retval = target_write_u32(target, FP_CTRL, 3); if (retval != ERROR_OK) return retval; /* check the fpb is actually enabled */ uint32_t fpctrl; retval = target_read_u32(target, FP_CTRL, &fpctrl); if (retval != ERROR_OK) return retval; if (fpctrl & 1) return ERROR_OK; return ERROR_FAIL; } static int cortex_m_endreset_event(struct target *target) { int i; int retval; uint32_t dcb_demcr; struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; struct cortex_m_fp_comparator *fp_list = cortex_m->fp_comparator_list; struct cortex_m_dwt_comparator *dwt_list = cortex_m->dwt_comparator_list; /* REVISIT The four debug monitor bits are currently ignored... */ retval = mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr); if (retval != ERROR_OK) return retval; LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr); /* this register is used for emulated dcc channel */ retval = mem_ap_write_u32(swjdp, DCB_DCRDR, 0); if (retval != ERROR_OK) return retval; /* Enable debug requests */ retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { retval = mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN); if (retval != ERROR_OK) return retval; } /* clear any interrupt masking */ cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS); /* Enable features controlled by ITM and DWT blocks, and catch only * the vectors we were told to pay attention to. * * Target firmware is responsible for all fault handling policy * choices *EXCEPT* explicitly scripted overrides like "vector_catch" * or manual updates to the NVIC SHCSR and CCR registers. */ retval = mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | armv7m->demcr); if (retval != ERROR_OK) return retval; /* Paranoia: evidently some (early?) chips don't preserve all the * debug state (including FBP, DWT, etc) across reset... */ /* Enable FPB */ retval = cortex_m_enable_fpb(target); if (retval != ERROR_OK) { LOG_ERROR("Failed to enable the FPB"); return retval; } cortex_m->fpb_enabled = 1; /* Restore FPB registers */ for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) { retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value); if (retval != ERROR_OK) return retval; } /* Restore DWT registers */ for (i = 0; i < cortex_m->dwt_num_comp; i++) { retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 0, dwt_list[i].comp); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 4, dwt_list[i].mask); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 8, dwt_list[i].function); if (retval != ERROR_OK) return retval; } retval = dap_run(swjdp); if (retval != ERROR_OK) return retval; register_cache_invalidate(armv7m->arm.core_cache); /* make sure we have latest dhcsr flags */ retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); return retval; } static int cortex_m_examine_debug_reason(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason * only check the debug reason if we don't know it already */ if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { if (cortex_m->nvic_dfsr & DFSR_BKPT) { target->debug_reason = DBG_REASON_BREAKPOINT; if (cortex_m->nvic_dfsr & DFSR_DWTTRAP) target->debug_reason = DBG_REASON_WPTANDBKPT; } else if (cortex_m->nvic_dfsr & DFSR_DWTTRAP) target->debug_reason = DBG_REASON_WATCHPOINT; else if (cortex_m->nvic_dfsr & DFSR_VCATCH) target->debug_reason = DBG_REASON_BREAKPOINT; else /* EXTERNAL, HALTED */ target->debug_reason = DBG_REASON_UNDEFINED; } return ERROR_OK; } static int cortex_m_examine_exception_reason(struct target *target) { uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1; struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; int retval; retval = mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr); if (retval != ERROR_OK) return retval; switch (armv7m->exception_number) { case 2: /* NMI */ break; case 3: /* Hard Fault */ retval = mem_ap_read_atomic_u32(swjdp, NVIC_HFSR, &except_sr); if (retval != ERROR_OK) return retval; if (except_sr & 0x40000000) { retval = mem_ap_read_u32(swjdp, NVIC_CFSR, &cfsr); if (retval != ERROR_OK) return retval; } break; case 4: /* Memory Management */ retval = mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(swjdp, NVIC_MMFAR, &except_ar); if (retval != ERROR_OK) return retval; break; case 5: /* Bus Fault */ retval = mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr); if (retval != ERROR_OK) return retval; retval = mem_ap_read_u32(swjdp, NVIC_BFAR, &except_ar); if (retval != ERROR_OK) return retval; break; case 6: /* Usage Fault */ retval = mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr); if (retval != ERROR_OK) return retval; break; case 11: /* SVCall */ break; case 12: /* Debug Monitor */ retval = mem_ap_read_u32(swjdp, NVIC_DFSR, &except_sr); if (retval != ERROR_OK) return retval; break; case 14: /* PendSV */ break; case 15: /* SysTick */ break; default: except_sr = 0; break; } retval = dap_run(swjdp); if (retval == ERROR_OK) LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32, armv7m_exception_string(armv7m->exception_number), shcsr, except_sr, cfsr, except_ar); return retval; } static int cortex_m_debug_entry(struct target *target) { int i; uint32_t xPSR; int retval; struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; struct arm *arm = &armv7m->arm; struct adiv5_dap *swjdp = armv7m->arm.dap; struct reg *r; LOG_DEBUG(" "); cortex_m_clear_halt(target); retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; retval = armv7m->examine_debug_reason(target); if (retval != ERROR_OK) return retval; /* Examine target state and mode * First load register accessible through core debug port */ int num_regs = arm->core_cache->num_regs; for (i = 0; i < num_regs; i++) { r = &armv7m->arm.core_cache->reg_list[i]; if (!r->valid) arm->read_core_reg(target, r, i, ARM_MODE_ANY); } r = arm->cpsr; xPSR = buf_get_u32(r->value, 0, 32); /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */ if (xPSR & 0xf00) { r->dirty = r->valid; cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff); } /* Are we in an exception handler */ if (xPSR & 0x1FF) { armv7m->exception_number = (xPSR & 0x1FF); arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { unsigned control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 2); /* is this thread privileged? */ arm->core_mode = control & 1 ? ARM_MODE_USER_THREAD : ARM_MODE_THREAD; /* which stack is it using? */ if (control & 2) arm->map = armv7m_psp_reg_map; else arm->map = armv7m_msp_reg_map; armv7m->exception_number = 0; } if (armv7m->exception_number) cortex_m_examine_exception_reason(target); LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s", arm_mode_name(arm->core_mode), buf_get_u32(arm->pc->value, 0, 32), target_state_name(target)); if (armv7m->post_debug_entry) { retval = armv7m->post_debug_entry(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int cortex_m_poll(struct target *target) { int detected_failure = ERROR_OK; int retval = ERROR_OK; enum target_state prev_target_state = target->state; struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; /* Read from Debug Halting Control and Status Register */ retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; return retval; } /* Recover from lockup. See ARMv7-M architecture spec, * section B1.5.15 "Unrecoverable exception cases". */ if (cortex_m->dcb_dhcsr & S_LOCKUP) { LOG_ERROR("%s -- clearing lockup after double fault", target_name(target)); cortex_m_write_debug_halt_mask(target, C_HALT, 0); target->debug_reason = DBG_REASON_DBGRQ; /* We have to execute the rest (the "finally" equivalent, but * still throw this exception again). */ detected_failure = ERROR_FAIL; /* refresh status bits */ retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; } if (cortex_m->dcb_dhcsr & S_RESET_ST) { target->state = TARGET_RESET; return ERROR_OK; } if (target->state == TARGET_RESET) { /* Cannot switch context while running so endreset is * called with target->state == TARGET_RESET */ LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32, cortex_m->dcb_dhcsr); retval = cortex_m_endreset_event(target); if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; return retval; } target->state = TARGET_RUNNING; prev_target_state = TARGET_RUNNING; } if (cortex_m->dcb_dhcsr & S_HALT) { target->state = TARGET_HALTED; if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) { retval = cortex_m_debug_entry(target); if (retval != ERROR_OK) return retval; if (arm_semihosting(target, &retval) != 0) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); } if (prev_target_state == TARGET_DEBUG_RUNNING) { LOG_DEBUG(" "); retval = cortex_m_debug_entry(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state. * How best to model low power modes? */ if (target->state == TARGET_UNKNOWN) { /* check if processor is retiring instructions */ if (cortex_m->dcb_dhcsr & S_RETIRE_ST) { target->state = TARGET_RUNNING; retval = ERROR_OK; } } /* Did we detect a failure condition that we cleared? */ if (detected_failure != ERROR_OK) retval = detected_failure; return retval; } static int cortex_m_halt(struct target *target) { LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { /* we came here in a reset_halt or reset_init sequence * debug entry was already prepared in cortex_m3_assert_reset() */ target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } } /* Write to Debug Halting Control and Status Register */ cortex_m_write_debug_halt_mask(target, C_HALT, 0); target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } static int cortex_m_soft_reset_halt(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; uint32_t dcb_dhcsr = 0; int retval, timeout = 0; /* soft_reset_halt is deprecated on cortex_m as the same functionality * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset' * As this reset only used VC_CORERESET it would only ever reset the cortex_m * core, not the peripherals */ LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead."); /* Enter debug state on reset; restore DEMCR in endreset_event() */ retval = mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); if (retval != ERROR_OK) return retval; /* Request a core-only reset */ retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET); if (retval != ERROR_OK) return retval; target->state = TARGET_RESET; /* registers are now invalid */ register_cache_invalidate(cortex_m->armv7m.arm.core_cache); while (timeout < 100) { retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr); if (retval == ERROR_OK) { retval = mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m->nvic_dfsr); if (retval != ERROR_OK) return retval; if ((dcb_dhcsr & S_HALT) && (cortex_m->nvic_dfsr & DFSR_VCATCH)) { LOG_DEBUG("system reset-halted, DHCSR 0x%08x, " "DFSR 0x%08x", (unsigned) dcb_dhcsr, (unsigned) cortex_m->nvic_dfsr); cortex_m_poll(target); /* FIXME restore user's vector catch config */ return ERROR_OK; } else LOG_DEBUG("waiting for system reset-halt, " "DHCSR 0x%08x, %d ms", (unsigned) dcb_dhcsr, timeout); } timeout++; alive_sleep(1); } return ERROR_OK; } void cortex_m_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; /* set any pending breakpoints */ while (breakpoint) { if (!breakpoint->set) cortex_m_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } } static int cortex_m_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct armv7m_common *armv7m = target_to_armv7m(target); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; struct reg *r; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); cortex_m_enable_breakpoints(target); cortex_m_enable_watchpoints(target); } if (debug_execution) { r = armv7m->arm.core_cache->reg_list + ARMV7M_PRIMASK; /* Disable interrupts */ /* We disable interrupts in the PRIMASK register instead of * masking with C_MASKINTS. This is probably the same issue * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS * in parallel with disabled interrupts can cause local faults * to not be taken. * * REVISIT this clearly breaks non-debug execution, since the * PRIMASK register state isn't saved/restored... workaround * by never resuming app code after debug execution. */ buf_set_u32(r->value, 0, 1, 1); r->dirty = true; r->valid = true; /* Make sure we are in Thumb mode */ r = armv7m->arm.cpsr; buf_set_u32(r->value, 24, 1, 1); r->dirty = true; r->valid = true; } /* current = 1: continue on current pc, otherwise continue at
*/ r = armv7m->arm.pc; if (!current) { buf_set_u32(r->value, 0, 32, address); r->dirty = true; r->valid = true; } /* if we halted last time due to a bkpt instruction * then we have to manually step over it, otherwise * the core will break again */ if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32)) && !debug_execution) armv7m_maybe_skip_bkpt_inst(target, NULL); resume_pc = buf_get_u32(r->value, 0, 32); armv7m_restore_context(target); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); cortex_m_single_step_core(target); cortex_m_set_breakpoint(target, breakpoint); } } /* Restart core */ cortex_m_write_debug_halt_mask(target, 0, C_HALT); target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ register_cache_invalidate(armv7m->arm.core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; } /* int irqstepcount = 0; */ static int cortex_m_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; struct adiv5_dap *swjdp = armv7m->arm.dap; struct breakpoint *breakpoint = NULL; struct reg *pc = armv7m->arm.pc; bool bkpt_inst_found = false; int retval; bool isr_timed_out = false; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(pc->value, 0, 32, address); uint32_t pc_value = buf_get_u32(pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { breakpoint = breakpoint_find(target, pc_value); if (breakpoint) cortex_m_unset_breakpoint(target, breakpoint); } armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found); target->debug_reason = DBG_REASON_SINGLESTEP; armv7m_restore_context(target); target_call_event_callbacks(target, TARGET_EVENT_RESUMED); /* if no bkpt instruction is found at pc then we can perform * a normal step, otherwise we have to manually step over the bkpt * instruction - as such simulate a step */ if (bkpt_inst_found == false) { /* Automatic ISR masking mode off: Just step over the next instruction */ if ((cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO)) cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); else { /* Process interrupts during stepping in a way they don't interfere * debugging. * * Principle: * * Set a temporary break point at the current pc and let the core run * with interrupts enabled. Pending interrupts get served and we run * into the breakpoint again afterwards. Then we step over the next * instruction with interrupts disabled. * * If the pending interrupts don't complete within time, we leave the * core running. This may happen if the interrupts trigger faster * than the core can process them or the handler doesn't return. * * If no more breakpoints are available we simply do a step with * interrupts enabled. * */ /* 2012-09-29 ph * * If a break point is already set on the lower half word then a break point on * the upper half word will not break again when the core is restarted. So we * just step over the instruction with interrupts disabled. * * The documentation has no information about this, it was found by observation * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 dosen't seem to * suffer from this problem. * * To add some confusion: pc_value has bit 0 always set, while the breakpoint * address has it always cleared. The former is done to indicate thumb mode * to gdb. * */ if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) { LOG_DEBUG("Stepping over next instruction with interrupts disabled"); cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0); cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); /* Re-enable interrupts */ cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS); } else { /* Set a temporary break point */ if (breakpoint) retval = cortex_m_set_breakpoint(target, breakpoint); else retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value)); bool tmp_bp_set = (retval == ERROR_OK); /* No more breakpoints left, just do a step */ if (!tmp_bp_set) cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); else { /* Start the core */ LOG_DEBUG("Starting core to serve pending interrupts"); int64_t t_start = timeval_ms(); cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP); /* Wait for pending handlers to complete or timeout */ do { retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; return retval; } isr_timed_out = ((timeval_ms() - t_start) > 500); } while (!((cortex_m->dcb_dhcsr & S_HALT) || isr_timed_out)); /* only remove breakpoint if we created it */ if (breakpoint) cortex_m_unset_breakpoint(target, breakpoint); else { /* Remove the temporary breakpoint */ breakpoint_remove(target, pc_value); } if (isr_timed_out) { LOG_DEBUG("Interrupt handlers didn't complete within time, " "leaving target running"); } else { /* Step over next instruction with interrupts disabled */ cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0); cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); /* Re-enable interrupts */ cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS); } } } } } retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; /* registers are now invalid */ register_cache_invalidate(armv7m->arm.core_cache); if (breakpoint) cortex_m_set_breakpoint(target, breakpoint); if (isr_timed_out) { /* Leave the core running. The user has to stop execution manually. */ target->debug_reason = DBG_REASON_NOTHALTED; target->state = TARGET_RUNNING; return ERROR_OK; } LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); retval = cortex_m_debug_entry(target); if (retval != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); return ERROR_OK; } static int cortex_m_assert_reset(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config; LOG_DEBUG("target->state: %s", target_state_name(target)); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ target_handle_event(target, TARGET_EVENT_RESET_ASSERT); register_cache_invalidate(cortex_m->armv7m.arm.core_cache); target->state = TARGET_RESET; return ERROR_OK; } /* some cores support connecting while srst is asserted * use that mode is it has been configured */ bool srst_asserted = false; if ((jtag_reset_config & RESET_HAS_SRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { adapter_assert_reset(); srst_asserted = true; } /* Enable debug requests */ int retval; retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { retval = mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN); if (retval != ERROR_OK) return retval; } /* If the processor is sleeping in a WFI or WFE instruction, the * C_HALT bit must be asserted to regain control */ if (cortex_m->dcb_dhcsr & S_SLEEP) { retval = mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval != ERROR_OK) return retval; } retval = mem_ap_write_u32(swjdp, DCB_DCRDR, 0); if (retval != ERROR_OK) return retval; if (!target->reset_halt) { /* Set/Clear C_MASKINTS in a separate operation */ if (cortex_m->dcb_dhcsr & C_MASKINTS) { retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT); if (retval != ERROR_OK) return retval; } /* clear any debug flags before resuming */ cortex_m_clear_halt(target); /* clear C_HALT in dhcsr reg */ cortex_m_write_debug_halt_mask(target, 0, C_HALT); } else { /* Halt in debug on reset; endreset_event() restores DEMCR. * * REVISIT catching BUSERR presumably helps to defend against * bad vector table entries. Should this include MMERR or * other flags too? */ retval = mem_ap_write_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); if (retval != ERROR_OK) return retval; } if (jtag_reset_config & RESET_HAS_SRST) { /* default to asserting srst */ if (!srst_asserted) adapter_assert_reset(); } else { /* Use a standard Cortex-M3 software reset mechanism. * We default to using VECRESET as it is supported on all current cores. * This has the disadvantage of not resetting the peripherals, so a * reset-init event handler is needed to perform any peripheral resets. */ LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ) ? "SYSRESETREQ" : "VECTRESET"); if (reset_config == CORTEX_M_RESET_VECTRESET) { LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event " "handler to reset any peripherals or configure hardware srst support."); } retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); if (retval != ERROR_OK) LOG_DEBUG("Ignoring AP write error right after reset"); retval = ahbap_debugport_init(swjdp); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); return retval; } { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI * after reset) on LM3S6918 -- Michael Schwingen */ uint32_t tmp; retval = mem_ap_read_atomic_u32(swjdp, NVIC_AIRCR, &tmp); if (retval != ERROR_OK) return retval; } } target->state = TARGET_RESET; jtag_add_sleep(50000); register_cache_invalidate(cortex_m->armv7m.arm.core_cache); if (target->reset_halt) { retval = target_halt(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int cortex_m_deassert_reset(struct target *target) { LOG_DEBUG("target->state: %s", target_state_name(target)); /* deassert reset lines */ adapter_deassert_reset(); enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_HAS_SRST) && !(jtag_reset_config & RESET_SRST_NO_GATING)) { int retval = ahbap_debugport_init(target_to_cm(target)->armv7m.arm.dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); return retval; } } return ERROR_OK; } int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval; int fp_num = 0; uint32_t hilo; struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; if (breakpoint->set) { LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id); return ERROR_OK; } if (cortex_m->auto_bp_type) breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address); if (breakpoint->type == BKPT_HARD) { while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code)) fp_num++; if (fp_num >= cortex_m->fp_num_code) { LOG_ERROR("Can not find free FPB Comparator!"); return ERROR_FAIL; } breakpoint->set = fp_num + 1; hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; comparator_list[fp_num].used = 1; comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "", fp_num, comparator_list[fp_num].fpcr_value); if (!cortex_m->fpb_enabled) { LOG_DEBUG("FPB wasn't enabled, do it now"); retval = cortex_m_enable_fpb(target); if (retval != ERROR_OK) { LOG_ERROR("Failed to enable the FPB"); return retval; } cortex_m->fpb_enabled = 1; } } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for * semihosting; don't use that. Otherwise the BKPT * parameter is arbitrary. */ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code); if (retval != ERROR_OK) return retval; breakpoint->set = true; } LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, breakpoint->length, breakpoint->set); return ERROR_OK; } int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval; struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, breakpoint->length, breakpoint->set); if (breakpoint->type == BKPT_HARD) { int fp_num = breakpoint->set - 1; if ((fp_num < 0) || (fp_num >= cortex_m->fp_num_code)) { LOG_DEBUG("Invalid FP Comparator number in breakpoint"); return ERROR_OK; } comparator_list[fp_num].used = 0; comparator_list[fp_num].fpcr_value = 0; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } else { retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } breakpoint->set = false; return ERROR_OK; } int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_m_common *cortex_m = target_to_cm(target); if (cortex_m->auto_bp_type) breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address); if (breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) { if (breakpoint->type == BKPT_HARD) { LOG_INFO("flash patch comparator requested outside code memory region"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_SOFT) { LOG_INFO("soft breakpoint requested in code (flash) memory region"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) { LOG_INFO("no flash patch comparator unit available for hardware breakpoint"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->length == 3) { LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request"); breakpoint->length = 2; } if ((breakpoint->length != 2)) { LOG_INFO("only breakpoints of two bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) cortex_m->fp_code_available--; return cortex_m_set_breakpoint(target, breakpoint); } int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct cortex_m_common *cortex_m = target_to_cm(target); /* REVISIT why check? FBP can be updated with core running ... */ if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (cortex_m->auto_bp_type) breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address); if (breakpoint->set) cortex_m_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) cortex_m->fp_code_available++; return ERROR_OK; } int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint) { int dwt_num = 0; uint32_t mask, temp; struct cortex_m_common *cortex_m = target_to_cm(target); /* watchpoint params were validated earlier */ mask = 0; temp = watchpoint->length; while (temp) { temp >>= 1; mask++; } mask--; /* REVISIT Don't fully trust these "not used" records ... users * may set up breakpoints by hand, e.g. dual-address data value * watchpoint using comparator #1; comparator #0 matching cycle * count; send data trace info through ITM and TPIU; etc */ struct cortex_m_dwt_comparator *comparator; for (comparator = cortex_m->dwt_comparator_list; comparator->used && dwt_num < cortex_m->dwt_num_comp; comparator++, dwt_num++) continue; if (dwt_num >= cortex_m->dwt_num_comp) { LOG_ERROR("Can not find free DWT Comparator"); return ERROR_FAIL; } comparator->used = 1; watchpoint->set = dwt_num + 1; comparator->comp = watchpoint->address; target_write_u32(target, comparator->dwt_comparator_address + 0, comparator->comp); comparator->mask = mask; target_write_u32(target, comparator->dwt_comparator_address + 4, comparator->mask); switch (watchpoint->rw) { case WPT_READ: comparator->function = 5; break; case WPT_WRITE: comparator->function = 6; break; case WPT_ACCESS: comparator->function = 7; break; } target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x", watchpoint->unique_id, dwt_num, (unsigned) comparator->comp, (unsigned) comparator->mask, (unsigned) comparator->function); return ERROR_OK; } int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_dwt_comparator *comparator; int dwt_num; if (!watchpoint->set) { LOG_WARNING("watchpoint (wpid: %d) not set", watchpoint->unique_id); return ERROR_OK; } dwt_num = watchpoint->set - 1; LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear", watchpoint->unique_id, dwt_num, (unsigned) watchpoint->address); if ((dwt_num < 0) || (dwt_num >= cortex_m->dwt_num_comp)) { LOG_DEBUG("Invalid DWT Comparator number in watchpoint"); return ERROR_OK; } comparator = cortex_m->dwt_comparator_list + dwt_num; comparator->used = 0; comparator->function = 0; target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); watchpoint->set = false; return ERROR_OK; } int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct cortex_m_common *cortex_m = target_to_cm(target); if (cortex_m->dwt_comp_available < 1) { LOG_DEBUG("no comparators?"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* hardware doesn't support data value masking */ if (watchpoint->mask != ~(uint32_t)0) { LOG_DEBUG("watchpoint value masks not supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* hardware allows address masks of up to 32K */ unsigned mask; for (mask = 0; mask < 16; mask++) { if ((1u << mask) == watchpoint->length) break; } if (mask == 16) { LOG_DEBUG("unsupported watchpoint length"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->address & ((1 << mask) - 1)) { LOG_DEBUG("watchpoint address is unaligned"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* Caller doesn't seem to be able to describe watching for data * values of zero; that flags "no value". * * REVISIT This DWT may well be able to watch for specific data * values. Requires comparator #1 to set DATAVMATCH and match * the data, and another comparator (DATAVADDR0) matching addr. */ if (watchpoint->value) { LOG_DEBUG("data value watchpoint not YET supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } cortex_m->dwt_comp_available--; LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available); return ERROR_OK; } int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct cortex_m_common *cortex_m = target_to_cm(target); /* REVISIT why check? DWT can be updated with core running ... */ if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (watchpoint->set) cortex_m_unset_watchpoint(target, watchpoint); cortex_m->dwt_comp_available++; LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available); return ERROR_OK; } void cortex_m_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; /* set any pending watchpoints */ while (watchpoint) { if (!watchpoint->set) cortex_m_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } } static int cortex_m_load_core_reg_u32(struct target *target, uint32_t num, uint32_t *value) { int retval; /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register * Selector values for R0..R15, xPSR, MSP, and PSP. */ switch (num) { case 0 ... 18: /* read a normal core register */ retval = cortexm_dap_read_coreregister_u32(target, value, num); if (retval != ERROR_OK) { LOG_ERROR("JTAG failure %i", retval); return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value); break; case ARMV7M_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRSR, 0x21); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); break; case ARMV7M_S0 ... ARMV7M_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, (int)(num - ARMV7M_S0), *value); break; case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: case ARMV7M_CONTROL: /* Cortex-M3 packages these four registers as bitfields * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ cortexm_dap_read_coreregister_u32(target, value, 20); switch (num) { case ARMV7M_PRIMASK: *value = buf_get_u32((uint8_t *)value, 0, 1); break; case ARMV7M_BASEPRI: *value = buf_get_u32((uint8_t *)value, 8, 8); break; case ARMV7M_FAULTMASK: *value = buf_get_u32((uint8_t *)value, 16, 1); break; case ARMV7M_CONTROL: *value = buf_get_u32((uint8_t *)value, 24, 2); break; } LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value) { int retval; uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register * Selector values for R0..R15, xPSR, MSP, and PSP. */ switch (num) { case 0 ... 18: retval = cortexm_dap_write_coreregister_u32(target, value, num); if (retval != ERROR_OK) { struct reg *r; LOG_ERROR("JTAG failure"); r = armv7m->arm.core_cache->reg_list + num; r->dirty = r->valid; return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value); break; case ARMV7M_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16)); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); break; case ARMV7M_S0 ... ARMV7M_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16)); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, (int)(num - ARMV7M_S0), value); break; case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: case ARMV7M_CONTROL: /* Cortex-M3 packages these four registers as bitfields * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ cortexm_dap_read_coreregister_u32(target, ®, 20); switch (num) { case ARMV7M_PRIMASK: buf_set_u32((uint8_t *)®, 0, 1, value); break; case ARMV7M_BASEPRI: buf_set_u32((uint8_t *)®, 8, 8, value); break; case ARMV7M_FAULTMASK: buf_set_u32((uint8_t *)®, 16, 1, value); break; case ARMV7M_CONTROL: buf_set_u32((uint8_t *)®, 24, 2, value); break; } cortexm_dap_write_coreregister_u32(target, reg, 20); LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } static int cortex_m_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; if (armv7m->arm.is_armv6m) { /* armv6m does not handle unaligned memory access */ if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; } return mem_ap_read(swjdp, buffer, size, count, address, true); } static int cortex_m_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; if (armv7m->arm.is_armv6m) { /* armv6m does not handle unaligned memory access */ if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; } return mem_ap_write(swjdp, buffer, size, count, address, true); } static int cortex_m_init_target(struct command_context *cmd_ctx, struct target *target) { armv7m_build_reg_cache(target); return ERROR_OK; } void cortex_m_deinit_target(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); free(cortex_m->fp_comparator_list); cortex_m_dwt_free(target); free(cortex_m); } /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid" * on r/w if the core is not running, and clear on resume or reset ... or * at least, in a post_restore_context() method. */ struct dwt_reg_state { struct target *target; uint32_t addr; uint8_t value[4]; /* scratch/cache */ }; static int cortex_m_dwt_get_reg(struct reg *reg) { struct dwt_reg_state *state = reg->arch_info; uint32_t tmp; int retval = target_read_u32(state->target, state->addr, &tmp); if (retval != ERROR_OK) return retval; buf_set_u32(state->value, 0, 32, tmp); return ERROR_OK; } static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf) { struct dwt_reg_state *state = reg->arch_info; return target_write_u32(state->target, state->addr, buf_get_u32(buf, 0, reg->size)); } struct dwt_reg { uint32_t addr; char *name; unsigned size; }; static struct dwt_reg dwt_base_regs[] = { { DWT_CTRL, "dwt_ctrl", 32, }, /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly * increments while the core is asleep. */ { DWT_CYCCNT, "dwt_cyccnt", 32, }, /* plus some 8 bit counters, useful for profiling with TPIU */ }; static struct dwt_reg dwt_comp[] = { #define DWT_COMPARATOR(i) \ { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \ { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \ { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, } DWT_COMPARATOR(0), DWT_COMPARATOR(1), DWT_COMPARATOR(2), DWT_COMPARATOR(3), #undef DWT_COMPARATOR }; static const struct reg_arch_type dwt_reg_type = { .get = cortex_m_dwt_get_reg, .set = cortex_m_dwt_set_reg, }; static void cortex_m_dwt_addreg(struct target *t, struct reg *r, struct dwt_reg *d) { struct dwt_reg_state *state; state = calloc(1, sizeof *state); if (!state) return; state->addr = d->addr; state->target = t; r->name = d->name; r->size = d->size; r->value = state->value; r->arch_info = state; r->type = &dwt_reg_type; } void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target) { uint32_t dwtcr; struct reg_cache *cache; struct cortex_m_dwt_comparator *comparator; int reg, i; target_read_u32(target, DWT_CTRL, &dwtcr); if (!dwtcr) { LOG_DEBUG("no DWT"); return; } cm->dwt_num_comp = (dwtcr >> 28) & 0xF; cm->dwt_comp_available = cm->dwt_num_comp; cm->dwt_comparator_list = calloc(cm->dwt_num_comp, sizeof(struct cortex_m_dwt_comparator)); if (!cm->dwt_comparator_list) { fail0: cm->dwt_num_comp = 0; LOG_ERROR("out of mem"); return; } cache = calloc(1, sizeof *cache); if (!cache) { fail1: free(cm->dwt_comparator_list); goto fail0; } cache->name = "Cortex-M DWT registers"; cache->num_regs = 2 + cm->dwt_num_comp * 3; cache->reg_list = calloc(cache->num_regs, sizeof *cache->reg_list); if (!cache->reg_list) { free(cache); goto fail1; } for (reg = 0; reg < 2; reg++) cortex_m_dwt_addreg(target, cache->reg_list + reg, dwt_base_regs + reg); comparator = cm->dwt_comparator_list; for (i = 0; i < cm->dwt_num_comp; i++, comparator++) { int j; comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i; for (j = 0; j < 3; j++, reg++) cortex_m_dwt_addreg(target, cache->reg_list + reg, dwt_comp + 3 * i + j); /* make sure we clear any watchpoints enabled on the target */ target_write_u32(target, comparator->dwt_comparator_address + 8, 0); } *register_get_last_cache_p(&target->reg_cache) = cache; cm->dwt_cache = cache; LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s", dwtcr, cm->dwt_num_comp, (dwtcr & (0xf << 24)) ? " only" : "/trigger"); /* REVISIT: if num_comp > 1, check whether comparator #1 can * implement single-address data value watchpoints ... so we * won't need to check it later, when asked to set one up. */ } static void cortex_m_dwt_free(struct target *target) { struct cortex_m_common *cm = target_to_cm(target); struct reg_cache *cache = cm->dwt_cache; free(cm->dwt_comparator_list); cm->dwt_comparator_list = NULL; if (cache) { register_unlink_cache(&target->reg_cache, cache); if (cache->reg_list) { for (size_t i = 0; i < cache->num_regs; i++) free(cache->reg_list[i].arch_info); free(cache->reg_list); } free(cache); } cm->dwt_cache = NULL; } #define MVFR0 0xe000ef40 #define MVFR1 0xe000ef44 #define MVFR0_DEFAULT_M4 0x10110021 #define MVFR1_DEFAULT_M4 0x11000011 int cortex_m_examine(struct target *target) { int retval; uint32_t cpuid, fpcr, mvfr0, mvfr1; int i; struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; struct armv7m_common *armv7m = target_to_armv7m(target); /* stlink shares the examine handler but does not support * all its calls */ if (!armv7m->stlink) { retval = ahbap_debugport_init(swjdp); if (retval != ERROR_OK) return retval; } if (!target_was_examined(target)) { target_set_examined(target); /* Read from Device Identification Registers */ retval = target_read_u32(target, CPUID, &cpuid); if (retval != ERROR_OK) return retval; /* Get CPU Type */ i = (cpuid >> 4) & 0xf; LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected", i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf)); LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid); /* test for floating point feature on cortex-m4 */ if (i == 4) { target_read_u32(target, MVFR0, &mvfr0); target_read_u32(target, MVFR1, &mvfr1); if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i); armv7m->fp_feature = FPv4_SP; } } else if (i == 0) { /* Cortex-M0 does not support unaligned memory access */ armv7m->arm.is_armv6m = true; } if (armv7m->fp_feature != FPv4_SP && armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { /* free unavailable FPU registers */ size_t idx; for (idx = ARMV7M_NUM_CORE_REGS_NOFP; idx < armv7m->arm.core_cache->num_regs; idx++) free(armv7m->arm.core_cache->reg_list[idx].value); armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; } if (i == 4 || i == 3) { /* Cortex-M3/M4 has 4096 bytes autoincrement range */ armv7m->dap.tar_autoincr_block = (1 << 12); } /* Configure trace modules */ retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr); if (retval != ERROR_OK) return retval; if (armv7m->trace_config.config_type != DISABLED) { armv7m_trace_tpiu_config(target); armv7m_trace_itm_config(target); } /* NOTE: FPB and DWT are both optional. */ /* Setup FPB */ target_read_u32(target, FP_CTRL, &fpcr); cortex_m->auto_bp_type = 1; /* bits [14:12] and [7:4] */ cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); cortex_m->fp_num_lit = (fpcr >> 8) & 0xF; cortex_m->fp_code_available = cortex_m->fp_num_code; free(cortex_m->fp_comparator_list); cortex_m->fp_comparator_list = calloc( cortex_m->fp_num_code + cortex_m->fp_num_lit, sizeof(struct cortex_m_fp_comparator)); cortex_m->fpb_enabled = fpcr & 1; for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) { cortex_m->fp_comparator_list[i].type = (i < cortex_m->fp_num_code) ? FPCR_CODE : FPCR_LITERAL; cortex_m->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i; /* make sure we clear any breakpoints enabled on the target */ target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0); } LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", fpcr, cortex_m->fp_num_code, cortex_m->fp_num_lit); /* Setup DWT */ cortex_m_dwt_free(target); cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", target_name(target), cortex_m->fp_num_code, cortex_m->dwt_num_comp); } return ERROR_OK; } static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctrl) { struct armv7m_common *armv7m = target_to_armv7m(target); struct adiv5_dap *swjdp = armv7m->arm.dap; uint16_t dcrdr; uint8_t buf[2]; int retval; retval = mem_ap_read(swjdp, buf, 2, 1, DCB_DCRDR, false); if (retval != ERROR_OK) return retval; dcrdr = target_buffer_get_u16(target, buf); *ctrl = (uint8_t)dcrdr; *value = (uint8_t)(dcrdr >> 8); LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl); /* write ack back to software dcc register * signify we have read data */ if (dcrdr & (1 << 0)) { target_buffer_set_u16(target, buf, 0); retval = mem_ap_write(swjdp, buf, 2, 1, DCB_DCRDR, false); if (retval != ERROR_OK) return retval; } return ERROR_OK; } static int cortex_m_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { uint8_t data; uint8_t ctrl; uint32_t i; for (i = 0; i < (size * 4); i++) { int retval = cortex_m_dcc_read(target, &data, &ctrl); if (retval != ERROR_OK) return retval; buffer[i] = data; } return ERROR_OK; } static int cortex_m_handle_target_request(void *priv) { struct target *target = priv; if (!target_was_examined(target)) return ERROR_OK; if (!target->dbg_msg_enabled) return ERROR_OK; if (target->state == TARGET_RUNNING) { uint8_t data; uint8_t ctrl; int retval; retval = cortex_m_dcc_read(target, &data, &ctrl); if (retval != ERROR_OK) return retval; /* check if we have data */ if (ctrl & (1 << 0)) { uint32_t request; /* we assume target is quick enough */ request = data; for (int i = 1; i <= 3; i++) { retval = cortex_m_dcc_read(target, &data, &ctrl); if (retval != ERROR_OK) return retval; request |= ((uint32_t)data << (i * 8)); } target_request(target, request); } } return ERROR_OK; } static int cortex_m_init_arch_info(struct target *target, struct cortex_m_common *cortex_m, struct jtag_tap *tap) { int retval; struct armv7m_common *armv7m = &cortex_m->armv7m; armv7m_init_arch_info(target, armv7m); /* prepare JTAG information for the new target */ cortex_m->jtag_info.tap = tap; cortex_m->jtag_info.scann_size = 4; /* default reset mode is to use srst if fitted * if not it will use CORTEX_M3_RESET_VECTRESET */ cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET; armv7m->arm.dap = &armv7m->dap; /* Leave (only) generic DAP stuff for debugport_init(); */ armv7m->dap.jtag_info = &cortex_m->jtag_info; armv7m->dap.memaccess_tck = 8; /* Cortex-M3/M4 has 4096 bytes autoincrement range * but set a safe default to 1024 to support Cortex-M0 * this will be changed in cortex_m3_examine if a M3/M4 is detected */ armv7m->dap.tar_autoincr_block = (1 << 10); /* register arch-specific functions */ armv7m->examine_debug_reason = cortex_m_examine_debug_reason; armv7m->post_debug_entry = NULL; armv7m->pre_restore_context = NULL; armv7m->load_core_reg_u32 = cortex_m_load_core_reg_u32; armv7m->store_core_reg_u32 = cortex_m_store_core_reg_u32; target_register_timer_callback(cortex_m_handle_target_request, 1, 1, target); retval = arm_jtag_setup_connection(&cortex_m->jtag_info); if (retval != ERROR_OK) return retval; return ERROR_OK; } static int cortex_m_target_create(struct target *target, Jim_Interp *interp) { struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common)); cortex_m->common_magic = CORTEX_M_COMMON_MAGIC; cortex_m_init_arch_info(target, cortex_m, target->tap); return ERROR_OK; } /*--------------------------------------------------------------------------*/ static int cortex_m_verify_pointer(struct command_context *cmd_ctx, struct cortex_m_common *cm) { if (cm->common_magic != CORTEX_M_COMMON_MAGIC) { command_print(cmd_ctx, "target is not a Cortex-M"); return ERROR_TARGET_INVALID; } return ERROR_OK; } /* * Only stuff below this line should need to verify that its target * is a Cortex-M3. Everything else should have indirected through the * cortexm3_target structure, which is only used with CM3 targets. */ static const struct { char name[10]; unsigned mask; } vec_ids[] = { { "hard_err", VC_HARDERR, }, { "int_err", VC_INTERR, }, { "bus_err", VC_BUSERR, }, { "state_err", VC_STATERR, }, { "chk_err", VC_CHKERR, }, { "nocp_err", VC_NOCPERR, }, { "mm_err", VC_MMERR, }, { "reset", VC_CORERESET, }, }; COMMAND_HANDLER(handle_cortex_m_vector_catch_command) { struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; struct adiv5_dap *swjdp = armv7m->arm.dap; uint32_t demcr = 0; int retval; retval = cortex_m_verify_pointer(CMD_CTX, cortex_m); if (retval != ERROR_OK) return retval; retval = mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr); if (retval != ERROR_OK) return retval; if (CMD_ARGC > 0) { unsigned catch = 0; if (CMD_ARGC == 1) { if (strcmp(CMD_ARGV[0], "all") == 0) { catch = VC_HARDERR | VC_INTERR | VC_BUSERR | VC_STATERR | VC_CHKERR | VC_NOCPERR | VC_MMERR | VC_CORERESET; goto write; } else if (strcmp(CMD_ARGV[0], "none") == 0) goto write; } while (CMD_ARGC-- > 0) { unsigned i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0) continue; catch |= vec_ids[i].mask; break; } if (i == ARRAY_SIZE(vec_ids)) { LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } } write: /* For now, armv7m->demcr only stores vector catch flags. */ armv7m->demcr = catch; demcr &= ~0xffff; demcr |= catch; /* write, but don't assume it stuck (why not??) */ retval = mem_ap_write_u32(swjdp, DCB_DEMCR, demcr); if (retval != ERROR_OK) return retval; retval = mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr); if (retval != ERROR_OK) return retval; /* FIXME be sure to clear DEMCR on clean server shutdown. * Otherwise the vector catch hardware could fire when there's * no debugger hooked up, causing much confusion... */ } for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD_CTX, "%9s: %s", vec_ids[i].name, (demcr & vec_ids[i].mask) ? "catch" : "ignore"); } return ERROR_OK; } COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command) { struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); int retval; static const Jim_Nvp nvp_maskisr_modes[] = { { .name = "auto", .value = CORTEX_M_ISRMASK_AUTO }, { .name = "off", .value = CORTEX_M_ISRMASK_OFF }, { .name = "on", .value = CORTEX_M_ISRMASK_ON }, { .name = NULL, .value = -1 }, }; const Jim_Nvp *n; retval = cortex_m_verify_pointer(CMD_CTX, cortex_m); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); return ERROR_OK; } if (CMD_ARGC > 0) { n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]); if (n->name == NULL) return ERROR_COMMAND_SYNTAX_ERROR; cortex_m->isrmasking_mode = n->value; if (cortex_m->isrmasking_mode == CORTEX_M_ISRMASK_ON) cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0); else cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS); } n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode); command_print(CMD_CTX, "cortex_m interrupt mask %s", n->name); return ERROR_OK; } COMMAND_HANDLER(handle_cortex_m_reset_config_command) { struct target *target = get_current_target(CMD_CTX); struct cortex_m_common *cortex_m = target_to_cm(target); int retval; char *reset_config; retval = cortex_m_verify_pointer(CMD_CTX, cortex_m); if (retval != ERROR_OK) return retval; if (CMD_ARGC > 0) { if (strcmp(*CMD_ARGV, "sysresetreq") == 0) cortex_m->soft_reset_config = CORTEX_M_RESET_SYSRESETREQ; else if (strcmp(*CMD_ARGV, "vectreset") == 0) cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET; } switch (cortex_m->soft_reset_config) { case CORTEX_M_RESET_SYSRESETREQ: reset_config = "sysresetreq"; break; case CORTEX_M_RESET_VECTRESET: reset_config = "vectreset"; break; default: reset_config = "unknown"; break; } command_print(CMD_CTX, "cortex_m reset_config %s", reset_config); return ERROR_OK; } static const struct command_registration cortex_m_exec_command_handlers[] = { { .name = "maskisr", .handler = handle_cortex_m_mask_interrupts_command, .mode = COMMAND_EXEC, .help = "mask cortex_m interrupts", .usage = "['auto'|'on'|'off']", }, { .name = "vector_catch", .handler = handle_cortex_m_vector_catch_command, .mode = COMMAND_EXEC, .help = "configure hardware vectors to trigger debug entry", .usage = "['all'|'none'|('bus_err'|'chk_err'|...)*]", }, { .name = "reset_config", .handler = handle_cortex_m_reset_config_command, .mode = COMMAND_ANY, .help = "configure software reset handling", .usage = "['srst'|'sysresetreq'|'vectreset']", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration cortex_m_command_handlers[] = { { .chain = armv7m_command_handlers, }, { .chain = armv7m_trace_command_handlers, }, { .name = "cortex_m", .mode = COMMAND_EXEC, .help = "Cortex-M command group", .usage = "", .chain = cortex_m_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; struct target_type cortexm_target = { .name = "cortex_m", .deprecated_name = "cortex_m3", .poll = cortex_m_poll, .arch_state = armv7m_arch_state, .target_request_data = cortex_m_target_request_data, .halt = cortex_m_halt, .resume = cortex_m_resume, .step = cortex_m_step, .assert_reset = cortex_m_assert_reset, .deassert_reset = cortex_m_deassert_reset, .soft_reset_halt = cortex_m_soft_reset_halt, .get_gdb_reg_list = armv7m_get_gdb_reg_list, .read_memory = cortex_m_read_memory, .write_memory = cortex_m_write_memory, .checksum_memory = armv7m_checksum_memory, .blank_check_memory = armv7m_blank_check_memory, .run_algorithm = armv7m_run_algorithm, .start_algorithm = armv7m_start_algorithm, .wait_algorithm = armv7m_wait_algorithm, .add_breakpoint = cortex_m_add_breakpoint, .remove_breakpoint = cortex_m_remove_breakpoint, .add_watchpoint = cortex_m_add_watchpoint, .remove_watchpoint = cortex_m_remove_watchpoint, .commands = cortex_m_command_handlers, .target_create = cortex_m_target_create, .init_target = cortex_m_init_target, .examine = cortex_m_examine, .deinit_target = cortex_m_deinit_target, }; openocd-0.9.0/src/target/cortex_m.h0000644000175000017500000001572712516456303014157 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef CORTEX_M_H #define CORTEX_M_H #include "armv7m.h" #define CORTEX_M_COMMON_MAGIC 0x1A451A45 #define SYSTEM_CONTROL_BASE 0x400FE000 #define ITM_TER0 0xE0000E00 #define ITM_TPR 0xE0000E40 #define ITM_TCR 0xE0000E80 #define ITM_LAR 0xE0000FB0 #define ITM_LAR_KEY 0xC5ACCE55 #define CPUID 0xE000ED00 /* Debug Control Block */ #define DCB_DHCSR 0xE000EDF0 #define DCB_DCRSR 0xE000EDF4 #define DCB_DCRDR 0xE000EDF8 #define DCB_DEMCR 0xE000EDFC #define DCRSR_WnR (1 << 16) #define DWT_CTRL 0xE0001000 #define DWT_CYCCNT 0xE0001004 #define DWT_COMP0 0xE0001020 #define DWT_MASK0 0xE0001024 #define DWT_FUNCTION0 0xE0001028 #define FP_CTRL 0xE0002000 #define FP_REMAP 0xE0002004 #define FP_COMP0 0xE0002008 #define FP_COMP1 0xE000200C #define FP_COMP2 0xE0002010 #define FP_COMP3 0xE0002014 #define FP_COMP4 0xE0002018 #define FP_COMP5 0xE000201C #define FP_COMP6 0xE0002020 #define FP_COMP7 0xE0002024 #define FPU_CPACR 0xE000ED88 #define FPU_FPCCR 0xE000EF34 #define FPU_FPCAR 0xE000EF38 #define FPU_FPDSCR 0xE000EF3C #define TPIU_SSPSR 0xE0040000 #define TPIU_CSPSR 0xE0040004 #define TPIU_ACPR 0xE0040010 #define TPIU_SPPR 0xE00400F0 #define TPIU_FFSR 0xE0040300 #define TPIU_FFCR 0xE0040304 #define TPIU_FSCR 0xE0040308 /* DCB_DHCSR bit and field definitions */ #define DBGKEY (0xA05F << 16) #define C_DEBUGEN (1 << 0) #define C_HALT (1 << 1) #define C_STEP (1 << 2) #define C_MASKINTS (1 << 3) #define S_REGRDY (1 << 16) #define S_HALT (1 << 17) #define S_SLEEP (1 << 18) #define S_LOCKUP (1 << 19) #define S_RETIRE_ST (1 << 24) #define S_RESET_ST (1 << 25) /* DCB_DEMCR bit and field definitions */ #define TRCENA (1 << 24) #define VC_HARDERR (1 << 10) #define VC_INTERR (1 << 9) #define VC_BUSERR (1 << 8) #define VC_STATERR (1 << 7) #define VC_CHKERR (1 << 6) #define VC_NOCPERR (1 << 5) #define VC_MMERR (1 << 4) #define VC_CORERESET (1 << 0) #define NVIC_ICTR 0xE000E004 #define NVIC_ISE0 0xE000E100 #define NVIC_ICSR 0xE000ED04 #define NVIC_AIRCR 0xE000ED0C #define NVIC_SHCSR 0xE000ED24 #define NVIC_CFSR 0xE000ED28 #define NVIC_MMFSRb 0xE000ED28 #define NVIC_BFSRb 0xE000ED29 #define NVIC_USFSRh 0xE000ED2A #define NVIC_HFSR 0xE000ED2C #define NVIC_DFSR 0xE000ED30 #define NVIC_MMFAR 0xE000ED34 #define NVIC_BFAR 0xE000ED38 /* NVIC_AIRCR bits */ #define AIRCR_VECTKEY (0x5FA << 16) #define AIRCR_SYSRESETREQ (1 << 2) #define AIRCR_VECTCLRACTIVE (1 << 1) #define AIRCR_VECTRESET (1 << 0) /* NVIC_SHCSR bits */ #define SHCSR_BUSFAULTENA (1 << 17) /* NVIC_DFSR bits */ #define DFSR_HALTED 1 #define DFSR_BKPT 2 #define DFSR_DWTTRAP 4 #define DFSR_VCATCH 8 #define FPCR_CODE 0 #define FPCR_LITERAL 1 #define FPCR_REPLACE_REMAP (0 << 30) #define FPCR_REPLACE_BKPT_LOW (1 << 30) #define FPCR_REPLACE_BKPT_HIGH (2 << 30) #define FPCR_REPLACE_BKPT_BOTH (3 << 30) struct cortex_m_fp_comparator { int used; int type; uint32_t fpcr_value; uint32_t fpcr_address; }; struct cortex_m_dwt_comparator { int used; uint32_t comp; uint32_t mask; uint32_t function; uint32_t dwt_comparator_address; }; enum cortex_m_soft_reset_config { CORTEX_M_RESET_SYSRESETREQ, CORTEX_M_RESET_VECTRESET, }; enum cortex_m_isrmasking_mode { CORTEX_M_ISRMASK_AUTO, CORTEX_M_ISRMASK_OFF, CORTEX_M_ISRMASK_ON, }; struct cortex_m_common { int common_magic; struct arm_jtag jtag_info; /* Context information */ uint32_t dcb_dhcsr; uint32_t nvic_dfsr; /* Debug Fault Status Register - shows reason for debug halt */ uint32_t nvic_icsr; /* Interrupt Control State Register - shows active and pending IRQ */ /* Flash Patch and Breakpoint (FPB) */ int fp_num_lit; int fp_num_code; int fp_code_available; int fpb_enabled; int auto_bp_type; struct cortex_m_fp_comparator *fp_comparator_list; /* Data Watchpoint and Trace (DWT) */ int dwt_num_comp; int dwt_comp_available; struct cortex_m_dwt_comparator *dwt_comparator_list; struct reg_cache *dwt_cache; enum cortex_m_soft_reset_config soft_reset_config; enum cortex_m_isrmasking_mode isrmasking_mode; struct armv7m_common armv7m; }; static inline struct cortex_m_common * target_to_cm(struct target *target) { return container_of(target->arch_info, struct cortex_m_common, armv7m); } int cortex_m_examine(struct target *target); int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint); int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint); int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint); int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint); int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint); int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); void cortex_m_enable_breakpoints(struct target *target); void cortex_m_enable_watchpoints(struct target *target); void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target); void cortex_m_deinit_target(struct target *target); #endif /* CORTEX_M_H */ openocd-0.9.0/src/target/nds32_aice.c0000644000175000017500000001215112315575361014233 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes technology. * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "nds32_aice.h" int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val) { if (aice->port->api->read_reg_64 == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->read_reg_64(aice->coreid, num, val); } int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val) { if (aice->port->api->write_reg_64 == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->write_reg_64(aice->coreid, num, val); } int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, uint32_t *physical_address) { if (aice->port->api->read_tlb == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->read_tlb(aice->coreid, virtual_address, physical_address); } int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address) { if (aice->port->api->cache_ctl == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->cache_ctl(aice->coreid, subtype, address); } int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times) { if (aice->port->api->set_retry_times == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_retry_times(a_retry_times); } int aice_program_edm(struct aice_port_s *aice, char *command_sequence) { if (aice->port->api->program_edm == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->program_edm(aice->coreid, command_sequence); } int aice_set_command_mode(struct aice_port_s *aice, enum aice_command_mode command_mode) { if (aice->port->api->set_command_mode == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_command_mode(command_mode); } int aice_execute(struct aice_port_s *aice, uint32_t *instructions, uint32_t instruction_num) { if (aice->port->api->execute == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->execute(aice->coreid, instructions, instruction_num); } int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script) { if (aice->port->api->set_custom_srst_script == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_custom_srst_script(script); } int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script) { if (aice->port->api->set_custom_trst_script == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_custom_trst_script(script); } int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script) { if (aice->port->api->set_custom_restart_script == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_custom_restart_script(script); } int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check) { if (aice->port->api->set_count_to_check_dbger == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->set_count_to_check_dbger(count_to_check); } int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration, uint32_t reg_no, uint32_t *samples, uint32_t *num_samples) { if (aice->port->api->profiling == NULL) { LOG_WARNING("Not implemented: %s", __func__); return ERROR_FAIL; } return aice->port->api->profiling(aice->coreid, interval, iteration, reg_no, samples, num_samples); } openocd-0.9.0/src/target/nds32_aice.h0000644000175000017500000001347412315575361014251 00000000000000/*************************************************************************** * Copyright (C) 2013 Andes technology. * * Hsiangkai Wang * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef __NDS32_AICE_H__ #define __NDS32_AICE_H__ #include int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val); int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val); int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, uint32_t *physical_address); int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address); int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times); int aice_program_edm(struct aice_port_s *aice, char *command_sequence); int aice_set_command_mode(struct aice_port_s *aice, enum aice_command_mode command_mode); int aice_execute(struct aice_port_s *aice, uint32_t *instructions, uint32_t instruction_num); int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script); int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script); int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script); int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check); int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration, uint32_t reg_no, uint32_t *samples, uint32_t *num_samples); static inline int aice_open(struct aice_port_s *aice, struct aice_port_param_s *param) { return aice->port->api->open(param); } static inline int aice_close(struct aice_port_s *aice) { return aice->port->api->close(); } static inline int aice_reset(struct aice_port_s *aice) { return aice->port->api->reset(); } static inline int aice_assert_srst(struct aice_port_s *aice, enum aice_srst_type_s srst) { return aice->port->api->assert_srst(aice->coreid, srst); } static inline int aice_run(struct aice_port_s *aice) { return aice->port->api->run(aice->coreid); } static inline int aice_halt(struct aice_port_s *aice) { return aice->port->api->halt(aice->coreid); } static inline int aice_step(struct aice_port_s *aice) { return aice->port->api->step(aice->coreid); } static inline int aice_read_register(struct aice_port_s *aice, uint32_t num, uint32_t *val) { return aice->port->api->read_reg(aice->coreid, num, val); } static inline int aice_write_register(struct aice_port_s *aice, uint32_t num, uint32_t val) { return aice->port->api->write_reg(aice->coreid, num, val); } static inline int aice_read_debug_reg(struct aice_port_s *aice, uint32_t addr, uint32_t *val) { return aice->port->api->read_debug_reg(aice->coreid, addr, val); } static inline int aice_write_debug_reg(struct aice_port_s *aice, uint32_t addr, const uint32_t val) { return aice->port->api->write_debug_reg(aice->coreid, addr, val); } static inline int aice_read_mem_unit(struct aice_port_s *aice, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { return aice->port->api->read_mem_unit(aice->coreid, addr, size, count, buffer); } static inline int aice_write_mem_unit(struct aice_port_s *aice, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { return aice->port->api->write_mem_unit(aice->coreid, addr, size, count, buffer); } static inline int aice_read_mem_bulk(struct aice_port_s *aice, uint32_t addr, uint32_t length, uint8_t *buffer) { return aice->port->api->read_mem_bulk(aice->coreid, addr, length, buffer); } static inline int aice_write_mem_bulk(struct aice_port_s *aice, uint32_t addr, uint32_t length, const uint8_t *buffer) { return aice->port->api->write_mem_bulk(aice->coreid, addr, length, buffer); } static inline int aice_idcode(struct aice_port_s *aice, uint32_t *idcode, uint8_t *num_of_idcode) { return aice->port->api->idcode(idcode, num_of_idcode); } static inline int aice_state(struct aice_port_s *aice, enum aice_target_state_s *state) { return aice->port->api->state(aice->coreid, state); } static inline int aice_set_jtag_clock(struct aice_port_s *aice, uint32_t a_clock) { return aice->port->api->set_jtag_clock(a_clock); } static inline int aice_memory_access(struct aice_port_s *aice, enum nds_memory_access a_access) { return aice->port->api->memory_access(aice->coreid, a_access); } static inline int aice_memory_mode(struct aice_port_s *aice, enum nds_memory_select mem_select) { return aice->port->api->memory_mode(aice->coreid, mem_select); } static inline int aice_set_data_endian(struct aice_port_s *aice, enum aice_target_endian target_data_endian) { return aice->port->api->set_data_endian(aice->coreid, target_data_endian); } #endif openocd-0.9.0/src/target/adi_v5_swd.c0000644000175000017500000003055412516456303014351 00000000000000/*************************************************************************** * * Copyright (C) 2010 by David Brownell * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ***************************************************************************/ /** * @file * Utilities to support ARM "Serial Wire Debug" (SWD), a low pin-count debug * link protocol used in cases where JTAG is not wanted. This is coupled to * recent versions of ARM's "CoreSight" debug framework. This specific code * is a transport level interface, with "target/arm_adi_v5.[hc]" code * understanding operation semantics, shared with the JTAG transport. * * Single-DAP support only. * * for details, see "ARM IHI 0031A" * ARM Debug Interface v5 Architecture Specification * especially section 5.3 for SWD protocol * * On many chips (most current Cortex-M3 parts) SWD is a run-time alternative * to JTAG. Boards may support one or both. There are also SWD-only chips, * (using SW-DP not SWJ-DP). * * Even boards that also support JTAG can benefit from SWD support, because * usually there's no way to access the SWO trace view mechanism in JTAG mode. * That is, trace access may require SWD support. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "arm_adi_v5.h" #include #include #include #include /* YUK! - but this is currently a global.... */ extern struct jtag_interface *jtag_interface; static bool do_sync; static void swd_finish_read(struct adiv5_dap *dap) { const struct swd_driver *swd = jtag_interface->swd; if (dap->last_read != NULL) { swd->read_reg(dap, swd_cmd(true, false, DP_RDBUFF), dap->last_read); dap->last_read = NULL; } } static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data); static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data); static void swd_clear_sticky_errors(struct adiv5_dap *dap) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); swd->write_reg(dap, swd_cmd(false, false, DP_ABORT), STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR); } static int swd_run_inner(struct adiv5_dap *dap) { const struct swd_driver *swd = jtag_interface->swd; int retval; retval = swd->run(dap); if (retval != ERROR_OK) { /* fault response */ dap->do_reconnect = true; } return retval; } static int swd_connect(struct adiv5_dap *dap) { uint32_t idcode; int status; /* FIXME validate transport config ... is the * configured DAP present (check IDCODE)? * Is *only* one DAP configured? * * MUST READ IDCODE */ /* Note, debugport_init() does setup too */ jtag_interface->swd->switch_seq(dap, JTAG_TO_SWD); dap->do_reconnect = false; swd_queue_dp_read(dap, DP_IDCODE, &idcode); /* force clear all sticky faults */ swd_clear_sticky_errors(dap); status = swd_run_inner(dap); if (status == ERROR_OK) { LOG_INFO("SWD IDCODE %#8.8" PRIx32, idcode); dap->do_reconnect = false; } else dap->do_reconnect = true; return status; } static inline int check_sync(struct adiv5_dap *dap) { return do_sync ? swd_run_inner(dap) : ERROR_OK; } static int swd_check_reconnect(struct adiv5_dap *dap) { if (dap->do_reconnect) return swd_connect(dap); return ERROR_OK; } static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); swd->write_reg(dap, swd_cmd(false, false, DP_ABORT), DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR); return check_sync(dap); } /** Select the DP register bank matching bits 7:4 of reg. */ static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg) { uint32_t select_dp_bank = (reg & 0x000000F0) >> 4; if (reg == DP_SELECT) return; if (select_dp_bank == dap->dp_bank_value) return; dap->dp_bank_value = select_dp_bank; select_dp_bank |= dap->ap_current | dap->ap_bank_value; swd_queue_dp_write(dap, DP_SELECT, select_dp_bank); } static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; swd_queue_dp_bankselect(dap, reg); swd->read_reg(dap, swd_cmd(true, false, reg), data); return check_sync(dap); } static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; swd_finish_read(dap); swd_queue_dp_bankselect(dap, reg); swd->write_reg(dap, swd_cmd(false, false, reg), data); return check_sync(dap); } /** Select the AP register bank matching bits 7:4 of reg. */ static void swd_queue_ap_bankselect(struct adiv5_dap *dap, unsigned reg) { uint32_t select_ap_bank = reg & 0x000000F0; if (select_ap_bank == dap->ap_bank_value) return; dap->ap_bank_value = select_ap_bank; select_ap_bank |= dap->ap_current | dap->dp_bank_value; swd_queue_dp_write(dap, DP_SELECT, select_ap_bank); } static int swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; swd_queue_ap_bankselect(dap, reg); swd->read_reg(dap, swd_cmd(true, true, reg), dap->last_read); dap->last_read = data; return check_sync(dap); } static int swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { const struct swd_driver *swd = jtag_interface->swd; assert(swd); int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; swd_finish_read(dap); swd_queue_ap_bankselect(dap, reg); swd->write_reg(dap, swd_cmd(false, true, reg), data); return check_sync(dap); } /** Executes all queued DAP operations. */ static int swd_run(struct adiv5_dap *dap) { swd_finish_read(dap); return swd_run_inner(dap); } const struct dap_ops swd_dap_ops = { .is_swd = true, .queue_dp_read = swd_queue_dp_read, .queue_dp_write = swd_queue_dp_write, .queue_ap_read = swd_queue_ap_read, .queue_ap_write = swd_queue_ap_write, .queue_ap_abort = swd_queue_ap_abort, .run = swd_run, }; /* * This represents the bits which must be sent out on TMS/SWDIO to * switch a DAP implemented using an SWJ-DP module into SWD mode. * These bits are stored (and transmitted) LSB-first. * * See the DAP-Lite specification, section 2.2.5 for information * about making the debug link select SWD or JTAG. (Similar info * is in a few other ARM documents.) */ static const uint8_t jtag2swd_bitseq[] = { /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, * putting both JTAG and SWD logic into reset state. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Switching sequence enables SWD and disables JTAG * NOTE: bits in the DP's IDCODE may expose the need for * an old/obsolete/deprecated sequence (0xb6 0xed). */ 0x9e, 0xe7, /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, * putting both JTAG and SWD logic into reset state. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; /** * Put the debug link into SWD mode, if the target supports it. * The link's initial mode may be either JTAG (for example, * with SWJ-DP after reset) or SWD. * * @param target Enters SWD mode (if possible). * * Note that targets using the JTAG-DP do not support SWD, and that * some targets which could otherwise support it may have have been * configured to disable SWD signaling * * @return ERROR_OK or else a fault code. */ int dap_to_swd(struct target *target) { struct arm *arm = target_to_arm(target); int retval; if (!arm->dap) { LOG_ERROR("SWD mode is not available"); return ERROR_FAIL; } LOG_DEBUG("Enter SWD mode"); /* REVISIT it's ugly to need to make calls to a "jtag" * subsystem if the link may not be in JTAG mode... */ retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq), jtag2swd_bitseq, TAP_INVALID); if (retval == ERROR_OK) retval = jtag_execute_queue(); /* set up the DAP's ops vector for SWD mode. */ arm->dap->ops = &swd_dap_ops; return retval; } COMMAND_HANDLER(handle_swd_wcr) { int retval; struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; uint32_t wcr; unsigned trn, scale = 0; switch (CMD_ARGC) { /* no-args: just dump state */ case 0: /*retval = swd_queue_dp_read(dap, DP_WCR, &wcr); */ retval = dap_queue_dp_read(dap, DP_WCR, &wcr); if (retval == ERROR_OK) dap->ops->run(dap); if (retval != ERROR_OK) { LOG_ERROR("can't read WCR?"); return retval; } command_print(CMD_CTX, "turnaround=%" PRIu32 ", prescale=%" PRIu32, WCR_TO_TRN(wcr), WCR_TO_PRESCALE(wcr)); return ERROR_OK; case 2: /* TRN and prescale */ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], scale); if (scale > 7) { LOG_ERROR("prescale %d is too big", scale); return ERROR_FAIL; } /* FALL THROUGH */ case 1: /* TRN only */ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], trn); if (trn < 1 || trn > 4) { LOG_ERROR("turnaround %d is invalid", trn); return ERROR_FAIL; } wcr = ((trn - 1) << 8) | scale; /* FIXME * write WCR ... * then, re-init adapter with new TRN */ LOG_ERROR("can't yet modify WCR"); return ERROR_FAIL; default: /* too many arguments */ return ERROR_COMMAND_SYNTAX_ERROR; } } static const struct command_registration swd_commands[] = { { /* * Set up SWD and JTAG targets identically, unless/until * infrastructure improves ... meanwhile, ignore all * JTAG-specific stuff like IR length for SWD. * * REVISIT can we verify "just one SWD DAP" here/early? */ .name = "newdap", .jim_handler = jim_jtag_newtap, .mode = COMMAND_CONFIG, .help = "declare a new SWD DAP" }, { .name = "wcr", .handler = handle_swd_wcr, .mode = COMMAND_ANY, .help = "display or update DAP's WCR register", .usage = "turnaround (1..4), prescale (0..7)", }, /* REVISIT -- add a command for SWV trace on/off */ COMMAND_REGISTRATION_DONE }; static const struct command_registration swd_handlers[] = { { .name = "swd", .mode = COMMAND_ANY, .help = "SWD command group", .chain = swd_commands, }, COMMAND_REGISTRATION_DONE }; static int swd_select(struct command_context *ctx) { int retval; retval = register_commands(ctx, NULL, swd_handlers); if (retval != ERROR_OK) return retval; const struct swd_driver *swd = jtag_interface->swd; /* be sure driver is in SWD mode; start * with hardware default TRN (1), it can be changed later */ if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) { LOG_DEBUG("no SWD driver?"); return ERROR_FAIL; } retval = swd->init(); if (retval != ERROR_OK) { LOG_DEBUG("can't init SWD driver"); return retval; } /* force DAP into SWD mode (not JTAG) */ /*retval = dap_to_swd(target);*/ if (ctx->current_target) { /* force DAP into SWD mode (not JTAG) */ struct target *target = get_current_target(ctx); retval = dap_to_swd(target); } return retval; } static int swd_init(struct command_context *ctx) { struct target *target = get_current_target(ctx); struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; /* Force the DAP's ops vector for SWD mode. * messy - is there a better way? */ arm->dap->ops = &swd_dap_ops; return swd_connect(dap); } static struct transport swd_transport = { .name = "swd", .select = swd_select, .init = swd_init, }; static void swd_constructor(void) __attribute__((constructor)); static void swd_constructor(void) { transport_register(&swd_transport); } /** Returns true if the current debug session * is using SWD as its transport. */ bool transport_is_swd(void) { return get_current_transport() == &swd_transport; } openocd-0.9.0/src/target/register.c0000644000175000017500000000704012516456304014144 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "register.h" #include /** * @file * Holds utilities to work with register caches. * * OpenOCD uses machine registers internally, and exposes them by name * to Tcl scripts. Sets of related registers are grouped into caches. * For example, a CPU core will expose a set of registers, and there * may be separate registers associated with debug or trace modules. */ struct reg *register_get_by_name(struct reg_cache *first, const char *name, bool search_all) { unsigned i; struct reg_cache *cache = first; while (cache) { for (i = 0; i < cache->num_regs; i++) { if (strcmp(cache->reg_list[i].name, name) == 0) return &(cache->reg_list[i]); } if (search_all) cache = cache->next; else break; } return NULL; } struct reg_cache **register_get_last_cache_p(struct reg_cache **first) { struct reg_cache **cache_p = first; if (*cache_p) while (*cache_p) cache_p = &((*cache_p)->next); else return first; return cache_p; } void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache) { while (*cache_p && *cache_p != cache) cache_p = &((*cache_p)->next); if (*cache_p) *cache_p = cache->next; } /** Marks the contents of the register cache as invalid (and clean). */ void register_cache_invalidate(struct reg_cache *cache) { struct reg *reg = cache->reg_list; for (unsigned n = cache->num_regs; n != 0; n--, reg++) { reg->valid = 0; reg->dirty = 0; } } static int register_get_dummy_core_reg(struct reg *reg) { return ERROR_OK; } static int register_set_dummy_core_reg(struct reg *reg, uint8_t *buf) { reg->dirty = 1; reg->valid = 1; return ERROR_OK; } static const struct reg_arch_type dummy_type = { .get = register_get_dummy_core_reg, .set = register_set_dummy_core_reg, }; void register_init_dummy(struct reg *reg) { reg->type = &dummy_type; } openocd-0.9.0/src/target/register.h0000644000175000017500000001034412516456304014152 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef REGISTER_H #define REGISTER_H struct target; enum reg_type { REG_TYPE_INT, REG_TYPE_INT8, REG_TYPE_INT16, REG_TYPE_INT32, REG_TYPE_INT64, REG_TYPE_INT128, REG_TYPE_UINT8, REG_TYPE_UINT16, REG_TYPE_UINT32, REG_TYPE_UINT64, REG_TYPE_UINT128, REG_TYPE_CODE_PTR, REG_TYPE_DATA_PTR, REG_TYPE_FLOAT, REG_TYPE_IEEE_SINGLE, REG_TYPE_IEEE_DOUBLE, REG_TYPE_ARCH_DEFINED, }; struct reg_feature { const char *name; }; struct reg_data_type_vector { struct reg_data_type *type; uint32_t count; }; struct reg_data_type_union_field { const char *name; struct reg_data_type *type; struct reg_data_type_union_field *next; }; struct reg_data_type_union { struct reg_data_type_union_field *fields; }; struct reg_data_type_bitfield { uint32_t start; uint32_t end; }; struct reg_data_type_struct_field { const char *name; bool use_bitfields; union { struct reg_data_type_bitfield *bitfield; struct reg_data_type *type; }; struct reg_data_type_struct_field *next; }; struct reg_data_type_struct { uint32_t size; struct reg_data_type_struct_field *fields; }; struct reg_data_type_flags_field { const char *name; struct reg_data_type_bitfield *bitfield; struct reg_data_type_flags_field *next; }; struct reg_data_type_flags { uint32_t size; struct reg_data_type_flags_field *fields; }; enum reg_data_type_class { REG_TYPE_CLASS_VECTOR, REG_TYPE_CLASS_UNION, REG_TYPE_CLASS_STRUCT, REG_TYPE_CLASS_FLAGS, }; struct reg_data_type { enum reg_type type; const char *id; enum reg_data_type_class type_class; union { struct reg_data_type_vector *reg_type_vector; struct reg_data_type_union *reg_type_union; struct reg_data_type_struct *reg_type_struct; struct reg_data_type_flags *reg_type_flags; }; }; struct reg { const char *name; uint32_t number; struct reg_feature *feature; bool caller_save; void *value; bool dirty; bool valid; bool exist; uint32_t size; struct reg_data_type *reg_data_type; const char *group; void *arch_info; const struct reg_arch_type *type; }; struct reg_cache { const char *name; struct reg_cache *next; struct reg *reg_list; unsigned num_regs; }; struct reg_arch_type { int (*get)(struct reg *reg); int (*set)(struct reg *reg, uint8_t *buf); }; struct reg *register_get_by_name(struct reg_cache *first, const char *name, bool search_all); struct reg_cache **register_get_last_cache_p(struct reg_cache **first); void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache); void register_cache_invalidate(struct reg_cache *cache); void register_init_dummy(struct reg *reg); #endif /* REGISTER_H */ openocd-0.9.0/src/target/armv4_5.c0000644000175000017500000013110312516456303013572 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by Oyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "armv4_5.h" #include "arm_jtag.h" #include "breakpoints.h" #include "arm_disassembler.h" #include #include "algorithm.h" #include "register.h" /* offsets into armv4_5 core register cache */ enum { /* ARMV4_5_CPSR = 31, */ ARMV4_5_SPSR_FIQ = 32, ARMV4_5_SPSR_IRQ = 33, ARMV4_5_SPSR_SVC = 34, ARMV4_5_SPSR_ABT = 35, ARMV4_5_SPSR_UND = 36, ARM_SPSR_MON = 41, }; static const uint8_t arm_usr_indices[17] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ARMV4_5_CPSR, }; static const uint8_t arm_fiq_indices[8] = { 16, 17, 18, 19, 20, 21, 22, ARMV4_5_SPSR_FIQ, }; static const uint8_t arm_irq_indices[3] = { 23, 24, ARMV4_5_SPSR_IRQ, }; static const uint8_t arm_svc_indices[3] = { 25, 26, ARMV4_5_SPSR_SVC, }; static const uint8_t arm_abt_indices[3] = { 27, 28, ARMV4_5_SPSR_ABT, }; static const uint8_t arm_und_indices[3] = { 29, 30, ARMV4_5_SPSR_UND, }; static const uint8_t arm_mon_indices[3] = { 39, 40, ARM_SPSR_MON, }; static const struct { const char *name; unsigned short psr; /* For user and system modes, these list indices for all registers. * otherwise they're just indices for the shadow registers and SPSR. */ unsigned short n_indices; const uint8_t *indices; } arm_mode_data[] = { /* Seven modes are standard from ARM7 on. "System" and "User" share * the same registers; other modes shadow from 3 to 8 registers. */ { .name = "User", .psr = ARM_MODE_USR, .n_indices = ARRAY_SIZE(arm_usr_indices), .indices = arm_usr_indices, }, { .name = "FIQ", .psr = ARM_MODE_FIQ, .n_indices = ARRAY_SIZE(arm_fiq_indices), .indices = arm_fiq_indices, }, { .name = "Supervisor", .psr = ARM_MODE_SVC, .n_indices = ARRAY_SIZE(arm_svc_indices), .indices = arm_svc_indices, }, { .name = "Abort", .psr = ARM_MODE_ABT, .n_indices = ARRAY_SIZE(arm_abt_indices), .indices = arm_abt_indices, }, { .name = "IRQ", .psr = ARM_MODE_IRQ, .n_indices = ARRAY_SIZE(arm_irq_indices), .indices = arm_irq_indices, }, { .name = "Undefined instruction", .psr = ARM_MODE_UND, .n_indices = ARRAY_SIZE(arm_und_indices), .indices = arm_und_indices, }, { .name = "System", .psr = ARM_MODE_SYS, .n_indices = ARRAY_SIZE(arm_usr_indices), .indices = arm_usr_indices, }, /* TrustZone "Security Extensions" add a secure monitor mode. * This is distinct from a "debug monitor" which can support * non-halting debug, in conjunction with some debuggers. */ { .name = "Secure Monitor", .psr = ARM_MODE_MON, .n_indices = ARRAY_SIZE(arm_mon_indices), .indices = arm_mon_indices, }, /* These special modes are currently only supported * by ARMv6M and ARMv7M profiles */ { .name = "Thread", .psr = ARM_MODE_THREAD, }, { .name = "Thread (User)", .psr = ARM_MODE_USER_THREAD, }, { .name = "Handler", .psr = ARM_MODE_HANDLER, }, }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ const char *arm_mode_name(unsigned psr_mode) { for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return arm_mode_data[i].name; } LOG_ERROR("unrecognized psr mode: %#02x", psr_mode); return "UNRECOGNIZED"; } /** Return true iff the parameter denotes a valid ARM processor mode. */ bool is_arm_mode(unsigned psr_mode) { for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return true; } return false; } /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */ int arm_mode_to_number(enum arm_mode mode) { switch (mode) { case ARM_MODE_ANY: /* map MODE_ANY to user mode */ case ARM_MODE_USR: return 0; case ARM_MODE_FIQ: return 1; case ARM_MODE_IRQ: return 2; case ARM_MODE_SVC: return 3; case ARM_MODE_ABT: return 4; case ARM_MODE_UND: return 5; case ARM_MODE_SYS: return 6; case ARM_MODE_MON: return 7; default: LOG_ERROR("invalid mode value encountered %d", mode); return -1; } } /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */ enum arm_mode armv4_5_number_to_mode(int number) { switch (number) { case 0: return ARM_MODE_USR; case 1: return ARM_MODE_FIQ; case 2: return ARM_MODE_IRQ; case 3: return ARM_MODE_SVC; case 4: return ARM_MODE_ABT; case 5: return ARM_MODE_UND; case 6: return ARM_MODE_SYS; case 7: return ARM_MODE_MON; default: LOG_ERROR("mode index out of bounds %d", number); return ARM_MODE_ANY; } } static const char *arm_state_strings[] = { "ARM", "Thumb", "Jazelle", "ThumbEE", }; /* Templates for ARM core registers. * * NOTE: offsets in this table are coupled to the arm_mode_data * table above, the armv4_5_core_reg_map array below, and also to * the ARMV4_5_CPSR symbol (which should vanish after ARM11 updates). */ static const struct { /* The name is used for e.g. the "regs" command. */ const char *name; /* The {cookie, mode} tuple uniquely identifies one register. * In a given mode, cookies 0..15 map to registers R0..R15, * with R13..R15 usually called SP, LR, PC. * * MODE_ANY is used as *input* to the mapping, and indicates * various special cases (sigh) and errors. * * Cookie 16 is (currently) confusing, since it indicates * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY. * (Exception modes have both CPSR and SPSR registers ...) */ unsigned cookie; unsigned gdb_index; enum arm_mode mode; } arm_core_regs[] = { /* IMPORTANT: we guarantee that the first eight cached registers * correspond to r0..r7, and the fifteenth to PC, so that callers * don't need to map them. */ { .name = "r0", .cookie = 0, .mode = ARM_MODE_ANY, .gdb_index = 0, }, { .name = "r1", .cookie = 1, .mode = ARM_MODE_ANY, .gdb_index = 1, }, { .name = "r2", .cookie = 2, .mode = ARM_MODE_ANY, .gdb_index = 2, }, { .name = "r3", .cookie = 3, .mode = ARM_MODE_ANY, .gdb_index = 3, }, { .name = "r4", .cookie = 4, .mode = ARM_MODE_ANY, .gdb_index = 4, }, { .name = "r5", .cookie = 5, .mode = ARM_MODE_ANY, .gdb_index = 5, }, { .name = "r6", .cookie = 6, .mode = ARM_MODE_ANY, .gdb_index = 6, }, { .name = "r7", .cookie = 7, .mode = ARM_MODE_ANY, .gdb_index = 7, }, /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging * them as MODE_ANY creates special cases. (ANY means * "not mapped" elsewhere; here it's "everything but FIQ".) */ { .name = "r8", .cookie = 8, .mode = ARM_MODE_ANY, .gdb_index = 8, }, { .name = "r9", .cookie = 9, .mode = ARM_MODE_ANY, .gdb_index = 9, }, { .name = "r10", .cookie = 10, .mode = ARM_MODE_ANY, .gdb_index = 10, }, { .name = "r11", .cookie = 11, .mode = ARM_MODE_ANY, .gdb_index = 11, }, { .name = "r12", .cookie = 12, .mode = ARM_MODE_ANY, .gdb_index = 12, }, /* Historical GDB mapping of indices: * - 13-14 are sp and lr, but banked counterparts are used * - 16-24 are left for deprecated 8 FPA + 1 FPS * - 25 is the cpsr */ /* NOTE all MODE_USR registers are equivalent to MODE_SYS ones */ { .name = "sp_usr", .cookie = 13, .mode = ARM_MODE_USR, .gdb_index = 26, }, { .name = "lr_usr", .cookie = 14, .mode = ARM_MODE_USR, .gdb_index = 27, }, /* guaranteed to be at index 15 */ { .name = "pc", .cookie = 15, .mode = ARM_MODE_ANY, .gdb_index = 15, }, { .name = "r8_fiq", .cookie = 8, .mode = ARM_MODE_FIQ, .gdb_index = 28, }, { .name = "r9_fiq", .cookie = 9, .mode = ARM_MODE_FIQ, .gdb_index = 29, }, { .name = "r10_fiq", .cookie = 10, .mode = ARM_MODE_FIQ, .gdb_index = 30, }, { .name = "r11_fiq", .cookie = 11, .mode = ARM_MODE_FIQ, .gdb_index = 31, }, { .name = "r12_fiq", .cookie = 12, .mode = ARM_MODE_FIQ, .gdb_index = 32, }, { .name = "sp_fiq", .cookie = 13, .mode = ARM_MODE_FIQ, .gdb_index = 33, }, { .name = "lr_fiq", .cookie = 14, .mode = ARM_MODE_FIQ, .gdb_index = 34, }, { .name = "sp_irq", .cookie = 13, .mode = ARM_MODE_IRQ, .gdb_index = 35, }, { .name = "lr_irq", .cookie = 14, .mode = ARM_MODE_IRQ, .gdb_index = 36, }, { .name = "sp_svc", .cookie = 13, .mode = ARM_MODE_SVC, .gdb_index = 37, }, { .name = "lr_svc", .cookie = 14, .mode = ARM_MODE_SVC, .gdb_index = 38, }, { .name = "sp_abt", .cookie = 13, .mode = ARM_MODE_ABT, .gdb_index = 39, }, { .name = "lr_abt", .cookie = 14, .mode = ARM_MODE_ABT, .gdb_index = 40, }, { .name = "sp_und", .cookie = 13, .mode = ARM_MODE_UND, .gdb_index = 41, }, { .name = "lr_und", .cookie = 14, .mode = ARM_MODE_UND, .gdb_index = 42, }, { .name = "cpsr", .cookie = 16, .mode = ARM_MODE_ANY, .gdb_index = 25, }, { .name = "spsr_fiq", .cookie = 16, .mode = ARM_MODE_FIQ, .gdb_index = 43, }, { .name = "spsr_irq", .cookie = 16, .mode = ARM_MODE_IRQ, .gdb_index = 44, }, { .name = "spsr_svc", .cookie = 16, .mode = ARM_MODE_SVC, .gdb_index = 45, }, { .name = "spsr_abt", .cookie = 16, .mode = ARM_MODE_ABT, .gdb_index = 46, }, { .name = "spsr_und", .cookie = 16, .mode = ARM_MODE_UND, .gdb_index = 47, }, /* These are only used for GDB target description, banked registers are accessed instead */ { .name = "sp", .cookie = 13, .mode = ARM_MODE_ANY, .gdb_index = 13, }, { .name = "lr", .cookie = 14, .mode = ARM_MODE_ANY, .gdb_index = 14, }, /* These exist only when the Security Extension (TrustZone) is present */ { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, .gdb_index = 48, }, { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, }, { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, }, }; /* map core mode (USR, FIQ, ...) and register number to * indices into the register cache */ const int armv4_5_core_reg_map[8][17] = { { /* USR */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31 }, { /* FIQ (8 shadows of USR, vs normal 3) */ 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32 }, { /* IRQ */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33 }, { /* SVC */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34 }, { /* ABT */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35 }, { /* UND */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36 }, { /* SYS (same registers as USR) */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31 }, { /* MON */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39, } }; /** * Configures host-side ARM records to reflect the specified CPSR. * Later, code can use arm_reg_current() to map register numbers * according to how they are exposed by this mode. */ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) { enum arm_mode mode = cpsr & 0x1f; int num; /* NOTE: this may be called very early, before the register * cache is set up. We can't defend against many errors, in * particular against CPSRs that aren't valid *here* ... */ if (arm->cpsr) { buf_set_u32(arm->cpsr->value, 0, 32, cpsr); arm->cpsr->valid = 1; arm->cpsr->dirty = 0; } arm->core_mode = mode; /* mode_to_number() warned; set up a somewhat-sane mapping */ num = arm_mode_to_number(mode); if (num < 0) { mode = ARM_MODE_USR; num = 0; } arm->map = &armv4_5_core_reg_map[num][0]; arm->spsr = (mode == ARM_MODE_USR || mode == ARM_MODE_SYS) ? NULL : arm->core_cache->reg_list + arm->map[16]; /* Older ARMs won't have the J bit */ enum arm_state state; if (cpsr & (1 << 5)) { /* T */ if (cpsr & (1 << 24)) { /* J */ LOG_WARNING("ThumbEE -- incomplete support"); state = ARM_STATE_THUMB_EE; } else state = ARM_STATE_THUMB; } else { if (cpsr & (1 << 24)) { /* J */ LOG_ERROR("Jazelle state handling is BROKEN!"); state = ARM_STATE_JAZELLE; } else state = ARM_STATE_ARM; } arm->core_state = state; LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, arm_mode_name(mode), arm_state_strings[arm->core_state]); } /** * Returns handle to the register currently mapped to a given number. * Someone must have called arm_set_cpsr() before. * * \param arm This core's state and registers are used. * \param regnum From 0..15 corresponding to R0..R14 and PC. * Note that R0..R7 don't require mapping; you may access those * as the first eight entries in the register cache. Likewise * R15 (PC) doesn't need mapping; you may also access it directly. * However, R8..R14, and SPSR (arm->spsr) *must* be mapped. * CPSR (arm->cpsr) is also not mapped. */ struct reg *arm_reg_current(struct arm *arm, unsigned regnum) { struct reg *r; if (regnum > 16) return NULL; if (!arm->map) { LOG_ERROR("Register map is not available yet, the target is not fully initialised"); r = arm->core_cache->reg_list + regnum; } else r = arm->core_cache->reg_list + arm->map[regnum]; /* e.g. invalid CPSR said "secure monitor" mode on a core * that doesn't support it... */ if (!r) { LOG_ERROR("Invalid CPSR mode"); r = arm->core_cache->reg_list + regnum; } return r; } static const uint8_t arm_gdb_dummy_fp_value[12]; static struct reg_feature arm_gdb_dummy_fp_features = { .name = "net.sourceforge.openocd.fake_fpa" }; /** * Dummy FPA registers are required to support GDB on ARM. * Register packets require eight obsolete FPA register values. * Modern ARM cores use Vector Floating Point (VFP), if they * have any floating point support. VFP is not FPA-compatible. */ struct reg arm_gdb_dummy_fp_reg = { .name = "GDB dummy FPA register", .value = (uint8_t *) arm_gdb_dummy_fp_value, .valid = 1, .size = 96, .exist = false, .number = 16, .feature = &arm_gdb_dummy_fp_features, .group = "fake_fpa", }; static const uint8_t arm_gdb_dummy_fps_value[4]; /** * Dummy FPA status registers are required to support GDB on ARM. * Register packets require an obsolete FPA status register. */ struct reg arm_gdb_dummy_fps_reg = { .name = "GDB dummy FPA status register", .value = (uint8_t *) arm_gdb_dummy_fps_value, .valid = 1, .size = 32, .exist = false, .number = 24, .feature = &arm_gdb_dummy_fp_features, .group = "fake_fpa", }; static void arm_gdb_dummy_init(void) __attribute__ ((constructor)); static void arm_gdb_dummy_init(void) { register_init_dummy(&arm_gdb_dummy_fp_reg); register_init_dummy(&arm_gdb_dummy_fps_reg); } static int armv4_5_get_core_reg(struct reg *reg) { int retval; struct arm_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } retval = reg_arch_info->arm->read_core_reg(target, reg, reg_arch_info->num, reg_arch_info->mode); if (retval == ERROR_OK) { reg->valid = 1; reg->dirty = 0; } return retval; } static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) { struct arm_reg *reg_arch_info = reg->arch_info; struct target *target = reg_arch_info->target; struct arm *armv4_5_target = target_to_arm(target); uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Except for CPSR, the "reg" command exposes a writeback model * for the register cache. */ if (reg == armv4_5_target->cpsr) { arm_set_cpsr(armv4_5_target, value); /* Older cores need help to be in ARM mode during halt * mode debug, so we clear the J and T bits if we flush. * For newer cores (v6/v7a/v7r) we don't need that, but * it won't hurt since CPSR is always flushed anyway. */ if (armv4_5_target->core_mode != (enum arm_mode)(value & 0x1f)) { LOG_DEBUG("changing ARM core mode to '%s'", arm_mode_name(value & 0x1f)); value &= ~((1 << 24) | (1 << 5)); uint8_t t[4]; buf_set_u32(t, 0, 32, value); armv4_5_target->write_core_reg(target, reg, 16, ARM_MODE_ANY, t); } } else { buf_set_u32(reg->value, 0, 32, value); reg->valid = 1; } reg->dirty = 1; return ERROR_OK; } static const struct reg_arch_type arm_reg_type = { .get = armv4_5_get_core_reg, .set = armv4_5_set_core_reg, }; struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) { int num_regs = ARRAY_SIZE(arm_core_regs); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); struct arm_reg *reg_arch_info = calloc(num_regs, sizeof(struct arm_reg)); int i; if (!cache || !reg_list || !reg_arch_info) { free(cache); free(reg_list); free(reg_arch_info); return NULL; } cache->name = "ARM registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = 0; for (i = 0; i < num_regs; i++) { /* Skip registers this core doesn't expose */ if (arm_core_regs[i].mode == ARM_MODE_MON && arm->core_type != ARM_MODE_MON) continue; /* REVISIT handle Cortex-M, which only shadows R13/SP */ reg_arch_info[i].num = arm_core_regs[i].cookie; reg_arch_info[i].mode = arm_core_regs[i].mode; reg_arch_info[i].target = target; reg_arch_info[i].arm = arm; reg_list[i].name = arm_core_regs[i].name; reg_list[i].number = arm_core_regs[i].gdb_index; reg_list[i].size = 32; reg_list[i].value = reg_arch_info[i].value; reg_list[i].type = &arm_reg_type; reg_list[i].arch_info = ®_arch_info[i]; reg_list[i].exist = true; /* This really depends on the calling convention in use */ reg_list[i].caller_save = false; /* Registers data type, as used by GDB target description */ reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type)); switch (arm_core_regs[i].cookie) { case 13: reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR; break; case 14: case 15: reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR; break; default: reg_list[i].reg_data_type->type = REG_TYPE_UINT32; break; } /* let GDB shows banked registers only in "info all-reg" */ reg_list[i].feature = malloc(sizeof(struct reg_feature)); if (reg_list[i].number <= 15 || reg_list[i].number == 25) { reg_list[i].feature->name = "org.gnu.gdb.arm.core"; reg_list[i].group = "general"; } else { reg_list[i].feature->name = "net.sourceforge.openocd.banked"; reg_list[i].group = "banked"; } cache->num_regs++; } arm->pc = reg_list + 15; arm->cpsr = reg_list + ARMV4_5_CPSR; arm->core_cache = cache; return cache; } int arm_arch_state(struct target *target) { struct arm *arm = target_to_arm(target); if (arm->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("BUG: called for a non-ARM target"); return ERROR_FAIL; } LOG_USER("target halted in %s state due to %s, current mode: %s\n" "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s", arm_state_strings[arm->core_state], debug_reason_name(target), arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), arm->is_semihosting ? ", semihosting" : ""); return ERROR_OK; } #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \ (cache->reg_list[armv4_5_core_reg_map[mode][num]]) COMMAND_HANDLER(handle_armv4_5_reg_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); struct reg *regs; if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (target->state != TARGET_HALTED) { command_print(CMD_CTX, "error: target must be halted for register accesses"); return ERROR_FAIL; } if (arm->core_type != ARM_MODE_ANY) { command_print(CMD_CTX, "Microcontroller Profile not supported - use standard reg cmd"); return ERROR_OK; } if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } if (!arm->full_context) { command_print(CMD_CTX, "error: target doesn't support %s", CMD_NAME); return ERROR_FAIL; } regs = arm->core_cache->reg_list; for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) { const char *name; char *sep = "\n"; char *shadow = ""; /* label this bank of registers (or shadows) */ switch (arm_mode_data[mode].psr) { case ARM_MODE_SYS: continue; case ARM_MODE_USR: name = "System and User"; sep = ""; break; case ARM_MODE_MON: if (arm->core_type != ARM_MODE_MON) continue; /* FALLTHROUGH */ default: name = arm_mode_data[mode].name; shadow = "shadow "; break; } command_print(CMD_CTX, "%s%s mode %sregisters", sep, name, shadow); /* display N rows of up to 4 registers each */ for (unsigned i = 0; i < arm_mode_data[mode].n_indices; ) { char output[80]; int output_len = 0; for (unsigned j = 0; j < 4; j++, i++) { uint32_t value; struct reg *reg = regs; if (i >= arm_mode_data[mode].n_indices) break; reg += arm_mode_data[mode].indices[i]; /* REVISIT be smarter about faults... */ if (!reg->valid) arm->full_context(target); value = buf_get_u32(reg->value, 0, 32); output_len += snprintf(output + output_len, sizeof(output) - output_len, "%8s: %8.8" PRIx32 " ", reg->name, value); } command_print(CMD_CTX, "%s", output); } } return ERROR_OK; } COMMAND_HANDLER(handle_armv4_5_core_state_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (arm->core_type == ARM_MODE_THREAD) { /* armv7m not supported */ command_print(CMD_CTX, "Unsupported Command"); return ERROR_OK; } if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "arm") == 0) arm->core_state = ARM_STATE_ARM; if (strcmp(CMD_ARGV[0], "thumb") == 0) arm->core_state = ARM_STATE_THUMB; } command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]); return ERROR_OK; } COMMAND_HANDLER(handle_arm_disassemble_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); if (target == NULL) { LOG_ERROR("No target selected"); return ERROR_FAIL; } struct arm *arm = target_to_arm(target); uint32_t address; int count = 1; int thumb = 0; if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (arm->core_type == ARM_MODE_THREAD) { /* armv7m is always thumb mode */ thumb = 1; } switch (CMD_ARGC) { case 3: if (strcmp(CMD_ARGV[2], "thumb") != 0) goto usage; thumb = 1; /* FALL THROUGH */ case 2: COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count); /* FALL THROUGH */ case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); if (address & 0x01) { if (!thumb) { command_print(CMD_CTX, "Disassemble as Thumb"); thumb = 1; } address &= ~1; } break; default: usage: count = 0; retval = ERROR_COMMAND_SYNTAX_ERROR; } while (count-- > 0) { struct arm_instruction cur_instruction; if (thumb) { /* Always use Thumb2 disassembly for best handling * of 32-bit BL/BLX, and to work with newer cores * (some ARMv6, all ARMv7) that use Thumb2. */ retval = thumb2_opcode(target, address, &cur_instruction); if (retval != ERROR_OK) break; } else { uint32_t opcode; retval = target_read_u32(target, address, &opcode); if (retval != ERROR_OK) break; retval = arm_evaluate_opcode(opcode, address, &cur_instruction) != ERROR_OK; if (retval != ERROR_OK) break; } command_print(CMD_CTX, "%s", cur_instruction.text); address += cur_instruction.instruction_size; } return retval; } static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; struct arm *arm; int retval; context = current_command_context(interp); assert(context != NULL); target = get_current_target(context); if (target == NULL) { LOG_ERROR("%s: no current target", __func__); return JIM_ERR; } if (!target_was_examined(target)) { LOG_ERROR("%s: not yet examined", target_name(target)); return JIM_ERR; } arm = target_to_arm(target); if (!is_arm(arm)) { LOG_ERROR("%s: not an ARM", target_name(target)); return JIM_ERR; } if ((argc < 6) || (argc > 7)) { /* FIXME use the command name to verify # params... */ LOG_ERROR("%s: wrong number of arguments", __func__); return JIM_ERR; } int cpnum; uint32_t op1; uint32_t op2; uint32_t CRn; uint32_t CRm; uint32_t value; long l; /* NOTE: parameter sequence matches ARM instruction set usage: * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX * The "rX" is necessarily omitted; it uses Tcl mechanisms. */ retval = Jim_GetLong(interp, argv[1], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "coprocessor", (int) l); return JIM_ERR; } cpnum = l; retval = Jim_GetLong(interp, argv[2], &l); if (retval != JIM_OK) return retval; if (l & ~0x7) { LOG_ERROR("%s: %s %d out of range", __func__, "op1", (int) l); return JIM_ERR; } op1 = l; retval = Jim_GetLong(interp, argv[3], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "CRn", (int) l); return JIM_ERR; } CRn = l; retval = Jim_GetLong(interp, argv[4], &l); if (retval != JIM_OK) return retval; if (l & ~0xf) { LOG_ERROR("%s: %s %d out of range", __func__, "CRm", (int) l); return JIM_ERR; } CRm = l; retval = Jim_GetLong(interp, argv[5], &l); if (retval != JIM_OK) return retval; if (l & ~0x7) { LOG_ERROR("%s: %s %d out of range", __func__, "op2", (int) l); return JIM_ERR; } op2 = l; value = 0; /* FIXME don't assume "mrc" vs "mcr" from the number of params; * that could easily be a typo! Check both... * * FIXME change the call syntax here ... simplest to just pass * the MRC() or MCR() instruction to be executed. That will also * let us support the "mrc2" and "mcr2" opcodes (toggling one bit) * if that's ever needed. */ if (argc == 7) { retval = Jim_GetLong(interp, argv[6], &l); if (retval != JIM_OK) return retval; value = l; /* NOTE: parameters reordered! */ /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */ retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value); if (retval != ERROR_OK) return JIM_ERR; } else { /* NOTE: parameters reordered! */ /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */ retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value); if (retval != ERROR_OK) return JIM_ERR; Jim_SetResult(interp, Jim_NewIntObj(interp, value)); } return JIM_OK; } COMMAND_HANDLER(handle_arm_semihosting_command) { struct target *target = get_current_target(CMD_CTX); if (target == NULL) { LOG_ERROR("No target selected"); return ERROR_FAIL; } struct arm *arm = target_to_arm(target); if (!is_arm(arm)) { command_print(CMD_CTX, "current target isn't an ARM"); return ERROR_FAIL; } if (!arm->setup_semihosting) { command_print(CMD_CTX, "semihosting not supported for current target"); return ERROR_FAIL; } if (CMD_ARGC > 0) { int semihosting; COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } if (arm->setup_semihosting(target, semihosting) != ERROR_OK) { LOG_ERROR("Failed to Configure semihosting"); return ERROR_FAIL; } /* FIXME never let that "catch" be dropped! */ arm->is_semihosting = semihosting; } command_print(CMD_CTX, "semihosting is %s", arm->is_semihosting ? "enabled" : "disabled"); return ERROR_OK; } static const struct command_registration arm_exec_command_handlers[] = { { .name = "reg", .handler = handle_armv4_5_reg_command, .mode = COMMAND_EXEC, .help = "display ARM core registers", .usage = "", }, { .name = "core_state", .handler = handle_armv4_5_core_state_command, .mode = COMMAND_EXEC, .usage = "['arm'|'thumb']", .help = "display/change ARM core state", }, { .name = "disassemble", .handler = handle_arm_disassemble_command, .mode = COMMAND_EXEC, .usage = "address [count ['thumb']]", .help = "disassemble instructions ", }, { .name = "mcr", .mode = COMMAND_EXEC, .jim_handler = &jim_mcrmrc, .help = "write coprocessor register", .usage = "cpnum op1 CRn CRm op2 value", }, { .name = "mrc", .jim_handler = &jim_mcrmrc, .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, { "semihosting", .handler = handle_arm_semihosting_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm_command_handlers[] = { { .name = "arm", .mode = COMMAND_ANY, .help = "ARM command group", .usage = "", .chain = arm_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct arm *arm = target_to_arm(target); unsigned int i; if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } switch (reg_class) { case REG_CLASS_GENERAL: *reg_list_size = 26; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) (*reg_list)[i] = arm_reg_current(arm, i); /* For GDB compatibility, take FPA registers size into account and zero-fill it*/ for (i = 16; i < 24; i++) (*reg_list)[i] = &arm_gdb_dummy_fp_reg; (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[25] = arm->cpsr; return ERROR_OK; break; case REG_CLASS_ALL: *reg_list_size = (arm->core_type != ARM_MODE_MON ? 48 : 51); *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) (*reg_list)[i] = arm_reg_current(arm, i); for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) { int reg_index = arm->core_cache->reg_list[i].number; if (!(arm_core_regs[i].mode == ARM_MODE_MON && arm->core_type != ARM_MODE_MON)) (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); } /* When we supply the target description, there is no need for fake FPA */ for (i = 16; i < 24; i++) { (*reg_list)[i] = &arm_gdb_dummy_fp_reg; (*reg_list)[i]->size = 0; } (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[24]->size = 0; return ERROR_OK; break; default: LOG_ERROR("not a valid register class type in query."); return ERROR_FAIL; break; } } /* wait for execution to complete and check exit point */ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval; struct arm *arm = target_to_arm(target); retval = target_wait_state(target, TARGET_HALTED, timeout_ms); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { retval = target_halt(target); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, 500); if (retval != ERROR_OK) return retval; return ERROR_TARGET_TIMEOUT; } /* fast exit: ARMv5+ code can use BKPT */ if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point) { LOG_WARNING( "target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "", buf_get_u32(arm->pc->value, 0, 32)); return ERROR_TARGET_TIMEOUT; } return ERROR_OK; } int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)) { struct arm *arm = target_to_arm(target); struct arm_algorithm *arm_algorithm_info = arch_info; enum arm_state core_state = arm->core_state; uint32_t context[17]; uint32_t cpsr; int exit_breakpoint_size = 0; int i; int retval = ERROR_OK; LOG_DEBUG("Running algorithm"); if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("current target isn't an ARMV4/5 target"); return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* armv5 and later can terminate with BKPT instruction; less overhead */ if (!exit_point && arm->is_armv4) { LOG_ERROR("ARMv4 target needs HW breakpoint location"); return ERROR_FAIL; } /* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure; * they'll be restored later. */ for (i = 0; i <= 16; i++) { struct reg *r; r = &ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i); if (!r->valid) arm->read_core_reg(target, r, i, arm_algorithm_info->core_mode); context[i] = buf_get_u32(r->value, 0, 32); } cpsr = buf_get_u32(arm->cpsr->value, 0, 32); for (i = 0; i < num_mem_params; i++) { retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) return retval; } for (i = 0; i < num_reg_params; i++) { struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } retval = armv4_5_set_core_reg(reg, reg_params[i].value); if (retval != ERROR_OK) return retval; } arm->core_state = arm_algorithm_info->core_state; if (arm->core_state == ARM_STATE_ARM) exit_breakpoint_size = 4; else if (arm->core_state == ARM_STATE_THUMB) exit_breakpoint_size = 2; else { LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state"); return ERROR_COMMAND_SYNTAX_ERROR; } if (arm_algorithm_info->core_mode != ARM_MODE_ANY) { LOG_DEBUG("setting core_mode: 0x%2.2x", arm_algorithm_info->core_mode); buf_set_u32(arm->cpsr->value, 0, 5, arm_algorithm_info->core_mode); arm->cpsr->dirty = 1; arm->cpsr->valid = 1; } /* terminate using a hardware or (ARMv5+) software breakpoint */ if (exit_point) { retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD); if (retval != ERROR_OK) { LOG_ERROR("can't add HW breakpoint to terminate algorithm"); return ERROR_TARGET_FAILURE; } } retval = target_resume(target, 0, entry_point, 1, 1); if (retval != ERROR_OK) return retval; retval = run_it(target, exit_point, timeout_ms, arch_info); if (exit_point) breakpoint_remove(target, exit_point); if (retval != ERROR_OK) return retval; for (i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) { int retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retvaltemp != ERROR_OK) retval = retvaltemp; } } for (i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); retval = ERROR_COMMAND_SYNTAX_ERROR; continue; } if (reg->size != reg_params[i].size) { LOG_ERROR( "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); retval = ERROR_COMMAND_SYNTAX_ERROR; continue; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } /* restore everything we saved before (17 or 18 registers) */ for (i = 0; i <= 16; i++) { uint32_t regvalue; regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32); if (regvalue != context[i]) { LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).name, context[i]); buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32, context[i]); ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).valid = 1; ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).dirty = 1; } } arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; arm->core_state = core_state; return retval; } int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion); } /** * Runs ARM code in the target to calculate a CRC32 checksum. * */ int arm_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct arm_algorithm arm_algo; struct arm *arm = target_to_arm(target); struct reg_param reg_params[2]; int retval; uint32_t i; uint32_t exit_var = 0; /* see contrib/loaders/checksum/armv4_5_crc.s for src */ static const uint32_t arm_crc_code[] = { 0xE1A02000, /* mov r2, r0 */ 0xE3E00000, /* mov r0, #0xffffffff */ 0xE1A03001, /* mov r3, r1 */ 0xE3A04000, /* mov r4, #0 */ 0xEA00000B, /* b ncomp */ /* nbyte: */ 0xE7D21004, /* ldrb r1, [r2, r4] */ 0xE59F7030, /* ldr r7, CRC32XOR */ 0xE0200C01, /* eor r0, r0, r1, asl 24 */ 0xE3A05000, /* mov r5, #0 */ /* loop: */ 0xE3500000, /* cmp r0, #0 */ 0xE1A06080, /* mov r6, r0, asl #1 */ 0xE2855001, /* add r5, r5, #1 */ 0xE1A00006, /* mov r0, r6 */ 0xB0260007, /* eorlt r0, r6, r7 */ 0xE3550008, /* cmp r5, #8 */ 0x1AFFFFF8, /* bne loop */ 0xE2844001, /* add r4, r4, #1 */ /* ncomp: */ 0xE1540003, /* cmp r4, r3 */ 0x1AFFFFF1, /* bne nbyte */ /* end: */ 0xe1200070, /* bkpt #0 */ /* CRC32XOR: */ 0x04C11DB7 /* .word 0x04C11DB7 */ }; retval = target_alloc_working_area(target, sizeof(arm_crc_code), &crc_algorithm); if (retval != ERROR_OK) return retval; /* convert code into a buffer in target endianness */ for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) { retval = target_write_u32(target, crc_algorithm->address + i * sizeof(uint32_t), arm_crc_code[i]); if (retval != ERROR_OK) return retval; } arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); buf_set_u32(reg_params[1].value, 0, 32, count); /* 20 second timeout/megabyte */ int timeout = 20000 * (1 + (count / (1024 * 1024))); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) exit_var = crc_algorithm->address + sizeof(arm_crc_code) - 8; retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, exit_var, timeout, &arm_algo); if (retval != ERROR_OK) { LOG_ERROR("error executing ARM crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); target_free_working_area(target, crc_algorithm); return retval; } *checksum = buf_get_u32(reg_params[0].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); target_free_working_area(target, crc_algorithm); return ERROR_OK; } /** * Runs ARM code in the target to check whether a memory block holds * all ones. NOR flash which has been erased, and thus may be written, * holds all ones. * */ int arm_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank) { struct working_area *check_algorithm; struct reg_param reg_params[3]; struct arm_algorithm arm_algo; struct arm *arm = target_to_arm(target); int retval; uint32_t i; uint32_t exit_var = 0; /* see contrib/loaders/erase_check/armv4_5_erase_check.s for src */ static const uint32_t check_code[] = { /* loop: */ 0xe4d03001, /* ldrb r3, [r0], #1 */ 0xe0022003, /* and r2, r2, r3 */ 0xe2511001, /* subs r1, r1, #1 */ 0x1afffffb, /* bne loop */ /* end: */ 0xe1200070, /* bkpt #0 */ }; /* make sure we have a working area */ retval = target_alloc_working_area(target, sizeof(check_code), &check_algorithm); if (retval != ERROR_OK) return retval; /* convert code into a buffer in target endianness */ for (i = 0; i < ARRAY_SIZE(check_code); i++) { retval = target_write_u32(target, check_algorithm->address + i * sizeof(uint32_t), check_code[i]); if (retval != ERROR_OK) return retval; } arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, 0xff); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) exit_var = check_algorithm->address + sizeof(check_code) - 4; retval = target_run_algorithm(target, 0, NULL, 3, reg_params, check_algorithm->address, exit_var, 10000, &arm_algo); if (retval != ERROR_OK) { destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); target_free_working_area(target, check_algorithm); return retval; } *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); target_free_working_area(target, check_algorithm); return ERROR_OK; } static int arm_full_context(struct target *target) { struct arm *arm = target_to_arm(target); unsigned num_regs = arm->core_cache->num_regs; struct reg *reg = arm->core_cache->reg_list; int retval = ERROR_OK; for (; num_regs && retval == ERROR_OK; num_regs--, reg++) { if (reg->valid) continue; retval = armv4_5_get_core_reg(reg); } return retval; } static int arm_default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { LOG_ERROR("%s doesn't implement MRC", target_type_name(target)); return ERROR_FAIL; } static int arm_default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) { LOG_ERROR("%s doesn't implement MCR", target_type_name(target)); return ERROR_FAIL; } int arm_init_arch_info(struct target *target, struct arm *arm) { target->arch_info = arm; arm->target = target; arm->common_magic = ARM_COMMON_MAGIC; /* core_type may be overridden by subtype logic */ if (arm->core_type != ARM_MODE_THREAD) { arm->core_type = ARM_MODE_ANY; arm_set_cpsr(arm, ARM_MODE_USR); } /* default full_context() has no core-specific optimizations */ if (!arm->full_context && arm->read_core_reg) arm->full_context = arm_full_context; if (!arm->mrc) arm->mrc = arm_default_mrc; if (!arm->mcr) arm->mcr = arm_default_mcr; return ERROR_OK; } openocd-0.9.0/src/target/armv4_5.h0000644000175000017500000000535412315575361013612 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009 by Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARMV4_5_H #define ARMV4_5_H /* This stuff "knows" that its callers aren't talking * to microcontroller profile (current Cortex-M) parts. * We want to phase it out so core code can be shared. */ /* OBSOLETE, DO NOT USE IN NEW CODE! The "number" of an arm_mode is an * index into the armv4_5_core_reg_map array. Its remaining users are * remnants which could as easily walk * the register cache directly as * use the expensive ARMV4_5_CORE_REG_MODE() macro. */ int arm_mode_to_number(enum arm_mode mode); enum arm_mode armv4_5_number_to_mode(int number); extern const int armv4_5_core_reg_map[8][17]; #define ARMV4_5_CORE_REG_MODE(cache, mode, num) \ (cache->reg_list[armv4_5_core_reg_map[arm_mode_to_number(mode)][num]]) /* offset into armv4_5 core register cache -- OBSOLETE, DO NOT USE! */ enum { ARMV4_5_CPSR = 31, }; #endif /* ARMV4_5_H */ openocd-0.9.0/src/target/arm7_9_common.c0000644000175000017500000025720312516456303014775 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * * Copyright (C) 2009 by David Brownell * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "breakpoints.h" #include "embeddedice.h" #include "target_request.h" #include "etm.h" #include #include "arm_simulator.h" #include "arm_semihosting.h" #include "algorithm.h" #include "register.h" #include "armv4_5.h" /** * @file * Hold common code supporting the ARM7 and ARM9 core generations. * * While the ARM core implementations evolved substantially during these * two generations, they look quite similar from the JTAG perspective. * Both have similar debug facilities, based on the same two scan chains * providing access to the core and to an EmbeddedICE module. Both can * support similar ETM and ETB modules, for tracing. And both expose * what could be viewed as "ARM Classic", with multiple processor modes, * shadowed registers, and support for the Thumb instruction set. * * Processor differences include things like presence or absence of MMU * and cache, pipeline sizes, use of a modified Harvard Architecure * (with separate instruction and data busses from the CPU), support * for cpu clock gating during idle, and more. */ static int arm7_9_debug_entry(struct target *target); /** * Clear watchpoints for an ARM7/9 target. * * @param arm7_9 Pointer to the common struct for an ARM7/9 target * @return JTAG error status after executing queue */ static int arm7_9_clear_watchpoints(struct arm7_9_common *arm7_9) { LOG_DEBUG("-"); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); arm7_9->sw_breakpoint_count = 0; arm7_9->sw_breakpoints_added = 0; arm7_9->wp0_used = 0; arm7_9->wp1_used = arm7_9->wp1_used_default; arm7_9->wp_available = arm7_9->wp_available_max; return jtag_execute_queue(); } /** * Assign a watchpoint to one of the two available hardware comparators in an * ARM7 or ARM9 target. * * @param arm7_9 Pointer to the common struct for an ARM7/9 target * @param breakpoint Pointer to the breakpoint to be used as a watchpoint */ static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *breakpoint) { if (!arm7_9->wp0_used) { arm7_9->wp0_used = 1; breakpoint->set = 1; arm7_9->wp_available--; } else if (!arm7_9->wp1_used) { arm7_9->wp1_used = 1; breakpoint->set = 2; arm7_9->wp_available--; } else LOG_ERROR("BUG: no hardware comparator available"); LOG_DEBUG("BPID: %" PRId32 " (0x%08" PRIx32 ") using hw wp: %d", breakpoint->unique_id, breakpoint->address, breakpoint->set); } /** * Setup an ARM7/9 target's embedded ICE registers for software breakpoints. * * @param arm7_9 Pointer to common struct for ARM7/9 targets * @return Error codes if there is a problem finding a watchpoint or the result * of executing the JTAG queue */ static int arm7_9_set_software_breakpoints(struct arm7_9_common *arm7_9) { if (arm7_9->sw_breakpoints_added) return ERROR_OK; if (arm7_9->wp_available < 1) { LOG_WARNING("can't enable sw breakpoints with no watchpoint unit available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } arm7_9->wp_available--; /* pick a breakpoint unit */ if (!arm7_9->wp0_used) { arm7_9->sw_breakpoints_added = 1; arm7_9->wp0_used = 3; } else if (!arm7_9->wp1_used) { arm7_9->sw_breakpoints_added = 2; arm7_9->wp1_used = 3; } else { LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1"); return ERROR_FAIL; } if (arm7_9->sw_breakpoints_added == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], arm7_9->arm_bkpt); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffffu); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); } else if (arm7_9->sw_breakpoints_added == 2) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], arm7_9->arm_bkpt); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0x0); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0xffffffffu); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE); } else { LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1"); return ERROR_FAIL; } LOG_DEBUG("SW BP using hw wp: %d", arm7_9->sw_breakpoints_added); return jtag_execute_queue(); } /** * Setup the common pieces for an ARM7/9 target after reset or on startup. * * @param target Pointer to an ARM7/9 target to setup * @return Result of clearing the watchpoints on the target */ static int arm7_9_setup(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); return arm7_9_clear_watchpoints(arm7_9); } /** * Set either a hardware or software breakpoint on an ARM7/9 target. The * breakpoint is set up even if it is already set. Some actions, e.g. reset, * might have erased the values in Embedded ICE. * * @param target Pointer to the target device to set the breakpoints on * @param breakpoint Pointer to the breakpoint to be set * @return For hardware breakpoints, this is the result of executing the JTAG * queue. For software breakpoints, this will be the status of the * required memory reads and writes */ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval = ERROR_OK; LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32 ", Type: %d", breakpoint->unique_id, breakpoint->address, breakpoint->type); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (breakpoint->type == BKPT_HARD) { /* either an ARM (4 byte) or Thumb (2 byte) breakpoint */ uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u; /* reassign a hw breakpoint */ if (breakpoint->set == 0) arm7_9_assign_wp(arm7_9, breakpoint); if (breakpoint->set == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], breakpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffffu); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); } else if (breakpoint->set == 2) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], breakpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE); } else { LOG_ERROR("BUG: no hardware comparator available"); return ERROR_OK; } retval = jtag_execute_queue(); } else if (breakpoint->type == BKPT_SOFT) { /* did we already set this breakpoint? */ if (breakpoint->set) return ERROR_OK; if (breakpoint->length == 4) { uint32_t verify = 0xffffffff; /* keep the original instruction in target endianness */ retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; /* write the breakpoint instruction in target * endianness (arm7_9->arm_bkpt is host endian) */ retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; if (verify != arm7_9->arm_bkpt) { LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } } else { uint16_t verify = 0xffff; /* keep the original instruction in target endianness */ retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; /* write the breakpoint instruction in target * endianness (arm7_9->thumb_bkpt is host endian) */ retval = target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; if (verify != arm7_9->thumb_bkpt) { LOG_ERROR("Unable to set thumb software breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } } retval = arm7_9_set_software_breakpoints(arm7_9); if (retval != ERROR_OK) return retval; arm7_9->sw_breakpoint_count++; breakpoint->set = 1; } return retval; } /** * Unsets an existing breakpoint on an ARM7/9 target. If it is a hardware * breakpoint, the watchpoint used will be freed and the Embedded ICE registers * will be updated. Otherwise, the software breakpoint will be restored to its * original instruction if it hasn't already been modified. * * @param target Pointer to ARM7/9 target to unset the breakpoint from * @param breakpoint Pointer to breakpoint to be unset * @return For hardware breakpoints, this is the result of executing the JTAG * queue. For software breakpoints, this will be the status of the * required memory reads and writes */ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32, breakpoint->unique_id, breakpoint->address); if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { LOG_DEBUG("BPID: %" PRId32 " Releasing hw wp: %d", breakpoint->unique_id, breakpoint->set); if (breakpoint->set == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); arm7_9->wp0_used = 0; arm7_9->wp_available++; } else if (breakpoint->set == 2) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); arm7_9->wp1_used = 0; arm7_9->wp_available++; } retval = jtag_execute_queue(); breakpoint->set = 0; } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { uint32_t current_instr; /* check that user program as not modified breakpoint instruction */ retval = target_read_memory(target, breakpoint->address, 4, 1, (uint8_t *)¤t_instr); if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); if (current_instr == arm7_9->arm_bkpt) { retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } else { uint16_t current_instr; /* check that user program as not modified breakpoint instruction */ retval = target_read_memory(target, breakpoint->address, 2, 1, (uint8_t *)¤t_instr); if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); if (current_instr == arm7_9->thumb_bkpt) retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } if (--arm7_9->sw_breakpoint_count == 0) { /* We have removed the last sw breakpoint, clear the hw breakpoint we used *to implement it */ if (arm7_9->sw_breakpoints_added == 1) embeddedice_set_reg(&arm7_9->eice_cache->reg_list[ EICE_W0_CONTROL_VALUE], 0); else if (arm7_9->sw_breakpoints_added == 2) embeddedice_set_reg(&arm7_9->eice_cache->reg_list[ EICE_W1_CONTROL_VALUE], 0); } breakpoint->set = 0; } return retval; } /** * Add a breakpoint to an ARM7/9 target. This makes sure that there are no * dangling breakpoints and that the desired breakpoint can be added. * * @param target Pointer to the target ARM7/9 device to add a breakpoint to * @param breakpoint Pointer to the breakpoint to be added * @return An error status if there is a problem adding the breakpoint or the * result of setting the breakpoint */ int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (arm7_9->breakpoint_count == 0) { /* make sure we don't have any dangling breakpoints. This is vital upon * GDB connect/disconnect */ arm7_9_clear_watchpoints(arm7_9); } if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1)) { LOG_INFO("no watchpoint unit available for hardware breakpoint"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if ((breakpoint->length != 2) && (breakpoint->length != 4)) { LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (breakpoint->type == BKPT_HARD) arm7_9_assign_wp(arm7_9, breakpoint); arm7_9->breakpoint_count++; return arm7_9_set_breakpoint(target, breakpoint); } /** * Removes a breakpoint from an ARM7/9 target. This will make sure there are no * dangling breakpoints and updates available watchpoints if it is a hardware * breakpoint. * * @param target Pointer to the target to have a breakpoint removed * @param breakpoint Pointer to the breakpoint to be removed * @return Error status if there was a problem unsetting the breakpoint or the * watchpoints could not be cleared */ int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); retval = arm7_9_unset_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; if (breakpoint->type == BKPT_HARD) arm7_9->wp_available++; arm7_9->breakpoint_count--; if (arm7_9->breakpoint_count == 0) { /* make sure we don't have any dangling breakpoints */ retval = arm7_9_clear_watchpoints(arm7_9); if (retval != ERROR_OK) return retval; } return ERROR_OK; } /** * Sets a watchpoint for an ARM7/9 target in one of the watchpoint units. It is * considered a bug to call this function when there are no available watchpoint * units. * * @param target Pointer to an ARM7/9 target to set a watchpoint on * @param watchpoint Pointer to the watchpoint to be set * @return Error status if watchpoint set fails or the result of executing the * JTAG queue */ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watchpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int rw_mask = 1; uint32_t mask; mask = watchpoint->length - 1; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (watchpoint->rw == WPT_ACCESS) rw_mask = 0; else rw_mask = 1; if (!arm7_9->wp0_used) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], watchpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], watchpoint->mask); if (watchpoint->mask != 0xffffffffu) embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], watchpoint->value); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1)); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; watchpoint->set = 1; arm7_9->wp0_used = 2; } else if (!arm7_9->wp1_used) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], watchpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], watchpoint->mask); if (watchpoint->mask != 0xffffffffu) embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], watchpoint->value); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1)); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; watchpoint->set = 2; arm7_9->wp1_used = 2; } else { LOG_ERROR("BUG: no hardware comparator available"); return ERROR_OK; } return ERROR_OK; } /** * Unset an existing watchpoint and clear the used watchpoint unit. * * @param target Pointer to the target to have the watchpoint removed * @param watchpoint Pointer to the watchpoint to be removed * @return Error status while trying to unset the watchpoint or the result of * executing the JTAG queue */ static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!watchpoint->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (watchpoint->set == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; arm7_9->wp0_used = 0; } else if (watchpoint->set == 2) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; arm7_9->wp1_used = 0; } watchpoint->set = 0; return ERROR_OK; } /** * Add a watchpoint to an ARM7/9 target. If there are no watchpoint units * available, an error response is returned. * * @param target Pointer to the ARM7/9 target to add a watchpoint to * @param watchpoint Pointer to the watchpoint to be added * @return Error status while trying to add the watchpoint */ int arm7_9_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (arm7_9->wp_available < 1) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4)) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; arm7_9->wp_available--; return ERROR_OK; } /** * Remove a watchpoint from an ARM7/9 target. The watchpoint will be unset and * the used watchpoint unit will be reopened. * * @param target Pointer to the target to remove a watchpoint from * @param watchpoint Pointer to the watchpoint to be removed * @return Result of trying to unset the watchpoint */ int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (watchpoint->set) { retval = arm7_9_unset_watchpoint(target, watchpoint); if (retval != ERROR_OK) return retval; } arm7_9->wp_available++; return ERROR_OK; } /** * Restarts the target by sending a RESTART instruction and moving the JTAG * state to IDLE. This includes a timeout waiting for DBGACK and SYSCOMP to be * asserted by the processor. * * @param target Pointer to target to issue commands to * @return Error status if there is a timeout or a problem while executing the * JTAG queue */ int arm7_9_execute_sys_speed(struct target *target) { int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; /* set RESTART instruction */ if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; } retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { /* read debug status register */ embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1)) && (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1))) break; if (debug_level >= 3) alive_sleep(100); else keep_alive(); } if (timeout) { LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32 "", buf_get_u32(dbg_stat->value, 0, dbg_stat->size)); return ERROR_TARGET_TIMEOUT; } return ERROR_OK; } /** * Restarts the target by sending a RESTART instruction and moving the JTAG * state to IDLE. This validates that DBGACK and SYSCOMP are set without * waiting until they are. * * @param target Pointer to the target to issue commands to * @return Always ERROR_OK */ static int arm7_9_execute_fast_sys_speed(struct target *target) { static int set; static uint8_t check_value[4], check_mask[4]; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; int retval; /* set RESTART instruction */ if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; } retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; if (!set) { /* check for DBGACK and SYSCOMP set (others don't care) */ /* NB! These are constants that must be available until after next jtag_execute() and * we evaluate the values upon first execution in lieu of setting up these constants * during early setup. * */ buf_set_u32(check_value, 0, 32, 0x9); buf_set_u32(check_mask, 0, 32, 0x9); set = 1; } /* read debug status register */ embeddedice_read_reg_w_check(dbg_stat, check_value, check_mask); return ERROR_OK; } /** * Get some data from the ARM7/9 target. * * @param target Pointer to the ARM7/9 target to read data from * @param size The number of 32bit words to be read * @param buffer Pointer to the buffer that will hold the data * @return The result of receiving data from the Embedded ICE unit */ int arm7_9_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; uint32_t *data; int retval = ERROR_OK; uint32_t i; data = malloc(size * (sizeof(uint32_t))); retval = embeddedice_receive(jtag_info, data, size); /* return the 32-bit ints in the 8-bit array */ for (i = 0; i < size; i++) h_u32_to_le(buffer + (i * 4), data[i]); free(data); return retval; } /** * Handles requests to an ARM7/9 target. If debug messaging is enabled, the * target is running and the DCC control register has the W bit high, this will * execute the request on the target. * * @param priv Void pointer expected to be a struct target pointer * @return ERROR_OK unless there are issues with the JTAG queue or when reading * from the Embedded ICE unit */ static int arm7_9_handle_target_request(void *priv) { int retval = ERROR_OK; struct target *target = priv; if (!target_was_examined(target)) return ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL]; if (!target->dbg_msg_enabled) return ERROR_OK; if (target->state == TARGET_RUNNING) { /* read DCC control register */ embeddedice_read_reg(dcc_control); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* check W bit */ if (buf_get_u32(dcc_control->value, 1, 1) == 1) { uint32_t request; retval = embeddedice_receive(jtag_info, &request, 1); if (retval != ERROR_OK) return retval; retval = target_request(target, request); if (retval != ERROR_OK) return retval; } } return ERROR_OK; } /** * Polls an ARM7/9 target for its current status. If DBGACK is set, the target * is manipulated to the right halted state based on its current state. This is * what happens: * * * * * * * * *
State Action
TARGET_RUNNING | TARGET_RESET Enters debug mode. If TARGET_RESET, pc may be checked
TARGET_UNKNOWN Warning is logged
TARGET_DEBUG_RUNNING Enters debug mode
TARGET_HALTED Nothing
* * If the target does not end up in the halted state, a warning is produced. If * DBGACK is cleared, then the target is expected to either be running or * running in debug. * * @param target Pointer to the ARM7/9 target to poll * @return ERROR_OK or an error status if a command fails */ int arm7_9_poll(struct target *target) { int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; /* read debug status register */ embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1)) { /* LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, *32));*/ if (target->state == TARGET_UNKNOWN) { /* Starting OpenOCD with target in debug-halt */ target->state = TARGET_RUNNING; LOG_DEBUG("DBGACK already set during server startup."); } if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { target->state = TARGET_HALTED; retval = arm7_9_debug_entry(target); if (retval != ERROR_OK) return retval; if (arm_semihosting(target, &retval) != 0) return retval; retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED); if (retval != ERROR_OK) return retval; } if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; retval = arm7_9_debug_entry(target); if (retval != ERROR_OK) return retval; retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); if (retval != ERROR_OK) return retval; } if (target->state != TARGET_HALTED) LOG_WARNING( "DBGACK set, but the target did not end up in the halted state %d", target->state); } else { if (target->state != TARGET_DEBUG_RUNNING) target->state = TARGET_RUNNING; } return ERROR_OK; } /** * Asserts the reset (SRST) on an ARM7/9 target. Some -S targets (ARM966E-S in * the STR912 isn't affected, ARM926EJ-S in the LPC3180 and AT91SAM9260 is * affected) completely stop the JTAG clock while the core is held in reset * (SRST). It isn't possible to program the halt condition once reset is * asserted, hence a hook that allows the target to set up its reset-halt * condition is setup prior to asserting reset. * * @param target Pointer to an ARM7/9 target to assert reset on * @return ERROR_FAIL if the JTAG device does not have SRST, otherwise ERROR_OK */ int arm7_9_assert_reset(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); enum reset_types jtag_reset_config = jtag_get_reset_config(); bool use_event = false; LOG_DEBUG("target->state: %s", target_state_name(target)); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) use_event = true; else if (!(jtag_reset_config & RESET_HAS_SRST)) { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* At this point trst has been asserted/deasserted once. We would * like to program EmbeddedICE while SRST is asserted, instead of * depending on SRST to leave that module alone. However, many CPUs * gate the JTAG clock while SRST is asserted; or JTAG may need * clock stability guarantees (adaptive clocking might help). * * So we assume JTAG access during SRST is off the menu unless it's * been specifically enabled. */ bool srst_asserted = false; if (!use_event && !(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); srst_asserted = true; } if (target->reset_halt) { /* * For targets that don't support communication while SRST is * asserted, we need to set up the reset vector catch first. * * When we use TRST+SRST and that's equivalent to a power-up * reset, these settings may well be reset anyway; so setting * them here won't matter. */ if (arm7_9->has_vector_catch) { /* program vector catch register to catch reset */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1); /* extra runtest added as issues were found with * certain ARM9 cores (maybe more) - AT91SAM9260 * and STR9 */ jtag_add_runtest(1, TAP_IDLE); } else { /* program watchpoint unit to match on reset vector * address */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); } } if (use_event) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); else { /* If we use SRST ... we'd like to issue just SRST, but the * board or chip may be set up so we have to assert TRST as * well. On some chips that combination is equivalent to a * power-up reset, and generally clobbers EICE state. */ if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else if (!srst_asserted) jtag_add_reset(0, 1); jtag_add_sleep(50000); } target->state = TARGET_RESET; register_cache_invalidate(arm7_9->arm.core_cache); /* REVISIT why isn't standard debug entry logic sufficient?? */ if (target->reset_halt && (!(jtag_reset_config & RESET_SRST_PULLS_TRST) || use_event)) { /* debug entry was prepared above */ target->debug_reason = DBG_REASON_DBGRQ; } return ERROR_OK; } /** * Deassert the reset (SRST) signal on an ARM7/9 target. If SRST pulls TRST * and the target is being reset into a halt, a warning will be triggered * because it is not possible to reset into a halted mode in this case. The * target is halted using the target's functions. * * @param target Pointer to the target to have the reset deasserted * @return ERROR_OK or an error from polling or halting the target */ int arm7_9_deassert_reset(struct target *target) { int retval = ERROR_OK; LOG_DEBUG("target->state: %s", target_state_name(target)); /* deassert reset lines */ jtag_add_reset(0, 0); /* In case polling is disabled, we need to examine the * target and poll here for this target to work correctly. * * Otherwise, e.g. halt will fail afterwards with bogus * error messages as halt will believe that reset is * still in effect. */ retval = target_examine_one(target); if (retval != ERROR_OK) return retval; retval = target_poll(target); if (retval != ERROR_OK) return retval; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target->reset_halt && (jtag_reset_config & RESET_SRST_PULLS_TRST) != 0) { LOG_WARNING( "srst pulls trst - can not reset into halted mode. Issuing halt after reset."); retval = target_halt(target); if (retval != ERROR_OK) return retval; } return retval; } /** * Clears the halt condition for an ARM7/9 target. If it isn't coming out of * reset and if DBGRQ is used, it is progammed to be deasserted. If the reset * vector catch was used, it is restored. Otherwise, the control value is * restored and the watchpoint unit is restored if it was in use. * * @param target Pointer to the ARM7/9 target to have halt cleared * @return Always ERROR_OK */ static int arm7_9_clear_halt(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; /* we used DBGRQ only if we didn't come out of reset */ if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq) { /* program EmbeddedICE Debug Control Register to deassert DBGRQ */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0); embeddedice_store_reg(dbg_ctrl); } else { if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch) { /* if we came out of reset, and vector catch is supported, we used * vector catch to enter debug state * restore the register in that case */ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]); } else { /* restore registers if watchpoint unit 0 was in use */ if (arm7_9->wp0_used) { if (arm7_9->debug_entry_from_reset) embeddedice_store_reg(&arm7_9->eice_cache->reg_list[ EICE_W0_ADDR_VALUE]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[ EICE_W0_ADDR_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[ EICE_W0_DATA_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[ EICE_W0_CONTROL_MASK]); } /* control value always has to be restored, as it was either disabled, * or enabled with possibly different bits */ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]); } } return ERROR_OK; } /** * Issue a software reset and halt to an ARM7/9 target. The target is halted * and then there is a wait until the processor shows the halt. This wait can * timeout and results in an error being returned. The software reset involves * clearing the halt, updating the debug control register, changing to ARM mode, * reset of the program counter, and reset of all of the registers. * * @param target Pointer to the ARM7/9 target to be reset and halted by software * @return Error status if any of the commands fail, otherwise ERROR_OK */ int arm7_9_soft_reset_halt(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int i; int retval; /* FIX!!! replace some of this code with tcl commands * * halt # the halt command is synchronous * armv4_5 core_state arm * */ retval = target_halt(target); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0) break; embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (debug_level >= 3) alive_sleep(100); else keep_alive(); } if (timeout) { LOG_ERROR("Failed to halt CPU after 1 sec"); return ERROR_TARGET_TIMEOUT; } target->state = TARGET_HALTED; /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS * ensure that DBGRQ is cleared */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1); buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0); buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1); embeddedice_store_reg(dbg_ctrl); retval = arm7_9_clear_halt(target); if (retval != ERROR_OK) return retval; /* if the target is in Thumb state, change to ARM state */ if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1)) { uint32_t r0_thumb, pc_thumb; LOG_DEBUG("target entered debug from Thumb state, changing to ARM"); /* Entered debug from Thumb mode */ arm->core_state = ARM_STATE_THUMB; arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); } /* REVISIT likewise for bit 5 -- switch Jazelle-to-ARM */ /* all register content is now invalid */ register_cache_invalidate(arm->core_cache); /* SVC, ARM state, IRQ and FIQ disabled */ uint32_t cpsr; cpsr = buf_get_u32(arm->cpsr->value, 0, 32); cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); arm->pc->dirty = 1; arm->pc->valid = 1; /* reset registers */ for (i = 0; i <= 14; i++) { struct reg *r = arm_reg_current(arm, i); buf_set_u32(r->value, 0, 32, 0xffffffff); r->dirty = 1; r->valid = 1; } retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED); if (retval != ERROR_OK) return retval; return ERROR_OK; } /** * Halt an ARM7/9 target. This is accomplished by either asserting the DBGRQ * line or by programming a watchpoint to trigger on any address. It is * considered a bug to call this function while the target is in the * TARGET_RESET state. * * @param target Pointer to the ARM7/9 target to be halted * @return Always ERROR_OK */ int arm7_9_halt(struct target *target) { if (target->state == TARGET_RESET) { LOG_ERROR( "BUG: arm7/9 does not support halt during reset. This is handled in arm7_9_assert_reset()"); return ERROR_OK; } struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("target was in unknown state when halt was requested"); if (arm7_9->use_dbgrq) { /* program EmbeddedICE Debug Control Register to assert DBGRQ */ if (arm7_9->set_special_dbgrq) arm7_9->set_special_dbgrq(target); else { buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 1); embeddedice_store_reg(dbg_ctrl); } } else { /* program watchpoint unit to match on any address */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); } target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } /** * Handle an ARM7/9 target's entry into debug mode. The halt is cleared on the * ARM. The JTAG queue is then executed and the reason for debug entry is * examined. Once done, the target is verified to be halted and the processor * is forced into ARM mode. The core registers are saved for the current core * mode and the program counter (register 15) is updated as needed. The core * registers and CPSR and SPSR are saved for restoration later. * * @param target Pointer to target that is entering debug mode * @return Error code if anything fails, otherwise ERROR_OK */ static int arm7_9_debug_entry(struct target *target) { int i; uint32_t context[16]; uint32_t *context_p[16]; uint32_t r0_thumb, pc_thumb; uint32_t cpsr, cpsr_mask = 0; int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; #ifdef _DEBUG_ARM7_9_ LOG_DEBUG("-"); #endif /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS * ensure that DBGRQ is cleared */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1); buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0); buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1); embeddedice_store_reg(dbg_ctrl); retval = arm7_9_clear_halt(target); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; retval = arm7_9->examine_debug_reason(target); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* if the target is in Thumb state, change to ARM state */ if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1)) { LOG_DEBUG("target entered debug from Thumb state"); /* Entered debug from Thumb mode */ arm->core_state = ARM_STATE_THUMB; cpsr_mask = 1 << 5; arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); LOG_DEBUG("r0_thumb: 0x%8.8" PRIx32 ", pc_thumb: 0x%8.8" PRIx32, r0_thumb, pc_thumb); } else if (buf_get_u32(dbg_stat->value, 5, 1)) { /* \todo Get some vaguely correct handling of Jazelle, if * anyone ever uses it and full info becomes available. * See ARM9EJS TRM B.7.1 for how to switch J->ARM; and * B.7.3 for the reverse. That'd be the bare minimum... */ LOG_DEBUG("target entered debug from Jazelle state"); arm->core_state = ARM_STATE_JAZELLE; cpsr_mask = 1 << 24; LOG_ERROR("Jazelle debug entry -- BROKEN!"); } else { LOG_DEBUG("target entered debug from ARM state"); /* Entered debug from ARM mode */ arm->core_state = ARM_STATE_ARM; } for (i = 0; i < 16; i++) context_p[i] = &context[i]; /* save core registers (r0 - r15 of current core mode) */ arm7_9->read_core_regs(target, 0xffff, context_p); arm7_9->read_xpsr(target, &cpsr, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; /* Sync our CPSR copy with J or T bits EICE reported, but * which we then erased by putting the core into ARM mode. */ arm_set_cpsr(arm, cpsr | cpsr_mask); if (!is_arm_mode(arm->core_mode)) { target->state = TARGET_UNKNOWN; LOG_ERROR("cpsr contains invalid mode value - communication failure"); return ERROR_TARGET_FAILURE; } LOG_DEBUG("target entered debug state in %s mode", arm_mode_name(arm->core_mode)); if (arm->core_state == ARM_STATE_THUMB) { LOG_DEBUG("thumb state, applying fixups"); context[0] = r0_thumb; context[15] = pc_thumb; } else if (arm->core_state == ARM_STATE_ARM) { /* adjust value stored by STM */ context[15] -= 3 * 4; } if ((target->debug_reason != DBG_REASON_DBGRQ) || (!arm7_9->use_dbgrq)) context[15] -= 3 * ((arm->core_state == ARM_STATE_ARM) ? 4 : 2); else context[15] -= arm7_9->dbgreq_adjust_pc * ((arm->core_state == ARM_STATE_ARM) ? 4 : 2); for (i = 0; i <= 15; i++) { struct reg *r = arm_reg_current(arm, i); LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, context[i]); buf_set_u32(r->value, 0, 32, context[i]); /* r0 and r15 (pc) have to be restored later */ r->dirty = (i == 0) || (i == 15); r->valid = 1; } LOG_DEBUG("entered debug state at PC 0x%" PRIx32 "", context[15]); /* exceptions other than USR & SYS have a saved program status register */ if (arm->spsr) { uint32_t spsr; arm7_9->read_xpsr(target, &spsr, 1); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; buf_set_u32(arm->spsr->value, 0, 32, spsr); arm->spsr->dirty = 0; arm->spsr->valid = 1; } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; if (arm7_9->post_debug_entry) { retval = arm7_9->post_debug_entry(target); if (retval != ERROR_OK) return retval; } return ERROR_OK; } /** * Validate the full context for an ARM7/9 target in all processor modes. If * there are any invalid registers for the target, they will all be read. This * includes the PSR. * * @param target Pointer to the ARM7/9 target to capture the full context from * @return Error if the target is not halted, has an invalid core mode, or if * the JTAG queue fails to execute */ static int arm7_9_full_context(struct target *target) { int i; int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND) * SYS shares registers with User, so we don't touch SYS */ for (i = 0; i < 6; i++) { uint32_t mask = 0; uint32_t *reg_p[16]; int j; int valid = 1; /* check if there are invalid registers in the current mode */ for (j = 0; j <= 16; j++) { if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid == 0) valid = 0; } if (!valid) { uint32_t tmp_cpsr; /* change processor mode (and mask T bit) */ tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xe0; tmp_cpsr |= armv4_5_number_to_mode(i); tmp_cpsr &= ~0x20; arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); for (j = 0; j < 15; j++) { if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid == 0) { reg_p[j] = (uint32_t *)ARMV4_5_CORE_REG_MODE( arm->core_cache, armv4_5_number_to_mode(i), j).value; mask |= 1 << j; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid = 1; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).dirty = 0; } } /* if only the PSR is invalid, mask is all zeroes */ if (mask) arm7_9->read_core_regs(target, mask, reg_p); /* check if the PSR has to be read */ if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), 16).valid == 0) { arm7_9->read_xpsr(target, (uint32_t *)ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), 16).value, 1); ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), 16).valid = 1; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0; } } } /* restore processor mode (mask T bit) */ arm7_9->write_xpsr_im8(target, buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; return ERROR_OK; } /** * Restore the processor context on an ARM7/9 target. The full processor * context is analyzed to see if any of the registers are dirty on this end, but * have a valid new value. If this is the case, the processor is changed to the * appropriate mode and the new register values are written out to the * processor. If there happens to be a dirty register with an invalid value, an * error will be logged. * * @param target Pointer to the ARM7/9 target to have its context restored * @return Error status if the target is not halted or the core mode in the * armv4_5 struct is invalid. */ static int arm7_9_restore_context(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *reg; enum arm_mode current_mode = arm->core_mode; int i, j; int dirty; int mode_change; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (arm7_9->pre_restore_context) arm7_9->pre_restore_context(target); if (!is_arm_mode(arm->core_mode)) { LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND) * SYS shares registers with User, so we don't touch SYS */ for (i = 0; i < 6; i++) { LOG_DEBUG("examining %s mode", arm_mode_name(arm->core_mode)); dirty = 0; mode_change = 0; /* check if there are dirty registers in the current mode */ for (j = 0; j <= 16; j++) { reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j); if (reg->dirty == 1) { if (reg->valid == 1) { dirty = 1; LOG_DEBUG("examining dirty reg: %s", reg->name); struct arm_reg *reg_arch_info; reg_arch_info = reg->arch_info; if ((reg_arch_info->mode != ARM_MODE_ANY) && (reg_arch_info->mode != current_mode) && !((reg_arch_info->mode == ARM_MODE_USR) && (arm->core_mode == ARM_MODE_SYS)) && !((reg_arch_info->mode == ARM_MODE_SYS) && (arm->core_mode == ARM_MODE_USR))) { mode_change = 1; LOG_DEBUG("require mode change"); } } else LOG_ERROR("BUG: dirty register '%s', but no valid data", reg->name); } } if (dirty) { uint32_t mask = 0x0; int num_regs = 0; uint32_t regs[16]; if (mode_change) { uint32_t tmp_cpsr; /* change processor mode (mask T bit) */ tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xe0; tmp_cpsr |= armv4_5_number_to_mode(i); tmp_cpsr &= ~0x20; arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); current_mode = armv4_5_number_to_mode(i); } for (j = 0; j <= 14; j++) { reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j); if (reg->dirty == 1) { regs[j] = buf_get_u32(reg->value, 0, 32); mask |= 1 << j; num_regs++; reg->dirty = 0; reg->valid = 1; LOG_DEBUG("writing register %i mode %s " "with value 0x%8.8" PRIx32, j, arm_mode_name(arm->core_mode), regs[j]); } } if (mask) arm7_9->write_core_regs(target, mask, regs); reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode( i), 16); struct arm_reg *reg_arch_info; reg_arch_info = reg->arch_info; if ((reg->dirty) && (reg_arch_info->mode != ARM_MODE_ANY)) { LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8" PRIx32 "", i, buf_get_u32(reg->value, 0, 32)); arm7_9->write_xpsr(target, buf_get_u32(reg->value, 0, 32), 1); } } } if (!arm->cpsr->dirty && (arm->core_mode != current_mode)) { /* restore processor mode (mask T bit) */ uint32_t tmp_cpsr; tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0; tmp_cpsr |= armv4_5_number_to_mode(i); tmp_cpsr &= ~0x20; LOG_DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", (unsigned)(tmp_cpsr)); arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); } else if (arm->cpsr->dirty) { /* CPSR has been changed, full restore necessary (mask T bit) */ LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32, buf_get_u32(arm->cpsr->value, 0, 32)); arm7_9->write_xpsr(target, buf_get_u32(arm->cpsr->value, 0, 32) & ~0x20, 0); arm->cpsr->dirty = 0; arm->cpsr->valid = 1; } /* restore PC */ LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); arm7_9->write_pc(target, buf_get_u32(arm->pc->value, 0, 32)); arm->pc->dirty = 0; return ERROR_OK; } /** * Restart the core of an ARM7/9 target. A RESTART command is sent to the * instruction register and the JTAG state is set to TAP_IDLE causing a core * restart. * * @param target Pointer to the ARM7/9 target to be restarted * @return Result of executing the JTAG queue */ static int arm7_9_restart_core(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; int retval; /* set RESTART instruction */ if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; } retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); if (retval != ERROR_OK) return retval; jtag_add_runtest(1, TAP_IDLE); return jtag_execute_queue(); } /** * Enable the watchpoints on an ARM7/9 target. The target's watchpoints are * iterated through and are set on the target if they aren't already set. * * @param target Pointer to the ARM7/9 target to enable watchpoints on */ static void arm7_9_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { if (watchpoint->set == 0) arm7_9_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } } /** * Enable the breakpoints on an ARM7/9 target. The target's breakpoints are * iterated through and are set on the target. * * @param target Pointer to the ARM7/9 target to enable breakpoints on */ static void arm7_9_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; /* set any pending breakpoints */ while (breakpoint) { arm7_9_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } } int arm7_9_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int err, retval = ERROR_OK; LOG_DEBUG("-"); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) target_free_all_working_areas(target); /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); uint32_t current_pc; current_pc = buf_get_u32(arm->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { struct breakpoint *breakpoint; breakpoint = breakpoint_find(target, buf_get_u32(arm->pc->value, 0, 32)); if (breakpoint != NULL) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %" PRId32, breakpoint->address, breakpoint->unique_id); retval = arm7_9_unset_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; /* calculate PC of next instruction */ uint32_t next_pc; retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) { uint32_t current_opcode; target_read_u32(target, current_pc, ¤t_opcode); LOG_ERROR( "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); return retval; } LOG_DEBUG("enable single-step"); arm7_9->enable_single_step(target, next_pc); target->debug_reason = DBG_REASON_SINGLESTEP; retval = arm7_9_restore_context(target); if (retval != ERROR_OK) return retval; if (arm->core_state == ARM_STATE_ARM) arm7_9->branch_resume(target); else if (arm->core_state == ARM_STATE_THUMB) arm7_9->branch_resume_thumb(target); else { LOG_ERROR("unhandled core state"); return ERROR_FAIL; } buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0); embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size)); err = arm7_9_execute_sys_speed(target); LOG_DEBUG("disable single-step"); arm7_9->disable_single_step(target); if (err != ERROR_OK) { retval = arm7_9_set_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; target->state = TARGET_UNKNOWN; return err; } retval = arm7_9_debug_entry(target); if (retval != ERROR_OK) return retval; LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); retval = arm7_9_set_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } } /* enable any pending breakpoints and watchpoints */ arm7_9_enable_breakpoints(target); arm7_9_enable_watchpoints(target); retval = arm7_9_restore_context(target); if (retval != ERROR_OK) return retval; if (arm->core_state == ARM_STATE_ARM) arm7_9->branch_resume(target); else if (arm->core_state == ARM_STATE_THUMB) arm7_9->branch_resume_thumb(target); else { LOG_ERROR("unhandled core state"); return ERROR_FAIL; } /* deassert DBGACK and INTDIS */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0); /* INTDIS only when we really resume, not during debug execution */ if (!debug_execution) buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 0); embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size)); retval = arm7_9_restart_core(target); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) { /* registers are now invalid */ register_cache_invalidate(arm->core_cache); target->state = TARGET_RUNNING; retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED); if (retval != ERROR_OK) return retval; } else { target->state = TARGET_DEBUG_RUNNING; retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); if (retval != ERROR_OK) return retval; } LOG_DEBUG("target resumed"); return ERROR_OK; } void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; uint32_t current_pc; current_pc = buf_get_u32(arm->pc->value, 0, 32); if (next_pc != current_pc) { /* setup an inverse breakpoint on the current PC * - comparator 1 matches the current address * - rangeout from comparator 1 is connected to comparator 0 rangein * - comparator 0 matches any address, as long as rangein is low */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~(EICE_W_CTRL_RANGE | EICE_W_CTRL_nOPC) & 0xff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], current_pc); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); } else { embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], next_pc); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); } } void arm7_9_disable_eice_step(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK]); embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]); } int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct breakpoint *breakpoint = NULL; int err, retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); uint32_t current_pc = buf_get_u32(arm->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) breakpoint = breakpoint_find(target, current_pc); if (breakpoint != NULL) { retval = arm7_9_unset_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } target->debug_reason = DBG_REASON_SINGLESTEP; /* calculate PC of next instruction */ uint32_t next_pc; retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) { uint32_t current_opcode; target_read_u32(target, current_pc, ¤t_opcode); LOG_ERROR( "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); return retval; } retval = arm7_9_restore_context(target); if (retval != ERROR_OK) return retval; arm7_9->enable_single_step(target, next_pc); if (arm->core_state == ARM_STATE_ARM) arm7_9->branch_resume(target); else if (arm->core_state == ARM_STATE_THUMB) arm7_9->branch_resume_thumb(target); else { LOG_ERROR("unhandled core state"); return ERROR_FAIL; } retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED); if (retval != ERROR_OK) return retval; err = arm7_9_execute_sys_speed(target); arm7_9->disable_single_step(target); /* registers are now invalid */ register_cache_invalidate(arm->core_cache); if (err != ERROR_OK) target->state = TARGET_UNKNOWN; else { retval = arm7_9_debug_entry(target); if (retval != ERROR_OK) return retval; retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED); if (retval != ERROR_OK) return retval; LOG_DEBUG("target stepped"); } if (breakpoint) { retval = arm7_9_set_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } return err; } static int arm7_9_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { uint32_t *reg_p[16]; int retval; struct arm_reg *areg = r->arch_info; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; if (!is_arm_mode(arm->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) return ERROR_COMMAND_SYNTAX_ERROR; if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) && (areg->mode != ARM_MODE_ANY)) { uint32_t tmp_cpsr; /* change processor mode (mask T bit) */ tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0; tmp_cpsr |= mode; tmp_cpsr &= ~0x20; arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); } uint32_t value = 0; if ((num >= 0) && (num <= 15)) { /* read a normal core register */ reg_p[num] = &value; arm7_9->read_core_regs(target, 1 << num, reg_p); } else { /* read a program status register * if the register mode is MODE_ANY, we read the cpsr, otherwise a spsr */ arm7_9->read_xpsr(target, &value, areg->mode != ARM_MODE_ANY); } retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; r->valid = 1; r->dirty = 0; buf_set_u32(r->value, 0, 32, value); if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) && (areg->mode != ARM_MODE_ANY)) { /* restore processor mode (mask T bit) */ arm7_9->write_xpsr_im8(target, buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0); } return ERROR_OK; } static int arm7_9_write_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode, uint8_t *value) { uint32_t reg[16]; struct arm_reg *areg = r->arch_info; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; if (!is_arm_mode(arm->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) return ERROR_COMMAND_SYNTAX_ERROR; if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) && (areg->mode != ARM_MODE_ANY)) { uint32_t tmp_cpsr; /* change processor mode (mask T bit) */ tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0; tmp_cpsr |= mode; tmp_cpsr &= ~0x20; arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); } if ((num >= 0) && (num <= 15)) { /* write a normal core register */ reg[num] = buf_get_u32(value, 0, 32); arm7_9->write_core_regs(target, 1 << num, reg); } else { /* write a program status register * if the register mode is MODE_ANY, we write the cpsr, otherwise a spsr */ int spsr = (areg->mode != ARM_MODE_ANY); uint32_t t = buf_get_u32(value, 0, 32); /* if we're writing the CPSR, mask the T bit */ if (!spsr) t &= ~0x20; arm7_9->write_xpsr(target, t, spsr); } r->valid = 1; r->dirty = 0; if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) && (areg->mode != ARM_MODE_ANY)) { /* restore processor mode (mask T bit) */ arm7_9->write_xpsr_im8(target, buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0); } return jtag_execute_queue(); } int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; uint32_t reg[16]; uint32_t num_accesses = 0; int thisrun_accesses; int i; uint32_t cpsr; int retval; int last_reg = 0; LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /* load the base register with the address of the first word */ reg[0] = address; arm7_9->write_core_regs(target, 0x1, reg); int j = 0; switch (size) { case 4: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; if (last_reg <= thisrun_accesses) last_reg = thisrun_accesses; arm7_9->load_word_regs(target, reg_list); /* fast memory reads are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else retval = arm7_9_execute_sys_speed(target); if (retval != ERROR_OK) return retval; arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4); /* advance buffer, count number of accesses */ buffer += thisrun_accesses * 4; num_accesses += thisrun_accesses; if ((j++%1024) == 0) keep_alive(); } break; case 2: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; for (i = 1; i <= thisrun_accesses; i++) { if (i > last_reg) last_reg = i; arm7_9->load_hword_reg(target, i); /* fast memory reads are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else retval = arm7_9_execute_sys_speed(target); if (retval != ERROR_OK) return retval; } arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2); /* advance buffer, count number of accesses */ buffer += thisrun_accesses * 2; num_accesses += thisrun_accesses; if ((j++%1024) == 0) keep_alive(); } break; case 1: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; for (i = 1; i <= thisrun_accesses; i++) { if (i > last_reg) last_reg = i; arm7_9->load_byte_reg(target, i); /* fast memory reads are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else retval = arm7_9_execute_sys_speed(target); if (retval != ERROR_OK) return retval; } arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1); /* advance buffer, count number of accesses */ buffer += thisrun_accesses * 1; num_accesses += thisrun_accesses; if ((j++%1024) == 0) keep_alive(); } break; } if (!is_arm_mode(arm->core_mode)) return ERROR_FAIL; for (i = 0; i <= last_reg; i++) { struct reg *r = arm_reg_current(arm, i); r->dirty = r->valid; } arm7_9->read_xpsr(target, &cpsr, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while reading cpsr"); return ERROR_TARGET_DATA_ABORT; } if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( "memory read caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); arm7_9->write_xpsr_im8(target, buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0); return ERROR_TARGET_DATA_ABORT; } return ERROR_OK; } int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; uint32_t reg[16]; uint32_t num_accesses = 0; int thisrun_accesses; int i; uint32_t cpsr; int retval; int last_reg = 0; #ifdef _DEBUG_ARM7_9_ LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count); #endif if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; /* load the base register with the address of the first word */ reg[0] = address; arm7_9->write_core_regs(target, 0x1, reg); /* Clear DBGACK, to make sure memory fetches work as expected */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0); embeddedice_store_reg(dbg_ctrl); switch (size) { case 4: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; for (i = 1; i <= thisrun_accesses; i++) { if (i > last_reg) last_reg = i; reg[i] = target_buffer_get_u32(target, buffer); buffer += 4; } arm7_9->write_core_regs(target, reg_list, reg); arm7_9->store_word_regs(target, reg_list); /* fast memory writes are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else { retval = arm7_9_execute_sys_speed(target); /* * if memory writes are made when the clock is running slow * (i.e. 32 kHz) which is necessary in some scripts to reconfigure * processor operations after a "reset halt" or "reset init", * need to immediately stroke the keep alive or will end up with * gdb "keep alive not sent error message" problem. */ keep_alive(); } if (retval != ERROR_OK) return retval; num_accesses += thisrun_accesses; } break; case 2: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; for (i = 1; i <= thisrun_accesses; i++) { if (i > last_reg) last_reg = i; reg[i] = target_buffer_get_u16(target, buffer) & 0xffff; buffer += 2; } arm7_9->write_core_regs(target, reg_list, reg); for (i = 1; i <= thisrun_accesses; i++) { arm7_9->store_hword_reg(target, i); /* fast memory writes are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else { retval = arm7_9_execute_sys_speed(target); /* * if memory writes are made when the clock is running slow * (i.e. 32 kHz) which is necessary in some scripts to reconfigure * processor operations after a "reset halt" or "reset init", * need to immediately stroke the keep alive or will end up with * gdb "keep alive not sent error message" problem. */ keep_alive(); } if (retval != ERROR_OK) return retval; } num_accesses += thisrun_accesses; } break; case 1: while (num_accesses < count) { uint32_t reg_list; thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses); reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe; for (i = 1; i <= thisrun_accesses; i++) { if (i > last_reg) last_reg = i; reg[i] = *buffer++ & 0xff; } arm7_9->write_core_regs(target, reg_list, reg); for (i = 1; i <= thisrun_accesses; i++) { arm7_9->store_byte_reg(target, i); /* fast memory writes are only safe when the target is running * from a sufficiently high clock (32 kHz is usually too slow) */ if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else { retval = arm7_9_execute_sys_speed(target); /* * if memory writes are made when the clock is running slow * (i.e. 32 kHz) which is necessary in some scripts to reconfigure * processor operations after a "reset halt" or "reset init", * need to immediately stroke the keep alive or will end up with * gdb "keep alive not sent error message" problem. */ keep_alive(); } if (retval != ERROR_OK) return retval; } num_accesses += thisrun_accesses; } break; } /* Re-Set DBGACK */ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1); embeddedice_store_reg(dbg_ctrl); if (!is_arm_mode(arm->core_mode)) return ERROR_FAIL; for (i = 0; i <= last_reg; i++) { struct reg *r = arm_reg_current(arm, i); r->dirty = r->valid; } arm7_9->read_xpsr(target, &cpsr, 0); retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("JTAG error while reading cpsr"); return ERROR_TARGET_DATA_ABORT; } if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( "memory write caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); arm7_9->write_xpsr_im8(target, buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0); return ERROR_TARGET_DATA_ABORT; } return ERROR_OK; } int arm7_9_write_memory_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval; if (size == 4 && count > 32 && arm7_9->bulk_write_memory) { /* Attempt to do a bulk write */ retval = arm7_9->bulk_write_memory(target, address, count, buffer); if (retval == ERROR_OK) return ERROR_OK; } return arm7_9->write_memory(target, address, size, count, buffer); } int arm7_9_write_memory_no_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); return arm7_9->write_memory(target, address, size, count, buffer); } static int dcc_count; static const uint8_t *dcc_buffer; static int arm7_9_dcc_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); retval = target_wait_state(target, TARGET_DEBUG_RUNNING, 500); if (retval != ERROR_OK) return retval; int little = target->endianness == TARGET_LITTLE_ENDIAN; int count = dcc_count; const uint8_t *buffer = dcc_buffer; if (count > 2) { /* Handle first & last using standard embeddedice_write_reg and the middle ones w/the * core function repeated. */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], fast_target_buffer_get_u32(buffer, little)); buffer += 4; struct embeddedice_reg *ice_reg = arm7_9->eice_cache->reg_list[EICE_COMMS_DATA].arch_info; uint8_t reg_addr = ice_reg->addr & 0x1f; struct jtag_tap *tap; tap = ice_reg->jtag_info->tap; embeddedice_write_dcc(tap, reg_addr, buffer, little, count-2); buffer += (count-2)*4; embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], fast_target_buffer_get_u32(buffer, little)); } else { int i; for (i = 0; i < count; i++) { embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], fast_target_buffer_get_u32(buffer, little)); buffer += 4; } } retval = target_halt(target); if (retval != ERROR_OK) return retval; return target_wait_state(target, TARGET_HALTED, 500); } static const uint32_t dcc_code[] = { /* r0 == input, points to memory buffer * r1 == scratch */ /* spin until DCC control (c0) reports data arrived */ 0xee101e10, /* w: mrc p14, #0, r1, c0, c0 */ 0xe3110001, /* tst r1, #1 */ 0x0afffffc, /* bne w */ /* read word from DCC (c1), write to memory */ 0xee111e10, /* mrc p14, #0, r1, c1, c0 */ 0xe4801004, /* str r1, [r0], #4 */ /* repeat */ 0xeafffff9 /* b w */ }; int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (address % 4 != 0) return ERROR_TARGET_UNALIGNED_ACCESS; if (!arm7_9->dcc_downloads) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* regrab previously allocated working_area, or allocate a new one */ if (!arm7_9->dcc_working_area) { uint8_t dcc_code_buf[6 * 4]; /* make sure we have a working area */ if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) { LOG_INFO("no working area available, falling back to memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* copy target instructions to target endianness */ target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code); /* write DCC code to working area, using the non-optimized * memory write to avoid ending up here again */ retval = arm7_9_write_memory_no_opt(target, arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf); if (retval != ERROR_OK) return retval; } struct arm_algorithm arm_algo; struct reg_param reg_params[1]; arm_algo.common_magic = ARM_COMMON_MAGIC; arm_algo.core_mode = ARM_MODE_SVC; arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); dcc_count = count; dcc_buffer = buffer; retval = armv4_5_run_algorithm_inner(target, 0, NULL, 1, reg_params, arm7_9->dcc_working_area->address, arm7_9->dcc_working_area->address + 6*4, 20*1000, &arm_algo, arm7_9_dcc_completion); if (retval == ERROR_OK) { uint32_t endaddress = buf_get_u32(reg_params[0].value, 0, 32); if (endaddress != (address + count*4)) { LOG_ERROR( "DCC write failed, expected end address 0x%08" PRIx32 " got 0x%0" PRIx32 "", (address + count*4), endaddress); retval = ERROR_FAIL; } } destroy_reg_param(®_params[0]); return retval; } /** * Perform per-target setup that requires JTAG access. */ int arm7_9_examine(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval; if (!target_was_examined(target)) { struct reg_cache *t, **cache_p; t = embeddedice_build_reg_cache(target, arm7_9); if (t == NULL) return ERROR_FAIL; cache_p = register_get_last_cache_p(&target->reg_cache); (*cache_p) = t; arm7_9->eice_cache = (*cache_p); if (arm7_9->arm.etm) (*cache_p)->next = etm_build_reg_cache(target, &arm7_9->jtag_info, arm7_9->arm.etm); target_set_examined(target); } retval = embeddedice_setup(target); if (retval == ERROR_OK) retval = arm7_9_setup(target); if (retval == ERROR_OK && arm7_9->arm.etm) retval = etm_setup(target); return retval; } int arm7_9_check_reset(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (get_target_reset_nag() && !arm7_9->dcc_downloads) LOG_WARNING( "NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'."); if (get_target_reset_nag() && (target->working_area_size == 0)) LOG_WARNING("NOTE! Severe performance degradation without working memory enabled."); if (get_target_reset_nag() && !arm7_9->fast_memory_access) LOG_WARNING( "NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'."); return ERROR_OK; } int arm7_9_endianness_callback(jtag_callback_data_t pu8_in, jtag_callback_data_t i_size, jtag_callback_data_t i_be, jtag_callback_data_t i_flip) { uint8_t *in = (uint8_t *)pu8_in; int size = (int)i_size; int be = (int)i_be; int flip = (int)i_flip; uint32_t readback; switch (size) { case 4: readback = le_to_h_u32(in); if (flip) readback = flip_u32(readback, 32); if (be) h_u32_to_be(in, readback); else h_u32_to_le(in, readback); break; case 2: readback = le_to_h_u16(in); if (flip) readback = flip_u32(readback, 16); if (be) h_u16_to_be(in, readback & 0xffff); else h_u16_to_le(in, readback & 0xffff); break; case 1: readback = *in; if (flip) readback = flip_u32(readback, 8); *in = readback & 0xff; break; } return ERROR_OK; } COMMAND_HANDLER(handle_arm7_9_dbgrq_command) { struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } if (CMD_ARGC > 0) COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->use_dbgrq); command_print(CMD_CTX, "use of EmbeddedICE dbgrq instead of breakpoint for target halt %s", (arm7_9->use_dbgrq) ? "enabled" : "disabled"); return ERROR_OK; } COMMAND_HANDLER(handle_arm7_9_fast_memory_access_command) { struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } if (CMD_ARGC > 0) COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->fast_memory_access); command_print(CMD_CTX, "fast memory access is %s", (arm7_9->fast_memory_access) ? "enabled" : "disabled"); return ERROR_OK; } COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command) { struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } if (CMD_ARGC > 0) COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->dcc_downloads); command_print(CMD_CTX, "dcc downloads are %s", (arm7_9->dcc_downloads) ? "enabled" : "disabled"); return ERROR_OK; } static int arm7_9_setup_semihosting(struct target *target, int enable) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { LOG_USER("current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } if (arm7_9->has_vector_catch) { struct reg *vector_catch = &arm7_9->eice_cache ->reg_list[EICE_VEC_CATCH]; if (!vector_catch->valid) embeddedice_read_reg(vector_catch); buf_set_u32(vector_catch->value, 2, 1, enable); embeddedice_store_reg(vector_catch); } else { /* TODO: allow optional high vectors and/or BKPT_HARD */ if (enable) breakpoint_add(target, 8, 4, BKPT_SOFT); else breakpoint_remove(target, 8); } return ERROR_OK; } int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) { int retval = ERROR_OK; struct arm *arm = &arm7_9->arm; arm7_9->common_magic = ARM7_9_COMMON_MAGIC; retval = arm_jtag_setup_connection(&arm7_9->jtag_info); if (retval != ERROR_OK) return retval; /* caller must have allocated via calloc(), so everything's zeroed */ arm7_9->wp_available_max = 2; arm7_9->fast_memory_access = false; arm7_9->dcc_downloads = false; arm->arch_info = arm7_9; arm->core_type = ARM_MODE_ANY; arm->read_core_reg = arm7_9_read_core_reg; arm->write_core_reg = arm7_9_write_core_reg; arm->full_context = arm7_9_full_context; arm->setup_semihosting = arm7_9_setup_semihosting; retval = arm_init_arch_info(target, arm); if (retval != ERROR_OK) return retval; return target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target); } static const struct command_registration arm7_9_any_command_handlers[] = { { "dbgrq", .handler = handle_arm7_9_dbgrq_command, .mode = COMMAND_ANY, .usage = "['enable'|'disable']", .help = "use EmbeddedICE dbgrq instead of breakpoint " "for target halt requests", }, { "fast_memory_access", .handler = handle_arm7_9_fast_memory_access_command, .mode = COMMAND_ANY, .usage = "['enable'|'disable']", .help = "use fast memory accesses instead of slower " "but potentially safer accesses", }, { "dcc_downloads", .handler = handle_arm7_9_dcc_downloads_command, .mode = COMMAND_ANY, .usage = "['enable'|'disable']", .help = "use DCC downloads for larger memory writes", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm7_9_command_handlers[] = { { .chain = arm_command_handlers, }, { .chain = etm_command_handlers, }, { .name = "arm7_9", .mode = COMMAND_ANY, .help = "arm7/9 specific commands", .usage = "", .chain = arm7_9_any_command_handlers, }, COMMAND_REGISTRATION_DONE }; openocd-0.9.0/src/target/arm7_9_common.h0000644000175000017500000002154212315575361015000 00000000000000/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM7_9_COMMON_H #define ARM7_9_COMMON_H #include "arm.h" #include "arm_jtag.h" #define ARM7_9_COMMON_MAGIC 0x0a790a79 /**< */ /** * Structure for items that are common between both ARM7 and ARM9 targets. */ struct arm7_9_common { struct arm arm; uint32_t common_magic; struct arm_jtag jtag_info; /**< JTAG information for target */ struct reg_cache *eice_cache; /**< Embedded ICE register cache */ uint32_t arm_bkpt; /**< ARM breakpoint instruction */ uint16_t thumb_bkpt; /**< Thumb breakpoint instruction */ int sw_breakpoints_added; /**< Specifies which watchpoint software breakpoints are setup on */ int sw_breakpoint_count; /**< keep track of number of software breakpoints we have set */ int breakpoint_count; /**< Current number of set breakpoints */ int wp_available; /**< Current number of available watchpoint units */ int wp_available_max; /**< Maximum number of available watchpoint units */ int wp0_used; /**< Specifies if and how watchpoint unit 0 is used */ int wp1_used; /**< Specifies if and how watchpoint unit 1 is used */ int wp1_used_default; /**< Specifies if and how watchpoint unit 1 is used by default */ int dbgreq_adjust_pc; /**< Amount of PC adjustment caused by a DBGREQ */ bool use_dbgrq; /**< Specifies if DBGRQ should be used to halt the target */ bool need_bypass_before_restart; /**< Specifies if there should be a bypass before a JTAG restart */ bool has_single_step; bool has_monitor_mode; bool has_vector_catch; /**< Specifies if the target has a reset vector catch */ bool debug_entry_from_reset; /**< Specifies if debug entry was from a reset */ bool fast_memory_access; bool dcc_downloads; struct working_area *dcc_working_area; int (*examine_debug_reason)(struct target *target); /**< Function for determining why debug state was entered */ void (*change_to_arm)(struct target *target, uint32_t *r0, uint32_t *pc); /**< Function for changing from Thumb to ARM mode */ void (*read_core_regs)(struct target *target, uint32_t mask, uint32_t *core_regs[16]); /**< Function for reading the core registers */ void (*read_core_regs_target_buffer)(struct target *target, uint32_t mask, void *buffer, int size); void (*read_xpsr)(struct target *target, uint32_t *xpsr, int spsr); /**< Function for reading CPSR or SPSR */ void (*write_xpsr)(struct target *target, uint32_t xpsr, int spsr); /**< Function for writing to CPSR or SPSR */ void (*write_xpsr_im8)(struct target *target, uint8_t xpsr_im, int rot, int spsr); /**< Function for writing an immediate value to CPSR or SPSR */ void (*write_core_regs)(struct target *target, uint32_t mask, uint32_t core_regs[16]); void (*load_word_regs)(struct target *target, uint32_t mask); void (*load_hword_reg)(struct target *target, int num); void (*load_byte_reg)(struct target *target, int num); void (*store_word_regs)(struct target *target, uint32_t mask); void (*store_hword_reg)(struct target *target, int num); void (*store_byte_reg)(struct target *target, int num); void (*write_pc)(struct target *target, uint32_t pc); /**< Function for writing to the program counter */ void (*branch_resume)(struct target *target); void (*branch_resume_thumb)(struct target *target); void (*enable_single_step)(struct target *target, uint32_t next_pc); void (*disable_single_step)(struct target *target); void (*set_special_dbgrq)(struct target *target); /**< Function for setting DBGRQ if the normal way won't work */ int (*post_debug_entry)(struct target *target); /**< Callback function called after entering debug mode */ void (*pre_restore_context)(struct target *target); /**< Callback function called before restoring the processor context */ /** * Variant specific memory write function that does not dispatch to bulk_write_memory. * Used as a fallback when bulk writes are unavailable, or for writing data needed to * do the bulk writes. */ int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /** * Write target memory in multiples of 4 bytes, optimized for * writing large quantities of data. */ int (*bulk_write_memory)(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer); }; static inline struct arm7_9_common *target_to_arm7_9(struct target *target) { return container_of(target->arch_info, struct arm7_9_common, arm); } static inline bool is_arm7_9(struct arm7_9_common *arm7_9) { return arm7_9->common_magic == ARM7_9_COMMON_MAGIC; } extern const struct command_registration arm7_9_command_handlers[]; int arm7_9_poll(struct target *target); int arm7_9_target_request_data(struct target *target, uint32_t size, uint8_t *buffer); int arm7_9_assert_reset(struct target *target); int arm7_9_deassert_reset(struct target *target); int arm7_9_reset_request_halt(struct target *target); int arm7_9_early_halt(struct target *target); int arm7_9_soft_reset_halt(struct target *target); int arm7_9_halt(struct target *target); int arm7_9_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints); int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_write_memory_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_write_memory_no_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer); int arm7_9_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_prams, struct reg_param *reg_param, uint32_t entry_point, void *arch_info); int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint); int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); int arm7_9_add_watchpoint(struct target *target, struct watchpoint *watchpoint); int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc); void arm7_9_disable_eice_step(struct target *target); int arm7_9_execute_sys_speed(struct target *target); int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9); int arm7_9_examine(struct target *target); int arm7_9_check_reset(struct target *target); int arm7_9_endianness_callback(jtag_callback_data_t pu8_in, jtag_callback_data_t i_size, jtag_callback_data_t i_be, jtag_callback_data_t i_flip); #endif /* ARM7_9_COMMON_H */ openocd-0.9.0/src/target/arm_semihosting.c0000644000175000017500000003742612516456303015522 00000000000000/*************************************************************************** * Copyright (C) 2009 by Marvell Technology Group Ltd. * * Written by Nicolas Pitre * * * * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /** * @file * Hold ARM semihosting support. * * Semihosting enables code running on an ARM target to use the I/O * facilities on the host computer. The target application must be linked * against a library that forwards operation requests by using the SVC * instruction trapped at the Supervisor Call vector by the debugger. * Details can be found in chapter 8 of DUI0203I_rvct_developer_guide.pdf * from ARM Ltd. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arm.h" #include "armv4_5.h" #include "arm7_9_common.h" #include "armv7m.h" #include "cortex_m.h" #include "register.h" #include "arm_semihosting.h" #include #include #include static const int open_modeflags[12] = { O_RDONLY, O_RDONLY | O_BINARY, O_RDWR, O_RDWR | O_BINARY, O_WRONLY | O_CREAT | O_TRUNC, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, O_RDWR | O_CREAT | O_TRUNC, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, O_WRONLY | O_CREAT | O_APPEND, O_WRONLY | O_CREAT | O_APPEND | O_BINARY, O_RDWR | O_CREAT | O_APPEND, O_RDWR | O_CREAT | O_APPEND | O_BINARY }; static int do_semihosting(struct target *target) { struct arm *arm = target_to_arm(target); uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); uint8_t params[16]; int retval, result; /* * TODO: lots of security issues are not considered yet, such as: * - no validation on target provided file descriptors * - no safety checks on opened/deleted/renamed file paths * Beware the target app you use this support with. * * TODO: explore mapping requests to GDB's "File-I/O Remote * Protocol Extension" ... when GDB is active. */ switch (r0) { case 0x01: /* SYS_OPEN */ retval = target_read_memory(target, r1, 4, 3, params); if (retval != ERROR_OK) return retval; else { uint32_t a = target_buffer_get_u32(target, params+0); uint32_t m = target_buffer_get_u32(target, params+4); uint32_t l = target_buffer_get_u32(target, params+8); if (l <= 255 && m <= 11) { uint8_t fn[256]; retval = target_read_memory(target, a, 1, l, fn); if (retval != ERROR_OK) return retval; fn[l] = 0; if (strcmp((char *)fn, ":tt") == 0) { if (m < 4) result = dup(STDIN_FILENO); else result = dup(STDOUT_FILENO); } else { /* cygwin requires the permission setting * otherwise it will fail to reopen a previously * written file */ result = open((char *)fn, open_modeflags[m], 0644); } arm->semihosting_errno = errno; } else { result = -1; arm->semihosting_errno = EINVAL; } } break; case 0x02: /* SYS_CLOSE */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); result = close(fd); arm->semihosting_errno = errno; } break; case 0x03: /* SYS_WRITEC */ { unsigned char c; retval = target_read_memory(target, r1, 1, 1, &c); if (retval != ERROR_OK) return retval; putchar(c); result = 0; } break; case 0x04: /* SYS_WRITE0 */ do { unsigned char c; retval = target_read_memory(target, r1++, 1, 1, &c); if (retval != ERROR_OK) return retval; if (!c) break; putchar(c); } while (1); result = 0; break; case 0x05: /* SYS_WRITE */ retval = target_read_memory(target, r1, 4, 3, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); size_t l = target_buffer_get_u32(target, params+8); uint8_t *buf = malloc(l); if (!buf) { result = -1; arm->semihosting_errno = ENOMEM; } else { retval = target_read_buffer(target, a, l, buf); if (retval != ERROR_OK) { free(buf); return retval; } result = write(fd, buf, l); arm->semihosting_errno = errno; if (result >= 0) result = l - result; free(buf); } } break; case 0x06: /* SYS_READ */ retval = target_read_memory(target, r1, 4, 3, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); ssize_t l = target_buffer_get_u32(target, params+8); uint8_t *buf = malloc(l); if (!buf) { result = -1; arm->semihosting_errno = ENOMEM; } else { result = read(fd, buf, l); arm->semihosting_errno = errno; if (result >= 0) { retval = target_write_buffer(target, a, result, buf); if (retval != ERROR_OK) { free(buf); return retval; } result = l - result; } free(buf); } } break; case 0x07: /* SYS_READC */ result = getchar(); break; case 0x08: /* SYS_ISERROR */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; result = (target_buffer_get_u32(target, params+0) != 0); break; case 0x09: /* SYS_ISTTY */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; result = isatty(target_buffer_get_u32(target, params+0)); break; case 0x0a: /* SYS_SEEK */ retval = target_read_memory(target, r1, 4, 2, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); off_t pos = target_buffer_get_u32(target, params+4); result = lseek(fd, pos, SEEK_SET); arm->semihosting_errno = errno; if (result == pos) result = 0; } break; case 0x0c: /* SYS_FLEN */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); struct stat buf; result = fstat(fd, &buf); if (result == -1) { arm->semihosting_errno = errno; result = -1; break; } result = buf.st_size; } break; case 0x0e: /* SYS_REMOVE */ retval = target_read_memory(target, r1, 4, 2, params); if (retval != ERROR_OK) return retval; else { uint32_t a = target_buffer_get_u32(target, params+0); uint32_t l = target_buffer_get_u32(target, params+4); if (l <= 255) { uint8_t fn[256]; retval = target_read_memory(target, a, 1, l, fn); if (retval != ERROR_OK) return retval; fn[l] = 0; result = remove((char *)fn); arm->semihosting_errno = errno; } else { result = -1; arm->semihosting_errno = EINVAL; } } break; case 0x0f: /* SYS_RENAME */ retval = target_read_memory(target, r1, 4, 4, params); if (retval != ERROR_OK) return retval; else { uint32_t a1 = target_buffer_get_u32(target, params+0); uint32_t l1 = target_buffer_get_u32(target, params+4); uint32_t a2 = target_buffer_get_u32(target, params+8); uint32_t l2 = target_buffer_get_u32(target, params+12); if (l1 <= 255 && l2 <= 255) { uint8_t fn1[256], fn2[256]; retval = target_read_memory(target, a1, 1, l1, fn1); if (retval != ERROR_OK) return retval; retval = target_read_memory(target, a2, 1, l2, fn2); if (retval != ERROR_OK) return retval; fn1[l1] = 0; fn2[l2] = 0; result = rename((char *)fn1, (char *)fn2); arm->semihosting_errno = errno; } else { result = -1; arm->semihosting_errno = EINVAL; } } break; case 0x11: /* SYS_TIME */ result = time(NULL); break; case 0x13: /* SYS_ERRNO */ result = arm->semihosting_errno; break; case 0x15: /* SYS_GET_CMDLINE */ retval = target_read_memory(target, r1, 4, 2, params); if (retval != ERROR_OK) return retval; else { uint32_t a = target_buffer_get_u32(target, params+0); uint32_t l = target_buffer_get_u32(target, params+4); char *arg = "foobar"; uint32_t s = strlen(arg) + 1; if (l < s) result = -1; else { retval = target_write_buffer(target, a, s, (uint8_t *)arg); if (retval != ERROR_OK) return retval; result = 0; } } break; case 0x16: /* SYS_HEAPINFO */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; else { uint32_t a = target_buffer_get_u32(target, params+0); /* tell the remote we have no idea */ memset(params, 0, 4*4); retval = target_write_memory(target, a, 4, 4, params); if (retval != ERROR_OK) return retval; result = 0; } break; case 0x18: /* angel_SWIreason_ReportException */ switch (r1) { case 0x20026: /* ADP_Stopped_ApplicationExit */ fprintf(stderr, "semihosting: *** application exited ***\n"); break; case 0x20000: /* ADP_Stopped_BranchThroughZero */ case 0x20001: /* ADP_Stopped_UndefinedInstr */ case 0x20002: /* ADP_Stopped_SoftwareInterrupt */ case 0x20003: /* ADP_Stopped_PrefetchAbort */ case 0x20004: /* ADP_Stopped_DataAbort */ case 0x20005: /* ADP_Stopped_AddressException */ case 0x20006: /* ADP_Stopped_IRQ */ case 0x20007: /* ADP_Stopped_FIQ */ case 0x20020: /* ADP_Stopped_BreakPoint */ case 0x20021: /* ADP_Stopped_WatchPoint */ case 0x20022: /* ADP_Stopped_StepComplete */ case 0x20023: /* ADP_Stopped_RunTimeErrorUnknown */ case 0x20024: /* ADP_Stopped_InternalError */ case 0x20025: /* ADP_Stopped_UserInterruption */ case 0x20027: /* ADP_Stopped_StackOverflow */ case 0x20028: /* ADP_Stopped_DivisionByZero */ case 0x20029: /* ADP_Stopped_OSSpecific */ default: fprintf(stderr, "semihosting: exception %#x\n", (unsigned) r1); } return target_call_event_callbacks(target, TARGET_EVENT_HALTED); case 0x12: /* SYS_SYSTEM */ /* Provide SYS_SYSTEM functionality. Uses the * libc system command, there may be a reason *NOT* * to use this, but as I can't think of one, I * implemented it this way. */ retval = target_read_memory(target, r1, 4, 2, params); if (retval != ERROR_OK) return retval; else { uint32_t len = target_buffer_get_u32(target, params+4); uint32_t c_ptr = target_buffer_get_u32(target, params); uint8_t cmd[256]; if (len > 255) { result = -1; arm->semihosting_errno = EINVAL; } else { memset(cmd, 0x0, 256); retval = target_read_memory(target, c_ptr, 1, len, cmd); if (retval != ERROR_OK) return retval; else result = system((const char *)cmd); } } break; case 0x0d: /* SYS_TMPNAM */ case 0x10: /* SYS_CLOCK */ case 0x17: /* angel_SWIreason_EnterSVC */ case 0x30: /* SYS_ELAPSED */ case 0x31: /* SYS_TICKFREQ */ default: fprintf(stderr, "semihosting: unsupported call %#x\n", (unsigned) r0); result = -1; arm->semihosting_errno = ENOTSUP; } /* resume execution to the original mode */ /* REVISIT this looks wrong ... ARM11 and Cortex-A8 * should work this way at least sometimes. */ if (is_arm7_9(target_to_arm7_9(target))) { uint32_t spsr; /* return value in R0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); arm->core_cache->reg_list[0].dirty = 1; /* LR --> PC */ buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); arm->core_cache->reg_list[15].dirty = 1; /* saved PSR --> current PSR */ spsr = buf_get_u32(arm->spsr->value, 0, 32); /* REVISIT should this be arm_set_cpsr(arm, spsr) * instead of a partially unrolled version? */ buf_set_u32(arm->cpsr->value, 0, 32, spsr); arm->cpsr->dirty = 1; arm->core_mode = spsr & 0x1f; if (spsr & 0x20) arm->core_state = ARM_STATE_THUMB; } else { /* resume execution, this will be pc+2 to skip over the * bkpt instruction */ /* return result in R0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); arm->core_cache->reg_list[0].dirty = 1; } return target_resume(target, 1, 0, 0, 0); } /** * Checks for and processes an ARM semihosting request. This is meant * to be called when the target is stopped due to a debug mode entry. * If the value 0 is returned then there was nothing to process. A non-zero * return value signifies that a request was processed and the target resumed, * or an error was encountered, in which case the caller must return * immediately. * * @param target Pointer to the ARM target to process. This target must * not represent an ARMv6-M or ARMv7-M processor. * @param retval Pointer to a location where the return code will be stored * @return non-zero value if a request was processed or an error encountered */ int arm_semihosting(struct target *target, int *retval) { struct arm *arm = target_to_arm(target); uint32_t pc, lr, spsr; struct reg *r; if (!arm->is_semihosting) return 0; if (is_arm7_9(target_to_arm7_9(target))) { if (arm->core_mode != ARM_MODE_SVC) return 0; /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */ r = arm->pc; pc = buf_get_u32(r->value, 0, 32); if (pc != 0x00000008 && pc != 0xffff0008) return 0; r = arm_reg_current(arm, 14); lr = buf_get_u32(r->value, 0, 32); /* Core-specific code should make sure SPSR is retrieved * when the above checks pass... */ if (!arm->spsr->valid) { LOG_ERROR("SPSR not valid!"); *retval = ERROR_FAIL; return 1; } spsr = buf_get_u32(arm->spsr->value, 0, 32); /* check instruction that triggered this trap */ if (spsr & (1 << 5)) { /* was in Thumb (or ThumbEE) mode */ uint8_t insn_buf[2]; uint16_t insn; *retval = target_read_memory(target, lr-2, 2, 1, insn_buf); if (*retval != ERROR_OK) return 1; insn = target_buffer_get_u16(target, insn_buf); /* SVC 0xab */ if (insn != 0xDFAB) return 0; } else if (spsr & (1 << 24)) { /* was in Jazelle mode */ return 0; } else { /* was in ARM mode */ uint8_t insn_buf[4]; uint32_t insn; *retval = target_read_memory(target, lr-4, 4, 1, insn_buf); if (*retval != ERROR_OK) return 1; insn = target_buffer_get_u32(target, insn_buf); /* SVC 0x123456 */ if (insn != 0xEF123456) return 0; } } else if (is_armv7m(target_to_armv7m(target))) { uint16_t insn; if (target->debug_reason != DBG_REASON_BREAKPOINT) return 0; r = arm->pc; pc = buf_get_u32(r->value, 0, 32); pc &= ~1; *retval = target_read_u16(target, pc, &insn); if (*retval != ERROR_OK) return 1; /* bkpt 0xAB */ if (insn != 0xBEAB) return 0; } else { LOG_ERROR("Unsupported semi-hosting Target"); return 0; } *retval = do_semihosting(target); return 1; } openocd-0.9.0/src/target/arm_semihosting.h0000644000175000017500000000305712315575361015523 00000000000000/*************************************************************************** * Copyright (C) 2009 by Marvell Technology Group Ltd. * * Written by Nicolas Pitre * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef ARM_SEMIHOSTING_H #define ARM_SEMIHOSTING_H int arm_semihosting(struct target *target, int *retval); #endif openocd-0.9.0/BUGS0000644000175000017500000000472512516456301010566 00000000000000// This file is part of the Doxygen Developer Manual /** @page bugs Bug Reporting Please report bugs by subscribing to the OpenOCD mailing list and posting a message with your report: openocd-devel@lists.sourceforge.net Also, please check the bug database to see if a ticket for the bug has already been opened. You might be asked to open such a ticket, or to update an existing ticket with more data. http://bugs.openocd.org/ To minimize work for OpenOCD developers, you should try to include all of the information listed below. If you feel that some of the items below are unnecessary for a clear bug report, you may leave them out; likewise, feel free to include additional information that may be important. - Target PCB/board description - Configuration scripts - OpenOCD command line - List of commands issued or GDB operations performed - Expected result - Actual result - Logs using debug_level 3 (or with '-d 3' on the command line) - If the report is for a regression: - Include logs for both working and broken versions. - Find the precise version that caused the regression by binary search. You can use "git bisect" to expedite this binary search: http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html If possible, please develop and attach a patch that helps to expose or solve the reported problem. See the HACKING file for information about that process. Attach all files directly to your posting. The mailing list knows to transform attachments to links, but attachments must be less than 300KB in total. @section bugscrashdump Obtaining Crash Backtraces If OpenOCD is crashing, there are two very effective things you can do to improve your chances of getting help on the development mailing list. Try to reproduce the problem using the dummy JTAG interface to allow other developers to replicate your problem robustly and use GDB to get a trace:@par @code % OPENOCDSRC/configure --enable-dummy ... % openocd -f interface/dummy.cfg -f target/xxx.cfg => SEGFAULT % gdb --args openocd .... (gdb) run (gdb) bt => here a stack trace is dumped. @endcode @section bugsintreedebug Running and Debugging In-Tree To run or debug the in-tree executable (not recommended), you must use libtool to set up the correct shared library paths: @code libtool gdb --args openocd .... @endcode or the more pedantic (and forward-compatible): @code libtool --mode=execute gdb --args openocd .... @endcode */ /** @file This file contains the @ref bugs page. */ openocd-0.9.0/NEWS0000644000175000017500000001014212526201107010561 00000000000000This file includes highlights of the changes made in the OpenOCD source archive release. JTAG Layer: * SWD support with FTDI, Versaloon, J-Link, sysfsgpio * CMSIS-DAP massive speed and stability improvements * Versaloon driver ported to libusb-1.0 * STLink can reestablish communication with a target that was disconnected or rebooted * STLink FAULT and WAIT SWD handling improved * New hla_serial command to distinguish between several HLA adapters attached to a single machine * Serial number support for CMSIS-DAP and J-Link adapters * Support for more J-Link adapters * TAP autoprobing improvements * Big speedup for SVF playback with USB Blaster Boundary Scan: Target Layer: * Stability improvements for targets that get disconnected or rebooted during a debug session * MIPS speed and reliability improvements * MIPS 1.5/2.0 fixes * ARMv7-R improvements * Cortex-A improvements, A7, A15 MPCores support * FPU support for ARMv7-M (Cortex-M4F) * TPIU/ITM support (including SWO/SWV tracing), can be captured with external tools or STLink * JTAG Serial Port (Advanced Debug System softcore) support * Profiling support for OpenRISC * ChibiOS/RT 3.0 support (with and without FPU) * FreeRTOS current versions support * Freescale MQX RTOS support * GDB target description support for MIPS * The last created target is auto-selected as the current Flash Layer: * nRF51 async loader to improve flashing performance and stability * Cypress PSoC 41xx/42xx and CCG1 families flash driver * Silabs SiM3 family flash driver * Marvell Wireless Microcontroller SPI flash driver * Kinetis mass erase (part unsecuring) implemented * lpcspifi stability fixes * STM32 family sync with reference manuals, L0 support, bugfixes * LPC2000 driver automatically determines part and flash size * NXP LPC11(x)xx, LPC13xx, LPC15xx, LPC8xx, LPC5410x, LPC407x support * Atmel SAMD, SAMR, SAML21 devices support * Atmel SAM4E16 support * ZeroGecko family support * TI Tiva C Blizzard and Snowflake families support * Nuvoton NuMicro M051 support Board, Target, and Interface Configuration Scripts: * Normal target configs can work with HLA (STLink, ICDI) adapters * STM32 discovery and Nucleo boards configs * Gumstix AeroCore board config * General Plus GP326XXXA target config * Micrel KS869x target config * ASUS RT-N66U board config * Atmel SAM4E-EK board config * Atmel AT91SAM4L proper reset handling implemented * TI OMAP/AM 3505, 3517 target configs * nRF51822-mKIT board config * RC Module К1879ХБ1Я target config * TI TMDX570LS20SUSB board config * TI TMS570 USB Kit board config * TI CC2538, CC26xx target configs * TI AM437x major config improvements, DDR support * TI AM437X IDK board config * TI SimpleLink Wi-Fi CC3200 LaunchPad configs * Silicon Labs EM357, EM358 target configs * Infineon XMC1000, XMC4000 family targets and boards configs * Atheros AR9331 target config * TP-LINK TL-MR3020 board config * Alphascale asm9260t target and eval kit configs * Olimex SAM7-LA2 (AT91SAM7A2) board config * EFM32 Gecko boards configs * Spansion FM4 target and SK-FM4-176L-S6E2CC board configs * LPC1xxx target configs were restructured * IoT-LAB debug adapter config * DP BusBlaster KT-Link compatible config Server Layer: * Polling period can be configured * "shutdown" command has an immediate effect * The "program" command doesn't lead to a shutdown by default, use optional "exit" parameter for the old behaviour * Proper OS signal handling was implemented * Async target notifications for the Tcl RPC Documentation: Build and Release: This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: http://sourceforge.net/p/openocd/code/ci/v0.9.0/log/?path= For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/TODO0000644000175000017500000003700512315575360010574 00000000000000// This file is part of the Doxygen Developer Manual /** @page tasks Pending and Open Tasks This page lists pending and open tasks being considered or worked upon by the OpenOCD community. @section thelist The List Most items are open for the taking, but please post to the mailing list before spending much time working on anything lists here. The community may have evolved an idea since it was added here. Feel free to send patches to add or clarify items on this list, too. @section thelisttcl TCL This section provides possible things to improve with OpenOCD's TCL support. - Fix problem with incorrect line numbers reported for a syntax error in a reset init event. - organize the TCL configurations: - provide more directory structure for boards/targets? - factor configurations into layers (encapsulation and re-use) - Fix handling of variables between multiple command line "-c" and "-f" parameters. Currently variables assigned through one such parameter command/script are unset before the next one is invoked. - Isolate all TCL command support: - Pure C CLI implementations using --disable-builtin-tcl. - Allow developers to build new dongles using OpenOCD's JTAG core. - At first, provide only low-level JTAG support; target layer and above rely heavily on scripting event mechanisms. - Allow full TCL support? add --with-tcl=/path/to/installed/tcl - Move TCL support out of foo.[ch] and into foo_tcl.[ch] (other ideas?) - See src/jtag/core.c and src/jtag/tcl.c for an example. - allow some of these TCL command modules to be dynamically loadable? @section thelistjtag JTAG This section list issues that need to be resolved in the JTAG layer. @subsection thelistjtagcore JTAG Core The following tasks have been suggested for cleaning up the JTAG layer: - use tap_set_state everywhere to allow logging TAP state transitions - Encapsulate cmd_queue_cur_state and related variable handling. - add slick 32 bit versions of jtag_add_xxx_scan() that avoids buf_set_u32() calls and other evidence of poor impedance match between API and calling code. New API should cut down # of lines in calling code by 100's and make things clearer. Also potentially be supported directly in minidriver API for better embedded host performance. The following tasks have been suggested for adding new core JTAG support: - Improve autodetection of TAPs by supporting tcl escape procedures that can configure discovered TAPs based on IDCODE value ... they could: - Remove guessing for irlen - Allow non-default irmask/ircapture values - SPI/UART emulation: - (ab)use bit-banging JTAG interfaces to emulate SPI/UART - allow SPI to program flash, MCUs, etc. @subsection thelistjtaginterfaces JTAG Interfaces There are some known bugs to fix in JTAG adapter drivers: - For JTAG_STATEMOVE to TAP_RESET, all drivers must ignore the current recorded state. The tap_get_state() call won't necessarily return the correct value, especially at server startup. Fix is easy: in that case, always issue five clocks with TMS high. - amt_jtagaccel.c - arm-jtag-ew.c - bitbang.c - bitq.c - gw16012.c - jlink.c - usbprog.c - vsllink.c - rlink/rlink.c - bug: USBprog is broken with new tms sequence; it needs 7-clock cycles. Fix promised from Peter Denison openwrt at marshadder.org Workaround: use "tms_sequence long" @par https://lists.berlios.de/pipermail/openocd-development/2009-July/009426.html The following tasks have been suggested for improving OpenOCD's JTAG interface support: - rework USB communication to be more robust. Two possible options are: -# use libusb-1.0.1 with libusb-compat-0.1.1 (non-blocking I/O wrapper) -# rewrite implementation to use non-blocking I/O - J-Link driver: - fix to work with long scan chains, such as R.Doss's svf test. - FT2232 (libftdi): - make performance comparable to alternatives (on Win32, D2XX is faster) - make usability comparable to alternatives - Autodetect USB based adapters; this should be easy on Linux. If there's more than one, list the options; otherwise, just select that one. The following tasks have been suggested for adding new JTAG interfaces: - TCP driver: allow client/server for remote JTAG interface control. This requires a client and a server. The server is built into the normal OpenOCD and takes commands from the client and executes them on the interface returning the result of TCP/IP. The client is an OpenOCD which is built with a TCP/IP minidriver. The use of a minidriver is required to capture all the jtag_add_xxx() fn's at a high enough level and repackage these cmd's as TCP/IP packets handled by the server. @section thelistswd Serial Wire Debug - implement Serial Wire Debug interface @section thelistbs Boundary Scan Support - add STAPL support? - add BSDL support? A few possible options for the above: -# Fake a TCL equivalent? -# Integrate an existing library? -# Write a new C implementation a la Jim? Once the above are completed: - add support for programming flash using boundary scan techniques - add integration with a modified gerber view program: - provide means to view the PCB and select pins and traces - allow use-cases such as the following: - @b Stimulus -# Double-click on a pin (or trace) with the mouse. - @b Effects -# The trace starts blinking, and -# OpenOCD toggles the pin(s) 0/1. @section thelisttargets Target Support - Many common ARM cores could be autodetected using IDCODE - general layer cleanup: @par https://lists.berlios.de/pipermail/openocd-development/2009-May/006590.html - regression: "reset halt" between 729(works) and 788(fails): @par https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html - registers - add flush-value operation, call them all on resume/reset - mcr/mrc target->type support - missing from ARM920t, ARM966e, XScale. It's possible that the current syntax is unable to support read-modify-write operations(see arm966e). - mcr/mrc - retire cp15 commands when there the mrc/mrc commands have been tested from: arm926ejs, arm720t, cortex_a8 - ARM7/9: - clean up "arm9tdmi vector_catch". Available for some arm7 cores? @par https://lists.berlios.de/pipermail/openocd-development/2009-October/011488.html https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html - add reset option to allow programming embedded ice while srst is asserted. Some CPUs will gate the JTAG clock when srst is asserted and in this case, it is necessary to program embedded ice and then assert srst afterwards. - ARM926EJS: - reset run/halt/step is not robust; needs testing to map out problems. - ARM11 improvements (MB?) - add support for asserting srst to reset the core. - Single stepping works, but should automatically use hardware stepping if available. - mdb can return garbage data if read byte operation fails for a memory region(16 & 32 byte access modes may be supported). Is this a bug in the .MX31 PDK init script? Try on i.MX31 PDK: mdw 0xb80005f0 0x8, mdh 0xb80005f0 0x10, mdb 0xb80005f0 0x20. mdb returns garabage. - implement missing functionality (grep FNC_INFO_NOTIMPLEMENTED ...) - Thumb2 single stepping: ARM1156T2 needs simulator support - Cortex A8 support (ML) - add target implementation (ML) - Cortex M3 support - when stepping, only write dirtied registers (be faster) - when connecting to halted core, fetch registers (startup is quirky) - Generic ARM run_algorithm() interface - tagged struct wrapping ARM instructions and metadata - not revision-specific (current: ARMv4+ARMv5 -or- ARMv6 -or- ARMv7) - usable with at least arm_nandwrite() and generic CFI drivers - ETM - don't show FIFOFULL registers if they're not supported - use comparators to get more breakpoints and watchpoints - add "etm drivers" command - trace driver init() via examine() paths only, not setup()/reset - MC1322x support (JW/DE?) - integrate and test support from JW (and DE?) - get working with a known good interface (i.e. not today's jlink) - AT91SAM92xx: - improvements for unknown-board-atmel-at91sam9260.cfg (RD) - STR9x: (ZW) - improvements to str912.cfg to be more general purpose - AVR: (SQ) - independently verify implementation - incrementally improve working prototype in trunk. (SQ) - work out how to debug this target - AVR debugging protocol. - FPGA: - Altera Nios Soft-CPU support - Coldfire (suggested by NC) - can we draw from the BDM project? @par http://bdm.sourceforge.net/ or the OSBDM package @par http://forums.freescale.com/freescale/board/message?board.id=OSBDM08&thread.id=422 @section thelistsvf SVF/XSVF - develop SVF unit tests - develop XSVF unit tests @section thelistflash Flash Support - finish documentation for the following flash drivers: - avr - pic32mx - ocl - str9xpec - Don't expect writing all-ones to be a safe way to write without changing bit values. Minimally it loses on flash modules with internal ECC, where it may change the ECC. - NOR flash_write_unlock() does that between sectors - there may be other cases too - Make sure all commands accept either a bank name or a bank number, and be sure both identifiers show up in "flash banks" and "nand list". Right now the user-friendly names are pretty much hidden... @subsection thelistflashcfi CFI - finish implementing bus width/chip width handling (suggested by NC) - factor vendor-specific code into separate source files - add new callback interface for vendor-specific code - investigate/implement "thin wrapper" to use eCos CFI drivers (ØH) @section thelistdebug Debugger Support - add support for masks in watchpoints? @par https://lists.berlios.de/pipermail/openocd-development/2009-October/011507.html - breakpoints can get lost in some circumstances: @par https://lists.berlios.de/pipermail/openocd-development/2009-June/008853.html - add support for masks in watchpoints. The trick is that GDB does not support a breakpoint mask in the remote protocol. One way to work around this is to add a separate command "watchpoint_mask add/rem ", that is run to register a list of masks that the gdb_server knows to use with a particular watchpoint address. - integrate Keil AGDI interface to OpenOCD? (submitted by Dario Vecchio) @section thelisttesting Testing Suite This section includes several related groups of ideas: - @ref thelistunittests - @ref thelistsmoketests - @ref thelisttestreports - @ref thelisttestgenerichw @subsection thelistunittests Unit Tests - add testing skeleton to provide frameworks for adding tests - implement server unit tests - implement JTAG core unit tests - implement JTAG interface unit tests - implement flash unit tests - implement target unit tests @subsection thelistsmoketests Smoke Test Tools -# extend 'make check' with a smoketest app - checks for OOCD_TEST_CONFIG, etc. in environment (or config file) - if properly set, runs the smoke test with specified parameters - openocd -f ${OOCD_TEST_CONFIG} - implies a modular test suite (see below) - should be able to run some minimal tests with dummy interface: - compare results of baseline sanity checks with expected results -# builds a more complete test suite: - existing testing/examples/ look like a great start - all targets should be tested fully and for all capabilities - we do NOT want a "lowest common denominator" test suite - ... but can we start with one to get going? - probably requires one test configuration file per board/target - modularization can occur here, just like with targets/boards/chips - coverage can increase over time, building up bundles of tests -# add new 'smoketest' Makefile target: - calls 'make check' (and the smoketest app) - gather inputs and output into a report file @subsection thelisttestreports Test Feedback Tools These ideas were first introduced here: @par https://lists.berlios.de/pipermail/openocd-development/2009-May/006358.html - provide report submission scripts for e-mail and web forms - add new Makefile targets to post the report: - 'checkreportsend' -- send to list via e-mail (via sendmail) - 'checkreportpost' -- send web form (via curl or other script) @subsection thelisttestgenerichw Generic Hardware Tester - implement VHDL to use for FPGA-based JTAG TAP testing device - develop test suite that utilizes this testing device @section thelistautotools Autotools Build System - make entire configure process require less user consideration: - automatically detect the features that are available, unless options were specifically provided to configure - provide a report of the drivers that will be build at the end of running configure, so the users can verify which drivers will be built during 'make' (and their options) . - eliminate sources of confusion in @c bootstrap script: -# Make @c bootstrap call 'configure --enable-maintainer-mode \'? -# Add @c buildstrap script to assist with bootstrap and configure steps. - automatically build tool-chains required for cross-compiling - produce mingw32, arm-elf, others using in-tree scripts - build all required target code from sources - make JTAG and USB debug output a run-time configuration option @section thelistarchitecture Architectural Tasks The following architectural tasks need to be accomplished and should be fairly easy to complete: - use dynamic allocations for working memory. Scan & fix code for excessive stack allocations. take linux/scripts/checkstack.pl and see what the worst offenders are. Dynamic stack allocations are found at the bottom of the list below. Example, on amd64: $ objdump -d | checkstack.pl | head -10 0x004311e3 image_open [openocd]: 13464 0x00431301 image_open [openocd]: 13464 0x004237a4 target_array2mem [openocd]: 4376 0x0042382b target_array2mem [openocd]: 4376 0x00423e74 target_mem2array [openocd]: 4360 0x00423ef9 target_mem2array [openocd]: 4360 0x00404aed handle_svf_command [openocd]: 2248 0x00404b7e handle_svf_command [openocd]: 2248 0x00413581 handle_flash_fill_command [openocd]: 2200 0x004135fa handle_flash_fill_command [openocd]: 2200 - clean-up code to match style guides - factor code to eliminate duplicated functionality - rewrite code that uses casts to access 16-bit and larger types from unaligned memory addresses - libopenocd support: @par https://lists.berlios.de/pipermail/openocd-development/2009-May/006405.html - review and clean up interface/target/flash APIs The following strategic tasks will require ambition, knowledge, and time to complete: - overhaul use of types to improve 32/64-bit portability - types for both host and target word sizes? - can we use GDB's CORE_TYPE support? - Allow N:M:P mapping of servers, targets, and interfaces - loadable module support for interface/target/flash drivers and commands - support both static and dynamic modules. - should probably use libltdl for dynamic library handing. @section thelistadmin Documentation Tasks - Develop milestone and release guidelines, processes, and scripts. - Develop "style" guidelines (and scripts) for maintainers: - reviewing patches - committing to git - Review Users' Guide for documentation errors or omissions - "capture" and "ocd_find" commands - "ocd_" prefix on various stuff - Update Developer's Manual (doxygen output) - Add documentation describing the architecture of each module - Provide more Technical Primers to bootstrap contributor knowledge */ /** @file This file contains the @ref thelist page. */ openocd-0.9.0/compile0000755000175000017500000001624512526201646011462 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program 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 2, or (at your option) # any later version. # # This program 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 . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: openocd-0.9.0/contrib/0000755000175000017500000000000012516456301011613 500000000000000openocd-0.9.0/contrib/rpc_examples/0000755000175000017500000000000012327155502014274 500000000000000openocd-0.9.0/contrib/rpc_examples/ocd_rpc_example.py0000755000175000017500000001030312327155502017712 00000000000000#!/usr/bin/env python3 """ OpenOCD RPC example, covered by GNU GPLv3 or later Copyright (C) 2014 Andreas Ortmann (ortmann@finf.uni-hannover.de) Example output: ./ocd_rpc_example.py echo says hi! target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000188 msp: 0x10000fd8 variable @ 0x10000000: 0x01c9c380 variable @ 0x10000000: 0xdeadc0de memory (before): ['0xdeadc0de', '0x00000011', '0xaaaaaaaa', '0x00000023', '0x00000042', '0x0000ffff'] memory (after): ['0x00000001', '0x00000000', '0xaaaaaaaa', '0x00000023', '0x00000042', '0x0000ffff'] """ import socket import itertools def strToHex(data): return map(strToHex, data) if isinstance(data, list) else int(data, 16) def hexify(data): return "" if data is None else ("0x%08x" % data) def compareData(a, b): for i, j, num in zip(a, b, itertools.count(0)): if i != j: print("difference at %d: %s != %s" % (num, hexify(i), hexify(j))) class OpenOcd: COMMAND_TOKEN = '\x1a' def __init__(self, verbose=False): self.verbose = verbose self.tclRpcIp = "127.0.0.1" self.tclRpcPort = 6666 self.bufferSize = 4096 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def __enter__(self): self.sock.connect((self.tclRpcIp, self.tclRpcPort)) return self def __exit__(self, type, value, traceback): try: self.send("exit") finally: self.sock.close() def send(self, cmd): """Send a command string to TCL RPC. Return the result that was read.""" data = (cmd + OpenOcd.COMMAND_TOKEN).encode("utf-8") if self.verbose: print("<- ", data) self.sock.send(data) return self._recv() def _recv(self): """Read from the stream until the token (\x1a) was received.""" data = bytes() while True: chunk = self.sock.recv(self.bufferSize) data += chunk if bytes(OpenOcd.COMMAND_TOKEN, encoding="utf-8") in chunk: break if self.verbose: print("-> ", data) data = data.decode("utf-8").strip() data = data[:-1] # strip trailing \x1a return data def readVariable(self, address): raw = self.send("ocd_mdw 0x%x" % address).split(": ") return None if (len(raw) < 2) else strToHex(raw[1]) def readMemory(self, wordLen, address, n): self.send("array unset output") # better to clear the array before self.send("mem2array output %d 0x%x %d" % (wordLen, address, n)) output = self.send("ocd_echo $output").split(" ") return [int(output[2*i+1]) for i in range(len(output)//2)] def writeVariable(self, address, value): assert value is not None self.send("mww 0x%x 0x%x" % (address, value)) def writeMemory(self, wordLen, address, n, data): array = " ".join(["%d 0x%x" % (a, b) for a, b in enumerate(data)]) self.send("array unset 1986ве1Ñ‚") # better to clear the array before self.send("array set 1986ве1Ñ‚ { %s }" % array) self.send("array2mem 1986ве1Ñ‚ 0x%x %s %d" % (wordLen, address, n)) if __name__ == "__main__": def show(*args): print(*args, end="\n\n") with OpenOcd() as ocd: ocd.send("reset") show(ocd.send("ocd_echo \"echo says hi!\"")[:-1]) show(ocd.send("capture \"ocd_halt\"")[:-1]) # Read the first few words at the RAM region (put starting adress of RAM # region into 'addr') addr = 0x10000000 value = ocd.readVariable(addr) show("variable @ %s: %s" % (hexify(addr), hexify(value))) ocd.writeVariable(addr, 0xdeadc0de) show("variable @ %s: %s" % (hexify(addr), hexify(ocd.readVariable(addr)))) data = [1, 0, 0xaaaaaaaa, 0x23, 0x42, 0xffff] wordlen = 32 n = len(data) read = ocd.readMemory(wordlen, addr, n) show("memory (before):", list(map(hexify, read))) ocd.writeMemory(wordlen, addr, n, data) read = ocd.readMemory(wordlen, addr, n) show("memory (after):", list(map(hexify, read))) compareData(read, data) ocd.send("resume") openocd-0.9.0/contrib/rpc_examples/ocdrpc.hs0000644000175000017500000000407112315575360016031 00000000000000-- OpenOCD RPC example, covered by GNU GPLv3 or later -- Copyright (C) 2014 Paul Fertser -- -- Example output: -- $ ./ocdrpc -- Halting the target, full log output captured: -- target state: halted -- target halted due to debug-request, current mode: Thread -- xPSR: 0x21000000 pc: 0x00003352 msp: 0x20000fe8 -- -- Read memory, parse the result and show as a list of strings: -- ["0x20001000","0x0000334d","0x00002abb","0x0000118f","0x00002707","0x00002707","0x00002707","0x00000000","0x00000000","0x00000000","0x00000000","0x00002707","0x00002707","0x00000000","0x00002707","0x00002781"] -- Resuming {-# LANGUAGE OverloadedStrings #-} module Main where import Prelude import Control.Applicative import Network.Socket import System.IO.Streams.Core hiding (connect) import System.IO.Streams.Network import System.IO.Streams.Attoparsec import Data.Attoparsec.ByteString.Char8 import Data.Attoparsec.Combinator import Data.ByteString.Char8 hiding (putStrLn, concat, map) import Text.Printf ocdReply = manyTill anyChar (char '\x1a') ocdExec (oistream, oostream) command = do write (Just $ pack $ command ++ "\x1a") oostream parseFromStream ocdReply oistream -- For each line: dispose of address, then match hex values mdwParser = (manyTill anyChar (string ": ") *> hexadecimal `sepBy` char ' ') `sepBy` string " \n" ocdMdw :: (InputStream ByteString, OutputStream ByteString) -> Integer -> Integer -> IO [Integer] ocdMdw s start count = do s <- ocdExec s $ "ocd_mdw " ++ show start ++ " " ++ show count case parseOnly mdwParser (pack s) of Right r -> return $ concat r main = do osock <- socket AF_INET Stream defaultProtocol haddr <- inet_addr "127.0.0.1" connect osock (SockAddrInet 6666 haddr) ostreams <- socketToStreams osock putStrLn "Halting the target, full log output captured:" ocdExec ostreams "capture \"halt\"" >>= putStrLn putStrLn "Read memory, parse the result and show as a list of strings:" ocdMdw ostreams 0 16 >>= putStrLn . (show :: [String] -> String) . map (printf "0x%08x") putStrLn "Resuming" ocdExec ostreams "resume" openocd-0.9.0/contrib/remote_bitbang/0000755000175000017500000000000012315575360014600 500000000000000openocd-0.9.0/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c0000644000175000017500000002471012315575360021757 00000000000000/*************************************************************************** * Copyright (C) 2013 Paul Fertser * * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* This is a test application to be used as a remote bitbang server for the OpenOCD remote_bitbang interface driver. To compile run: gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c Usage example: On Raspberry Pi run: socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" On host run: openocd -c "interface remote_bitbang; remote_bitbang_host raspberrypi; remote_bitbang_port 7777" \ -f target/stm32f1x.cfg Or if you want to test UNIX sockets, run both on Raspberry Pi: socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" openocd -c "interface remote_bitbang; remote_bitbang_host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg */ #include #include #include #include #include #include #include #include #define LOG_ERROR(...) do { \ fprintf(stderr, __VA_ARGS__); \ fputc('\n', stderr); \ } while (0) #define LOG_WARNING(...) LOG_ERROR(__VA_ARGS__) #define ERROR_OK (-1) #define ERROR_FAIL (-2) #define ERROR_JTAG_INIT_FAILED ERROR_FAIL /* * Helper func to determine if gpio number valid * * Assume here that there will be less than 1000 gpios on a system */ static int is_gpio_valid(int gpio) { return gpio >= 0 && gpio < 1000; } /* * Helper func to open, write to and close a file * name and valstr must be null terminated. * * Returns negative on failure. */ static int open_write_close(const char *name, const char *valstr) { int ret; int fd = open(name, O_WRONLY); if (fd < 0) return fd; ret = write(fd, valstr, strlen(valstr)); close(fd); return ret; } /* * Helper func to unexport gpio from sysfs */ static void unexport_sysfs_gpio(int gpio) { char gpiostr[4]; if (!is_gpio_valid(gpio)) return; snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0) LOG_ERROR("Couldn't unexport gpio %d", gpio); return; } /* * Exports and sets up direction for gpio. * If the gpio is an output, it is initialized according to init_high, * otherwise it is ignored. * * If the gpio is already exported we just show a warning and continue; if * openocd happened to crash (or was killed by user) then the gpios will not * have been cleaned up. */ static int setup_sysfs_gpio(int gpio, int is_output, int init_high) { char buf[40]; char gpiostr[4]; int ret; if (!is_gpio_valid(gpio)) return ERROR_OK; snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); ret = open_write_close("/sys/class/gpio/export", gpiostr); if (ret < 0) { if (errno == EBUSY) { LOG_WARNING("gpio %d is already exported", gpio); } else { LOG_ERROR("Couldn't export gpio %d", gpio); perror("sysfsgpio: "); return ERROR_FAIL; } } snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio); ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in"); if (ret < 0) { LOG_ERROR("Couldn't set direction for gpio %d", gpio); perror("sysfsgpio: "); unexport_sysfs_gpio(gpio); return ERROR_FAIL; } snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio); if (is_output) ret = open(buf, O_WRONLY | O_NONBLOCK | O_SYNC); else ret = open(buf, O_RDONLY | O_NONBLOCK | O_SYNC); if (ret < 0) unexport_sysfs_gpio(gpio); return ret; } /* * file descriptors for /sys/class/gpio/gpioXX/value * Set up during init. */ static int tck_fd = -1; static int tms_fd = -1; static int tdi_fd = -1; static int tdo_fd = -1; static int trst_fd = -1; static int srst_fd = -1; /* * Bitbang interface read of TDO * * The sysfs value will read back either '0' or '1'. The trick here is to call * lseek to bypass buffering in the sysfs kernel driver. */ static int sysfsgpio_read(void) { char buf[1]; /* important to seek to signal sysfs of new read */ lseek(tdo_fd, 0, SEEK_SET); int ret = read(tdo_fd, &buf, sizeof(buf)); if (ret < 0) { LOG_WARNING("reading tdo failed"); return 0; } return buf[0]; } /* * Bitbang interface write of TCK, TMS, TDI * * Seeing as this is the only function where the outputs are changed, * we can cache the old value to avoid needlessly writing it. */ static void sysfsgpio_write(int tck, int tms, int tdi) { const char one[] = "1"; const char zero[] = "0"; static int last_tck; static int last_tms; static int last_tdi; static int first_time; size_t bytes_written; if (!first_time) { last_tck = !tck; last_tms = !tms; last_tdi = !tdi; first_time = 1; } if (tdi != last_tdi) { bytes_written = write(tdi_fd, tdi ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tdi failed"); } if (tms != last_tms) { bytes_written = write(tms_fd, tms ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tms failed"); } /* write clk last */ if (tck != last_tck) { bytes_written = write(tck_fd, tck ? &one : &zero, 1); if (bytes_written != 1) LOG_WARNING("writing tck failed"); } last_tdi = tdi; last_tms = tms; last_tck = tck; } /* * Bitbang interface to manipulate reset lines SRST and TRST * * (1) assert or (0) deassert reset lines */ static void sysfsgpio_reset(int trst, int srst) { const char one[] = "1"; const char zero[] = "0"; size_t bytes_written; /* assume active low */ if (srst_fd >= 0) { bytes_written = write(srst_fd, srst ? &zero : &one, 1); if (bytes_written != 1) LOG_WARNING("writing srst failed"); } /* assume active low */ if (trst_fd >= 0) { bytes_written = write(trst_fd, trst ? &zero : &one, 1); if (bytes_written != 1) LOG_WARNING("writing trst failed"); } } /* gpio numbers for each gpio. Negative values are invalid */ static int tck_gpio = -1; static int tms_gpio = -1; static int tdi_gpio = -1; static int tdo_gpio = -1; static int trst_gpio = -1; static int srst_gpio = -1; /* helper func to close and cleanup files only if they were valid/ used */ static void cleanup_fd(int fd, int gpio) { if (gpio >= 0) { if (fd >= 0) close(fd); unexport_sysfs_gpio(gpio); } } static void cleanup_all_fds(void) { cleanup_fd(tck_fd, tck_gpio); cleanup_fd(tms_fd, tms_gpio); cleanup_fd(tdi_fd, tdi_gpio); cleanup_fd(tdo_fd, tdo_gpio); cleanup_fd(trst_fd, trst_gpio); cleanup_fd(srst_fd, srst_gpio); } static void process_remote_protocol(void) { int c; while (1) { c = getchar(); if (c == EOF || c == 'Q') /* Quit */ break; else if (c == 'b' || c == 'B') /* Blink */ continue; else if (c >= 'r' && c <= 'r' + 2) { /* Reset */ char d = c - 'r'; sysfsgpio_reset(!!(d & 2), (d & 1)); } else if (c >= '0' && c <= '0' + 7) {/* Write */ char d = c - '0'; sysfsgpio_write(!!(d & 4), !!(d & 2), (d & 1)); } else if (c == 'R') putchar(sysfsgpio_read()); else LOG_ERROR("Unknown command '%c' received", c); } } int main(int argc, char *argv[]) { LOG_WARNING("SysfsGPIO remote_bitbang JTAG driver\n"); for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "tck")) tck_gpio = atoi(argv[++i]); else if (!strcmp(argv[i], "tms")) tms_gpio = atoi(argv[++i]); else if (!strcmp(argv[i], "tdo")) tdo_gpio = atoi(argv[++i]); else if (!strcmp(argv[i], "tdi")) tdi_gpio = atoi(argv[++i]); else if (!strcmp(argv[i], "trst")) trst_gpio = atoi(argv[++i]); else if (!strcmp(argv[i], "srst")) srst_gpio = atoi(argv[++i]); else { LOG_ERROR("Usage:\n%s ((tck|tms|tdo|tdi|trst|srst) num)*", argv[0]); return -1; } } if (!(is_gpio_valid(tck_gpio) && is_gpio_valid(tms_gpio) && is_gpio_valid(tdi_gpio) && is_gpio_valid(tdo_gpio))) { if (!is_gpio_valid(tck_gpio)) LOG_ERROR("gpio num for tck is invalid"); if (!is_gpio_valid(tms_gpio)) LOG_ERROR("gpio num for tms is invalid"); if (!is_gpio_valid(tdo_gpio)) LOG_ERROR("gpio num for tdo is invalid"); if (!is_gpio_valid(tdi_gpio)) LOG_ERROR("gpio num for tdi is invalid"); LOG_ERROR("Require tck, tms, tdi and tdo gpios to all be specified"); return ERROR_JTAG_INIT_FAILED; } /* * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. */ tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0); if (tck_fd < 0) goto out_error; tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1); if (tms_fd < 0) goto out_error; tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0); if (tdi_fd < 0) goto out_error; tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0); if (tdo_fd < 0) goto out_error; /* assume active low */ if (trst_gpio > 0) { trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1); if (trst_fd < 0) goto out_error; } /* assume active low */ if (srst_gpio > 0) { srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1); if (srst_fd < 0) goto out_error; } LOG_WARNING("SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d", tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); LOG_WARNING("SysfsGPIO num: srst = %d", srst_gpio); LOG_WARNING("SysfsGPIO num: trst = %d", trst_gpio); setvbuf(stdout, NULL, _IONBF, 0); process_remote_protocol(); cleanup_all_fds(); return 0; out_error: cleanup_all_fds(); return ERROR_JTAG_INIT_FAILED; } openocd-0.9.0/contrib/gen-stellaris-part-header.pl0000755000175000017500000000616212315575360017047 00000000000000#!/usr/bin/perl # Automatically generates the StellarisParts struct in src/flash/nor/stellaris.c # Uses the header files from TI/Luminary's StellarisWare complete Firmware Development Package # available from: http://www.luminarymicro.com/products/software_updates.html $comment = "// Autogenerated by contrib/gen-stellaris-part-header.pl // From Stellaris Firmware Development Package revision"; $struct_header = "static const struct { uint8_t class; uint8_t partno; const char *partname; } StellarisParts[] = { "; $struct_footer = "\t{0xFF, 0x00, \"Unknown Part\"}\n};\n"; $#ARGV == 1 || die "Usage: $0 \n"; -d $ARGV[0] || die $ARGV[0]." is not a directory\n"; $dir = $ARGV[0]; -f $ARGV[1] || die $ARGV[1]." is not a file\n"; $file = $ARGV[1]; print STDERR "Scanning $dir, Updating $file\n"; opendir(DIR, $dir) || die "can't open $dir: $!"; @files = readdir(DIR); closedir(DIR); @header_files = sort(grep(/lm.+\.h/, @files)); $ver = 0; $new_struct = $struct_header; process_file(@header_files); $new_struct .= $struct_footer; $dump = "$comment $ver\n$new_struct"; { local($/, *INPUT); open(INPUT, $file) || die "can't open $file: $!"; $contents = ; close(INPUT); } $old_struct = qr/((^\/\/.*?\n)*)\Q$struct_header\E.*?$struct_footer/sm; $contents =~ s/$old_struct/$dump/; open(OUTPUT, ">$file") || die "can't open file $file for writing: $!"; print OUTPUT $contents; close(OUTPUT); sub process_file { foreach $h_file (@_) { ($base) = ($h_file =~ m/lm..(.{3,7})\.h/ig); $base = uc($base); local($/, *FILE); open(FILE, "$dir/$h_file"); $content = ; close(FILE); $invalid = 0; if ($content =~ /This is part of revision (\d+) of/) { if ($ver != 0 and $ver != $1) { print STDERR "File version mismatch: $ver != $1\n"; $ver = max($ver, $1); } else { $ver = $1; } } if ($content =~ /SYSCTL_DID0_CLASS_[^M].+?0x(\S+)/s) { $class = hex($1) >> 16; } else { # attempt another way to get class if ($content =~ /\s(\S+)-class/) { $class = getclass($1); if ($class eq 0xFF) { print STDERR "$h_file unknown class\n"; $invalid = 1; } } else { print STDERR "$h_file is missing SYSCTL_DID0_CLASS_\n"; $class = 0; $invalid = 1; } } if ($content =~ /SYSCTL_DID1_PRTNO_$base.+0x(\S+)/) { $prtno = hex($1); $base = "LM3S" . $base; } else { # LM4F have a changed header if ($content =~ /SYSCTL_DID1_PRTNO_LM4F$base.+?0x(\S+)/s) { $prtno = hex($1); $base = "LM4F" . $base; } else { print STDERR "$h_file is missing SYSCTL_DID1_PRTNO\n"; $prtno = 0; $invalid = 1; } } $new_member = sprintf "{0x%02X, 0x%02X, \"%s\"},", $class, $prtno >> 16, $base; if ($invalid == 1) { #$new_struct .= "\t//$new_member\t// Invalid\n"; } else { $new_struct .= "\t$new_member\n"; } } } sub getclass { $class = $_[0]; if ($class =~ /Sandstorm/i) { return 0; } elsif ($class =~ /Fury/i) { return 1; } elsif ($class =~ /DustDevil/i) { return 3; } elsif ($class =~ /Tempest/i) { return 4; } elsif ($class =~ /Blizzard/i) { return 5; } elsif ($class =~ /Firestorm/i) { return 6; } return 0xFF; } openocd-0.9.0/contrib/coresight-trace.txt0000644000175000017500000000577112315575360015375 00000000000000+OpenOCD and CoreSight Tracing + Many recent ARM chips (Using e..g. Cortex-M3 and Cortex-M4 cores) support CoreSight debug/trace. This note sketches an approach currently planned for those cores with OpenOCD. This tracing data can help debug and tune ARM software, but not all cores support tracing. Some support more extensive tracing other cores with trace support +should be able to use the same approach and maybe some of the same analysis code. +the Cortex-M3 is assumed here to be the +core in use, for simplicity and to reflect current OpenOCD users. This note summarizes a software model to generate, collect, and analyze such trace data . That is not fully implemented as of early January 2011, +and thus is not *yet* usable. + + +Some microcontroller cores support a low pin-count Single-wire trace, with a mode where +trace data is emitted (usually to a UART. To use this mode, +SWD must be in use. +At this writing, OpenOCD SWD support is not yet complete either. (There are also multi-wire trace ports requiring more complex debug adapters than OpenOCD currently supports, and offering richer data. + + +* ENABLING involves activating SWD and (single wire) trace. + +current expectations are that OpenOCD itself will handle enabling; activating single wire trace involves a debug adapter interaction, and collecting that trace data requires particular (re)wiring. + +* CONFIGURATION involves setting up ITM and/or ETM modules to emit the +desired data from the Cortex core. (This might include dumping +event counters printf-style messages; code profiling; and more. Not all +cores offer the same trace capabilities. + +current expectations are that Tcl scripts will be used to configure these +modules for the desired tracing, by direct writes to registers. In some +cases (as with RTOS event tracking and similar messaging, this might +be augmented or replaced by user code running on the ARM core. + +COLLECTION involves reading that trace data, probably through UART, and +saving it in a useful format to analyse For now, deferred analysis modes are assumed, not than real-time or interactive ones. + + +current expectations are to to dump data in text using contrib/itmdump.c +or derived tools, and to post-process it into reports. Such reports might +include program messaging (such as application data streams via ITM, maybe +using printf type messaging; code coverage analysis or so forth. Recent +versions of CMSIS software reserve some ITM codespace for RTOS event tracing and include ITM messaging support. Clearly some of that data would be valuable for interactive debugging. + +Should someone get ambitious, GUI reports should be possible. GNU tools +for simpler reports like gprof may be simpler to support at first. +In any case, OpenOCD is not currently GUI-oriented. Accordingly, we now +expect any such graphics to come from postprocessing. measurments for RTOS event timings should also be easy to collect. +Examples include context and message switch times, as well as times for application interactions. + openocd-0.9.0/contrib/loaders/0000755000175000017500000000000012315575360013250 500000000000000openocd-0.9.0/contrib/loaders/flash/0000755000175000017500000000000012516456301014341 500000000000000openocd-0.9.0/contrib/loaders/flash/mrvlqspi_write.S0000644000175000017500000001452612516456301017504 00000000000000/*************************************************************************** * Copyright (C) 2014 by Mahavir Jain * * * * Adapted from (contrib/loaders/flash/lpcspifi_write.S): * * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m3 .thumb .thumb_func /* * For compilation: * arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c contrib/loaders/flash/mrvlqspi_write.S * arm-none-eabi-objcopy -O binary mrvlqspi_write.o code.bin * Copy code.bin into mrvlqspi flash driver */ /* * Params : * r0 = workarea start, status (out) * r1 = workarea end * r2 = target address (offset from flash base) * r3 = count (bytes) * r4 = page size * r5 = qspi base address * Clobbered: * r7 - rp * r8 - wp, tmp * r9 - send/receive data * r10 - current page end address */ #define CNTL 0x0 #define CONF 0x4 #define DOUT 0x8 #define DIN 0xc #define INSTR 0x10 #define ADDR 0x14 #define RDMODE 0x18 #define HDRCNT 0x1c #define DINCNT 0x20 #define SS_EN (1 << 0) #define XFER_RDY (1 << 1) #define RFIFO_EMPTY (1 << 4) #define WFIFO_EMPTY (1 << 6) #define WFIFO_FULL (1 << 7) #define FIFO_FLUSH (1 << 9) #define RW_EN (1 << 13) #define XFER_STOP (1 << 14) #define XFER_START (1 << 15) #define INS_WRITE_ENABLE 0x06 #define INS_READ_STATUS 0x05 #define INS_PAGE_PROGRAM 0x02 init: mov.w r10, #0x00 find_next_page_boundary: add r10, r4 /* Increment to the next page */ cmp r10, r2 /* If we have not reached the next page boundary after the target address, keep going */ bls find_next_page_boundary write_enable: /* Flush read/write fifo's */ bl flush_fifo /* Instruction byte 1 */ movs r8, #0x1 str r8, [r5, #HDRCNT] /* Set write enable instruction */ movs r8, #INS_WRITE_ENABLE str r8, [r5, #INSTR] movs r9, #0x1 bl start_tx bl stop_tx page_program: /* Instruction byte 1, Addr byte 3 */ movs r8, #0x31 str r8, [r5, #HDRCNT] /* Todo: set addr and data pin to single */ write_address: mov r8, r2 str r8, [r5, #ADDR] /* Set page program instruction */ movs r8, #INS_PAGE_PROGRAM str r8, [r5, #INSTR] /* Start write transfer */ movs r9, #0x1 bl start_tx wait_fifo: ldr r8, [r0] /* read the write pointer */ cmp r8, #0 /* if it's zero, we're gonzo */ beq exit ldr r7, [r0, #4] /* read the read pointer */ cmp r7, r8 /* wait until they are not equal */ beq wait_fifo write: ldrb r9, [r7], #0x01 /* Load one byte from the FIFO, increment the read pointer by 1 */ bl write_data /* send the byte to the flash chip */ cmp r7, r1 /* wrap the read pointer if it is at the end */ it cs addcs r7, r0, #8 /* skip loader args */ str r7, [r0, #4] /* store the new read pointer */ subs r3, r3, #1 /* decrement count */ cmp r3, #0 /* Exit if we have written everything */ beq write_wait add r2, #1 /* Increment flash address by 1 */ cmp r10, r2 /* See if we have reached the end of a page */ bne wait_fifo /* If not, keep writing bytes */ write_wait: bl stop_tx /* Otherwise, end the command and keep going w/ the next page */ add r10, r4 /* Move up the end-of-page address by the page size*/ check_flash_busy: /* Wait for the flash to finish the previous page write */ /* Flush read/write fifo's */ bl flush_fifo /* Instruction byte 1 */ movs r8, #0x1 str r8, [r5, #HDRCNT] /* Continuous data in of status register */ movs r8, #0x0 str r8, [r5, #DINCNT] /* Set write enable instruction */ movs r8, #INS_READ_STATUS str r8, [r5, #INSTR] /* Start read transfer */ movs r9, #0x0 bl start_tx wait_flash_busy: bl read_data and.w r9, r9, #0x1 cmp r9, #0x0 bne.n wait_flash_busy bl stop_tx cmp r3, #0 bne.n write_enable /* If it is done, start a new page write */ b exit /* All data written, exit */ write_data: /* Send/receive 1 byte of data over QSPI */ ldr r8, [r5, #CNTL] lsls r8, r8, #24 bmi.n write_data str r9, [r5, #DOUT] bx lr read_data: /* Read 1 byte of data over QSPI */ ldr r8, [r5, #CNTL] lsls r8, r8, #27 bmi.n read_data ldr r9, [r5, #DIN] bx lr flush_fifo: /* Flush read write fifos */ ldr r8, [r5, #CONF] orr.w r8, r8, #FIFO_FLUSH str r8, [r5, #CONF] flush_reset: ldr r8, [r5, #CONF] lsls r8, r8, #22 bmi.n flush_reset bx lr start_tx: ldr r8, [r5, #CNTL] orr.w r8, r8, #SS_EN str r8, [r5, #CNTL] xfer_rdy: ldr r8, [r5, #CNTL] lsls r8, r8, #30 bpl.n xfer_rdy ldr r8, [r5, #CONF] bfi r8, r9, #13, #1 orr.w r8, r8, #XFER_START str r8, [r5, #CONF] bx lr stop_tx: ldr r8, [r5, #CNTL] lsls r8, r8, #30 bpl.n stop_tx wfifo_wait: ldr r8, [r5, #CNTL] lsls r8, r8, #25 bpl.n wfifo_wait ldr r8, [r5, #CONF] orr.w r8, r8, #XFER_STOP str r8, [r5, #CONF] xfer_start: ldr r8, [r5, #CONF] lsls r8, r8, #16 bmi.n xfer_start ss_disable: # Disable SS_EN ldr r8, [r5, #CNTL] bic.w r8, r8, #SS_EN str r8, [r5, #CNTL] wait: ldr r8, [r5, #CNTL] lsls r8, r8, #30 bpl.n wait bx lr error: movs r0, #0 str r0, [r2, #4] /* set rp = 0 on error */ exit: mov r0, r6 bkpt #0x00 .end openocd-0.9.0/contrib/loaders/flash/cortex-m0.S0000644000175000017500000000536012516456301016227 00000000000000/*************************************************************************** * Copyright (C) 2014 by Angus Gratton * * Derived from stm32f1x.S: * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * Copyright (C) 2013 by Roman Dmitrienko * * me@iamroman.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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 . * ***************************************************************************/ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func /* Written for NRF51822 (src/flash/nor/nrf51.c) however the NRF NVMC is * very generic (CPU blocks during flash writes), so this is actually * just a generic word-oriented copy routine for cortex-m0 (also * suitable for cortex m0plus/m3/m4.) * * To assemble: * arm-none-eabi-gcc -c cortex-m0.S * * To disassemble: * arm-none-eabi-objdump -o cortex-m0.o * * Thanks to Jens Bauer for providing advice on some of the tweaks. */ /* Params: * r0 - byte count (in) * r1 - workarea start * r2 - workarea end * r3 - target address * Clobbered: * r4 - rp * r5 - wp, tmp */ wait_fifo: ldr r5, [r1, #0] /* read wp */ cmp r5, #0 /* abort if wp == 0 */ beq exit ldr r4, [r1, #4] /* read rp */ cmp r4, r5 /* wait until rp != wp */ beq wait_fifo ldmia r4!, {r5} /* "*target_address++ = *rp++" */ stmia r3!, {r5} cmp r4, r2 /* wrap rp at end of work area buffer */ bcc no_wrap mov r4, r1 adds r4, #8 /* skip rp,wp at start of work area */ no_wrap: str r4, [r1, #4] /* write back rp */ subs r0, #4 /* decrement byte count */ bne wait_fifo /* loop if not done */ exit: bkpt #0 openocd-0.9.0/contrib/loaders/flash/lpcspifi_init.S0000644000175000017500000001030112315575360017240 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /*************************************************************************** * This is an algorithm for the LPC43xx family (and probably the LPC18xx * * family as well, though they have not been tested) that will initialize * * memory-mapped SPI flash accesses. Unfortunately NXP has published * * neither the ROM source code that performs this initialization nor the * * register descriptions necessary to do so, so this code is necessary to * * call into the ROM SPIFI API. * ***************************************************************************/ .text .syntax unified .arch armv7-m .thumb .thumb_func .align 2 /* * Params : * r0 = spifi clock speed */ #define IOCONFIG_BASE_HIGH 0x4008 #define IOCONFIG_BASE_LOW 0x6000 #define IOCONFIG_SCK_OFFSET 0x18c #define IOCONFIG_HOLD_OFFSET 0x190 #define IOCONFIG_WP_OFFSET 0x194 #define IOCONFIG_MISO_OFFSET 0x198 #define IOCONFIG_MOSI_OFFSET 0x19c #define IOCONFIG_CS_OFFSET 0x1a0 #define SPIFI_ROM_TABLE_BASE_HIGH 0x1040 #define SPIFI_ROM_TABLE_BASE_LOW 0x0118 code: mov.w r8, r0 sub sp, #0x84 add r7, sp, #0x0 /* Initialize SPIFI pins */ mov.w r3, #IOCONFIG_BASE_LOW movt r3, #IOCONFIG_BASE_HIGH mov.w r2, #0xf3 str.w r2, [r3, #IOCONFIG_SCK_OFFSET] mov.w r3, #IOCONFIG_BASE_LOW movt r3, #IOCONFIG_BASE_HIGH mov.w r2, #IOCONFIG_BASE_LOW movt r2, #IOCONFIG_BASE_HIGH mov.w r1, #IOCONFIG_BASE_LOW movt r1, #IOCONFIG_BASE_HIGH mov.w r0, #IOCONFIG_BASE_LOW movt r0, #IOCONFIG_BASE_HIGH mov.w r4, #0xd3 str.w r4, [r0, #IOCONFIG_MOSI_OFFSET] mov r0, r4 str.w r0, [r1, #IOCONFIG_MISO_OFFSET] mov r1, r0 str.w r1, [r2, #IOCONFIG_WP_OFFSET] str.w r1, [r3, #IOCONFIG_HOLD_OFFSET] mov.w r3, #IOCONFIG_BASE_LOW movt r3, #IOCONFIG_BASE_HIGH mov.w r2, #0x13 str.w r2, [r3, #IOCONFIG_CS_OFFSET] /* Perform SPIFI init. See spifi_rom_api.h (in NXP lpc43xx driver package) for details */ /* on initialization arguments. */ movw r3, #SPIFI_ROM_TABLE_BASE_LOW /* The ROM API table is located @ 0x10400118, and */ movt r3, #SPIFI_ROM_TABLE_BASE_HIGH /* the first pointer in the struct is to the init function. */ ldr r3, [r3, #0x0] ldr r4, [r3, #0x0] /* Grab the init function pointer from the table */ /* Set up function arguments */ movw r0, #0x3b4 movt r0, #0x1000 /* Pointer to a SPIFI data struct that we don't care about */ mov.w r1, #0x3 /* "csHigh". Not 100% sure what this does. */ mov.w r2, #0xc0 /* The configuration word: S_RCVCLOCK | S_FULLCLK */ mov.w r3, r8 /* SPIFI clock speed (12MHz) */ blx r4 /* Call the init function */ b done done: bkpt #0 .end openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s0000644000175000017500000000457712315575360020666 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldrh r5, [r0], #2 strh r9, [r8] strh r11, [r10] strh r3, [r8] strh r5, [r1] nop busy: ldrh r6, [r1] eor r7, r5, r6 ands r7, #0x80 bne busy subs r2, r2, #1 /* 0x1 */ moveq r5, #128 /* 0x80 */ beq done add r1, r1, #2 /* 0x2 */ b code done: b done .end openocd-0.9.0/contrib/loaders/flash/armv7m_cfi_span_16_dq7.s0000644000175000017500000000462312315575360020612 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .arch armv7-m .thumb .thumb_func .align 2 /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldrh r5, [r0], #2 strh r9, [r8] strh r11, [r10] strh r3, [r8] strh r5, [r1] nop busy: ldrh r6, [r1] eor r7, r5, r6 ands r7, r4, r7 bne busy subs r2, r2, #1 /* 0x1 */ beq success add r1, r1, #2 /* 0x2 */ b code success: mov r5, #128 /* 0x80 */ b done done: bkpt #0 .end openocd-0.9.0/contrib/loaders/flash/armv7m_cfi_span_16.s0000644000175000017500000000523512315575360020037 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .arch armv7-m .thumb .thumb_func .align 2 /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldrh r5, [r0], #2 strh r9, [r8] strh r11, [r10] strh r3, [r8] strh r5, [r1] nop busy: ldrh r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ ands r6, r6, r4, lsr #2 beq busy /* b if DQ5 low */ ldrh r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ mov r5, #0 /* 0x0 - return 0x00, error */ bne done cont: subs r2, r2, #1 /* 0x1 */ beq success add r1, r1, #2 /* 0x2 */ b code success: mov r5, #128 /* 0x80 */ b done done: bkpt #0 .end openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_intel_8.s0000644000175000017500000000407312315575360020175 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* algorithm register usage: * r0: source address (in RAM) * r1: target address (in Flash) * r2: count * r3: flash write command * r4: status byte (returned to host) * r5: busy test pattern * r6: error test pattern */ loop: ldrb r4, [r0], #1 strb r3, [r1] strb r4, [r1] busy: ldrb r4, [r1] and r7, r4, r5 cmp r7, r5 bne busy tst r4, r6 bne done subs r2, r2, #1 beq done add r1, r1, #1 b loop done: b done .end openocd-0.9.0/contrib/loaders/flash/lpcspifi_erase.S0000644000175000017500000001355512315575360017412 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m3 .thumb .thumb_func /* * Params : * r0 = start address, status (out) * r1 = count * r2 = erase command * r3 = block size */ #define SSP_BASE_HIGH 0x4008 #define SSP_BASE_LOW 0x3000 #define SSP_CR0_OFFSET 0x00 #define SSP_CR1_OFFSET 0x04 #define SSP_DATA_OFFSET 0x08 #define SSP_CPSR_OFFSET 0x10 #define SSP_SR_OFFSET 0x0c #define SSP_CLOCK_BASE_HIGH 0x4005 #define SSP_CLOCK_BASE_LOW 0x0000 #define SSP_BRANCH_CLOCK_BASE_HIGH 0x4005 #define SSP_BRANCH_CLOCK_BASE_LOW 0x2000 #define SSP_BASE_CLOCK_OFFSET 0x94 #define SSP_BRANCH_CLOCK_OFFSET 0x700 #define IOCONFIG_BASE_HIGH 0x4008 #define IOCONFIG_BASE_LOW 0x6000 #define IOCONFIG_SCK_OFFSET 0x18c #define IOCONFIG_HOLD_OFFSET 0x190 #define IOCONFIG_WP_OFFSET 0x194 #define IOCONFIG_MISO_OFFSET 0x198 #define IOCONFIG_MOSI_OFFSET 0x19c #define IOCONFIG_CS_OFFSET 0x1a0 #define IO_BASE_HIGH 0x400f #define IO_BASE_LOW 0x4000 #define IO_CS_OFFSET 0xab #define IODIR_BASE_HIGH 0x400f #define IODIR_BASE_LOW 0x6000 #define IO_CS_DIR_OFFSET 0x14 setup: /* Initialize SSP pins and module */ mov.w r10, #IOCONFIG_BASE_LOW movt r10, #IOCONFIG_BASE_HIGH mov.w r8, #0xea str.w r8, [r10, #IOCONFIG_SCK_OFFSET] /* Configure SCK pin function */ mov.w r8, #0x40 str.w r8, [r10, #IOCONFIG_HOLD_OFFSET] /* Configure /HOLD pin function */ mov.w r8, #0x40 str.w r8, [r10, #IOCONFIG_WP_OFFSET] /* Configure /WP pin function */ mov.w r8, #0xed str.w r8, [r10, #IOCONFIG_MISO_OFFSET] /* Configure MISO pin function */ mov.w r8, #0xed str.w r8, [r10, #IOCONFIG_MOSI_OFFSET] /* Configure MOSI pin function */ mov.w r8, #0x44 str.w r8, [r10, #IOCONFIG_CS_OFFSET] /* Configure CS pin function */ mov.w r10, #IODIR_BASE_LOW movt r10, #IODIR_BASE_HIGH mov.w r8, #0x800 str r8, [r10, #IO_CS_DIR_OFFSET] /* Set CS as output */ mov.w r10, #IO_BASE_LOW movt r10, #IO_BASE_HIGH mov.w r8, #0xff str.w r8, [r10, #IO_CS_OFFSET] /* Set CS high */ mov.w r10, #SSP_CLOCK_BASE_LOW movt r10, #SSP_CLOCK_BASE_HIGH mov.w r8, #0x0000 movt r8, #0x0100 str.w r8, [r10, #SSP_BASE_CLOCK_OFFSET] /* Configure SSP0 base clock (use 12 MHz IRC) */ mov.w r10, #SSP_BRANCH_CLOCK_BASE_LOW movt r10, #SSP_BRANCH_CLOCK_BASE_HIGH mov.w r8, #0x01 str.w r8, [r10, #SSP_BRANCH_CLOCK_OFFSET] /* Configure (enable) SSP0 branch clock */ mov.w r10, #SSP_BASE_LOW movt r10, #SSP_BASE_HIGH mov.w r8, #0x07 str.w r8, [r10, #SSP_CR0_OFFSET] /* Set clock postscale */ mov.w r8, #0x02 str.w r8, [r10, #SSP_CPSR_OFFSET] /* Set clock prescale */ str.w r8, [r10, #SSP_CR1_OFFSET] /* Enable SSP in SPI mode */ write_enable: bl cs_down mov.w r9, #0x06 /* Send the write enable command */ bl write_data bl cs_up bl cs_down mov.w r9, #0x05 /* Get status register */ bl write_data mov.w r9, #0x00 /* Dummy data to clock in status */ bl write_data bl cs_up tst r9, #0x02 /* If the WE bit isn't set, we have a problem. */ beq error erase: bl cs_down mov.w r9, r2 /* Send the erase command */ bl write_data write_address: lsr r9, r0, #16 /* Send the current 24-bit write address, MSB first */ bl write_data lsr r9, r0, #8 bl write_data mov.w r9, r0 bl write_data bl cs_up wait_flash_busy: /* Wait for the flash to finish the previous erase */ bl cs_down mov.w r9, #0x05 /* Get status register */ bl write_data mov.w r9, #0x00 /* Dummy data to clock in status */ bl write_data bl cs_up tst r9, #0x01 /* If it isn't done, keep waiting */ bne wait_flash_busy subs r1, r1, #1 /* decrement count */ cbz r1, exit /* Exit if we have written everything */ add r0, r3 /* Move the address up by the block size */ b write_enable /* Start a new block erase */ write_data: /* Send/receive 1 byte of data over SSP */ mov.w r10, #SSP_BASE_LOW movt r10, #SSP_BASE_HIGH str.w r9, [r10, #SSP_DATA_OFFSET] /* Write supplied data to the SSP data reg */ wait_transmit: ldr r9, [r10, #SSP_SR_OFFSET] /* Check SSP status */ tst r9, #0x0010 /* Check if BSY bit is set */ bne wait_transmit /* If still transmitting, keep waiting */ ldr r9, [r10, #SSP_DATA_OFFSET] /* Load received data */ bx lr /* Exit subroutine */ cs_up: mov.w r8, #0xff b cs_write cs_down: mov.w r8, #0x0000 cs_write: mov.w r10, #IO_BASE_LOW movt r10, #IO_BASE_HIGH str.w r8, [r10, #IO_CS_OFFSET] bx lr error: movs r0, #0 exit: bkpt #0x00 .end openocd-0.9.0/contrib/loaders/flash/mdr32fx.S0000644000175000017500000000717012315575360015703 00000000000000/*************************************************************************** * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * Copyright (C) 2013 by Paul Fertser * * fercerpav@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func .global write /* Params: * r0 - flash base (in), status (out) * r1 - count (32bit) * r2 - workarea start * r3 - workarea end * r4 - target address * Clobbered: * r5 - rp * r6 - wp, tmp * r7 - current FLASH_CMD */ #define FLASH_CMD 0x00 #define FLASH_ADR 0x04 #define FLASH_DI 0x08 #define FLASH_NVSTR (1 << 13) #define FLASH_PROG (1 << 12) #define FLASH_MAS1 (1 << 11) #define FLASH_ERASE (1 << 10) #define FLASH_SE (1 << 8) #define FLASH_YE (1 << 7) #define FLASH_XE (1 << 6) ldr r7, [r0, #FLASH_CMD] wait_fifo: ldr r6, [r2, #0] /* read wp */ cmp r6, #0 /* abort if wp == 0 */ beq exit ldr r5, [r2, #4] /* read rp */ cmp r5, r6 /* wait until rp != wp */ beq wait_fifo ldr r6, [r5] /* "*target_address++ = *rp++" */ str r4, [r0, #FLASH_ADR] str r6, [r0, #FLASH_DI] ldr r6, =(FLASH_XE | FLASH_PROG) orrs r7, r7, r6 str r7, [r0, #FLASH_CMD] # wait 5us movs r6, #5 bl delay ldr r6, =#FLASH_NVSTR orrs r7, r7, r6 str r7, [r0, #FLASH_CMD] # wait 10us movs r6, #13 bl delay movs r6, #FLASH_YE orrs r7, r7, r6 str r7, [r0, #FLASH_CMD] # wait 40us movs r6, #61 bl delay movs r6, #FLASH_YE bics r7, r7, r6 str r7, [r0, #FLASH_CMD] ldr r6, =#FLASH_PROG bics r7, r7, r6 str r7, [r0, #FLASH_CMD] # wait 5us movs r6, #5 bl delay ldr r6, =#(FLASH_XE | FLASH_NVSTR) bics r7, r7, r6 str r7, [r0, #FLASH_CMD] adds r5, #4 adds r4, #4 cmp r5, r3 /* wrap rp at end of buffer */ bcc no_wrap mov r5, r2 adds r5, #8 no_wrap: str r5, [r2, #4] /* store rp */ subs r1, r1, #1 /* decrement word count */ cmp r1, #0 beq exit /* loop if not done */ b wait_fifo exit: mov r0, r6 /* return status in r0 */ bkpt #0 /* r6 - in * for r6 == 1 it'll take: * 1 (prepare operand) + 4 (bl) + 2 (subs+cmp) + 1 (bne) + 3 (b) -> * 11 tacts == 1.4us with 8MHz * every extra iteration will take 5 tacts == 0.6us */ delay: subs r6, r6, #1 cmp r6, #0 bne delay bx lr openocd-0.9.0/contrib/loaders/flash/efm32.S0000644000175000017500000000744612315575360015340 00000000000000/*************************************************************************** * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * Copyright (C) 2013 by Roman Dmitrienko * * me@iamroman.org * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func /* Params: * r0 - flash base (in), status (out) * r1 - count (word-32bit) * r2 - workarea start * r3 - workarea end * r4 - target address * Clobbered: * r5 - rp * r6 - wp, tmp * r7 - tmp */ /* offsets of registers from flash reg base */ #define EFM32_MSC_WRITECTRL_OFFSET 0x008 #define EFM32_MSC_WRITECMD_OFFSET 0x00c #define EFM32_MSC_ADDRB_OFFSET 0x010 #define EFM32_MSC_WDATA_OFFSET 0x018 #define EFM32_MSC_STATUS_OFFSET 0x01c #define EFM32_MSC_LOCK_OFFSET 0x03c /* unlock MSC */ ldr r6, =#0x1b71 str r6, [r0, #EFM32_MSC_LOCK_OFFSET] /* set WREN to 1 */ movs r6, #1 str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET] wait_fifo: ldr r6, [r2, #0] /* read wp */ cmp r6, #0 /* abort if wp == 0 */ beq exit ldr r5, [r2, #4] /* read rp */ cmp r5, r6 /* wait until rp != wp */ beq wait_fifo /* store address in MSC_ADDRB */ str r4, [r0, #EFM32_MSC_ADDRB_OFFSET] /* set LADDRIM bit */ movs r6, #1 str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] /* check status for INVADDR and/or LOCKED */ ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] movs r7, #6 tst r6, r7 bne error /* wait for WDATAREADY */ wait_wdataready: ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] movs r7, #8 tst r6, r7 beq wait_wdataready /* load data to WDATA */ ldr r6, [r5] str r6, [r0, #EFM32_MSC_WDATA_OFFSET] /* set WRITEONCE bit */ movs r6, #8 str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] adds r5, #4 /* rp++ */ adds r4, #4 /* target_address++ */ /* wait until BUSY flag is reset */ busy: ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] movs r7, #1 tst r6, r7 bne busy cmp r5, r3 /* wrap rp at end of buffer */ bcc no_wrap mov r5, r2 adds r5, #8 no_wrap: str r5, [r2, #4] /* store rp */ subs r1, r1, #1 /* decrement word count */ cmp r1, #0 beq exit /* loop if not done */ b wait_fifo error: movs r0, #0 str r0, [r2, #4] /* set rp = 0 on error */ exit: mov r0, r6 /* return status in r0 */ bkpt #0 openocd-0.9.0/contrib/loaders/flash/sim3x.s0000644000175000017500000000466212516456301015520 00000000000000/*************************************************************************** * Copyright (C) 2014 by Ladislav Bábel * * ladababel@seznam.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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. * ***************************************************************************/ #define INITIAL_UNLOCK 0x5A #define MULTIPLE_UNLOCK 0xF2 #define FLASHCTRL_KEY 0x4002E0C0 #define FLASHCTRL_CONFIG 0x4002E000 #define FLASHCTRL_WRADDR 0x4002E0A0 #define FLASHCTRL_WRDATA 0x4002E0B0 #define BUSYF 0x00100000 /* Write the initial unlock value to KEY (0xA5) */ movs r6, #INITIAL_UNLOCK str r6, [r0, #FLASHCTRL_KEY] /* Write the multiple unlock value to KEY (0xF2) */ movs r6, #MULTIPLE_UNLOCK str r6, [r0, #FLASHCTRL_KEY] wait_fifo: ldr r6, [r2, #0] cmp r6, #0 beq exit ldr r5, [r2, #4] cmp r5, r6 beq wait_fifo /* wait for BUSYF flag */ wait_busy1: ldr r6, [r0, #FLASHCTRL_CONFIG] tst r6, #BUSYF bne wait_busy1 /* Write the destination address to WRADDR */ str r4, [r0, #FLASHCTRL_WRADDR] /* Write the data half-word to WRDATA in right-justified format */ ldrh r6, [r5] str r6, [r0, #FLASHCTRL_WRDATA] adds r5, #2 adds r4, #2 /* wrap rp at end of buffer */ cmp r5, r3 bcc no_wrap mov r5, r2 adds r5, #8 no_wrap: str r5, [r2, #4] subs r1, r1, #1 cmp r1, #0 beq exit b wait_fifo exit: movs r6, #MULTIPLE_LOCK str r6, [r0, #FLASHCTRL_KEY] /* wait for BUSYF flag */ wait_busy2: ldr r6, [r0, #FLASHCTRL_CONFIG] tst r6, #BUSYF bne wait_busy2 bkpt #0 openocd-0.9.0/contrib/loaders/flash/str7x.s0000644000175000017500000000440112315575360015537 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4t .section .init /* r0 source address r1 address r2 FLASH_CR0 r3 dword count r4 result r5 busy mask */ write: mov r4, #0x10000000 /* set DWPG bit */ str r4, [r2, #0x0] /* FLASH_CR0 */ str r1, [r2, #0x10] /* FLASH_AR */ ldr r4, [r0], #4 /* load data */ str r4, [r2, #0x8] /* FLASH_DR0 */ ldr r4, [r0], #4 /* load data */ str r4, [r2, #0xc] /* FLASH_DR1 */ mov r4, #0x90000000 /* set DWPG and WMS bits */ str r4, [r2, #0x0] /* FLASH_CR0 */ busy: ldr r4, [r2, #0x0] /* FLASH_CR0 */ tst r4, r5 bne busy ldr r4, [r2, #0x14] /* FLASH_ER */ tst r4, #0xff /* do we have errors */ tsteq r4, #0x100 /* write protection set */ bne exit add r1, r1, #0x8 /* next 8 bytes */ subs r3, r3, #1 /* decremment dword count */ bne write exit: b exit .end openocd-0.9.0/contrib/loaders/flash/str9x.s0000644000175000017500000000412012315575360015537 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv5t .section .init /* r0 source address (in) r1 target address (in) r2 word count (in) r3 result (out) */ write: bic r4, r1, #3 /* word address */ mov r3, #0x40 /* write command */ strh r3, [r4, #0] ldrh r3, [r0], #2 /* read data */ strh r3, [r1], #2 /* write data */ mov r3, #0x70 /* status command */ strh r3, [r4, #0] busy: ldrb r3, [r4, #0] /* status */ tst r3, #0x80 beq busy mov r5, #0x50 /* clear status command */ strh r5, [r4, #0] mov r5, #0xFF /* read array */ strh r5, [r4, #0] tst r3, #0x12 bne exit subs r2, r2, #1 /* decremment word count */ bne write exit: bkpt #0 .end openocd-0.9.0/contrib/loaders/flash/stellaris.s0000644000175000017500000000533212315575360016456 00000000000000/*************************************************************************** * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m3 .thumb .thumb_func /* * Params : * r0 = workarea start * r1 = workarea end * r2 = target address * r3 = count (32bit words) * * Clobbered: * r4 = pFLASH_CTRL_BASE * r5 = FLASHWRITECMD * r7 - rp * r8 - wp, tmp */ write: ldr r4, pFLASH_CTRL_BASE ldr r5, FLASHWRITECMD wait_fifo: ldr r8, [r0, #0] /* read wp */ cmp r8, #0 /* abort if wp == 0 */ beq exit ldr r7, [r0, #4] /* read rp */ cmp r7, r8 /* wait until rp != wp */ beq wait_fifo mainloop: str r2, [r4, #0] /* FMA - write address */ add r2, r2, #4 /* increment target address */ ldr r8, [r7], #4 str r8, [r4, #4] /* FMD - write data */ str r5, [r4, #8] /* FMC - enable write */ busy: ldr r8, [r4, #8] tst r8, #1 bne busy cmp r7, r1 /* wrap rp at end of buffer */ it cs addcs r7, r0, #8 /* skip loader args */ str r7, [r0, #4] /* store rp */ subs r3, r3, #1 /* decrement word count */ cbz r3, exit /* loop if not done */ b wait_fifo exit: bkpt #0 pFLASH_CTRL_BASE: .word 0x400FD000 FLASHWRITECMD: .word 0xA4420001 openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_span_8.s0000644000175000017500000000515312315575360020023 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldrb r5, [r0], #1 strb r9, [r8] strb r11, [r10] strb r3, [r8] strb r5, [r1] nop busy: ldrb r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ ands r6, r6, r4, lsr #2 beq busy /* b if DQ5 low */ ldrb r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ mov r5, #0 /* 0x0 - return 0x00, error */ bne done cont: subs r2, r2, #1 /* 0x1 */ moveq r5, #128 /* 0x80 */ beq done add r1, r1, #1 /* 0x1 */ b code done: b done .end openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_span_16.s0000644000175000017500000000515312315575360020102 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldrh r5, [r0], #2 strh r9, [r8] strh r11, [r10] strh r3, [r8] strh r5, [r1] nop busy: ldrh r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ ands r6, r6, r4, lsr #2 beq busy /* b if DQ5 low */ ldrh r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ mov r5, #0 /* 0x0 - return 0x00, error */ bne done cont: subs r2, r2, #1 /* 0x1 */ moveq r5, #128 /* 0x80 */ beq done add r1, r1, #2 /* 0x2 */ b code done: b done .end openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_span_32.s0000644000175000017500000000515312315575360020100 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* input parameters - */ /* R0 = source address */ /* R1 = destination address */ /* R2 = number of writes */ /* R3 = flash write command */ /* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */ /* output parameters - */ /* R5 = 0x80 ok 0x00 bad */ /* temp registers - */ /* R6 = value read from flash to test status */ /* R7 = holding register */ /* unlock registers - */ /* R8 = unlock1_addr */ /* R9 = unlock1_cmd */ /* R10 = unlock2_addr */ /* R11 = unlock2_cmd */ code: ldr r5, [r0], #4 str r9, [r8] str r11, [r10] str r3, [r8] str r5, [r1] nop busy: ldr r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ ands r6, r6, r4, lsr #2 beq busy /* b if DQ5 low */ ldr r6, [r1] eor r7, r5, r6 ands r7, r4, r7 beq cont /* b if DQ7 == Data7 */ mov r5, #0 /* 0x0 - return 0x00, error */ bne done cont: subs r2, r2, #1 /* 0x1 */ moveq r5, #128 /* 0x80 */ beq done add r1, r1, #4 /* 0x4 */ b code done: b done .end openocd-0.9.0/contrib/loaders/flash/stm32lx.S0000644000175000017500000000466612315575360015741 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2011 Clement Burin des Roziers * * clement.burin-des-roziers@hikob.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ // Build : arm-eabi-gcc -c stm32lx.S .text .syntax unified .cpu cortex-m3 .thumb .thumb_func .global write /* r0 - destination address r1 - source address r2 - count */ // Set 0 to r3 movs r3, #0 // Go to compare b.n test_done write_word: // Load one word from address in r0, increment by 4 ldr.w ip, [r1], #4 // Store the word to address in r1, increment by 4 str.w ip, [r0], #4 // Increment r3 adds r3, #1 test_done: // Compare r3 and r2 cmp r3, r2 // Loop if not zero bcc.n write_word // Set breakpoint to exit bkpt #0x00 openocd-0.9.0/contrib/loaders/flash/stm32f1x.S0000644000175000017500000000515112315575360016002 00000000000000/*************************************************************************** * Copyright (C) 2011 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func .global write /* Params: * r0 - flash base (in), status (out) * r1 - count (halfword-16bit) * r2 - workarea start * r3 - workarea end * r4 - target address * Clobbered: * r5 - rp * r6 - wp, tmp * r7 - tmp */ #define STM32_FLASH_SR_OFFSET 0x0c /* offset of SR register from flash reg base */ wait_fifo: ldr r6, [r2, #0] /* read wp */ cmp r6, #0 /* abort if wp == 0 */ beq exit ldr r5, [r2, #4] /* read rp */ cmp r5, r6 /* wait until rp != wp */ beq wait_fifo ldrh r6, [r5] /* "*target_address++ = *rp++" */ strh r6, [r4] adds r5, #2 adds r4, #2 busy: ldr r6, [r0, #STM32_FLASH_SR_OFFSET] /* wait until BSY flag is reset */ movs r7, #1 tst r6, r7 bne busy movs r7, #0x14 /* check the error bits */ tst r6, r7 bne error cmp r5, r3 /* wrap rp at end of buffer */ bcc no_wrap mov r5, r2 adds r5, #8 no_wrap: str r5, [r2, #4] /* store rp */ subs r1, r1, #1 /* decrement halfword count */ cmp r1, #0 beq exit /* loop if not done */ b wait_fifo error: movs r0, #0 str r0, [r2, #4] /* set rp = 0 on error */ exit: mov r0, r6 /* return status in r0 */ bkpt #0 openocd-0.9.0/contrib/loaders/flash/stm32f2x.S0000644000175000017500000000615612315575360016011 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2011 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m3 .thumb .thumb_func /* * Params : * r0 = workarea start, status (out) * r1 = workarea end * r2 = target address * r3 = count (16bit words) * r4 = flash base * * Clobbered: * r6 - temp * r7 - rp * r8 - wp, tmp */ #define STM32_FLASH_CR_OFFSET 0x10 /* offset of CR register in FLASH struct */ #define STM32_FLASH_SR_OFFSET 0x0c /* offset of SR register in FLASH struct */ wait_fifo: ldr r8, [r0, #0] /* read wp */ cmp r8, #0 /* abort if wp == 0 */ beq exit ldr r7, [r0, #4] /* read rp */ cmp r7, r8 /* wait until rp != wp */ beq wait_fifo ldr r6, STM32_PROG16 str r6, [r4, #STM32_FLASH_CR_OFFSET] ldrh r6, [r7], #0x02 /* read one half-word from src, increment ptr */ strh r6, [r2], #0x02 /* write one half-word from src, increment ptr */ busy: ldr r6, [r4, #STM32_FLASH_SR_OFFSET] tst r6, #0x10000 /* BSY (bit16) == 1 => operation in progress */ bne busy /* wait more... */ tst r6, #0xf0 /* PGSERR | PGPERR | PGAERR | WRPERR */ bne error /* fail... */ cmp r7, r1 /* wrap rp at end of buffer */ it cs addcs r7, r0, #8 /* skip loader args */ str r7, [r0, #4] /* store rp */ subs r3, r3, #1 /* decrement halfword count */ cbz r3, exit /* loop if not done */ b wait_fifo error: movs r1, #0 str r1, [r0, #4] /* set rp = 0 on error */ exit: mov r0, r6 /* return status in r0 */ bkpt #0x00 STM32_PROG16: .word 0x101 /* PG | PSIZE_16*/ openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_intel_16.s0000644000175000017500000000407312315575360020254 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* algorithm register usage: * r0: source address (in RAM) * r1: target address (in Flash) * r2: count * r3: flash write command * r4: status byte (returned to host) * r5: busy test pattern * r6: error test pattern */ loop: ldrh r4, [r0], #2 strh r3, [r1] strh r4, [r1] busy: ldrh r4, [r1] and r7, r4, r5 cmp r7, r5 bne busy tst r4, r6 bne done subs r2, r2, #1 beq done add r1, r1, #2 b loop done: b done .end openocd-0.9.0/contrib/loaders/flash/armv4_5_cfi_intel_32.s0000644000175000017500000000407312315575360020252 00000000000000/*************************************************************************** * Copyright (C) 2005, 2007 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2010 Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arm .arch armv4 .section .init /* algorithm register usage: * r0: source address (in RAM) * r1: target address (in Flash) * r2: count * r3: flash write command * r4: status byte (returned to host) * r5: busy test pattern * r6: error test pattern */ loop: ldr r4, [r0], #4 str r3, [r1] str r4, [r1] busy: ldr r4, [r1] and r7, r4, r5 cmp r7, r5 bne busy tst r4, r6 bne done subs r2, r2, #1 beq done add r1, r1, #4 b loop done: b done .end openocd-0.9.0/contrib/loaders/flash/at91sam7x/0000755000175000017500000000000012315575360016103 500000000000000openocd-0.9.0/contrib/loaders/flash/at91sam7x/samregs.h0000644000175000017500000001107412315575360017640 00000000000000/* * Copyright (C) 2005-2006 by egnite Software 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 EGNITE SOFTWARE GMBH 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 EGNITE * SOFTWARE GMBH 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/ */ #ifndef samregsH #define samregsH /* * Register definitions below copied from NutOS */ #define DBGU_BASE 0xFFFFF200 /*!< \brief DBGU base address. */ #define DBGU_CIDR_OFF 0x00000040 /*!< \brief DBGU chip ID register offset. */ #define DBGU_CIDR (DBGU_BASE + DBGU_CIDR_OFF) /*!< \brief DBGU chip ID register. */ #define MC_BASE 0xFFFFFF00 /*!< \brief Memory controller base. */ #define MC_FMR_OFF 0x00000060 /*!< \brief MC flash mode register offset. */ #define MC_FMR (MC_BASE + MC_FMR_OFF) /*!< \brief MC flash mode register address. */ #define MC_FRDY 0x00000001 /*!< \brief Flash ready. */ #define MC_LOCKE 0x00000004 /*!< \brief Lock error. */ #define MC_PROGE 0x00000008 /*!< \brief Programming error. */ #define MC_NEBP 0x00000080 /*!< \brief No erase before programming. */ #define MC_FWS_MASK 0x00000300 /*!< \brief Flash wait state mask. */ #define MC_FWS_1R2W 0x00000000 /*!< \brief 1 cycle for read, 2 for write operations. */ #define MC_FWS_2R3W 0x00000100 /*!< \brief 2 cycles for read, 3 for write operations. */ #define MC_FWS_3R4W 0x00000200 /*!< \brief 3 cycles for read, 4 for write operations. */ #define MC_FWS_4R4W 0x00000300 /*!< \brief 4 cycles for read and write operations. */ #define MC_FMCN_MASK 0x00FF0000 /*!< \brief Flash microsecond cycle number mask. */ #define MC_FCR_OFF 0x00000064 /*!< \brief MC flash command register offset. */ #define MC_FCR (MC_BASE + MC_FCR_OFF) /*!< \brief MC flash command register address. */ #define MC_FCMD_MASK 0x0000000F /*!< \brief Flash command mask. */ #define MC_FCMD_NOP 0x00000000 /*!< \brief No command. */ #define MC_FCMD_WP 0x00000001 /*!< \brief Write page. */ #define MC_FCMD_SLB 0x00000002 /*!< \brief Set lock bit. */ #define MC_FCMD_WPL 0x00000003 /*!< \brief Write page and lock. */ #define MC_FCMD_CLB 0x00000004 /*!< \brief Clear lock bit. */ #define MC_FCMD_EA 0x00000008 /*!< \brief Erase all. */ #define MC_FCMD_SGPB 0x0000000B /*!< \brief Set general purpose NVM bit. */ #define MC_FCMD_CGPB 0x0000000D /*!< \brief Clear general purpose NVM bit. */ #define MC_FCMD_SSB 0x0000000F /*!< \brief Set security bit. */ #define MC_PAGEN_MASK 0x0003FF00 /*!< \brief Page number mask. */ #define MC_KEY 0x5A000000 /*!< \brief Writing protect key. */ #define MC_FSR_OFF 0x00000068 /*!< \brief MC flash status register offset. */ #define MC_FSR (MC_BASE + MC_FSR_OFF) /*!< \brief MC flash status register address. */ #define MC_SECURITY 0x00000010 /*!< \brief Security bit status. */ #endif openocd-0.9.0/contrib/loaders/flash/at91sam7x/dcc.c0000644000175000017500000000413712315575360016725 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "dcc.h" /* debug channel read (debugger->MCU) */ uint32 dcc_rd(void) { volatile uint32 dcc_reg; do { asm volatile ("mrc p14, 0, %0, C0, C0" : "=r" (dcc_reg) :); } while ((dcc_reg&1) == 0); asm volatile ("mrc p14, 0, %0, C1, C0" : "=r" (dcc_reg) :); return dcc_reg; } /* debug channel write (MCU->debugger) */ int dcc_wr(uint32 data) { volatile uint32 dcc_reg; do { asm volatile ("mrc p14, 0, %0, C0, C0" : "=r" (dcc_reg) :); /* operation controled by master, cancel operation upon reception of data for immediate response */ if (dcc_reg&1) return -1; } while (dcc_reg&2); asm volatile ("mcr p14, 0, %0, C1, C0" : : "r" (data)); return 0; } openocd-0.9.0/contrib/loaders/flash/at91sam7x/dcc.h0000644000175000017500000000316412315575360016731 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef dccH #define dccH #include "platform.h" /* debug channel read (debugger->MCU) */ uint32 dcc_rd(void); /* debug channel write (MCU->debugger) */ int dcc_wr(uint32 data); #endif openocd-0.9.0/contrib/loaders/flash/at91sam7x/crt.s0000644000175000017500000001533612315575360017007 00000000000000/**************************************************************************** * Copyright (c) 2006 by Michael Fischer. 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 author 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 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. * **************************************************************************** * * History: * * 18.12.06 mifi First Version * The hardware initialization is based on the startup file * crtat91sam7x256_rom.S from NutOS 4.2.1. * Therefore partial copyright by egnite Software GmbH. ****************************************************************************/ /* * Some defines for the program status registers */ ARM_MODE_USER = 0x10 /* Normal User Mode */ ARM_MODE_FIQ = 0x11 /* FIQ Fast Interrupts Mode */ ARM_MODE_IRQ = 0x12 /* IRQ Standard Interrupts Mode */ ARM_MODE_SVC = 0x13 /* Supervisor Interrupts Mode */ ARM_MODE_ABORT = 0x17 /* Abort Processing memory Faults Mode */ ARM_MODE_UNDEF = 0x1B /* Undefined Instructions Mode */ ARM_MODE_SYS = 0x1F /* System Running in Priviledged Operating Mode */ ARM_MODE_MASK = 0x1F I_BIT = 0x80 /* disable IRQ when I bit is set */ F_BIT = 0x40 /* disable IRQ when I bit is set */ /* * Register Base Address */ AIC_BASE = 0xFFFFF000 AIC_EOICR_OFF = 0x130 AIC_IDCR_OFF = 0x124 RSTC_MR = 0xFFFFFD08 RSTC_KEY = 0xA5000000 RSTC_URSTEN = 0x00000001 WDT_BASE = 0xFFFFFD40 WDT_MR_OFF = 0x00000004 WDT_WDDIS = 0x00008000 MC_BASE = 0xFFFFFF00 MC_FMR_OFF = 0x00000060 MC_FWS_1FWS = 0x00480100 .section .vectors,"ax" .code 32 /****************************************************************************/ /* Vector table and reset entry */ /****************************************************************************/ _vectors: ldr pc, ResetAddr /* Reset */ ldr pc, UndefAddr /* Undefined instruction */ ldr pc, SWIAddr /* Software interrupt */ ldr pc, PAbortAddr /* Prefetch abort */ ldr pc, DAbortAddr /* Data abort */ ldr pc, ReservedAddr /* Reserved */ ldr pc, IRQAddr /* IRQ interrupt */ ldr pc, FIQAddr /* FIQ interrupt */ ResetAddr: .word ResetHandler UndefAddr: .word UndefHandler SWIAddr: .word SWIHandler PAbortAddr: .word PAbortHandler DAbortAddr: .word DAbortHandler ReservedAddr: .word 0 IRQAddr: .word IRQHandler FIQAddr: .word FIQHandler .ltorg .section .init, "ax" .code 32 .global ResetHandler .global ExitFunction .extern main /****************************************************************************/ /* Reset handler */ /****************************************************************************/ ResetHandler: /* * The watchdog is enabled after processor reset. Disable it. */ ldr r1, =WDT_BASE ldr r0, =WDT_WDDIS str r0, [r1, #WDT_MR_OFF] /* * Enable user reset: assertion length programmed to 1ms */ ldr r0, =(RSTC_KEY | RSTC_URSTEN | (4 << 8)) ldr r1, =RSTC_MR str r0, [r1, #0] /* * Use 2 cycles for flash access. */ ldr r1, =MC_BASE ldr r0, =MC_FWS_1FWS str r0, [r1, #MC_FMR_OFF] /* * Disable all interrupts. Useful for debugging w/o target reset. */ ldr r1, =AIC_BASE mvn r0, #0 str r0, [r1, #AIC_EOICR_OFF] str r0, [r1, #AIC_IDCR_OFF] /* * Setup a stack for each mode */ msr CPSR_c, #ARM_MODE_UNDEF | I_BIT | F_BIT /* Undefined Instruction Mode */ ldr sp, =__stack_und_end msr CPSR_c, #ARM_MODE_ABORT | I_BIT | F_BIT /* Abort Mode */ ldr sp, =__stack_abt_end msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT /* FIQ Mode */ ldr sp, =__stack_fiq_end msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* IRQ Mode */ ldr sp, =__stack_irq_end msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT /* Supervisor Mode */ ldr sp, =__stack_svc_end /* * Clear .bss section */ ldr r1, =__bss_start ldr r2, =__bss_end ldr r3, =0 bss_clear_loop: cmp r1, r2 strne r3, [r1], #+4 bne bss_clear_loop /* * Jump to main */ mrs r0, cpsr bic r0, r0, #I_BIT | F_BIT /* Enable FIQ and IRQ interrupt */ msr cpsr, r0 mov r0, #0 /* No arguments */ mov r1, #0 /* No arguments */ ldr r2, =main mov lr, pc bx r2 /* And jump... */ ExitFunction: nop nop nop b ExitFunction /****************************************************************************/ /* Default interrupt handler */ /****************************************************************************/ UndefHandler: b UndefHandler SWIHandler: b SWIHandler PAbortHandler: b PAbortHandler DAbortHandler: b DAbortHandler IRQHandler: b IRQHandler FIQHandler: b FIQHandler .weak ExitFunction .weak UndefHandler, PAbortHandler, DAbortHandler .weak IRQHandler, FIQHandler .ltorg /*** EOF ***/ openocd-0.9.0/contrib/loaders/flash/at91sam7x/ocl.h0000644000175000017500000000356612315575360016763 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef OCL_H #define OCL_H /* command/response mask */ #define OCL_CMD_MASK 0xFFFF0000L /* commads */ #define OCL_FLASH_BLOCK 0x0CFB0000L #define OCL_ERASE_BLOCK 0x0CEB0000L #define OCL_ERASE_ALL 0x0CEA0000L #define OCL_PROBE 0x0CBE0000L /* responses */ #define OCL_CMD_DONE 0x0ACD0000L #define OCL_CMD_ERR 0x0ACE0000L #define OCL_CHKS_FAIL 0x0ACF0000L #define OCL_BUFF_OVER 0x0AB00000L #define OCL_CHKS_INIT 0xC100CD0CL #endif /* OCL_H */ openocd-0.9.0/contrib/loaders/flash/at91sam7x/at91sam7x_ocl_flash.script0000644000175000017500000000012412315575360023016 00000000000000soft_reset_halt load_image at91sam7x_ocl.bin 0x200000 resume 0x200000 flash probe 0 openocd-0.9.0/contrib/loaders/flash/at91sam7x/platform.h0000644000175000017500000000412512315575360020022 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef platformH #define platformH #include "samregs.h" #define outb(_reg, _val) (*((volatile unsigned char *)(_reg)) = (_val)) #define outw(_reg, _val) (*((volatile unsigned short *)(_reg)) = (_val)) #define outr(_reg, _val) (*((volatile unsigned int *)(_reg)) = (_val)) #define inb(_reg) (*((volatile unsigned char *)(_reg))) #define inw(_reg) (*((volatile unsigned short *)(_reg))) #define inr(_reg) (*((volatile unsigned int *)(_reg))) #define _BV(bit) (1 << (bit)) typedef signed char int8; typedef unsigned char uint8; typedef signed short int16; typedef unsigned short uint16; typedef signed int int32; typedef unsigned int uint32; #endif openocd-0.9.0/contrib/loaders/flash/at91sam7x/makefile0000644000175000017500000000546112315575360017531 00000000000000############################################################################################## # Start of default section # TRGT = arm-elf- CC = $(TRGT)gcc CP = $(TRGT)objcopy AS = $(TRGT)gcc -x assembler-with-cpp HEX = $(CP) -O ihex BIN = $(CP) -O binary OBJDUMP = $(TRGT)objdump MCU = arm7tdmi # List all default C defines here, like -D_DEBUG=1 DDEFS = # List all default ASM defines here, like -D_DEBUG=1 DADEFS = # List all default directories to look for include files here DINCDIR = # List the default directory to look for the libraries here DLIBDIR = # List all default libraries here DLIBS = # # End of default section ############################################################################################## ############################################################################################## # Start of user section # # Define project name here PROJECT = at91sam7x_ocl # Define linker script file here LDSCRIPT= at91sam7x_ram.ld # List all user C define here, like -D_DEBUG=1 UDEFS = # Define ASM defines here UADEFS = # List C source files here SRC = main.c dcc.c samflash.c # List ASM source files here ASRC = crt.s # List all user directories here UINCDIR = # List the user directory to look for the libraries here ULIBDIR = # List all user libraries here ULIBS = # Define optimisation level here OPT = -O2 # # End of user defines ############################################################################################## INCDIR = $(patsubst %,-I%,$(DINCDIR) $(UINCDIR)) LIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR)) DEFS = $(DDEFS) $(UDEFS) ADEFS = $(DADEFS) $(UADEFS) OBJS = $(ASRC:.s=.o) $(SRC:.c=.o) LIBS = $(DLIBS) $(ULIBS) MCFLAGS = -mcpu=$(MCU) ASFLAGS = $(MCFLAGS) -g -gdwarf-2 -Wa,-amhls=$(<:.s=.lst) $(ADEFS) CPFLAGS = $(MCFLAGS) $(OPT) -gdwarf-2 -mthumb-interwork -fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm -Wa,-ahlms=$(<:.c=.lst) $(DEFS) LDFLAGS = $(MCFLAGS) -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch $(LIBDIR) # Generate dependency information #CPFLAGS += -MD -MP -MF .dep/$(@F).d # # makefile rules # all: $(OBJS) $(PROJECT).elf $(PROJECT).hex $(PROJECT).bin $(PROJECT).lst %o : %c $(CC) -c $(CPFLAGS) -I . $(INCDIR) $< -o $@ %o : %s $(AS) -c $(ASFLAGS) $< -o $@ %elf: $(OBJS) $(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $@ %hex: %elf $(HEX) $< $@ %bin: %elf $(BIN) $< $@ %.lst: %.elf $(OBJDUMP) -h -S $< > $@ clean: -rm -f $(OBJS) -rm -f $(PROJECT).elf -rm -f $(PROJECT).map -rm -f $(PROJECT).hex -rm -f $(PROJECT).bin -rm -f $(PROJECT).lst -rm -f $(SRC:.c=.c.bak) -rm -f $(SRC:.c=.lst) -rm -f $(ASRC:.s=.s.bak) -rm -f $(ASRC:.s=.lst) -rm -fR .dep # # Include the dependency files, should be the last of the makefile # #-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) # *** EOF ***openocd-0.9.0/contrib/loaders/flash/at91sam7x/main.c0000644000175000017500000000645712315575360017127 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "platform.h" #include #include "dcc.h" #include "samflash.h" #define BUFSIZE 1024 /* words, i.e. 4 KiB */ uint32 buffer[1024]; void cmd_flash(uint32 cmd) { unsigned int len; uint32 adr; uint32 chksum; unsigned int bi; /* buffer index */ unsigned int bi_start; /* receive start mark */ unsigned int bi_end; /* receive end mark */ unsigned int ofs; int pagenum; int result; adr = dcc_rd(); len = cmd&0xffff; ofs = adr%flash_page_size; bi_start = ofs/4; bi_end = (ofs + len + 3)/4; if (bi_end > BUFSIZE) { dcc_wr(OCL_BUFF_OVER); return; } chksum = OCL_CHKS_INIT; for (bi = 0; bi < bi_end; bi++) chksum^=buffer[bi]=dcc_rd(); if (dcc_rd() != chksum) { dcc_wr(OCL_CHKS_FAIL); return; } /* fill in unused positions with unprogrammed values */ for (bi = 0; bi < bi_start; bi++) buffer[bi]=0xffffffff; for (bi = bi_end; bi%flash_page_size; bi++) buffer[bi]=0xffffffff; result = 0; pagenum = adr/flash_page_size; for (bi = 0; bi < bi_end; bi += flash_page_size/4) { result = flash_page_program(buffer + bi, pagenum++); if (result) break; } /* verify written data */ if (!result) result = flash_verify(adr, len, ((uint8 *)buffer) + ofs); dcc_wr(OCL_CMD_DONE | result); } int main (void) { uint32 cmd; for (;;) { cmd = dcc_rd(); switch (cmd&OCL_CMD_MASK) { case OCL_PROBE: dcc_wr(OCL_CMD_DONE | flash_init()); dcc_wr(0x100000); /* base */ dcc_wr(flash_page_count*flash_page_size); /* size */ dcc_wr(1); /* num_sectors */ dcc_wr(4096 | ((unsigned long) flash_page_size << 16)); /* buflen and bufalign */ break; case OCL_ERASE_ALL: dcc_wr(OCL_CMD_DONE | flash_erase_all()); break; case OCL_FLASH_BLOCK: cmd_flash(cmd); break; default: /* unknown command */ dcc_wr(OCL_CMD_ERR); break; } } return(0); /* we shall never get here, just to supress compiler warning */ } openocd-0.9.0/contrib/loaders/flash/at91sam7x/at91sam7x_ram.ld0000644000175000017500000000652612315575360020752 00000000000000/**************************************************************************** * Copyright (c) 2006 by Michael Fischer. 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 author 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 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. * **************************************************************************** * * History: * * 30.03.06 mifi First Version ****************************************************************************/ ENTRY(ResetHandler) SEARCH_DIR(.) /* * Define stack size here */ FIQ_STACK_SIZE = 0x0100; IRQ_STACK_SIZE = 0x0100; ABT_STACK_SIZE = 0x0100; UND_STACK_SIZE = 0x0100; SVC_STACK_SIZE = 0x0100; MEMORY { ram : org = 0x00200000, len = 64k } /* * Do not change the next code */ SECTIONS { .text : { *(.vectors); . = ALIGN(4); *(.init); . = ALIGN(4); *(.text); . = ALIGN(4); *(.rodata); . = ALIGN(4); *(.rodata*); . = ALIGN(4); *(.glue_7t); . = ALIGN(4); *(.glue_7); . = ALIGN(4); etext = .; } > ram .data : { PROVIDE (__data_start = .); *(.data) . = ALIGN(4); edata = .; _edata = .; PROVIDE (__data_end = .); } > ram .bss : { PROVIDE (__bss_start = .); *(.bss) *(COMMON) . = ALIGN(4); PROVIDE (__bss_end = .); . = ALIGN(256); PROVIDE (__stack_start = .); PROVIDE (__stack_fiq_start = .); . += FIQ_STACK_SIZE; . = ALIGN(4); PROVIDE (__stack_fiq_end = .); PROVIDE (__stack_irq_start = .); . += IRQ_STACK_SIZE; . = ALIGN(4); PROVIDE (__stack_irq_end = .); PROVIDE (__stack_abt_start = .); . += ABT_STACK_SIZE; . = ALIGN(4); PROVIDE (__stack_abt_end = .); PROVIDE (__stack_und_start = .); . += UND_STACK_SIZE; . = ALIGN(4); PROVIDE (__stack_und_end = .); PROVIDE (__stack_svc_start = .); . += SVC_STACK_SIZE; . = ALIGN(4); PROVIDE (__stack_svc_end = .); PROVIDE (__stack_end = .); PROVIDE (__heap_start = .); } > ram } /*** EOF ***/ openocd-0.9.0/contrib/loaders/flash/at91sam7x/samflash.c0000644000175000017500000001262212315575360017770 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "samflash.h" unsigned int flash_page_count = 1024; unsigned int flash_page_size = 256; /* pages per lock bit */ unsigned int flash_lock_pages = 1024/16; /* detect chip and set loader parameters */ int flash_init(void) { unsigned int nvpsiz; nvpsiz = (inr(DBGU_CIDR) >> 8)&0xf; switch (nvpsiz) { case 3: /* AT91SAM7x32 */ flash_page_count = 256; flash_page_size = 128; flash_lock_pages = 256/8; break; case 5: /* AT91SAM7x64 */ flash_page_count = 512; flash_page_size = 128; flash_lock_pages = 512/16; break; case 7: /* AT91SAM7x128*/ flash_page_count = 512; flash_page_size = 256; flash_lock_pages = 512/8; break; case 9: /* AT91SAM7x256 */ flash_page_count = 1024; flash_page_size = 256; flash_lock_pages = 1024/16; break; case 10: /* AT91SAM7x512 */ flash_page_count = 2048; flash_page_size = 256; flash_lock_pages = 2048/32; break; default: return FLASH_STAT_INITE; } return FLASH_STAT_OK; } /* program single flash page */ int flash_page_program(uint32 *data, int page_num) { int i; int efc_ofs; uint32 *flash_ptr; uint32 *data_ptr; /* select proper controller */ if (page_num >= 1024) efc_ofs = 0x10; else efc_ofs = 0; /* wait until FLASH is ready, just for sure */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); /* calculate page address, only lower 8 bits are used to address the latch, but the upper part of address is needed for writing to proper EFC */ flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size)); data_ptr = data; /* copy data to latch */ for (i = flash_page_size/4; i; i--) { /* we do not use memcpy to be sure that only 32 bit access is used */ *(flash_ptr++)=*(data_ptr++); } /* page number and page write command to FCR */ outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | MC_KEY | MC_FCMD_WP); /* wait until it's done */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); /* check for errors */ if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE; if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE; #if 0 /* verify written data */ flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size)); data_ptr = data; for (i = flash_page_size/4; i; i--) { if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE; } #endif return FLASH_STAT_OK; } int flash_erase_plane(int efc_ofs) { unsigned int lockbits; int page_num; page_num = 0; lockbits = inr(MC_FSR + efc_ofs) >> 16; while (lockbits) { if (lockbits&1) { /* wait until FLASH is ready, just for sure */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | 0x5a000004); /* wait until it's done */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); /* check for errors */ if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE; if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE; } if ((page_num += flash_lock_pages) > flash_page_count) break; lockbits>>=1; } /* wait until FLASH is ready, just for sure */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); /* erase all command to FCR */ outr(MC_FCR + efc_ofs, 0x5a000008); /* wait until it's done */ while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0); /* check for errors */ if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE; if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE; /* set no erase before programming */ outr(MC_FMR + efc_ofs, inr(MC_FMR + efc_ofs) | 0x80); return FLASH_STAT_OK; } /* erase whole chip */ int flash_erase_all(void) { int result; if ((result = flash_erase_plane(0)) != FLASH_STAT_OK) return result; /* the second flash controller, if any */ if (flash_page_count > 1024) result = flash_erase_plane(0x10); return result; } int flash_verify(uint32 adr, unsigned int len, uint8 *src) { unsigned char *flash_ptr; flash_ptr = (uint8 *)FLASH_AREA_ADDR + adr; for (;len; len--) { if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE; } return FLASH_STAT_OK; } openocd-0.9.0/contrib/loaders/flash/at91sam7x/samflash.h0000644000175000017500000000403512315575360017774 00000000000000/*************************************************************************** * Copyright (C) 2007 by Pavel Chromy * * chromy@asix.cz * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef samflashH #define samflashH #include "platform.h" #define FLASH_AREA_ADDR 0x100000 #define FLASH_STAT_OK 0 #define FLASH_STAT_PROGE 1 #define FLASH_STAT_LOCKE 2 #define FLASH_STAT_VERIFE 3 #define FLASH_STAT_INITE 4 extern unsigned int flash_page_count; extern unsigned int flash_page_size; /* words */ /* detect chip and set loader parameters */ int flash_init(void); /* program single flash page */ int flash_page_program(uint32 *data, int page_num); /* erase whole chip */ int flash_erase_all(void); /* verify written data */ int flash_verify(uint32 adr, unsigned int len, uint8 *src); #endif openocd-0.9.0/contrib/loaders/flash/pic32mx.s0000644000175000017500000000710712315575360015743 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .arch m4k .set noreorder .set noat /* params: * $a0 src adr - ram + result * $a1 dest adr - flash * $a2 count (32bit words) * vars * * temps: * $t0, $t1, $t2, $t3, $t4, $t5 * $s0, $s1, $s3, $s4, $s5 */ .type main, @function .global main .ent main main: /* setup constants */ lui $t0, 0xaa99 ori $t0, 0x6655 /* NVMKEY1 */ lui $t1, 0x5566 ori $t1, 0x99AA /* NVMKEY2 */ lui $t2, 0xBF80 ori $t2, 0xF400 /* NVMCON */ ori $t3, $zero, 0x4003 /* NVMCON row write cmd */ ori $t4, $zero, 0x8000 /* NVMCON start cmd */ write_row: /* can we perform a row write: 128 32bit words */ sltiu $s3, $a2, 128 bne $s3, $zero, write_word ori $t5, $zero, 0x4000 /* NVMCON clear cmd */ /* perform row write 512 bytes */ sw $a1, 32($t2) /* set NVMADDR with dest addr - real addr */ sw $a0, 64($t2) /* set NVMSRCADDR with src addr - real addr */ bal progflash addiu $a0, $a0, 512 addiu $a1, $a1, 512 beq $zero, $zero, write_row addiu $a2, $a2, -128 write_word: /* write 32bit words */ lui $s5, 0xa000 ori $s5, 0x0000 or $a0, $a0, $s5 /* convert to virtual addr */ beq $zero, $zero, next_word ori $t3, $zero, 0x4001 /* NVMCON word write cmd */ prog_word: lw $s4, 0($a0) /* load data - from virtual addr */ sw $s4, 48($t2) /* set NVMDATA with data */ sw $a1, 32($t2) /* set NVMADDR with dest addr - real addr */ bal progflash addiu $a0, $a0, 4 addiu $a1, $a1, 4 addiu $a2, $a2, -1 next_word: bne $a2, $zero, prog_word nop done: beq $zero, $zero, exit addiu $a0, $zero, 0 error: /* save result to $a0 */ addiu $a0, $s1, 0 exit: sdbbp .end main .type progflash, @function .global progflash .ent progflash progflash: sw $t3, 0($t2) /* set NVMWREN */ sw $t0, 16($t2) /* write NVMKEY1 */ sw $t1, 16($t2) /* write NVMKEY2 */ sw $t4, 8($t2) /* start operation */ waitflash: lw $s0, 0($t2) and $s0, $s0, $t4 bne $s0, $zero, waitflash nop /* following is to comply with errata #34 * 500ns delay required */ nop nop nop nop /* check for errors */ lw $s1, 0($t2) andi $s1, $zero, 0x3000 bne $s1, $zero, error sw $t5, 4($t2) /* clear NVMWREN */ jr $ra nop .end progflash openocd-0.9.0/contrib/loaders/flash/lpcspifi_write.S0000644000175000017500000001676712516456301017451 00000000000000/*************************************************************************** * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .cpu cortex-m3 .thumb .thumb_func /* * Params : * r0 = workarea start, status (out) * r1 = workarea end * r2 = target address (offset from flash base) * r3 = count (bytes) * r4 = page size * Clobbered: * r7 - rp * r8 - wp, tmp * r9 - send/receive data * r10 - temp * r11 - current page end address */ /* * This code is embedded within: src/flash/nor/lpcspifi.c as a "C" array. * * To rebuild: * arm-none-eabi-gcc -c lpcspifi_write.S * arm-none-eabi-objcopy -O binary lpcspifi_write.o lpcspifi_write.bin * xxd -c 8 -i lpcspifi_write.bin > lpcspifi_write.txt * * Then read and edit this result into the "C" source. */ #define SSP_BASE_HIGH 0x4008 #define SSP_BASE_LOW 0x3000 #define SSP_CR0_OFFSET 0x00 #define SSP_CR1_OFFSET 0x04 #define SSP_DATA_OFFSET 0x08 #define SSP_CPSR_OFFSET 0x10 #define SSP_SR_OFFSET 0x0c #define SSP_CLOCK_BASE_HIGH 0x4005 #define SSP_CLOCK_BASE_LOW 0x0000 #define SSP_BRANCH_CLOCK_BASE_HIGH 0x4005 #define SSP_BRANCH_CLOCK_BASE_LOW 0x2000 #define SSP_BASE_CLOCK_OFFSET 0x94 #define SSP_BRANCH_CLOCK_OFFSET 0x700 #define IOCONFIG_BASE_HIGH 0x4008 #define IOCONFIG_BASE_LOW 0x6000 #define IOCONFIG_SCK_OFFSET 0x18c #define IOCONFIG_HOLD_OFFSET 0x190 #define IOCONFIG_WP_OFFSET 0x194 #define IOCONFIG_MISO_OFFSET 0x198 #define IOCONFIG_MOSI_OFFSET 0x19c #define IOCONFIG_CS_OFFSET 0x1a0 #define IO_BASE_HIGH 0x400f #define IO_BASE_LOW 0x4000 #define IO_CS_OFFSET 0xab #define IODIR_BASE_HIGH 0x400f #define IODIR_BASE_LOW 0x6000 #define IO_CS_DIR_OFFSET 0x14 setup: /* Initialize SSP pins and module */ mov.w r10, #IOCONFIG_BASE_LOW movt r10, #IOCONFIG_BASE_HIGH mov.w r8, #0xea str.w r8, [r10, #IOCONFIG_SCK_OFFSET] /* Configure SCK pin function */ mov.w r8, #0x40 str.w r8, [r10, #IOCONFIG_HOLD_OFFSET] /* Configure /HOLD pin function */ mov.w r8, #0x40 str.w r8, [r10, #IOCONFIG_WP_OFFSET] /* Configure /WP pin function */ mov.w r8, #0xed str.w r8, [r10, #IOCONFIG_MISO_OFFSET] /* Configure MISO pin function */ mov.w r8, #0xed str.w r8, [r10, #IOCONFIG_MOSI_OFFSET] /* Configure MOSI pin function */ mov.w r8, #0x44 str.w r8, [r10, #IOCONFIG_CS_OFFSET] /* Configure CS pin function */ mov.w r10, #IODIR_BASE_LOW movt r10, #IODIR_BASE_HIGH mov.w r8, #0x800 str r8, [r10, #IO_CS_DIR_OFFSET] /* Set CS as output */ mov.w r10, #IO_BASE_LOW movt r10, #IO_BASE_HIGH mov.w r8, #0xff str.w r8, [r10, #IO_CS_OFFSET] /* Set CS high */ mov.w r10, #SSP_CLOCK_BASE_LOW movt r10, #SSP_CLOCK_BASE_HIGH mov.w r8, #0x0000 movt r8, #0x0100 str.w r8, [r10, #SSP_BASE_CLOCK_OFFSET] /* Configure SSP0 base clock (use 12 MHz IRC) */ mov.w r10, #SSP_BRANCH_CLOCK_BASE_LOW movt r10, #SSP_BRANCH_CLOCK_BASE_HIGH mov.w r8, #0x01 str.w r8, [r10, #SSP_BRANCH_CLOCK_OFFSET] /* Configure (enable) SSP0 branch clock */ mov.w r10, #SSP_BASE_LOW movt r10, #SSP_BASE_HIGH mov.w r8, #0x07 str.w r8, [r10, #SSP_CR0_OFFSET] /* Set clock postscale */ mov.w r8, #0x02 str.w r8, [r10, #SSP_CPSR_OFFSET] /* Set clock prescale */ str.w r8, [r10, #SSP_CR1_OFFSET] /* Enable SSP in SPI mode */ mov.w r11, #0x00 find_next_page_boundary: add r11, r4 /* Increment to the next page */ cmp r11, r2 /* If we have not reached the next page boundary after the target address, keep going */ bls find_next_page_boundary write_enable: bl cs_down mov.w r9, #0x06 /* Send the write enable command */ bl write_data bl cs_up bl cs_down mov.w r9, #0x05 /* Get status register */ bl write_data mov.w r9, #0x00 /* Dummy data to clock in status */ bl write_data bl cs_up tst r9, #0x02 /* If the WE bit isn't set, we have a problem. */ beq error page_program: bl cs_down mov.w r9, #0x02 /* Send the page program command */ bl write_data write_address: lsr r9, r2, #16 /* Send the current 24-bit write address, MSB first */ bl write_data lsr r9, r2, #8 bl write_data mov.w r9, r2 bl write_data wait_fifo: ldr r8, [r0] /* read the write pointer */ cmp r8, #0 /* if it's zero, we're gonzo */ beq exit ldr r7, [r0, #4] /* read the read pointer */ cmp r7, r8 /* wait until they are not equal */ beq wait_fifo write: ldrb r9, [r7], #0x01 /* Load one byte from the FIFO, increment the read pointer by 1 */ bl write_data /* send the byte to the flash chip */ cmp r7, r1 /* wrap the read pointer if it is at the end */ it cs addcs r7, r0, #8 /* skip loader args */ str r7, [r0, #4] /* store the new read pointer */ subs r3, r3, #1 /* decrement count */ cbz r3, exit /* Exit if we have written everything */ add r2, #1 /* Increment flash address by 1 */ cmp r11, r2 /* See if we have reached the end of a page */ bne wait_fifo /* If not, keep writing bytes */ bl cs_up /* Otherwise, end the command and keep going w/ the next page */ add r11, r4 /* Move up the end-of-page address by the page size*/ wait_flash_busy: /* Wait for the flash to finish the previous page write */ bl cs_down mov.w r9, #0x05 /* Get status register */ bl write_data mov.w r9, #0x00 /* Dummy data to clock in status */ bl write_data bl cs_up tst r9, #0x01 /* If it isn't done, keep waiting */ bne wait_flash_busy b write_enable /* If it is done, start a new page write */ write_data: /* Send/receive 1 byte of data over SSP */ mov.w r10, #SSP_BASE_LOW movt r10, #SSP_BASE_HIGH str.w r9, [r10, #SSP_DATA_OFFSET] /* Write supplied data to the SSP data reg */ wait_transmit: ldr r9, [r10, #SSP_SR_OFFSET] /* Check SSP status */ tst r9, #0x0010 /* Check if BSY bit is set */ bne wait_transmit /* If still transmitting, keep waiting */ ldr r9, [r10, #SSP_DATA_OFFSET] /* Load received data */ bx lr /* Exit subroutine */ cs_up: mov.w r8, #0xff b cs_write cs_down: mov.w r8, #0x0000 cs_write: mov.w r10, #IO_BASE_LOW movt r10, #IO_BASE_HIGH str.w r8, [r10, #IO_CS_OFFSET] bx lr error: movs r0, #0 str r0, [r2, #4] /* set rp = 0 on error */ exit: bl cs_up /* end the command before returning */ mov r0, r6 bkpt #0x00 .end openocd-0.9.0/contrib/loaders/flash/armv7m_io.s0000644000175000017500000000361012315575360016351 00000000000000/*************************************************************************** * Copyright (C) 2013 by Henrik Nilsson * * henrik.nilsson@bytequest.se * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .text .syntax unified .arch armv7-m .thumb .thumb_func .align 4 /* Inputs: * r0 buffer address * r1 NAND data address (byte wide) * r2 buffer length */ read: ldrb r3, [r1] strb r3, [r0], #1 subs r2, r2, #1 bne read done_read: bkpt #0 .align 4 /* Inputs: * r0 NAND data address (byte wide) * r1 buffer address * r2 buffer length */ write: ldrb r3, [r1], #1 strb r3, [r0] subs r2, r2, #1 bne write done_write: bkpt #0 .end openocd-0.9.0/contrib/loaders/README0000644000175000017500000000164312315575360014054 00000000000000Included in these directories are the src to the various ram loaders used within openocd. ** target checksum loaders ** checksum/armv4_5_crc.s : - ARMv4 and ARMv5 checksum loader : see target/arm_crc_code.c:arm_crc_code checksum/armv7m_crc.s : - ARMv7m checksum loader : see target/armv7m.c:cortex_m_crc_code checksum/mips32.s : - MIPS32 checksum loader : see target/mips32.c:mips_crc_code ** target flash loaders ** flash/pic32mx.s : - Microchip PIC32 flash loader : see flash/nor/pic32mx.c:pic32mx_flash_write_code flash/stellaris.s : - TI Stellaris flash loader : see flash/nor/stellaris.c:stellaris_write_code flash/stm32x.s : - ST STM32 flash loader : see flash/nor/stm32x.c:stm32x_flash_write_code flash/str7x.s : - ST STR7 flash loader : see flash/nor/str7x.c:str7x_flash_write_code flash/str9x.s : - ST STR9 flash loader : see flash/nor/str9x.c:str9x_flash_write_code Spencer Oliver spen@spen-soft.co.uk openocd-0.9.0/contrib/loaders/checksum/0000755000175000017500000000000012315575360015052 500000000000000openocd-0.9.0/contrib/loaders/checksum/armv4_5_crc.s0000644000175000017500000000357712315575360017276 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* r0 - address in - crc out r1 - char count */ .text .arm _start: main: mov r2, r0 mov r0, #0xffffffff /* crc */ mov r3, r1 mov r4, #0 b ncomp nbyte: ldrb r1, [r2, r4] ldr r7, CRC32XOR eor r0, r0, r1, asl #24 mov r5, #0 loop: cmp r0, #0 mov r6, r0, asl #1 add r5, r5, #1 mov r0, r6 eorlt r0, r6, r7 cmp r5, #8 bne loop add r4, r4, #1 ncomp: cmp r4, r3 bne nbyte end: bkpt #0 CRC32XOR: .word 0x04c11db7 .end openocd-0.9.0/contrib/loaders/checksum/armv7m_crc.s0000644000175000017500000000376312315575360017227 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* parameters: r0 - address in - crc out r1 - char count */ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func .align 2 _start: main: mov r2, r0 movs r0, #0 mvns r0, r0 ldr r6, CRC32XOR mov r3, r1 movs r4, #0 b ncomp nbyte: ldrb r1, [r2, r4] lsls r1, r1, #24 eors r0, r0, r1 movs r5, #0 loop: cmp r0, #0 bge notset lsls r0, r0, #1 eors r0, r0, r6 b cont notset: lsls r0, r0, #1 cont: adds r5, r5, #1 cmp r5, #8 bne loop adds r4, r4, #1 ncomp: cmp r4, r3 bne nbyte bkpt #0 .align 2 CRC32XOR: .word 0x04c11db7 .end openocd-0.9.0/contrib/loaders/checksum/mips32.s0000644000175000017500000000451012315575360016273 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ .global main .text .set noreorder /* params: * $a0 address in * $a1 byte count * vars * $a0 crc * $a1 crc data byte * temps: * t3 v0 a3 a2 t0 v1 */ .ent main main: addiu $t4, $a0, 0 /* address in */ addiu $t2, $a1, 0 /* count */ addiu $a0, $zero, 0xffffffff /* a0 crc - result */ beq $zero, $zero, ncomp addiu $t3, $zero, 0 /* clear bytes read */ nbyte: lb $a1, ($t4) /* load byte from source address */ addi $t4, $t4, 1 /* inc byte count */ crc: sll $a1, $a1, 24 lui $v0, 0x04c1 xor $a0, $a0, $a1 ori $a3, $v0, 0x1db7 addu $a2, $zero, $zero /* clear bit count */ loop: sll $t0, $a0, 1 addiu $a2, $a2, 1 /* inc bit count */ slti $a0, $a0, 0 xor $t1, $t0, $a3 movn $t0, $t1, $a0 slti $v1, $a2, 8 /* 8bits processed */ bne $v1, $zero, loop addu $a0, $t0, $zero ncomp: bne $t2, $t3, nbyte /* all bytes processed */ addiu $t3, $t3, 1 wait: sdbbp .end main openocd-0.9.0/contrib/loaders/erase_check/0000755000175000017500000000000012315575360015504 500000000000000openocd-0.9.0/contrib/loaders/erase_check/armv7m_erase_check.s0000644000175000017500000000326412315575360021342 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* parameters: r0 - address in r1 - byte count r2 - mask - result out */ .text .syntax unified .cpu cortex-m0 .thumb .thumb_func .align 2 loop: ldrb r3, [r0] adds r0, #1 ands r2, r2, r3 subs r1, r1, #1 bne loop end: bkpt #0 .end openocd-0.9.0/contrib/loaders/erase_check/armv4_5_erase_check.s0000644000175000017500000000321212315575360021377 00000000000000/*************************************************************************** * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* parameters: r0 - address in r1 - byte count r2 - mask - result out */ .text .arm loop: ldrb r3, [r0], #1 and r2, r2, r3 subs r1, r1, #1 bne loop end: bkpt #0 CRC32XOR: .word 0x04c11db7 .end openocd-0.9.0/contrib/rtos-helpers/0000755000175000017500000000000012516456301014242 500000000000000openocd-0.9.0/contrib/rtos-helpers/FreeRTOS-openocd.c0000644000175000017500000000111012516456301017335 00000000000000/* * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer * present in the kernel, so it has to be supplied by other means for * OpenOCD's threads awareness. * * Add this file to your project, and, if you're using --gc-sections, * ``--undefined=uxTopUsedPriority'' (or * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final * linking) to your LDFLAGS; same with all the other symbols you need. */ #include "FreeRTOS.h" #ifdef __GNUC__ #define USED __attribute__((used)) #else #define USED #endif const int USED uxTopUsedPriority = configMAX_PRIORITIES; openocd-0.9.0/contrib/99-openocd.rules0000644000175000017500000001052112516456301014474 00000000000000# Copy this file to /etc/udev/rules.d/ ACTION!="add|change", GOTO="openocd_rules_end" SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end" # Please keep this list sorted by VID:PID # opendous and estick ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="664", GROUP="plugdev" # Original FT232/FT245 VID:PID ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev" # Original FT2232 VID:PID ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev" # Original FT4232 VID:PID ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev" # Original FT232H VID:PID ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="664", GROUP="plugdev" # DISTORTEC JTAG-lock-pick Tiny 2 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="664", GROUP="plugdev" # TUMPA, TUMPA Lite ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev" # XDS100v2 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="664", GROUP="plugdev" # Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="664", GROUP="plugdev" # TI/Luminary Stellaris Evaluation Board FTDI (several) ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev" # TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev" # egnite Turtelizer 2 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="664", GROUP="plugdev" # Section5 ICEbear ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev" # Amontec JTAGkey and JTAGkey-tiny ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev" # TI ICDI ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="664", GROUP="plugdev" # STLink v1 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="664", GROUP="plugdev" # STLink v2 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="664", GROUP="plugdev" # STLink v2-1 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev" # Hilscher NXHX Boards ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="664", GROUP="plugdev" # Hitex STR9-comStick ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev" # Hitex STM32-PerformanceStick ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev" # Amontec JTAGkey-HiSpeed ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev" # IAR J-Link USB ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="664", GROUP="plugdev" # J-Link-OB (onboard) ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev" # Raisonance RLink ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev" # Debug Board for Neo1973 ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="664", GROUP="plugdev" # Olimex ARM-USB-OCD ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev" # Olimex ARM-USB-OCD-TINY ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev" # Olimex ARM-JTAG-EW ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="664", GROUP="plugdev" # Olimex ARM-USB-OCD-TINY-H ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev" # Olimex ARM-USB-OCD-H ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="664", GROUP="plugdev" # USBprog with OpenOCD firmware ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev" # TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev" # Marvell Sheevaplug ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev" # CMSIS-DAP compatible adapters ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev" LABEL="openocd_rules_end" openocd-0.9.0/contrib/itmdump.c0000644000175000017500000002212412516456301013357 00000000000000/* * Copyright (C) 2010 by David Brownell * * This program 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 program 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 . */ /* * Simple utility to parse and dump ARM Cortex-M3 SWO trace output. Once the * mechanisms work right, this information can be used for various purposes * including profiling (particularly easy for flat PC-sample profiles) and * for debugging. * * SWO is the Single Wire Output found on some ARM cores, most notably on the * Cortex-M3. It combines data from several sources: * * - Software trace (ITM): so-called "printf-style" application messaging * using "ITM stimulus ports"; and differential timestamps. * - Hardware trace (DWT): for profiling counters and comparator matches. * - TPIU may issue sync packets. * * The trace data format is defined in Appendix E, "Debug ITM and DWT packet * protocol", of the ARMv7-M Architecture Reference Manual (DDI 0403C). It * is a superset of the ITM data format from the Coresight TRM. * * The trace data has two encodings. The working assumption is that data * gets into this program using the UART encoding. */ #include #include #include #include #include #include unsigned int dump_swit; /* Example ITM trace word (0xWWXXYYZZ) parsing for task events, sent * on port 31 (Reserved for "the" RTOS in CMSIS v1.30) * WWXX: event code (0..3 pre-assigned, 4..15 reserved) * YY: task priority * ZZ: task number * * NOTE that this specific encoding could be space-optimized; and that * trace data streams could also be history-sensitive. */ static void show_task(int port, unsigned data) { unsigned code = data >> 16; char buf[16]; if (dump_swit) return; switch (code) { case 0: strcpy(buf, "run"); break; case 1: strcpy(buf, "block"); break; case 2: strcpy(buf, "create"); break; case 3: strcpy(buf, "destroy"); break; /* 4..15 reserved for other infrastructure ops */ default: sprintf(buf, "code %d", code); break; } printf("TASK %d, pri %d: %s", (data >> 0) & 0xff, (data >> 8) & 0xff, buf); } static void show_reserved(FILE *f, char *label, int c) { unsigned i; if (dump_swit) return; printf("%s - %#02x", label, c); for (i = 0; (c & 0x80) && i < 4; i++) { c = fgetc(f); if (c == EOF) { printf("(ERROR %d - %s) ", errno, strerror(errno)); break; } printf(" %#02x", c); } printf("\n"); } static bool read_varlen(FILE *f, int c, unsigned *value) { unsigned size; unsigned char buf[4]; *value = 0; switch (c & 3) { case 3: size = 4; break; case 2: size = 2; break; case 1: size = 1; break; default: printf("INVALID SIZE\n"); return false; } memset(buf, 0, sizeof buf); if (fread(buf, 1, size, f) != size) goto err; *value = (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + (buf[0] << 0); return true; err: printf("(ERROR %d - %s)\n", errno, strerror(errno)); return false; } static void show_hard(FILE *f, int c) { unsigned type = c >> 3; unsigned value; char *label; if (dump_swit) return; printf("DWT - "); if (!read_varlen(f, c, &value)) return; printf("%#x", value); switch (type) { case 0: /* event counter wrapping */ printf("overflow %s%s%s%s%s%s", (value & (1 << 5)) ? "cyc " : "", (value & (1 << 4)) ? "fold " : "", (value & (1 << 3)) ? "lsu " : "", (value & (1 << 2)) ? "slp " : "", (value & (1 << 1)) ? "exc " : "", (value & (1 << 0)) ? "cpi " : ""); break; case 1: /* exception tracing */ switch (value >> 12) { case 1: label = "entry to"; break; case 2: label = "exit from"; break; case 3: label = "return to"; break; default: label = "?"; break; } printf("%s exception %d", label, value & 0x1ff); break; case 2: /* PC sampling */ if (c == 0x15) printf("PC - sleep"); else printf("PC - %#08x", value); break; case 8: /* data tracing, pc value */ case 10: case 12: case 14: printf("Data trace %d, PC %#08x", (c >> 4) & 3, value); /* optionally followed by data value */ break; case 9: /* data tracing, address offset */ case 11: case 13: case 15: printf("Data trace %d, address offset %#04x", (c >> 4) & 3, value); /* always followed by data value */ break; case 16 ... 23: /* data tracing, data value */ printf("Data trace %d, ", (c >> 4) & 3); label = (c & 0x8) ? "write" : "read"; switch (c & 3) { case 3: printf("word %s, value %#08x", label, value); break; case 2: printf("halfword %s, value %#04x", label, value); break; case 1: printf("byte %s, value %#02x", label, value); break; } break; default: printf("UNDEFINED, rawtype: %x", type); break; } printf("\n"); return; } /* * Table of SWIT (SoftWare InstrumentTation) message dump formats, for * ITM port 0..31 application data. * * Eventually this should be customizable; all usage is application defined. * * REVISIT there can be up to 256 trace ports, via "ITM Extension" packets */ struct { int port; void (*show)(int port, unsigned data); } format[] = { { .port = 31, .show = show_task, }, }; static void show_swit(FILE *f, int c) { unsigned port = c >> 3; unsigned value = 0; unsigned i; if (port + 1 == dump_swit) { if (!read_varlen(f, c, &value)) return; printf("%c", value); return; } if (!read_varlen(f, c, &value)) return; if (dump_swit) return; printf("SWIT %u - ", port); printf("%#08x", value); for (i = 0; i < sizeof(format) / sizeof(format[0]); i++) { if (format[i].port == port) { printf(", "); format[i].show(port, value); break; } } printf("\n"); return; } static void show_timestamp(FILE *f, int c) { unsigned counter = 0; char *label = ""; bool delayed = false; if (dump_swit) return; printf("TIMESTAMP - "); /* Format 2: header only */ if (!(c & 0x80)) { switch (c) { case 0: /* sync packet -- coding error! */ case 0x70: /* overflow -- ditto! */ printf("ERROR - %#02x\n", c); break; default: /* synchronous to ITM */ counter = c >> 4; goto done; } return; } /* Format 1: one to four bytes of data too */ switch (c >> 4) { default: label = ", reserved control\n"; break; case 0xc: /* synchronous to ITM */ break; case 0xd: label = ", timestamp delayed"; delayed = true; break; case 0xe: label = ", packet delayed"; delayed = true; break; case 0xf: label = ", packet and timetamp delayed"; delayed = true; break; } c = fgetc(f); if (c == EOF) goto err; counter = c & 0x7f; if (!(c & 0x80)) goto done; c = fgetc(f); if (c == EOF) goto err; counter |= (c & 0x7f) << 7; if (!(c & 0x80)) goto done; c = fgetc(f); if (c == EOF) goto err; counter |= (c & 0x7f) << 14; if (!(c & 0x80)) goto done; c = fgetc(f); if (c == EOF) goto err; counter |= (c & 0x7f) << 21; done: /* REVISIT should we try to convert from delta values? */ printf("+%u%s\n", counter, label); return; err: printf("(ERROR %d - %s) ", errno, strerror(errno)); goto done; } int main(int argc, char **argv) { FILE *f = stdin; int c; /* parse arguments */ while ((c = getopt(argc, argv, "f:d:")) != EOF) { switch (c) { case 'f': /* e.g. from UART connected to /dev/ttyUSB0 */ f = fopen(optarg, "r"); if (!f) { perror(optarg); return 1; } break; case 'd': dump_swit = atoi(optarg); break; default: fprintf(stderr, "usage: %s [-f input]", basename(argv[0])); return 1; } } /* Parse data ... records have a header then data bytes. * NOTE: we assume getc() deals in 8-bit bytes. */ bool overflow = false; while ((c = getc(f)) != EOF) { /* Sync packet ... 7 zeroes, 0x80 */ if (c == 0) { int i; for (i = 0; i < 6; i++) { c = fgetc(f); if (c == EOF) break; if (c != 0) goto bad_sync; } c = fgetc(f); if (c == 0x80) { printf("SYNC\n"); continue; } bad_sync: printf("BAD SYNC\n"); continue; } /* Overflow packet */ if (c == 0x70) { /* REVISIT later, report just what overflowed! * Timestamp and SWIT can happen. Non-ITM too? */ overflow = true; printf("OVERFLOW ...\n"); continue; } overflow = false; switch (c & 0x0f) { case 0x00: /* Timestamp */ show_timestamp(f, c); break; case 0x04: /* "Reserved" */ show_reserved(f, "RESERVED", c); break; case 0x08: /* ITM Extension */ /* FIXME someday, handle these ... */ show_reserved(f, "ITM EXT", c); break; case 0x0c: /* DWT Extension */ show_reserved(f, "DWT EXT", c); break; default: if (c & 4) show_hard(f, c); else show_swit(f, c); break; } } return 0; } openocd-0.9.0/contrib/libdcc/0000755000175000017500000000000012315575360013037 500000000000000openocd-0.9.0/contrib/libdcc/example.c0000644000175000017500000000460412315575360014562 00000000000000/*************************************************************************** * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * Copyright (C) 2008 by Frederik Kriewtz * * frederik@kriewitz.eu * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "dcc_stdio.h" /* enable openocd debugmsg at the gdb prompt: * monitor target_request debugmsgs enable * * create a trace point: * monitor trace point 1 * * to show how often the trace point was hit: * monitor trace point */ int main(void) { dbg_write_str("hello world"); dbg_write_char('t'); dbg_write_char('e'); dbg_write_char('s'); dbg_write_char('t'); dbg_write_char('\n'); unsigned long test_u32 = 0x01234567; dbg_write_u32(&test_u32, 1); static const unsigned short test_u16[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x0123, 0x4567, 0x89AB, 0xCDEF}; dbg_write_u16(test_u16, 8); static const unsigned char test_u8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0XDD, 0xEE, 0xFF}; dbg_write_u8(test_u8, 16); while(1) { dbg_trace_point(0); } } openocd-0.9.0/contrib/libdcc/README0000644000175000017500000000064012315575360013637 00000000000000This code is an example of using the openocd debug message system. Before the message output is seen in the debug window, the functionality will need enabling: From the gdb prompt: monitor target_request debugmsgs enable monitor trace point 1 From the Telnet prompt: target_request debugmsgs enable trace point 1 To see how many times the trace point was hit: (monitor) trace point 1 Spen spen@spen-soft.co.uk openocd-0.9.0/contrib/libdcc/dcc_stdio.c0000644000175000017500000001065312315575360015063 00000000000000/*************************************************************************** * Copyright (C) 2008 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * Copyright (C) 2008 by Frederik Kriewtz * * frederik@kriewitz.eu * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "dcc_stdio.h" #define TARGET_REQ_TRACEMSG 0x00 #define TARGET_REQ_DEBUGMSG_ASCII 0x01 #define TARGET_REQ_DEBUGMSG_HEXMSG(size) (0x01 | ((size & 0xff) << 8)) #define TARGET_REQ_DEBUGCHAR 0x02 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_6SM__) /* we use the System Control Block DCRDR reg to simulate a arm7_9 dcc channel * DCRDR[7:0] is used by target for status * DCRDR[15:8] is used by target for write buffer * DCRDR[23:16] is used for by host for status * DCRDR[31:24] is used for by host for write buffer */ #define NVIC_DBG_DATA_R (*((volatile unsigned short *)0xE000EDF8)) #define BUSY 1 void dbg_write(unsigned long dcc_data) { int len = 4; while (len--) { /* wait for data ready */ while (NVIC_DBG_DATA_R & BUSY); /* write our data and set write flag - tell host there is data*/ NVIC_DBG_DATA_R = (unsigned short)(((dcc_data & 0xff) << 8) | BUSY); dcc_data >>= 8; } } #elif defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5T__) void dbg_write(unsigned long dcc_data) { unsigned long dcc_status; do { asm volatile("mrc p14, 0, %0, c0, c0" : "=r" (dcc_status)); } while (dcc_status & 0x2); asm volatile("mcr p14, 0, %0, c1, c0" : : "r" (dcc_data)); } #else #error unsupported target #endif void dbg_trace_point(unsigned long number) { dbg_write(TARGET_REQ_TRACEMSG | (number << 8)); } void dbg_write_u32(const unsigned long *val, long len) { dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(4) | ((len & 0xffff) << 16)); while (len > 0) { dbg_write(*val); val++; len--; } } void dbg_write_u16(const unsigned short *val, long len) { unsigned long dcc_data; dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(2) | ((len & 0xffff) << 16)); while (len > 0) { dcc_data = val[0] | ((len > 1) ? val[1] << 16: 0x0000); dbg_write(dcc_data); val += 2; len -= 2; } } void dbg_write_u8(const unsigned char *val, long len) { unsigned long dcc_data; dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(1) | ((len & 0xffff) << 16)); while (len > 0) { dcc_data = val[0] | ((len > 1) ? val[1] << 8 : 0x00) | ((len > 2) ? val[2] << 16 : 0x00) | ((len > 3) ? val[3] << 24 : 0x00); dbg_write(dcc_data); val += 4; len -= 4; } } void dbg_write_str(const char *msg) { long len; unsigned long dcc_data; for (len = 0; msg[len] && (len < 65536); len++); dbg_write(TARGET_REQ_DEBUGMSG_ASCII | ((len & 0xffff) << 16)); while (len > 0) { dcc_data = msg[0] | ((len > 1) ? msg[1] << 8 : 0x00) | ((len > 2) ? msg[2] << 16 : 0x00) | ((len > 3) ? msg[3] << 24 : 0x00); dbg_write(dcc_data); msg += 4; len -= 4; } } void dbg_write_char(char msg) { dbg_write(TARGET_REQ_DEBUGCHAR | ((msg & 0xff) << 16)); } openocd-0.9.0/contrib/libdcc/dcc_stdio.h0000644000175000017500000000366012315575360015070 00000000000000/*************************************************************************** * Copyright (C) 2008 by Dominic Rath * * Dominic.Rath@gmx.de * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * This program 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 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifndef DCC_STDIO_H #define DCC_STDIO_H void dbg_trace_point(unsigned long number); void dbg_write_u32(const unsigned long *val, long len); void dbg_write_u16(const unsigned short *val, long len); void dbg_write_u8(const unsigned char *val, long len); void dbg_write_str(const char *msg); void dbg_write_char(char msg); #endif /* DCC_STDIO_H */ openocd-0.9.0/contrib/cross-build.sh0000755000175000017500000000723412315575360014332 00000000000000#!/bin/sh # This is an example of how to do a cross-build of OpenOCD using pkg-config. # Cross-building with pkg-config is deceptively hard and most guides and # tutorials are incomplete or give bad advice. Some of the traps that are easy # to fall in but handled by this script are: # # * Polluting search paths and flags with values from the build system. # * Faulty pkg-config wrappers shipped with distribution packaged cross- # toolchains. # * Build failing because pkg-config discards some paths even though they are # correctly listed in the .pc file. # * Getting successfully built binaries that cannot find runtime data because # paths refer to the build file system. # # This script is probably more useful as a reference than as a complete build # tool but for some configurations it may be usable as-is. It only cross- # builds libusb-1.0 from source, but the script can be extended to build other # prerequisities in a similar manner. # # Usage: # export LIBUSB1_SRC=/path/to/libusb-1.0 # export HIDAPI_SRC=/path/to/hidapi # export OPENOCD_CONFIG="--enable-..." # cd /work/dir # /path/to/openocd/contrib/cross-build.sh # # For static linking, a workaround is to # export LIBUSB1_CONFIG="--enable-static --disable-shared" # # All the paths must not contain any spaces. set -e -x WORK_DIR=$PWD ## Source code paths, customize as necessary : ${OPENOCD_SRC:="`dirname "$0"`/.."} : ${LIBUSB1_SRC:=/path/to/libusb} : ${HIDAPI_SRC:=/path/to/hidapi} OPENOCD_SRC=`readlink -m $OPENOCD_SRC` LIBUSB1_SRC=`readlink -m $LIBUSB1_SRC` HIDAPI_SRC=`readlink -m $HIDAPI_SRC` HOST_TRIPLET=$1 BUILD_DIR=$WORK_DIR/$HOST_TRIPLET-build LIBUSB1_BUILD_DIR=$BUILD_DIR/libusb1 HIDAPI_BUILD_DIR=$BUILD_DIR/hidapi OPENOCD_BUILD_DIR=$BUILD_DIR/openocd ## Root of host file tree SYSROOT=$WORK_DIR/$HOST_TRIPLET-root ## Install location within host file tree : ${PREFIX=/usr} ## OpenOCD-only install dir for packaging PACKAGE_DIR=$WORK_DIR/openocd_`git --git-dir=$OPENOCD_SRC/.git describe`_$HOST_TRIPLET ####### # Create pkg-config wrapper and make sure it's used export PKG_CONFIG=$WORK_DIR/$HOST_TRIPLET-pkg-config cat > $PKG_CONFIG <> 4) ) ls.append( "%x" % ( b & 0x0f ) ) for i in range(8): if b & (1<> 4) ) ls.append( "%x" % ( b & 0x0f ) ) return ''.join(ls) def ReadByte( f ): """Read a byte from a file and return it as an int in least significant 8 bits""" b = f.read(1) if b: return 0xff & b[0]; else: return -1 def ShowState( state ): """return the given state int as a state string""" #return "0x%02x" % state # comment this out to get textual state form global State if 0 <= state <= IRUPDATE: return State[state] else: return "Unknown state 0x%02x" % state def ShowOpcode( op, f ): """return the given byte as an opcode string""" global Xsdrsize if op == XCOMPLETE: print("XCOMPLETE") elif op == XTDOMASK: buf = bytes2hexString( f, Xsdrsize ) print("XTDOMASK 0x%s" % buf) elif op == XSIR: len = ReadByte( f ) buf = bytes2hexString( f, len ) print("XSIR 0x%02X 0x%s" % (len, buf)) elif op == XSDR: tdi = bytes2hexString( f, Xsdrsize ) print("XSDR 0x%s" % tdi) elif op == XRUNTEST: len = struct.unpack( '>i', f.read(4) )[0] print("XRUNTEST 0x%08X" % len) elif op == XREPEAT: len = ReadByte( f ) print("XREPEAT 0x%02X" % len) elif op == XSDRSIZE: Xsdrsize = struct.unpack( '>i', f.read(4) )[0] #print("XSDRSIZE 0x%08X" % Xsdrsize, file=sys.stderr ) print("XSDRSIZE 0x%08X %d" % (Xsdrsize, Xsdrsize) ) elif op == XSDRTDO: tdi = bytes2hexString( f, Xsdrsize ) tdo = bytes2hexString( f, Xsdrsize ) print("XSDRTDO 0x%s 0x%s" % (tdi, tdo) ) elif op == XSETSDRMASKS: addrmask = bytes2hexString( f, Xsdrsize ) datamask = ReadSDRMASKS( f, Xsdrsize ) print("XSETSDRMASKS 0x%s 0x%s" % (addrmask, datamask) ) elif op == XSDRINC: startaddr = bytes2hexString( f, Xsdrsize ) len = ReadByte(f) print("XSDRINC 0x%s 0x%02X" % (startaddr, len), end='' ) for numTimes in range(len): data = bytes2hexString( f, SetsdrmasksOnesCount) print(" 0x%s" % data ) print() # newline elif op == XSDRB: tdi = bytes2hexString( f, Xsdrsize ) print("XSDRB 0x%s" % tdi ) elif op == XSDRC: tdi = bytes2hexString( f, Xsdrsize ) print("XSDRC 0x%s" % tdi ) elif op == XSDRE: tdi = bytes2hexString( f, Xsdrsize ) print("XSDRE 0x%s" % tdi ) elif op == XSDRTDOB: tdo = bytes2hexString( f, Xsdrsize ) print("XSDRTDOB 0x%s" % tdo ) elif op == XSDRTDOC: tdi = bytes2hexString( f, Xsdrsize ) tdo = bytes2hexString( f, Xsdrsize ) print("XSDRTDOC 0x%s 0x%s" % (tdi, tdo) ) elif op == XSDRTDOE: tdi = bytes2hexString( f, Xsdrsize ) tdo = bytes2hexString( f, Xsdrsize ) print("XSDRTDOE 0x%s 0x%s" % (tdi, tdo) ) elif op == XSTATE: b = ReadByte(f) print("XSTATE %s" % ShowState(b)) elif op == XENDIR: b = ReadByte( f ) print("XENDIR %s" % 'IRPAUSE' if b==1 else 'IDLE') elif op == XENDDR: b = ReadByte( f ) print("XENDDR %s" % 'DRPAUSE' if b==1 else 'IDLE') elif op == XSIR2: len = struct.unpack( '>H', f.read(2) )[0] buf = bytes2hexString( f, len ) print("XSIR2 0x%04X 0x%s" % (len, buf)) elif op == XCOMMENT: cmt = [] while 1: b = ReadByte(f) if b == 0: # terminating nul break; cmt.append( chr(b) ) print("XCOMMENT \"%s\"" % ''.join(cmt) ) elif op == XWAIT: run_state = ReadByte(f) end_state = ReadByte(f) useconds = struct.unpack( '>i', f.read(4) )[0] print("XWAIT %s %s" % (ShowState(run_state), ShowState(end_state)), useconds) elif op == XWAITSTATE: run_state = ReadByte(f) end_state = ReadByte(f) clocks = struct.unpack( '>i', f.read(4) )[0] useconds = struct.unpack( '>i', f.read(4) )[0] print("XWAITSTATE %s %s CLOCKS=%d USECS=%d" % (ShowState(run_state), ShowState(end_state), clocks, useconds) ) elif op == LCOUNT: loop_count = struct.unpack( '>i', f.read(4) )[0] print("LCOUNT", loop_count ) elif op == LDELAY: run_state = ReadByte(f) clocks = struct.unpack( '>i', f.read(4) )[0] useconds = struct.unpack( '>i', f.read(4) )[0] print("LDELAY %s CLOCKS=%d USECS=%d" % (ShowState(run_state), clocks, useconds) ) elif op == LSDR: tdi = bytes2hexString( f, Xsdrsize ) tdo = bytes2hexString( f, Xsdrsize ) print("LSDR 0x%s 0x%s" % (tdi, tdo) ) elif op == XTRST: # the argument is a single byte and it is the index into "trst_mode_allowed" trst_mode = ReadByte(f) if trst_mode <= 3: print("TRST %s" % trst_mode_allowed[trst_mode] ) else: print("TRST 0x%02X" % trst_mode ); else: print("UNKNOWN op 0x%02X %d" % (op, op)) exit(1) def main(): if len( sys.argv ) < 2: print("usage %s " % sys.argv[0]) exit(1) f = open( sys.argv[1], 'rb' ) opcode = ReadByte( f ) while opcode != -1: # print the position within the file, then the command print( "%d: " % f.tell(), end='' ) ShowOpcode( opcode, f ) opcode = ReadByte(f) if __name__ == "__main__": main() openocd-0.9.0/contrib/xsvf_tools/svf2xsvf.py0000644000175000017500000006412612315575360016117 00000000000000#!/usr/bin/python3.0 # Copyright 2008, SoftPLC Corporation http://softplc.com # Dick Hollenbeck dick@softplc.com # This program 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 2 # of the License, or (at your option) any later version. # # This program 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, you may find one here: # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html # or you may search the http://www.gnu.org website for the version 2 license, # or you may write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # A python program to convert an SVF file to an XSVF file. There is an # option to include comments containing the source file line number from the origin # SVF file before each outputted XSVF statement. # # We deviate from the XSVF spec in that we introduce a new command called # XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately # XRUNSTATE was ill conceived and is not used here. We also add support for the # three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file # generated from this program is suitable for use with the xsvf player in # OpenOCD with my modifications to xsvf.c. # # This program is written for python 3.0, and it is not easy to change this # back to 2.x. You may find it easier to use python 3.x even if that means # building it. import re import sys import struct # There are both ------ and ------ sections to this program if len( sys.argv ) < 3: print("usage %s " % sys.argv[0]) exit(1) inputFilename = sys.argv[1] outputFilename = sys.argv[2] doCOMMENTs = True # Save XCOMMENTs in the output xsvf file #doCOMMENTs = False # Save XCOMMENTs in the output xsvf file # pick your file encoding file_encoding = 'ISO-8859-1' #file_encoding = 'utf-8' xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares #-----< Lexer >--------------------------------------------------------------- StateBin = (RESET,IDLE, DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) # Any integer index into this tuple will be equal to its corresponding StateBin value StateTxt = ("RESET","IDLE", "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") (XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE, LCOUNT,LDELAY,LSDR,XTRST) = range(29) #Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back # and check a completion status, essentially waiting on a part until it signals that it is done. # For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST) # and exit loop when LSDR compares match. """ LCOUNT 25; ! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; ! Test for the completed status. Match means pass. ! Loop back to LDELAY line if not match and loop count less than 25. LSDR 1 TDI (0) TDO (1); """ #XTRST is an opcode Xilinx seemed to have missed and it comes from the SVF TRST statement. LineNumber = 1 def s_ident(scanner, token): return ("ident", token.upper(), LineNumber) def s_hex(scanner, token): global LineNumber LineNumber = LineNumber + token.count('\n') token = ''.join(token.split()) return ("hex", token[1:-1], LineNumber) def s_int(scanner, token): return ("int", int(token), LineNumber) def s_float(scanner, token): return ("float", float(token), LineNumber) #def s_comment(scanner, token): return ("comment", token, LineNumber) def s_semicolon(scanner, token): return ("semi", token, LineNumber) def s_nl(scanner,token): global LineNumber LineNumber = LineNumber + 1 #print( 'LineNumber=', LineNumber, file=sys.stderr ) return None #2.00E-002 scanner = re.Scanner([ (r"[a-zA-Z]\w*", s_ident), # (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float), (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float), (r"\d+", s_int), (r"\(([0-9a-fA-F]|\s)*\)", s_hex), (r"(!|//).*$", None), (r";", s_semicolon), (r"\n",s_nl), (r"\s*", None), ], re.MULTILINE ) # open the file using the given encoding file = open( sys.argv[1], encoding=file_encoding ) # read all svf file input into string "input" input = file.read() file.close() # Lexer: # create a list of tuples containing (tokenType, tokenValue, LineNumber) tokens = scanner.scan( input )[0] input = None # allow gc to reclaim memory holding file #for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue ) #---------------------------------------------------------------------- tokVal = tokType = tokLn = None tup = iter( tokens ) def nextTok(): """ Function to read the next token from tup into tokType, tokVal, tokLn (linenumber) which are globals. """ global tokType, tokVal, tokLn, tup tokType, tokVal, tokLn = tup.__next__() class ParseError(Exception): """A class to hold a parsing error message""" def __init__(self, linenumber, token, message): self.linenumber = linenumber self.token = token self.message = message def __str__(self): global inputFilename return "Error in file \'%s\' at line %d near token %s\n %s" % ( inputFilename, self.linenumber, repr(self.token), self.message) class MASKSET(object): """ Class MASKSET holds a set of bit vectors, all of which are related, will all have the same length, and are associated with one of the seven shiftOps: HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a size. """ def __init__(self, name): self.empty() self.name = name def empty(self): self.mask = bytearray() self.smask = bytearray() self.tdi = bytearray() self.tdo = bytearray() self.size = 0 def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ): """ Set all the lengths equal in the event some of the masks were not seen as part of the last change set. """ if self.size == newSize: return if newSize == 0: self.empty() return # If an SIR was given without a MASK(), then use a mask of all zeros. # this is not consistent with the SVF spec, but it makes sense because # it would be odd to be testing an instruction register read out of a # tap without giving a mask for it. Also, lattice seems to agree and is # generating SVF files that comply with this philosophy. if self.name == 'SIR' and not sawMASK: self.mask = bytearray( newSize ) if newSize != len(self.mask): self.mask = bytearray( newSize ) if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros for i in range( newSize ): self.mask[i] = 1 if newSize != len(self.tdo): self.tdo = bytearray( newSize ) if newSize != len(self.tdi): self.tdi = bytearray( newSize ) if newSize != len(self.smask): self.smask = bytearray( newSize ) self.size = newSize #---------- def makeBitArray( hexString, bitCount ): """ Converts a packed sequence of hex ascii characters into a bytearray where each element in the array holds exactly one bit. Only "bitCount" bits are scanned and these must be the least significant bits in the hex number. That is, it is legal to have some unused bits in the must significant hex nibble of the input "hexString". The string is scanned starting from the backend, then just before returning we reverse the array. This way the append() method can be used, which I assume is faster than an insert. """ global tokLn a = bytearray() length = bitCount hexString = list(hexString) hexString.reverse() #print(hexString) for c in hexString: if length <= 0: break; c = int(c, 16) for mask in [1,2,4,8]: if length <= 0: break; length = length - 1 a.append( (c & mask) != 0 ) if length > 0: raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount ) a.reverse() #print(a) return a def makeXSVFbytes( bitarray ): """ Make a bytearray which is contains the XSVF bits which will be written directly to disk. The number of bytes needed is calculated from the size of the argument bitarray. """ bitCount = len(bitarray) byteCount = (bitCount+7)//8 ba = bytearray( byteCount ) firstBit = (bitCount % 8) - 1 if firstBit == -1: firstBit = 7 bitNdx = 0 for byteNdx in range(byteCount): mask = 1<> 1 bitNdx = bitNdx + 1 ba[byteNdx] = byte firstBit = 7 return ba def writeComment( outputFile, shiftOp_linenum, shiftOp ): """ Write an XCOMMENT record to outputFile """ comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul ba = bytearray(1) ba[0] = XCOMMENT ba += comment.encode() outputFile.write( ba ) def combineBitVectors( trailer, meat, header ): """ Combine the 3 bit vectors comprizing a transmission. Since the least significant bits are sent first, the header is put onto the list last so they are sent first from that least significant position. """ ret = bytearray() ret.extend( trailer ) ret.extend( meat ) ret.extend( header ) return ret def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ): """ Write the output for the SVF RUNTEST command. run_count - the number of clocks min_time - the number of seconds tokenTxt - either RUNTEST or LDELAY """ # convert from secs to usecs min_time = int( min_time * 1000000) # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to # implement the required behavior of the SVF RUNTEST command. if doCOMMENTs: writeComment( output, tokLn, tokenTxt ) if tokenTxt == 'RUNTEST': obuf = bytearray(11) obuf[0] = XWAITSTATE obuf[1] = run_state obuf[2] = end_state struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf outputFile.write( obuf ) else: # == 'LDELAY' obuf = bytearray(10) obuf[0] = LDELAY obuf[1] = run_state # LDELAY has no end_state struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf outputFile.write( obuf ) output = open( outputFilename, mode='wb' ) hir = MASKSET('HIR') hdr = MASKSET('HDR') tir = MASKSET('TIR') tdr = MASKSET('TDR') sir = MASKSET('SIR') sdr = MASKSET('SDR') expecting_eof = True # one of the commands that take the shiftParts after the length, the parse # template for all of these commands is identical shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR') # the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR' shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir ) # what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK') # the set of legal states which can trail the RUNTEST command run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE') enddr_state_allowed = ('DRPAUSE', 'IDLE') endir_state_allowed = ('IRPAUSE', 'IDLE') trst_mode_allowed = ('ON', 'OFF', 'Z', 'ABSENT') enddr_state = IDLE endir_state = IDLE frequency = 1.00e+006 # HZ; # change detection for xsdrsize and xtdomask xsdrsize = -1 # the last one sent, send only on change xtdomask = bytearray() # the last one sent, send only on change # we use a number of single byte writes for the XSVF command below cmdbuf = bytearray(1) # Save the XREPEAT setting into the file as first thing. obuf = bytearray(2) obuf[0] = XREPEAT obuf[1] = xrepeat output.write( obuf ) try: while 1: expecting_eof = True nextTok() expecting_eof = False # print( tokType, tokVal, tokLn ) if tokVal in shiftOps: shiftOp_linenum = tokLn shiftOp = tokVal set = shiftSets[shiftOps.index(shiftOp)] # set flags false, if we see one later, set that one true later sawTDI = sawTDO = sawMASK = sawSMASK = False nextTok() if tokType != 'int': raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) ) length = tokVal nextTok() while tokVal != ';': if tokVal not in shiftParts: raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'") shiftPart = tokVal nextTok() if tokType != 'hex': raise ParseError( tokLn, tokVal, "Expecting hex bits" ) bits = makeBitArray( tokVal, length ) if shiftPart == 'TDI': sawTDI = True set.tdi = bits elif shiftPart == 'TDO': sawTDO = True set.tdo = bits elif shiftPart == 'MASK': sawMASK = True set.mask = bits elif shiftPart == 'SMASK': sawSMASK = True set.smask = bits nextTok() set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length ) # process all the gathered parameters and generate outputs here if shiftOp == 'SIR': if doCOMMENTs: writeComment( output, shiftOp_linenum, 'SIR' ) tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi ) if len(tdi) > 255: obuf = bytearray(3) obuf[0] = XSIR2 struct.pack_into( ">h", obuf, 1, len(tdi) ) else: obuf = bytearray(2) obuf[0] = XSIR obuf[1] = len(tdi) output.write( obuf ) obuf = makeXSVFbytes( tdi ) output.write( obuf ) elif shiftOp == 'SDR': if doCOMMENTs: writeComment( output, shiftOp_linenum, shiftOp ) if not sawTDO: # pass a zero filled bit vector for the sdr.mask mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask ) tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) if xsdrsize != len(tdi): xsdrsize = len(tdi) cmdbuf[0] = XSDRSIZE output.write( cmdbuf ) obuf = bytearray(4) struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf output.write( obuf ) if xtdomask != mask: xtdomask = mask cmdbuf[0] = XTDOMASK output.write( cmdbuf ) obuf = makeXSVFbytes( mask ) output.write( obuf ) cmdbuf[0] = XSDR output.write( cmdbuf ) obuf = makeXSVFbytes( tdi ) output.write( obuf ) else: mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) if xsdrsize != len(tdi): xsdrsize = len(tdi) cmdbuf[0] = XSDRSIZE output.write( cmdbuf ) obuf = bytearray(4) struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf output.write( obuf ) if xtdomask != mask: xtdomask = mask cmdbuf[0] = XTDOMASK output.write( cmdbuf ) obuf = makeXSVFbytes( mask ) output.write( obuf ) cmdbuf[0] = XSDRTDO output.write( cmdbuf ) obuf = makeXSVFbytes( tdi ) output.write( obuf ) obuf = makeXSVFbytes( tdo ) output.write( obuf ) #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) elif shiftOp == 'LSDR': if doCOMMENTs: writeComment( output, shiftOp_linenum, shiftOp ) mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) if xsdrsize != len(tdi): xsdrsize = len(tdi) cmdbuf[0] = XSDRSIZE output.write( cmdbuf ) obuf = bytearray(4) struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf output.write( obuf ) if xtdomask != mask: xtdomask = mask cmdbuf[0] = XTDOMASK output.write( cmdbuf ) obuf = makeXSVFbytes( mask ) output.write( obuf ) cmdbuf[0] = LSDR output.write( cmdbuf ) obuf = makeXSVFbytes( tdi ) output.write( obuf ) obuf = makeXSVFbytes( tdo ) output.write( obuf ) #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) elif tokVal == 'RUNTEST' or tokVal == 'LDELAY': # e.g. from lattice tools: # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;" saveTok = tokVal nextTok() min_time = 0 run_count = 0 max_time = 600 # ten minutes if tokVal in run_state_allowed: run_state = StateTxt.index(tokVal) end_state = run_state # bottom of page 17 of SVF spec nextTok() if tokType != 'int' and tokType != 'float': raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]") timeval = tokVal; nextTok() if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK': raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)") if tokVal == 'TCK' or tokVal == 'SCK': run_count = int( timeval ) else: min_time = timeval nextTok() if tokType == 'int' or tokType == 'float': min_time = tokVal nextTok() if tokVal != 'SEC': raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time") nextTok() if tokVal == 'MAXIMUM': nextTok() if tokType != 'int' and tokType != 'float': raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM") max_time = tokVal nextTok() if tokVal != 'SEC': raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time") nextTok() if tokVal == 'ENDSTATE': nextTok() if tokVal not in run_state_allowed: raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE") end_state = StateTxt.index(tokVal) nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....") # print( "run_count=", run_count, "min_time=", min_time, # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] ) writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok ) elif tokVal == 'LCOUNT': nextTok() if tokType != 'int': raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT") loopCount = tokVal nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count") if doCOMMENTs: writeComment( output, tokLn, 'LCOUNT' ) obuf = bytearray(5) obuf[0] = LCOUNT struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf output.write( obuf ) elif tokVal == 'ENDDR': nextTok() if tokVal not in enddr_state_allowed: raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE)") enddr_state = StateTxt.index(tokVal) nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state") if doCOMMENTs: writeComment( output, tokLn, 'ENDDR' ) obuf = bytearray(2) obuf[0] = XENDDR # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. # boolean argument to XENDDR which only handles two of the 3 intended states. obuf[1] = 1 if enddr_state == DRPAUSE else 0 output.write( obuf ) elif tokVal == 'ENDIR': nextTok() if tokVal not in endir_state_allowed: raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE)") endir_state = StateTxt.index(tokVal) nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state") if doCOMMENTs: writeComment( output, tokLn, 'ENDIR' ) obuf = bytearray(2) obuf[0] = XENDIR # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. # boolean argument to XENDDR which only handles two of the 3 intended states. obuf[1] = 1 if endir_state == IRPAUSE else 0 output.write( obuf ) elif tokVal == 'STATE': nextTok() ln = tokLn while tokVal != ';': if tokVal not in StateTxt: raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE") stable_state = StateTxt.index( tokVal ) if doCOMMENTs and ln != -1: writeComment( output, ln, 'STATE' ) ln = -1 # save comment only once obuf = bytearray(2) obuf[0] = XSTATE obuf[1] = stable_state output.write( obuf ) nextTok() elif tokVal == 'FREQUENCY': nextTok() if tokVal != ';': if tokType != 'int' and tokType != 'float': raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY") frequency = tokVal nextTok() if tokVal != 'HZ': raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles") nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ") elif tokVal == 'TRST': nextTok() if tokVal not in trst_mode_allowed: raise ParseError( tokLn, tokVal, "Expecting 'ON|OFF|Z|ABSENT' after TRST") trst_mode = tokVal nextTok() if tokVal != ';': raise ParseError( tokLn, tokVal, "Expecting ';' after TRST trst_mode") if doCOMMENTs: writeComment( output, tokLn, 'TRST %s' % trst_mode ) obuf = bytearray( 2 ) obuf[0] = XTRST obuf[1] = trst_mode_allowed.index( trst_mode ) # use the index as the binary argument to XTRST opcode output.write( obuf ) else: raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal) except StopIteration: if not expecting_eof: print( "Unexpected End of File at line ", tokLn ) except ParseError as pe: print( "\n", pe ) finally: # print( "closing file" ) cmdbuf[0] = XCOMPLETE output.write( cmdbuf ) output.close() openocd-0.9.0/depcomp0000755000175000017500000005601612526201647011462 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program 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 2, or (at your option) # any later version. # This program 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 . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: openocd-0.9.0/aclocal.m40000644000175000017500000126560712526201641011750 00000000000000# generated automatically by aclocal 1.13.4 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2010 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi # Handle Gentoo/FreeBSD as it was Linux case $host_vendor in gentoo) version_type=linux ;; *) version_type=freebsd-$objformat ;; esac case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; linux) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' need_lib_prefix=no need_version=no ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS # longlong.m4 serial 17 dnl Copyright (C) 1999-2007, 2009-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_LONG_LONG_INT if 'long long int' works. # This fixes a bug in Autoconf 2.61, and can be faster # than what's in Autoconf 2.62 through 2.68. # Note: If the type 'long long int' exists but is only 32 bits large # (as on some very old compilers), HAVE_LONG_LONG_INT will not be # defined. In this case you can treat 'long long int' like 'long int'. AC_DEFUN([AC_TYPE_LONG_LONG_INT], [ AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], [ac_cv_type_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int if test $ac_cv_type_long_long_int = yes; then dnl Catch a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. dnl If cross compiling, assume the bug is not important, since dnl nobody cross compiles for this platform as far as we know. AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[@%:@include @%:@ifndef LLONG_MAX @%:@ define HALF \ (1LL << (sizeof (long long int) * CHAR_BIT - 2)) @%:@ define LLONG_MAX (HALF - 1 + HALF) @%:@endif]], [[long long int n = 1; int i; for (i = 0; ; i++) { long long int m = n << i; if (m >> i != n) return 1; if (LLONG_MAX / 2 < m) break; } return 0;]])], [], [ac_cv_type_long_long_int=no], [:]) fi fi]) if test $ac_cv_type_long_long_int = yes; then AC_DEFINE([HAVE_LONG_LONG_INT], [1], [Define to 1 if the system has the type 'long long int'.]) fi ]) # Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. # This fixes a bug in Autoconf 2.61, and can be faster # than what's in Autoconf 2.62 through 2.68. # Note: If the type 'unsigned long long int' exists but is only 32 bits # large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT # will not be defined. In this case you can treat 'unsigned long long int' # like 'unsigned long int'. AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], [ AC_CACHE_CHECK([for unsigned long long int], [ac_cv_type_unsigned_long_long_int], [ac_cv_type_unsigned_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then AC_LINK_IFELSE( [_AC_TYPE_LONG_LONG_SNIPPET], [], [ac_cv_type_unsigned_long_long_int=no]) fi]) if test $ac_cv_type_unsigned_long_long_int = yes; then AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], [Define to 1 if the system has the type 'unsigned long long int'.]) fi ]) # Expands to a C program that can be used to test for simultaneous support # of 'long long' and 'unsigned long long'. We don't want to say that # 'long long' is available if 'unsigned long long' is not, or vice versa, # because too many programs rely on the symmetry between signed and unsigned # integer types (excluding 'bool'). AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], [ AC_LANG_PROGRAM( [[/* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63;]], [[/* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull));]]) ]) # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3293 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4]) m4_define([LT_PACKAGE_REVISION], [1.3293]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4' macro_revision='1.3293' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program 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 2 of the License, or # (at your option) any later version. # # This program 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # ------------------------------------------- # Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.13.4], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.13.4])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR openocd-0.9.0/tools/0000755000175000017500000000000012526202223011304 500000000000000openocd-0.9.0/tools/rlink_make_speed_table/0000755000175000017500000000000012315575362015764 500000000000000openocd-0.9.0/tools/rlink_make_speed_table/rlink_make_speed_table0000755000175000017500000000003712315575362022275 00000000000000#!/bin/sh exec perl "$0.pl" $* openocd-0.9.0/tools/rlink_make_speed_table/rlink_make_speed_table.pl0000755000175000017500000000560012315575362022710 00000000000000#!/bin/perl #*************************************************************************** #* Copyright (C) 2008 Lou Deluxe * #* lou.openocd012@fixit.nospammail.net * #* * #* This program 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 2 of the License, or * #* (at your option) any later version. * #* * #* This program 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, write to the * #* Free Software Foundation, Inc., * #* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * #*************************************************************************** # A simple utility to read a list of files (names composed by numeric prescaler arguments) and compose a C source file defining data structures which hold the binary data read from those files. my @speed_table = (); print < $a} @ARGV) { my(@ary) = ( byte_array_from_file(${prescaler} . "_init.dtc"), byte_array_from_file(${prescaler} . "_call.dtc") ); for $i (@ary) { $i = sprintf("%d", $i); } $bytes = join(', ', @ary); $bytes =~ s/(^|\s)(.{70}?\S*)/\2\n/go; # break up long lines $bytes =~ s/\n +/\n/go; $bytes =~ s/(^|\n)/\1\t/go; # format nicely printf("static const uint8_t dtc_%d[] = {\n%s\n};\n\n", $prescaler, $bytes); push(@speed_table, sprintf("\tdtc_%d, sizeof(dtc_%d), (ST7_FOSC * 2) / (1000 * %d), %d\n", $prescaler, $prescaler, $prescaler, $prescaler)); } printf("const struct rlink_speed_table rlink_speed_table[] = { {\n%s} };\n\n", join("}, {\n", @speed_table)); printf("const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table);\n\n"); sub byte_array_from_file { my($filename) = @_; my(@array, $text, $i) = (); open(IN, '<', $filename) || die "$filename: $!"; undef($/); $text = ; close(IN); for($i = 0; $i < length($text); $i++) { push(@array, ord(substr($text, $i, 1))); } @array; } openocd-0.9.0/tools/st7_dtc_as/0000755000175000017500000000000012315575362013353 500000000000000openocd-0.9.0/tools/st7_dtc_as/st7_dtc_as0000755000175000017500000000003712315575362015253 00000000000000#!/bin/sh exec perl "$0.pl" $* openocd-0.9.0/tools/st7_dtc_as/st7_dtc_as.pl0000755000175000017500000003176712315575362015703 00000000000000#!/bin/perl #*************************************************************************** #* Copyright (C) 2008 Lou Deluxe * #* lou.openocd012@fixit.nospammail.net * #* * #* This program 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 2 of the License, or * #* (at your option) any later version. * #* * #* This program 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, write to the * #* Free Software Foundation, Inc., * #* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * #*************************************************************************** # A rudimentary assembler for DTC code. # It is not robust, by any means, but it gets the job done. {package DTC_as; my($i); # for later loop to generate reverse lookup sub new { my($self) = bless{}; $self->{'pagewidth'} = 60; $self; } %status_bit_arg = ( 'STOP' => 0x01, 'ERROR' => 0x02, ); %cp_arg = ( 'A=>X' => 0x00, 'A 0x01, 'CARRY' => 0x02, 'ALWAYS' => 0x03, 'ADR_BUFFER0=>CMP0' => 0x04, 'ADR_BUFFER0 0x05, 'ADR_BUFFER1=>CMP1' => 0x06, 'ADR_BUFFER1 0x07, ); %shift_unit_arg = ( 'CARD' => 0x00, 'MPEG' => 0x08, ); %shift_pin_arg = ( 'PIN0=>IN' => 0x00, 'PIN1=>IN' => 0x04, 'OUT=>PIN0' => 0x01, 'OUT=>PIN1' => 0x03, ); @ld_arg = ( '', 'X', 'Y', 'MASK', 'ADR_BUFFER00', 'ADR_BUFFER01', 'ADR_BUFFER10', 'ADR_BUFFER11', 'CMP00', 'CMP01', 'CMP10', 'CMP11', 'DATA_FLASH', 'CTRL_FCI', 'CTRL_CARD', 'CTRL_MPEG', 'DR_PARALLEL', 'DDR_PARALLEL', 'OR_PARALLEL', 'DR_CARD', 'DDR_CARD', 'OR_CARD', 'SHIFT_CARD', 'DR_MPEG', 'DDR_MPEG', 'OR_MPEG', 'SHIFT_MPEG', 'DATA_BUFFER0', 'DATA_BUFFER1', 'ECC_CRC', 'TMP_ECC', 'BUFFER_MNGT' ); for($i = 0; $i < @ld_arg; $i++) { $ld_arg{$ld_arg[$i]} = $i; } # ADDER8 / SUB8 sub alu8 { my($self) = shift; my($operand, $i) = shift; if(defined($ld_arg{$operand})) { $i = $ld_arg{$operand}; if($i > 0x00 && $i < 0x04) { return(($i - 0x01) << 3); } } return undef; } # ADDER16 / SUB16 sub alu16 { my($self) = shift; my($operand, $i) = shift; $operand .= '0'; if(defined($ld_arg{$operand})) { $i = $ld_arg{$operand}; if($i > 0x03 && $i < 0x0c) { return(($i - 0x04) << 2); } } return undef; } # BSET / BCLR sub bsetorclr { my($self) = shift; my($ret); if(@_ < 1) { return undef; } $ret = $_[0]; if(($ret < 0) || ($ret > 3)) { return undef; } return $ret; } # Opcode lookup table %op = ( 'NOP' => [ 0x0, ], 'SEC' => [ 0x1, ], 'CLC' => [ 0x2, ], 'RET' => [ 0x3, ], 'STATUS' => [ 0x4, sub { my($self) = shift; my($ret, $i); for $i (@_) { if(!defined($status_bit_arg{"\U$i"})) { return undef; } $ret |= $status_bit_arg{"\U$i"}; } if($ret < 1) { return undef; } return $ret; } ], 'CP' => [ 0x8, sub { my($self) = shift; if((@_ != 1) || (!defined($cp_arg{"\U$_[0]"}))) { return undef; } return($cp_arg{"\U$_[0]"}); } ], 'SHIFT' => [ 0x10, sub { my($self) = shift; my($ret, $i); if((@_ < 2) || (!defined($shift_unit_arg{"\U$_[0]"}))) { return undef; } $ret = $shift_unit_arg{"\U$_[0]"}; shift; for $i (@_) { if(!defined($shift_pin_arg{"\U$i"})) { return undef; } $ret |= $shift_pin_arg{"\U$i"}; } return $ret; } ], 'SUB8' => [ 0x24, \&alu8 ], 'ADDER8' => [ 0x25, \&alu8 ], 'SUB16' => [ 0x26, \&alu16 ], 'ADDER16' => [ 0x27, \&alu16 ], 'BCLR' => [ 0x28, \&bsetorclr ], 'BSET' => [ 0x38, \&bsetorclr ], 'REVERSE' => [ 0x30, ], 'XOR' => [ 0x31, ], 'AND' => [ 0x32, ], 'EXCHANGE' => [ 0x33, ], 'DECY' => [ 0x3c, ], 'INCY' => [ 0x3d, ], 'JP' => [ 0x40, sub { my($self) = shift; my($i); if(@_ != 1) { return undef; } $i = $_[0]; if(!defined($self->{'label'}{$i})) { $i =~ s/^://o; if(!defined($self->{'label'}{$i})) { # not a defined label undef $i; } } if(defined($i)) { $i = $self->{'label'}{$i} - $self->{'pc'}; } else { $i = $_[0]; } if($i =~ m/^([+-]?\d+)$/) { $i = 0 + $1; if(($i > 31) || ($i < -31)) { warn "relative jump ($i) out of range"; return undef; } if($i < 0) { return(0x20 - $1); } else { return(0x00 + $1); } } return undef; } ], 'BRANCH' => [ 0x60, ], 'LD' => [ 0x80, sub { my($self) = shift; my($i); # print STDERR join(", ", LD, @_), "\n"; if(@_ == 1) { $_[1] = 'A'; } if(@_ != 2) { return undef; } if($_[0] =~ m/^([ML])S[BN]$/o) { # MSB/LSB aka MSN/LSN if($1 eq 'L') { $_[0] = 'A.L'; } else { $_[0] = 'A.H'; } } if($_[0] =~ m/^A\.([LH])$/o) { # A.L/A.H my($islsb) = ($1 eq 'L') ? 1 : 0; $i = $_[1]; if($i =~ s/^0x([0-9a-fA-F])$/hex($1)/e) { # print "$i looks hex\n"; } elsif($i =~ m/^\d+$/) { # print "$i looks decimal\n"; } elsif(defined($self->{'label'}{$i})) { # print "label match for $i ($self->{'label'}{$i})\n"; $i = $self->{'label'}{$i}; # print "\$i=$i\n"; # print "\$islsb=$islsb\n"; if($islsb) { $i = ($i & 0xf); } else { $i = ($i >> 4) & 0xf; } # print "\$i=$i\n"; } else { print "no label match for $i\n"; return undef; } if(($i < 0) || ($i > 0xf)) { return undef; } if($islsb) { $i |= 0x10; }; return(0x20 | $i); } elsif($_[0] eq 'A') { if(!defined($ld_arg{$_[1]})) { return undef; } return(0x40 | $ld_arg{$_[1]}); } elsif($_[1] eq 'A') { if(!defined($ld_arg{$_[0]})) { return undef; } return(0x00 | $ld_arg{$_[0]}); } return undef; } ], ); $op{'JR'} = $op{'JP'}; sub pass { my($self, $ifh, $ofh, $passnum) = @_; # passnum=0 for plain parsing pass to populate label values # passnum=1 for actual pass to assemble my($line, $oline, $opcd); if($passnum == 0) { delete($self->{'label'}); delete($self->{'binary'}); delete($self->{'ENTRY'}); delete($self->{'LUT'}); } seek($ifh, 0, 0); # rewind $self->{'pc'} = 0; $self->{'line_number'} = 0; while(defined($line = <$ifh>)) { $self->{'line_number'}++; $line =~ s/\s+$//so; $oline = $line; $line =~ s/;.*//o; $line =~ s/^\s+//o; @_ = split(/[\s,]+/, $line); undef($opcd); if(@_ > 0) { if( ($_[0] =~ s/^://o) || ($_[0] =~ s/:$//o) ) { if($passnum == 0) { if(defined($self->{'label'}{$_[0]})) { die "label redefinition for \"$_[0]\" in line $self->{'line_number'}"; } $self->{'label'}{$_[0]} = $self->{'pc'}; } shift(@_); } if(@_ > 0) { if($passnum == 1) { if((@_ == 3) && ($_[1] eq '=')) { # convert this = that to LD $_[1] = $_[0]; $_[0] = 'LD'; } elsif((@_ == 3) && ($_[1] eq '+=')) { # convert this += that to ADDER8 or ADDER16 if($_[0] eq 'A') { @_ = ('ADDER8', $_[2]); } elsif($_[2] eq 'X') { @_ = ('ADDER16', $_[0]); } } elsif((@_ == 3) && ($_[1] eq '-=')) { # convert this -= that to ADDER8 or ADDER16 if($_[0] eq 'A') { @_ = ('SUB8', $_[2]); } elsif($_[2] eq 'X') { @_ = ('SUB16', $_[0]); } } elsif((@_ == 1) && ($_[0] =~ m/^(B((SET)|(CLR)))([1-4])$/oi)) { # convert BSETn or BCLRn to BSET n-1 or BCLR n-1 $_[0] = $1; $_[1] = $5 - 1; } $op = "\U$_[0]"; if(!defined($op{$op})) { die "unknown instruction: $op in line $self->{'line_number'}"; } shift(@_); $op = $op{$op}; $sub = $op->[1]; if(defined($sub)) { $opcd = &$sub($self, @_); } else { $opcd = 0; } if(!defined($opcd)) { die "bad argument(s) in line $self->{'line_number'}"; } $opcd |= $op->[0]; } $self->{'pc'}++; } } else { if($passnum == 0) { if($oline =~ m/^;LUT; (.*)/o) { my($entry, $label) = split(/\s+/, $1); $entry =~ s/^0x//o; $self->{'LUT'}[hex($entry)] = $label; } if($oline =~ m/^;ENTRY; (.*)/o) { my($id, $label) = split(/\s+/, $1); $self->{'ENTRY'}{$id} = $label; } } } if($passnum == 1) { if(defined($opcd)) { $self->{'binary'} .= chr($opcd); printf $ofh ("/* 0x%02x */ 0x%02x%s /* %-*s */\n", $self->{'pc'} - 1, $opcd, ( ( ($self->{'last pc'} < 0xff) || ($self->{'last pc'} != $self->{'pc'} - 1) ) ? ',' : '' ), $self->{'pagewidth'} - 23, $oline ); } else { if($oline ne '') { print $ofh " /* $oline */\n"; } else { print $ofh "\n"; } } } } if($passnum == 0) { $self->{'last pc'} = $self->{'pc'} - 1; } if($passnum == 1) { while($self->{'pc'} < 0xff) { printf $ofh ("/* 0x%02x */ 0,\n", $self->{'pc'} ); $self->{'pc'}++; } if($self->{'pc'} < 0x100) { printf $ofh ("/* 0x%02x */ 0\n", $self->{'pc'} ); $self->{'pc'}++; } } } } # package DTC_as use Getopt::Std; %opt = ( 't' => 'unsigned char', ); # -t type of arrays (defaults to unsigned char) # -l lookup table array name (no table generated if not provided) # -d DTC code array name (naked elements if not provided) # -i input filename (trailing argument if not provided) # -o output filename (stdout if not provided) getopts('l:d:i:o:t:b', \%opt); if(defined($opt{'i'})) { $infile = $opt{'i'}; } else { $infile = shift; } if(!open(IN, '<', $infile)) { die "$infile: $!"; } if($opt{'b'}) { if(!defined($opt{'o'})) { die "binary format requires -o"; } if(!open(OUT, '>&', *STDOUT)) { die "dup stdout: $!"; } open(STDOUT, '>&', *STDERR); } else { if(defined($opt{'o'})) { if(!open(OUT, '>', $opt{'o'})) { die "$opt{'o'}: $!"; } } else { if(!open(OUT, '>&', *STDOUT)) { die "dup stdout: $!"; } open(STDOUT, '>&', *STDERR); } } $as = new DTC_as; $as->pass(*IN, *OUT, 0); if(defined($opt{'d'})) { print OUT "$opt{'t'} $opt{'d'}", "[0x100] = {\n"; } $as->pass(*IN, *OUT, 1); if(defined($opt{'d'})) { print OUT "};\n\n"; } close(IN); if(defined($opt{'l'})) { print OUT "$opt{'t'} $opt{'l'}", "[0x40] = {\n"; # $end = @{$as->{'LUT'}}; # if($end > 0x100) { # $end = 0x100; # } for($i = 0xc0; $i < 0x100; $i++) { $label = $as->{'LUT'}[$i]; if(defined($label)) { if(defined($as->{'label'}{$label})) { printf OUT ("/* 0x%02x */ 0x%02x%s /* %s */\n", $i, $as->{'label'}{$label}, (($i < 0xff) ? ',' : ''), $label ); } else { die "label $label has not been defined"; } } else { printf OUT ("/* 0x%02x */ 0%s\n", $i, (($i < 0xff) ? ',' : ''), ); } } print OUT "};\n\n"; } close(OUT); sub DTCLOAD_COMMENT { 0; } sub DTCLOAD_ENTRY { 1; } sub DTCLOAD_LOAD { 2; } sub DTCLOAD_RUN { 3; } sub DTCLOAD_LUT_START { 4; } sub DTCLOAD_LUT { 5; } if($opt{'b'}) { open(OUT, ">", $opt{'o'}) || die "$opt{'o'}: $!"; syswrite(OUT, pack('CC', DTCLOAD_LUT_COMMENT, 3 - 1) . 'DTC'); $ref = $as->{'LUT'}; if(@$ref > 0) { for($start = 0; $start < @$ref && !defined($ref->[$start]); $start++) {} for($end = 0xff; $end >= $start && !defined($ref->[$end]); $end--) {} undef($lut); for($i = $start; $i <= $end; $i++) { if(!defined($ref->[$i])) { $lut .= "\0"; next; } $label = $ref->[$i]; if(defined($as->{'label'}{$label})) { $label = $as->{'label'}{$label}; # printf("adding LUT entry 0x%02x\n", $label); $lut .= chr($label); } else { die "label $label has not been defined"; } } if(length($lut) > 0) { syswrite(OUT, pack('CCC', DTCLOAD_LUT_START, 1 - 1, $start)); syswrite(OUT, pack('CC', DTCLOAD_LUT, length($lut) - 1) . $lut); } } while(($key, $label) = each(%{$as->{'ENTRY'}})) { # print "$key = $label\n"; if(defined($as->{'label'}{$label})) { $label = $as->{'label'}{$label}; # print "key=$key\n"; # print "label=$label\n"; syswrite(OUT, pack('CCC', DTCLOAD_ENTRY, length($key), $label) . $key); } else { die "label $label has not been defined"; } } if(length($as->{'binary'})) { # printf("DTC code size: 0x%x\n", length($as->{'binary'})); syswrite(OUT, pack('CC', DTCLOAD_LOAD , length($as->{'binary'}) - 1 ) . $as->{'binary'}); if(%{$as->{'ENTRY'}} < 1) { syswrite(OUT, pack('CCC', DTCLOAD_RUN, 1 - 1, 0x00)); } } close(OUT); } 0; openocd-0.9.0/tools/logger.pl0000644000175000017500000000162512315575362013061 00000000000000#!/usr/bin/perl # logger.pl: masks long meaningless output with pretty lines of dots # Details: 1) reads lines from STDIN and echos them on STDOUT, # 2) print a '.' to STDERR every $N lines. # 3) print a newline after a sequence of $C dots use strict; use warnings; # make sure all output gets displayed immediately $| = 1; # TODO: add -n and -c options w/ zero checks) # line and column limits my $N = 10; my $C = 72; # current line and column counters my $n = 0; my $c = 0; # read all lines from STDIN while () { # echo line to output print STDOUT $_; # echo line to console if it is important if (/(Warning|Error)/) { print STDERR "\n" if $c; print STDERR $_; $c = 0; } # only display progress every Nth step next if ++$n % $N; print STDERR "."; # wrap at column C to provide fixed-width rows of dots print STDERR "\n" unless ++$c % $C; } print STDERR "\n" if $c; openocd-0.9.0/common.mk0000644000175000017500000000045412315575360011723 00000000000000 # common flags used in openocd build AM_CPPFLAGS = -I$(top_srcdir)/src \ -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper \ -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" if INTERNAL_JIMTCL AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ -I$(top_builddir)/jimtcl endif openocd-0.9.0/README0000644000175000017500000003144512516456301010762 00000000000000Welcome to OpenOCD! =================== OpenOCD provides on-chip programming and debugging support with a layered architecture of JTAG interface and TAP support including: - (X)SVF playback to faciliate automated boundary scan and FPGA/CPLD programming; - debug target support (e.g. ARM, MIPS): single-stepping, breakpoints/watchpoints, gprof profiling, etc; - flash chip drivers (e.g. CFI, NAND, internal flash); - embedded TCL interpreter for easy scripting. Several network interfaces are available for interacting with OpenOCD: telnet, TCL, and GDB. The GDB server enables OpenOCD to function as a "remote target" for source-level debugging of embedded systems using the GNU GDB program (and the others who talk GDB protocol, e.g. IDA Pro). This README file contains an overview of the following topics: - quickstart instructions, - how to find and build more OpenOCD documentation, - list of the supported hardware, - the installation and build process, - packaging tips. ============================ Quickstart for the impatient ============================ If you have a popular board then just start OpenOCD with its config, e.g.: openocd -f board/stm32f4discovery.cfg If you are connecting a particular adapter with some specific target, you need to source both the jtag interface and the target configs, e.g.: openocd -f interface/ftdi/jtagkey2.cfg -c "transport select jtag" \ -f target/ti_calypso.cfg openocd -f interface/stlink-v2-1.cfg -c "transport select hla_swd" \ -f target/stm32l0.cfg NB: when using an FTDI-based adapter you should prefer configs in the ftdi directory; the old configs for the ft2232 are deprecated. After OpenOCD startup, connect GDB with (gdb) target extended-remote localhost:3333 ===================== OpenOCD Documentation ===================== In addition to the in-tree documentation, the latest manuals may be viewed online at the following URLs: OpenOCD User's Guide: http://openocd.org/doc/html/index.html OpenOCD Developer's Manual: http://openocd.org/doc/doxygen/html/index.html These reflect the latest development versions, so the following section introduces how to build the complete documentation from the package. For more information, refer to these documents or contact the developers by subscribing to the OpenOCD developer mailing list: openocd-devel@lists.sourceforge.net Building the OpenOCD Documentation ---------------------------------- By default the OpenOCD build process prepares documentation in the "Info format" and installs it the standard way, so that "info openocd" can access it. Additionally, the OpenOCD User's Guide can be produced in the following different formats: # If PDFVIEWER is set, this creates and views the PDF User Guide. make pdf && ${PDFVIEWER} doc/openocd.pdf # If HTMLVIEWER is set, this creates and views the HTML User Guide. make html && ${HTMLVIEWER} doc/openocd.html/index.html The OpenOCD Developer Manual contains information about the internal architecture and other details about the code: # NB! make sure doxygen is installed, type doxygen --version make doxygen && ${HTMLVIEWER} doxygen/index.html ================== Supported hardware ================== JTAG adapters ------------- AICE, ARM-JTAG-EW, ARM-USB-OCD, ARM-USB-TINY, AT91RM9200, axm0432, BCM2835, Bus Blaster, Buspirate, Chameleon, CMSIS-DAP, Cortino, DENX, Digilent JTAG-SMT2, DLC 5, DLP-USB1232H, embedded projects, eStick, FlashLINK, FlossJTAG, Flyswatter, Flyswatter2, Gateworks, Hoegl, ICDI, ICEBear, J-Link, JTAG VPI, JTAGkey, JTAGkey2, JTAG-lock-pick, KT-Link, Lisa/L, LPC1768-Stick, MiniModule, NGX, NXHX, OOCDLink, Opendous, OpenJTAG, Openmoko, OpenRD, OSBDM, Presto, Redbee, RLink, SheevaPlug devkit, Stellaris evkits, ST-LINK (SWO tracing supported), STM32-PerformanceStick, STR9-comStick, sysfsgpio, TUMPA, Turtelizer, ULINK, USB-A9260, USB-Blaster, USB-JTAG, USBprog, VPACLink, VSLLink, Wiggler, XDS100v2, Xverve. Debug targets ------------- ARM11, ARM7, ARM9, AVR32, Cortex-A, Cortex-R, Cortex-M, Feroceon/Dragonite, DSP563xx, DSP5680xx, FA526, MIPS EJTAG, NDS32, XScale, Intel Quark. Flash drivers ------------- ADUC702x, AT91SAM, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI, Marvell QSPI, Milandr, NuMicro, PIC32mx, PSoC4, SiM3x, Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood, S3C24xx, S3C6400. ================== Installing OpenOCD ================== A Note to OpenOCD Users ----------------------- If you would rather be working "with" OpenOCD rather than "on" it, your operating system or JTAG interface supplier may provide binaries for you in a convenient-enough package. Such packages may be more stable than git mainline, where bleeding-edge development takes place. These "Packagers" produce binary releases of OpenOCD after the developers produces new "release" versions of the source code. Previous versions of OpenOCD cannot be used to diagnose problems with the current release, so users are encouraged to keep in contact with their distribution package maintainers or interface vendors to ensure suitable upgrades appear regularly. Users of these binary versions of OpenOCD must contact their Packager to ask for support or newer versions of the binaries; the OpenOCD developers do not support packages directly. A Note to OpenOCD Packagers --------------------------- You are a PACKAGER of OpenOCD if you: - Sell dongles and include pre-built binaries; - Supply tools or IDEs (a development solution integrating OpenOCD); - Build packages (e.g. RPM or DEB files for a GNU/Linux distribution). As a PACKAGER, you will experience first reports of most issues. When you fix those problems for your users, your solution may help prevent hundreds (if not thousands) of other questions from other users. If something does not work for you, please work to inform the OpenOCD developers know how to improve the system or documentation to avoid future problems, and follow-up to help us ensure the issue will be fully resolved in our future releases. That said, the OpenOCD developers would also like you to follow a few suggestions: - Send patches, including config files, upstream, participate in the discussions; - Enable all the options OpenOCD supports, even those unrelated to your particular hardware; - Use "ftdi" interface adapter driver for the FTDI-based devices. As a PACKAGER, never link against the FTD2XX library, as the resulting binaries can't be legally distributed, due to the restrictions of the GPL. ================ Building OpenOCD ================ The INSTALL file contains generic instructions for running 'configure' and compiling the OpenOCD source code. That file is provided by default for all GNU autotools packages. If you are not familiar with the GNU autotools, then you should read those instructions first. The remainder of this document tries to provide some instructions for those looking for a quick-install. OpenOCD Dependencies -------------------- GCC or Clang is currently required to build OpenOCD. The developers have begun to enforce strict code warnings (-Wall, -Werror, -Wextra, and more) and use C99-specific features: inline functions, named initializers, mixing declarations with code, and other tricks. While it may be possible to use other compilers, they must be somewhat modern and could require extending support to conditionally remove GCC-specific extensions. You'll also need: - make - libtool - pkg-config >= 0.23 (or compatible) Additionally, for building from git: - autoconf >= 2.64 - automake >= 1.9 - texinfo USB-based adapters depend on libusb-1.0 and some older drivers require libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as FreeBSD's, additionally needs the corresponding .pc files. USB-Blaster, ASIX Presto, OpenJTAG and ft2232 interface adapter drivers need either one of: - libftdi: http://www.intra2net.com/en/developer/libftdi/index.php - ftd2xx: http://www.ftdichip.com/Drivers/D2XX.htm (proprietary, GPL-incompatible) CMSIS-DAP support needs HIDAPI library. Permissions delegation ---------------------- Running OpenOCD with root/administrative permissions is strongly discouraged for security reasons. For USB devices on GNU/Linux you should use the contrib/99-openocd.rules file. It probably belongs somewhere in /etc/udev/rules.d, but consult your operating system documentation to be sure. Do not forget to add yourself to the "plugdev" group. For parallel port adapters on GNU/Linux and FreeBSD please change your "ppdev" (parport* or ppi*) device node permissions accordingly. For parport adapters on Windows you need to run install_giveio.bat (it's also possible to use "ioperm" with Cygwin instead) to give ordinary users permissions for accessing the "LPT" registers directly. Compiling OpenOCD ----------------- To build OpenOCD, use the following sequence of commands: ./bootstrap (when building from the git repository) ./configure [options] make sudo make install The 'configure' step generates the Makefiles required to build OpenOCD, usually with one or more options provided to it. The first 'make' step will build OpenOCD and place the final executable in './src/'. The final (optional) step, ``make install'', places all of the files in the required location. To see the list of all the supported options, run ./configure --help Cross-compiling Options ----------------------- Cross-compiling is supported the standard autotools way, you just need to specify the cross-compiling target triplet in the --host option, e.g. for cross-building for Windows 32-bit with MinGW on Debian: ./configure --host=i686-w64-mingw32 [options] To make pkg-config work nicely for cross-compiling, you might need an additional wrapper script as described at http://www.flameeyes.eu/autotools-mythbuster/pkgconfig/cross-compiling.html This is needed to tell pkg-config where to look for the target libraries that OpenOCD depends on. Alternatively, you can specify *_CFLAGS and *_LIBS environment variables directly, see "./configure --help" for the details. Parallel Port Dongles --------------------- If you want to access the parallel port using the PPDEV interface you have to specify both --enable-parport AND --enable-parport-ppdev, since the the later option is an option to the parport driver. The same is true for the --enable-parport-giveio option, you have to use both the --enable-parport AND the --enable-parport-giveio option if you want to use giveio instead of ioperm parallel port access method. Using FTDI's FTD2XX ------------------- The (closed source) FTDICHIP.COM solution is faster than libftdi on Windows. That is the motivation for supporting it even though its licensing restricts it to non-redistributable OpenOCD binaries, and it is not available for all operating systems used with OpenOCD. You may, however, build such copies for personal use. The FTDICHIP drivers come as either a (win32) ZIP file, or a (Linux) TAR.GZ file. You must unpack them ``some where'' convenient. As of this writing FTDICHIP does not supply means to install these files "in an appropriate place." You should use the following ./configure options to make use of FTD2XX: --with-ftd2xx-win32-zipdir Where (CYGWIN/MINGW) the zip file from ftdichip.com was unpacked --with-ftd2xx-linux-tardir Where (Linux/Unix) the tar file from ftdichip.com was unpacked --with-ftd2xx-lib=(static|shared) Use static or shared ftd2xx libs (default is static) Remember, this library is binary-only, while OpenOCD is licenced according to GNU GPLv2 without any exceptions. That means that _distributing_ copies of OpenOCD built with the FTDI code would violate the OpenOCD licensing terms. Note that on Linux there is no good reason to use these FTDI binaries; they are no faster (on Linux) than libftdi, and cause licensing issues. ========================== Obtaining OpenOCD From GIT ========================== You can download the current GIT version with a GIT client of your choice from the main repository: git://git.code.sf.net/p/openocd/code You may prefer to use a mirror: http://repo.or.cz/r/openocd.git git://repo.or.cz/openocd.git Using the GIT command line client, you might use the following command to set up a local copy of the current repository (make sure there is no directory called "openocd" in the current directory): git clone git://git.code.sf.net/p/openocd/code openocd Then you can update that at your convenience using git pull There is also a gitweb interface, which you can use either to browse the repository or to download arbitrary snapshots using HTTP: http://repo.or.cz/w/openocd.git Snapshots are compressed tarballs of the source tree, about 1.3 MBytes each at this writing. openocd-0.9.0/ltmain.sh0000755000175000017500000105017112526201642011720 00000000000000 # libtool (GNU libtool) 2.4 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4 TIMESTAMP="" package_revision=1.3293 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${EGREP="grep -E"} : ${FGREP="grep -F"} : ${GREP="grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_apped perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 openocd-0.9.0/configure0000755000175000017500000206133112526201644012007 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for openocd 0.9.0. # # Report bugs to >. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and OpenOCD Mailing $0: List about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='openocd' PACKAGE_TARNAME='openocd' PACKAGE_VERSION='0.9.0' PACKAGE_STRING='openocd 0.9.0' PACKAGE_BUGREPORT='OpenOCD Mailing List ' PACKAGE_URL='' ac_unique_file="src/openocd.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" enable_option_checking=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS INTERNAL_JIMTCL_FALSE INTERNAL_JIMTCL_TRUE MINIDRIVER_DUMMY_FALSE MINIDRIVER_DUMMY_TRUE MINIDRIVER_FALSE MINIDRIVER_TRUE BITQ_FALSE BITQ_TRUE IS_DARWIN_FALSE IS_DARWIN_TRUE IS_WIN32_FALSE IS_WIN32_TRUE IS_MINGW_FALSE IS_MINGW_TRUE IS_CYGWIN_FALSE IS_CYGWIN_TRUE USE_LIBUSB1_FALSE USE_LIBUSB1_TRUE USE_LIBUSB0_FALSE USE_LIBUSB0_TRUE SYSFSGPIO_FALSE SYSFSGPIO_TRUE BUSPIRATE_FALSE BUSPIRATE_TRUE REMOTE_BITBANG_FALSE REMOTE_BITBANG_TRUE OOCD_TRACE_FALSE OOCD_TRACE_TRUE OPENJTAG_FALSE OPENJTAG_TRUE PRESTO_DRIVER_FALSE PRESTO_DRIVER_TRUE PRESTO_LIBFTDI_FALSE PRESTO_LIBFTDI_TRUE GW16012_FALSE GW16012_TRUE AMTJTAGACCEL_FALSE AMTJTAGACCEL_TRUE USB_BLASTER_DRIVER_FALSE USB_BLASTER_DRIVER_TRUE JTAG_VPI_FALSE JTAG_VPI_TRUE USB_BLASTER_FTD2XX_FALSE USB_BLASTER_FTD2XX_TRUE USB_BLASTER_LIBFTDI_FALSE USB_BLASTER_LIBFTDI_TRUE FT2232_DRIVER_FALSE FT2232_DRIVER_TRUE FT2232_LIBFTDI_FALSE FT2232_LIBFTDI_TRUE BITBANG_FALSE BITBANG_TRUE BCM2835GPIO_FALSE BCM2835GPIO_TRUE AT91RM9200_FALSE AT91RM9200_TRUE IOUTIL_FALSE IOUTIL_TRUE ZY1000_MASTER_FALSE ZY1000_MASTER_TRUE ZY1000_FALSE ZY1000_TRUE EP93XX_FALSE EP93XX_TRUE GIVEIO_FALSE GIVEIO_TRUE DUMMY_FALSE DUMMY_TRUE PARPORT_FALSE PARPORT_TRUE RELEASE_FALSE RELEASE_TRUE HLADAPTER_FALSE HLADAPTER_TRUE CMSIS_DAP_FALSE CMSIS_DAP_TRUE ARMJTAGEW_FALSE ARMJTAGEW_TRUE RLINK_FALSE RLINK_TRUE USBPROG_FALSE USBPROG_TRUE AICE_FALSE AICE_TRUE OPENDOUS_FALSE OPENDOUS_TRUE OSBDM_FALSE OSBDM_TRUE JLINK_FALSE JLINK_TRUE VSLLINK_FALSE VSLLINK_TRUE USB_BLASTER_2_FALSE USB_BLASTER_2_TRUE ULINK_FALSE ULINK_TRUE HLADAPTER_ICDI_FALSE HLADAPTER_ICDI_TRUE HLADAPTER_STLINK_FALSE HLADAPTER_STLINK_TRUE FTDI_FALSE FTDI_TRUE HIDAPI_LIBS HIDAPI_CFLAGS LIBUSB0_LIBS LIBUSB0_CFLAGS LIBUSB1_LIBS LIBUSB1_CFLAGS LIBFTDI_LIBS LIBFTDI_CFLAGS subdirs doxygen_as_pdf doxygen_as_html LIBTOOL_DEPS CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG RANLIB am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM MAKEINFO target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_assert with_ftd2xx with_ftd2xx_win32_zipdir with_ftd2xx_linux_tardir with_ftd2xx_lib enable_doxygen_html enable_doxygen_pdf enable_gccwarnings enable_wextra enable_werror enable_verbose enable_verbose_jtag_io enable_verbose_usb_io enable_verbose_usb_comms enable_malloc_logging enable_dummy enable_ftdi enable_stlink enable_ti_icdi enable_ulink enable_usb_blaster_2 enable_vsllink enable_jlink enable_osbdm enable_opendous enable_aice enable_usbprog enable_rlink enable_armjtagew enable_cmsis_dap enable_parport enable_parport_ppdev enable_parport_giveio enable_ft2232_libftdi enable_ft2232_ftd2xx enable_legacy_ft2232_libftdi enable_legacy_ft2232_ftd2xx enable_jtag_vpi enable_usb_blaster_libftdi enable_usb_blaster_ftd2xx enable_amtjtagaccel enable_zy1000_master enable_zy1000 enable_ioutil enable_ep93xx enable_at91rm9200 enable_bcm2835gpio enable_gw16012 enable_presto_libftdi enable_presto_ftd2xx enable_openjtag_ftd2xx enable_openjtag_ftdi enable_oocd_trace enable_buspirate enable_sysfsgpio enable_minidriver_dummy enable_internal_jimtcl enable_remote_bitbang ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR CPP LIBFTDI_CFLAGS LIBFTDI_LIBS LIBUSB1_CFLAGS LIBUSB1_LIBS LIBUSB0_CFLAGS LIBUSB0_LIBS HIDAPI_CFLAGS HIDAPI_LIBS' ac_subdirs_all='jimtcl' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures openocd 0.9.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/openocd] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of openocd 0.9.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-assert turn off assertions --disable-doxygen-html Disable building Doxygen manual as HTML. --enable-doxygen-pdf Enable building Doxygen manual as PDF. --disable-gccwarnings Disable compiler warnings --disable-wextra Disable extra compiler warnings --disable-werror Do not treat warnings as errors --enable-verbose Enable verbose JTAG I/O messages (for debugging). --enable-verbose-jtag-io Enable verbose JTAG I/O messages (for debugging). --enable-verbose-usb-io Enable verbose USB I/O messages (for debugging) --enable-verbose-usb-comms Enable verbose USB communication messages (for debugging) --enable-malloc-logging Include free space in logging messages (requires malloc.h). --enable-dummy Enable building the dummy port driver --enable-ftdi Enable building support for the MPSSE mode of FTDI based devices (default is auto) --enable-stlink Enable building support for the ST-Link JTAG Programmer (default is auto) --enable-ti-icdi Enable building support for the TI ICDI JTAG Programmer (default is auto) --enable-ulink Enable building support for the Keil ULINK JTAG Programmer (default is auto) --enable-usb-blaster-2 Enable building support for the Altera USB-Blaster II Compatible (default is auto) --enable-vsllink Enable building support for the Versaloon-Link JTAG Programmer (default is auto) --enable-jlink Enable building support for the Segger J-Link JTAG Programmer (default is auto) --enable-osbdm Enable building support for the OSBDM (JTAG only) Programmer (default is auto) --enable-opendous Enable building support for the eStick/opendous JTAG Programmer (default is auto) --enable-aice Enable building support for the Andes JTAG Programmer (default is auto) --enable-usbprog Enable building support for the USBProg JTAG Programmer (default is auto) --enable-rlink Enable building support for the Raisonance RLink JTAG Programmer (default is auto) --enable-armjtagew Enable building support for the Olimex ARM-JTAG-EW Programmer (default is auto) --enable-cmsis-dap Enable building support for the CMSIS-DAP Compliant Debugger (default is auto) --enable-parport Enable building the pc parallel port driver --disable-parport-ppdev Disable use of ppdev (/dev/parportN) for parport (for x86 only) --enable-parport-giveio Enable use of giveio for parport (for CygWin only) --enable-legacy-ft2232_libftdi (DEPRECATED) Enable building support for FT2232 based devices using the libftdi library --enable-legacy-ft2232_ftd2xx (DEPRECATED) Enable building support for FT2232 based devices using the D2XX library from ftdichip.com --enable-jtag_vpi Enable building support for JTAG VPI --enable-usb_blaster_libftdi Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX --enable-usb_blaster_ftd2xx Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com --enable-amtjtagaccel Enable building the Amontec JTAG-Accelerator driver --enable-zy1000-master Use ZY1000 JTAG master registers --enable-zy1000 Enable ZY1000 interface --enable-ioutil Enable ioutil functions - useful for standalone OpenOCD implementations --enable-ep93xx Enable building support for EP93xx based SBCs --enable-at91rm9200 Enable building support for AT91RM9200 based SBCs --enable-bcm2835gpio Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi) --enable-gw16012 Enable building support for the Gateworks GW16012 JTAG Programmer --enable-presto_libftdi Enable building support for ASIX Presto Programmer using the libftdi driver --enable-presto_ftd2xx Enable building support for ASIX Presto Programmer using the FTD2XX driver --enable-openjtag_ftd2xx Enable building support for the OpenJTAG Programmer with ftd2xx driver --enable-openjtag_ftdi Enable building support for the OpenJTAG Programmer with ftdi driver --enable-oocd_trace Enable building support for some prototype OpenOCD+trace ETM capture hardware --enable-buspirate Enable building support for the Buspirate --enable-sysfsgpio Enable building support for programming driven via sysfs gpios. --enable-minidriver-dummy Enable the dummy minidriver. --disable-internal-jimtcl Disable building internal jimtcl --enable-remote-bitbang Enable building support for the Remote Bitbang jtag driver Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-ftd2xx= This option has been removed. --with-ftd2xx-win32-zipdir Where (CYGWIN/MINGW) the zip file from ftdichip.com was unpacked (default=search) --with-ftd2xx-linux-tardir Where (Linux/Unix) the tar file from ftdichip.com was unpacked (default=search) --with-ftd2xx-lib Use static or shared ftd2xx libs (default=static) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path CPP C preprocessor LIBFTDI_CFLAGS C compiler flags for LIBFTDI, overriding pkg-config LIBFTDI_LIBS linker flags for LIBFTDI, overriding pkg-config LIBUSB1_CFLAGS C compiler flags for LIBUSB1, overriding pkg-config LIBUSB1_LIBS linker flags for LIBUSB1, overriding pkg-config LIBUSB0_CFLAGS C compiler flags for LIBUSB0, overriding pkg-config LIBUSB0_LIBS linker flags for LIBUSB0, overriding pkg-config HIDAPI_CFLAGS C compiler flags for HIDAPI, overriding pkg-config HIDAPI_LIBS linker flags for HIDAPI, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to >. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF openocd configure 0.9.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------------------------------------------- ## ## Report this to OpenOCD Mailing List ## ## ------------------------------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by openocd $as_me 0.9.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # check for makeinfo before calling AM_INIT_AUTOMAKE # Extract the first word of "makeinfo", so it can be a program name with args. set dummy makeinfo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MAKEINFO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MAKEINFO"; then ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKEINFO="makeinfo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MAKEINFO=$ac_cv_prog_MAKEINFO if test -n "$MAKEINFO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 $as_echo "$MAKEINFO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$MAKEINFO" = "x"; then MAKEINFO='echo makeinfo missing; true' { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Info documentation will not be built." >&5 $as_echo "$as_me: WARNING: Info documentation will not be built." >&2;} fi am__api_version='1.13' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='openocd' VERSION='0.9.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' ac_config_headers="$ac_config_headers config.h" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : fi if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.23 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=no fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4' macro_revision='1.3293' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' lt_prog_compiler_pic='-Xcompiler -fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi # Handle Gentoo/FreeBSD as it was Linux case $host_vendor in gentoo) version_type=linux ;; *) version_type=freebsd-$objformat ;; esac case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; linux) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' need_lib_prefix=no need_version=no ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 $as_echo_n "checking for unsigned long long int... " >&6; } if ${ac_cv_type_unsigned_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_type_unsigned_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63; int main () { /* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else ac_cv_type_unsigned_long_long_int=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 $as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } if test $ac_cv_type_unsigned_long_long_int = yes; then $as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 $as_echo_n "checking for long long int... " >&6; } if ${ac_cv_type_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_type_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int if test $ac_cv_type_long_long_int = yes; then if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef LLONG_MAX # define HALF \ (1LL << (sizeof (long long int) * CHAR_BIT - 2)) # define LLONG_MAX (HALF - 1 + HALF) #endif int main () { long long int n = 1; int i; for (i = 0; ; i++) { long long int m = n << i; if (m >> i != n) return 1; if (LLONG_MAX / 2 < m) break; } return 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_type_long_long_int=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 $as_echo "$ac_cv_type_long_long_int" >&6; } if test $ac_cv_type_long_long_int = yes; then $as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ioperm" >&5 $as_echo_n "checking for library containing ioperm... " >&6; } if ${ac_cv_search_ioperm+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ioperm (); int main () { return ioperm (); ; return 0; } _ACEOF for ac_lib in '' ioperm; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ioperm=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ioperm+:} false; then : break fi done if ${ac_cv_search_ioperm+:} false; then : else ac_cv_search_ioperm=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ioperm" >&5 $as_echo "$ac_cv_search_ioperm" >&6; } ac_res=$ac_cv_search_ioperm if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi for ac_header in sys/socket.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" if test "x$ac_cv_header_sys_socket_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SOCKET_H 1 _ACEOF fi done for ac_header in arpa/inet.h do : ac_fn_c_check_header_compile "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "#include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif " if test "x$ac_cv_header_arpa_inet_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ARPA_INET_H 1 _ACEOF fi done for ac_header in elf.h do : ac_fn_c_check_header_mongrel "$LINENO" "elf.h" "ac_cv_header_elf_h" "$ac_includes_default" if test "x$ac_cv_header_elf_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ELF_H 1 _ACEOF fi done for ac_header in dirent.h do : ac_fn_c_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" if test "x$ac_cv_header_dirent_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DIRENT_H 1 _ACEOF fi done for ac_header in fcntl.h do : ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" if test "x$ac_cv_header_fcntl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FCNTL_H 1 _ACEOF fi done for ac_header in ifaddrs.h do : ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "#include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif " if test "x$ac_cv_header_ifaddrs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_IFADDRS_H 1 _ACEOF fi done for ac_header in malloc.h do : ac_fn_c_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" if test "x$ac_cv_header_malloc_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MALLOC_H 1 _ACEOF fi done for ac_header in netdb.h do : ac_fn_c_check_header_mongrel "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" if test "x$ac_cv_header_netdb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETDB_H 1 _ACEOF fi done for ac_header in netinet/in.h do : ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "#include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif " if test "x$ac_cv_header_netinet_in_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_IN_H 1 _ACEOF fi done for ac_header in netinet/tcp.h do : ac_fn_c_check_header_compile "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" "#include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif " if test "x$ac_cv_header_netinet_tcp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_TCP_H 1 _ACEOF fi done for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF fi done for ac_header in strings.h do : ac_fn_c_check_header_mongrel "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" if test "x$ac_cv_header_strings_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRINGS_H 1 _ACEOF fi done for ac_header in sys/ioctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ioctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IOCTL_H 1 _ACEOF fi done for ac_header in sys/param.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" if test "x$ac_cv_header_sys_param_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_PARAM_H 1 _ACEOF fi done for ac_header in sys/poll.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$ac_includes_default" if test "x$ac_cv_header_sys_poll_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_POLL_H 1 _ACEOF fi done for ac_header in sys/select.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" if test "x$ac_cv_header_sys_select_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SELECT_H 1 _ACEOF fi done for ac_header in sys/stat.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stat_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_STAT_H 1 _ACEOF fi done for ac_header in sys/time.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TIME_H 1 _ACEOF fi done for ac_header in sys/types.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TYPES_H 1 _ACEOF fi done for ac_header in unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNISTD_H 1 _ACEOF fi done for ac_header in net/if.h do : ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" "#include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif " if test "x$ac_cv_header_net_if_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NET_IF_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5 $as_echo_n "checking whether to enable assertions... " >&6; } # Check whether --enable-assert was given. if test "${enable_assert+set}" = set; then : enableval=$enable_assert; ac_enable_assert=$enableval if test "x$enableval" = xno; then : $as_echo "#define NDEBUG 1" >>confdefs.h elif test "x$enableval" != xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5 $as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;} ac_enable_assert=yes fi else ac_enable_assert=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5 $as_echo "$ac_enable_assert" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac for ac_func in strndup do : ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" if test "x$ac_cv_func_strndup" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRNDUP 1 _ACEOF fi done for ac_func in strnlen do : ac_fn_c_check_func "$LINENO" "strnlen" "ac_cv_func_strnlen" if test "x$ac_cv_func_strnlen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRNLEN 1 _ACEOF fi done for ac_func in gettimeofday do : ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETTIMEOFDAY 1 _ACEOF fi done for ac_func in usleep do : ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" if test "x$ac_cv_func_usleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_USLEEP 1 _ACEOF fi done for ac_func in vasprintf do : ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" if test "x$ac_cv_func_vasprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VASPRINTF 1 _ACEOF fi done build_bitbang=no build_bitq=no is_cygwin=no is_mingw=no is_win32=no is_darwin=no # guess-rev.sh only exists in the repository, not in the released archives { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build a release" >&5 $as_echo_n "checking whether to build a release... " >&6; } if test -x $srcdir/guess-rev.sh ; then build_release=no else build_release=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_release" >&5 $as_echo "$build_release" >&6; } # Check whether --with-ftd2xx was given. if test "${with_ftd2xx+set}" = set; then : withval=$with_ftd2xx; # Option Given. cat << __EOF__ The option: --with-ftd2xx= has been removed. On Linux, the new option is: --with-ftd2xx-linux-tardir=/path/to/files Where is the path the the directory where the "tar.gz" file from FTDICHIP.COM was unpacked, for example: --with-ftd2xx-linux-tardir=${HOME}/libftd2xx0.4.16 On Cygwin/MingW32, the new option is: --with-ftd2xx-win32-zipdir=/path/to/files Where is the path to the directory where the "zip" file from FTDICHIP.COM was unpacked, for example: --with-ftd2xx-win32-zipdir=${HOME}/ftd2xx.cdm.files __EOF__ as_fn_error $? "Sorry Cannot continue" "$LINENO" 5 else true fi # Adapter drivers # 1st column -- configure option # 2nd column -- description # 3rd column -- symbol used for both config.h and automake #======================================== # FTD2XXX support comes in 4 forms. # (1) win32 - via a zip file # (2) linux - via a tar file # (3) linux/cygwin/mingw - via libftdi # (4) darwin - installed under /usr/local # # In case (1) and (2) we need to know where the package was unpacked. # Check whether --with-ftd2xx-win32-zipdir was given. if test "${with_ftd2xx_win32_zipdir+set}" = set; then : withval=$with_ftd2xx_win32_zipdir; # option present if test -d $with_ftd2xx_win32_zipdir then with_ftd2xx_win32_zipdir=`cd $with_ftd2xx_win32_zipdir && pwd` { $as_echo "$as_me:${as_lineno-$LINENO}: Using: ftdichip.com library: $with_ftd2xx_win32_zipdir" >&5 $as_echo "$as_me: Using: ftdichip.com library: $with_ftd2xx_win32_zipdir" >&6;} else as_fn_error $? "Parameter to --with-ftd2xx-win32-zipdir is not a dir: $with_ftd2xx_win32_zipdir" "$LINENO" 5 fi else true fi # Check whether --with-ftd2xx-linux-tardir was given. if test "${with_ftd2xx_linux_tardir+set}" = set; then : withval=$with_ftd2xx_linux_tardir; # Option present if test $is_win32 = yes ; then as_fn_error $? "The option: --with-ftd2xx-linux-tardir is only usable on linux" "$LINENO" 5 fi if test -d $with_ftd2xx_linux_tardir then with_ftd2xx_linux_tardir=`cd $with_ftd2xx_linux_tardir && pwd` { $as_echo "$as_me:${as_lineno-$LINENO}: Using: ftdichip.com library: $with_ftd2xx_linux_tardir" >&5 $as_echo "$as_me: Using: ftdichip.com library: $with_ftd2xx_linux_tardir" >&6;} else as_fn_error $? "Parameter to --with-ftd2xx-linux-tardir is not a dir: $with_ftd2xx_linux_tardir" "$LINENO" 5 fi else true fi # Check whether --with-ftd2xx-lib was given. if test "${with_ftd2xx_lib+set}" = set; then : withval=$with_ftd2xx_lib; case "$withval" in static) with_ftd2xx_lib=$withval ;; shared) with_ftd2xx_lib=$withval ;; *) as_fn_error $? "Option: --with-ftd2xx-lib=static or --with-ftd2xx-lib=shared not, $withval" "$LINENO" 5 ;; esac else # Default is static - it is simpler :-( with_ftd2xx_lib=static fi # Check whether --enable-doxygen-html was given. if test "${enable_doxygen_html+set}" = set; then : enableval=$enable_doxygen_html; doxygen_as_html=$enableval else doxygen_as_html=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Doxygen as HTML" >&5 $as_echo_n "checking whether to build Doxygen as HTML... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doxygen_as_html" >&5 $as_echo "$doxygen_as_html" >&6; } # Check whether --enable-doxygen-pdf was given. if test "${enable_doxygen_pdf+set}" = set; then : enableval=$enable_doxygen_pdf; doxygen_as_pdf=$enableval else doxygen_as_pdf=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Doxygen as PDF" >&5 $as_echo_n "checking whether to build Doxygen as PDF... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doxygen_as_pdf" >&5 $as_echo "$doxygen_as_pdf" >&6; } # Check whether --enable-gccwarnings was given. if test "${enable_gccwarnings+set}" = set; then : enableval=$enable_gccwarnings; gcc_warnings=$enableval else gcc_warnings=yes fi # Check whether --enable-wextra was given. if test "${enable_wextra+set}" = set; then : enableval=$enable_wextra; gcc_wextra=$enableval else gcc_wextra=$gcc_warnings fi # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; gcc_werror=$enableval else gcc_werror=$gcc_warnings fi # set default verbose options, overridden by following options debug_jtag_io=no debug_usb_io=no debug_usb_comms=no # Check whether --enable-verbose was given. if test "${enable_verbose+set}" = set; then : enableval=$enable_verbose; debug_jtag_io=$enableval debug_usb_io=$enableval debug_usb_comms=$enableval fi # Check whether --enable-verbose_jtag_io was given. if test "${enable_verbose_jtag_io+set}" = set; then : enableval=$enable_verbose_jtag_io; debug_jtag_io=$enableval fi # Check whether --enable-verbose_usb_io was given. if test "${enable_verbose_usb_io+set}" = set; then : enableval=$enable_verbose_usb_io; debug_usb_io=$enableval fi # Check whether --enable-verbose_usb_comms was given. if test "${enable_verbose_usb_comms+set}" = set; then : enableval=$enable_verbose_usb_comms; debug_usb_comms=$enableval fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable verbose JTAG I/O messages" >&5 $as_echo_n "checking whether to enable verbose JTAG I/O messages... " >&6; }; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug_jtag_io" >&5 $as_echo "$debug_jtag_io" >&6; } if test $debug_jtag_io = yes; then $as_echo "#define _DEBUG_JTAG_IO_ 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable verbose USB I/O messages" >&5 $as_echo_n "checking whether to enable verbose USB I/O messages... " >&6; }; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug_usb_io" >&5 $as_echo "$debug_usb_io" >&6; } if test $debug_usb_io = yes; then $as_echo "#define _DEBUG_USB_IO_ 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable verbose USB communication messages" >&5 $as_echo_n "checking whether to enable verbose USB communication messages... " >&6; }; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug_usb_comms" >&5 $as_echo "$debug_usb_comms" >&6; } if test $debug_usb_comms = yes; then $as_echo "#define _DEBUG_USB_COMMS_ 1" >>confdefs.h fi debug_malloc=no # Check whether --enable-malloc_logging was given. if test "${enable_malloc_logging+set}" = set; then : enableval=$enable_malloc_logging; debug_malloc=$enableval fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable malloc free space logging" >&5 $as_echo_n "checking whether to enable malloc free space logging... " >&6; }; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug_malloc" >&5 $as_echo "$debug_malloc" >&6; } if test $debug_malloc = yes; then $as_echo "#define _DEBUG_FREE_SPACE_ 1" >>confdefs.h fi # Check whether --enable-dummy was given. if test "${enable_dummy+set}" = set; then : enableval=$enable_dummy; build_dummy=$enableval else build_dummy=no fi # Check whether --enable-ftdi was given. if test "${enable_ftdi+set}" = set; then : enableval=$enable_ftdi; else enable_ftdi=auto fi # Check whether --enable-stlink was given. if test "${enable_stlink+set}" = set; then : enableval=$enable_stlink; else enable_stlink=auto fi # Check whether --enable-ti-icdi was given. if test "${enable_ti_icdi+set}" = set; then : enableval=$enable_ti_icdi; else enable_ti_icdi=auto fi # Check whether --enable-ulink was given. if test "${enable_ulink+set}" = set; then : enableval=$enable_ulink; else enable_ulink=auto fi # Check whether --enable-usb-blaster-2 was given. if test "${enable_usb_blaster_2+set}" = set; then : enableval=$enable_usb_blaster_2; else enable_usb_blaster_2=auto fi # Check whether --enable-vsllink was given. if test "${enable_vsllink+set}" = set; then : enableval=$enable_vsllink; else enable_vsllink=auto fi # Check whether --enable-jlink was given. if test "${enable_jlink+set}" = set; then : enableval=$enable_jlink; else enable_jlink=auto fi # Check whether --enable-osbdm was given. if test "${enable_osbdm+set}" = set; then : enableval=$enable_osbdm; else enable_osbdm=auto fi # Check whether --enable-opendous was given. if test "${enable_opendous+set}" = set; then : enableval=$enable_opendous; else enable_opendous=auto fi # Check whether --enable-aice was given. if test "${enable_aice+set}" = set; then : enableval=$enable_aice; else enable_aice=auto fi # Check whether --enable-usbprog was given. if test "${enable_usbprog+set}" = set; then : enableval=$enable_usbprog; else enable_usbprog=auto fi # Check whether --enable-rlink was given. if test "${enable_rlink+set}" = set; then : enableval=$enable_rlink; else enable_rlink=auto fi # Check whether --enable-armjtagew was given. if test "${enable_armjtagew+set}" = set; then : enableval=$enable_armjtagew; else enable_armjtagew=auto fi # Check whether --enable-cmsis-dap was given. if test "${enable_cmsis_dap+set}" = set; then : enableval=$enable_cmsis_dap; else enable_cmsis_dap=auto fi # Check whether --enable-parport was given. if test "${enable_parport+set}" = set; then : enableval=$enable_parport; build_parport=$enableval else build_parport=no fi # Check whether --enable-parport_ppdev was given. if test "${enable_parport_ppdev+set}" = set; then : enableval=$enable_parport_ppdev; parport_use_ppdev=$enableval else parport_use_ppdev=yes fi # Check whether --enable-parport_giveio was given. if test "${enable_parport_giveio+set}" = set; then : enableval=$enable_parport_giveio; parport_use_giveio=$enableval else parport_use_giveio= fi # Check whether --enable-ft2232_libftdi was given. if test "${enable_ft2232_libftdi+set}" = set; then : enableval=$enable_ft2232_libftdi; if test $enableval = yes; then as_fn_error $? "The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_libftdi" "$LINENO" 5 fi fi # Check whether --enable-ft2232_ftd2xx was given. if test "${enable_ft2232_ftd2xx+set}" = set; then : enableval=$enable_ft2232_ftd2xx; if test $enableval = yes; then as_fn_error $? "The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_ftd2xx" "$LINENO" 5 fi fi # Check whether --enable-legacy-ft2232_libftdi was given. if test "${enable_legacy_ft2232_libftdi+set}" = set; then : enableval=$enable_legacy_ft2232_libftdi; build_ft2232_libftdi=$enableval else build_ft2232_libftdi=no fi # Check whether --enable-legacy-ft2232_ftd2xx was given. if test "${enable_legacy_ft2232_ftd2xx+set}" = set; then : enableval=$enable_legacy_ft2232_ftd2xx; build_ft2232_ftd2xx=$enableval else build_ft2232_ftd2xx=no fi # Check whether --enable-jtag_vpi was given. if test "${enable_jtag_vpi+set}" = set; then : enableval=$enable_jtag_vpi; build_jtag_vpi=$enableval else build_jtag_vpi=no fi # Check whether --enable-usb_blaster_libftdi was given. if test "${enable_usb_blaster_libftdi+set}" = set; then : enableval=$enable_usb_blaster_libftdi; build_usb_blaster_libftdi=$enableval else build_usb_blaster_libftdi=no fi # Check whether --enable-usb_blaster_ftd2xx was given. if test "${enable_usb_blaster_ftd2xx+set}" = set; then : enableval=$enable_usb_blaster_ftd2xx; build_usb_blaster_ftd2xx=$enableval else build_usb_blaster_ftd2xx=no fi # Check whether --enable-amtjtagaccel was given. if test "${enable_amtjtagaccel+set}" = set; then : enableval=$enable_amtjtagaccel; build_amtjtagaccel=$enableval else build_amtjtagaccel=no fi # Check whether --enable-zy1000_master was given. if test "${enable_zy1000_master+set}" = set; then : enableval=$enable_zy1000_master; build_zy1000_master=$enableval else build_zy1000_master=no fi # Check whether --enable-zy1000 was given. if test "${enable_zy1000+set}" = set; then : enableval=$enable_zy1000; build_zy1000=$enableval else build_zy1000=no fi # Check whether --enable-ioutil was given. if test "${enable_ioutil+set}" = set; then : enableval=$enable_ioutil; build_ioutil=$enableval else build_ioutil=no fi case "${host_cpu}" in arm*) # Check whether --enable-ep93xx was given. if test "${enable_ep93xx+set}" = set; then : enableval=$enable_ep93xx; build_ep93xx=$enableval else build_ep93xx=no fi # Check whether --enable-at91rm9200 was given. if test "${enable_at91rm9200+set}" = set; then : enableval=$enable_at91rm9200; build_at91rm9200=$enableval else build_at91rm9200=no fi # Check whether --enable-bcm2835gpio was given. if test "${enable_bcm2835gpio+set}" = set; then : enableval=$enable_bcm2835gpio; build_bcm2835gpio=$enableval else build_bcm2835gpio=no fi ;; *) build_ep93xx=no build_at91rm9200=no build_bcm2835gpio=no ;; esac # Check whether --enable-gw16012 was given. if test "${enable_gw16012+set}" = set; then : enableval=$enable_gw16012; build_gw16012=$enableval else build_gw16012=no fi # Check whether --enable-presto_libftdi was given. if test "${enable_presto_libftdi+set}" = set; then : enableval=$enable_presto_libftdi; build_presto_libftdi=$enableval else build_presto_libftdi=no fi # Check whether --enable-presto_ftd2xx was given. if test "${enable_presto_ftd2xx+set}" = set; then : enableval=$enable_presto_ftd2xx; build_presto_ftd2xx=$enableval else build_presto_ftd2xx=no fi # Check whether --enable-openjtag_ftd2xx was given. if test "${enable_openjtag_ftd2xx+set}" = set; then : enableval=$enable_openjtag_ftd2xx; build_openjtag_ftd2xx=$enableval else build_openjtag_ftd2xx=no fi # Check whether --enable-openjtag_ftdi was given. if test "${enable_openjtag_ftdi+set}" = set; then : enableval=$enable_openjtag_ftdi; build_openjtag_ftdi=$enableval else build_openjtag_ftdi=no fi # Check whether --enable-oocd_trace was given. if test "${enable_oocd_trace+set}" = set; then : enableval=$enable_oocd_trace; build_oocd_trace=$enableval else build_oocd_trace=no fi # Check whether --enable-buspirate was given. if test "${enable_buspirate+set}" = set; then : enableval=$enable_buspirate; build_buspirate=$enableval else build_buspirate=no fi # Check whether --enable-sysfsgpio was given. if test "${enable_sysfsgpio+set}" = set; then : enableval=$enable_sysfsgpio; build_sysfsgpio=$enableval else build_sysfsgpio=no fi # Check whether --enable-minidriver_dummy was given. if test "${enable_minidriver_dummy+set}" = set; then : enableval=$enable_minidriver_dummy; build_minidriver_dummy=$enableval else build_minidriver_dummy=no fi # Check whether --enable-internal-jimtcl was given. if test "${enable_internal_jimtcl+set}" = set; then : enableval=$enable_internal_jimtcl; use_internal_jimtcl=$enableval else use_internal_jimtcl=yes fi build_minidriver=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ZY1000 minidriver" >&5 $as_echo_n "checking whether to enable ZY1000 minidriver... " >&6; } if test $build_zy1000 = yes; then if test $build_minidriver = yes; then as_fn_error $? "Multiple minidriver options have been enabled." "$LINENO" 5 fi $as_echo "#define HAVE_JTAG_MINIDRIVER_H 1" >>confdefs.h build_minidriver=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_zy1000" >&5 $as_echo "$build_zy1000" >&6; } # Check whether --enable-remote-bitbang was given. if test "${enable_remote_bitbang+set}" = set; then : enableval=$enable_remote_bitbang; build_remote_bitbang=$enableval else build_remote_bitbang=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable dummy minidriver" >&5 $as_echo_n "checking whether to enable dummy minidriver... " >&6; } if test $build_minidriver_dummy = yes; then if test $build_minidriver = yes; then as_fn_error $? "Multiple minidriver options have been enabled." "$LINENO" 5 fi build_minidriver=yes $as_echo "#define BUILD_MINIDRIVER_DUMMY 1" >>confdefs.h $as_echo "#define HAVE_JTAG_MINIDRIVER_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_minidriver_dummy" >&5 $as_echo "$build_minidriver_dummy" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether standard drivers can be built" >&5 $as_echo_n "checking whether standard drivers can be built... " >&6; } if test "$build_minidriver" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Using the minidriver disables all other drivers." >&5 $as_echo "$as_me: WARNING: Using the minidriver disables all other drivers." >&2;} sleep 2 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi case "${host_cpu}" in i?86|x86*) ;; *) if test x$parport_use_ppdev = xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --disable-parport-ppdev is not supported by the host CPU" >&5 $as_echo "$as_me: WARNING: --disable-parport-ppdev is not supported by the host CPU" >&2;} fi parport_use_ppdev=yes ;; esac case $host in *-cygwin*) is_win32=yes parport_use_ppdev=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return __MINGW32__; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : is_mingw=yes else is_mingw=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $is_mingw = yes; then $as_echo "#define IS_MINGW 1" >>confdefs.h if test x$parport_use_giveio = xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --disable-parport-giveio is not supported by MinGW32 hosts" >&5 $as_echo "$as_me: WARNING: --disable-parport-giveio is not supported by MinGW32 hosts" >&2;} fi parport_use_giveio=yes is_cygwin=no else is_cygwin=yes $as_echo "#define IS_CYGWIN 1" >>confdefs.h # sys/io.h needed under cygwin for parport access if test $build_parport = yes; then for ac_header in sys/io.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/io.h" "ac_cv_header_sys_io_h" "$ac_includes_default" if test "x$ac_cv_header_sys_io_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IO_H 1 _ACEOF else as_fn_error $? "Please install the cygwin ioperm package" "$LINENO" 5 fi done fi fi $as_echo "#define IS_WIN32 1" >>confdefs.h $as_echo "#define IS_DARWIN 0" >>confdefs.h ;; *-mingw*) is_mingw=yes is_win32=yes parport_use_ppdev=no if test x$parport_use_giveio = xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --disable-parport-giveio is not supported by MinGW32 hosts" >&5 $as_echo "$as_me: WARNING: --disable-parport-giveio is not supported by MinGW32 hosts" >&2;} fi parport_use_giveio=yes if test x$build_buspirate = xyes; then as_fn_error $? "buspirate currently not supported by MinGW32 hosts" "$LINENO" 5 fi CFLAGS="$CFLAGS -D__USE_MINGW_ANSI_STDIO" $as_echo "#define IS_MINGW 1" >>confdefs.h $as_echo "#define IS_WIN32 1" >>confdefs.h $as_echo "#define IS_DARWIN 0" >>confdefs.h ;; *darwin*) is_darwin=yes if test x$parport_use_giveio = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-parport-giveio cannot be used by Darwin hosts" >&5 $as_echo "$as_me: WARNING: --enable-parport-giveio cannot be used by Darwin hosts" >&2;} fi parport_use_giveio=no $as_echo "#define IS_CYGWIN 0" >>confdefs.h $as_echo "#define IS_WIN32 0" >>confdefs.h $as_echo "#define IS_DARWIN 1" >>confdefs.h ;; *) if test x$parport_use_giveio = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-parport-giveio cannot be used by $host hosts" >&5 $as_echo "$as_me: WARNING: --enable-parport-giveio cannot be used by $host hosts" >&2;} fi parport_use_giveio=no $as_echo "#define IS_CYGWIN 0" >>confdefs.h $as_echo "#define IS_WIN32 0" >>confdefs.h $as_echo "#define IS_DARWIN 0" >>confdefs.h ;; esac if test $is_win32 = yes; then $as_echo "#define WIN32_LEAN_AND_MEAN 1" >>confdefs.h fi if test $build_parport = yes; then build_bitbang=yes $as_echo "#define BUILD_PARPORT 1" >>confdefs.h else $as_echo "#define BUILD_PARPORT 0" >>confdefs.h fi if test $build_dummy = yes; then build_bitbang=yes $as_echo "#define BUILD_DUMMY 1" >>confdefs.h else $as_echo "#define BUILD_DUMMY 0" >>confdefs.h fi if test $build_ep93xx = yes; then build_bitbang=yes $as_echo "#define BUILD_EP93XX 1" >>confdefs.h else $as_echo "#define BUILD_EP93XX 0" >>confdefs.h fi if test $build_zy1000 = yes; then $as_echo "#define BUILD_ZY1000 1" >>confdefs.h else $as_echo "#define BUILD_ZY1000 0" >>confdefs.h fi if test $build_zy1000_master = yes; then $as_echo "#define BUILD_ZY1000_MASTER 1" >>confdefs.h else $as_echo "#define BUILD_ZY1000_MASTER 0" >>confdefs.h fi if test $build_at91rm9200 = yes; then build_bitbang=yes $as_echo "#define BUILD_AT91RM9200 1" >>confdefs.h else $as_echo "#define BUILD_AT91RM9200 0" >>confdefs.h fi if test $build_bcm2835gpio = yes; then build_bitbang=yes $as_echo "#define BUILD_BCM2835GPIO 1" >>confdefs.h else $as_echo "#define BUILD_BCM2835GPIO 0" >>confdefs.h fi if test x$parport_use_ppdev = xyes; then $as_echo "#define PARPORT_USE_PPDEV 1" >>confdefs.h else $as_echo "#define PARPORT_USE_PPDEV 0" >>confdefs.h fi if test x$parport_use_giveio = xyes; then $as_echo "#define PARPORT_USE_GIVEIO 1" >>confdefs.h else $as_echo "#define PARPORT_USE_GIVEIO 0" >>confdefs.h fi if test $build_bitbang = yes; then $as_echo "#define BUILD_BITBANG 1" >>confdefs.h else $as_echo "#define BUILD_BITBANG 0" >>confdefs.h fi if test $build_ft2232_libftdi = yes; then $as_echo "#define BUILD_FT2232_LIBFTDI 1" >>confdefs.h else $as_echo "#define BUILD_FT2232_LIBFTDI 0" >>confdefs.h fi if test $build_ft2232_ftd2xx = yes; then $as_echo "#define BUILD_FT2232_FTD2XX 1" >>confdefs.h else $as_echo "#define BUILD_FT2232_FTD2XX 0" >>confdefs.h fi if test $build_usb_blaster_libftdi = yes; then $as_echo "#define BUILD_USB_BLASTER_LIBFTDI 1" >>confdefs.h else $as_echo "#define BUILD_USB_BLASTER_LIBFTDI 0" >>confdefs.h fi if test $build_jtag_vpi = yes; then $as_echo "#define BUILD_JTAG_VPI 1" >>confdefs.h else $as_echo "#define BUILD_JTAG_VPI 0" >>confdefs.h fi if test $build_usb_blaster_ftd2xx = yes; then $as_echo "#define BUILD_USB_BLASTER_FTD2XX 1" >>confdefs.h else $as_echo "#define BUILD_USB_BLASTER_FTD2XX 0" >>confdefs.h fi if test $build_amtjtagaccel = yes; then $as_echo "#define BUILD_AMTJTAGACCEL 1" >>confdefs.h else $as_echo "#define BUILD_AMTJTAGACCEL 0" >>confdefs.h fi if test $build_gw16012 = yes; then $as_echo "#define BUILD_GW16012 1" >>confdefs.h else $as_echo "#define BUILD_GW16012 0" >>confdefs.h fi if test $build_presto_libftdi = yes; then build_bitq=yes $as_echo "#define BUILD_PRESTO_LIBFTDI 1" >>confdefs.h else $as_echo "#define BUILD_PRESTO_LIBFTDI 0" >>confdefs.h fi if test $build_presto_ftd2xx = yes; then build_bitq=yes $as_echo "#define BUILD_PRESTO_FTD2XX 1" >>confdefs.h else $as_echo "#define BUILD_PRESTO_FTD2XX 0" >>confdefs.h fi if test $build_bitq = yes; then $as_echo "#define BUILD_BITQ 1" >>confdefs.h else $as_echo "#define BUILD_BITQ 0" >>confdefs.h fi $as_echo "#define BUILD_OPENJTAG 0" >>confdefs.h $as_echo "#define BUILD_OPENJTAG_FTD2XX 0" >>confdefs.h $as_echo "#define BUILD_OPENJTAG_LIBFTDI 0" >>confdefs.h if test $build_openjtag_ftd2xx = yes; then $as_echo "#define BUILD_OPENJTAG 1" >>confdefs.h $as_echo "#define BUILD_OPENJTAG_FTD2XX 1" >>confdefs.h fi if test $build_openjtag_ftdi = yes; then $as_echo "#define BUILD_OPENJTAG 1" >>confdefs.h $as_echo "#define BUILD_OPENJTAG_LIBFTDI 1" >>confdefs.h fi if test $build_oocd_trace = yes; then $as_echo "#define BUILD_OOCD_TRACE 1" >>confdefs.h else $as_echo "#define BUILD_OOCD_TRACE 0" >>confdefs.h fi if test $build_buspirate = yes; then $as_echo "#define BUILD_BUSPIRATE 1" >>confdefs.h else $as_echo "#define BUILD_BUSPIRATE 0" >>confdefs.h fi if test $use_internal_jimtcl = yes; then if test -f "$srcdir/jimtcl/configure.ac"; then subdirs="$subdirs jimtcl" echo -e '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" --disable-install-jim "'\$'@"' > "$srcdir/jimtcl/configure.gnu" else as_fn_error $? "jimtcl not found, run git submodule init and git submodule update." "$LINENO" 5 fi fi if test $build_remote_bitbang = yes; then build_bitbang=yes $as_echo "#define BUILD_REMOTE_BITBANG 1" >>confdefs.h else $as_echo "#define BUILD_REMOTE_BITBANG 0" >>confdefs.h fi if test $build_sysfsgpio = yes; then build_bitbang=yes $as_echo "#define BUILD_SYSFSGPIO 1" >>confdefs.h else $as_echo "#define BUILD_SYSFSGPIO 0" >>confdefs.h fi #-- Deal with MingW/Cygwin FTD2XX issues if test $is_win32 = yes; then if test "${with_ftd2xx_linux_tardir+set}" = set then as_fn_error $? "The option: with_ftd2xx_linux_tardir is for LINUX only." "$LINENO" 5 fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ftd2xx.lib exists (win32)" >&5 $as_echo_n "checking for ftd2xx.lib exists (win32)... " >&6; } # if we are given a zipdir... if test "${with_ftd2xx_win32_zipdir+set}" = set then # Set the CFLAGS for "ftd2xx.h" f=$with_ftd2xx_win32_zipdir/ftd2xx.h if test ! -f $f ; then as_fn_error $? "File: $f cannot be found" "$LINENO" 5 fi CFLAGS="$CFLAGS -I$with_ftd2xx_win32_zipdir" # And calculate the LDFLAGS for the machine case "$host_cpu" in i?86|x86_32) LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/i386" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/i386/ftd2xx.lib ;; amd64|x86_64) LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/amd64" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/amd64/ftd2xx.lib ;; *) as_fn_error $? "Unknown Win32 host cpu: $host_cpu" "$LINENO" 5 ;; esac if test ! -f $f ; then as_fn_error $? "Library: $f not found" "$LINENO" 5 fi else LIBS="$LIBS -lftd2xx" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ASSUMPTION: The (win32) FTDICHIP.COM files: ftd2xx.h and ftd2xx.lib are in a proper place" >&5 $as_echo "$as_me: WARNING: ASSUMPTION: The (win32) FTDICHIP.COM files: ftd2xx.h and ftd2xx.lib are in a proper place" >&2;} fi fi fi # win32 if test $is_darwin = yes ; then if test "${with_ftd2xx_win32_zipdir+set}" = set then as_fn_error $? "The option: --with-ftd2xx-win32-zipdir is for win32 only" "$LINENO" 5 fi if test "${with_ftd2xx_linux_tardir+set}" = set then as_fn_error $? "The option: with_ftd2xx_linux_tardir is for LINUX only." "$LINENO" 5 fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libftd2xx.a (darwin)" >&5 $as_echo_n "checking for libftd2xx.a (darwin)... " >&6; } if test ! -f /usr/local/include/ftd2xx.h ; then as_fn_error $? "ftd2xx library from FTDICHIP.com seems to be missing, cannot find: /usr/local/include/ftd2xx.h" "$LINENO" 5 fi CFLAGS="$CFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lftd2xx" { $as_echo "$as_me:${as_lineno-$LINENO}: result: -L/usr/local/lib -lftd2xx" >&5 $as_echo "-L/usr/local/lib -lftd2xx" >&6; } fi fi # darwin if test $is_win32 = no && test $is_darwin = no ; then if test "${with_ftd2xx_win32_zipdir+set}" = set then as_fn_error $? "The option: --with-ftd2xx-win32-zipdir is for win32 only" "$LINENO" 5 fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then # Must be linux if test $host_os != linux-gnu && test $host_os != linux ; then as_fn_error $? "The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-ft2232-libftdi instead" "$LINENO" 5 fi # Are we given a TAR directory? if test "${with_ftd2xx_linux_tardir+set}" = set then { $as_echo "$as_me:${as_lineno-$LINENO}: checking uninstalled ftd2xx distribution" >&5 $as_echo_n "checking uninstalled ftd2xx distribution... " >&6; } # The .H file is simple.. FTD2XX_H=$with_ftd2xx_linux_tardir/ftd2xx.h if test ! -f "${FTD2XX_H}"; then as_fn_error $? "Option: --with-ftd2xx-linux-tardir appears wrong, cannot find: ${FTD2XX_H}" "$LINENO" 5 fi CFLAGS="$CFLAGS -I$with_ftd2xx_linux_tardir" if test $with_ftd2xx_lib = shared; then FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir" FTD2XX_LIB="-lftd2xx" else # Test #1 - v1.0.x case "$host_cpu" in i?86|x86_32) dir=build/i386;; amd64|x86_64) dir=build/x86_64;; *) dir=none;; esac if test -f "$with_ftd2xx_linux_tardir/$dir/libftd2xx.a"; then FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir/$dir" # Also needs -lrt FTD2XX_LIB="-lftd2xx -lrt" else # Test Number2. # Grr.. perhaps it exists as a version number? FTD2XX_LIB="$with_ftd2xx_linux_tardir/static_lib/libftd2xx.a.*.*.*" count=`ls ${FTD2XX_LIB} | wc -l` if test $count -gt 1 ; then as_fn_error $? "Multiple libftd2xx.a files found in: $with_ftd2xx_linux_tardir/static_lib sorry cannot handle this yet" "$LINENO" 5 fi if test $count -ne 1 ; then as_fn_error $? "Not found: $f, option: --with-ftd2xx-linux-tardir appears to be wrong" "$LINENO" 5 fi # Because the "-l" rules do not understand version numbers... # we will just stuff the absolute path onto the LIBS variable FTD2XX_LIB="`ls ${FTD2XX_LIB}` -lpthread" FTD2XX_LDFLAGS="" fi fi LDFLAGS="${LDFLAGS} ${FTD2XX_LDFLAGS}" LIBS="${FTD2XX_LIB} ${LIBS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${FTD2XX_LDFLAGS} ${FTD2XX_LIB}" >&5 $as_echo "${FTD2XX_LDFLAGS} ${FTD2XX_LIB}" >&6; } else ac_fn_c_check_header_mongrel "$LINENO" "ftd2xx.h" "ac_cv_header_ftd2xx_h" "$ac_includes_default" if test "x$ac_cv_header_ftd2xx_h" = xyes; then : else as_fn_error $? "You seem to be missing the FTD2xx driver header file." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing FT_GetLibraryVersion" >&5 $as_echo_n "checking for library containing FT_GetLibraryVersion... " >&6; } if ${ac_cv_search_FT_GetLibraryVersion+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char FT_GetLibraryVersion (); int main () { return FT_GetLibraryVersion (); ; return 0; } _ACEOF for ac_lib in '' ftd2xx; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -lrt -lusb-1.0 $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_FT_GetLibraryVersion=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_FT_GetLibraryVersion+:} false; then : break fi done if ${ac_cv_search_FT_GetLibraryVersion+:} false; then : else ac_cv_search_FT_GetLibraryVersion=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_FT_GetLibraryVersion" >&5 $as_echo "$ac_cv_search_FT_GetLibraryVersion" >&6; } ac_res=$ac_cv_search_FT_GetLibraryVersion if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "You appear to be missing the FTD2xx driver library." "$LINENO" 5 fi fi fi fi # linux if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then # Before we go any further - make sure we can *BUILD* and *RUN* # a simple app with the "ftd2xx.lib" file - in what ever form we where given # We should be able to compile, link and run this test program now { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ftd2xx library works" >&5 $as_echo_n "checking whether ftd2xx library works... " >&6; } # # Save the LDFLAGS for later.. LDFLAGS_SAVE=$LDFLAGS CFLAGS_SAVE=$CFLAGS _LDFLAGS=`eval echo $LDFLAGS` _CFLAGS=`eval echo $CFLAGS` LDFLAGS=$_LDFLAGS CFLAGS=$_CFLAGS if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: Skipping as we are cross-compiling" >&5 $as_echo "Skipping as we are cross-compiling" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include int main () { DWORD x; FT_GetLibraryVersion( &x ); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: Success!" >&5 $as_echo "Success!" >&6; } else as_fn_error $? "Cannot build & run test program using ftd2xx.lib" "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ftd2xx highspeed device support" >&5 $as_echo_n "checking for ftd2xx highspeed device support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include DWORD x = FT_DEVICE_4232H; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define BUILD_FT2232_HIGHSPEED 1" >>confdefs.h build_ft2232_highspeed=yes else build_ft2232_highspeed=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_ft2232_highspeed" >&5 $as_echo "$build_ft2232_highspeed" >&6; } if test $build_ft2232_highspeed = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You need a newer FTD2XX driver (version 2.04.16 or later)." >&5 $as_echo "$as_me: WARNING: You need a newer FTD2XX driver (version 2.04.16 or later)." >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ftd2xx FT232H device support" >&5 $as_echo_n "checking for ftd2xx FT232H device support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include DWORD x = FT_DEVICE_232H; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAS_ENUM_FT232H 1" >>confdefs.h has_enum_ft232h=yes else has_enum_ft232h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_enum_ft232h" >&5 $as_echo "$has_enum_ft232h" >&6; } if test $has_enum_ft232h = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You need a newer FTD2XX driver (version 2.08.12 or later)." >&5 $as_echo "$as_me: WARNING: You need a newer FTD2XX driver (version 2.08.12 or later)." >&2;} fi LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE fi if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes -o \ $build_openjtag_ftdi = yes -o $build_presto_libftdi = yes; then # we can have libftdi or libftdi1, so check it and use the latest one pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFTDI" >&5 $as_echo_n "checking for LIBFTDI... " >&6; } if test -n "$LIBFTDI_CFLAGS"; then pkg_cv_LIBFTDI_CFLAGS="$LIBFTDI_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libftdi1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libftdi1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBFTDI_CFLAGS=`$PKG_CONFIG --cflags "libftdi1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBFTDI_LIBS"; then pkg_cv_LIBFTDI_LIBS="$LIBFTDI_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libftdi1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libftdi1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBFTDI_LIBS=`$PKG_CONFIG --libs "libftdi1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBFTDI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libftdi1" 2>&1` else LIBFTDI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libftdi1" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBFTDI_PKG_ERRORS" >&5 use_libftdi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_libftdi=no else LIBFTDI_CFLAGS=$pkg_cv_LIBFTDI_CFLAGS LIBFTDI_LIBS=$pkg_cv_LIBFTDI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_libftdi=yes fi if test $use_libftdi = no; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFTDI" >&5 $as_echo_n "checking for LIBFTDI... " >&6; } if test -n "$LIBFTDI_CFLAGS"; then pkg_cv_LIBFTDI_CFLAGS="$LIBFTDI_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libftdi\""; } >&5 ($PKG_CONFIG --exists --print-errors "libftdi") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBFTDI_CFLAGS=`$PKG_CONFIG --cflags "libftdi" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBFTDI_LIBS"; then pkg_cv_LIBFTDI_LIBS="$LIBFTDI_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libftdi\""; } >&5 ($PKG_CONFIG --exists --print-errors "libftdi") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBFTDI_LIBS=`$PKG_CONFIG --libs "libftdi" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBFTDI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libftdi" 2>&1` else LIBFTDI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libftdi" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBFTDI_PKG_ERRORS" >&5 use_libftdi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_libftdi=no else LIBFTDI_CFLAGS=$pkg_cv_LIBFTDI_CFLAGS LIBFTDI_LIBS=$pkg_cv_LIBFTDI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_libftdi=yes fi fi if test $use_libftdi = no; then as_fn_error $? "The libftdi driver is not present on your system." "$LINENO" 5 fi # # Try to build a small program. { $as_echo "$as_me:${as_lineno-$LINENO}: checking Build & Link with libftdi..." >&5 $as_echo_n "checking Build & Link with libftdi...... " >&6; } LDFLAGS_SAVE=$LDFLAGS CFLAGS_SAVE=$CFLAGS LIBS_SAVE=$LIBS _LDFLAGS=`eval echo $LDFLAGS` _CFLAGS=`eval echo $CFLAGS` _LIBS=`eval echo $LIBS` LDFLAGS=$_LDFLAGS CFLAGS="$_CFLAGS $LIBFTDI_CFLAGS" LIBS="$_LIBS $LIBFTDI_LIBS" if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: Skipping as we are cross-compiling, trying build only" >&5 $as_echo "Skipping as we are cross-compiling, trying build only" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ftdi_new" >&5 $as_echo_n "checking for library containing ftdi_new... " >&6; } if ${ac_cv_search_ftdi_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ftdi_new (); int main () { return ftdi_new (); ; return 0; } _ACEOF for ac_lib in '' ; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ftdi_new=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ftdi_new+:} false; then : break fi done if ${ac_cv_search_ftdi_new+:} false; then : else ac_cv_search_ftdi_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ftdi_new" >&5 $as_echo "$ac_cv_search_ftdi_new" >&6; } ac_res=$ac_cv_search_ftdi_new if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "Cannot link with libftdi" "$LINENO" 5 fi else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct ftdi_context *p; p = ftdi_new(); if( p != NULL ){ return 0; } else { fprintf( stderr, "calling ftdi_new() failed\n"); return 1; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: Success" >&5 $as_echo "Success" >&6; } else as_fn_error $? "Cannot build & run test program using libftdi" "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libftdi highspeed device support" >&5 $as_echo_n "checking for libftdi highspeed device support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { enum ftdi_chip_type x = TYPE_2232H; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define BUILD_FT2232_HIGHSPEED 1" >>confdefs.h build_ft2232_highspeed=yes else build_ft2232_highspeed=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_ft2232_highspeed" >&5 $as_echo "$build_ft2232_highspeed" >&6; } if test $build_ft2232_highspeed = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You need a newer libftdi version (0.16 or later)." >&5 $as_echo "$as_me: WARNING: You need a newer libftdi version (0.16 or later)." >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libftdi FT232H device support" >&5 $as_echo_n "checking for libftdi FT232H device support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { enum ftdi_chip_type x = TYPE_232H; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAS_ENUM_FT232H 1" >>confdefs.h has_enum_ft232h=yes else has_enum_ft232h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_enum_ft232h" >&5 $as_echo "$has_enum_ft232h" >&6; } if test $has_enum_ft232h = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You need a newer libftdi version (0.20 or later)." >&5 $as_echo "$as_me: WARNING: You need a newer libftdi version (0.20 or later)." >&2;} fi # Restore the 'unexpanded ldflags' LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE LIBS=$LIBS_SAVE fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB1" >&5 $as_echo_n "checking for LIBUSB1... " >&6; } if test -n "$LIBUSB1_CFLAGS"; then pkg_cv_LIBUSB1_CFLAGS="$LIBUSB1_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb-1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBUSB1_CFLAGS=`$PKG_CONFIG --cflags "libusb-1.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBUSB1_LIBS"; then pkg_cv_LIBUSB1_LIBS="$LIBUSB1_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb-1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBUSB1_LIBS=`$PKG_CONFIG --libs "libusb-1.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBUSB1_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb-1.0" 2>&1` else LIBUSB1_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb-1.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBUSB1_PKG_ERRORS" >&5 use_libusb1=no { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead" >&5 $as_echo "$as_me: WARNING: libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead" >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_libusb1=no { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead" >&5 $as_echo "$as_me: WARNING: libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead" >&2;} else LIBUSB1_CFLAGS=$pkg_cv_LIBUSB1_CFLAGS LIBUSB1_LIBS=$pkg_cv_LIBUSB1_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_libusb1=yes $as_echo "#define HAVE_LIBUSB1 1" >>confdefs.h if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.9\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.9") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then $as_echo "#define HAVE_LIBUSB_ERROR_NAME 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libusb-1.x older than 1.0.9 detected, consider updating" >&5 $as_echo "$as_me: WARNING: libusb-1.x older than 1.0.9 detected, consider updating" >&2;} fi LIBUSB1_CFLAGS=`echo $LIBUSB1_CFLAGS | sed 's/-I/-isystem /'` { $as_echo "$as_me:${as_lineno-$LINENO}: libusb-1.0 header bug workaround: LIBUSB1_CFLAGS changed to \"$LIBUSB1_CFLAGS\"" >&5 $as_echo "$as_me: libusb-1.0 header bug workaround: LIBUSB1_CFLAGS changed to \"$LIBUSB1_CFLAGS\"" >&6;} fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB0" >&5 $as_echo_n "checking for LIBUSB0... " >&6; } if test -n "$LIBUSB0_CFLAGS"; then pkg_cv_LIBUSB0_CFLAGS="$LIBUSB0_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBUSB0_CFLAGS=`$PKG_CONFIG --cflags "libusb" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBUSB0_LIBS"; then pkg_cv_LIBUSB0_LIBS="$LIBUSB0_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBUSB0_LIBS=`$PKG_CONFIG --libs "libusb" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBUSB0_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb" 2>&1` else LIBUSB0_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBUSB0_PKG_ERRORS" >&5 use_libusb0=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_libusb0=no else LIBUSB0_CFLAGS=$pkg_cv_LIBUSB0_CFLAGS LIBUSB0_LIBS=$pkg_cv_LIBUSB0_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_libusb0=yes fi for hidapi_lib in hidapi hidapi-hidraw hidapi-libusb; do pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HIDAPI" >&5 $as_echo_n "checking for HIDAPI... " >&6; } if test -n "$HIDAPI_CFLAGS"; then pkg_cv_HIDAPI_CFLAGS="$HIDAPI_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$hidapi_lib\""; } >&5 ($PKG_CONFIG --exists --print-errors "$hidapi_lib") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_HIDAPI_CFLAGS=`$PKG_CONFIG --cflags "$hidapi_lib" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$HIDAPI_LIBS"; then pkg_cv_HIDAPI_LIBS="$HIDAPI_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$hidapi_lib\""; } >&5 ($PKG_CONFIG --exists --print-errors "$hidapi_lib") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_HIDAPI_LIBS=`$PKG_CONFIG --libs "$hidapi_lib" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then HIDAPI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$hidapi_lib" 2>&1` else HIDAPI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$hidapi_lib" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$HIDAPI_PKG_ERRORS" >&5 use_hidapi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_hidapi=no else HIDAPI_CFLAGS=$pkg_cv_HIDAPI_CFLAGS HIDAPI_LIBS=$pkg_cv_HIDAPI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_hidapi=yes break fi done if test $use_libusb1 = yes; then if test $enable_ftdi != no; then $as_echo "#define BUILD_FTDI 1" >>confdefs.h else $as_echo "#define BUILD_FTDI 0" >>confdefs.h fi else if test $enable_ftdi = yes; then as_fn_error $? "libusb-1.x is required for the MPSSE mode of FTDI based devices" "$LINENO" 5 fi enable_ftdi=no fi if test $enable_ftdi != no; then FTDI_TRUE= FTDI_FALSE='#' else FTDI_TRUE='#' FTDI_FALSE= fi if test $use_libusb1 = yes; then if test $enable_stlink != no; then $as_echo "#define BUILD_HLADAPTER_STLINK 1" >>confdefs.h else $as_echo "#define BUILD_HLADAPTER_STLINK 0" >>confdefs.h fi else if test $enable_stlink = yes; then as_fn_error $? "libusb-1.x is required for the ST-Link JTAG Programmer" "$LINENO" 5 fi enable_stlink=no fi if test $enable_stlink != no; then HLADAPTER_STLINK_TRUE= HLADAPTER_STLINK_FALSE='#' else HLADAPTER_STLINK_TRUE='#' HLADAPTER_STLINK_FALSE= fi if test $use_libusb1 = yes; then if test $enable_ti_icdi != no; then $as_echo "#define BUILD_HLADAPTER_ICDI 1" >>confdefs.h else $as_echo "#define BUILD_HLADAPTER_ICDI 0" >>confdefs.h fi else if test $enable_ti_icdi = yes; then as_fn_error $? "libusb-1.x is required for the TI ICDI JTAG Programmer" "$LINENO" 5 fi enable_ti_icdi=no fi if test $enable_ti_icdi != no; then HLADAPTER_ICDI_TRUE= HLADAPTER_ICDI_FALSE='#' else HLADAPTER_ICDI_TRUE='#' HLADAPTER_ICDI_FALSE= fi if test $use_libusb1 = yes; then if test $enable_ulink != no; then $as_echo "#define BUILD_ULINK 1" >>confdefs.h else $as_echo "#define BUILD_ULINK 0" >>confdefs.h fi else if test $enable_ulink = yes; then as_fn_error $? "libusb-1.x is required for the Keil ULINK JTAG Programmer" "$LINENO" 5 fi enable_ulink=no fi if test $enable_ulink != no; then ULINK_TRUE= ULINK_FALSE='#' else ULINK_TRUE='#' ULINK_FALSE= fi if test $use_libusb1 = yes; then if test $enable_usb_blaster_2 != no; then $as_echo "#define BUILD_USB_BLASTER_2 1" >>confdefs.h else $as_echo "#define BUILD_USB_BLASTER_2 0" >>confdefs.h fi else if test $enable_usb_blaster_2 = yes; then as_fn_error $? "libusb-1.x is required for the Altera USB-Blaster II Compatible" "$LINENO" 5 fi enable_usb_blaster_2=no fi if test $enable_usb_blaster_2 != no; then USB_BLASTER_2_TRUE= USB_BLASTER_2_FALSE='#' else USB_BLASTER_2_TRUE='#' USB_BLASTER_2_FALSE= fi if test $use_libusb1 = yes; then if test $enable_vsllink != no; then $as_echo "#define BUILD_VSLLINK 1" >>confdefs.h else $as_echo "#define BUILD_VSLLINK 0" >>confdefs.h fi else if test $enable_vsllink = yes; then as_fn_error $? "libusb-1.x is required for the Versaloon-Link JTAG Programmer" "$LINENO" 5 fi enable_vsllink=no fi if test $enable_vsllink != no; then VSLLINK_TRUE= VSLLINK_FALSE='#' else VSLLINK_TRUE='#' VSLLINK_FALSE= fi if test $use_libusb1 = yes -o $use_libusb0 = yes; then if test $enable_jlink != no; then $as_echo "#define BUILD_JLINK 1" >>confdefs.h else $as_echo "#define BUILD_JLINK 0" >>confdefs.h fi else if test $enable_jlink = yes; then as_fn_error $? "libusb-1.x or libusb-0.1 is required for the Segger J-Link JTAG Programmer" "$LINENO" 5 fi enable_jlink=no fi if test $enable_jlink != no; then JLINK_TRUE= JLINK_FALSE='#' else JLINK_TRUE='#' JLINK_FALSE= fi if test $use_libusb1 = yes -o $use_libusb0 = yes; then if test $enable_osbdm != no; then $as_echo "#define BUILD_OSBDM 1" >>confdefs.h else $as_echo "#define BUILD_OSBDM 0" >>confdefs.h fi else if test $enable_osbdm = yes; then as_fn_error $? "libusb-1.x or libusb-0.1 is required for the OSBDM (JTAG only) Programmer" "$LINENO" 5 fi enable_osbdm=no fi if test $enable_osbdm != no; then OSBDM_TRUE= OSBDM_FALSE='#' else OSBDM_TRUE='#' OSBDM_FALSE= fi if test $use_libusb1 = yes -o $use_libusb0 = yes; then if test $enable_opendous != no; then $as_echo "#define BUILD_OPENDOUS 1" >>confdefs.h else $as_echo "#define BUILD_OPENDOUS 0" >>confdefs.h fi else if test $enable_opendous = yes; then as_fn_error $? "libusb-1.x or libusb-0.1 is required for the eStick/opendous JTAG Programmer" "$LINENO" 5 fi enable_opendous=no fi if test $enable_opendous != no; then OPENDOUS_TRUE= OPENDOUS_FALSE='#' else OPENDOUS_TRUE='#' OPENDOUS_FALSE= fi if test $use_libusb1 = yes -o $use_libusb0 = yes; then if test $enable_aice != no; then $as_echo "#define BUILD_AICE 1" >>confdefs.h else $as_echo "#define BUILD_AICE 0" >>confdefs.h fi else if test $enable_aice = yes; then as_fn_error $? "libusb-1.x or libusb-0.1 is required for the Andes JTAG Programmer" "$LINENO" 5 fi enable_aice=no fi if test $enable_aice != no; then AICE_TRUE= AICE_FALSE='#' else AICE_TRUE='#' AICE_FALSE= fi if test $use_libusb0 = yes; then if test $enable_usbprog != no; then $as_echo "#define BUILD_USBPROG 1" >>confdefs.h else $as_echo "#define BUILD_USBPROG 0" >>confdefs.h fi else if test $enable_usbprog = yes; then as_fn_error $? "libusb-0.1 is required for the USBProg JTAG Programmer" "$LINENO" 5 fi enable_usbprog=no fi if test $enable_usbprog != no; then USBPROG_TRUE= USBPROG_FALSE='#' else USBPROG_TRUE='#' USBPROG_FALSE= fi if test $use_libusb0 = yes; then if test $enable_rlink != no; then $as_echo "#define BUILD_RLINK 1" >>confdefs.h else $as_echo "#define BUILD_RLINK 0" >>confdefs.h fi else if test $enable_rlink = yes; then as_fn_error $? "libusb-0.1 is required for the Raisonance RLink JTAG Programmer" "$LINENO" 5 fi enable_rlink=no fi if test $enable_rlink != no; then RLINK_TRUE= RLINK_FALSE='#' else RLINK_TRUE='#' RLINK_FALSE= fi if test $use_libusb0 = yes; then if test $enable_armjtagew != no; then $as_echo "#define BUILD_ARMJTAGEW 1" >>confdefs.h else $as_echo "#define BUILD_ARMJTAGEW 0" >>confdefs.h fi else if test $enable_armjtagew = yes; then as_fn_error $? "libusb-0.1 is required for the Olimex ARM-JTAG-EW Programmer" "$LINENO" 5 fi enable_armjtagew=no fi if test $enable_armjtagew != no; then ARMJTAGEW_TRUE= ARMJTAGEW_FALSE='#' else ARMJTAGEW_TRUE='#' ARMJTAGEW_FALSE= fi if test $use_hidapi = yes; then if test $enable_cmsis_dap != no; then $as_echo "#define BUILD_CMSIS_DAP 1" >>confdefs.h else $as_echo "#define BUILD_CMSIS_DAP 0" >>confdefs.h fi else if test $enable_cmsis_dap = yes; then as_fn_error $? "hidapi is required for the CMSIS-DAP Compliant Debugger" "$LINENO" 5 fi enable_cmsis_dap=no fi if test $enable_cmsis_dap != no; then CMSIS_DAP_TRUE= CMSIS_DAP_FALSE='#' else CMSIS_DAP_TRUE='#' CMSIS_DAP_FALSE= fi if test $enable_stlink != no -o $enable_ti_icdi != no; then $as_echo "#define BUILD_HLADAPTER 1" >>confdefs.h else $as_echo "#define BUILD_HLADAPTER 0" >>confdefs.h fi if test $enable_stlink != no -o $enable_ti_icdi != no; then HLADAPTER_TRUE= HLADAPTER_FALSE='#' else HLADAPTER_TRUE='#' HLADAPTER_FALSE= fi if test $build_release = yes; then RELEASE_TRUE= RELEASE_FALSE='#' else RELEASE_TRUE='#' RELEASE_FALSE= fi if test $build_parport = yes; then PARPORT_TRUE= PARPORT_FALSE='#' else PARPORT_TRUE='#' PARPORT_FALSE= fi if test $build_dummy = yes; then DUMMY_TRUE= DUMMY_FALSE='#' else DUMMY_TRUE='#' DUMMY_FALSE= fi if test x$parport_use_giveio = xyes; then GIVEIO_TRUE= GIVEIO_FALSE='#' else GIVEIO_TRUE='#' GIVEIO_FALSE= fi if test $build_ep93xx = yes; then EP93XX_TRUE= EP93XX_FALSE='#' else EP93XX_TRUE='#' EP93XX_FALSE= fi if test $build_zy1000 = yes; then ZY1000_TRUE= ZY1000_FALSE='#' else ZY1000_TRUE='#' ZY1000_FALSE= fi if test $build_zy1000_master = yes; then ZY1000_MASTER_TRUE= ZY1000_MASTER_FALSE='#' else ZY1000_MASTER_TRUE='#' ZY1000_MASTER_FALSE= fi if test $build_ioutil = yes; then IOUTIL_TRUE= IOUTIL_FALSE='#' else IOUTIL_TRUE='#' IOUTIL_FALSE= fi if test $build_at91rm9200 = yes; then AT91RM9200_TRUE= AT91RM9200_FALSE='#' else AT91RM9200_TRUE='#' AT91RM9200_FALSE= fi if test $build_bcm2835gpio = yes; then BCM2835GPIO_TRUE= BCM2835GPIO_FALSE='#' else BCM2835GPIO_TRUE='#' BCM2835GPIO_FALSE= fi if test $build_bitbang = yes; then BITBANG_TRUE= BITBANG_FALSE='#' else BITBANG_TRUE='#' BITBANG_FALSE= fi if test $build_ft2232_libftdi = yes; then FT2232_LIBFTDI_TRUE= FT2232_LIBFTDI_FALSE='#' else FT2232_LIBFTDI_TRUE='#' FT2232_LIBFTDI_FALSE= fi if test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes; then FT2232_DRIVER_TRUE= FT2232_DRIVER_FALSE='#' else FT2232_DRIVER_TRUE='#' FT2232_DRIVER_FALSE= fi if test $build_usb_blaster_libftdi = yes; then USB_BLASTER_LIBFTDI_TRUE= USB_BLASTER_LIBFTDI_FALSE='#' else USB_BLASTER_LIBFTDI_TRUE='#' USB_BLASTER_LIBFTDI_FALSE= fi if test $build_usb_blaster_ftd2xx = yes; then USB_BLASTER_FTD2XX_TRUE= USB_BLASTER_FTD2XX_FALSE='#' else USB_BLASTER_FTD2XX_TRUE='#' USB_BLASTER_FTD2XX_FALSE= fi if test $build_jtag_vpi = yes -o $build_jtag_vpi = yes; then JTAG_VPI_TRUE= JTAG_VPI_FALSE='#' else JTAG_VPI_TRUE='#' JTAG_VPI_FALSE= fi if test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes -o $enable_usb_blaster_2 != no; then USB_BLASTER_DRIVER_TRUE= USB_BLASTER_DRIVER_FALSE='#' else USB_BLASTER_DRIVER_TRUE='#' USB_BLASTER_DRIVER_FALSE= fi if test $build_amtjtagaccel = yes; then AMTJTAGACCEL_TRUE= AMTJTAGACCEL_FALSE='#' else AMTJTAGACCEL_TRUE='#' AMTJTAGACCEL_FALSE= fi if test $build_gw16012 = yes; then GW16012_TRUE= GW16012_FALSE='#' else GW16012_TRUE='#' GW16012_FALSE= fi if test $build_presto_libftdi = yes; then PRESTO_LIBFTDI_TRUE= PRESTO_LIBFTDI_FALSE='#' else PRESTO_LIBFTDI_TRUE='#' PRESTO_LIBFTDI_FALSE= fi if test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes; then PRESTO_DRIVER_TRUE= PRESTO_DRIVER_FALSE='#' else PRESTO_DRIVER_TRUE='#' PRESTO_DRIVER_FALSE= fi if test $build_openjtag_ftd2xx = yes -o $build_openjtag_ftdi = yes; then OPENJTAG_TRUE= OPENJTAG_FALSE='#' else OPENJTAG_TRUE='#' OPENJTAG_FALSE= fi if test $build_oocd_trace = yes; then OOCD_TRACE_TRUE= OOCD_TRACE_FALSE='#' else OOCD_TRACE_TRUE='#' OOCD_TRACE_FALSE= fi if test $build_remote_bitbang = yes; then REMOTE_BITBANG_TRUE= REMOTE_BITBANG_FALSE='#' else REMOTE_BITBANG_TRUE='#' REMOTE_BITBANG_FALSE= fi if test $build_buspirate = yes; then BUSPIRATE_TRUE= BUSPIRATE_FALSE='#' else BUSPIRATE_TRUE='#' BUSPIRATE_FALSE= fi if test $build_sysfsgpio = yes; then SYSFSGPIO_TRUE= SYSFSGPIO_FALSE='#' else SYSFSGPIO_TRUE='#' SYSFSGPIO_FALSE= fi if test $use_libusb0 = yes; then USE_LIBUSB0_TRUE= USE_LIBUSB0_FALSE='#' else USE_LIBUSB0_TRUE='#' USE_LIBUSB0_FALSE= fi if test $use_libusb1 = yes; then USE_LIBUSB1_TRUE= USE_LIBUSB1_FALSE='#' else USE_LIBUSB1_TRUE='#' USE_LIBUSB1_FALSE= fi if test $is_cygwin = yes; then IS_CYGWIN_TRUE= IS_CYGWIN_FALSE='#' else IS_CYGWIN_TRUE='#' IS_CYGWIN_FALSE= fi if test $is_mingw = yes; then IS_MINGW_TRUE= IS_MINGW_FALSE='#' else IS_MINGW_TRUE='#' IS_MINGW_FALSE= fi if test $is_win32 = yes; then IS_WIN32_TRUE= IS_WIN32_FALSE='#' else IS_WIN32_TRUE='#' IS_WIN32_FALSE= fi if test $is_darwin = yes; then IS_DARWIN_TRUE= IS_DARWIN_FALSE='#' else IS_DARWIN_TRUE='#' IS_DARWIN_FALSE= fi if test $build_bitq = yes; then BITQ_TRUE= BITQ_FALSE='#' else BITQ_TRUE='#' BITQ_FALSE= fi if test $use_hidapi = yes; then CMSIS_DAP_TRUE= CMSIS_DAP_FALSE='#' else CMSIS_DAP_TRUE='#' CMSIS_DAP_FALSE= fi if test $build_minidriver = yes; then MINIDRIVER_TRUE= MINIDRIVER_FALSE='#' else MINIDRIVER_TRUE='#' MINIDRIVER_FALSE= fi if test $build_minidriver_dummy = yes; then MINIDRIVER_DUMMY_TRUE= MINIDRIVER_DUMMY_FALSE='#' else MINIDRIVER_DUMMY_TRUE='#' MINIDRIVER_DUMMY_FALSE= fi if test $use_internal_jimtcl = yes; then INTERNAL_JIMTCL_TRUE= INTERNAL_JIMTCL_FALSE='#' else INTERNAL_JIMTCL_TRUE='#' INTERNAL_JIMTCL_FALSE= fi # Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h? { $as_echo "$as_me:${as_lineno-$LINENO}: checking for environ in unistd.h and stdlib.h" >&5 $as_echo_n "checking for environ in unistd.h and stdlib.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main () { char **ep = environ; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } has_environ=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # Possibility #2: can environ be found in an available library? { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extern environ" >&5 $as_echo_n "checking for extern environ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern char **environ; int main () { char **ep = environ; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define NEED_ENVIRON_EXTERN 1" >>confdefs.h has_environ=yes else has_environ=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${has_environ}" >&5 $as_echo "${has_environ}" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "${has_environ}" != "yes" ; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Could not find 'environ' in unistd.h or available libraries. See \`config.log' for more details" "$LINENO" 5; } fi $as_echo "#define _GNU_SOURCE 1" >>confdefs.h # set default gcc warnings GCC_WARNINGS="-Wall -Wstrict-prototypes -Wformat-security -Wshadow" if test "${gcc_wextra}" = yes; then GCC_WARNINGS="${GCC_WARNINGS} -Wextra -Wno-unused-parameter" GCC_WARNINGS="${GCC_WARNINGS} -Wbad-function-cast" GCC_WARNINGS="${GCC_WARNINGS} -Wcast-align" GCC_WARNINGS="${GCC_WARNINGS} -Wredundant-decls" fi if test "${gcc_werror}" = yes; then GCC_WARNINGS="${GCC_WARNINGS} -Werror" fi # overide default gcc cflags if test $gcc_warnings = yes; then CFLAGS="$CFLAGS $GCC_WARNINGS" fi ac_config_files="$ac_config_files Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/jtag/drivers/Makefile src/jtag/drivers/usb_blaster/Makefile src/jtag/hla/Makefile src/jtag/aice/Makefile src/transport/Makefile src/target/openrisc/Makefile src/xsvf/Makefile src/svf/Makefile src/target/Makefile src/rtos/Makefile src/server/Makefile src/flash/Makefile src/flash/nor/Makefile src/flash/nand/Makefile src/pld/Makefile doc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FTDI_TRUE}" && test -z "${FTDI_FALSE}"; then as_fn_error $? "conditional \"FTDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HLADAPTER_STLINK_TRUE}" && test -z "${HLADAPTER_STLINK_FALSE}"; then as_fn_error $? "conditional \"HLADAPTER_STLINK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HLADAPTER_ICDI_TRUE}" && test -z "${HLADAPTER_ICDI_FALSE}"; then as_fn_error $? "conditional \"HLADAPTER_ICDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ULINK_TRUE}" && test -z "${ULINK_FALSE}"; then as_fn_error $? "conditional \"ULINK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USB_BLASTER_2_TRUE}" && test -z "${USB_BLASTER_2_FALSE}"; then as_fn_error $? "conditional \"USB_BLASTER_2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${VSLLINK_TRUE}" && test -z "${VSLLINK_FALSE}"; then as_fn_error $? "conditional \"VSLLINK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${JLINK_TRUE}" && test -z "${JLINK_FALSE}"; then as_fn_error $? "conditional \"JLINK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSBDM_TRUE}" && test -z "${OSBDM_FALSE}"; then as_fn_error $? "conditional \"OSBDM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OPENDOUS_TRUE}" && test -z "${OPENDOUS_FALSE}"; then as_fn_error $? "conditional \"OPENDOUS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AICE_TRUE}" && test -z "${AICE_FALSE}"; then as_fn_error $? "conditional \"AICE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USBPROG_TRUE}" && test -z "${USBPROG_FALSE}"; then as_fn_error $? "conditional \"USBPROG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${RLINK_TRUE}" && test -z "${RLINK_FALSE}"; then as_fn_error $? "conditional \"RLINK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ARMJTAGEW_TRUE}" && test -z "${ARMJTAGEW_FALSE}"; then as_fn_error $? "conditional \"ARMJTAGEW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CMSIS_DAP_TRUE}" && test -z "${CMSIS_DAP_FALSE}"; then as_fn_error $? "conditional \"CMSIS_DAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HLADAPTER_TRUE}" && test -z "${HLADAPTER_FALSE}"; then as_fn_error $? "conditional \"HLADAPTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${RELEASE_TRUE}" && test -z "${RELEASE_FALSE}"; then as_fn_error $? "conditional \"RELEASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${PARPORT_TRUE}" && test -z "${PARPORT_FALSE}"; then as_fn_error $? "conditional \"PARPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DUMMY_TRUE}" && test -z "${DUMMY_FALSE}"; then as_fn_error $? "conditional \"DUMMY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GIVEIO_TRUE}" && test -z "${GIVEIO_FALSE}"; then as_fn_error $? "conditional \"GIVEIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${EP93XX_TRUE}" && test -z "${EP93XX_FALSE}"; then as_fn_error $? "conditional \"EP93XX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ZY1000_TRUE}" && test -z "${ZY1000_FALSE}"; then as_fn_error $? "conditional \"ZY1000\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ZY1000_MASTER_TRUE}" && test -z "${ZY1000_MASTER_FALSE}"; then as_fn_error $? "conditional \"ZY1000_MASTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IOUTIL_TRUE}" && test -z "${IOUTIL_FALSE}"; then as_fn_error $? "conditional \"IOUTIL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AT91RM9200_TRUE}" && test -z "${AT91RM9200_FALSE}"; then as_fn_error $? "conditional \"AT91RM9200\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BCM2835GPIO_TRUE}" && test -z "${BCM2835GPIO_FALSE}"; then as_fn_error $? "conditional \"BCM2835GPIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BITBANG_TRUE}" && test -z "${BITBANG_FALSE}"; then as_fn_error $? "conditional \"BITBANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FT2232_LIBFTDI_TRUE}" && test -z "${FT2232_LIBFTDI_FALSE}"; then as_fn_error $? "conditional \"FT2232_LIBFTDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FT2232_DRIVER_TRUE}" && test -z "${FT2232_DRIVER_FALSE}"; then as_fn_error $? "conditional \"FT2232_DRIVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USB_BLASTER_LIBFTDI_TRUE}" && test -z "${USB_BLASTER_LIBFTDI_FALSE}"; then as_fn_error $? "conditional \"USB_BLASTER_LIBFTDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USB_BLASTER_FTD2XX_TRUE}" && test -z "${USB_BLASTER_FTD2XX_FALSE}"; then as_fn_error $? "conditional \"USB_BLASTER_FTD2XX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${JTAG_VPI_TRUE}" && test -z "${JTAG_VPI_FALSE}"; then as_fn_error $? "conditional \"JTAG_VPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USB_BLASTER_DRIVER_TRUE}" && test -z "${USB_BLASTER_DRIVER_FALSE}"; then as_fn_error $? "conditional \"USB_BLASTER_DRIVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMTJTAGACCEL_TRUE}" && test -z "${AMTJTAGACCEL_FALSE}"; then as_fn_error $? "conditional \"AMTJTAGACCEL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GW16012_TRUE}" && test -z "${GW16012_FALSE}"; then as_fn_error $? "conditional \"GW16012\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${PRESTO_LIBFTDI_TRUE}" && test -z "${PRESTO_LIBFTDI_FALSE}"; then as_fn_error $? "conditional \"PRESTO_LIBFTDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${PRESTO_DRIVER_TRUE}" && test -z "${PRESTO_DRIVER_FALSE}"; then as_fn_error $? "conditional \"PRESTO_DRIVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OPENJTAG_TRUE}" && test -z "${OPENJTAG_FALSE}"; then as_fn_error $? "conditional \"OPENJTAG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OOCD_TRACE_TRUE}" && test -z "${OOCD_TRACE_FALSE}"; then as_fn_error $? "conditional \"OOCD_TRACE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${REMOTE_BITBANG_TRUE}" && test -z "${REMOTE_BITBANG_FALSE}"; then as_fn_error $? "conditional \"REMOTE_BITBANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUSPIRATE_TRUE}" && test -z "${BUSPIRATE_FALSE}"; then as_fn_error $? "conditional \"BUSPIRATE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${SYSFSGPIO_TRUE}" && test -z "${SYSFSGPIO_FALSE}"; then as_fn_error $? "conditional \"SYSFSGPIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_LIBUSB0_TRUE}" && test -z "${USE_LIBUSB0_FALSE}"; then as_fn_error $? "conditional \"USE_LIBUSB0\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_LIBUSB1_TRUE}" && test -z "${USE_LIBUSB1_FALSE}"; then as_fn_error $? "conditional \"USE_LIBUSB1\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_CYGWIN_TRUE}" && test -z "${IS_CYGWIN_FALSE}"; then as_fn_error $? "conditional \"IS_CYGWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_MINGW_TRUE}" && test -z "${IS_MINGW_FALSE}"; then as_fn_error $? "conditional \"IS_MINGW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_WIN32_TRUE}" && test -z "${IS_WIN32_FALSE}"; then as_fn_error $? "conditional \"IS_WIN32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_DARWIN_TRUE}" && test -z "${IS_DARWIN_FALSE}"; then as_fn_error $? "conditional \"IS_DARWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BITQ_TRUE}" && test -z "${BITQ_FALSE}"; then as_fn_error $? "conditional \"BITQ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CMSIS_DAP_TRUE}" && test -z "${CMSIS_DAP_FALSE}"; then as_fn_error $? "conditional \"CMSIS_DAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MINIDRIVER_TRUE}" && test -z "${MINIDRIVER_FALSE}"; then as_fn_error $? "conditional \"MINIDRIVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MINIDRIVER_DUMMY_TRUE}" && test -z "${MINIDRIVER_DUMMY_FALSE}"; then as_fn_error $? "conditional \"MINIDRIVER_DUMMY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${INTERNAL_JIMTCL_TRUE}" && test -z "${INTERNAL_JIMTCL_FALSE}"; then as_fn_error $? "conditional \"INTERNAL_JIMTCL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by openocd $as_me 0.9.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to >." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ openocd config.status 0.9.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/helper/Makefile") CONFIG_FILES="$CONFIG_FILES src/helper/Makefile" ;; "src/jtag/Makefile") CONFIG_FILES="$CONFIG_FILES src/jtag/Makefile" ;; "src/jtag/drivers/Makefile") CONFIG_FILES="$CONFIG_FILES src/jtag/drivers/Makefile" ;; "src/jtag/drivers/usb_blaster/Makefile") CONFIG_FILES="$CONFIG_FILES src/jtag/drivers/usb_blaster/Makefile" ;; "src/jtag/hla/Makefile") CONFIG_FILES="$CONFIG_FILES src/jtag/hla/Makefile" ;; "src/jtag/aice/Makefile") CONFIG_FILES="$CONFIG_FILES src/jtag/aice/Makefile" ;; "src/transport/Makefile") CONFIG_FILES="$CONFIG_FILES src/transport/Makefile" ;; "src/target/openrisc/Makefile") CONFIG_FILES="$CONFIG_FILES src/target/openrisc/Makefile" ;; "src/xsvf/Makefile") CONFIG_FILES="$CONFIG_FILES src/xsvf/Makefile" ;; "src/svf/Makefile") CONFIG_FILES="$CONFIG_FILES src/svf/Makefile" ;; "src/target/Makefile") CONFIG_FILES="$CONFIG_FILES src/target/Makefile" ;; "src/rtos/Makefile") CONFIG_FILES="$CONFIG_FILES src/rtos/Makefile" ;; "src/server/Makefile") CONFIG_FILES="$CONFIG_FILES src/server/Makefile" ;; "src/flash/Makefile") CONFIG_FILES="$CONFIG_FILES src/flash/Makefile" ;; "src/flash/nor/Makefile") CONFIG_FILES="$CONFIG_FILES src/flash/nor/Makefile" ;; "src/flash/nand/Makefile") CONFIG_FILES="$CONFIG_FILES src/flash/nand/Makefile" ;; "src/pld/Makefile") CONFIG_FILES="$CONFIG_FILES src/pld/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi # # CONFIG_SUBDIRS section. # if test "$no_recursion" != yes; then # Remove --cache-file, --srcdir, and --disable-option-checking arguments # so they do not pile up. ac_sub_configure_args= ac_prev= eval "set x $ac_configure_args" shift for ac_arg do if test -n "$ac_prev"; then ac_prev= continue fi case $ac_arg in -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ | --c=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; --disable-option-checking) ;; *) case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_sub_configure_args " '$ac_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ac_arg="--prefix=$prefix" case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" # Pass --silent if test "$silent" = yes; then ac_sub_configure_args="--silent $ac_sub_configure_args" fi # Always prepend --disable-option-checking to silence warnings, since # different subdirs can have different --enable and --with options. ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" ac_popdir=`pwd` for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue # Do not complain, so a configure script can configure whichever # parts of a large source tree are present. test -d "$srcdir/$ac_dir" || continue ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 $as_echo "$ac_msg" >&6 as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" # Check for guested configure; otherwise get Cygnus style configure. if test -f "$ac_srcdir/configure.gnu"; then ac_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ac_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ac_sub_configure=$ac_aux_dir/configure else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi # The recursion is here. if test -n "$ac_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; *) # Relative name. ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 $as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 fi cd "$ac_popdir" done fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo echo echo OpenOCD configuration summary echo -------------------------------------------------- s="MPSSE mode of FTDI based devices " case $enable_ftdi in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="ST-Link JTAG Programmer " case $enable_stlink in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="TI ICDI JTAG Programmer " case $enable_ti_icdi in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Keil ULINK JTAG Programmer " case $enable_ulink in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Altera USB-Blaster II Compatible " case $enable_usb_blaster_2 in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Versaloon-Link JTAG Programmer " case $enable_vsllink in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Segger J-Link JTAG Programmer " case $enable_jlink in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="OSBDM (JTAG only) Programmer " case $enable_osbdm in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="eStick/opendous JTAG Programmer " case $enable_opendous in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Andes JTAG Programmer " case $enable_aice in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="USBProg JTAG Programmer " case $enable_usbprog in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Raisonance RLink JTAG Programmer " case $enable_rlink in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="Olimex ARM-JTAG-EW Programmer " case $enable_armjtagew in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac s="CMSIS-DAP Compliant Debugger " case $enable_cmsis_dap in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac echo if test $build_ft2232_libftdi = yes -o $build_ft2232_ftd2xx = yes; then if test $enable_ftdi = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building the deprecated 'ft2232' adapter driver but not its replacement!" >&5 $as_echo "$as_me: WARNING: Building the deprecated 'ft2232' adapter driver but not its replacement!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please consider using --enable-ftdi instead." >&5 $as_echo "$as_me: WARNING: Please consider using --enable-ftdi instead." >&2;} else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building the deprecated 'ft2232' adapter driver." >&5 $as_echo "$as_me: WARNING: Building the deprecated 'ft2232' adapter driver." >&2;} fi fi openocd-0.9.0/README.Windows0000644000175000017500000000451712526201107012404 00000000000000Building OpenOCD for Windows ---------------------------- You can build OpenOCD for Windows natively with either MinGW-w64/MSYS or Cygwin (plain MinGW might work with --disable-werror but is not recommended as it doesn't provide enough C99 compatibility). Alternatively, one can cross-compile it using MinGW-w64 on a *nix host. See README for the generic instructions. Also, the MSYS2 project provides both ready-made binaries and an easy way to self-compile from their software repository out of the box. Native MinGW-w64/MSYS compilation ----------------------------- As MSYS doesn't come with pkg-config pre-installed, you need to add it manually. The easiest way to do that is to download pkg-config-lite from: http://sourceforge.net/projects/pkgconfiglite/ Then simply unzip the archive to the root directory of your MinGW-w64 installation. USB adapters ------------ For the adapters that use a HID-based protocol, e.g. CMSIS-DAP, you do not need to perform any additional configuration. For all the others you usually need to have WinUSB.sys (or libusbK.sys) driver installed. Some vendor software (e.g. for ST-LINKv2) does it on its own. For the other cases the easiest way to assign WinUSB to a device is to use the latest Zadig installer: http://zadig.akeo.ie When using a composite USB device, it's often necessary to assign WinUSB.sys to the composite parent instead of the specific interface. To do that one needs to activate an advanced option in the Zadig installer. For the old drivers that use libusb-0.1 API you might need to link against libusb-win32 headers and install the corresponding driver with Zadig. If you need to use the same adapter with other applications that may require another driver, a solution for Windows Vista and above is to activate the IgnoreHWSerNum registry setting for the USB device. That setting forces Windows to associate the driver per port instead of per serial number, the same behaviour as when the device does not contain a serial number. So different drivers can be installed for the adapter on different ports and you just need to plug the adapter into the correct port depending on which application to use. For more information, see: http://msdn.microsoft.com/en-us/library/windows/hardware/jj649944(v=vs.85).aspx http://www.ftdichip.com/Support/Knowledgebase/index.html?ignorehardwareserialnumber.htm openocd-0.9.0/configure.ac0000644000175000017500000012407712526201212012362 00000000000000AC_PREREQ(2.64) AC_INIT([openocd], [0.9.0], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) m4_include([config_subdir.m4])dnl # check for makeinfo before calling AM_INIT_AUTOMAKE AC_CHECK_PROG([MAKEINFO], [makeinfo], [makeinfo]) if test "x$MAKEINFO" = "x"; then MAKEINFO='echo makeinfo missing; true' AC_MSG_WARN([Info documentation will not be built.]) fi AC_SUBST([MAKEINFO]) AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip subdir-objects]) AC_CONFIG_HEADERS([config.h]) AH_BOTTOM([ #include #include #include ]) AC_LANG_C AC_PROG_CC AC_PROG_CC_C99 AM_PROG_CC_C_O AC_PROG_RANLIB PKG_PROG_PKG_CONFIG([0.23]) dnl disable checks for C++, Fortran and GNU Java Compiler m4_defun([_LT_AC_LANG_CXX_CONFIG], [:]) m4_defun([_LT_AC_LANG_F77_CONFIG], [:]) m4_defun([_LT_AC_LANG_GCJ_CONFIG], [:]) AC_DISABLE_SHARED AC_PROG_LIBTOOL AC_SUBST([LIBTOOL_DEPS]) dnl configure checks required for Jim files (these are obsolete w/ C99) AC_C_CONST AC_TYPE_LONG_LONG_INT AC_SEARCH_LIBS([ioperm], [ioperm]) AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([arpa/inet.h], [], [], [dnl #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif ]) AC_CHECK_HEADERS([elf.h]) AC_CHECK_HEADERS([dirent.h]) AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([ifaddrs.h], [], [], [dnl #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif ]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([netinet/in.h], [], [], [dnl #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif ]) AC_CHECK_HEADERS([netinet/tcp.h], [], [], [dnl #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif ]) AC_CHECK_HEADERS([pthread.h]) AC_CHECK_HEADERS([strings.h]) AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/poll.h]) AC_CHECK_HEADERS([sys/select.h]) AC_CHECK_HEADERS([sys/stat.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/types.h]) AC_CHECK_HEADERS([unistd.h]) AC_CHECK_HEADERS([net/if.h], [], [], [dnl #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_SYS_SOCKET_H # include #endif ]) AC_HEADER_ASSERT AC_HEADER_STDBOOL AC_HEADER_TIME AC_C_BIGENDIAN AC_CHECK_FUNCS([strndup]) AC_CHECK_FUNCS([strnlen]) AC_CHECK_FUNCS([gettimeofday]) AC_CHECK_FUNCS([usleep]) AC_CHECK_FUNCS([vasprintf]) build_bitbang=no build_bitq=no is_cygwin=no is_mingw=no is_win32=no is_darwin=no # guess-rev.sh only exists in the repository, not in the released archives AC_MSG_CHECKING([whether to build a release]) if test -x $srcdir/guess-rev.sh ; then build_release=no else build_release=yes fi AC_MSG_RESULT([$build_release]) AC_ARG_WITH(ftd2xx, AS_HELP_STRING([--with-ftd2xx=],[This option has been removed.]), [ # Option Given. cat << __EOF__ The option: --with-ftd2xx= has been removed. On Linux, the new option is: --with-ftd2xx-linux-tardir=/path/to/files Where is the path the the directory where the "tar.gz" file from FTDICHIP.COM was unpacked, for example: --with-ftd2xx-linux-tardir=${HOME}/libftd2xx0.4.16 On Cygwin/MingW32, the new option is: --with-ftd2xx-win32-zipdir=/path/to/files Where is the path to the directory where the "zip" file from FTDICHIP.COM was unpacked, for example: --with-ftd2xx-win32-zipdir=${HOME}/ftd2xx.cdm.files __EOF__ AC_MSG_ERROR([Sorry Cannot continue]) ], [true]) # Adapter drivers # 1st column -- configure option # 2nd column -- description # 3rd column -- symbol used for both config.h and automake m4_define([ADAPTER_ARG], [m4_argn([1], $1)]) m4_define([ADAPTER_DESC], [m4_argn([2], $1)]) m4_define([ADAPTER_SYM], [m4_argn([3], $1)]) m4_define([ADAPTER_VAR], [enable_[]ADAPTER_ARG($1)]) m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])]) m4_define([USB1_ADAPTERS], [[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]], [[stlink], [ST-Link JTAG Programmer], [HLADAPTER_STLINK]], [[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]], [[ulink], [Keil ULINK JTAG Programmer], [ULINK]], [[usb_blaster_2], [Altera USB-Blaster II Compatible], [USB_BLASTER_2]], [[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]]]) m4_define([USB_ADAPTERS], [[[jlink], [Segger J-Link JTAG Programmer], [JLINK]], [[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]], [[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]], [[aice], [Andes JTAG Programmer], [AICE]]]) m4_define([USB0_ADAPTERS], [[[usbprog], [USBProg JTAG Programmer], [USBPROG]], [[rlink], [Raisonance RLink JTAG Programmer], [RLINK]], [[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]]]) m4_define([HIDAPI_ADAPTERS], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]]]) #======================================== # FTD2XXX support comes in 4 forms. # (1) win32 - via a zip file # (2) linux - via a tar file # (3) linux/cygwin/mingw - via libftdi # (4) darwin - installed under /usr/local # # In case (1) and (2) we need to know where the package was unpacked. AC_ARG_WITH(ftd2xx-win32-zipdir, AS_HELP_STRING([--with-ftd2xx-win32-zipdir],[Where (CYGWIN/MINGW) the zip file from ftdichip.com was unpacked (default=search)]), [ # option present if test -d $with_ftd2xx_win32_zipdir then with_ftd2xx_win32_zipdir=`cd $with_ftd2xx_win32_zipdir && pwd` AC_MSG_NOTICE([Using: ftdichip.com library: $with_ftd2xx_win32_zipdir]) else AC_MSG_ERROR([Parameter to --with-ftd2xx-win32-zipdir is not a dir: $with_ftd2xx_win32_zipdir]) fi ], [true]) AC_ARG_WITH(ftd2xx-linux-tardir, AS_HELP_STRING([--with-ftd2xx-linux-tardir], [Where (Linux/Unix) the tar file from ftdichip.com was unpacked (default=search)]), [ # Option present if test $is_win32 = yes ; then AC_MSG_ERROR([The option: --with-ftd2xx-linux-tardir is only usable on linux]) fi if test -d $with_ftd2xx_linux_tardir then with_ftd2xx_linux_tardir=`cd $with_ftd2xx_linux_tardir && pwd` AC_MSG_NOTICE([Using: ftdichip.com library: $with_ftd2xx_linux_tardir]) else AC_MSG_ERROR([Parameter to --with-ftd2xx-linux-tardir is not a dir: $with_ftd2xx_linux_tardir]) fi ], [true]) AC_ARG_WITH(ftd2xx-lib, AS_HELP_STRING([--with-ftd2xx-lib], [Use static or shared ftd2xx libs (default=static)]), [ case "$withval" in static) with_ftd2xx_lib=$withval ;; shared) with_ftd2xx_lib=$withval ;; *) AC_MSG_ERROR([Option: --with-ftd2xx-lib=static or --with-ftd2xx-lib=shared not, $withval]) ;; esac ], [ # Default is static - it is simpler :-( with_ftd2xx_lib=static ]) AC_ARG_ENABLE([doxygen-html], AS_HELP_STRING([--disable-doxygen-html], [Disable building Doxygen manual as HTML.]), [doxygen_as_html=$enableval], [doxygen_as_html=yes]) AC_SUBST([doxygen_as_html]) AC_MSG_CHECKING([whether to build Doxygen as HTML]) AC_MSG_RESULT([$doxygen_as_html]) AC_ARG_ENABLE([doxygen-pdf], AS_HELP_STRING([--enable-doxygen-pdf], [Enable building Doxygen manual as PDF.]), [doxygen_as_pdf=$enableval], [doxygen_as_pdf=no]) AC_SUBST([doxygen_as_pdf]) AC_MSG_CHECKING([whether to build Doxygen as PDF]) AC_MSG_RESULT([$doxygen_as_pdf]) AC_ARG_ENABLE([gccwarnings], AS_HELP_STRING([--disable-gccwarnings], [Disable compiler warnings]), [gcc_warnings=$enableval], [gcc_warnings=yes]) AC_ARG_ENABLE([wextra], AS_HELP_STRING([--disable-wextra], [Disable extra compiler warnings]), [gcc_wextra=$enableval], [gcc_wextra=$gcc_warnings]) AC_ARG_ENABLE([werror], AS_HELP_STRING([--disable-werror], [Do not treat warnings as errors]), [gcc_werror=$enableval], [gcc_werror=$gcc_warnings]) # set default verbose options, overridden by following options debug_jtag_io=no debug_usb_io=no debug_usb_comms=no AC_ARG_ENABLE([verbose], AS_HELP_STRING([--enable-verbose], [Enable verbose JTAG I/O messages (for debugging).]), [ debug_jtag_io=$enableval debug_usb_io=$enableval debug_usb_comms=$enableval ], []) AC_ARG_ENABLE([verbose_jtag_io], AS_HELP_STRING([--enable-verbose-jtag-io], [Enable verbose JTAG I/O messages (for debugging).]), [debug_jtag_io=$enableval], []) AC_ARG_ENABLE([verbose_usb_io], AS_HELP_STRING([--enable-verbose-usb-io], [Enable verbose USB I/O messages (for debugging)]), [debug_usb_io=$enableval], []) AC_ARG_ENABLE([verbose_usb_comms], AS_HELP_STRING([--enable-verbose-usb-comms], [Enable verbose USB communication messages (for debugging)]), [debug_usb_comms=$enableval], []) AC_MSG_CHECKING([whether to enable verbose JTAG I/O messages]); AC_MSG_RESULT([$debug_jtag_io]) if test $debug_jtag_io = yes; then AC_DEFINE([_DEBUG_JTAG_IO_],[1], [Print verbose JTAG I/O messages]) fi AC_MSG_CHECKING([whether to enable verbose USB I/O messages]); AC_MSG_RESULT([$debug_usb_io]) if test $debug_usb_io = yes; then AC_DEFINE([_DEBUG_USB_IO_],[1], [Print verbose USB I/O messages]) fi AC_MSG_CHECKING([whether to enable verbose USB communication messages]); AC_MSG_RESULT([$debug_usb_comms]) if test $debug_usb_comms = yes; then AC_DEFINE([_DEBUG_USB_COMMS_],[1], [Print verbose USB communication messages]) fi debug_malloc=no AC_ARG_ENABLE([malloc_logging], AS_HELP_STRING([--enable-malloc-logging], [Include free space in logging messages (requires malloc.h).]), [debug_malloc=$enableval], []) AC_MSG_CHECKING([whether to enable malloc free space logging]); AC_MSG_RESULT([$debug_malloc]) if test $debug_malloc = yes; then AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) fi AC_ARG_ENABLE([dummy], AS_HELP_STRING([--enable-dummy], [Enable building the dummy port driver]), [build_dummy=$enableval], [build_dummy=no]) m4_define([AC_ARG_ADAPTERS], [ m4_foreach([adapter], [$1], [AC_ARG_ENABLE(ADAPTER_OPT([adapter]), AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])], [Enable building support for the ]ADAPTER_DESC([adapter])[ (default is $2)]), [], [ADAPTER_VAR([adapter])=$2]) ]) ]) AC_ARG_ADAPTERS([USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS], [auto]) AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), [build_parport=$enableval], [build_parport=no]) AC_ARG_ENABLE([parport_ppdev], AS_HELP_STRING([--disable-parport-ppdev], [Disable use of ppdev (/dev/parportN) for parport (for x86 only)]), [parport_use_ppdev=$enableval], [parport_use_ppdev=yes]) AC_ARG_ENABLE([parport_giveio], AS_HELP_STRING([--enable-parport-giveio], [Enable use of giveio for parport (for CygWin only)]), [parport_use_giveio=$enableval], [parport_use_giveio=]) AC_ARG_ENABLE([ft2232_libftdi], [], [ if test $enableval = yes; then AC_MSG_ERROR([The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_libftdi]) fi ]) AC_ARG_ENABLE([ft2232_ftd2xx], [], [ if test $enableval = yes; then AC_MSG_ERROR([The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_ftd2xx]) fi ]) AC_ARG_ENABLE([legacy-ft2232_libftdi], AS_HELP_STRING([--enable-legacy-ft2232_libftdi], [(DEPRECATED) Enable building support for FT2232 based devices using the libftdi library]), [build_ft2232_libftdi=$enableval], [build_ft2232_libftdi=no]) AC_ARG_ENABLE([legacy-ft2232_ftd2xx], AS_HELP_STRING([--enable-legacy-ft2232_ftd2xx], [(DEPRECATED) Enable building support for FT2232 based devices using the D2XX library from ftdichip.com]), [build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no]) AC_ARG_ENABLE([jtag_vpi], AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]), [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) AC_ARG_ENABLE([usb_blaster_libftdi], AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]), [build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no]) AC_ARG_ENABLE([usb_blaster_ftd2xx], AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]), [build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no]) AC_ARG_ENABLE([amtjtagaccel], AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) AC_ARG_ENABLE([zy1000_master], AS_HELP_STRING([--enable-zy1000-master], [Use ZY1000 JTAG master registers]), [build_zy1000_master=$enableval], [build_zy1000_master=no]) AC_ARG_ENABLE([zy1000], AS_HELP_STRING([--enable-zy1000], [Enable ZY1000 interface]), [build_zy1000=$enableval], [build_zy1000=no]) AC_ARG_ENABLE([ioutil], AS_HELP_STRING([--enable-ioutil], [Enable ioutil functions - useful for standalone OpenOCD implementations]), [build_ioutil=$enableval], [build_ioutil=no]) case "${host_cpu}" in arm*) AC_ARG_ENABLE([ep93xx], AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]), [build_ep93xx=$enableval], [build_ep93xx=no]) AC_ARG_ENABLE([at91rm9200], AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]), [build_at91rm9200=$enableval], [build_at91rm9200=no]) AC_ARG_ENABLE([bcm2835gpio], AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]), [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no]) ;; *) build_ep93xx=no build_at91rm9200=no build_bcm2835gpio=no ;; esac AC_ARG_ENABLE([gw16012], AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), [build_gw16012=$enableval], [build_gw16012=no]) AC_ARG_ENABLE([presto_libftdi], AS_HELP_STRING([--enable-presto_libftdi], [Enable building support for ASIX Presto Programmer using the libftdi driver]), [build_presto_libftdi=$enableval], [build_presto_libftdi=no]) AC_ARG_ENABLE([presto_ftd2xx], AS_HELP_STRING([--enable-presto_ftd2xx], [Enable building support for ASIX Presto Programmer using the FTD2XX driver]), [build_presto_ftd2xx=$enableval], [build_presto_ftd2xx=no]) AC_ARG_ENABLE([openjtag_ftd2xx], AS_HELP_STRING([--enable-openjtag_ftd2xx], [Enable building support for the OpenJTAG Programmer with ftd2xx driver]), [build_openjtag_ftd2xx=$enableval], [build_openjtag_ftd2xx=no]) AC_ARG_ENABLE([openjtag_ftdi], AS_HELP_STRING([--enable-openjtag_ftdi], [Enable building support for the OpenJTAG Programmer with ftdi driver]), [build_openjtag_ftdi=$enableval], [build_openjtag_ftdi=no]) AC_ARG_ENABLE([oocd_trace], AS_HELP_STRING([--enable-oocd_trace], [Enable building support for some prototype OpenOCD+trace ETM capture hardware]), [build_oocd_trace=$enableval], [build_oocd_trace=no]) AC_ARG_ENABLE([buspirate], AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]), [build_buspirate=$enableval], [build_buspirate=no]) AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) AC_ARG_ENABLE([minidriver_dummy], AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]), [build_minidriver_dummy=$enableval], [build_minidriver_dummy=no]) AC_ARG_ENABLE([internal-jimtcl], AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]), [use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes]) build_minidriver=no AC_MSG_CHECKING([whether to enable ZY1000 minidriver]) if test $build_zy1000 = yes; then if test $build_minidriver = yes; then AC_MSG_ERROR([Multiple minidriver options have been enabled.]) fi AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1], [Define to 1 if you have the header file.]) build_minidriver=yes fi AC_MSG_RESULT([$build_zy1000]) AC_ARG_ENABLE([remote-bitbang], AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]), [build_remote_bitbang=$enableval], [build_remote_bitbang=no]) AC_MSG_CHECKING([whether to enable dummy minidriver]) if test $build_minidriver_dummy = yes; then if test $build_minidriver = yes; then AC_MSG_ERROR([Multiple minidriver options have been enabled.]) fi build_minidriver=yes AC_DEFINE([BUILD_MINIDRIVER_DUMMY], [1], [Use the dummy minidriver.]) AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1], [Define to 1 if you have the header file.]) fi AC_MSG_RESULT([$build_minidriver_dummy]) AC_MSG_CHECKING([whether standard drivers can be built]) if test "$build_minidriver" = yes; then AC_MSG_RESULT([no]) AC_MSG_WARN([Using the minidriver disables all other drivers.]) sleep 2 else AC_MSG_RESULT([yes]) fi case "${host_cpu}" in i?86|x86*) ;; *) if test x$parport_use_ppdev = xno; then AC_MSG_WARN([--disable-parport-ppdev is not supported by the host CPU]) fi parport_use_ppdev=yes ;; esac case $host in *-cygwin*) is_win32=yes parport_use_ppdev=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[return __MINGW32__;]])], [is_mingw=yes],[is_mingw=no]) if test $is_mingw = yes; then AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) if test x$parport_use_giveio = xno; then AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts]) fi parport_use_giveio=yes is_cygwin=no else is_cygwin=yes AC_DEFINE([IS_CYGWIN], [1], [1 if building for Cygwin.]) # sys/io.h needed under cygwin for parport access if test $build_parport = yes; then AC_CHECK_HEADERS([sys/io.h],[],AC_MSG_ERROR([Please install the cygwin ioperm package])) fi fi AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ;; *-mingw*) is_mingw=yes is_win32=yes parport_use_ppdev=no if test x$parport_use_giveio = xno; then AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts]) fi parport_use_giveio=yes if test x$build_buspirate = xyes; then AC_MSG_ERROR([buspirate currently not supported by MinGW32 hosts]) fi CFLAGS="$CFLAGS -D__USE_MINGW_ANSI_STDIO" AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ;; *darwin*) is_darwin=yes if test x$parport_use_giveio = xyes; then AC_MSG_WARN([--enable-parport-giveio cannot be used by Darwin hosts]) fi parport_use_giveio=no AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) AC_DEFINE([IS_DARWIN], [1], [1 if building for Darwin.]) ;; *) if test x$parport_use_giveio = xyes; then AC_MSG_WARN([--enable-parport-giveio cannot be used by ]$host[ hosts]) fi parport_use_giveio=no AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ;; esac if test $is_win32 = yes; then AC_DEFINE([WIN32_LEAN_AND_MEAN], [1], [1 to exclude old conflicting definitions when building on Windows]) fi if test $build_parport = yes; then build_bitbang=yes AC_DEFINE([BUILD_PARPORT], [1], [1 if you want parport.]) else AC_DEFINE([BUILD_PARPORT], [0], [0 if you don't want parport.]) fi if test $build_dummy = yes; then build_bitbang=yes AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.]) else AC_DEFINE([BUILD_DUMMY], [0], [0 if you don't want dummy driver.]) fi if test $build_ep93xx = yes; then build_bitbang=yes AC_DEFINE([BUILD_EP93XX], [1], [1 if you want ep93xx.]) else AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.]) fi if test $build_zy1000 = yes; then AC_DEFINE([BUILD_ZY1000], [1], [1 if you want ZY1000.]) else AC_DEFINE([BUILD_ZY1000], [0], [0 if you don't want ZY1000.]) fi if test $build_zy1000_master = yes; then AC_DEFINE([BUILD_ZY1000_MASTER], [1], [1 if you want ZY1000 JTAG master registers.]) else AC_DEFINE([BUILD_ZY1000_MASTER], [0], [0 if you don't want ZY1000 JTAG master registers.]) fi if test $build_at91rm9200 = yes; then build_bitbang=yes AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.]) else AC_DEFINE([BUILD_AT91RM9200], [0], [0 if you don't want at91rm9200.]) fi if test $build_bcm2835gpio = yes; then build_bitbang=yes AC_DEFINE([BUILD_BCM2835GPIO], [1], [1 if you want bcm2835gpio.]) else AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.]) fi if test x$parport_use_ppdev = xyes; then AC_DEFINE([PARPORT_USE_PPDEV], [1], [1 if you want parport to use ppdev.]) else AC_DEFINE([PARPORT_USE_PPDEV], [0], [0 if you don't want parport to use ppdev.]) fi if test x$parport_use_giveio = xyes; then AC_DEFINE([PARPORT_USE_GIVEIO], [1], [1 if you want parport to use giveio.]) else AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) fi if test $build_bitbang = yes; then AC_DEFINE([BUILD_BITBANG], [1], [1 if you want a bitbang interface.]) else AC_DEFINE([BUILD_BITBANG], [0], [0 if you don't want a bitbang interface.]) fi if test $build_ft2232_libftdi = yes; then AC_DEFINE([BUILD_FT2232_LIBFTDI], [1], [1 if you want libftdi ft2232.]) else AC_DEFINE([BUILD_FT2232_LIBFTDI], [0], [0 if you don't want libftdi ft2232.]) fi if test $build_ft2232_ftd2xx = yes; then AC_DEFINE([BUILD_FT2232_FTD2XX], [1], [1 if you want ftd2xx ft2232.]) else AC_DEFINE([BUILD_FT2232_FTD2XX], [0], [0 if you don't want ftd2xx ft2232.]) fi if test $build_usb_blaster_libftdi = yes; then AC_DEFINE([BUILD_USB_BLASTER_LIBFTDI], [1], [1 if you want libftdi usb_blaster.]) else AC_DEFINE([BUILD_USB_BLASTER_LIBFTDI], [0], [0 if you don't want libftdi usb_blaster.]) fi if test $build_jtag_vpi = yes; then AC_DEFINE([BUILD_JTAG_VPI], [1], [1 if you want JTAG VPI.]) else AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.]) fi if test $build_usb_blaster_ftd2xx = yes; then AC_DEFINE([BUILD_USB_BLASTER_FTD2XX], [1], [1 if you want ftd2xx usb_blaster.]) else AC_DEFINE([BUILD_USB_BLASTER_FTD2XX], [0], [0 if you don't want ftd2xx usb_blaster.]) fi if test $build_amtjtagaccel = yes; then AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.]) else AC_DEFINE([BUILD_AMTJTAGACCEL], [0], [0 if you don't want the Amontec JTAG-Accelerator driver.]) fi if test $build_gw16012 = yes; then AC_DEFINE([BUILD_GW16012], [1], [1 if you want the Gateworks GW16012 driver.]) else AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) fi if test $build_presto_libftdi = yes; then build_bitq=yes AC_DEFINE([BUILD_PRESTO_LIBFTDI], [1], [1 if you want the ASIX PRESTO driver using libftdi.]) else AC_DEFINE([BUILD_PRESTO_LIBFTDI], [0], [0 if you don't want the ASIX PRESTO driver using libftdi.]) fi if test $build_presto_ftd2xx = yes; then build_bitq=yes AC_DEFINE([BUILD_PRESTO_FTD2XX], [1], [1 if you want the ASIX PRESTO driver using FTD2XX.]) else AC_DEFINE([BUILD_PRESTO_FTD2XX], [0], [0 if you don't want the ASIX PRESTO driver using FTD2XX.]) fi if test $build_bitq = yes; then AC_DEFINE([BUILD_BITQ], [1], [1 if you want a bitq interface.]) else AC_DEFINE([BUILD_BITQ], [0], [0 if you don't want a bitq interface.]) fi AC_DEFINE([BUILD_OPENJTAG], [0], [0 if you don't want the OpenJTAG driver.]) AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [0], [0 if you don't want the OpenJTAG driver with FTD2XX driver.]) AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [0], [0 if you don't want to build OpenJTAG driver with libftdi.]) if test $build_openjtag_ftd2xx = yes; then AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG driver.]) AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [1], [1 if you want the OpenJTAG driver with FTD2XX driver.]) fi if test $build_openjtag_ftdi = yes; then AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG drvier.]) AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [1], [1 if you want to build OpenJTAG with FTDI driver.]) fi if test $build_oocd_trace = yes; then AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.]) else AC_DEFINE([BUILD_OOCD_TRACE], [0], [0 if you don't want the OpenOCD+trace ETM capture driver.]) fi if test $build_buspirate = yes; then AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.]) else AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.]) fi if test $use_internal_jimtcl = yes; then if test -f "$srcdir/jimtcl/configure.ac"; then AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim]) else AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.]) fi fi if test $build_remote_bitbang = yes; then build_bitbang=yes AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.]) else AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang JTAG driver.]) fi if test $build_sysfsgpio = yes; then build_bitbang=yes AC_DEFINE([BUILD_SYSFSGPIO], [1], [1 if you want the SysfsGPIO driver.]) else AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) fi #-- Deal with MingW/Cygwin FTD2XX issues if test $is_win32 = yes; then if test "${with_ftd2xx_linux_tardir+set}" = set then AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then AC_MSG_CHECKING([for ftd2xx.lib exists (win32)]) # if we are given a zipdir... if test "${with_ftd2xx_win32_zipdir+set}" = set then # Set the CFLAGS for "ftd2xx.h" f=$with_ftd2xx_win32_zipdir/ftd2xx.h if test ! -f $f ; then AC_MSG_ERROR([File: $f cannot be found]) fi CFLAGS="$CFLAGS -I$with_ftd2xx_win32_zipdir" # And calculate the LDFLAGS for the machine case "$host_cpu" in i?86|x86_32) LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/i386" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/i386/ftd2xx.lib ;; amd64|x86_64) LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/amd64" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/amd64/ftd2xx.lib ;; *) AC_MSG_ERROR([Unknown Win32 host cpu: $host_cpu]) ;; esac if test ! -f $f ; then AC_MSG_ERROR([Library: $f not found]) fi else LIBS="$LIBS -lftd2xx" AC_MSG_WARN([ASSUMPTION: The (win32) FTDICHIP.COM files: ftd2xx.h and ftd2xx.lib are in a proper place]) fi fi fi # win32 if test $is_darwin = yes ; then if test "${with_ftd2xx_win32_zipdir+set}" = set then AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) fi if test "${with_ftd2xx_linux_tardir+set}" = set then AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then AC_MSG_CHECKING([for libftd2xx.a (darwin)]) if test ! -f /usr/local/include/ftd2xx.h ; then AC_MSG_ERROR([ftd2xx library from FTDICHIP.com seems to be missing, cannot find: /usr/local/include/ftd2xx.h]) fi CFLAGS="$CFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lftd2xx" AC_MSG_RESULT([-L/usr/local/lib -lftd2xx]) fi fi # darwin if test $is_win32 = no && test $is_darwin = no ; then if test "${with_ftd2xx_win32_zipdir+set}" = set then AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) fi if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then # Must be linux if test $host_os != linux-gnu && test $host_os != linux ; then AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-ft2232-libftdi instead]) fi # Are we given a TAR directory? if test "${with_ftd2xx_linux_tardir+set}" = set then AC_MSG_CHECKING([uninstalled ftd2xx distribution]) # The .H file is simple.. FTD2XX_H=$with_ftd2xx_linux_tardir/ftd2xx.h if test ! -f "${FTD2XX_H}"; then AC_MSG_ERROR([Option: --with-ftd2xx-linux-tardir appears wrong, cannot find: ${FTD2XX_H}]) fi CFLAGS="$CFLAGS -I$with_ftd2xx_linux_tardir" if test $with_ftd2xx_lib = shared; then FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir" FTD2XX_LIB="-lftd2xx" else # Test #1 - v1.0.x case "$host_cpu" in i?86|x86_32) dir=build/i386;; amd64|x86_64) dir=build/x86_64;; *) dir=none;; esac if test -f "$with_ftd2xx_linux_tardir/$dir/libftd2xx.a"; then FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir/$dir" # Also needs -lrt FTD2XX_LIB="-lftd2xx -lrt" else # Test Number2. # Grr.. perhaps it exists as a version number? FTD2XX_LIB="$with_ftd2xx_linux_tardir/static_lib/libftd2xx.a.*.*.*" count=`ls ${FTD2XX_LIB} | wc -l` if test $count -gt 1 ; then AC_MSG_ERROR([Multiple libftd2xx.a files found in: $with_ftd2xx_linux_tardir/static_lib sorry cannot handle this yet]) fi if test $count -ne 1 ; then AC_MSG_ERROR([Not found: $f, option: --with-ftd2xx-linux-tardir appears to be wrong]) fi # Because the "-l" rules do not understand version numbers... # we will just stuff the absolute path onto the LIBS variable FTD2XX_LIB="`ls ${FTD2XX_LIB}` -lpthread" FTD2XX_LDFLAGS="" fi fi LDFLAGS="${LDFLAGS} ${FTD2XX_LDFLAGS}" LIBS="${FTD2XX_LIB} ${LIBS}" AC_MSG_RESULT([${FTD2XX_LDFLAGS} ${FTD2XX_LIB}]) else AC_CHECK_HEADER([ftd2xx.h],[],[ AC_MSG_ERROR([You seem to be missing the FTD2xx driver header file.]) ]) AC_SEARCH_LIBS([FT_GetLibraryVersion],[ftd2xx],,[ AC_MSG_ERROR([You appear to be missing the FTD2xx driver library.]) ],[-lrt -lusb-1.0]) fi fi fi # linux if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then # Before we go any further - make sure we can *BUILD* and *RUN* # a simple app with the "ftd2xx.lib" file - in what ever form we where given # We should be able to compile, link and run this test program now AC_MSG_CHECKING([whether ftd2xx library works]) # # Save the LDFLAGS for later.. LDFLAGS_SAVE=$LDFLAGS CFLAGS_SAVE=$CFLAGS _LDFLAGS=`eval echo $LDFLAGS` _CFLAGS=`eval echo $CFLAGS` LDFLAGS=$_LDFLAGS CFLAGS=$_CFLAGS AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include ]], [[ DWORD x; FT_GetLibraryVersion( &x ); ]])], [ AC_MSG_RESULT([Success!]) ], [ AC_MSG_ERROR([Cannot build & run test program using ftd2xx.lib]) ], [ AC_MSG_RESULT([Skipping as we are cross-compiling]) ]) AC_MSG_CHECKING([for ftd2xx highspeed device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include DWORD x = FT_DEVICE_4232H; ]], [])], [ AC_DEFINE([BUILD_FT2232_HIGHSPEED], [1], [Support FT2232H/FT4232HS with FTD2XX or libftdi.]) build_ft2232_highspeed=yes ], [ build_ft2232_highspeed=no ]) AC_MSG_RESULT([$build_ft2232_highspeed]) if test $build_ft2232_highspeed = no; then AC_MSG_WARN([You need a newer FTD2XX driver (version 2.04.16 or later).]) fi AC_MSG_CHECKING([for ftd2xx FT232H device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include "confdefs.h" #if IS_WIN32 #include "windows.h" #endif #include #include DWORD x = FT_DEVICE_232H; ]], [])], [ AC_DEFINE([HAS_ENUM_FT232H], [1], [Support FT232H with FTD2XX or libftdi.]) has_enum_ft232h=yes ], [ has_enum_ft232h=no ]) AC_MSG_RESULT([$has_enum_ft232h]) if test $has_enum_ft232h = no; then AC_MSG_WARN([You need a newer FTD2XX driver (version 2.08.12 or later).]) fi LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE fi if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes -o \ $build_openjtag_ftdi = yes -o $build_presto_libftdi = yes; then # we can have libftdi or libftdi1, so check it and use the latest one PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [use_libftdi=no]) if test $use_libftdi = no; then PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) fi if test $use_libftdi = no; then AC_MSG_ERROR([The libftdi driver is not present on your system.]) fi # # Try to build a small program. AC_MSG_CHECKING([Build & Link with libftdi...]) LDFLAGS_SAVE=$LDFLAGS CFLAGS_SAVE=$CFLAGS LIBS_SAVE=$LIBS _LDFLAGS=`eval echo $LDFLAGS` _CFLAGS=`eval echo $CFLAGS` _LIBS=`eval echo $LIBS` LDFLAGS=$_LDFLAGS CFLAGS="$_CFLAGS $LIBFTDI_CFLAGS" LIBS="$_LIBS $LIBFTDI_LIBS" AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct ftdi_context *p; p = ftdi_new(); if( p != NULL ){ return 0; } else { fprintf( stderr, "calling ftdi_new() failed\n"); return 1; } ]])], [ AC_MSG_RESULT([Success]) ], [ AC_MSG_ERROR([Cannot build & run test program using libftdi]) ], [ AC_MSG_RESULT([Skipping as we are cross-compiling, trying build only]) AC_SEARCH_LIBS([ftdi_new], [], [], [AC_MSG_ERROR([Cannot link with libftdi])]) ]) AC_MSG_CHECKING([for libftdi highspeed device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ enum ftdi_chip_type x = TYPE_2232H; ]])], [ AC_DEFINE([BUILD_FT2232_HIGHSPEED], [1], [Support FT2232H/FT4232HS with FTD2XX or libftdi.]) build_ft2232_highspeed=yes ], [ build_ft2232_highspeed=no ]) AC_MSG_RESULT([$build_ft2232_highspeed]) if test $build_ft2232_highspeed = no; then AC_MSG_WARN([You need a newer libftdi version (0.16 or later).]) fi AC_MSG_CHECKING([for libftdi FT232H device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ enum ftdi_chip_type x = TYPE_232H; ]])], [ AC_DEFINE([HAS_ENUM_FT232H], [1], [Support FT232H with FTD2XX or libftdi.]) has_enum_ft232h=yes ], [ has_enum_ft232h=no ]) AC_MSG_RESULT([$has_enum_ft232h]) if test $has_enum_ft232h = no; then AC_MSG_WARN([You need a newer libftdi version (0.20 or later).]) fi # Restore the 'unexpanded ldflags' LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE LIBS=$LIBS_SAVE fi PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x]) PKG_CHECK_EXISTS([libusb-1.0 >= 1.0.9], [AC_DEFINE([HAVE_LIBUSB_ERROR_NAME], [1], [Define if your libusb has libusb_error_name()])], [AC_MSG_WARN([libusb-1.x older than 1.0.9 detected, consider updating])]) LIBUSB1_CFLAGS=`echo $LIBUSB1_CFLAGS | sed 's/-I/-isystem /'` AC_MSG_NOTICE([libusb-1.0 header bug workaround: LIBUSB1_CFLAGS changed to "$LIBUSB1_CFLAGS"]) ], [ use_libusb1=no AC_MSG_WARN([libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead]) ]) PKG_CHECK_MODULES([LIBUSB0], [libusb], [use_libusb0=yes], [use_libusb0=no]) for hidapi_lib in hidapi hidapi-hidraw hidapi-libusb; do PKG_CHECK_MODULES([HIDAPI],[$hidapi_lib],[ use_hidapi=yes break ],[ use_hidapi=no ]) done m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ if test $2; then if test $ADAPTER_VAR([adapter]) != no; then AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).) else AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) fi else if test $ADAPTER_VAR([adapter]) = yes; then AC_MSG_ERROR([$3 is required for the ADAPTER_DESC([adapter])]) fi ADAPTER_VAR([adapter])=no fi AM_CONDITIONAL(ADAPTER_SYM([adapter]), [test $ADAPTER_VAR([adapter]) != no]) ]) ]) PROCESS_ADAPTERS([USB1_ADAPTERS], [$use_libusb1 = yes], [libusb-1.x]) PROCESS_ADAPTERS([USB_ADAPTERS], [$use_libusb1 = yes -o $use_libusb0 = yes], [libusb-1.x or libusb-0.1]) PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi]) if test $enable_stlink != no -o $enable_ti_icdi != no; then AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) else AC_DEFINE([BUILD_HLADAPTER], [0], [0 if you want the High Level JTAG driver.]) fi AM_CONDITIONAL([HLADAPTER], [test $enable_stlink != no -o $enable_ti_icdi != no]) AM_CONDITIONAL([RELEASE], [test $build_release = yes]) AM_CONDITIONAL([PARPORT], [test $build_parport = yes]) AM_CONDITIONAL([DUMMY], [test $build_dummy = yes]) AM_CONDITIONAL([GIVEIO], [test x$parport_use_giveio = xyes]) AM_CONDITIONAL([EP93XX], [test $build_ep93xx = yes]) AM_CONDITIONAL([ZY1000], [test $build_zy1000 = yes]) AM_CONDITIONAL([ZY1000_MASTER], [test $build_zy1000_master = yes]) AM_CONDITIONAL([IOUTIL], [test $build_ioutil = yes]) AM_CONDITIONAL([AT91RM9200], [test $build_at91rm9200 = yes]) AM_CONDITIONAL([BCM2835GPIO], [test $build_bcm2835gpio = yes]) AM_CONDITIONAL([BITBANG], [test $build_bitbang = yes]) AM_CONDITIONAL([FT2232_LIBFTDI], [test $build_ft2232_libftdi = yes]) AM_CONDITIONAL([FT2232_DRIVER], [test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes]) AM_CONDITIONAL([USB_BLASTER_LIBFTDI], [test $build_usb_blaster_libftdi = yes]) AM_CONDITIONAL([USB_BLASTER_FTD2XX], [test $build_usb_blaster_ftd2xx = yes]) AM_CONDITIONAL([JTAG_VPI], [test $build_jtag_vpi = yes -o $build_jtag_vpi = yes]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes -o $enable_usb_blaster_2 != no]) AM_CONDITIONAL([AMTJTAGACCEL], [test $build_amtjtagaccel = yes]) AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes]) AM_CONDITIONAL([PRESTO_LIBFTDI], [test $build_presto_libftdi = yes]) AM_CONDITIONAL([PRESTO_DRIVER], [test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes]) AM_CONDITIONAL([OPENJTAG], [test $build_openjtag_ftd2xx = yes -o $build_openjtag_ftdi = yes]) AM_CONDITIONAL([OOCD_TRACE], [test $build_oocd_trace = yes]) AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes]) AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes]) AM_CONDITIONAL([SYSFSGPIO], [test $build_sysfsgpio = yes]) AM_CONDITIONAL([USE_LIBUSB0], [test $use_libusb0 = yes]) AM_CONDITIONAL([USE_LIBUSB1], [test $use_libusb1 = yes]) AM_CONDITIONAL([IS_CYGWIN], [test $is_cygwin = yes]) AM_CONDITIONAL([IS_MINGW], [test $is_mingw = yes]) AM_CONDITIONAL([IS_WIN32], [test $is_win32 = yes]) AM_CONDITIONAL([IS_DARWIN], [test $is_darwin = yes]) AM_CONDITIONAL([BITQ], [test $build_bitq = yes]) AM_CONDITIONAL([CMSIS_DAP], [test $use_hidapi = yes]) AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes]) AM_CONDITIONAL([MINIDRIVER_DUMMY], [test $build_minidriver_dummy = yes]) AM_CONDITIONAL([INTERNAL_JIMTCL], [test $use_internal_jimtcl = yes]) # Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h? AC_MSG_CHECKING([for environ in unistd.h and stdlib.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _GNU_SOURCE #include #include ]], [[char **ep = environ;]] )], [ AC_MSG_RESULT([yes]) has_environ=yes ], [ AC_MSG_RESULT([no]) # Possibility #2: can environ be found in an available library? AC_MSG_CHECKING([for extern environ]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ extern char **environ; ]], [[char **ep = environ;]] )], [ AC_DEFINE(NEED_ENVIRON_EXTERN, [1], [Must declare 'environ' to use it.]) has_environ=yes ], [ has_environ=no ]) AC_MSG_RESULT([${has_environ}]) ]) if test "${has_environ}" != "yes" ; then AC_MSG_FAILURE([Could not find 'environ' in unistd.h or available libraries.]) fi AC_DEFINE([_GNU_SOURCE],[1],[Use GNU C library extensions (e.g. stdndup).]) # set default gcc warnings GCC_WARNINGS="-Wall -Wstrict-prototypes -Wformat-security -Wshadow" if test "${gcc_wextra}" = yes; then GCC_WARNINGS="${GCC_WARNINGS} -Wextra -Wno-unused-parameter" GCC_WARNINGS="${GCC_WARNINGS} -Wbad-function-cast" GCC_WARNINGS="${GCC_WARNINGS} -Wcast-align" GCC_WARNINGS="${GCC_WARNINGS} -Wredundant-decls" fi if test "${gcc_werror}" = yes; then GCC_WARNINGS="${GCC_WARNINGS} -Werror" fi # overide default gcc cflags if test $gcc_warnings = yes; then CFLAGS="$CFLAGS $GCC_WARNINGS" fi AC_CONFIG_FILES([ Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/jtag/drivers/Makefile src/jtag/drivers/usb_blaster/Makefile src/jtag/hla/Makefile src/jtag/aice/Makefile src/transport/Makefile src/target/openrisc/Makefile src/xsvf/Makefile src/svf/Makefile src/target/Makefile src/rtos/Makefile src/server/Makefile src/flash/Makefile src/flash/nor/Makefile src/flash/nand/Makefile src/pld/Makefile doc/Makefile ]) AC_OUTPUT echo echo echo OpenOCD configuration summary echo -------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) case $ADAPTER_VAR([adapter]) in auto) echo "$s"yes '(auto)' ;; yes) echo "$s"yes ;; no) echo "$s"no ;; esac ]) echo if test $build_ft2232_libftdi = yes -o $build_ft2232_ftd2xx = yes; then if test $enable_ftdi = no; then AC_MSG_WARN([Building the deprecated 'ft2232' adapter driver but not its replacement!]) AC_MSG_WARN([Please consider using --enable-ftdi instead.]) else AC_MSG_WARN([Building the deprecated 'ft2232' adapter driver.]) fi fi openocd-0.9.0/config.guess0000755000175000017500000013030512526201646012416 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-08-14' # This 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 2 of the License, or # (at your option) any later version. # # This program 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 . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU/*) eval $set_cc_for_build cat <<-EOF > $dummy.c #include #ifdef __UCLIBC__ # ifdef __UCLIBC_CONFIG_VERSION__ LIBC=uclibc __UCLIBC_CONFIG_VERSION__ # else LIBC=uclibc # endif #else # ifdef __dietlibc__ LIBC=dietlibc # else LIBC=gnu # endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openocd-0.9.0/install-sh0000755000175000017500000003325512526201646012110 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: openocd-0.9.0/NEWTAPS0000644000175000017500000000757512315575360011161 00000000000000Reporting Unknown JTAG TAP IDS ------------------------------ If OpenOCD reports an UNKNOWN or Unexpected Tap ID please report it to the development mailing list - However - keep reading. openocd-devel@lists.sourceforge.net. ======================================== About "UNEXPECTED" tap ids. Before reporting an "UNEXPECTED TAP ID" - take a closer look. Perhaps you have your OpenOCD configured the wrong way, maybe you have the tap configured the wrong way? Or something else is wrong. (Remember: OpenOCD does not stop if the tap is not present) This "tap id check" is there for a purpose. The goal is to help get the *right* configuration. The idea is this: Every JTAG tap is suppose to have "a unique 32bit tap id" number. They are suppose to be "sort of unique" but they are not. There are no guarantees. Version Number Changes: Sometimes, the tap ID only differs by VERSION number. If so - it's not a big deal. Please do report this information. We'd like to know about it. For example Error: ERROR: Tap: s3c4510.cpu - Expected id: 0x3f0f0f0f, Got: 0x1f0f0f0f Error: ERROR: expected: mfg: 0x787, part: 0xf0f0, ver: 0x3 Error: ERROR: got: mfg: 0x787, part: 0xf0f0, ver: 0x1 ======================================== Updating the Tap ID number your self Why do this? You just want the warning to go away. And don't want to update your version/instance of OpenOCD. On simple systems, to fix this problem, in your "openocd.cfg" file, override the tap id. Depending on the tap, add one of these 3 commands: set CPUTAPID newvalue or set BSTAPID newvalue or set FLASHTAPID newvalue or set ETMTAPID newvalue Where "newvalue" is the new value you are seeing. On complex systems, (with many taps and chips) you probably have a custom configuration file. Its is more complicated, you're going to have to read through the configuration files ======================================== What to send: Cut & paste the output of OpenOCD that pointed you at this file. Please include the VERSION number of OpenOCD you are using. And please include the information below. ======================================== A) The JTAG TAP ID code. This is always a 32bit hex number. Examples: 0x1f0f0f0f - is an old ARM7TDMI 0x3f0f0f0f - is a newer ARM7TDMI 0x3ba00477 - is an ARM cortex M3 Some chips have multiple JTAG taps - be sure to list each one individually - ORDER is important! ======================================== B) The maker of the part Examples: Xilinx, Atmel, ST Micro Systems, Freescale ======================================== C) The family of parts it belongs to Examples: "NXP LPC Series" "Atmel SAM7 Series" ======================================== D) The actual part number on the package For example: "S3C45101x01" ======================================== E) What type of board it is. ie: a "commercial off the self eval board" that one can purchase (as opposed to your private internal custom board) For example: ST Micro systems has Eval boards, so does Analog Devices Or - if it is inside something "hackers like to hack" that information is helpful too. For example: A consumer GPS unit or a cellphone ======================================== (F) The maker of the board ie: Olimex, LogicPD, Freescale(eval board) ======================================== (G) Identifying information on the board. Not good: "iar red ST eval board" Really good: "IAR STR912-SK evaluation board" ======================================== (H) Are there other interesting (JTAG) chips on the board? ie: An FPGA or CPLD ... ======================================== (I) What target config files need updating? In fact it's best if you submit a patch with those updates. Most of the other information listed here is just to help create a good patch. ======================================== openocd-0.9.0/config.sub0000755000175000017500000010606012526201646012062 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-08-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This 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 2 of the License, or # (at your option) any later version. # # This program 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 . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx | dvp \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mipsEE* | ee | ps2) basic_machine=mips64r5900el-scei case $os in -linux*) ;; *) os=-elf ;; esac ;; iop) basic_machine=mipsel-scei os=-irx ;; dvp) basic_machine=dvp-scei os=-elf ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -irx* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openocd-0.9.0/missing0000755000175000017500000001533112526201646011476 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program 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 2, or (at your option) # any later version. # This program 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 . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: openocd-0.9.0/config_subdir.m40000644000175000017500000000145312315575360013161 00000000000000dnl dnl If needed, define the m4_ifblank and m4_ifnblank macros from autoconf 2.64 dnl This allows us to run with earlier Autoconfs as well. ifdef([m4_ifblank],[],[ m4_define([m4_ifblank], [m4_if(m4_translit([[$1]], [ ][ ][ ]), [], [$2], [$3])])]) dnl ifdef([m4_ifnblank],[],[ m4_define([m4_ifnblank], [m4_if(m4_translit([[$1]], [ ][ ][ ]), [], [$3], [$2])])]) dnl dnl AC_CONFIG_SUBDIRS does not allow configure options to be passed dnl to subdirs, this function allows that by creating a configure.gnu dnl script that prepends configure options and then calls the real dnl configure script AC_DEFUN([AX_CONFIG_SUBDIR_OPTION], [ AC_CONFIG_SUBDIRS([$1]) m4_ifblank([$2], [rm -f $srcdir/$1/configure.gnu], [echo -e '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" $2 "'\$'@"' > "$srcdir/$1/configure.gnu" ]) ]) openocd-0.9.0/HACKING0000644000175000017500000001612612516456301011070 00000000000000// This file is part of the Doxygen Developer Manual /** @page patchguide Patch Guidelines \attention If you're behind a corporate wall with http only access to the world, you can still use these instructions! \attention You can't send patches to the mailing list anymore at all. Nowadays you are expected to send patches to the OpenOCD Gerrit GIT server for a review. @section gerrit Submitting patches to the OpenOCD Gerrit server OpenOCD is to some extent a "self service" open source project, so to contribute, you must follow the standard procedures to have the best possible chance to get your changes accepted. The procedure to create a patch is essentially: - make the changes - create a commit - send the changes to the Gerrit server for review - correct the patch and re-send it according to review feedback Your patch (or commit) should be a "good patch": focus it on a single issue, and make it be easily reviewable. Don't make it so large that it's hard to review; split large patches into smaller ones. (That can also help track down bugs later on.) All patches should be "clean", which includes preserving the existing coding style and updating documentation as needed. Say in the commit message if it's a bugfix (describe the bug) or a new feature. Don't expect patches to merge immediately for the next release. Be ready to rework patches in response to feedback. Add yourself to the GPL copyright for non-trivial changes. @section stepbystep Step by step procedure -# Create a Gerrit account at: http://openocd.zylin.com - On subsequent sign ins, use the full URL prefaced with 'http://' For example: http://user_identifier.open_id_provider.com -# Add a username to your profile. After creating the Gerrit account and signing in, you will need to add a username to your profile. To do this, go to 'Settings', and add a username of your choice. Your username will be required in step 3 and substituted wherever the string 'USERNAME' is found. -# Create an SSH public key following the directions on github: https://help.github.com/articles/generating-ssh-keys . You can skip step 3 (adding key to Github account) and 4 (testing) - these are useful only if you actually use Github or want to test whether the new key works fine. -# Add this new SSH key to your Gerrit account: go to 'Settings' > 'SSH Public Keys', paste the contents of ~/.ssh/id_rsa.pub into the text field (if it's not visible click on 'Add Key ...' button) and confirm by clicking 'Add' button. -# Clone the git repository, rather than just download the source: @code git clone git://git.code.sf.net/p/openocd/code openocd @endcode or if you have problems with the "git:" protocol, use the slower http protocol: @code git clone http://git.code.sf.net/p/openocd/code openocd @endcode -# Set up Gerrit with your local repository. All this does it to instruct git locally how to send off the changes. -# Add a new remote to git using Gerrit username: @code git remote add review ssh://USERNAME@openocd.zylin.com:29418/openocd.git git config remote.review.push HEAD:refs/publish/master @endcode Or with http only: @code git remote add review http://USERNAME@openocd.zylin.com/p/openocd.git git config remote.review.push HEAD:refs/publish/master @endcode The http password is configured from your gerrit settings - http://openocd.zylin.com/#/settings/http-password. \note If you want to simplify http access you can also add your http password to the url as follows: @code git remote add review http://USERNAME:PASSWORD@openocd.zylin.com/p/openocd.git @endcode -# You will need to install this hook, we will look into a better solution: @code scp -p -P 29418 USERNAME@openocd.zylin.com:hooks/commit-msg .git/hooks/ @endcode Or with http only: @code wget http://openocd.zylin.com/tools/hooks/commit-msg mv commit-msg .git/hooks chmod +x .git/hooks/commit-msg @endcode \note A script exists to simplify the two items above. execute: @code tools/initial.sh @endcode With @ being your Gerrit username. -# Set up git with your name and email: @code git config --global user.name "John Smith" git config --global user.email "john@smith.org" @endcode -# Work on your patches. Split the work into multiple small patches that can be reviewed and applied seperately and safely to the OpenOCD repository. @code while(!done) { work - edit files using your favorite editor. run "git commit -s -a" to commit all changes. run tools/checkpatch.sh to verify your patch style is ok. } @endcode \note use "git add ." before commit to add new files. Comment template, notice the short first line w/topic. The topic field should identify the main part or subsystem the patch touches. Check git log for examples. @code topic: Short comment Longer comments over several lines, explaining (where applicable) the reason for the patch and the general idea the solution is based on, any major design decisions, etc... Signed-off-by: ... @endcode -# Next you need to make sure that your patches are on top of the latest stuff on the server and that there are no conflicts: @code git pull --rebase origin master @endcode -# Send the patches to the Gerrit server for review: @code git push review @endcode -# Forgot something, want to add more? Just make the changes and do: @code git commit --amend git push review @endcode Further reading: http://www.coreboot.org/Git @section timeline When can I expect my contribution to be committed? The code review is intended to take as long as a week or two to allow maintainers and contributors who work on OpenOCD only in their spare time oportunity to perform a review and raise objections. With Gerrit much of the urgency of getting things committed has been removed as the work in progress is safely stored in Gerrit and available if someone needs to build on your work before it is submitted to the official repository. Another factor that contributes to the desire for longer cool-off times (the time a patch lies around without any further changes or comments), it means that the chances of quality regression on the master branch will be much reduced. If a contributor pushes a patch, it is considered good form if another contributor actually approves and submits that patch. It should be noted that a negative review in Gerrit ("-1" or "-2") may (but does not have to) be disregarded if all conditions listed below are met: - the concerns raised in the review have been addressed (or explained), - reviewer does not re-examine the change in a month, - reviewer does not answer e-mails for another month. @section browsing Browsing Patches All OpenOCD patches can be reviewed here. @section reviewing Reviewing Patches From the main Review page select the patch you want to review and click on that patch. On the appearing page select the download method (top right). Apply the patch. After building and testing you can leave a note with the "Reply" button and mark the patch with -1, 0 and +1. */ /** @file This file contains the @ref patchguide page. */ openocd-0.9.0/Makefile.am0000644000175000017500000000542612315712572012140 00000000000000# not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = gnu 1.6 # make sure we pass the correct jimtcl flags to distcheck DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim nobase_dist_pkgdata_DATA = \ contrib/libdcc/dcc_stdio.c \ contrib/libdcc/dcc_stdio.h \ contrib/libdcc/example.c \ contrib/libdcc/README \ contrib/99-openocd.rules if INTERNAL_JIMTCL SUBDIRS = jimtcl else SUBDIRS = endif SUBDIRS += src doc EXTRA_DIST = \ BUGS \ HACKING \ NEWTAPS \ README.Windows \ README.OSX \ $(wildcard $(srcdir)/NEWS*) \ Doxyfile.in \ tools/logger.pl \ tools/rlink_make_speed_table \ tools/st7_dtc_as \ contrib libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status --recheck docs: pdf html doxygen Doxyfile: $(srcdir)/Doxyfile.in @echo "Creating $@ from $<..." @( \ echo "### @@@ -= DO NOT EDIT THIS FILE =- @@@ ###" && \ echo "### @@@ Make changes to Doxyfile.in @@@ ###" && \ sed -e 's,@srcdir\@,$(srcdir),' \ -e 's,@builddir\@,$(builddir),' \ -e 's,@doxygen_as_html\@,$(doxygen_as_html),' \ -e 's,@doxygen_as_pdf\@,$(doxygen_as_pdf),' $< \ ) > $@ THE_MANUAL = doxygen/latex/refman.pdf doxygen:: $(MAKE) Doxyfile doxygen Doxyfile 2>&1 | perl $(srcdir)/tools/logger.pl > doxygen.log @if [ -f doxygen/latex/refman.tex ]; then \ echo "Creating $(THE_MANUAL)..."; \ $(MAKE) $(THE_MANUAL); \ else \ echo "Skipping Doxygen PDF..."; \ fi $(THE_MANUAL): %.pdf: %.tex -cd $$(dirname $*) && pdflatex $$(basename $*) -cd $$(dirname $*) && pdflatex $$(basename $*) TCL_PATH = tcl # command to find paths of script files, relative to TCL_PATH TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' -o -name '*.txt' | \ sed -e 's,^$(srcdir)/$(TCL_PATH),,' dist-hook: if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \ git --git-dir $(srcdir)/.git log | $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \ fi for i in $$($(TCL_FILES)); do \ j="$(distdir)/$(TCL_PATH)/$$i" && \ mkdir -p "$$(dirname $$j)" && \ $(INSTALL_DATA) $(srcdir)/$(TCL_PATH)/$$i $$j; \ done install-data-hook: for i in $$($(TCL_FILES)); do \ j="$(DESTDIR)$(pkgdatadir)/scripts/$$i" && \ mkdir -p "$$(dirname $$j)" && \ $(INSTALL_DATA) $(srcdir)/$(TCL_PATH)/$$i $$j; \ done uninstall-hook: rm -rf $(DESTDIR)$(pkgdatadir)/scripts distclean-local: rm -rf Doxyfile doxygen rm -f $(srcdir)/jimtcl/configure.gnu DISTCLEANFILES = doxygen.log MAINTAINERCLEANFILES = \ $(srcdir)/INSTALL \ $(srcdir)/configure \ $(srcdir)/Makefile.in \ $(srcdir)/depcomp \ $(srcdir)/config.guess \ $(srcdir)/config.sub \ $(srcdir)/config.h.in \ $(srcdir)/config.h.in~ \ $(srcdir)/compile \ $(srcdir)/ltmain.sh \ $(srcdir)/missing \ $(srcdir)/aclocal.m4 \ $(srcdir)/install-sh openocd-0.9.0/Makefile.in0000644000175000017500000007440312526201646012151 00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/config.h.in $(nobase_dist_pkgdata_DATA) COPYING TODO \ compile config.guess config.sub install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgdatadir)" DATA = $(nobase_dist_pkgdata_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = src doc jimtcl DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).zip GZIP_ENV = --best DIST_TARGETS = dist-bzip2 dist-gzip dist-zip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HIDAPI_CFLAGS = @HIDAPI_CFLAGS@ HIDAPI_LIBS = @HIDAPI_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBFTDI_CFLAGS = @LIBFTDI_CFLAGS@ LIBFTDI_LIBS = @LIBFTDI_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBUSB0_CFLAGS = @LIBUSB0_CFLAGS@ LIBUSB0_LIBS = @LIBUSB0_LIBS@ LIBUSB1_CFLAGS = @LIBUSB1_CFLAGS@ LIBUSB1_LIBS = @LIBUSB1_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ doxygen_as_html = @doxygen_as_html@ doxygen_as_pdf = @doxygen_as_pdf@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = gnu 1.6 # make sure we pass the correct jimtcl flags to distcheck DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim nobase_dist_pkgdata_DATA = \ contrib/libdcc/dcc_stdio.c \ contrib/libdcc/dcc_stdio.h \ contrib/libdcc/example.c \ contrib/libdcc/README \ contrib/99-openocd.rules @INTERNAL_JIMTCL_FALSE@SUBDIRS = src doc @INTERNAL_JIMTCL_TRUE@SUBDIRS = jimtcl src doc EXTRA_DIST = \ BUGS \ HACKING \ NEWTAPS \ README.Windows \ README.OSX \ $(wildcard $(srcdir)/NEWS*) \ Doxyfile.in \ tools/logger.pl \ tools/rlink_make_speed_table \ tools/st7_dtc_as \ contrib THE_MANUAL = doxygen/latex/refman.pdf TCL_PATH = tcl # command to find paths of script files, relative to TCL_PATH TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' -o -name '*.txt' | \ sed -e 's,^$(srcdir)/$(TCL_PATH),,' DISTCLEANFILES = doxygen.log MAINTAINERCLEANFILES = \ $(srcdir)/INSTALL \ $(srcdir)/configure \ $(srcdir)/Makefile.in \ $(srcdir)/depcomp \ $(srcdir)/config.guess \ $(srcdir)/config.sub \ $(srcdir)/config.h.in \ $(srcdir)/config.h.in~ \ $(srcdir)/compile \ $(srcdir)/ltmain.sh \ $(srcdir)/missing \ $(srcdir)/aclocal.m4 \ $(srcdir)/install-sh all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-nobase_dist_pkgdataDATA: $(nobase_dist_pkgdata_DATA) @$(NORMAL_INSTALL) @list='$(nobase_dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(pkgdatadir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(pkgdatadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgdatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-nobase_dist_pkgdataDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-nobase_dist_pkgdataDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: $(am__recursive_targets) all install-am install-data-am \ install-strip uninstall-am .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-local distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-hook install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-nobase_dist_pkgdataDATA \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am uninstall-hook \ uninstall-nobase_dist_pkgdataDATA libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status --recheck docs: pdf html doxygen Doxyfile: $(srcdir)/Doxyfile.in @echo "Creating $@ from $<..." @( \ echo "### @@@ -= DO NOT EDIT THIS FILE =- @@@ ###" && \ echo "### @@@ Make changes to Doxyfile.in @@@ ###" && \ sed -e 's,@srcdir\@,$(srcdir),' \ -e 's,@builddir\@,$(builddir),' \ -e 's,@doxygen_as_html\@,$(doxygen_as_html),' \ -e 's,@doxygen_as_pdf\@,$(doxygen_as_pdf),' $< \ ) > $@ doxygen:: $(MAKE) Doxyfile doxygen Doxyfile 2>&1 | perl $(srcdir)/tools/logger.pl > doxygen.log @if [ -f doxygen/latex/refman.tex ]; then \ echo "Creating $(THE_MANUAL)..."; \ $(MAKE) $(THE_MANUAL); \ else \ echo "Skipping Doxygen PDF..."; \ fi $(THE_MANUAL): %.pdf: %.tex -cd $$(dirname $*) && pdflatex $$(basename $*) -cd $$(dirname $*) && pdflatex $$(basename $*) dist-hook: if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \ git --git-dir $(srcdir)/.git log | $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \ fi for i in $$($(TCL_FILES)); do \ j="$(distdir)/$(TCL_PATH)/$$i" && \ mkdir -p "$$(dirname $$j)" && \ $(INSTALL_DATA) $(srcdir)/$(TCL_PATH)/$$i $$j; \ done install-data-hook: for i in $$($(TCL_FILES)); do \ j="$(DESTDIR)$(pkgdatadir)/scripts/$$i" && \ mkdir -p "$$(dirname $$j)" && \ $(INSTALL_DATA) $(srcdir)/$(TCL_PATH)/$$i $$j; \ done uninstall-hook: rm -rf $(DESTDIR)$(pkgdatadir)/scripts distclean-local: rm -rf Doxyfile doxygen rm -f $(srcdir)/jimtcl/configure.gnu # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openocd-0.9.0/NEWS-0.2.00000644000175000017500000000715412315575360011240 00000000000000The OpenOCD 0.2.0 source archive release includes numerous improvements that were made since the initial 0.1.0 source archive release. Many contributors helped make this release a great success, and the community of developers and maintainers look forward to any response. In addition to the list of changes below, countless bug fixing and cleaning was performed across the tree. Various TCL command parameters must past stricter value checks, and many more error conditions have been handled correctly. These efforts helped to make the 0.2.0 release more stable and robust, though some changes may expose latent bugs in your existing configuration scripts. This release does not maintain backward compatibility in all respects, so some target or configuration scripts may need to be updated. In some cases, you may also see warnings; resolve those, because they indicate commands that will be removed in the future. The following areas of OpenOCD functionality changed in this release: JTAG Layer: - Improves modularity: core, TCL, driver commands, and interface have been separated, encapsulated, and documented for developers. Mostly. - Improves JTAG TAP transition tables: * Makes TAP paths variable length, rather than being fixed at 7 steps. * Fixes problems with some targets that did not like longer paths. - Improves JTAG driver/minidriver modularity and encapsulation. - New drivers: * Adds stub minidriver for developing new embedded JTAG interfaces. - Improves drivers: * ft2232+ftd2xx: + Adds initial high-speed device support: --enable-ftd2xx-highspeed + Supports more types of FTDI-based devices. * jlink: + Works with more versions of the firmware (v3 and newer) + Supports dynamically detects device capabilities and limits * vsllink: + Supports very long scan chains * amtjtagaccel: + Fixes broken ID code detection problems. Target Layer: - New devices: AVR, FA526 - Improved support: ARM ADI, ARM11, MIPS - Numerous other bug fixes and improvements Flash Layer: - Improved drivers: mflash - New drivers: AT91SAM3, AVR, Davinci NAND Board, Interface, and Target Configuration Scripts: - Many new and improved targets and boards are now available. - Better separation of "board" and "target" configuration - Moved all TCL files to top-level "tcl" directory in the source tree - Installation moved from '$pkglibdir/' to '$pkgdatadir/scripts/'. - Site-specific files should be installed under '$pkgdatadir/site/'; files that exist this tree will be used in preference to default distribution configurations in '$pkgdatadir/scripts/'. Documentation: - Updated User Guide: http://openocd.berlios.de/doc/html/index.html * Partially re-written and re-organized. * Standardized presentation for all commands. * Covers many drivers and commands that were previously omitted. * New index for commands and drivers. - Added Developer Manual: http://openocd.berlios.de/doc/doxygen/index.html * Now includes architecture, technical primers, style guides, and more. * Available in-tree and on-line. Build and Release: - Increased configuration and compilation warning coverage. * Use --disable-werror to work around build errors caused by warnings. - Use libtool to produce helper libraries as a step toward "libopenocd". - New processes and scripting to facilitate future source releases. For more details about what has changed since 0.1.0, see the ChangeLog associated with this release. For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES files in the source archive). openocd-0.9.0/NEWS-0.3.00000644000175000017500000000630112315575360011232 00000000000000This file should include highlights of the changes made in the OpenOCD openocd-0.3.0 source archive release. See the repository history for details about what changed, including bugfixes and other issues not mentioned here. JTAG Layer: FT2232H (high speed USB) support doesn't need separate configuration New FT2232H JTAG adapters: Amontec, Olimex, Signalyzer New reset_config options for SRST gating the JTAG clock (or not) TAP declaration no longer requires ircapture and mask attributes Scan chain setup should be more robust, with better diagnostics New TAP events: "post-reset" for TAP-invariant setup code (TAPs not usable yet) "setup" for use once TAPs are addressable (e.g. with ICEpick) Overridable Tcl "init_reset" and "jtag_init" procedures Simple "autoprobe" mechanism to help simplify server setup Boundary Scan: SVF bugfixes ... parsing fixes, better STATE switch conformance XSVF bugfixes ... be more correct, handle Xilinx tool output Target Layer: Warn on use of obsolete numeric target IDs New commands for use with Cortex-M3 processors: "cortex_m3 disassemble" ... Thumb2 disassembly (UAL format) "cortex_m3 vector_catch" ... traps certain hardware faults without tying up breakpoint resources If you're willing to help debug it VERY EARLY Cortex-A8 and ARMv7A support Updated BeagleBoard.org hardware support you may need to explicitly "reset" after connect-to-Beagle New commands for use with XScale processors: "xscale vector_table" ARM bugfixes to single-stepping Thumb code ETM: unavailable registers are not listed ETB, ETM: report actual hardware status ARM9 name change: "arm9 vector_catch" not "arm9tdmi vector_catch" ARM11 single stepping support for i.MX31 bugfix for missing "arm11" prefix on "arm11 memwrite ..." GDB support gdb_attach command is gone Flash Layer: The lpc2000 driver handles the new NXP LPC1700 (Cortex-M3) chips New drivers: lpc2900, for NXP LPC2900 chips (ARM968 based) mx3_nand, for imx31 New "last" flag for NOR "flash erase_sector" and "flash protect" The "nand erase N" command now erases all of bank N Speed up davinci_nand by about 3x Board, Target, and Interface Configuration Scripts: Amontec JTAGkey2 support Cleanup and additions for the TI/Luminary Stellaris scripts LPC1768 target (and flash) support Keil MCB1700 eval board Samsung s3c2450 Mini2440 board Numeric TAP and Target identifiers now trigger warnings PXA255 partially enumerates Documentation: Capture more debugging and setup advice Notes on target source code changes that may help debugging Build and Release: Repository moved from SVN at Berlios to GIT at SourceForge Clean builds on (32-bit) Cygwin Clean builds on 64-bit MinGW For more details about what has changed since the last release, see the git repository history. With gitweb, you can browse that in various levels of detail. For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES files in the source archive). openocd-0.9.0/NEWS-0.4.00000644000175000017500000000717412315575360011244 00000000000000This file includes highlights of the changes made in the OpenOCD 0.4.0 source archive release. See the repository history for details about what changed, including bugfixes and other issues not mentioned here. JTAG Layer: Support KT-Link JTAG adapter. Support USB-JTAG, Altera USB-Blaster and compatibles. Boundary Scan: Target Layer: General - Removed commands which have been obsolete for at least a year (from both documentation and, sometimes, code). - new "reset-assert" event, for systems without SRST ARM - supports "reset-assert" event (except on Cortex-M3) - renamed "armv4_5" command prefix as "arm" - recognize TrustZone "Secure Monitor" mode - "arm regs" command output changed - register names use "sp" not "r13" - add top-level "mcr" and "mrc" commands, replacing various core-specific operations - basic semihosting support (ARM7/ARM9 only, for now) ARM11 - Should act much more like other ARM cores: * Preliminary ETM and ETB hookup * accelerated "flash erase_check" * accelerated GDB memory checksum * support "arm regs" command * can access all core modes and registers * watchpoint support - Shares some core debug code with Cortex-A8 Cortex-A8 - Should act much more like other ARM cores: * support "arm regs" command * can access all core modes and registers * watchpoint support - Shares some core debug code with ARM11 Cortex-M3 - Exposed DWT registers like cycle counter - vector_catch settings not clobbered by resets - no longer interferes with firmware's fault handling ETM, ETB - "trigger_percent" command moved ETM --> ETB - "etm trigger_debug" command added MIPS - use fastdata writes Freescale DSP563xx cores (partial support) Flash Layer: 'flash bank' and 'nand device' take as first argument. With this, flash/NAND commands allow referencing banks by name: - : reference the bank with its defined name - [.N]: reference the driver's Nth bank New 'nand verify' command to check bank against an image file. The "flash erase_address" command now rejects partial sectors; previously it would silently erase extra data. If you want to erase the rest of the first and/or last sectors instead of failing, you must pass an explicit "pad" flag. New at91sam9 NAND controller driver. New s3c64xx NAND controller driver. Board, Target, and Interface Configuration Scripts: ARM9 - ETM and ETB hookup for iMX2* targets Add $HOME/.openocd to the search path. Handle Rev C of LM3S811 eval boards. - use "luminary-lm3s811.cfg" for older boards - use "luminary.cfg" for RevC and newer Core Jim/TCL Scripting: New 'usage' command to provide terse command help. Improved command 'help' command output (sorted and indented). Improved command handling: - Most boolean settings now accept any of the following: on/off, enable/disable, true/false, yes/no, 1/0 - More error checking and reporting. Documentation: New built-in command development documentation and primer. Build and Release: Use --enable-doxygen-pdf to build PDF developer documentation. Consider upgrading to libftdi 0.17 if you use that library; it includes bugfixes which improve FT2232H support. For more details about what has changed since the last release, see the git repository history. With gitweb, you can browse that in various levels of detail. For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/NEWS-0.5.00000644000175000017500000000520312315575360011234 00000000000000This file includes highlights of the changes made in the OpenOCD 0.5.0 source archive release. See the repository history for details about what changed, including bugfixes and other issues not mentioned here. JTAG Layer: New driver for "Bus Pirate" Rename various commands so they're not JTAG-specific There are migration procedures for most of these, but you should convert your scripts to the new names, since those procedures will not be around forever. jtag jinterface ... is now adapter_name jtag_khz ... is now adapter_khz jtag_nsrst_delay ... is now adapter_nsrst_delay jtag_nsrst_assert_width ... is now adapter_nsrst_assert_width Support Voipac VPACLink JTAG Adapter. Boundary Scan: Transport framework core ... supporting future work for SWD, SPI, and other non-JTAG ways to debug targets or program flash. Target Layer: ARM: - basic semihosting support for ARMv7M. - renamed "armv7m" command prefix as "arm" MIPS: - "ejtag_srst" variant removed. The same functionality is obtained by using "reset_config none". - added PIC32MX software reset support, this means srst is not required to be connected anymore. OTHER: - preliminary AVR32 AP7000 support. Flash Layer: New "stellaris recover" command, implements the procedure to recover locked devices (restoring non-volatile state to the factory defaults, including erasing the flash and its protection bits, and possibly re-enabling hardware debugging). PIC32MX now uses algorithm for flash programming, this has increased the performance by approx 96%. New 'pic32mx unlock' cmd to remove readout protection. New STM32 Value Line Support. New 'virtual' flash driver, used to associate other addresses with a flash bank. See pic32mx.cfg for usage. New iMX27 NAND flash controller driver. Board, Target, and Interface Configuration Scripts: Support IAR LPC1768 kickstart board (by Olimex) Support Voipac PXA270/PXA270M module. New $PARPORTADDR tcl variable used to change default parallel port address used. Remove lm3s811.cfg; use "stellaris.cfg" instead Core Jim/TCL Scripting: New "add_script_search_dir" command, behaviour is the same as the "-s" cmd line option. Documentation: Build and Release: For more details about what has changed since the last release, see the git repository history. With gitweb, you can browse that in various levels of detail. For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/NEWS-0.6.00000644000175000017500000000333412315575360011240 00000000000000This file includes highlights of the changes made in the OpenOCD source archive release. See the repository history for details about what changed, including bugfixes and other issues not mentioned here. JTAG Layer: New STLINK V1/V2 JTAG/SWD adapter support. New OSJTAG adapter support. New Tincantools Flyswatter2 support. Improved ULINK driver. Improved RLINK driver. Support for adapters based on FT232H chips. New experimental driver for FTDI based adapters, using libusb-1.0 in asynchronous mode. Boundary Scan: Target Layer: New Cortex-M0 support. New Cortex-M4 support. Improved Working area algorithm. New RTOS support. Currently linux, FreeRTOS, ThreadX and eCos. Connecting under reset to Cortex-Mx and MIPS chips. Flash Layer: New SST39WF1601 support. New EN29LV800BB support. New async algorithm support for selected targets, stm32, stellaris and pic32. New Atmel SAM3S, SAM3N support. New ST STM32L support. New Microchip PIC32MX1xx/2xx support. New Freescale Kinetis K40 support. Board, Target, and Interface Configuration Scripts: Support Dangerous Prototypes Bus Blaster. Support ST SPEAr Family. Support Gumstix Verdex boards. Support TI Beaglebone. Documentation: Improved HACKING info for submitting patches. Fixed numerous broken links. Build and Release: For more details about what has changed since the last release, see the git repository history. With gitweb, you can browse that in various levels of detail. For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/NEWS-0.7.00000644000175000017500000000234712315575360011244 00000000000000This file includes highlights of the changes made in the OpenOCD source archive release. See the repository history for details about what changed, including bugfixes and other issues not mentioned here. JTAG Layer: New TI ICDI adapter support. Support Latest OSBDM firmware. Improved MIPS EJTAG Support. Boundary Scan: Target Layer: New ARMv7R and Cortex-R4 support. Added ChibiOS/RT support. Flash Layer: New NXP LPC1850 support. New NXP LPC4300 support. New NXP SPIFI support. New Energy Micro EFM32 support. New ST STM32W support. New ST STM32f2 write protection and lock/unlock support. Ability to override STM32 flash bank size. Board, Target, and Interface Configuration Scripts: Support Freescale i.MX6 series targets. Documentation: New MIPS debugging info. Build and Release: For more details about what has changed since the last release, see the git repository history. With gitweb, you can browse that in various levels of detail. For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/NEWS-0.8.00000644000175000017500000000735312327162142011240 00000000000000This file includes highlights of the changes made in the OpenOCD source archive release. JTAG Layer: * New CMSIS-DAP driver * Andes AICE debug adapter support * New OpenJTAG driver * New BCM2835 (RaspberryPi) driver * JTAG VPI client driver (for OpenRISC Reference Platform SoC) * Xilinx BSCAN_* for OpenRISC support * ST-LINKv2-1 support * ST-LINKv2 SWO tracing support (UART emulation) * JLink-OB (onboard) support * Altera USB Blaster driver rewrite, initial Blaster II support * ULINK driver ported to libusb-1.0, OpenULINK build fixes * Support up to 64 bit IR lengths * SVF playback (FPGA programming) fixes * "ftdi" interface driver got extensive testing and is now recommended over the old ft2232 implementation Boundary Scan: Target Layer: * New target: Andes nds32 * New target: OpenRISC OR1K * New target: Intel Quark X10xx * MIPS EJTAG 1.5/2.0 support * MIPS speed improvements * Cortex-M, Cortex-A (MEM-AP, APB-AP) targets working with BE hosts now * XScale vector_catch support, reset fixes * dsp563xx ad-hoc breakpoint/watchpoint support * RTOS support for embKernel * Target profiling improvements * Memory access functions testbench Flash Layer: * STM32 family sync with reference manuals, other bugfixes * STM32F401, STM32F07x support * Atmel SAM4L, SAMG5x support * at91sam3sd8{a,b}, at91sam3s8{a,b,c}, at91sam4s, at91sam3n0{a,b,0a,0b} support, bugfixes * Atmel SAMD support * Milandr 1986ВЕ* support * Kinetis KL, K21 support * Nuvoton NuMicro MINI5{1,2,4} support * Nuvoton NUC910 series support * NXP LPC43xx, LPC2000 fixes * NXP LPC800, LPC810 support * More ATmega parts supported * Fujitsu MB9Ax family support * EFM32 Wonder Gecko family support * Nordic nRF51 support Board, Target, and Interface Configuration Scripts: * STM32W108xx generic target config * STM32F429 discovery board config * STM32 Nucleo boards configs * DENX M53EVK board config * Altera Cyclone V SoC, SoCkit config * New TI Launchpads board configs * TI am43xx devices, AM437x GP EVM, AM438x ePOS EVM board configs * Marvell Armada 370 family initial support * TI TMDX570LS31USB (TMS570, Cortex-R4) support scripts * Freescale FRDM-KL25Z, KL46Z board configs * Digilent Zedboard config * Asus RT-N16, Linksys WRT54GL, BT HomeHub board configs * Atmel Xplained initial support * Broadcom bcm28155_ap board config * TUMPA, TUMPA Lite interface configs * Digilent JTAG-SMT2 interface config * New RAM testing functions * Easy-to-use firmware recovery helpers targetting ordinary users with common equipment Server Layer: * Auto-generation of GDB target description for ARMv7-M, ARM4, nds32, OR1K, Quark * GDB File-I/O Remote Protocol extension support * Default GDB flashing events handlers to initialise and reset the target automatically when "load" is used Documentation: * Extensive README* changes * The official User's Guide was proofread * Example cross-build script * RTOS documentation improvements * Tcl RPC documentation and examples added Build and Release: * *BSD, OS X, clang, ARM, windows build fixes * New pkg-config support changes the way libusb (and other dependencies) are handled. Many adapter drivers are now selected automatically during the configure stage. This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: http://sourceforge.net/p/openocd/code/ci/v0.8.0/log/?path= For older NEWS, see the NEWS files associated with each release (i.e. NEWS-). For more information about contributing test reports, bug fixes, or new features and device support, please read the new Developer Manual (or the BUGS and PATCHES.txt files in the source archive). openocd-0.9.0/jimtcl/0000755000175000017500000000000012526202232011426 500000000000000openocd-0.9.0/jimtcl/BUGS0000644000175000017500000000003512315602574012040 00000000000000Known bugs ========== None! openocd-0.9.0/jimtcl/TODO0000644000175000017500000000146612315602574012056 00000000000000CORE LANGUAGE FEATURES CORE COMMANDS - [onleave] command, executing something as soon as the current procedure returns. With no arguments it returns the script set, with one appends the onleave script. There should be a way to reset. Currently we have [local] which can be used to delete procs on proc exit. Also try/on/finally. Is [onleave] really needed? OTHER COMMANDS NOT IN TCL BUT THAT SHOULD BE IN JIM - Set commands: [lunion], [lintersect], and [ldifference] EXTENSIONS - Cryptography: hash functions, block ciphers, strim ciphers, PRNGs. - Tuplespace extension (http://wiki.tcl.tk/3947) (using sqlite as backend) - Zlib - Gdlib - CGI (interface compatible with ncgi, but possibly written in C for speed) REFERENCES SYSTEM - Unify ref/getref/setref/collect/finalize under an unique [ref] command. openocd-0.9.0/jimtcl/jim_tcl.txt0000644000175000017500000056552312516456444013567 00000000000000Jim Tcl(n) ========== NAME ---- Jim Tcl v0.76 - reference manual for the Jim Tcl scripting language SYNOPSIS -------- cc -ljim or jimsh [] jimsh -e '' jimsh --version .Quick Index * <> * <> * <> * <> INTRODUCTION ------------ Jim Tcl is a small footprint reimplementation of the Tcl scripting language. The core language engine is compatible with Tcl 8.5+, while implementing a significant subset of the Tcl 8.6 command set, plus additional features available only in Jim Tcl. Some notable differences with Tcl 8.5/8.6 are: 1. Object-based I/O (aio), but with a Tcl-compatibility layer 2. I/O: Support for sockets and pipes including udp, unix domain sockets and IPv6 3. Integers are 64bit 4. Support for references (`ref`/`getref`/`setref`) and garbage collection 5. Builtin dictionary type (`dict`) with some limitations compared to Tcl 8.6 6. `env` command to access environment variables 7. Operating system features: `os.fork`, `os.wait`, `os.uptime`, `signal`, `alarm`, `sleep` 8. Much better error reporting. `info stacktrace` as a replacement for '$errorInfo', '$errorCode' 9. Support for "static" variables in procedures 10. Threads and coroutines are not supported 11. Command and variable traces are not supported 12. Built-in command line editing 13. Expression shorthand syntax: +$(...)+ 14. Modular build allows many features to be omitted or built as dynamic, loadable modules 15. Highly suitable for use in an embedded environment 16. Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets RECENT CHANGES -------------- Changes between 0.75 and 0.76 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Add support for `file link` 2. `glob` now supports the '--tails' option 3. Add support for `string cat` 4. Allow `info source` to add source info Changes between 0.74 and 0.75 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. `binary`, `pack` and `unpack` now support floating point 2. `file copy` '-force' handles source and target as the same file 3. `format` now supports +%b+ for binary conversion 4. `lsort` now supports '-unique' and '-real' 5. Add support for half-close with `aio close` ?r|w? 6. Add `socket pair` for a bidirectional pipe 7. Add '--random-hash' to randomise hash tables for greater security 8. `dict` now supports 'for', 'values', 'incr', 'append', 'lappend', 'update', 'info' and 'replace' 9. `file stat` no longer requires the variable name Changes between 0.73 and 0.74 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Numbers with leading zeros are treated as decimal, not octal 2. Add `aio isatty` 3. Add LFS (64 bit) support for `aio seek`, `aio tell`, `aio copyto`, `file copy` 4. `string compare` and `string equal` now support '-length' 5. `glob` now supports '-directory' Changes between 0.72 and 0.73 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Built-in regexp now support non-capturing parentheses: (?:...) 2. Add `string replace` 3. Add `string totitle` 4. Add `info statics` 5. Add +build-jim-ext+ for easy separate building of loadable modules (extensions) 6. `local` now works with any command, not just procs 7. Add `info alias` to access the target of an alias 8. UTF-8 encoding past the basic multilingual plane (BMP) is supported 9. Add `tcl::prefix` 10. Add `history` 11. Most extensions are now enabled by default 12. Add support for namespaces and the `namespace` command 13. Add `apply` Changes between 0.71 and 0.72 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. procs now allow 'args' and optional parameters in any position 2. Add Tcl-compatible expr functions, `rand()`, `srand()` and `pow()` 3. Add support for the '-force' option to `file delete` 4. Better diagnostics when `source` fails to load a script with a missing quote or bracket 5. New +tcl_platform(pathSeparator)+ 6. Add support settings the modification time with `file mtime` 7. `exec` is now fully supported on win32 (mingw32) 8. `file join`, `pwd`, `glob` etc. now work for mingw32 9. Line editing is now supported for the win32 console (mingw32) 10. Add `aio listen` command Changes between 0.70 and 0.71 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Allow 'args' to be renamed in procs 2. Add +$(...)+ shorthand syntax for expressions 3. Add automatic reference variables in procs with +&var+ syntax 4. Support +jimsh --version+ 5. Additional variables in +tcl_platform()+ 6. `local` procs now push existing commands and `upcall` can call them 7. Add `loop` command (TclX compatible) 8. Add `aio buffering` command 9. `info complete` can now return the missing character 10. `binary format` and `binary scan` are now (optionally) supported 11. Add `string byterange` 12. Built-in regexp now support non-greedy repetition (*?, +?, ??) TCL INTRODUCTION ----------------- Tcl stands for 'tool command language' and is pronounced 'tickle.' It is actually two things: a language and a library. First, Tcl is a simple textual language, intended primarily for issuing commands to interactive programs such as text editors, debuggers, illustrators, and shells. It has a simple syntax and is also programmable, so Tcl users can write command procedures to provide more powerful commands than those in the built-in set. Second, Tcl is a library package that can be embedded in application programs. The Tcl library consists of a parser for the Tcl language, routines to implement the Tcl built-in commands, and procedures that allow each application to extend Tcl with additional commands specific to that application. The application program generates Tcl commands and passes them to the Tcl parser for execution. Commands may be generated by reading characters from an input source, or by associating command strings with elements of the application's user interface, such as menu entries, buttons, or keystrokes. When the Tcl library receives commands it parses them into component fields and executes built-in commands directly. For commands implemented by the application, Tcl calls back to the application to execute the commands. In many cases commands will invoke recursive invocations of the Tcl interpreter by passing in additional strings to execute (procedures, looping commands, and conditional commands all work in this way). An application program gains three advantages by using Tcl for its command language. First, Tcl provides a standard syntax: once users know Tcl, they will be able to issue commands easily to any Tcl-based application. Second, Tcl provides programmability. All a Tcl application needs to do is to implement a few application-specific low-level commands. Tcl provides many utility commands plus a general programming interface for building up complex command procedures. By using Tcl, applications need not re-implement these features. Third, Tcl can be used as a common language for communicating between applications. Inter-application communication is not built into the Tcl core described here, but various add-on libraries, such as the Tk toolkit, allow applications to issue commands to each other. This makes it possible for applications to work together in much more powerful ways than was previously possible. Fourth, Jim Tcl includes a command processor, +jimsh+, which can be used to run standalone Tcl scripts, or to run Tcl commands interactively. This manual page focuses primarily on the Tcl language. It describes the language syntax and the built-in commands that will be available in any application based on Tcl. The individual library procedures are described in more detail in separate manual pages, one per procedure. JIMSH COMMAND INTERPRETER ------------------------- A simple, but powerful command processor, +jimsh+, is part of Jim Tcl. It may be invoked in interactive mode as: jimsh or to process the Tcl script in a file with: jimsh filename It may also be invoked to execute an immediate script with: jimsh -e "script" Interactive Mode ~~~~~~~~~~~~~~~~ Interactive mode reads Tcl commands from standard input, evaluates those commands and prints the results. $ jimsh Welcome to Jim version 0.73, Copyright (c) 2005-8 Salvatore Sanfilippo . info version 0.73 . lsort [info commands p*] package parray pid popen proc puts pwd . foreach i {a b c} { {> puts $i {> } a b c . bad invalid command name "bad" [error] . exit $ If +jimsh+ is configured with line editing (it is by default) and a VT-100-compatible terminal is detected, Emacs-style line editing commands are available, including: arrow keys, +\^W+ to erase a word, +\^U+ to erase the line, +^R+ for reverse incremental search in history. Additionally, the +h+ command may be used to display the command history. Command line history is automatically saved and loaded from +~/.jim_history+ In interactive mode, +jimsh+ automatically runs the script +~/.jimrc+ at startup if it exists. INTERPRETERS ------------ The central data structure in Tcl is an interpreter (C type 'Jim_Interp'). An interpreter consists of a set of command bindings, a set of variable values, and a few other miscellaneous pieces of state. Each Tcl command is interpreted in the context of a particular interpreter. Some Tcl-based applications will maintain multiple interpreters simultaneously, each associated with a different widget or portion of the application. Interpreters are relatively lightweight structures. They can be created and deleted quickly, so application programmers should feel free to use multiple interpreters if that simplifies the application. DATA TYPES ---------- Tcl supports only one type of data: strings. All commands, all arguments to commands, all command results, and all variable values are strings. Where commands require numeric arguments or return numeric results, the arguments and results are passed as strings. Many commands expect their string arguments to have certain formats, but this interpretation is up to the individual commands. For example, arguments often contain Tcl command strings, which may get executed as part of the commands. The easiest way to understand the Tcl interpreter is to remember that everything is just an operation on a string. In many cases Tcl constructs will look similar to more structured constructs from other languages. However, the Tcl constructs are not structured at all; they are just strings of characters, and this gives them a different behaviour than the structures they may look like. Although the exact interpretation of a Tcl string depends on who is doing the interpretation, there are three common forms that strings take: commands, expressions, and lists. The major sections below discuss these three forms in more detail. BASIC COMMAND SYNTAX -------------------- The Tcl language has syntactic similarities to both the Unix shells and Lisp. However, the interpretation of commands is different in Tcl than in either of those other two systems. A Tcl command string consists of one or more commands separated by newline characters or semi-colons. Each command consists of a collection of fields separated by white space (spaces or tabs). The first field must be the name of a command, and the additional fields, if any, are arguments that will be passed to that command. For example, the command: set a 22 has three fields: the first, `set`, is the name of a Tcl command, and the last two, 'a' and '22', will be passed as arguments to the `set` command. The command name may refer either to a built-in Tcl command, an application-specific command bound in with the library procedure 'Jim_CreateCommand', or a command procedure defined with the `proc` built-in command. Arguments are passed literally as text strings. Individual commands may interpret those strings in any fashion they wish. The `set` command, for example, will treat its first argument as the name of a variable and its second argument as a string value to assign to that variable. For other commands arguments may be interpreted as integers, lists, file names, or Tcl commands. Command names should normally be typed completely (e.g. no abbreviations). However, if the Tcl interpreter cannot locate a command it invokes a special command named `unknown` which attempts to find or create the command. For example, at many sites `unknown` will search through library directories for the desired command and create it as a Tcl procedure if it is found. The `unknown` command often provides automatic completion of abbreviated commands, but usually only for commands that were typed interactively. It's probably a bad idea to use abbreviations in command scripts and other forms that will be re-used over time: changes to the command set may cause abbreviations to become ambiguous, resulting in scripts that no longer work. COMMENTS -------- If the first non-blank character in a command is +\#+, then everything from the +#+ up through the next newline character is treated as a comment and ignored. When comments are embedded inside nested commands (e.g. fields enclosed in braces) they must have properly-matched braces (this is necessary because when Tcl parses the top-level command it doesn't yet know that the nested field will be used as a command so it cannot process the nested comment character as a comment). GROUPING ARGUMENTS WITH DOUBLE-QUOTES ------------------------------------- Normally each argument field ends at the next white space, but double-quotes may be used to create arguments with embedded space. If an argument field begins with a double-quote, then the argument isn't terminated by white space (including newlines) or a semi-colon (see below for information on semi-colons); instead it ends at the next double-quote character. The double-quotes are not included in the resulting argument. For example, the command set a "This is a single argument" will pass two arguments to `set`: 'a' and 'This is a single argument'. Within double-quotes, command substitutions, variable substitutions, and backslash substitutions still occur, as described below. If the first character of a command field is not a quote, then quotes receive no special interpretation in the parsing of that field. GROUPING ARGUMENTS WITH BRACES ------------------------------ Curly braces may also be used for grouping arguments. They are similar to quotes except for two differences. First, they nest; this makes them easier to use for complicated arguments like nested Tcl command strings. Second, the substitutions described below for commands, variables, and backslashes do *not* occur in arguments enclosed in braces, so braces can be used to prevent substitutions where they are undesirable. If an argument field begins with a left brace, then the argument ends at the matching right brace. Tcl will strip off the outermost layer of braces and pass the information between the braces to the command without any further modification. For example, in the command set a {xyz a {b c d}} the `set` command will receive two arguments: 'a' and 'xyz a {b c d}'. When braces or quotes are in effect, the matching brace or quote need not be on the same line as the starting quote or brace; in this case the newline will be included in the argument field along with any other characters up to the matching brace or quote. For example, the `eval` command takes one argument, which is a command string; `eval` invokes the Tcl interpreter to execute the command string. The command eval { set a 22 set b 33 } will assign the value '22' to 'a' and '33' to 'b'. If the first character of a command field is not a left brace, then neither left nor right braces in the field will be treated specially (except as part of variable substitution; see below). COMMAND SUBSTITUTION WITH BRACKETS ---------------------------------- If an open bracket occurs in a field of a command, then command substitution occurs (except for fields enclosed in braces). All of the text up to the matching close bracket is treated as a Tcl command and executed immediately. Then the result of that command is substituted for the bracketed text. For example, consider the command set a [set b] When the `set` command has only a single argument, it is the name of a variable and `set` returns the contents of that variable. In this case, if variable 'b' has the value 'foo', then the command above is equivalent to the command set a foo Brackets can be used in more complex ways. For example, if the variable 'b' has the value 'foo' and the variable 'c' has the value 'gorp', then the command set a xyz[set b].[set c] is equivalent to the command set a xyzfoo.gorp A bracketed command may contain multiple commands separated by newlines or semi-colons in the usual fashion. In this case the value of the last command is used for substitution. For example, the command set a x[set b 22 expr $b+2]x is equivalent to the command set a x24x If a field is enclosed in braces then the brackets and the characters between them are not interpreted specially; they are passed through to the argument verbatim. VARIABLE SUBSTITUTION WITH $ ---------------------------- The dollar sign (+$+) may be used as a special shorthand form for substituting variable values. If +$+ appears in an argument that isn't enclosed in braces then variable substitution will occur. The characters after the +$+, up to the first character that isn't a number, letter, or underscore, are taken as a variable name and the string value of that variable is substituted for the name. For example, if variable 'foo' has the value 'test', then the command set a $foo.c is equivalent to the command set a test.c There are two special forms for variable substitution. If the next character after the name of the variable is an open parenthesis, then the variable is assumed to be an array name, and all of the characters between the open parenthesis and the next close parenthesis are taken as an index into the array. Command substitutions and variable substitutions are performed on the information between the parentheses before it is used as an index. For example, if the variable 'x' is an array with one element named 'first' and value '87' and another element named '14' and value 'more', then the command set a xyz$x(first)zyx is equivalent to the command set a xyz87zyx If the variable 'index' has the value '14', then the command set a xyz$x($index)zyx is equivalent to the command set a xyzmorezyx For more information on arrays, see VARIABLES AND ARRAYS below. The second special form for variables occurs when the dollar sign is followed by an open curly brace. In this case the variable name consists of all the characters up to the next curly brace. Array references are not possible in this form: the name between braces is assumed to refer to a scalar variable. For example, if variable 'foo' has the value 'test', then the command set a abc${foo}bar is equivalent to the command set a abctestbar Variable substitution does not occur in arguments that are enclosed in braces: the dollar sign and variable name are passed through to the argument verbatim. The dollar sign abbreviation is simply a shorthand form. +$a+ is completely equivalent to +[set a]+; it is provided as a convenience to reduce typing. SEPARATING COMMANDS WITH SEMI-COLONS ------------------------------------ Normally, each command occupies one line (the command is terminated by a newline character). However, semi-colon (+;+) is treated as a command separator character; multiple commands may be placed on one line by separating them with a semi-colon. Semi-colons are not treated as command separators if they appear within curly braces or double-quotes. BACKSLASH SUBSTITUTION ---------------------- Backslashes may be used to insert non-printing characters into command fields and also to insert special characters like braces and brackets into fields without them being interpreted specially as described above. The backslash sequences understood by the Tcl interpreter are listed below. In each case, the backslash sequence is replaced by the given character: [[BackslashSequences]] +{backslash}b+:: Backspace (0x8) +{backslash}f+:: Form feed (0xc) +{backslash}n+:: Newline (0xa) +{backslash}r+:: Carriage-return (0xd). +{backslash}t+:: Tab (0x9). +{backslash}v+:: Vertical tab (0xb). +{backslash}{+:: Left brace ({). +{backslash}}+:: Right brace (}). +{backslash}[+:: Open bracket ([). +{backslash}]+:: Close bracket (]). +{backslash}$+:: Dollar sign ($). +{backslash}+:: Space ( ): doesn't terminate argument. +{backslash};+:: Semi-colon: doesn't terminate command. +{backslash}"+:: Double-quote. +{backslash}+:: Nothing: this joins two lines together into a single line. This backslash feature is unique in that it will be applied even when the sequence occurs within braces. +{backslash}{backslash}+:: Backslash ('{backslash}'). +{backslash}ddd+:: The digits +'ddd'+ (one, two, or three of them) give the octal value of the character. Note that Jim supports null characters in strings. +{backslash}unnnn+:: +{backslash}u\{nnn\}+:: +{backslash}Unnnnnnnn+:: The UTF-8 encoding of the unicode codepoint represented by the hex digits, +'nnnn'+, is inserted. The 'u' form allows for one to four hex digits. The 'U' form allows for one to eight hex digits. The 'u\{nnn\}' form allows for one to eight hex digits, but makes it easier to insert characters UTF-8 characters which are followed by a hex digit. For example, in the command set a \{x\[\ yz\141 the second argument to `set` will be +{x[ yza+. If a backslash is followed by something other than one of the options described above, then the backslash is transmitted to the argument field without any special processing, and the Tcl scanner continues normal processing with the next character. For example, in the command set \*a \\\{foo The first argument to `set` will be +{backslash}*a+ and the second argument will be +{backslash}{foo+. If an argument is enclosed in braces, then backslash sequences inside the argument are parsed but no substitution occurs (except for backslash-newline): the backslash sequence is passed through to the argument as is, without making any special interpretation of the characters in the backslash sequence. In particular, backslashed braces are not counted in locating the matching right brace that terminates the argument. For example, in the command set a {\{abc} the second argument to `set` will be +{backslash}{abc+. This backslash mechanism is not sufficient to generate absolutely any argument structure; it only covers the most common cases. To produce particularly complicated arguments it is probably easiest to use the `format` command along with command substitution. STRING AND LIST INDEX SPECIFICATIONS ------------------------------------ Many string and list commands take one or more 'index' parameters which specify a position in the string relative to the start or end of the string/list. The index may be one of the following forms: +integer+:: A simple integer, where '0' refers to the first element of the string or list. +integer+integer+ or:: +integer-integer+:: The sum or difference of the two integers. e.g. +2+3+ refers to the 5th element. This is useful when used with (e.g.) +$i+1+ rather than the more verbose +[expr {$i+1\}]+ +end+:: The last element of the string or list. +end-integer+:: The 'nth-from-last' element of the string or list. COMMAND SUMMARY --------------- 1. A command is just a string. 2. Within a string commands are separated by newlines or semi-colons (unless the newline or semi-colon is within braces or brackets or is backslashed). 3. A command consists of fields. The first field is the name of the command. The other fields are strings that are passed to that command as arguments. 4. Fields are normally separated by white space. 5. Double-quotes allow white space and semi-colons to appear within a single argument. Command substitution, variable substitution, and backslash substitution still occur inside quotes. 6. Braces defer interpretation of special characters. If a field begins with a left brace, then it consists of everything between the left brace and the matching right brace. The braces themselves are not included in the argument. No further processing is done on the information between the braces except that backslash-newline sequences are eliminated. 7. If a field doesn't begin with a brace then backslash, variable, and command substitution are done on the field. Only a single level of processing is done: the results of one substitution are not scanned again for further substitutions or any other special treatment. Substitution can occur on any field of a command, including the command name as well as the arguments. 8. If the first non-blank character of a command is a +\#+, everything from the +#+ up through the next newline is treated as a comment and ignored. EXPRESSIONS ----------- The second major interpretation applied to strings in Tcl is as expressions. Several commands, such as `expr`, `for`, and `if`, treat one or more of their arguments as expressions and call the Tcl expression processors ('Jim_ExprLong', 'Jim_ExprBoolean', etc.) to evaluate them. The operators permitted in Tcl expressions are a subset of the operators permitted in C expressions, and they have the same meaning and precedence as the corresponding C operators. Expressions almost always yield numeric results (integer or floating-point values). For example, the expression 8.2 + 6 evaluates to 14.2. Tcl expressions differ from C expressions in the way that operands are specified, and in that Tcl expressions support non-numeric operands and string comparisons. A Tcl expression consists of a combination of operands, operators, and parentheses. White space may be used between the operands and operators and parentheses; it is ignored by the expression processor. Where possible, operands are interpreted as integer values. Integer values may be specified in decimal (the normal case) or in hexadecimal (if the first two characters of the operand are '0x'). Note that Jim Tcl does *not* treat numbers with leading zeros as octal. If an operand does not have one of the integer formats given above, then it is treated as a floating-point number if that is possible. Floating-point numbers may be specified in any of the ways accepted by an ANSI-compliant C compiler (except that the 'f', 'F', 'l', and 'L' suffixes will not be permitted in most installations). For example, all of the following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. If no numeric interpretation is possible, then an operand is left as a string (and only a limited set of operators may be applied to it). 1. Operands may be specified in any of the following ways: 2. As a numeric value, either integer or floating-point. 3. As a Tcl variable, using standard '$' notation. The variable's value will be used as the operand. 4. As a string enclosed in double-quotes. The expression parser will perform backslash, variable, and command substitutions on the information between the quotes, and use the resulting value as the operand 5. As a string enclosed in braces. The characters between the open brace and matching close brace will be used as the operand without any substitutions. 6. As a Tcl command enclosed in brackets. The command will be executed and its result will be used as the operand. Where substitutions occur above (e.g. inside quoted strings), they are performed by the expression processor. However, an additional layer of substitution may already have been performed by the command parser before the expression processor was called. As discussed below, it is usually best to enclose expressions in braces to prevent the command parser from performing substitutions on the contents. For some examples of simple expressions, suppose the variable 'a' has the value 3 and the variable 'b' has the value 6. Then the expression on the left side of each of the lines below will evaluate to the value on the right side of the line: $a + 3.1 6.1 2 + "$a.$b" 5.6 4*[llength "6 2"] 8 {word one} < "word $a" 0 The valid operators are listed below, grouped in decreasing order of precedence: [[OperatorPrecedence]] +int() double() round() abs(), rand(), srand()+:: Unary functions (except rand() which takes no arguments) * +'int()'+ converts the numeric argument to an integer by truncating down. * +'double()'+ converts the numeric argument to floating point. * +'round()'+ converts the numeric argument to the closest integer value. * +'abs()'+ takes the absolute value of the numeric argument. * +'rand()'+ takes the absolute value of the numeric argument. * +'rand()'+ returns a pseudo-random floating-point value in the range (0,1). * +'srand()'+ takes an integer argument to (re)seed the random number generator. Returns the first random number from that seed. +sin() cos() tan() asin() acos() atan() sinh() cosh() tanh() ceil() floor() exp() log() log10() sqrt()+:: Unary math functions. If Jim is compiled with math support, these functions are available. +- + ~ !+:: Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operands may be applied to string operands, and bit-wise NOT may be applied only to integers. +** pow(x,y)+:: Power. e.g. 'x^y^'. If Jim is compiled with math support, supports doubles and integers. Otherwise supports integers only. (Note that the math-function form has the same highest precedence) +* / %+:: Multiply, divide, remainder. None of these operands may be applied to string operands, and remainder may be applied only to integers. ++ -+:: Add and subtract. Valid for any numeric operands. +<< >> <<< >>>+:: Left and right shift, left and right rotate. Valid for integer operands only. +< > \<= >=+:: Boolean less, greater, less than or equal, and greater than or equal. Each operator produces 1 if the condition is true, 0 otherwise. These operators may be applied to strings as well as numeric operands, in which case string comparison is used. +== !=+:: Boolean equal and not equal. Each operator produces a zero/one result. Valid for all operand types. *Note* that values will be converted to integers if possible, then floating point types, and finally strings will be compared. It is recommended that 'eq' and 'ne' should be used for string comparison. +eq ne+:: String equal and not equal. Uses the string value directly without attempting to convert to a number first. +in ni+:: String in list and not in list. For 'in', result is 1 if the left operand (as a string) is contained in the right operand (as a list), or 0 otherwise. The result for +{$a ni $list}+ is equivalent to +{!($a in $list)}+. +&+:: Bit-wise AND. Valid for integer operands only. +|+:: Bit-wise OR. Valid for integer operands only. +^+:: Bit-wise exclusive OR. Valid for integer operands only. +&&+:: Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise. Valid for numeric operands only (integers or floating-point). +||+:: Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. Valid for numeric operands only (integers or floating-point). +x ? y : z+:: If-then-else, as in C. If +'x'+ evaluates to non-zero, then the result is the value of +'y'+. Otherwise the result is the value of +'z'+. The +'x'+ operand must have a numeric value, while +'y'+ and +'z'+ can be of any type. See the C manual for more details on the results produced by each operator. All of the binary operators group left-to-right within the same precedence level. For example, the expression 4*2 < 7 evaluates to 0. The +&&+, +||+, and +?:+ operators have 'lazy evaluation', just as in C, which means that operands are not evaluated if they are not needed to determine the outcome. For example, in $v ? [a] : [b] only one of +[a]+ or +[b]+ will actually be evaluated, depending on the value of +$v+. All internal computations involving integers are done with the C type 'long long' if available, or 'long' otherwise, and all internal computations involving floating-point are done with the C type 'double'. When converting a string to floating-point, exponent overflow is detected and results in a Tcl error. For conversion to integer from string, detection of overflow depends on the behaviour of some routines in the local C library, so it should be regarded as unreliable. In any case, overflow and underflow are generally not detected reliably for intermediate results. Conversion among internal representations for integer, floating-point, and string operands is done automatically as needed. For arithmetic computations, integers are used until some floating-point number is introduced, after which floating-point is used. For example, 5 / 4 yields the result 1, while 5 / 4.0 5 / ( [string length "abcd"] + 0.0 ) both yield the result 1.25. String values may be used as operands of the comparison operators, although the expression evaluator tries to do comparisons as integer or floating-point when it can. If one of the operands of a comparison is a string and the other has a numeric value, the numeric operand is converted back to a string using the C 'sprintf' format specifier '%d' for integers and '%g' for floating-point values. For example, the expressions "0x03" > "2" "0y" < "0x12" both evaluate to 1. The first comparison is done using integer comparison, and the second is done using string comparison after the second operand is converted to the string '18'. In general it is safest to enclose an expression in braces when entering it in a command: otherwise, if the expression contains any white space then the Tcl interpreter will split it among several arguments. For example, the command expr $a + $b results in three arguments being passed to `expr`: +$a+, \+, and +$b+. In addition, if the expression isn't in braces then the Tcl interpreter will perform variable and command substitution immediately (it will happen in the command parser rather than in the expression parser). In many cases the expression is being passed to a command that will evaluate the expression later (or even many times if, for example, the expression is to be used to decide when to exit a loop). Usually the desired goal is to re-do the variable or command substitutions each time the expression is evaluated, rather than once and for all at the beginning. For example, the command for {set i 1} $i<=10 {incr i} {...} ** WRONG ** is probably intended to iterate over all values of +i+ from 1 to 10. After each iteration of the body of the loop, `for` will pass its second argument to the expression evaluator to see whether or not to continue processing. Unfortunately, in this case the value of +i+ in the second argument will be substituted once and for all when the `for` command is parsed. If +i+ was 0 before the `for` command was invoked then the second argument of `for` will be +0\<=10+ which will always evaluate to 1, even though +i+ eventually becomes greater than 10. In the above case the loop will never terminate. Instead, the expression should be placed in braces: for {set i 1} {$i<=10} {incr i} {...} ** RIGHT ** This causes the substitution of 'i' to be delayed; it will be re-done each time the expression is evaluated, which is the desired result. LISTS ----- The third major way that strings are interpreted in Tcl is as lists. A list is just a string with a list-like structure consisting of fields separated by white space. For example, the string Al Sue Anne John is a list with four elements or fields. Lists have the same basic structure as command strings, except that a newline character in a list is treated as a field separator just like space or tab. Conventions for braces and quotes and backslashes are the same for lists as for commands. For example, the string a b\ c {d e {f g h}} is a list with three elements: +a+, +b c+, and +d e {f g h}+. Whenever an element is extracted from a list, the same rules about braces and quotes and backslashes are applied as for commands. Thus in the example above when the third element is extracted from the list, the result is d e {f g h} (when the field was extracted, all that happened was to strip off the outermost layer of braces). Command substitution and variable substitution are never made on a list (at least, not by the list-processing commands; the list can always be passed to the Tcl interpreter for evaluation). The Tcl commands `concat`, `foreach`, `lappend`, `lindex`, `linsert`, `list`, `llength`, `lrange`, `lreplace`, `lsearch`, and `lsort` allow you to build lists, extract elements from them, search them, and perform other list-related functions. Advanced list commands include `lrepeat`, `lreverse`, `lmap`, `lassign`, `lset`. LIST EXPANSION -------------- A new addition to Tcl 8.5 is the ability to expand a list into separate arguments. Support for this feature is also available in Jim. Consider the following attempt to exec a list: set cmd {ls -l} exec $cmd This will attempt to exec the a command named "ls -l", which will clearly not work. Typically eval and concat are required to solve this problem, however it can be solved much more easily with +\{*\}+. exec {*}$cmd This will expand the following argument into individual elements and then evaluate the resulting command. Note that the official Tcl syntax is +\{*\}+, however +\{expand\}+ is retained for backward compatibility with experimental versions of this feature. REGULAR EXPRESSIONS ------------------- Tcl provides two commands that support string matching using regular expressions, `regexp` and `regsub`, as well as `switch -regexp` and `lsearch -regexp`. Regular expressions may be implemented one of two ways. Either using the system's C library POSIX regular expression support, or using the built-in regular expression engine. The differences between these are described below. *NOTE* Tcl 7.x and 8.x use perl-style Advanced Regular Expressions (+ARE+). POSIX Regular Expressions ~~~~~~~~~~~~~~~~~~~~~~~~~ If the system supports POSIX regular expressions, and UTF-8 support is not enabled, this support will be used by default. The type of regular expressions supported are Extended Regular Expressions (+ERE+) rather than Basic Regular Expressions (+BRE+). See REG_EXTENDED in the documentation. Using the system-supported POSIX regular expressions will typically make for the smallest code size, but some features such as UTF-8 and +{backslash}w+, +{backslash}d+, +{backslash}s+ are not supported, and null characters in strings are not supported. See regex(3) and regex(7) for full details. Jim built-in Regular Expressions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Jim built-in regular expression engine may be selected with +./configure --with-jim-regexp+ or it will be selected automatically if UTF-8 support is enabled. This engine supports UTF-8 as well as some +ARE+ features. The differences with both Tcl 7.x/8.x and POSIX are highlighted below. 1. UTF-8 strings and patterns are both supported 2. Supported character classes: +[:alnum:]+, +[:digit:]+ and +[:space:]+ 3. Supported shorthand character classes: +{backslash}w+ = +[:alnum:]+, +{backslash}d+ = +[:digit:],+ +{backslash}s+ = +[:space:]+ 4. Character classes apply to ASCII characters only 5. Supported constraint escapes: +{backslash}m+ = +{backslash}<+ = start of word, +{backslash}M+ = +{backslash}>+ = end of word 6. Backslash escapes may be used within regular expressions, such as +{backslash}n+ = newline, +{backslash}uNNNN+ = unicode 7. Support for the +?+ non-greedy quantifier. e.g. +*?+ 8. Support for non-capuring parentheses +(?:...)+ 9. Jim Tcl considers that both patterns and strings end at a null character (+\x00+) COMMAND RESULTS --------------- Each command produces two results: a code and a string. The code indicates whether the command completed successfully or not, and the string gives additional information. The valid codes are defined in jim.h, and are: +JIM_OK(0)+:: This is the normal return code, and indicates that the command completed successfully. The string gives the command's return value. +JIM_ERR(1)+:: Indicates that an error occurred; the string gives a message describing the error. +JIM_RETURN(2)+:: Indicates that the `return` command has been invoked, and that the current procedure (or top-level command or `source` command) should return immediately. The string gives the return value for the procedure or command. +JIM_BREAK(3)+:: Indicates that the `break` command has been invoked, so the innermost loop should abort immediately. The string should always be empty. +JIM_CONTINUE(4)+:: Indicates that the `continue` command has been invoked, so the innermost loop should go on to the next iteration. The string should always be empty. +JIM_SIGNAL(5)+:: Indicates that a signal was caught while executing a commands. The string contains the name of the signal caught. See the `signal` and `catch` commands. +JIM_EXIT(6)+:: Indicates that the command called the `exit` command. The string contains the exit code. Tcl programmers do not normally need to think about return codes, since +JIM_OK+ is almost always returned. If anything else is returned by a command, then the Tcl interpreter immediately stops processing commands and returns to its caller. If there are several nested invocations of the Tcl interpreter in progress, then each nested command will usually return the error to its caller, until eventually the error is reported to the top-level application code. The application will then display the error message for the user. In a few cases, some commands will handle certain `error` conditions themselves and not return them upwards. For example, the `for` command checks for the +JIM_BREAK+ code; if it occurs, then `for` stops executing the body of the loop and returns +JIM_OK+ to its caller. The `for` command also handles +JIM_CONTINUE+ codes and the procedure interpreter handles +JIM_RETURN+ codes. The `catch` command allows Tcl programs to catch errors and handle them without aborting command interpretation any further. The `info returncodes` command may be used to programmatically map between return codes and names. PROCEDURES ---------- Tcl allows you to extend the command interface by defining procedures. A Tcl procedure can be invoked just like any other Tcl command (it has a name and it receives one or more arguments). The only difference is that its body isn't a piece of C code linked into the program; it is a string containing one or more other Tcl commands. The `proc` command is used to create a new Tcl command procedure: +*proc* 'name arglist ?statics? body'+ The new command is named +'name'+, and it replaces any existing command there may have been by that name. Whenever the new command is invoked, the contents of +'body'+ will be executed by the Tcl interpreter. +'arglist'+ specifies the formal arguments to the procedure. It consists of a list, possibly empty, of the following argument specifiers: +name+:: Required Argument - A simple argument name. +name default+:: Optional Argument - A two-element list consisting of the argument name, followed by the default value, which will be used if the corresponding argument is not supplied. +&name+:: Reference Argument - The caller is expected to pass the name of an existing variable. An implicit `upvar 1 'origname' 'name'` is done to make the variable available in the proc scope. +*args*+:: Variable Argument - The special name +'args'+, which is assigned all remaining arguments (including none) as a list. The variable argument may only be specified once. Note that the syntax +args newname+ may be used to retain the special behaviour of +'args'+ with a different local name. In this case, the variable is named +'newname'+ rather than +'args'+. When the command is invoked, a local variable will be created for each of the formal arguments to the procedure; its value will be the value of corresponding argument in the invoking command or the argument's default value. Arguments with default values need not be specified in a procedure invocation. However, there must be enough actual arguments for all required arguments, and there must not be any extra actual arguments (unless the Variable Argument is specified). Actual arguments are assigned to formal arguments as in left-to-right order with the following precedence. 1. Required Arguments (including Reference Arguments) 2. Optional Arguments 3. Variable Argument The following example illustrates precedence. Assume a procedure declaration: proc p {{a A} args b {c C} d} {...} This procedure requires at least two arguments, but can accept an unlimited number. The following table shows how various numbers of arguments are assigned. Values marked as +-+ are assigned the default value. [width="40%",frame="topbot",options="header"] |============== |Number of arguments|a|args|b|c|d |2|-|-|1|-|2 |3|1|-|2|-|3 |4|1|-|2|3|4 |5|1|2|3|4|5 |6|1|2,3|4|5|6 |============== When +'body'+ is being executed, variable names normally refer to local variables, which are created automatically when referenced and deleted when the procedure returns. One local variable is automatically created for each of the procedure's arguments. Global variables can be accessed by invoking the `global` command or via the +::+ prefix. New in Jim ~~~~~~~~~~ In addition to procedure arguments, Jim procedures may declare static variables. These variables scoped to the procedure and initialised at procedure definition. Either from the static variable definition, or from the enclosing scope. Consider the following example: jim> set a 1 jim> proc a {} {a {b 2}} { set c 1 puts "$a $b $c" incr a incr b incr c } jim> a 1 2 1 jim> a 2 3 1 The static variable +'a'+ has no initialiser, so it is initialised from the enclosing scope with the value 1. (Note that it is an error if there is no variable with the same name in the enclosing scope). However +'b'+ has an initialiser, so it is initialised to 2. Unlike a local variable, the value of a static variable is retained across invocations of the procedure. See the `proc` command for information on how to define procedures and what happens when they are invoked. See also NAMESPACES. VARIABLES - SCALARS AND ARRAYS ------------------------------ Tcl allows the definition of variables and the use of their values either through '$'-style variable substitution, the `set` command, or a few other mechanisms. Variables need not be declared: a new variable will automatically be created each time a new variable name is used. Tcl supports two types of variables: scalars and arrays. A scalar variable has a single value, whereas an array variable can have any number of elements, each with a name (called its 'index') and a value. Array indexes may be arbitrary strings; they need not be numeric. Parentheses are used refer to array elements in Tcl commands. For example, the command set x(first) 44 will modify the element of 'x' whose index is 'first' so that its new value is '44'. Two-dimensional arrays can be simulated in Tcl by using indexes that contain multiple concatenated values. For example, the commands set a(2,3) 1 set a(3,6) 2 set the elements of 'a' whose indexes are '2,3' and '3,6'. In general, array elements may be used anywhere in Tcl that scalar variables may be used. If an array is defined with a particular name, then there may not be a scalar variable with the same name. Similarly, if there is a scalar variable with a particular name then it is not possible to make array references to the variable. To convert a scalar variable to an array or vice versa, remove the existing variable with the `unset` command. The `array` command provides several features for dealing with arrays, such as querying the names of all the elements of the array and converting between an array and a list. Variables may be either global or local. If a variable name is used when a procedure isn't being executed, then it automatically refers to a global variable. Variable names used within a procedure normally refer to local variables associated with that invocation of the procedure. Local variables are deleted whenever a procedure exits. Either `global` command may be used to request that a name refer to a global variable for the duration of the current procedure (this is somewhat analogous to 'extern' in C), or the variable may be explicitly scoped with the +::+ prefix. For example set a 1 set b 2 proc p {} { set c 3 global a puts "$a $::b $c" } p will output: 1 2 3 ARRAYS AS LISTS IN JIM ---------------------- Unlike Tcl, Jim can automatically convert between a list (with an even number of elements) and an array value. This is similar to the way Tcl can convert between a string and a list. For example: set a {1 one 2 two} puts $a(2) will output: two Thus `array set` is equivalent to `set` when the variable does not exist or is empty. The reverse is also true where an array will be converted into a list. set a(1) one; set a(2) two puts $a will output: 1 one 2 two DICTIONARY VALUES ----------------- Tcl 8.5 introduced the dict command, and Jim Tcl has added a version of this command. Dictionaries provide efficient access to key-value pairs, just like arrays, but dictionaries are pure values. This means that you can pass them to a procedure just as a list or a string. Tcl dictionaries are therefore much more like Tcl lists, except that they represent a mapping from keys to values, rather than an ordered sequence. You can nest dictionaries, so that the value for a particular key consists of another dictionary. That way you can elegantly build complicated data structures, such as hierarchical databases. You can also combine dictionaries with other Tcl data structures. For instance, you can build a list of dictionaries that themselves contain lists. Dictionaries are values that contain an efficient, order-preserving mapping from arbitrary keys to arbitrary values. Each key in the dictionary maps to a single value. They have a textual format that is exactly that of any list with an even number of elements, with each mapping in the dictionary being represented as two items in the list. When a command takes a dictionary and produces a new dictionary based on it (either returning it or writing it back into the variable that the starting dictionary was read from) the new dictionary will have the same order of keys, modulo any deleted keys and with new keys added on to the end. When a string is interpreted as a dictionary and it would otherwise have duplicate keys, only the last value for a particular key is used; the others are ignored, meaning that, "apple banana" and "apple carrot apple banana" are equivalent dictionaries (with different string representations). Note that in Jim, arrays are implemented as dictionaries. Thus automatic conversion between lists and dictionaries applies as it does for arrays. jim> dict set a 1 one 1 one jim> dict set a 2 two 1 one 2 two jim> puts $a 1 one 2 two jim> puts $a(2) two jim> dict set a 3 T three 1 one 2 two 3 {T three} See the `dict` command for more details. NAMESPACES ---------- Tcl added namespaces as a mechanism avoiding name clashes, especially in applications including a number of 3rd party components. While there is less need for namespaces in Jim Tcl (which does not strive to support large applications), it is convenient to provide a subset of the support for namespaces to easy porting code from Tcl. Jim Tcl currently supports "light-weight" namespaces which should be adequate for most purposes. This feature is currently experimental. See README.namespaces for more information and the documentation of the `namespace` command. GARBAGE COLLECTION, REFERENCES, LAMBDA -------------------------------------- Unlike Tcl, Jim has some sophisticated support for functional programming. These are described briefly below. More information may be found at http://wiki.tcl.tk/13847 References ~~~~~~~~~~ A reference can be thought of as holding a value with one level of indirection, where the value may be garbage collected when unreferenced. Consider the following example: jim> set r [ref "One String" test] .00000000000000000000> jim> getref $r One String The operation `ref` creates a references to the value specified by the first argument. (The second argument is a "type" used for documentation purposes). The operation `getref` is the dereferencing operation which retrieves the value stored in the reference. jim> setref $r "New String" New String jim> getref $r New String The operation `setref` replaces the value stored by the reference. If the old value is no longer accessible by any reference, it will eventually be automatically be garbage collected. Garbage Collection ~~~~~~~~~~~~~~~~~~ Normally, all values in Tcl are passed by value. As such values are copied and released automatically as necessary. With the introduction of references, it is possible to create values whose lifetime transcend their scope. To support this, case, the Jim system will periodically identify and discard objects which are no longer accessible by any reference. The `collect` command may be used to force garbage collection. Consider a reference created with a finalizer: jim> proc f {ref value} { puts "Finaliser called for $ref,$value" } jim> set r [ref "One String" test f] .00000000000 jim> collect 0 jim> set r "" jim> collect Finaliser called for .00000000000,One String 1 Note that once the reference, 'r', was modified so that it no longer contained a reference to the value, the garbage collector discarded the value (after calling the finalizer). The finalizer for a reference may be examined or changed with the `finalize` command jim> finalize $r f jim> finalize $r newf newf Lambda ~~~~~~ Jim provides a garbage collected lambda function. This is a procedure which is able to create an anonymous procedure. Consider: jim> set f [lambda {a} {{x 0}} { incr x $a }] jim> $f 1 1 jim> $f 2 3 jim> set f "" This create an anonymous procedure (with the name stored in 'f'), with a static variable which is incremented by the supplied value and the result returned. Once the procedure name is no longer accessible, it will automatically be deleted when the garbage collector runs. The procedure may also be delete immediately by renaming it "". e.g. jim> rename $f "" UTF-8 AND UNICODE ----------------- If Jim is built with UTF-8 support enabled (configure --enable-utf), then most string-related commands become UTF-8 aware. These include, but are not limited to, `string match`, `split`, `glob`, `scan` and `format`. UTF-8 encoding has many advantages, but one of the complications is that characters can take a variable number of bytes. Thus the addition of `string bytelength` which returns the number of bytes in a string, while `string length` returns the number of characters. If UTF-8 support is not enabled, all commands treat bytes as characters and `string bytelength` returns the same value as `string length`. Note that even if UTF-8 support is not enabled, the +{backslash}uNNNN+ and related syntax is still available to embed UTF-8 sequences. Jim Tcl supports all currently defined unicode codepoints. That is 21 bits, up to +'U+1FFFFF'. String Matching ~~~~~~~~~~~~~~~ Commands such as `string match`, `lsearch -glob`, `array names` and others use string pattern matching rules. These commands support UTF-8. For example: string match a\[\ua0-\ubf\]b "a\u00a3b" format and scan ~~~~~~~~~~~~~~~ +format %c+ allows a unicode codepoint to be be encoded. For example, the following will return a string with two bytes and one character. The same as +{backslash}ub5+ format %c 0xb5 `format` respects widths as character widths, not byte widths. For example, the following will return a string with three characters, not three bytes. format %.3s \ub5\ub6\ub7\ub8 Similarly, +scan ... %c+ allows a UTF-8 to be decoded to a unicode codepoint. The following will set +'a'+ to 181 (0xb5) and +'b'+ to 65 (0x41). scan \u00b5A %c%c a b `scan %s` will also accept a character class, including unicode ranges. String Classes ~~~~~~~~~~~~~~ `string is` has *not* been extended to classify UTF-8 characters. Therefore, the following will return 0, even though the string may be considered to be alphabetic. string is alpha \ub5Test This does not affect the string classes 'ascii', 'control', 'digit', 'double', 'integer' or 'xdigit'. Case Mapping and Conversion ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Jim provides a simplified unicode case mapping. This means that case conversion and comparison will not increase or decrease the number of characters in a string. (Although it may change the number of bytes). `string toupper` will convert any lowercase letters to their uppercase equivalent. Any character which is not a letter or has no uppercase equivalent is left unchanged. Similarly for `string tolower` and `string totitle`. Commands which perform case insensitive matches, such as `string compare -nocase` and `lsearch -nocase` fold both strings to uppercase before comparison. Invalid UTF-8 Sequences ~~~~~~~~~~~~~~~~~~~~~~~ Some UTF-8 character sequences are invalid, such as those beginning with '0xff', those which represent character sequences longer than 3 bytes (greater than U+FFFF), and those which end prematurely, such as a lone '0xc2'. In these situations, the offending bytes are treated as single characters. For example, the following returns 2. string bytelength \xff\xff Regular Expressions ~~~~~~~~~~~~~~~~~~~ If UTF-8 support is enabled, the built-in regular expression engine will be selected which supports UTF-8 strings and patterns. See REGULAR EXPRESSIONS BUILT-IN COMMANDS ----------------- The Tcl library provides the following built-in commands, which will be available in any application using Tcl. In addition to these built-in commands, there may be additional commands defined by each application, plus commands defined as Tcl procedures. In the command syntax descriptions below, words in +*boldface*+ are literals that you type verbatim to Tcl. Words in +'italics'+ are meta-symbols; they serve as names for any of a range of values that you can type. Optional arguments or groups of arguments are indicated by enclosing them in +?question-marks?+. Ellipses (+\...+) indicate that any number of additional arguments or groups of arguments may appear, in the same format as the preceding argument(s). [[CommandIndex]] Command Index ~~~~~~~~~~~~~ @INSERTINDEX@ alarm ~~~~~ +*alarm* 'seconds'+ Delivers the +SIGALRM+ signal to the process after the given number of seconds. If the platform supports 'ualarm(3)' then the argument may be a floating point value. Otherwise it must be an integer. Note that unless a signal handler for +SIGALRM+ has been installed (see `signal`), the process will exit on this signal. alias ~~~~~ +*alias* 'name args\...'+ Creates a single word alias (command) for one or more words. For example, the following creates an alias for the command `info exists`. alias e info exists if {[e var]} { ... } `alias` returns +'name'+, allowing it to be used with `local`. See also `proc`, `curry`, `lambda`, `local`, `info alias`, `exists -alias` append ~~~~~~ +*append* 'varName value ?value value ...?'+ Append all of the +'value'+ arguments to the current value of variable +'varName'+. If +'varName'+ doesn't exist, it is given a value equal to the concatenation of all the +'value'+ arguments. This command provides an efficient way to build up long variables incrementally. For example, "`append a $b`" is much more efficient than "`set a $a$b`" if +$a+ is long. apply ~~~~~~ +*apply* 'lambdaExpr ?arg1 arg2 \...?'+ The command `apply` provides for anonymous procedure calls, similar to `lambda`, but without command name being created, even temporarily. The function +'lambdaExpr'+ is a two element list +{args body}+ or a three element list +{args body namespace}+. The first element args specifies the formal arguments, in the same form as the `proc` and `lambda` commands. array ~~~~~ +*array* 'option arrayName ?arg\...?'+ This command performs one of several operations on the variable given by +'arrayName'+. Note that in general, if the named array does not exist, the +'array'+ command behaves as though the array exists but is empty. The +'option'+ argument determines what action is carried out by the command. The legal +'options'+ (which may be abbreviated) are: +*array exists* 'arrayName'+:: Returns 1 if arrayName is an array variable, 0 if there is no variable by that name. This command is essentially identical to `info exists` +*array get* 'arrayName ?pattern?'+:: Returns a list containing pairs of elements. The first element in each pair is the name of an element in arrayName and the second element of each pair is the value of the array element. The order of the pairs is undefined. If pattern is not specified, then all of the elements of the array are included in the result. If pattern is specified, then only those elements whose names match pattern (using the matching rules of string match) are included. If arrayName isn't the name of an array variable, or if the array contains no elements, then an empty list is returned. +*array names* 'arrayName ?pattern?'+:: Returns a list containing the names of all of the elements in the array that match pattern. If pattern is omitted then the command returns all of the element names in the array. If pattern is specified, then only those elements whose names match pattern (using the matching rules of string match) are included. If there are no (matching) elements in the array, or if arrayName isn't the name of an array variable, then an empty string is returned. +*array set* 'arrayName list'+:: Sets the values of one or more elements in arrayName. list must have a form like that returned by array get, consisting of an even number of elements. Each odd-numbered element in list is treated as an element name within arrayName, and the following element in list is used as a new value for that array element. If the variable arrayName does not already exist and list is empty, arrayName is created with an empty array value. +*array size* 'arrayName'+:: Returns the number of elements in the array. If arrayName isn't the name of an array then 0 is returned. +*array unset* 'arrayName ?pattern?'+:: Unsets all of the elements in the array that match pattern (using the matching rules of string match). If arrayName isn't the name of an array variable or there are no matching elements in the array, no error will be raised. If pattern is omitted and arrayName is an array variable, then the command unsets the entire array. The command always returns an empty string. break ~~~~~ +*break*+ This command may be invoked only inside the body of a loop command such as `for` or `foreach` or `while`. It returns a +JIM_BREAK+ code to signal the innermost containing loop command to return immediately. case ~~~~ +*case* 'string' ?in? 'patList body ?patList body ...?'+ +*case* 'string' ?in? {'patList body ?patList body ...?'}+ *Note* that the `switch` command should generally be preferred unless compatibility with Tcl 6.x is desired. Match +'string'+ against each of the +'patList'+ arguments in order. If one matches, then evaluate the following +'body'+ argument by passing it recursively to the Tcl interpreter, and return the result of that evaluation. Each +'patList'+ argument consists of a single pattern or list of patterns. Each pattern may contain any of the wild-cards described under `string match`. If a +'patList'+ argument is +default+, the corresponding body will be evaluated if no +'patList'+ matches +'string'+. If no +'patList'+ argument matches +'string'+ and no default is given, then the `case` command returns an empty string. Two syntaxes are provided. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line case commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the +'patList'+ arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behaviour of the second form different than the first form in some cases. Below are some examples of `case` commands: case abc in {a b} {format 1} default {format 2} a* {format 3} will return '3', case a in { {a b} {format 1} default {format 2} a* {format 3} } will return '1', and case xyz { {a b} {format 1} default {format 2} a* {format 3} } will return '2'. catch ~~~~~ +*catch* ?-?no?'code \...'? ?--? 'command ?resultVarName? ?optionsVarName?'+ The `catch` command may be used to prevent errors from aborting command interpretation. `catch` evaluates +'command'+, and returns a +JIM_OK+ code, regardless of any errors that might occur while executing +'command'+ (with the possible exception of +JIM_SIGNAL+ - see below). The return value from `catch` is a decimal string giving the code returned by the Tcl interpreter after executing +'command'+. This will be '0' (+JIM_OK+) if there were no errors in +'command'+; otherwise it will have a non-zero value corresponding to one of the exceptional return codes (see jim.h for the definitions of code values, or the `info returncodes` command). If the +'resultVarName'+ argument is given, then it gives the name of a variable; `catch` will set the value of the variable to the string returned from +'command'+ (either a result or an error message). If the +'optionsVarName'+ argument is given, then it gives the name of a variable; `catch` will set the value of the variable to a dictionary. For any return code other than +JIM_RETURN+, the value for the key +-code+ will be set to the return code. For +JIM_RETURN+ it will be set to the code given in `return -code`. Additionally, for the return code +JIM_ERR+, the value of the key +-errorinfo+ will contain the current stack trace (the same result as `info stacktrace`), the value of the key +-errorcode+ will contain the same value as the global variable $::errorCode, and the value of the key +-level+ will be the current return level (see `return -level`). This can be useful to rethrow an error: if {[catch {...} msg opts]} { ...maybe do something with the error... incr opts(-level) return {*}$opts $msg } Normally `catch` will +'not'+ catch any of the codes +JIM_EXIT+, +JIM_EVAL+ or +JIM_SIGNAL+. The set of codes which will be caught may be modified by specifying the one more codes before +'command'+. e.g. To catch +JIM_EXIT+ but not +JIM_BREAK+ or +JIM_CONTINUE+ catch -exit -nobreak -nocontinue -- { ... } The use of +--+ is optional. It signifies that no more return code options follow. Note that if a signal marked as `signal handle` is caught with `catch -signal`, the return value (stored in +'resultVarName'+) is name of the signal caught. cd ~~ +*cd* 'dirName'+ Change the current working directory to +'dirName'+. Returns an empty string. This command can potentially be disruptive to an application, so it may be removed in some applications. clock ~~~~~ +*clock seconds*+:: Returns the current time as seconds since the epoch. +*clock format* 'seconds' ?*-format* 'format?'+:: Format the given time (seconds since the epoch) according to the given format. See strftime(3) for supported formats. If no format is supplied, "%c" is used. +*clock scan* 'str' *-format* 'format'+:: Scan the given time string using the given format string. See strptime(3) for supported formats. close ~~~~~ +*close* 'fileId'+ +'fileId' *close*+ Closes the file given by +'fileId'+. +'fileId'+ must be the return value from a previous invocation of the `open` command; after this command, it should not be used anymore. collect ~~~~~~~ +*collect*+ Normally reference garbage collection is automatically performed periodically. However it may be run immediately with the `collect` command. See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. concat ~~~~~~ +*concat* 'arg ?arg \...?'+ This command treats each argument as a list and concatenates them into a single list. It permits any number of arguments. For example, the command concat a b {c d e} {f {g h}} will return a b c d e f {g h} as its result. continue ~~~~~~~~ +*continue*+ This command may be invoked only inside the body of a loop command such as `for` or `foreach` or `while`. It returns a +JIM_CONTINUE+ code to signal the innermost containing loop command to skip the remainder of the loop's body but continue with the next iteration of the loop. curry ~~~~~ +*alias* 'args\...'+ Similar to `alias` except it creates an anonymous procedure (lambda) instead of a named procedure. the following creates a local, unnamed alias for the command `info exists`. set e [local curry info exists] if {[$e var]} { ... } `curry` returns the name of the procedure. See also `proc`, `alias`, `lambda`, `local`. dict ~~~~ +*dict* 'option ?arg\...?'+ Performs one of several operations on dictionary values. The +'option'+ argument determines what action is carried out by the command. The legal +'options'+ are: +*dict create* '?key value \...?'+:: Create and return a new dictionary value that contains each of the key/value mappings listed as arguments (keys and values alternating, with each key being followed by its associated value.) +*dict exists* 'dictionary key ?key \...?'+:: Returns a boolean value indicating whether the given key (or path of keys through a set of nested dictionaries) exists in the given dictionary value. This returns a true value exactly when `dict get` on that path will succeed. +*dict get* 'dictionary ?key \...?'+:: Given a dictionary value (first argument) and a key (second argument), this will retrieve the value for that key. Where several keys are supplied, the behaviour of the command shall be as if the result of "`dict get $dictVal $key`" was passed as the first argument to dict get with the remaining arguments as second (and possibly subsequent) arguments. This facilitates lookups in nested dictionaries. If no keys are provided, dict would return a list containing pairs of elements in a man- ner similar to array get. That is, the first element of each pair would be the key and the second element would be the value for that key. It is an error to attempt to retrieve a value for a key that is not present in the dictionary. +*dict keys* 'dictionary ?pattern?'+:: Returns a list of the keys in the dictionary. If pattern is specified, then only those keys whose names match +'pattern'+ (using the matching rules of string match) are included. +*dict merge* ?'dictionary \...'?+:: Return a dictionary that contains the contents of each of the +'dictionary'+ arguments. Where two (or more) dictionaries contain a mapping for the same key, the resulting dictionary maps that key to the value according to the last dictionary on the command line containing a mapping for that key. +*dict set* 'dictionaryName key ?key \...? value'+:: This operation takes the +'name'+ of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. When multiple keys are present, this operation creates or updates a chain of nested dictionaries. +*dict size* 'dictionary'+:: Return the number of key/value mappings in the given dictionary value. +*dict unset* 'dictionaryName key ?key \...? value'+:: This operation (the companion to `dict set`) takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified, but the last key on the key-path need not exist. All other components on the path must exist. +*dict with* 'dictionaryName key ?key \...? script'+:: Execute the Tcl script in +'script'+ with the value for each key in +'dictionaryName'+ mapped to a variable with the same name. Where one or more keys are given, these indicate a chain of nested dictionaries, with the innermost dictionary being the one opened out for the execution of body. Making +'dictionaryName'+ unreadable will make the updates to the dictionary be discarded, and this also happens if the contents of +'dictionaryName'+ are adjusted so that the chain of dictionaries no longer exists. The result of `dict with` is (unless some kind of error occurs) the result of the evaluation of body. :: The variables are mapped in the scope enclosing the `dict with`; it is recommended that this command only be used in a local scope (procedure). Because of this, the variables set by `dict with` will continue to exist after the command finishes (unless explicitly unset). Note that changes to the contents of +'dictionaryName'+ only happen when +'script'+ terminates. +*dict for, values, incr, append, lappend, update, info, replace*+ to be documented... env ~~~ +*env* '?name? ?default?'+ If +'name'+ is supplied, returns the value of +'name'+ from the initial environment (see getenv(3)). An error is returned if +'name'+ does not exist in the environment, unless +'default'+ is supplied - in which case that value is returned instead. If no arguments are supplied, returns a list of all environment variables and their values as +{name value \...}+ See also the global variable +::env+ eof ~~~ +*eof* 'fileId'+ +'fileId' *eof*+ Returns 1 if an end-of-file condition has occurred on +'fileId'+, 0 otherwise. +'fileId'+ must have been the return value from a previous call to `open`, or it may be +stdin+, +stdout+, or +stderr+ to refer to one of the standard I/O channels. error ~~~~~ +*error* 'message ?stacktrace?'+ Returns a +JIM_ERR+ code, which causes command interpretation to be unwound. +'message'+ is a string that is returned to the application to indicate what went wrong. If the +'stacktrace'+ argument is provided and is non-empty, it is used to initialize the stacktrace. This feature is most useful in conjunction with the `catch` command: if a caught error cannot be handled successfully, +'stacktrace'+ can be used to return a stack trace reflecting the original point of occurrence of the error: catch {...} errMsg ... error $errMsg [info stacktrace] See also `errorInfo`, `info stacktrace`, `catch` and `return` errorInfo ~~~~~~~~~ +*errorInfo* 'error ?stacktrace?'+ Returns a human-readable representation of the given error message and stack trace. Typical usage is: if {[catch {...} error]} { puts stderr [errorInfo $error [info stacktrace]] exit 1 } See also `error`. eval ~~~~ +*eval* 'arg ?arg\...?'+ `eval` takes one or more arguments, which together comprise a Tcl command (or collection of Tcl commands separated by newlines in the usual way). `eval` concatenates all its arguments in the same fashion as the `concat` command, passes the concatenated string to the Tcl interpreter recursively, and returns the result of that evaluation (or any error generated by it). exec ~~~~ +*exec* 'arg ?arg\...?'+ This command treats its arguments as the specification of one or more UNIX commands to execute as subprocesses. The commands take the form of a standard shell pipeline; +|+ arguments separate commands in the pipeline and cause standard output of the preceding command to be piped into standard input of the next command (or +|&+ for both standard output and standard error). Under normal conditions the result of the `exec` command consists of the standard output produced by the last command in the pipeline. If any of the commands in the pipeline exit abnormally or are killed or suspended, then `exec` will return an error and the error message will include the pipeline's output followed by error messages describing the abnormal terminations. If any of the commands writes to its standard error file, then `exec` will return an error, and the error message will include the pipeline's output, followed by messages about abnormal terminations (if any), followed by the standard error output. If the last character of the result or error message is a newline then that character is deleted from the result or error message for consistency with normal Tcl return values. An +'arg'+ may have one of the following special forms: +>filename+:: The standard output of the last command in the pipeline is redirected to the file. In this situation `exec` will normally return an empty string. +>>filename+:: As above, but append to the file. +>@fileId+:: The standard output of the last command in the pipeline is redirected to the given (writable) file descriptor (e.g. stdout, stderr, or the result of `open`). In this situation `exec` will normally return an empty string. +2>filename+:: The standard error of the last command in the pipeline is redirected to the file. +2>>filename+:: As above, but append to the file. +2>@fileId+:: The standard error of the last command in the pipeline is redirected to the given (writable) file descriptor. +2>@1+:: The standard error of the last command in the pipeline is redirected to the same file descriptor as the standard output. +>&filename+:: Both the standard output and standard error of the last command in the pipeline is redirected to the file. +>>&filename+:: As above, but append to the file. ++, and +&+ arguments, and the arguments that follow +<+, +<<+, and +>+. The first word in each command is taken as the command name; the directories in the PATH environment variable are searched for an executable by the given name. No `glob` expansion or other shell-like substitutions are performed on the arguments to commands. If the command fails, the global $::errorCode (and the -errorcode option in `catch`) will be set to a list, as follows: +*CHILDKILLED* 'pid sigName msg'+:: This format is used when a child process has been killed because of a signal. The pid element will be the process's identifier (in decimal). The sigName element will be the symbolic name of the signal that caused the process to terminate; it will be one of the names from the include file signal.h, such as SIGPIPE. The msg element will be a short human-readable message describing the signal, such as "write on pipe with no readers" for SIGPIPE. +*CHILDSUSP* 'pid sigName msg'+:: This format is used when a child process has been suspended because of a signal. The pid element will be the process's identifier, in decimal. The sigName element will be the symbolic name of the signal that caused the process to suspend; this will be one of the names from the include file signal.h, such as SIGTTIN. The msg element will be a short human-readable message describing the signal, such as "background tty read" for SIGTTIN. +*CHILDSTATUS* 'pid code'+:: This format is used when a child process has exited with a non-zero exit status. The pid element will be the process's identifier (in decimal) and the code element will be the exit code returned by the process (also in decimal). The environment for the executed command is set from $::env (unless this variable is unset, in which case the original environment is used). exists ~~~~~~ +*exists ?-var|-proc|-command|-alias?* 'name'+ Checks the existence of the given variable, procedure, command or alias respectively and returns 1 if it exists or 0 if not. This command provides a more simplified/convenient version of `info exists`, `info procs` and `info commands`. If the type is omitted, a type of '-var' is used. The type may be abbreviated. exit ~~~~ +*exit* '?returnCode?'+ Terminate the process, returning +'returnCode'+ to the parent as the exit status. If +'returnCode'+ isn't specified then it defaults to 0. Note that exit can be caught with `catch`. expr ~~~~ +*expr* 'arg'+ Calls the expression processor to evaluate +'arg'+, and returns the result as a string. See the section EXPRESSIONS above. Note that Jim supports a shorthand syntax for `expr` as +$(\...)+ The following two are identical. set x [expr {3 * 2 + 1}] set x $(3 * 2 + 1) file ~~~~ +*file* 'option name ?arg\...?'+ Operate on a file or a file name. +'name'+ is the name of a file. +'option'+ indicates what to do with the file name. Any unique abbreviation for +'option'+ is acceptable. The valid options are: +*file atime* 'name'+:: Return a decimal string giving the time at which file +'name'+ was last accessed. The time is measured in the standard UNIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file doesn't exist or its access time cannot be queried then an error is generated. +*file copy ?-force?* 'source target'+:: Copies file +'source'+ to file +'target'+. The source file must exist. The target file must not exist, unless +-force+ is specified. +*file delete ?-force? ?--?* 'name\...'+:: Deletes file or directory +'name'+. If the file or directory doesn't exist, nothing happens. If it can't be deleted, an error is generated. Non-empty directories will not be deleted unless the +-force+ options is given. In this case no errors will be generated, even if the file/directory can't be deleted. Use +'--'+ if there is any possibility of the first name being +'-force'+. +*file dirname* 'name'+:: Return all of the characters in +'name'+ up to but not including the last slash character. If there are no slashes in +'name'+ then return +.+ (a single dot). If the last slash in +'name'+ is its first character, then return +/+. +*file executable* 'name'+:: Return '1' if file +'name'+ is executable by the current user, '0' otherwise. +*file exists* 'name'+:: Return '1' if file +'name'+ exists and the current user has search privileges for the directories leading to it, '0' otherwise. +*file extension* 'name'+:: Return all of the characters in +'name'+ after and including the last dot in +'name'+. If there is no dot in +'name'+ then return the empty string. +*file isdirectory* 'name'+:: Return '1' if file +'name'+ is a directory, '0' otherwise. +*file isfile* 'name'+:: Return '1' if file +'name'+ is a regular file, '0' otherwise. +*file join* 'arg\...'+:: Joins multiple path components. Note that if any components is an absolute path, the preceding components are ignored. Thus +"`file` join /tmp /root"+ returns +"/root"+. +*file link* ?*-hard|-symbolic*? 'newname target'+:: Creates a hard link (default) or symbolic link from +'newname'+ to +'target'+. Note that the sense of this command is the opposite of `file rename` and `file copy` and also of `ln`, but this is compatible with Tcl. An error is returned if +'target'+ doesn't exist or +'newname'+ already exists. +*file lstat* 'name varName'+:: Same as 'stat' option (see below) except uses the +'lstat'+ kernel call instead of +'stat'+. This means that if +'name'+ refers to a symbolic link the information returned in +'varName'+ is for the link rather than the file it refers to. On systems that don't support symbolic links this option behaves exactly the same as the 'stat' option. +*file mkdir* 'dir1 ?dir2\...?'+:: Creates each directory specified. For each pathname +'dir'+ specified, this command will create all non-existing parent directories as well as +'dir'+ itself. If an existing directory is specified, then no action is taken and no error is returned. Trying to overwrite an existing file with a directory will result in an error. Arguments are processed in the order specified, halting at the first error, if any. +*file mtime* 'name ?time?'+:: Return a decimal string giving the time at which file +'name'+ was last modified. The time is measured in the standard UNIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file doesn't exist or its modified time cannot be queried then an error is generated. If +'time'+ is given, sets the modification time of the file to the given value. +*file normalize* 'name'+:: Return the normalized path of +'name'+. See 'realpath(3)'. +*file owned* 'name'+:: Return '1' if file +'name'+ is owned by the current user, '0' otherwise. +*file readable* 'name'+:: Return '1' if file +'name'+ is readable by the current user, '0' otherwise. +*file readlink* 'name'+:: Returns the value of the symbolic link given by +'name'+ (i.e. the name of the file it points to). If +'name'+ isn't a symbolic link or its value cannot be read, then an error is returned. On systems that don't support symbolic links this option is undefined. +*file rename* ?*-force*? 'oldname' 'newname'+:: Renames the file from the old name to the new name. If +'newname'+ already exists, an error is returned unless +'-force'+ is specified. +*file rootname* 'name'+:: Return all of the characters in +'name'+ up to but not including the last '.' character in the name. If +'name'+ doesn't contain a dot, then return +'name'+. +*file size* 'name'+:: Return a decimal string giving the size of file +'name'+ in bytes. If the file doesn't exist or its size cannot be queried then an error is generated. +*file stat* 'name ?varName?'+:: Invoke the 'stat' kernel call on +'name'+, and return the result as a dictionary with the following keys: 'atime', 'ctime', 'dev', 'gid', 'ino', 'mode', 'mtime', 'nlink', 'size', 'type', 'uid'. Each element except 'type' is a decimal string with the value of the corresponding field from the 'stat' return structure; see the manual entry for 'stat' for details on the meanings of the values. The 'type' element gives the type of the file in the same form returned by the command `file type`. If +'varName'+ is specified, it is taken to be the name of an array variable and the values are also stored into the array. +*file tail* 'name'+:: Return all of the characters in +'name'+ after the last slash. If +'name'+ contains no slashes then return +'name'+. +*file tempfile* '?template?'+:: Creates and returns the name of a unique temporary file. If +'template'+ is omitted, a default template will be used to place the file in /tmp. See 'mkstemp(3)' for the format of the template and security concerns. +*file type* 'name'+:: Returns a string giving the type of file +'name'+, which will be one of +file+, +directory+, +characterSpecial+, +blockSpecial+, +fifo+, +link+, or +socket+. +*file writable* 'name'+:: Return '1' if file +'name'+ is writable by the current user, '0' otherwise. The `file` commands that return 0/1 results are often used in conditional or looping commands, for example: if {![file exists foo]} { error {bad file name} } else { ... } finalize ~~~~~~~~ +*finalize* 'reference ?command?'+ If +'command'+ is omitted, returns the finalizer command for the given reference. Otherwise, sets a new finalizer command for the given reference. +'command'+ may be the empty string to remove the current finalizer. The reference must be a valid reference create with the `ref` command. See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. flush ~~~~~ +*flush* 'fileId'+ +'fileId' *flush*+ Flushes any output that has been buffered for +'fileId'+. +'fileId'+ must have been the return value from a previous call to `open`, or it may be +stdout+ or +stderr+ to access one of the standard I/O streams; it must refer to a file that was opened for writing. This command returns an empty string. for ~~~ +*for* 'start test next body'+ `for` is a looping command, similar in structure to the C `for` statement. The +'start'+, +'next'+, and +'body'+ arguments must be Tcl command strings, and +'test'+ is an expression string. The `for` command first invokes the Tcl interpreter to execute +'start'+. Then it repeatedly evaluates +'test'+ as an expression; if the result is non-zero it invokes the Tcl interpreter on +'body'+, then invokes the Tcl interpreter on +'next'+, then repeats the loop. The command terminates when +'test'+ evaluates to 0. If a `continue` command is invoked within +'body'+ then any remaining commands in the current execution of +'body'+ are skipped; processing continues by invoking the Tcl interpreter on +'next'+, then evaluating +'test'+, and so on. If a `break` command is invoked within +'body'+ or +'next'+, then the `for` command will return immediately. The operation of `break` and `continue` are similar to the corresponding statements in C. `for` returns an empty string. foreach ~~~~~~~ +*foreach* 'varName list body'+ +*foreach* 'varList list ?varList2 list2 \...? body'+ In this command, +'varName'+ is the name of a variable, +'list'+ is a list of values to assign to +'varName'+, and +'body'+ is a collection of Tcl commands. For each field in +'list'+ (in order from left to right), `foreach` assigns the contents of the field to +'varName'+ (as if the `lindex` command had been used to extract the field), then calls the Tcl interpreter to execute +'body'+. If instead of being a simple name, +'varList'+ is used, multiple assignments are made each time through the loop, one for each element of +'varList'+. For example, if there are two elements in +'varList'+ and six elements in the list, the loop will be executed three times. If the length of the list doesn't evenly divide by the number of elements in +'varList'+, the value of the remaining variables in the last iteration of the loop are undefined. The `break` and `continue` statements may be invoked inside +'body'+, with the same effect as in the `for` command. `foreach` returns an empty string. format ~~~~~~ +*format* 'formatString ?arg \...?'+ This command generates a formatted string in the same way as the C 'sprintf' procedure (it uses 'sprintf' in its implementation). +'formatString'+ indicates how to format the result, using +%+ fields as in 'sprintf', and the additional arguments, if any, provide values to be substituted into the result. All of the 'sprintf' options are valid; see the 'sprintf' man page for details. Each +'arg'+ must match the expected type from the +%+ field in +'formatString'+; the `format` command converts each argument to the correct type (floating, integer, etc.) before passing it to 'sprintf' for formatting. The only unusual conversion is for +%c+; in this case the argument must be a decimal string, which will then be converted to the corresponding ASCII (or UTF-8) character value. In addition, Jim Tcl provides basic support for conversion to binary with +%b+. `format` does backslash substitution on its +'formatString'+ argument, so backslash sequences in +'formatString'+ will be handled correctly even if the argument is in braces. The return value from `format` is the formatted string. getref ~~~~~~ +*getref* 'reference'+ Returns the string associated with +'reference'+. The reference must be a valid reference create with the `ref` command. See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. gets ~~~~ +*gets* 'fileId ?varName?'+ +'fileId' *gets* '?varName?'+ Reads the next line from the file given by +'fileId'+ and discards the terminating newline character. If +'varName'+ is specified, then the line is placed in the variable by that name and the return value is a count of the number of characters read (not including the newline). If the end of the file is reached before reading any characters then -1 is returned and +'varName'+ is set to an empty string. If +'varName'+ is not specified then the return value will be the line (minus the newline character) or an empty string if the end of the file is reached before reading any characters. An empty string will also be returned if a line contains no characters except the newline, so `eof` may have to be used to determine what really happened. If the last character in the file is not a newline character, then `gets` behaves as if there were an additional newline character at the end of the file. +'fileId'+ must be +stdin+ or the return value from a previous call to `open`; it must refer to a file that was opened for reading. glob ~~~~ +*glob* ?*-nocomplain*? ?*-directory* 'dir'? ?*-tails*? ?*--*? 'pattern ?pattern \...?'+ This command performs filename globbing, using csh rules. The returned value from `glob` is the list of expanded filenames. If +-nocomplain+ is specified as the first argument then an empty list may be returned; otherwise an error is returned if the expanded list is empty. The +-nocomplain+ argument must be provided exactly: an abbreviation will not be accepted. If +-directory+ is given, the +'dir'+ is understood to contain a directory name to search in. This allows globbing inside directories whose names may contain glob-sensitive characters. The returned names include the directory name unless +'-tails'+ is specified. If +'-tails'+ is specified, along with +-directory+, the returned names are relative to the given directory. global ~~~~~~ +*global* 'varName ?varName \...?'+ This command is ignored unless a Tcl procedure is being interpreted. If so, then it declares each given +'varName'+ to be a global variable rather than a local one. For the duration of the current procedure (and only while executing in the current procedure), any reference to +'varName'+ will be bound to a global variable instead of a local one. An alternative to using `global` is to use the +::+ prefix to explicitly name a variable in the global scope. if ~~ +*if* 'expr1' ?*then*? 'body1' *elseif* 'expr2' ?*then*? 'body2' *elseif* \... ?*else*? ?'bodyN'?+ The `if` command evaluates +'expr1'+ as an expression (in the same way that `expr` evaluates its argument). The value of the expression must be numeric; if it is non-zero then +'body1'+ is executed by passing it to the Tcl interpreter. Otherwise +'expr2'+ is evaluated as an expression and if it is non-zero then +'body2'+ is executed, and so on. If none of the expressions evaluates to non-zero then +'bodyN'+ is executed. The +then+ and +else+ arguments are optional "noise words" to make the command easier to read. There may be any number of +elseif+ clauses, including zero. +'bodyN'+ may also be omitted as long as +else+ is omitted too. The return value from the command is the result of the body script that was executed, or an empty string if none of the expressions was non-zero and there was no +'bodyN'+. incr ~~~~ +*incr* 'varName ?increment?'+ Increment the value stored in the variable whose name is +'varName'+. The value of the variable must be integral. If +'increment'+ is supplied then its value (which must be an integer) is added to the value of variable +'varName'+; otherwise 1 is added to +'varName'+. The new value is stored as a decimal string in variable +'varName'+ and also returned as result. If the variable does not exist, the variable is implicitly created and set to +0+ first. info ~~~~ +*info* 'option ?arg\...?'+:: Provide information about various internals to the Tcl interpreter. The legal +'option'+'s (which may be abbreviated) are: +*info args* 'procname'+:: Returns a list containing the names of the arguments to procedure +'procname'+, in order. +'procname'+ must be the name of a Tcl command procedure. +*info alias* 'command'+:: +'command'+ must be an alias created with `alias`. In which case the target command and arguments, as passed to `alias` are returned. See `exists -alias` +*info body* 'procname'+:: Returns the body of procedure +'procname'+. +'procname'+ must be the name of a Tcl command procedure. +*info channels*+:: Returns a list of all open file handles from `open` or `socket` +*info commands* ?'pattern'?+:: If +'pattern'+ isn't specified, returns a list of names of all the Tcl commands, including both the built-in commands written in C and the command procedures defined using the `proc` command. If +'pattern'+ is specified, only those names matching +'pattern'+ are returned. Matching is determined using the same rules as for `string match`. +*info complete* 'command' ?'missing'?+:: Returns 1 if +'command'+ is a complete Tcl command in the sense of having no unclosed quotes, braces, brackets or array element names, If the command doesn't appear to be complete then 0 is returned. This command is typically used in line-oriented input environments to allow users to type in commands that span multiple lines; if the command isn't complete, the script can delay evaluating it until additional lines have been typed to complete the command. If +'varName'+ is specified, the missing character is stored in the variable with that name. +*info exists* 'varName'+:: Returns '1' if the variable named +'varName'+ exists in the current context (either as a global or local variable), returns '0' otherwise. +*info frame* ?'number'?+:: If +'number'+ is not specified, this command returns a number which is the same result as `info level` - the current stack frame level. If +'number'+ is specified, then the result is a list consisting of the procedure, filename and line number for the procedure call at level +'number'+ on the stack. If +'number'+ is positive then it selects a particular stack level (1 refers to the top-most active procedure, 2 to the procedure it called, and so on); otherwise it gives a level relative to the current level (0 refers to the current procedure, -1 to its caller, and so on). The level has an identical meaning to `info level`. +*info globals* ?'pattern'?+:: If +'pattern'+ isn't specified, returns a list of all the names of currently-defined global variables. If +'pattern'+ is specified, only those names matching +'pattern'+ are returned. Matching is determined using the same rules as for `string match`. +*info hostname*+:: An alias for `os.gethostname` for compatibility with Tcl 6.x +*info level* ?'number'?+:: If +'number'+ is not specified, this command returns a number giving the stack level of the invoking procedure, or 0 if the command is invoked at top-level. If +'number'+ is specified, then the result is a list consisting of the name and arguments for the procedure call at level +'number'+ on the stack. If +'number'+ is positive then it selects a particular stack level (1 refers to the top-most active procedure, 2 to the procedure it called, and so on); otherwise it gives a level relative to the current level (0 refers to the current procedure, -1 to its caller, and so on). See the `uplevel` command for more information on what stack levels mean. +*info locals* ?'pattern'?+:: If +'pattern'+ isn't specified, returns a list of all the names of currently-defined local variables, including arguments to the current procedure, if any. Variables defined with the `global` and `upvar` commands will not be returned. If +'pattern'+ is specified, only those names matching +'pattern'+ are returned. Matching is determined using the same rules as for `string match`. +*info nameofexecutable*+:: Returns the name of the binary file from which the application was invoked. A full path will be returned, unless the path can't be determined, in which case the empty string will be returned. +*info procs* ?'pattern'?+:: If +'pattern'+ isn't specified, returns a list of all the names of Tcl command procedures. If +'pattern'+ is specified, only those names matching +'pattern'+ are returned. Matching is determined using the same rules as for `string match`. +*info references*+:: Returns a list of all references which have not yet been garbage collected. +*info returncodes* ?'code'?+:: Returns a list representing the mapping of standard return codes to names. e.g. +{0 ok 1 error 2 return \...}+. If a code is given, instead returns the name for the given code. +*info script*+:: If a Tcl script file is currently being evaluated (i.e. there is a call to 'Jim_EvalFile' active or there is an active invocation of the `source` command), then this command returns the name of the innermost file being processed. Otherwise the command returns an empty string. +*info source* 'script ?filename line?'+:: With a single argument, returns the original source location of the given script as a list of +{filename linenumber}+. If the source location can't be determined, the list +{{} 0}+ is returned. If +'filename'+ and +'line'+ are given, returns a copy of +'script'+ with the associate source information. This can be useful to produce useful messages from `eval`, etc. if the original source information may be lost. +*info stacktrace*+:: After an error is caught with `catch`, returns the stack trace as a list of +{procedure filename line \...}+. +*info statics* 'procname'+:: Returns a dictionary of the static variables of procedure +'procname'+. +'procname'+ must be the name of a Tcl command procedure. An empty dictionary is returned if the procedure has no static variables. +*info version*+:: Returns the version number for this version of Jim in the form +*x.yy*+. +*info vars* ?'pattern'?+:: If +'pattern'+ isn't specified, returns a list of all the names of currently-visible variables, including both locals and currently-visible globals. If +'pattern'+ is specified, only those names matching +'pattern'+ are returned. Matching is determined using the same rules as for `string match`. join ~~~~ +*join* 'list ?joinString?'+ The +'list'+ argument must be a valid Tcl list. This command returns the string formed by joining all of the elements of +'list'+ together with +'joinString'+ separating each adjacent pair of elements. The +'joinString'+ argument defaults to a space character. kill ~~~~ +*kill* ?'SIG'|*-0*? 'pid'+ Sends the given signal to the process identified by +'pid'+. The signal may be specified by name or number in one of the following forms: * +TERM+ * +SIGTERM+ * +-TERM+ * +15+ * +-15+ The signal name may be in either upper or lower case. The special signal name +-0+ simply checks that a signal +'could'+ be sent. If no signal is specified, SIGTERM is used. An error is raised if the signal could not be delivered. lambda ~~~~~~ +*lambda* 'args ?statics? body'+ The `lambda` command is identical to `proc`, except rather than creating a named procedure, it creates an anonymous procedure and returns the name of the procedure. See `proc` and GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. lappend ~~~~~~~ +*lappend* 'varName value ?value value \...?'+ Treat the variable given by +'varName'+ as a list and append each of the +'value'+ arguments to that list as a separate element, with spaces between elements. If +'varName'+ doesn't exist, it is created as a list with elements given by the +'value'+ arguments. `lappend` is similar to `append` except that each +'value'+ is appended as a list element rather than raw text. This command provides a relatively efficient way to build up large lists. For example, lappend a $b is much more efficient than set a [concat $a [list $b]] when +$a+ is long. lassign ~~~~~~~ +*lassign* 'list varName ?varName \...?'+ This command treats the value +'list'+ as a list and assigns successive elements from that list to the variables given by the +'varName'+ arguments in order. If there are more variable names than list elements, the remaining variables are set to the empty string. If there are more list ele- ments than variables, a list of unassigned elements is returned. jim> lassign {1 2 3} a b; puts a=$a,b=$b 3 a=1,b=2 local ~~~~~ +*local* 'cmd ?arg\...?'+ First, `local` evaluates +'cmd'+ with the given arguments. The return value must be the name of an existing command, which is marked as having local scope. This means that when the current procedure exits, the specified command is deleted. This can be useful with `lambda`, local procedures or to automatically close a filehandle. In addition, if a command already exists with the same name, the existing command will be kept rather than deleted, and may be called via `upcall`. The previous command will be restored when the current procedure exits. See `upcall` for more details. In this example, a local procedure is created. Note that the procedure continues to have global scope while it is active. proc outer {} { # proc ... returns "inner" which is marked local local proc inner {} { # will be deleted when 'outer' exits } inner ... } In this example, the lambda is deleted at the end of the procedure rather than waiting until garbage collection. proc outer {} { set x [lambda inner {args} { # will be deleted when 'outer' exits }] # Use 'function' here which simply returns $x local function $x $x ... ... } loop ~~~~ +*loop* 'var first limit ?incr? body'+ Similar to `for` except simpler and possibly more efficient. With a positive increment, equivalent to: for {set var $first} {$var < $limit} {incr var $incr} $body If +'incr'+ is not specified, 1 is used. Note that setting the loop variable inside the loop does not affect the loop count. lindex ~~~~~~ +*lindex* 'list ?index ...?'+ Treats +'list'+ as a Tcl list and returns element +'index'+ from it (0 refers to the first element of the list). See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+. In extracting the element, +'lindex'+ observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. If no index values are given, simply returns +'list'+ If +'index'+ is negative or greater than or equal to the number of elements in +'list'+, then an empty string is returned. If additional index arguments are supplied, then each argument is used in turn to select an element from the previous indexing operation, allowing the script to select elements from sublists. linsert ~~~~~~~ +*linsert* 'list index element ?element element \...?'+ This command produces a new list from +'list'+ by inserting all of the +'element'+ arguments just before the element +'index'+ of +'list'+. Each +'element'+ argument will become a separate element of the new list. If +'index'+ is less than or equal to zero, then the new elements are inserted at the beginning of the list. If +'index'+ is greater than or equal to the number of elements in the list, then the new elements are appended to the list. See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+. list ~~~~ +*list* 'arg ?arg \...?'+ This command returns a list comprised of all the arguments, +'arg'+. Braces and backslashes get added as necessary, so that the `lindex` command may be used on the result to re-extract the original arguments, and also so that `eval` may be used to execute the resulting list, with +'arg1'+ comprising the command's name and the other args comprising its arguments. `list` produces slightly different results than `concat`: `concat` removes one level of grouping before forming the list, while `list` works directly from the original arguments. For example, the command list a b {c d e} {f {g h}} will return a b {c d e} {f {g h}} while `concat` with the same arguments will return a b c d e f {g h} llength ~~~~~~~ +*llength* 'list'+ Treats +'list'+ as a list and returns a decimal string giving the number of elements in it. lset ~~~~ +*lset* 'varName ?index ..? newValue'+ Sets an element in a list. The `lset` command accepts a parameter, +'varName'+, which it interprets as the name of a variable containing a Tcl list. It also accepts zero or more indices into the list. Finally, it accepts a new value for an element of varName. If no indices are presented, the command takes the form: lset varName newValue In this case, newValue replaces the old value of the variable varName. When presented with a single index, the `lset` command treats the content of the varName variable as a Tcl list. It addresses the index'th element in it (0 refers to the first element of the list). When interpreting the list, `lset` observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. The command constructs a new list in which the designated element is replaced with newValue. This new list is stored in the variable varName, and is also the return value from the `lset` command. If index is negative or greater than or equal to the number of elements in $varName, then an error occurs. See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+. If additional index arguments are supplied, then each argument is used in turn to address an element within a sublist designated by the previous indexing operation, allowing the script to alter elements in sublists. The command, lset a 1 2 newValue replaces element 2 of sublist 1 with +'newValue'+. The integer appearing in each index argument must be greater than or equal to zero. The integer appearing in each index argument must be strictly less than the length of the corresponding list. In other words, the `lset` command cannot change the size of a list. If an index is outside the permitted range, an error is reported. lmap ~~~~ +*lmap* 'varName list body'+ +*lmap* 'varList list ?varList2 list2 \...? body'+ `lmap` is a "collecting" `foreach` which returns a list of its results. For example: jim> lmap i {1 2 3 4 5} {expr $i*$i} 1 4 9 16 25 jim> lmap a {1 2 3} b {A B C} {list $a $b} {1 A} {2 B} {3 C} If the body invokes `continue`, no value is added for this iteration. If the body invokes `break`, the loop ends and no more values are added. load ~~~~ +*load* 'filename'+ Loads the dynamic extension, +'filename'+. Generally the filename should have the extension +.so+. The initialisation function for the module must be based on the name of the file. For example loading +hwaccess.so+ will invoke the initialisation function, +Jim_hwaccessInit+. Normally the `load` command should not be used directly. Instead it is invoked automatically by `package require`. lrange ~~~~~~ +*lrange* 'list first last'+ +'list'+ must be a valid Tcl list. This command will return a new list consisting of elements +'first'+ through +'last'+, inclusive. See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+. If +'last'+ is greater than or equal to the number of elements in the list, then it is treated as if it were +end+. If +'first'+ is greater than +'last'+ then an empty string is returned. Note: +"`lrange` 'list first first'"+ does not always produce the same result as +"`lindex` 'list first'"+ (although it often does for simple fields that aren't enclosed in braces); it does, however, produce exactly the same results as +"`list` [`lindex` 'list first']"+ lreplace ~~~~~~~~ +*lreplace* 'list first last ?element element \...?'+ Returns a new list formed by replacing one or more elements of +'list'+ with the +'element'+ arguments. +'first'+ gives the index in +'list'+ of the first element to be replaced. If +'first'+ is less than zero then it refers to the first element of +'list'+; the element indicated by +'first'+ must exist in the list. +'last'+ gives the index in +'list'+ of the last element to be replaced; it must be greater than or equal to +'first'+. See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+. The +'element'+ arguments specify zero or more new arguments to be added to the list in place of those that were deleted. Each +'element'+ argument will become a separate element of the list. If no +'element'+ arguments are specified, then the elements between +'first'+ and +'last'+ are simply deleted. lrepeat ~~~~~~~~ +*lrepeat* 'number element1 ?element2 \...?'+ Build a list by repeating elements +'number'+ times (which must be a positive integer). jim> lrepeat 3 a b a b a b a b lreverse ~~~~~~~~ +*lreverse* 'list'+ Returns the list in reverse order. jim> lreverse {1 2 3} 3 2 1 lsearch ~~~~~~~ +*lsearch* '?options? list pattern'+ This command searches the elements +'list'+ to see if one of them matches +'pattern'+. If so, the command returns the index of the first matching element (unless the options +-all+, +-inline+ or +-bool+ are specified.) If not, the command returns -1. The option arguments indicates how the elements of the list are to be matched against pattern and must have one of the values below: *Note* that this command is different from Tcl in that default match type is +-exact+ rather than +-glob+. +*-exact*+:: +'pattern'+ is a literal string that is compared for exact equality against each list element. This is the default. +*-glob*+:: +'pattern'+ is a glob-style pattern which is matched against each list element using the same rules as the string match command. +*-regexp*+:: +'pattern'+ is treated as a regular expression and matched against each list element using the rules described by `regexp`. +*-command* 'cmdname'+:: +'cmdname'+ is a command which is used to match the pattern against each element of the list. It is invoked as +'cmdname' ?*-nocase*? 'pattern listvalue'+ and should return 1 for a match, or 0 for no match. +*-all*+:: Changes the result to be the list of all matching indices (or all matching values if +-inline+ is specified as well). If indices are returned, the indices will be in numeric order. If values are returned, the order of the values will be the order of those values within the input list. +*-inline*+:: The matching value is returned instead of its index (or an empty string if no value matches). If +-all+ is also specified, then the result of the command is the list of all values that matched. The +-inline+ and +-bool+ options are mutually exclusive. +*-bool*+:: Changes the result to '1' if a match was found, or '0' otherwise. If +-all+ is also specified, the result will be a list of '0' and '1' for each element of the list depending upon whether the corresponding element matches. The +-inline+ and +-bool+ options are mutually exclusive. +*-not*+:: This negates the sense of the match, returning the index (or value if +-inline+ is specified) of the first non-matching value in the list. If +-bool+ is also specified, the '0' will be returned if a match is found, or '1' otherwise. If +-all+ is also specified, non-matches will be returned rather than matches. +*-nocase*+:: Causes comparisons to be handled in a case-insensitive manner. lsort ~~~~~ +*lsort* ?*-index* 'listindex'? ?*-nocase!-integer|-real|-command* 'cmdname'? ?*-unique*? ?*-decreasing*|*-increasing*? 'list'+ Sort the elements of +'list'+, returning a new list in sorted order. By default, ASCII (or UTF-8) sorting is used, with the result in increasing order. If +-nocase+ is specified, comparisons are case-insenstive. If +-integer+ is specified, numeric sorting is used. If +-real+ is specified, floating point number sorting is used. If +-command 'cmdname'+ is specified, +'cmdname'+ is treated as a command name. For each comparison, +'cmdname $value1 $value2+' is called which should compare the values and return an integer less than, equal to, or greater than zero if the +'$value1'+ is to be considered less than, equal to, or greater than +'$value2'+, respectively. If +-decreasing+ is specified, the resulting list is in the opposite order to what it would be otherwise. +-increasing+ is the default. If +-unique+ is specified, then only the last set of duplicate elements found in the list will be retained. Note that duplicates are determined relative to the comparison used in the sort. Thus if +-index 0+ is used, +{1 a}+ and +{1 b}+ would be considered duplicates and only the second element, +{1 b}+, would be retained. If +-index 'listindex'+ is specified, each element of the list is treated as a list and the given index is extracted from the list for comparison. The list index may be any valid list index, such as +1+, +end+ or +end-2+. open ~~~~ +*open* 'fileName ?access?'+ +*open* '|command-pipeline ?access?'+ Opens a file and returns an identifier that may be used in future invocations of commands like `read`, `puts`, and `close`. +'fileName'+ gives the name of the file to open. The +'access'+ argument indicates the way in which the file is to be accessed. It may have any of the following values: +r+:: Open the file for reading only; the file must already exist. +r++:: Open the file for both reading and writing; the file must already exist. +w+:: Open the file for writing only. Truncate it if it exists. If it doesn't exist, create a new file. +w++:: Open the file for reading and writing. Truncate it if it exists. If it doesn't exist, create a new file. +a+:: Open the file for writing only. The file must already exist, and the file is positioned so that new data is appended to the file. +a++:: Open the file for reading and writing. If the file doesn't exist, create a new empty file. Set the initial access position to the end of the file. +'access'+ defaults to 'r'. If a file is opened for both reading and writing, then `seek` must be invoked between a read and a write, or vice versa. If the first character of +'fileName'+ is "|" then the remaining characters of +'fileName'+ are treated as a list of arguments that describe a command pipeline to invoke, in the same style as the arguments for exec. In this case, the channel identifier returned by open may be used to write to the command's input pipe or read from its output pipe, depending on the value of +'access'+. If write-only access is used (e.g. +'access'+ is 'w'), then standard output for the pipeline is directed to the current standard output unless overridden by the command. If read-only access is used (e.g. +'access'+ is r), standard input for the pipeline is taken from the current standard input unless overridden by the command. The `pid` command may be used to return the process ids of the commands forming the command pipeline. See also `socket`, `pid`, `exec` package ~~~~~~~ +*package provide* 'name ?version?'+ Indicates that the current script provides the package named +'name'+. If no version is specified, '1.0' is used. Any script which provides a package may include this statement as the first statement, although it is not required. +*package require* 'name ?version?'*+ Searches for the package with the given +'name'+ by examining each path in '$::auto_path' and trying to load '$path/$name.so' as a dynamic extension, or '$path/$name.tcl' as a script package. The first such file which is found is considered to provide the the package. (The version number is ignored). If '$name.so' exists, it is loaded with the `load` command, otherwise if '$name.tcl' exists it is loaded with the `source` command. If `load` or `source` fails, `package require` will fail immediately. No further attempt will be made to locate the file. pid ~~~ +*pid*+ +*pid* 'fileId'+ The first form returns the process identifier of the current process. The second form accepts a handle returned by `open` and returns a list of the process ids forming the pipeline in the same form as `exec ... &`. If 'fileId' represents a regular file handle rather than a command pipeline, the empty string is returned instead. See also `open`, `exec` proc ~~~~ +*proc* 'name args ?statics? body'+ The `proc` command creates a new Tcl command procedure, +'name'+. When the new command is invoked, the contents of +'body'+ will be executed. Tcl interpreter. +'args'+ specifies the formal arguments to the procedure. If specified, +'static'+, declares static variables which are bound to the procedure. See PROCEDURES for detailed information about Tcl procedures. The `proc` command returns +'name'+ (which is useful with `local`). When a procedure is invoked, the procedure's return value is the value specified in a `return` command. If the procedure doesn't execute an explicit `return`, then its return value is the value of the last command executed in the procedure's body. If an error occurs while executing the procedure body, then the procedure-as-a-whole will return that same error. puts ~~~~ +*puts* ?*-nonewline*? '?fileId? string'+ +'fileId' *puts* ?*-nonewline*? 'string'+ Writes the characters given by +'string'+ to the file given by +'fileId'+. +'fileId'+ must have been the return value from a previous call to `open`, or it may be +stdout+ or +stderr+ to refer to one of the standard I/O channels; it must refer to a file that was opened for writing. In the first form, if no +'fileId'+ is specified then it defaults to +stdout+. `puts` normally outputs a newline character after +'string'+, but this feature may be suppressed by specifying the +-nonewline+ switch. Output to files is buffered internally by Tcl; the `flush` command may be used to force buffered characters to be output. pwd ~~~ +*pwd*+ Returns the path name of the current working directory. rand ~~~~ +*rand* '?min? ?max?'+ Returns a random integer between +'min'+ (defaults to 0) and +'max'+ (defaults to the maximum integer). If only one argument is given, it is interpreted as +'max'+. range ~~~~ +*range* '?start? end ?step?'+ Returns a list of integers starting at +'start'+ (defaults to 0) and ranging up to but not including +'end'+ in steps of +'step'+ defaults to 1). jim> range 5 0 1 2 3 4 jim> range 2 5 2 3 4 jim> range 2 10 4 2 6 jim> range 7 4 -2 7 5 read ~~~~ +*read* ?*-nonewline*? 'fileId'+ +'fileId' *read* ?*-nonewline*?+ +*read* 'fileId numBytes'+ +'fileId' *read* 'numBytes'+ In the first form, all of the remaining bytes are read from the file given by +'fileId'+; they are returned as the result of the command. If the +-nonewline+ switch is specified then the last character of the file is discarded if it is a newline. In the second form, the extra argument specifies how many bytes to read; exactly this many bytes will be read and returned, unless there are fewer than +'numBytes'+ bytes left in the file; in this case, all the remaining bytes are returned. +'fileId'+ must be +stdin+ or the return value from a previous call to `open`; it must refer to a file that was opened for reading. regexp ~~~~~~ +*regexp ?-nocase? ?-line? ?-indices? ?-start* 'offset'? *?-all? ?-inline? ?--?* 'exp string ?matchVar? ?subMatchVar subMatchVar \...?'+ Determines whether the regular expression +'exp'+ matches part or all of +'string'+ and returns 1 if it does, 0 if it doesn't. See REGULAR EXPRESSIONS above for complete information on the syntax of +'exp'+ and how it is matched against +'string'+. If additional arguments are specified after +'string'+ then they are treated as the names of variables to use to return information about which part(s) of +'string'+ matched +'exp'+. +'matchVar'+ will be set to the range of +'string'+ that matched all of +'exp'+. The first +'subMatchVar'+ will contain the characters in +'string'+ that matched the leftmost parenthesized subexpression within +'exp'+, the next +'subMatchVar'+ will contain the characters that matched the next parenthesized subexpression to the right in +'exp'+, and so on. Normally, +'matchVar'+ and the each +'subMatchVar'+ are set to hold the matching characters from `string`, however see +-indices+ and +-inline+ below. If there are more values for +'subMatchVar'+ than parenthesized subexpressions within +'exp'+, or if a particular subexpression in +'exp'+ doesn't match the string (e.g. because it was in a portion of the expression that wasn't matched), then the corresponding +'subMatchVar'+ will be set to +"-1 -1"+ if +-indices+ has been specified or to an empty string otherwise. The following switches modify the behaviour of +'regexp'+ +*-nocase*+:: Causes upper-case and lower-case characters to be treated as identical during the matching process. +*-line*+:: Use newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning in either REs or strings. With this flag, +[^+ bracket expressions and +.+ never match newline, a +^+ anchor matches the null string after any newline in the string in addition to its normal function, and the +$+ anchor matches the null string before any newline in the string in addition to its normal function. +*-indices*+:: Changes what is stored in the subMatchVars. Instead of storing the matching characters from string, each variable will contain a list of two decimal strings giving the indices in string of the first and last characters in the matching range of characters. +*-start* 'offset'+:: Specifies a character index offset into the string at which to start matching the regular expression. If +-indices+ is specified, the indices will be indexed starting from the absolute beginning of the input string. +'offset'+ will be constrained to the bounds of the input string. +*-all*+:: Causes the regular expression to be matched as many times as possible in the string, returning the total number of matches found. If this is specified with match variables, they will contain information for the last match only. +*-inline*+:: Causes the command to return, as a list, the data that would otherwise be placed in match variables. When using +-inline+, match variables may not be specified. If used with +-all+, the list will be concatenated at each iteration, such that a flat list is always returned. For each match iteration, the command will append the overall match data, plus one element for each subexpression in the regular expression. +*--*+:: Marks the end of switches. The argument following this one will be treated as +'exp'+ even if it starts with a +-+. regsub ~~~~~~ +*regsub ?-nocase? ?-all? ?-line? ?-start* 'offset'? ?*--*? 'exp string subSpec ?varName?'+ This command matches the regular expression +'exp'+ against +'string'+ using the rules described in REGULAR EXPRESSIONS above. If +'varName'+ is specified, the commands stores +'string'+ to +'varName'+ with the substitutions detailed below, and returns the number of substitutions made (normally 1 unless +-all+ is specified). This is 0 if there were no matches. If +'varName'+ is not specified, the substituted string will be returned instead. When copying +'string'+, the portion of +'string'+ that matched +'exp'+ is replaced with +'subSpec'+. If +'subSpec'+ contains a +&+ or +{backslash}0+, then it is replaced in the substitution with the portion of +'string'+ that matched +'exp'+. If +'subSpec'+ contains a +{backslash}n+, where +'n'+ is a digit between 1 and 9, then it is replaced in the substitution with the portion of +'string'+ that matched the +'n'+\'-th parenthesized subexpression of +'exp'+. Additional backslashes may be used in +'subSpec'+ to prevent special interpretation of +&+ or +{backslash}0+ or +{backslash}n+ or backslash. The use of backslashes in +'subSpec'+ tends to interact badly with the Tcl parser's use of backslashes, so it's generally safest to enclose +'subSpec'+ in braces if it includes backslashes. The following switches modify the behaviour of +'regsub'+ +*-nocase*+:: Upper-case characters in +'string'+ are converted to lower-case before matching against +'exp'+; however, substitutions specified by +'subSpec'+ use the original unconverted form of +'string'+. +*-all*+:: All ranges in +'string'+ that match +'exp'+ are found and substitution is performed for each of these ranges, rather than only the first. The +&+ and +{backslash}n+ sequences are handled for each substitution using the information from the corresponding match. +*-line*+:: Use newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning in either REs or strings. With this flag, +[^+ bracket expressions and +.+ never match newline, a +^+ anchor matches the null string after any newline in the string in addition to its normal function, and the +$+ anchor matches the null string before any newline in the string in addition to its normal function. +*-start* 'offset'+:: Specifies a character index offset into the string at which to start matching the regular expression. +'offset'+ will be constrained to the bounds of the input string. +*--*+:: Marks the end of switches. The argument following this one will be treated as +'exp'+ even if it starts with a +-+. ref ~~~ +*ref* 'string tag ?finalizer?'+ Create a new reference containing +'string'+ of type +'tag'+. If +'finalizer'+ is specified, it is a command which will be invoked when the a garbage collection cycle runs and this reference is no longer accessible. The finalizer is invoked as: finalizer reference string See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. rename ~~~~~~ +*rename* 'oldName newName'+ Rename the command that used to be called +'oldName'+ so that it is now called +'newName'+. If +'newName'+ is an empty string (e.g. {}) then +'oldName'+ is deleted. The `rename` command returns an empty string as result. return ~~~~~~ +*return* ?*-code* 'code'? ?*-errorinfo* 'stacktrace'? ?*-errorcode* 'errorcode'? ?*-level* 'n'? ?'value'?+ Return immediately from the current procedure (or top-level command or `source` command), with +'value'+ as the return value. If +'value'+ is not specified, an empty string will be returned as result. If +-code+ is specified (as either a number or ok, error, break, continue, signal, return or exit), this code will be used instead of +JIM_OK+. This is generally useful when implementing flow of control commands. If +-level+ is specified and greater than 1, it has the effect of delaying the new return code from +-code+. This is useful when rethrowing an error from `catch`. See the implementation of try/catch in tclcompat.tcl for an example of how this is done. Note: The following options are only used when +-code+ is JIM_ERR. If +-errorinfo+ is specified (as returned from `info stacktrace`) it is used to initialize the stacktrace. If +-errorcode+ is specified, it is used to set the global variable $::errorCode. scan ~~~~ +*scan* 'string format varName1 ?varName2 \...?'+ This command parses fields from an input string in the same fashion as the C 'sscanf' procedure. +'string'+ gives the input to be parsed and +'format'+ indicates how to parse it, using '%' fields as in 'sscanf'. All of the 'sscanf' options are valid; see the 'sscanf' man page for details. Each +'varName'+ gives the name of a variable; when a field is scanned from +'string'+, the result is converted back into a string and assigned to the corresponding +'varName'+. The only unusual conversion is for '%c'. For '%c' conversions a single character value is converted to a decimal string, which is then assigned to the corresponding +'varName'+; no field width may be specified for this conversion. seek ~~~~ +*seek* 'fileId offset ?origin?'+ +'fileId' *seek* 'offset ?origin?'+ Change the current access position for +'fileId'+. The +'offset'+ and +'origin'+ arguments specify the position at which the next read or write will occur for +'fileId'+. +'offset'+ must be a number (which may be negative) and +'origin'+ must be one of the following: +*start*+:: The new access position will be +'offset'+ bytes from the start of the file. +*current*+:: The new access position will be +'offset'+ bytes from the current access position; a negative +'offset'+ moves the access position backwards in the file. +*end*+:: The new access position will be +'offset'+ bytes from the end of the file. A negative +'offset'+ places the access position before the end-of-file, and a positive +'offset'+ places the access position after the end-of-file. The +'origin'+ argument defaults to +start+. +'fileId'+ must have been the return value from a previous call to `open`, or it may be +stdin+, +stdout+, or +stderr+ to refer to one of the standard I/O channels. This command returns an empty string. set ~~~ +*set* 'varName ?value?'+ Returns the value of variable +'varName'+. If +'value'+ is specified, then set the value of +'varName'+ to +'value'+, creating a new variable if one doesn't already exist, and return its value. If +'varName'+ contains an open parenthesis and ends with a close parenthesis, then it refers to an array element: the characters before the open parenthesis are the name of the array, and the characters between the parentheses are the index within the array. Otherwise +'varName'+ refers to a scalar variable. If no procedure is active, then +'varName'+ refers to a global variable. If a procedure is active, then +'varName'+ refers to a parameter or local variable of the procedure, unless the +'global'+ command has been invoked to declare +'varName'+ to be global. The +::+ prefix may also be used to explicitly reference a variable in the global scope. setref ~~~~~~ +*setref* 'reference string'+ Store a new string in +'reference'+, replacing the existing string. The reference must be a valid reference create with the `ref` command. See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail. signal ~~~~~~ Command for signal handling. See `kill` for the different forms which may be used to specify signals. Commands which return a list of signal names do so using the canonical form: "+SIGINT SIGTERM+". +*signal handle* ?'signals \...'?+:: If no signals are given, returns a list of all signals which are currently being handled. If signals are specified, these are added to the list of signals currently being handled. +*signal ignore* ?'signals \...'?+:: If no signals are given, returns a lists all signals which are currently being ignored. If signals are specified, these are added to the list of signals currently being ignored. These signals are still delivered, but are not considered by `catch -signal` or `try -signal`. Use `signal check` to determine which signals have occurred but been ignored. +*signal default* ?'signals \...'?+:: If no signals are given, returns a lists all signals which are currently have the default behaviour. If signals are specified, these are added to the list of signals which have the default behaviour. +*signal check ?-clear?* ?'signals \...'?+:: Returns a list of signals which have been delivered to the process but are 'ignored'. If signals are specified, only that set of signals will be checked, otherwise all signals will be checked. If +-clear+ is specified, any signals returned are removed and will not be returned by subsequent calls to `signal check` unless delivered again. +*signal throw* ?'signal'?+:: Raises the given signal, which defaults to +SIGINT+ if not specified. The behaviour is identical to: kill signal [pid] Note that `signal handle` and `signal ignore` represent two forms of signal handling. `signal handle` is used in conjunction with `catch -signal` or `try -signal` to immediately abort execution when the signal is delivered. Alternatively, `signal ignore` is used in conjunction with `signal check` to handle signal synchronously. Consider the two examples below. Prevent a processing from taking too long signal handle SIGALRM alarm 20 try -signal { .. possibly long running process .. alarm 0 } on signal {sig} { puts stderr "Process took too long" } Handle SIGHUP to reconfigure: signal ignore SIGHUP while {1} { ... handle configuration/reconfiguration ... while {[signal check -clear SIGHUP] eq ""} { ... do processing .. } # Received SIGHUP, so reconfigure } sleep ~~~~~ +*sleep* 'seconds'+ Pauses for the given number of seconds, which may be a floating point value less than one to sleep for less than a second, or an integer to sleep for one or more seconds. source ~~~~~~ +*source* 'fileName'+ Read file +'fileName'+ and pass the contents to the Tcl interpreter as a sequence of commands to execute in the normal fashion. The return value of `source` is the return value of the last command executed from the file. If an error occurs in executing the contents of the file, then the `source` command will return that error. If a `return` command is invoked from within the file, the remainder of the file will be skipped and the `source` command will return normally with the result from the `return` command. split ~~~~~ +*split* 'string ?splitChars?'+ Returns a list created by splitting +'string'+ at each character that is in the +'splitChars'+ argument. Each element of the result list will consist of the characters from +'string'+ between instances of the characters in +'splitChars'+. Empty list elements will be generated if +'string'+ contains adjacent characters in +'splitChars'+, or if the first or last character of +'string'+ is in +'splitChars'+. If +'splitChars'+ is an empty string then each character of +'string'+ becomes a separate element of the result list. +'splitChars'+ defaults to the standard white-space characters. For example, split "comp.unix.misc" . returns +'"comp unix misc"'+ and split "Hello world" {} returns +'"H e l l o { } w o r l d"'+. stackdump ~~~~~~~~~ +*stackdump* 'stacktrace'+ Creates a human readable representation of a stack trace. stacktrace ~~~~~~~~~~ +*stacktrace*+ Returns a live stack trace as a list of +proc file line proc file line \...+. Iteratively uses `info frame` to create the stack trace. This stack trace is in the same form as produced by `catch` and `info stacktrace` See also `stackdump`. string ~~~~~~ +*string* 'option arg ?arg \...?'+ Perform one of several string operations, depending on +'option'+. The legal options (which may be abbreviated) are: +*string bytelength* 'string'+:: Returns the length of the string in bytes. This will return the same value as `string length` if UTF-8 support is not enabled, or if the string is composed entirely of ASCII characters. See UTF-8 AND UNICODE. +*string byterange* 'string first last'+:: Like `string range` except works on bytes rather than characters. These commands are identical if UTF-8 support is not enabled. +*string cat* '?string1 string2 \...?'+:: Concatenates the given strings into a single string. +*string compare ?-nocase?* ?*-length* 'len? string1 string2'+:: Perform a character-by-character comparison of strings +'string1'+ and +'string2'+ in the same way as the C 'strcmp' procedure. Return -1, 0, or 1, depending on whether +'string1'+ is lexicographically less than, equal to, or greater than +'string2'+. If +-length+ is specified, then only the first +'len'+ characters are used in the comparison. If +'len'+ is negative, it is ignored. Performs a case-insensitive comparison if +-nocase+ is specified. +*string equal ?-nocase?* '?*-length* len?' 'string1 string2'+:: Returns 1 if the strings are equal, or 0 otherwise. If +-length+ is specified, then only the first +'len'+ characters are used in the comparison. If +'len'+ is negative, it is ignored. Performs a case-insensitive comparison if +-nocase+ is specified. +*string first* 'string1 string2 ?firstIndex?'+:: Search +'string2'+ for a sequence of characters that exactly match the characters in +'string1'+. If found, return the index of the first character in the first such match within +'string2'+. If not found, return -1. If +'firstIndex'+ is specified, matching will start from +'firstIndex'+ of +'string1'+. :: See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'firstIndex'+. +*string index* 'string charIndex'+:: Returns the +'charIndex'+'th character of the +'string'+ argument. A +'charIndex'+ of 0 corresponds to the first character of the string. If +'charIndex'+ is less than 0 or greater than or equal to the length of the string then an empty string is returned. :: See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'charIndex'+. +*string is* 'class' ?*-strict*? 'string'+:: Returns 1 if +'string'+ is a valid member of the specified character class, otherwise returns 0. If +-strict+ is specified, then an empty string returns 0, otherwise an empty string will return 1 on any class. The following character classes are recognized (the class name can be abbreviated): :: +alnum+;; Any alphabet or digit character. +alpha+;; Any alphabet character. +ascii+;; Any character with a value less than 128 (those that are in the 7-bit ascii range). +control+;; Any control character. +digit+;; Any digit character. +double+;; Any of the valid forms for a double in Tcl, with optional surrounding whitespace. In case of under/overflow in the value, 0 is returned. +graph+;; Any printing character, except space. +integer+;; Any of the valid string formats for an integer value in Tcl, with optional surrounding whitespace. +lower+;; Any lower case alphabet character. +print+;; Any printing character, including space. +punct+;; Any punctuation character. +space+;; Any space character. +upper+;; Any upper case alphabet character. +xdigit+;; Any hexadecimal digit character ([0-9A-Fa-f]). :: Note that string classification does +'not'+ respect UTF-8. See UTF-8 AND UNICODE +*string last* 'string1 string2 ?lastIndex?'+:: Search +'string2'+ for a sequence of characters that exactly match the characters in +'string1'+. If found, return the index of the first character in the last such match within +'string2'+. If there is no match, then return -1. If +'lastIndex'+ is specified, only characters up to +'lastIndex'+ of +'string2'+ will be considered in the match. :: See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'lastIndex'+. +*string length* 'string'+:: Returns a decimal string giving the number of characters in +'string'+. If UTF-8 support is enabled, this may be different than the number of bytes. See UTF-8 AND UNICODE +*string map ?-nocase?* 'mapping string'+:: Replaces substrings in +'string'+ based on the key-value pairs in +'mapping'+, which is a list of +key value key value \...+ as in the form returned by `array get`. Each instance of a key in the string will be replaced with its corresponding value. If +-nocase+ is specified, then matching is done without regard to case differences. Both key and value may be multiple characters. Replacement is done in an ordered manner, so the key appearing first in the list will be checked first, and so on. +'string'+ is only iterated over once, so earlier key replacements will have no affect for later key matches. For example, string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc :: will return the string +01321221+. :: Note that if an earlier key is a prefix of a later one, it will completely mask the later one. So if the previous example is reordered like this, string map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc :: it will return the string +02c322c222c+. +*string match ?-nocase?* 'pattern string'+:: See if +'pattern'+ matches +'string'+; return 1 if it does, 0 if it doesn't. Matching is done in a fashion similar to that used by the C-shell. For the two strings to match, their contents must be identical except that the following special sequences may appear in +'pattern'+: +*+;; Matches any sequence of characters in +'string'+, including a null string. +?+;; Matches any single character in +'string'+. +['chars']+;; Matches any character in the set given by +'chars'+. If a sequence of the form +'x-y'+ appears in +'chars'+, then any character between +'x'+ and +'y'+, inclusive, will match. +{backslash}x+;; Matches the single character +'x'+. This provides a way of avoiding the special interpretation of the characters +{backslash}*?[]+ in +'pattern'+. :: Performs a case-insensitive comparison if +-nocase+ is specified. +*string range* 'string first last'+:: Returns a range of consecutive characters from +'string'+, starting with the character whose index is +'first'+ and ending with the character whose index is +'last'+. An index of 0 refers to the first character of the string. :: See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+. :: If +'first'+ is less than zero then it is treated as if it were zero, and if +'last'+ is greater than or equal to the length of the string then it is treated as if it were +end+. If +'first'+ is greater than +'last'+ then an empty string is returned. +*string repeat* 'string count'+:: Returns a new string consisting of +'string'+ repeated +'count'+ times. +*string replace* 'string first last ?newstring?'+:: Removes a range of consecutive characters from +'string'+, starting with the character whose index is +'first'+ and ending with the character whose index is +'last'+. If +'newstring'+ is specified, then it is placed in the removed character range. If +'first'+ is less than zero then it is treated as if it were zero, and if +'last'+ is greater than or equal to the length of the string then it is treated as if it were +end+. If +'first'+ is greater than +'last'+ or the length of the initial string, or +'last'+ is less than 0, then the initial string is returned untouched. +*string reverse* 'string'+:: Returns a string that is the same length as +'string'+ but with its characters in the reverse order. +*string tolower* 'string'+:: Returns a value equal to +'string'+ except that all upper case letters have been converted to lower case. +*string totitle* 'string'+:: Returns a value equal to +'string'+ except that the first character is converted to title case (or upper case if there is no UTF-8 titlecase variant) and all remaining characters have been converted to lower case. +*string toupper* 'string'+:: Returns a value equal to +'string'+ except that all lower case letters have been converted to upper case. +*string trim* 'string ?chars?'+:: Returns a value equal to +'string'+ except that any leading or trailing characters from the set given by +'chars'+ are removed. If +'chars'+ is not specified then white space is removed (spaces, tabs, newlines, and carriage returns). +*string trimleft* 'string ?chars?'+:: Returns a value equal to +'string'+ except that any leading characters from the set given by +'chars'+ are removed. If +'chars'+ is not specified then white space is removed (spaces, tabs, newlines, and carriage returns). +*string trimright* 'string ?chars?'+:: Returns a value equal to +'string'+ except that any trailing characters from the set given by +'chars'+ are removed. If +'chars'+ is not specified then white space is removed (spaces, tabs, newlines, and carriage returns). Null characters are always removed. subst ~~~~~ +*subst ?-nobackslashes? ?-nocommands? ?-novariables?* 'string'+ This command performs variable substitutions, command substitutions, and backslash substitutions on its string argument and returns the fully-substituted result. The substitutions are performed in exactly the same way as for Tcl commands. As a result, the string argument is actually substituted twice, once by the Tcl parser in the usual fashion for Tcl commands, and again by the subst command. If any of the +-nobackslashes+, +-nocommands+, or +-novariables+ are specified, then the corresponding substitutions are not performed. For example, if +-nocommands+ is specified, no command substitution is performed: open and close brackets are treated as ordinary characters with no special interpretation. *Note*: when it performs its substitutions, subst does not give any special treatment to double quotes or curly braces. For example, the following script returns +xyz \{44\}+, not +xyz \{$a\}+. set a 44 subst {xyz {$a}} switch ~~~~~~ +*switch* '?options? string pattern body ?pattern body \...?'+ +*switch* '?options? string {pattern body ?pattern body \...?}'+ The `switch` command matches its string argument against each of the pattern arguments in order. As soon as it finds a pattern that matches string it evaluates the following body and returns the result of that evaluation. If the last pattern argument is default then it matches anything. If no pattern argument matches string and no default is given, then the `switch` command returns an empty string. If the initial arguments to switch start with - then they are treated as options. The following options are currently supported: +-exact+:: Use exact matching when comparing string to a pattern. This is the default. +-glob+:: When matching string to the patterns, use glob-style matching (i.e. the same as implemented by the string match command). +-regexp+:: When matching string to the patterns, use regular expression matching (i.e. the same as implemented by the regexp command). +-command 'commandname'+:: When matching string to the patterns, use the given command, which must be a single word. The command is invoked as 'commandname pattern string', or 'commandname -nocase pattern string' and must return 1 if matched, or 0 if not. +--+:: Marks the end of options. The argument following this one will be treated as string even if it starts with a +-+. Two syntaxes are provided for the pattern and body arguments. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line `switch` commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the pattern arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behaviour of the second form different than the first form in some cases. If a body is specified as +-+ it means that the body for the next pattern should also be used as the body for this pattern (if the next pattern also has a body of +-+ then the body after that is used, and so on). This feature makes it possible to share a single body among several patterns. Below are some examples of `switch` commands: switch abc a - b {format 1} abc {format 2} default {format 3} will return 2, switch -regexp aaab { ^a.*b$ - b {format 1} a* {format 2} default {format 3} } will return 1, and switch xyz { a - b {format 1} a* {format 2} default {format 3} } will return 3. tailcall ~~~~~~~~ +*tailcall* 'cmd ?arg\...?'+ The `tailcall` command provides an optimised way of invoking a command whilst replacing the current call frame. This is similar to 'exec' in Bourne Shell. The following are identical except the first immediately replaces the current call frame. tailcall a b c return [uplevel 1 [list a b c]] `tailcall` is useful as a dispatch mechanism: proc a {cmd args} { tailcall sub_$cmd {*}$args } proc sub_cmd1 ... proc sub_cmd2 ... tell ~~~~ +*tell* 'fileId'+ +'fileId' *tell*+ Returns a decimal string giving the current access position in +'fileId'+. +'fileId'+ must have been the return value from a previous call to `open`, or it may be +stdin+, +stdout+, or +stderr+ to refer to one of the standard I/O channels. throw ~~~~~ +*throw* 'code ?msg?'+ This command throws an exception (return) code along with an optional message. This command is mostly for convenient usage with `try`. The command +throw break+ is equivalent to +break+. The command +throw 20 message+ can be caught with an +on 20 \...+ clause to `try`. time ~~~~ +*time* 'command ?count?'+ This command will call the Tcl interpreter +'count'+ times to execute +'command'+ (or once if +'count'+ isn't specified). It will then return a string of the form 503 microseconds per iteration which indicates the average amount of time required per iteration, in microseconds. Time is measured in elapsed time, not CPU time. try ~~~ +*try* '?catchopts? tryscript' ?*on* 'returncodes {?resultvar? ?optsvar?} handlerscript \...'? ?*finally* 'finalscript'?+ The `try` command is provided as a convenience for exception handling. This interpeter first evaluates +'tryscript'+ under the effect of the catch options +'catchopts'+ (e.g. +-signal -noexit --+, see `catch`). It then evaluates the script for the first matching 'on' handler (there many be zero or more) based on the return code from the `try` section. For example a normal +JIM_ERR+ error will be matched by an 'on error' handler. Finally, any +'finalscript'+ is evaluated. The result of this command is the result of +'tryscript'+, except in the case where an exception occurs in a matching 'on' handler script or the 'finally' script, in which case the result is this new exception. The specified +'returncodes'+ is a list of return codes either as names ('ok', 'error', 'break', etc.) or as integers. If +'resultvar'+ and +'optsvar'+ are specified, they are set as for `catch` before evaluating the matching handler. For example: set f [open input] try -signal { process $f } on {continue break} {} { error "Unexpected break/continue" } on error {msg opts} { puts "Dealing with error" return {*}$opts $msg } on signal sig { puts "Got signal: $sig" } finally { $f close } If break, continue or error are raised, they are dealt with by the matching handler. In any case, the file will be closed via the 'finally' clause. See also `throw`, `catch`, `return`, `error`. unknown ~~~~~~~ +*unknown* 'cmdName ?arg arg ...?'+ This command doesn't actually exist as part of Tcl, but Tcl will invoke it if it does exist. If the Tcl interpreter encounters a command name for which there is not a defined command, then Tcl checks for the existence of a command named `unknown`. If there is no such command, then the interpreter returns an error. If the `unknown` command exists, then it is invoked with arguments consisting of the fully-substituted name and arguments for the original non-existent command. The `unknown` command typically does things like searching through library directories for a command procedure with the name +'cmdName'+, or expanding abbreviated command names to full-length, or automatically executing unknown commands as UNIX sub-processes. In some cases (such as expanding abbreviations) `unknown` will change the original command slightly and then (re-)execute it. The result of the `unknown` command is used as the result for the original non-existent command. unset ~~~~~ +*unset ?-nocomplain? ?--?* '?name name ...?'+ Remove variables. Each +'name'+ is a variable name, specified in any of the ways acceptable to the `set` command. If a +'name'+ refers to an element of an array, then that element is removed without affecting the rest of the array. If a +'name'+ consists of an array name with no parenthesized index, then the entire array is deleted. The `unset` command returns an empty string as result. An error occurs if any of the variables doesn't exist, unless '-nocomplain' is specified. The '--' argument may be specified to stop option processing in case the variable name may be '-nocomplain'. upcall ~~~~~~~ +*upcall* 'command ?args ...?'+ May be used from within a proc defined as `local` `proc` in order to call the previous, hidden version of the same command. If there is no previous definition of the command, an error is returned. uplevel ~~~~~~~ +*uplevel* '?level? command ?command ...?'+ All of the +'command'+ arguments are concatenated as if they had been passed to `concat`; the result is then evaluated in the variable context indicated by +'level'+. `uplevel` returns the result of that evaluation. If +'level'+ is an integer, then it gives a distance (up the procedure calling stack) to move before executing the command. If +'level'+ consists of +\#+ followed by a number then the number gives an absolute level number. If +'level'+ is omitted then it defaults to +1+. +'level'+ cannot be defaulted if the first +'command'+ argument starts with a digit or +#+. For example, suppose that procedure 'a' was invoked from top-level, and that it called 'b', and that 'b' called 'c'. Suppose that 'c' invokes the `uplevel` command. If +'level'+ is +1+ or +#2+ or omitted, then the command will be executed in the variable context of 'b'. If +'level'+ is +2+ or +#1+ then the command will be executed in the variable context of 'a'. If +'level'+ is '3' or +#0+ then the command will be executed at top-level (only global variables will be visible). The `uplevel` command causes the invoking procedure to disappear from the procedure calling stack while the command is being executed. In the above example, suppose 'c' invokes the command uplevel 1 {set x 43; d} where 'd' is another Tcl procedure. The `set` command will modify the variable 'x' in 'b's context, and 'd' will execute at level 3, as if called from 'b'. If it in turn executes the command uplevel {set x 42} then the `set` command will modify the same variable 'x' in 'b's context: the procedure 'c' does not appear to be on the call stack when 'd' is executing. The command `info level` may be used to obtain the level of the current procedure. `uplevel` makes it possible to implement new control constructs as Tcl procedures (for example, `uplevel` could be used to implement the `while` construct as a Tcl procedure). upvar ~~~~~ +*upvar* '?level? otherVar myVar ?otherVar myVar ...?'+ This command arranges for one or more local variables in the current procedure to refer to variables in an enclosing procedure call or to global variables. +'level'+ may have any of the forms permitted for the `uplevel` command, and may be omitted if the first letter of the first +'otherVar'+ isn't +#+ or a digit (it defaults to '1'). For each +'otherVar'+ argument, `upvar` makes the variable by that name in the procedure frame given by +'level'+ (or at global level, if +'level'+ is +#0+) accessible in the current procedure by the name given in the corresponding +'myVar'+ argument. The variable named by +'otherVar'+ need not exist at the time of the call; it will be created the first time +'myVar'+ is referenced, just like an ordinary variable. `upvar` may only be invoked from within procedures. `upvar` returns an empty string. The `upvar` command simplifies the implementation of call-by-name procedure calling and also makes it easier to build new control constructs as Tcl procedures. For example, consider the following procedure: proc add2 name { upvar $name x set x [expr $x+2] } 'add2' is invoked with an argument giving the name of a variable, and it adds two to the value of that variable. Although 'add2' could have been implemented using `uplevel` instead of `upvar`, `upvar` makes it simpler for 'add2' to access the variable in the caller's procedure frame. while ~~~~~ +*while* 'test body'+ The +'while'+ command evaluates +'test'+ as an expression (in the same way that `expr` evaluates its argument). The value of the expression must be numeric; if it is non-zero then +'body'+ is executed by passing it to the Tcl interpreter. Once +'body'+ has been executed then +'test'+ is evaluated again, and the process repeats until eventually +'test'+ evaluates to a zero numeric value. `continue` commands may be executed inside +'body'+ to terminate the current iteration of the loop, and `break` commands may be executed inside +'body'+ to cause immediate termination of the `while` command. The `while` command always returns an empty string. OPTIONAL-EXTENSIONS ------------------- The following extensions may or may not be available depending upon what options were selected when Jim Tcl was built. [[cmd_1]] posix: os.fork, os.wait, os.gethostname, os.getids, os.uptime ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*os.fork*+:: Invokes 'fork(2)' and returns the result. +*os.wait -nohang* 'pid'+:: Invokes waitpid(2), with WNOHANG if +-nohang+ is specified. Returns a list of 3 elements. {0 none 0} if -nohang is specified, and the process is still alive. {-1 error } if the process does not exist or has already been waited for. { exit } if the process exited normally. { signal } if the process terminated on a signal. { other 0} otherwise (core dump, stopped, continued, etc.) +*os.gethostname*+:: Invokes 'gethostname(3)' and returns the result. +*os.getids*+:: Returns the various user/group ids for the current process. jim> os.getids uid 1000 euid 1000 gid 100 egid 100 +*os.uptime*+:: Returns the number of seconds since system boot. See description of 'uptime' in 'sysinfo(2)'. ANSI I/O (aio) and EVENTLOOP API -------------------------------- Jim provides an alternative object-based API for I/O. See `open` and `socket` for commands which return an I/O handle. aio ~~~ +$handle *accept* ?addrvar?+:: Server socket only: Accept a connection and return stream. If +'addrvar'+ is specified, the address of the connected client is stored in the named variable in the form 'addr:port'. See `socket` for details. +$handle *buffering none|line|full*+:: Sets the buffering mode of the stream. +$handle *close* ?r(ead)|w(rite)?+:: Closes the stream. The two-argument form is a "half-close" on a socket. See the +shutdown(2)+ man page. +$handle *copyto* 'tofd ?size?'+:: Copy bytes to the file descriptor +'tofd'+. If +'size'+ is specified, at most that many bytes will be copied. Otherwise copying continues until the end of the input file. Returns the number of bytes actually copied. +$handle *eof*+:: Returns 1 if stream is at eof +$handle *filename*+:: Returns the original filename associated with the handle. Handles returned by `socket` give the socket type instead of a filename. +$handle *flush*+:: Flush the stream +$handle *gets* '?var?'+:: Read one line and return it or store it in the var +$handle *isatty*+:: Returns 1 if the stream is a tty device. +$handle *ndelay ?0|1?*+:: Set O_NDELAY (if arg). Returns current/new setting. Note that in general ANSI I/O interacts badly with non-blocking I/O. Use with care. +$handle *puts ?-nonewline?* 'str'+:: Write the string, with newline unless -nonewline +$handle *read ?-nonewline?* '?len?'+:: Read and return bytes from the stream. To eof if no len. +$handle *recvfrom* 'maxlen ?addrvar?'+:: Receives a message from the handle via recvfrom(2) and returns it. At most +'maxlen'+ bytes are read. If +'addrvar'+ is specified, the sending address of the message is stored in the named variable in the form 'addr:port'. See `socket` for details. +$handle *seek* 'offset' *?start|current|end?*+:: Seeks in the stream (default 'current') +$handle *sendto* 'str ?addr:?port'+:: Sends the string, +'str'+, to the given address via the socket using sendto(2). This is intended for udp/dgram sockets and may give an error or behave in unintended ways for other handle types. Returns the number of bytes written. +$handle *tell*+:: Returns the current seek position fconfigure ~~~~~~~~~~ +*fconfigure* 'handle' *?-blocking 0|1? ?-buffering noneline|full? ?-translation* 'mode'?+:: For compatibility with Tcl, a limited form of the `fconfigure` command is supported. * `fconfigure ... -blocking` maps to `aio ndelay` * `fconfigure ... -buffering` maps to `aio buffering` * `fconfigure ... -translation` is accepted but ignored [[cmd_2]] eventloop: after, vwait, update ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following commands allow a script to be invoked when the given condition occurs. If no script is given, returns the current script. If the given script is the empty, the handler is removed. +$handle *readable* '?readable-script?'+:: Sets or returns the script for when the socket is readable. +$handle *writable* '?writable-script?'+:: Sets or returns the script for when the socket is writable. +$handle *onexception* '?exception-script?'+:: Sets or returns the script for when when oob data received. For compatibility with 'Tcl', these may be prefixed with `fileevent`. e.g. :: +fileevent $handle *readable* '\...'+ Time-based execution is also available via the eventloop API. +*after* 'ms'+:: Sleeps for the given number of milliseconds. No events are processed during this time. +*after* 'ms'|*idle* script ?script \...?'+:: The scripts are concatenated and executed after the given number of milliseconds have elapsed. If 'idle' is specified, the script will run the next time the event loop is processed with `vwait` or `update`. The script is only run once and then removed. Returns an event id. +*after cancel* 'id|command'+:: Cancels an `after` event with the given event id or matching command (script). Returns the number of milliseconds remaining until the event would have fired. Returns the empty string if no matching event is found. +*after info* '?id?'+:: If +'id'+ is not given, returns a list of current `after` events. If +'id'+ is given, returns a list containing the associated script and either 'timer' or 'idle' to indicated the type of the event. An error occurs if +'id'+ does not match an event. +*vwait* 'variable'+:: A call to `vwait` is enters the eventloop. `vwait` processes events until the named (global) variable changes or all event handlers are removed. The variable need not exist beforehand. If there are no event handlers defined, `vwait` returns immediately. +*update ?idletasks?*+:: A call to `update` enters the eventloop to process expired events, but no new events. If 'idletasks' is specified, only expired time events are handled, not file events. Returns once handlers have been run for all expired events. Scripts are executed at the global scope. If an error occurs during a handler script, an attempt is made to call (the user-defined command) `bgerror` with the details of the error. If the `bgerror` command does not exist, the error message details are printed to stderr instead. If a file event handler script generates an error, the handler is automatically removed to prevent infinite errors. (A time event handler is always removed after execution). +*bgerror* 'msg'+:: Called when an event handler script generates an error. Note that the normal command resolution rules are used for bgerror. First the name is resolved in the current namespace, then in the global scope. socket ~~~~~~ Various socket types may be created. +*socket unix* 'path'+:: A unix domain socket client. +*socket unix.server* 'path'+:: A unix domain socket server. +*socket ?-ipv6? stream* 'addr:port'+:: A TCP socket client. (See the forms for +'addr'+ below) +*socket ?-ipv6? stream.server* '?addr:?port'+:: A TCP socket server (+'addr'+ defaults to +0.0.0.0+ for IPv4 or +[::]+ for IPv6). +*socket ?-ipv6? dgram* ?'addr:port'?+:: A UDP socket client. If the address is not specified, the client socket will be unbound and 'sendto' must be used to indicated the destination. +*socket ?-ipv6? dgram.server* 'addr:port'+:: A UDP socket server. +*socket pipe*+:: A pipe. Note that unlike all other socket types, this command returns a list of two channels: {read write} +*socket pair*+:: A socketpair (see socketpair(2)). Like `socket pipe`, this command returns a list of two channels: {s1 s2}. These channels are both readable and writable. This command creates a socket connected (client) or bound (server) to the given address. The returned value is channel and may generally be used with the various file I/O commands (gets, puts, read, etc.), either as object-based syntax or Tcl-compatible syntax. set f [socket stream www.google.com:80] aio.sockstream1 $f puts -nonewline "GET / HTTP/1.0\r\n\r\n" $f gets HTTP/1.0 302 Found $f close Server sockets, however support only 'accept', which is most useful in conjunction with the EVENTLOOP API. set f [socket stream.server 80] $f readable { set client [$f accept] $client gets $buf ... $client puts -nonewline "HTTP/1.1 404 Not found\r\n" $client close } vwait done The address, +'addr'+, can be given in one of the following forms: 1. For IPv4 socket types, an IPv4 address such as 192.168.1.1 2. For IPv6 socket types, an IPv6 address such as [fe80::1234] or [::] 3. A hostname Note that on many systems, listening on an IPv6 address such as [::] will also accept requests via IPv4. Where a hostname is specified, the +'first'+ returned address is used which matches the socket type is used. The special type 'pipe' isn't really a socket. lassign [socket pipe] r w # Must close $w after exec exec ps >@$w & $w close $r readable ... syslog ~~~~~~ +*syslog* '?options? ?priority? message'+ This command sends message to system syslog facility with given priority. Valid priorities are: emerg, alert, crit, err, error, warning, notice, info, debug If a message is specified, but no priority is specified, then a priority of info is used. By default, facility user is used and the value of global tcl variable argv0 is used as ident string. However, any of the following options may be specified before priority to control these parameters: +*-facility* 'value'+:: Use specified facility instead of user. The following values for facility are recognized: authpriv, cron, daemon, kernel, lpr, mail, news, syslog, user, uucp, local0-local7 +*-ident* 'string'+:: Use given string instead of argv0 variable for ident string. +*-options* 'integer'+:: Set syslog options such as +LOG_CONS+, +LOG_NDELAY+. You should use numeric values of those from your system syslog.h file, because I haven't got time to implement yet another hash table. pack: pack, unpack ~~~~~~~~~~~~~~~~~~ The optional 'pack' extension provides commands to encode and decode binary strings. +*pack* 'varName value' *-intle|-intbe|-floatle|-floatbe|-str* 'bitwidth ?bitoffset?'+:: Packs the binary representation of +'value'+ into the variable +'varName'+. The value is packed according to the given type (integer/floating point/string, big-endian/little-endian), width and bit offset. The variable is created if necessary (like `append`). Ihe variable is expanded if necessary. +*unpack* 'binvalue' *-intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str* 'bitpos bitwidth'+:: Unpacks bits from +'binvalue'+ at bit position +'bitpos'+ and with +'bitwidth'+. Interprets the value according to the type (integer/floating point/string, big-endian/little-endian and signed/unsigned) and returns it. For integer types, +'bitwidth'+ may be up to the size of a Jim Tcl integer (typically 64 bits). For floating point types, +'bitwidth'+ may be 32 bits (for single precision numbers) or 64 bits (for double precision). For the string type, both the width and the offset must be on a byte boundary (multiple of 8). Attempting to access outside the length of the value will return 0 for integer types, 0.0 for floating point types or the empty string for the string type. binary ~~~~~~ The optional, pure-Tcl 'binary' extension provides the Tcl-compatible `binary scan` and `binary format` commands based on the low-level `pack` and `unpack` commands. See the Tcl documentation at: http://www.tcl.tk/man/tcl8.5/TclCmd/binary.htm Note that 'binary format' with f/r/R specifiers (single-precision float) uses the value of Infinity in case of overflow. oo: class, super ~~~~~~~~~~~~~~~~ The optional, pure-Tcl 'oo' extension provides object-oriented (OO) support for Jim Tcl. See the online documentation (http://jim.tcl.tk/index.html/doc/www/www/documentation/oo/) for more details. +*class* 'classname ?baseclasses? classvars'+:: Create a new class, +'classname'+, with the given dictionary (+'classvars'+) as class variables. These are the initial variables which all newly created objects of this class are initialised with. If a list of baseclasses is given, methods and instance variables are inherited. +*super* 'method ?args \...?'+:: From within a method, invokes the given method on the base class. Note that this will only call the last baseclass given. tree ~~~~ The optional, pure-Tcl 'tree' extension implements an OO, general purpose tree structure similar to that provided by tcllib ::struct::tree (http://tcllib.sourceforge.net/doc/struct_tree.html) A tree is a collection of nodes, where each node (except the root node) has a single parent and zero or more child nodes (ordered), as well as zero or more attribute/value pairs. +*tree*+:: Creates and returns a new tree object with a single node named "root". All operations on the tree are invoked through this object. +$tree *destroy*+:: Destroy the tree and all it's nodes. (Note that the the tree will also be automatically garbage collected once it goes out of scope). +$tree *set* 'nodename key value'+:: Set the value for the given attribute key. +$tree *lappend* 'nodename key value \...'+:: Append to the (list) value(s) for the given attribute key, or set if not yet set. +$tree *keyexists* 'nodename key'+:: Returns 1 if the given attribute key exists. +$tree *get* 'nodename key'+:: Returns the value associated with the given attribute key. +$tree *getall* 'nodename'+:: Returns the entire attribute dictionary associated with the given key. +$tree *depth* 'nodename'+:: Returns the depth of the given node. The depth of "root" is 0. +$tree *parent* 'nodename'+:: Returns the node name of the parent node, or "" for the root node. +$tree *numchildren* 'nodename'+:: Returns the number of child nodes. +$tree *children* 'nodename'+:: Returns a list of the child nodes. +$tree *next* 'nodename'+:: Returns the next sibling node, or "" if none. +$tree *insert* 'nodename ?index?'+:: Add a new child node to the given node. The index is a list index such as +3+ or +end-2+. The default index is +end+. Returns the name of the newly added node. +$tree *walk* 'nodename' *dfs|bfs* {'actionvar nodevar'} 'script'+:: Walks the tree starting from the given node, either breadth first (+bfs+) depth first (+dfs+). The value +"enter"+ or +"exit"+ is stored in variable +'actionvar'+. The name of each node is stored in +'nodevar'+. The script is evaluated twice for each node, on entry and exit. +$tree *dump*+:: Dumps the tree contents to stdout tcl::prefix ~~~~~~~~~~~ The optional tclprefix extension provides the Tcl8.6-compatible 'tcl::prefix' command (http://www.tcl.tk/man/tcl8.6/TclCmd/prefix.htm) for matching strings against a table of possible values (typically commands or options). +*tcl::prefix all* 'table string'+:: Returns a list of all elements in +'table'+ that begin with the prefix +'string'+. +*tcl::prefix longest* 'table string'+:: Returns the longest common prefix of all elements in +'table'+ that begin with the prefix +'string'+. +*tcl::prefix match* '?options? table string'+:: If +'string'+ equals one element in +'table'+ or is a prefix to exactly one element, the matched element is returned. If not, the result depends on the +-error+ option. * +*-exact*+ Accept only exact matches. * +*-message* 'string'+ Use +'string'+ in the error message at a mismatch. Default is "option". * +*-error* 'options'+ The options are used when no match is found. If +'options'+ is empty, no error is generated and an empty string is returned. Otherwise the options are used as return options when generating the error message. The default corresponds to setting +-level 0+. history ~~~~~~~ The optional history extension provides script access to the command line editing and history support available in 'jimsh'. See 'examples/jtclsh.tcl' for an example. Note: if line editing support is not available, `history getline` acts like `gets` and the remaining subcommands do nothing. +*history load* 'filename'+:: Load history from a (text) file. If the file does not exist or is not readable, it is ignored. +*history getline* 'prompt ?varname?'+:: Displays the given prompt and allows a line to be entered. Similarly to `gets`, if +'varname'+ is given, it receives the line and the length of the line is returned, or -1 on EOF. If +'varname'+ is not given, the line is returned directly. +*history add* 'line'+:: Adds the given line to the history buffer. +*history save* 'filename'+:: Saves the current history buffer to the given file. +*history show*+:: Displays the current history buffer to standard output. namespace ~~~~~~~~~ Provides namespace-related functions. See also: http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm +*namespace code* 'script'+:: Captures the current namespace context for later execution of the script +'script'+. It returns a new script in which script has been wrapped in a +*namespace inscope*+ command. +*namespace current*+:: Returns the fully-qualified name for the current namespace. +*namespace delete* '?namespace ...?'+:: Deletes all commands and variables with the given namespace prefixes. +*namespace eval* 'namespace arg ?arg...?'+:: Activates a namespace called +'namespace'+ and evaluates some code in that context. +*namespace origin* 'command'+:: Returns the fully-qualified name of the original command to which the imported command +'command'+ refers. +*namespace parent* ?namespace?+:: Returns the fully-qualified name of the parent namespace for namespace +'namespace'+, if given, otherwise for the current namespace. +*namespace qualifiers* 'string'+:: Returns any leading namespace qualifiers for +'string'+ +*namespace tail* 'string'+:: Returns the simple name at the end of a qualified string. +*namespace upvar* 'namespace ?arg...?'+:: This command arranges for zero or more local variables in the current procedure to refer to variables in +'namespace'+ +*namespace which* '?-command|-variable? name'+:: Looks up +'name'+ as either a command (the default) or variable and returns its fully-qualified name. [[BuiltinVariables]] BUILT-IN VARIABLES ------------------ The following global variables are created automatically by the Tcl library. +*env*+:: This variable is set by Jim as an array whose elements are the environment variables for the process. Reading an element will return the value of the corresponding environment variable. This array is initialised at startup from the `env` command. It may be modified and will affect the environment passed to commands invoked with `exec`. +*platform_tcl*+:: This variable is set by Jim as an array containing information about the platform on which Jim was built. Currently this includes 'os' and 'platform'. +*auto_path*+:: This variable contains a list of paths to search for packages. It defaults to a location based on where jim is installed (e.g. +/usr/local/lib/jim+), but may be changed by +jimsh+ or the embedding application. Note that +jimsh+ will consider the environment variable +$JIMLIB+ to be a list of colon-separated list of paths to add to +*auto_path*+. +*errorCode*+:: This variable holds the value of the -errorcode return option set by the most recent error that occurred in this interpreter. This list value represents additional information about the error in a form that is easy to process with programs. The first element of the list identifies a general class of errors, and determines the format of the rest of the list. The following formats for -errorcode return options are used by the Tcl core; individual applications may define additional formats. Currently only `exec` sets this variable. Otherwise it will be +NONE+. The following global variables are set by jimsh. +*tcl_interactive*+:: This variable is set to 1 if jimsh is started in interactive mode or 0 otherwise. +*tcl_platform*+:: This variable is set by Jim as an array containing information about the platform upon which Jim was built. The following is an example of the contents of this array. tcl_platform(byteOrder) = littleEndian tcl_platform(os) = Darwin tcl_platform(platform) = unix tcl_platform(pointerSize) = 8 tcl_platform(threaded) = 0 tcl_platform(wordSize) = 8 tcl_platform(pathSeparator) = : +*argv0*+:: If jimsh is invoked to run a script, this variable contains the name of the script. +*argv*+:: If jimsh is invoked to run a script, this variable contains a list of any arguments supplied to the script. +*argc*+:: If jimsh is invoked to run a script, this variable contains the number of arguments supplied to the script. +*jim::argv0*+:: The value of argv[0] when jimsh was invoked. CHANGES IN PREVIOUS RELEASES ---------------------------- === In v0.70 === 1. +platform_tcl()+ settings are now automatically determined 2. Add aio `$handle filename` 3. Add `info channels` 4. The 'bio' extension is gone. Now `aio` supports 'copyto'. 5. Add `exists` command 6. Add the pure-Tcl 'oo' extension 7. The `exec` command now only uses vfork(), not fork() 8. Unit test framework is less verbose and more Tcl-compatible 9. Optional UTF-8 support 10. Optional built-in regexp engine for better Tcl compatibility and UTF-8 support 11. Command line editing in interactive mode, e.g. 'jimsh' === In v0.63 === 1. `source` now checks that a script is complete (.i.e. not missing a brace) 2. 'info complete' now uses the real parser and so is 100% accurate 3. Better access to live stack frames with 'info frame', `stacktrace` and `stackdump` 4. `tailcall` no longer loses stack trace information 5. Add `alias` and `curry` 6. `lambda`, `alias` and `curry` are implemented via `tailcall` for efficiency 7. `local` allows procedures to be deleted automatically at the end of the current procedure 8. udp sockets are now supported for both clients and servers. 9. vfork-based exec is now working correctly 10. Add 'file tempfile' 11. Add 'socket pipe' 12. Enhance 'try ... on ... finally' to be more Tcl 8.6 compatible 13. It is now possible to `return` from within `try` 14. IPv6 support is now included 15. Add 'string is' 16. Event handlers works better if an error occurs. eof handler has been removed. 17. `exec` now sets $::errorCode, and catch sets opts(-errorcode) for exit status 18. Command pipelines via open "|..." are now supported 19. `pid` can now return pids of a command pipeline 20. Add 'info references' 21. Add support for 'after +'ms'+', 'after idle', 'after info', `update` 22. `exec` now sets environment based on $::env 23. Add 'dict keys' 24. Add support for 'lsort -index' === In v0.62 === 1. Add support to `exec` for '>&', '>>&', '|&', '2>@1' 2. Fix `exec` error messages when special token (e.g. '>') is the last token 3. Fix `subst` handling of backslash escapes. 4. Allow abbreviated options for `subst` 5. Add support for `return`, `break`, `continue` in subst 6. Many `expr` bug fixes 7. Add support for functions in `expr` (e.g. int(), abs()), and also 'in', 'ni' list operations 8. The variable name argument to `regsub` is now optional 9. Add support for 'unset -nocomplain' 10. Add support for list commands: `lassign`, `lrepeat` 11. Fully-functional `lsearch` is now implemented 12. Add 'info nameofexecutable' and 'info returncodes' 13. Allow `catch` to determine what return codes are caught 14. Allow `incr` to increment an unset variable by first setting to 0 15. Allow 'args' and optional arguments to the left or required arguments in `proc` 16. Add 'file copy' 17. Add 'try ... finally' command LICENCE ------- Copyright 2005 Salvatore Sanfilippo Copyright 2005 Clemens Hintze Copyright 2005 patthoyts - Pat Thoyts Copyright 2008 oharboe - Oyvind Harboe - oyvind.harboe@zylin.com Copyright 2008 Andrew Lunn Copyright 2008 Duane Ellis Copyright 2008 Uwe Klein Copyright 2009 Steve Bennett [literal] 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. THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 JIM TCL PROJECT 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. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the Jim Tcl Project. openocd-0.9.0/jimtcl/linenoise.c0000644000175000017500000013204112516456444013517 00000000000000/* linenoise.c -- guerrilla line editing library against the idea that a * line editing lib needs to be 20,000 lines of C code. * * You can find the latest source code at: * * http://github.com/msteveb/linenoise * (forked from http://github.com/antirez/linenoise) * * Does a number of crazy assumptions that happen to be true in 99.9999% of * the 2010 UNIX computers around. * * ------------------------------------------------------------------------ * * Copyright (c) 2010, Salvatore Sanfilippo * Copyright (c) 2010, Pieter Noordhuis * Copyright (c) 2011, Steve Bennett * * 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. * * 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. * * ------------------------------------------------------------------------ * * References: * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html * * Bloat: * - Completion? * * Unix/termios * ------------ * List of escape sequences used by this program, we do everything just * a few sequences. In order to be so cheap we may have some * flickering effect with some slow terminal, but the lesser sequences * the more compatible. * * EL (Erase Line) * Sequence: ESC [ n K * Effect: if n is 0 or missing, clear from cursor to end of line * Effect: if n is 1, clear from beginning of line to cursor * Effect: if n is 2, clear entire line * * CUF (CUrsor Forward) * Sequence: ESC [ n C * Effect: moves cursor forward of n chars * * CR (Carriage Return) * Sequence: \r * Effect: moves cursor to column 1 * * The following are used to clear the screen: ESC [ H ESC [ 2 J * This is actually composed of two sequences: * * cursorhome * Sequence: ESC [ H * Effect: moves the cursor to upper left corner * * ED2 (Clear entire screen) * Sequence: ESC [ 2 J * Effect: clear the whole screen * * == For highlighting control characters, we also use the following two == * SO (enter StandOut) * Sequence: ESC [ 7 m * Effect: Uses some standout mode such as reverse video * * SE (Standout End) * Sequence: ESC [ 0 m * Effect: Exit standout mode * * == Only used if TIOCGWINSZ fails == * DSR/CPR (Report cursor position) * Sequence: ESC [ 6 n * Effect: reports current cursor position as ESC [ NNN ; MMM R * * win32/console * ------------- * If __MINGW32__ is defined, the win32 console API is used. * This could probably be made to work for the msvc compiler too. * This support based in part on work by Jon Griffiths. */ #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */ #include #include #define USE_WINCONSOLE #ifdef __MINGW32__ #define HAVE_UNISTD_H #else /* Microsoft headers don't like old POSIX names */ #define strdup _strdup #define snprintf _snprintf #endif #else #include #include #include #define USE_TERMIOS #define HAVE_UNISTD_H #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include "linenoise.h" #include "jim-config.h" #ifdef JIM_UTF8 #define USE_UTF8 #endif #include "utf8.h" #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 #define LINENOISE_MAX_LINE 4096 #define ctrl(C) ((C) - '@') /* Use -ve numbers here to co-exist with normal unicode chars */ enum { SPECIAL_NONE, SPECIAL_UP = -20, SPECIAL_DOWN = -21, SPECIAL_LEFT = -22, SPECIAL_RIGHT = -23, SPECIAL_DELETE = -24, SPECIAL_HOME = -25, SPECIAL_END = -26, SPECIAL_INSERT = -27, SPECIAL_PAGE_UP = -28, SPECIAL_PAGE_DOWN = -29 }; static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; static int history_len = 0; static char **history = NULL; /* Structure to contain the status of the current (being edited) line */ struct current { char *buf; /* Current buffer. Always null terminated */ int bufmax; /* Size of the buffer, including space for the null termination */ int len; /* Number of bytes in 'buf' */ int chars; /* Number of chars in 'buf' (utf-8 chars) */ int pos; /* Cursor position, measured in chars */ int cols; /* Size of the window, in chars */ const char *prompt; char *capture; /* Allocated capture buffer, or NULL for none. Always null terminated */ #if defined(USE_TERMIOS) int fd; /* Terminal fd */ #elif defined(USE_WINCONSOLE) HANDLE outh; /* Console output handle */ HANDLE inh; /* Console input handle */ int rows; /* Screen rows */ int x; /* Current column during output */ int y; /* Current row */ #endif }; static int fd_read(struct current *current); static int getWindowSize(struct current *current); void linenoiseHistoryFree(void) { if (history) { int j; for (j = 0; j < history_len; j++) free(history[j]); free(history); history = NULL; history_len = 0; } } #if defined(USE_TERMIOS) static void linenoiseAtExit(void); static struct termios orig_termios; /* in order to restore at exit */ static int rawmode = 0; /* for atexit() function to check if restore is needed*/ static int atexit_registered = 0; /* register atexit just 1 time */ static const char *unsupported_term[] = {"dumb","cons25",NULL}; static int isUnsupportedTerm(void) { char *term = getenv("TERM"); if (term) { int j; for (j = 0; unsupported_term[j]; j++) { if (strcmp(term, unsupported_term[j]) == 0) { return 1; } } } return 0; } static int enableRawMode(struct current *current) { struct termios raw; current->fd = STDIN_FILENO; if (!isatty(current->fd) || isUnsupportedTerm() || tcgetattr(current->fd, &orig_termios) == -1) { fatal: errno = ENOTTY; return -1; } if (!atexit_registered) { atexit(linenoiseAtExit); atexit_registered = 1; } raw = orig_termios; /* modify the original mode */ /* input modes: no break, no CR to NL, no parity check, no strip char, * no start/stop output control. */ raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); /* output modes - disable post processing */ raw.c_oflag &= ~(OPOST); /* control modes - set 8 bit chars */ raw.c_cflag |= (CS8); /* local modes - choing off, canonical off, no extended functions, * no signal chars (^Z,^C) */ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); /* control chars - set return condition: min number of bytes and timer. * We want read to return every single byte, without timeout. */ raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ /* put terminal in raw mode after flushing */ if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) { goto fatal; } rawmode = 1; current->cols = 0; return 0; } static void disableRawMode(struct current *current) { /* Don't even check the return value as it's too late. */ if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1) rawmode = 0; } /* At exit we'll try to fix the terminal to the initial conditions. */ static void linenoiseAtExit(void) { if (rawmode) { tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios); } linenoiseHistoryFree(); } /* gcc/glibc insists that we care about the return code of write! * Clarification: This means that a void-cast like "(void) (EXPR)" * does not work. */ #define IGNORE_RC(EXPR) if (EXPR) {} /* This is fdprintf() on some systems, but use a different * name to avoid conflicts */ static void fd_printf(int fd, const char *format, ...) { va_list args; char buf[64]; int n; va_start(args, format); n = vsnprintf(buf, sizeof(buf), format, args); va_end(args); IGNORE_RC(write(fd, buf, n)); } static void clearScreen(struct current *current) { fd_printf(current->fd, "\x1b[H\x1b[2J"); } static void cursorToLeft(struct current *current) { fd_printf(current->fd, "\r"); } static int outputChars(struct current *current, const char *buf, int len) { return write(current->fd, buf, len); } static void outputControlChar(struct current *current, char ch) { fd_printf(current->fd, "\x1b[7m^%c\x1b[0m", ch); } static void eraseEol(struct current *current) { fd_printf(current->fd, "\x1b[0K"); } static void setCursorPos(struct current *current, int x) { fd_printf(current->fd, "\r\x1b[%dC", x); } /** * Reads a char from 'fd', waiting at most 'timeout' milliseconds. * * A timeout of -1 means to wait forever. * * Returns -1 if no char is received within the time or an error occurs. */ static int fd_read_char(int fd, int timeout) { struct pollfd p; unsigned char c; p.fd = fd; p.events = POLLIN; if (poll(&p, 1, timeout) == 0) { /* timeout */ return -1; } if (read(fd, &c, 1) != 1) { return -1; } return c; } /** * Reads a complete utf-8 character * and returns the unicode value, or -1 on error. */ static int fd_read(struct current *current) { #ifdef USE_UTF8 char buf[4]; int n; int i; int c; if (read(current->fd, &buf[0], 1) != 1) { return -1; } n = utf8_charlen(buf[0]); if (n < 1 || n > 3) { return -1; } for (i = 1; i < n; i++) { if (read(current->fd, &buf[i], 1) != 1) { return -1; } } buf[n] = 0; /* decode and return the character */ utf8_tounicode(buf, &c); return c; #else return fd_read_char(current->fd, -1); #endif } static int countColorControlChars(const char* prompt) { /* ANSI color control sequences have the form: * "\x1b" "[" [0-9;]* "m" * We parse them with a simple state machine. */ enum { search_esc, expect_bracket, expect_trail } state = search_esc; int len = 0, found = 0; char ch; /* XXX: Strictly we should be checking utf8 chars rather than * bytes in case of the extremely unlikely scenario where * an ANSI sequence is part of a utf8 sequence. */ while ((ch = *prompt++) != 0) { switch (state) { case search_esc: if (ch == '\x1b') { state = expect_bracket; } break; case expect_bracket: if (ch == '[') { state = expect_trail; /* 3 for "\e[ ... m" */ len = 3; break; } state = search_esc; break; case expect_trail: if ((ch == ';') || ((ch >= '0' && ch <= '9'))) { /* 0-9, or semicolon */ len++; break; } if (ch == 'm') { found += len; } state = search_esc; break; } } return found; } static int getWindowSize(struct current *current) { struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) { current->cols = ws.ws_col; return 0; } /* Failed to query the window size. Perhaps we are on a serial terminal. * Try to query the width by sending the cursor as far to the right * and reading back the cursor position. * Note that this is only done once per call to linenoise rather than * every time the line is refreshed for efficiency reasons. */ if (current->cols == 0) { current->cols = 80; /* Move cursor far right and report cursor position, then back to the left */ fd_printf(current->fd, "\x1b[999C" "\x1b[6n"); /* Parse the response: ESC [ rows ; cols R */ if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') { int n = 0; while (1) { int ch = fd_read_char(current->fd, 100); if (ch == ';') { /* Ignore rows */ n = 0; } else if (ch == 'R') { /* Got cols */ if (n != 0 && n < 1000) { current->cols = n; } break; } else if (ch >= 0 && ch <= '9') { n = n * 10 + ch - '0'; } else { break; } } } } return 0; } /** * If escape (27) was received, reads subsequent * chars to determine if this is a known special key. * * Returns SPECIAL_NONE if unrecognised, or -1 if EOF. * * If no additional char is received within a short time, * 27 is returned. */ static int check_special(int fd) { int c = fd_read_char(fd, 50); int c2; if (c < 0) { return 27; } c2 = fd_read_char(fd, 50); if (c2 < 0) { return c2; } if (c == '[' || c == 'O') { /* Potential arrow key */ switch (c2) { case 'A': return SPECIAL_UP; case 'B': return SPECIAL_DOWN; case 'C': return SPECIAL_RIGHT; case 'D': return SPECIAL_LEFT; case 'F': return SPECIAL_END; case 'H': return SPECIAL_HOME; } } if (c == '[' && c2 >= '1' && c2 <= '8') { /* extended escape */ c = fd_read_char(fd, 50); if (c == '~') { switch (c2) { case '2': return SPECIAL_INSERT; case '3': return SPECIAL_DELETE; case '5': return SPECIAL_PAGE_UP; case '6': return SPECIAL_PAGE_DOWN; case '7': return SPECIAL_HOME; case '8': return SPECIAL_END; } } while (c != -1 && c != '~') { /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */ c = fd_read_char(fd, 50); } } return SPECIAL_NONE; } #elif defined(USE_WINCONSOLE) static DWORD orig_consolemode = 0; static int enableRawMode(struct current *current) { DWORD n; INPUT_RECORD irec; current->outh = GetStdHandle(STD_OUTPUT_HANDLE); current->inh = GetStdHandle(STD_INPUT_HANDLE); if (!PeekConsoleInput(current->inh, &irec, 1, &n)) { return -1; } if (getWindowSize(current) != 0) { return -1; } if (GetConsoleMode(current->inh, &orig_consolemode)) { SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT); } return 0; } static void disableRawMode(struct current *current) { SetConsoleMode(current->inh, orig_consolemode); } static void clearScreen(struct current *current) { COORD topleft = { 0, 0 }; DWORD n; FillConsoleOutputCharacter(current->outh, ' ', current->cols * current->rows, topleft, &n); FillConsoleOutputAttribute(current->outh, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols * current->rows, topleft, &n); SetConsoleCursorPosition(current->outh, topleft); } static void cursorToLeft(struct current *current) { COORD pos = { 0, (SHORT)current->y }; DWORD n; FillConsoleOutputAttribute(current->outh, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n); current->x = 0; } static int outputChars(struct current *current, const char *buf, int len) { COORD pos = { (SHORT)current->x, (SHORT)current->y }; DWORD n; WriteConsoleOutputCharacter(current->outh, buf, len, pos, &n); current->x += len; return 0; } static void outputControlChar(struct current *current, char ch) { COORD pos = { (SHORT)current->x, (SHORT)current->y }; DWORD n; FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n); outputChars(current, "^", 1); outputChars(current, &ch, 1); } static void eraseEol(struct current *current) { COORD pos = { (SHORT)current->x, (SHORT)current->y }; DWORD n; FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n); } static void setCursorPos(struct current *current, int x) { COORD pos = { (SHORT)x, (SHORT)current->y }; SetConsoleCursorPosition(current->outh, pos); current->x = x; } static int fd_read(struct current *current) { while (1) { INPUT_RECORD irec; DWORD n; if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) { break; } if (!ReadConsoleInput (current->inh, &irec, 1, &n)) { break; } if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown) { KEY_EVENT_RECORD *k = &irec.Event.KeyEvent; if (k->dwControlKeyState & ENHANCED_KEY) { switch (k->wVirtualKeyCode) { case VK_LEFT: return SPECIAL_LEFT; case VK_RIGHT: return SPECIAL_RIGHT; case VK_UP: return SPECIAL_UP; case VK_DOWN: return SPECIAL_DOWN; case VK_INSERT: return SPECIAL_INSERT; case VK_DELETE: return SPECIAL_DELETE; case VK_HOME: return SPECIAL_HOME; case VK_END: return SPECIAL_END; case VK_PRIOR: return SPECIAL_PAGE_UP; case VK_NEXT: return SPECIAL_PAGE_DOWN; } } /* Note that control characters are already translated in AsciiChar */ else { #ifdef USE_UTF8 return k->uChar.UnicodeChar; #else return k->uChar.AsciiChar; #endif } } } return -1; } static int countColorControlChars(const char* prompt) { /* For windows we assume that there are no embedded ansi color * control sequences. */ return 0; } static int getWindowSize(struct current *current) { CONSOLE_SCREEN_BUFFER_INFO info; if (!GetConsoleScreenBufferInfo(current->outh, &info)) { return -1; } current->cols = info.dwSize.X; current->rows = info.dwSize.Y; if (current->cols <= 0 || current->rows <= 0) { current->cols = 80; return -1; } current->y = info.dwCursorPosition.Y; current->x = info.dwCursorPosition.X; return 0; } #endif /** * Returns the unicode character at the given offset, * or -1 if none. */ static int get_char(struct current *current, int pos) { if (pos >= 0 && pos < current->chars) { int c; int i = utf8_index(current->buf, pos); (void)utf8_tounicode(current->buf + i, &c); return c; } return -1; } static void refreshLine(const char *prompt, struct current *current) { int plen; int pchars; int backup = 0; int i; const char *buf = current->buf; int chars = current->chars; int pos = current->pos; int b; int ch; int n; /* Should intercept SIGWINCH. For now, just get the size every time */ getWindowSize(current); plen = strlen(prompt); pchars = utf8_strlen(prompt, plen); /* Scan the prompt for embedded ansi color control sequences and * discount them as characters/columns. */ pchars -= countColorControlChars(prompt); /* Account for a line which is too long to fit in the window. * Note that control chars require an extra column */ /* How many cols are required to the left of 'pos'? * The prompt, plus one extra for each control char */ n = pchars + utf8_strlen(buf, current->len); b = 0; for (i = 0; i < pos; i++) { b += utf8_tounicode(buf + b, &ch); if (ch < ' ') { n++; } } /* If too many are needed, strip chars off the front of 'buf' * until it fits. Note that if the current char is a control character, * we need one extra col. */ if (current->pos < current->chars && get_char(current, current->pos) < ' ') { n++; } while (n >= current->cols && pos > 0) { b = utf8_tounicode(buf, &ch); if (ch < ' ') { n--; } n--; buf += b; pos--; chars--; } /* Cursor to left edge, then the prompt */ cursorToLeft(current); outputChars(current, prompt, plen); /* Now the current buffer content */ /* Need special handling for control characters. * If we hit 'cols', stop. */ b = 0; /* unwritted bytes */ n = 0; /* How many control chars were written */ for (i = 0; i < chars; i++) { int ch; int w = utf8_tounicode(buf + b, &ch); if (ch < ' ') { n++; } if (pchars + i + n >= current->cols) { break; } if (ch < ' ') { /* A control character, so write the buffer so far */ outputChars(current, buf, b); buf += b + w; b = 0; outputControlChar(current, ch + '@'); if (i < pos) { backup++; } } else { b += w; } } outputChars(current, buf, b); /* Erase to right, move cursor to original position */ eraseEol(current); setCursorPos(current, pos + pchars + backup); } static void set_current(struct current *current, const char *str) { strncpy(current->buf, str, current->bufmax); current->buf[current->bufmax - 1] = 0; current->len = strlen(current->buf); current->pos = current->chars = utf8_strlen(current->buf, current->len); } static int has_room(struct current *current, int bytes) { return current->len + bytes < current->bufmax - 1; } /** * Removes the char at 'pos'. * * Returns 1 if the line needs to be refreshed, 2 if not * and 0 if nothing was removed */ static int remove_char(struct current *current, int pos) { if (pos >= 0 && pos < current->chars) { int p1, p2; int ret = 1; p1 = utf8_index(current->buf, pos); p2 = p1 + utf8_index(current->buf + p1, 1); #ifdef USE_TERMIOS /* optimise remove char in the case of removing the last char */ if (current->pos == pos + 1 && current->pos == current->chars) { if (current->buf[pos] >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { ret = 2; fd_printf(current->fd, "\b \b"); } } #endif /* Move the null char too */ memmove(current->buf + p1, current->buf + p2, current->len - p2 + 1); current->len -= (p2 - p1); current->chars--; if (current->pos > pos) { current->pos--; } return ret; } return 0; } /** * Insert 'ch' at position 'pos' * * Returns 1 if the line needs to be refreshed, 2 if not * and 0 if nothing was inserted (no room) */ static int insert_char(struct current *current, int pos, int ch) { char buf[3]; int n = utf8_getchars(buf, ch); if (has_room(current, n) && pos >= 0 && pos <= current->chars) { int p1, p2; int ret = 1; p1 = utf8_index(current->buf, pos); p2 = p1 + n; #ifdef USE_TERMIOS /* optimise the case where adding a single char to the end and no scrolling is needed */ if (current->pos == pos && current->chars == pos) { if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { IGNORE_RC(write(current->fd, buf, n)); ret = 2; } } #endif memmove(current->buf + p2, current->buf + p1, current->len - p1); memcpy(current->buf + p1, buf, n); current->len += n; current->chars++; if (current->pos >= pos) { current->pos++; } return ret; } return 0; } /** * Captures up to 'n' characters starting at 'pos' for the cut buffer. * * This replaces any existing characters in the cut buffer. */ static void capture_chars(struct current *current, int pos, int n) { if (pos >= 0 && (pos + n - 1) < current->chars) { int p1 = utf8_index(current->buf, pos); int nbytes = utf8_index(current->buf + p1, n); if (nbytes) { free(current->capture); /* Include space for the null terminator */ current->capture = (char *)malloc(nbytes + 1); memcpy(current->capture, current->buf + p1, nbytes); current->capture[nbytes] = '\0'; } } } /** * Removes up to 'n' characters at cursor position 'pos'. * * Returns 0 if no chars were removed or non-zero otherwise. */ static int remove_chars(struct current *current, int pos, int n) { int removed = 0; /* First save any chars which will be removed */ capture_chars(current, pos, n); while (n-- && remove_char(current, pos)) { removed++; } return removed; } /** * Inserts the characters (string) 'chars' at the cursor position 'pos'. * * Returns 0 if no chars were inserted or non-zero otherwise. */ static int insert_chars(struct current *current, int pos, const char *chars) { int inserted = 0; while (*chars) { int ch; int n = utf8_tounicode(chars, &ch); if (insert_char(current, pos, ch) == 0) { break; } inserted++; pos++; chars += n; } return inserted; } #ifndef NO_COMPLETION static linenoiseCompletionCallback *completionCallback = NULL; static void beep() { #ifdef USE_TERMIOS fprintf(stderr, "\x7"); fflush(stderr); #endif } static void freeCompletions(linenoiseCompletions *lc) { size_t i; for (i = 0; i < lc->len; i++) free(lc->cvec[i]); free(lc->cvec); } static int completeLine(struct current *current) { linenoiseCompletions lc = { 0, NULL }; int c = 0; completionCallback(current->buf,&lc); if (lc.len == 0) { beep(); } else { size_t stop = 0, i = 0; while(!stop) { /* Show completion or original buffer */ if (i < lc.len) { struct current tmp = *current; tmp.buf = lc.cvec[i]; tmp.pos = tmp.len = strlen(tmp.buf); tmp.chars = utf8_strlen(tmp.buf, tmp.len); refreshLine(current->prompt, &tmp); } else { refreshLine(current->prompt, current); } c = fd_read(current); if (c == -1) { break; } switch(c) { case '\t': /* tab */ i = (i+1) % (lc.len+1); if (i == lc.len) beep(); break; case 27: /* escape */ /* Re-show original buffer */ if (i < lc.len) { refreshLine(current->prompt, current); } stop = 1; break; default: /* Update buffer and return */ if (i < lc.len) { set_current(current,lc.cvec[i]); } stop = 1; break; } } } freeCompletions(&lc); return c; /* Return last read character */ } /* Register a callback function to be called for tab-completion. */ void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { completionCallback = fn; } void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1)); lc->cvec[lc->len++] = strdup(str); } #endif static int linenoiseEdit(struct current *current) { int history_index = 0; /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); set_current(current, ""); refreshLine(current->prompt, current); while(1) { int dir = -1; int c = fd_read(current); #ifndef NO_COMPLETION /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if (c == '\t' && current->pos == current->chars && completionCallback != NULL) { c = completeLine(current); /* Return on errors */ if (c < 0) return current->len; /* Read next character when 0 */ if (c == 0) continue; } #endif process_char: if (c == -1) return current->len; #ifdef USE_TERMIOS if (c == 27) { /* escape sequence */ c = check_special(current->fd); } #endif switch(c) { case '\r': /* enter */ history_len--; free(history[history_len]); return current->len; case ctrl('C'): /* ctrl-c */ errno = EAGAIN; return -1; case 127: /* backspace */ case ctrl('H'): if (remove_char(current, current->pos - 1) == 1) { refreshLine(current->prompt, current); } break; case ctrl('D'): /* ctrl-d */ if (current->len == 0) { /* Empty line, so EOF */ history_len--; free(history[history_len]); return -1; } /* Otherwise fall through to delete char to right of cursor */ case SPECIAL_DELETE: if (remove_char(current, current->pos) == 1) { refreshLine(current->prompt, current); } break; case SPECIAL_INSERT: /* Ignore. Expansion Hook. * Future possibility: Toggle Insert/Overwrite Modes */ break; case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */ /* eat any spaces on the left */ { int pos = current->pos; while (pos > 0 && get_char(current, pos - 1) == ' ') { pos--; } /* now eat any non-spaces on the left */ while (pos > 0 && get_char(current, pos - 1) != ' ') { pos--; } if (remove_chars(current, pos, current->pos - pos)) { refreshLine(current->prompt, current); } } break; case ctrl('R'): /* ctrl-r */ { /* Display the reverse-i-search prompt and process chars */ char rbuf[50]; char rprompt[80]; int rchars = 0; int rlen = 0; int searchpos = history_len - 1; rbuf[0] = 0; while (1) { int n = 0; const char *p = NULL; int skipsame = 0; int searchdir = -1; snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf); refreshLine(rprompt, current); c = fd_read(current); if (c == ctrl('H') || c == 127) { if (rchars) { int p = utf8_index(rbuf, --rchars); rbuf[p] = 0; rlen = strlen(rbuf); } continue; } #ifdef USE_TERMIOS if (c == 27) { c = check_special(current->fd); } #endif if (c == ctrl('P') || c == SPECIAL_UP) { /* Search for the previous (earlier) match */ if (searchpos > 0) { searchpos--; } skipsame = 1; } else if (c == ctrl('N') || c == SPECIAL_DOWN) { /* Search for the next (later) match */ if (searchpos < history_len) { searchpos++; } searchdir = 1; skipsame = 1; } else if (c >= ' ') { if (rlen >= (int)sizeof(rbuf) + 3) { continue; } n = utf8_getchars(rbuf + rlen, c); rlen += n; rchars++; rbuf[rlen] = 0; /* Adding a new char resets the search location */ searchpos = history_len - 1; } else { /* Exit from incremental search mode */ break; } /* Now search through the history for a match */ for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) { p = strstr(history[searchpos], rbuf); if (p) { /* Found a match */ if (skipsame && strcmp(history[searchpos], current->buf) == 0) { /* But it is identical, so skip it */ continue; } /* Copy the matching line and set the cursor position */ set_current(current,history[searchpos]); current->pos = utf8_strlen(history[searchpos], p - history[searchpos]); break; } } if (!p && n) { /* No match, so don't add it */ rchars--; rlen -= n; rbuf[rlen] = 0; } } if (c == ctrl('G') || c == ctrl('C')) { /* ctrl-g terminates the search with no effect */ set_current(current, ""); c = 0; } else if (c == ctrl('J')) { /* ctrl-j terminates the search leaving the buffer in place */ c = 0; } /* Go process the char normally */ refreshLine(current->prompt, current); goto process_char; } break; case ctrl('T'): /* ctrl-t */ if (current->pos > 0 && current->pos <= current->chars) { /* If cursor is at end, transpose the previous two chars */ int fixer = (current->pos == current->chars); c = get_char(current, current->pos - fixer); remove_char(current, current->pos - fixer); insert_char(current, current->pos - 1, c); refreshLine(current->prompt, current); } break; case ctrl('V'): /* ctrl-v */ if (has_room(current, 3)) { /* Insert the ^V first */ if (insert_char(current, current->pos, c)) { refreshLine(current->prompt, current); /* Now wait for the next char. Can insert anything except \0 */ c = fd_read(current); /* Remove the ^V first */ remove_char(current, current->pos - 1); if (c != -1) { /* Insert the actual char */ insert_char(current, current->pos, c); } refreshLine(current->prompt, current); } } break; case ctrl('B'): case SPECIAL_LEFT: if (current->pos > 0) { current->pos--; refreshLine(current->prompt, current); } break; case ctrl('F'): case SPECIAL_RIGHT: if (current->pos < current->chars) { current->pos++; refreshLine(current->prompt, current); } break; case SPECIAL_PAGE_UP: dir = history_len - history_index - 1; /* move to start of history */ goto history_navigation; case SPECIAL_PAGE_DOWN: dir = -history_index; /* move to 0 == end of history, i.e. current */ goto history_navigation; case ctrl('P'): case SPECIAL_UP: dir = 1; goto history_navigation; case ctrl('N'): case SPECIAL_DOWN: history_navigation: if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(history[history_len - 1 - history_index]); history[history_len - 1 - history_index] = strdup(current->buf); /* Show the new entry */ history_index += dir; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { history_index = history_len - 1; break; } set_current(current, history[history_len - 1 - history_index]); refreshLine(current->prompt, current); } break; case ctrl('A'): /* Ctrl+a, go to the start of the line */ case SPECIAL_HOME: current->pos = 0; refreshLine(current->prompt, current); break; case ctrl('E'): /* ctrl+e, go to the end of the line */ case SPECIAL_END: current->pos = current->chars; refreshLine(current->prompt, current); break; case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */ if (remove_chars(current, 0, current->pos)) { refreshLine(current->prompt, current); } break; case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */ if (remove_chars(current, current->pos, current->chars - current->pos)) { refreshLine(current->prompt, current); } break; case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */ if (current->capture && insert_chars(current, current->pos, current->capture)) { refreshLine(current->prompt, current); } break; case ctrl('L'): /* Ctrl+L, clear screen */ clearScreen(current); /* Force recalc of window size for serial terminals */ current->cols = 0; refreshLine(current->prompt, current); break; default: /* Only tab is allowed without ^V */ if (c == '\t' || c >= ' ') { if (insert_char(current, current->pos, c) == 1) { refreshLine(current->prompt, current); } } break; } } return current->len; } int linenoiseColumns(void) { struct current current; enableRawMode (¤t); getWindowSize (¤t); disableRawMode (¤t); return current.cols; } char *linenoise(const char *prompt) { int count; struct current current; char buf[LINENOISE_MAX_LINE]; if (enableRawMode(¤t) == -1) { printf("%s", prompt); fflush(stdout); if (fgets(buf, sizeof(buf), stdin) == NULL) { return NULL; } count = strlen(buf); if (count && buf[count-1] == '\n') { count--; buf[count] = '\0'; } } else { current.buf = buf; current.bufmax = sizeof(buf); current.len = 0; current.chars = 0; current.pos = 0; current.prompt = prompt; current.capture = NULL; count = linenoiseEdit(¤t); disableRawMode(¤t); printf("\n"); free(current.capture); if (count == -1) { return NULL; } } return strdup(buf); } /* Using a circular buffer is smarter, but a bit more complex to handle. */ int linenoiseHistoryAdd(const char *line) { char *linecopy; if (history_max_len == 0) return 0; if (history == NULL) { history = (char **)malloc(sizeof(char*)*history_max_len); if (history == NULL) return 0; memset(history,0,(sizeof(char*)*history_max_len)); } /* do not insert duplicate lines into history */ if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) { return 0; } linecopy = strdup(line); if (!linecopy) return 0; if (history_len == history_max_len) { free(history[0]); memmove(history,history+1,sizeof(char*)*(history_max_len-1)); history_len--; } history[history_len] = linecopy; history_len++; return 1; } int linenoiseHistoryGetMaxLen(void) { return history_max_len; } int linenoiseHistorySetMaxLen(int len) { char **newHistory; if (len < 1) return 0; if (history) { int tocopy = history_len; newHistory = (char **)malloc(sizeof(char*)*len); if (newHistory == NULL) return 0; /* If we can't copy everything, free the elements we'll not use. */ if (len < tocopy) { int j; for (j = 0; j < tocopy-len; j++) free(history[j]); tocopy = len; } memset(newHistory,0,sizeof(char*)*len); memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy); free(history); history = newHistory; } history_max_len = len; if (history_len > history_max_len) history_len = history_max_len; return 1; } /* Save the history in the specified file. On success 0 is returned * otherwise -1 is returned. */ int linenoiseHistorySave(const char *filename) { FILE *fp = fopen(filename,"w"); int j; if (fp == NULL) return -1; for (j = 0; j < history_len; j++) { const char *str = history[j]; /* Need to encode backslash, nl and cr */ while (*str) { if (*str == '\\') { fputs("\\\\", fp); } else if (*str == '\n') { fputs("\\n", fp); } else if (*str == '\r') { fputs("\\r", fp); } else { fputc(*str, fp); } str++; } fputc('\n', fp); } fclose(fp); return 0; } /* Load the history from the specified file. If the file does not exist * zero is returned and no operation is performed. * * If the file exists and the operation succeeded 0 is returned, otherwise * on error -1 is returned. */ int linenoiseHistoryLoad(const char *filename) { FILE *fp = fopen(filename,"r"); char buf[LINENOISE_MAX_LINE]; if (fp == NULL) return -1; while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { char *src, *dest; /* Decode backslash escaped values */ for (src = dest = buf; *src; src++) { char ch = *src; if (ch == '\\') { src++; if (*src == 'n') { ch = '\n'; } else if (*src == 'r') { ch = '\r'; } else { ch = *src; } } *dest++ = ch; } /* Remove trailing newline */ if (dest != buf && (dest[-1] == '\n' || dest[-1] == '\r')) { dest--; } *dest = 0; linenoiseHistoryAdd(buf); } fclose(fp); return 0; } /* Provide access to the history buffer. * * If 'len' is not NULL, the length is stored in *len. */ char **linenoiseHistory(int *len) { if (len) { *len = history_len; } return history; } openocd-0.9.0/jimtcl/linenoise.h0000644000175000017500000000501012516456444013517 00000000000000/* linenoise.h -- guerrilla line editing library against the idea that a * line editing lib needs to be 20,000 lines of C code. * * See linenoise.c for more information. * * ------------------------------------------------------------------------ * * Copyright (c) 2010, Salvatore Sanfilippo * Copyright (c) 2010, Pieter Noordhuis * * 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. * * 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 __LINENOISE_H #define __LINENOISE_H /* Currently never enable completion */ #define NO_COMPLETION #ifndef NO_COMPLETION typedef struct linenoiseCompletions { size_t len; char **cvec; } linenoiseCompletions; typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); void linenoiseAddCompletion(linenoiseCompletions *, const char *); #endif char *linenoise(const char *prompt); int linenoiseHistoryAdd(const char *line); int linenoiseHistorySetMaxLen(int len); int linenoiseHistoryGetMaxLen(void); int linenoiseHistorySave(const char *filename); int linenoiseHistoryLoad(const char *filename); void linenoiseHistoryFree(void); char **linenoiseHistory(int *len); int linenoiseColumns(void); #endif /* __LINENOISE_H */ openocd-0.9.0/jimtcl/tree.tcl0000644000175000017500000001126512315602575013030 00000000000000# Conceptually compatible with tcllib ::struct::tree # but uses an object based interface. # To mimic tcllib, do: # rename [tree] mytree package require oo # set pt [tree] # # Create a tree # This automatically creates a node named "root" # # $pt destroy # # Destroy the tree and all it's nodes # # $pt set # # Set the value for the given key # # $pt lappend ... # # Append to the (list) value(s) for the given key, or set if not yet set # # $pt keyexists # # Returns 1 if the given key exists # # $pt get # # Returns the value associated with the given key # # $pt getall # # Returns the entire attribute dictionary associated with the given key # # $pt depth # # Returns the depth of the given node. The depth of "root" is 0. # # $pt parent # # Returns the name of the parent node, or "" for the root node. # # $pt numchildren # # Returns the number of child nodes. # # $pt children # # Returns a list of the child nodes. # # $pt next # # Returns the next sibling node, or "" if none. # # $pt insert ?index? # # Add a new child node to the given node. # THe default index is "end" # Returns the name of the newly added node # # $pt walk dfs|bfs {actionvar nodevar} # # Walks the tree starting from the given node, either breadth first (bfs) # depth first (dfs). # The value "enter" or "exit" is stored in variable $actionvar # The name of each node is stored in $nodevar. # The script $code is evaluated twice for each node, on entry and exit. # # $pt dump # # Dumps the tree contents to stdout #------------------------------------------ # Internal implementation. # The tree class has 4 instance variables. # - tree is a dictionary. key=node, value=node value dictionary # - parent is a dictionary. key=node, value=parent of this node # - children is a dictionary. key=node, value=list of child nodes for this node # - nodeid is an integer which increments to give each node a unique id # Construct a tree with a single root node with no parent and no children class tree { tree {root {}} parents {root {}} children {root {}} nodeid 0 } # Simply walk up the tree to get the depth tree method depth {node} { set depth 0 while {$node ne "root"} { incr depth set node [dict get $parents $node] } return $depth } tree method parent {node} { dict get $parents $node } tree method children {node} { dict get $children $node } tree method numchildren {node} { llength [dict get $children $node] } tree method next {node} { # My siblings are my parents children set siblings [dict get $children [dict get $parents $node]] # Find me set i [lsearch $siblings $node] incr i lindex $siblings $i } tree method set {node key value} { dict set tree $node $key $value return $value } tree method get {node key} { dict get $tree $node $key } tree method keyexists {node key} { dict exists $tree $node $key } tree method getall {node} { dict get $tree $node } tree method insert {node {index end}} { # Make a new node and add it to the tree set childname node[incr nodeid] dict set tree $childname {} # The new node has no children dict set children $childname {} # Set the parent dict set parents $childname $node # And add it as a child set nodes [dict get $children $node] dict set children $node [linsert $nodes $index $childname] return $childname } tree method lappend {node key args} { if {[dict exists $tree $node $key]} { set result [dict get $tree $node $key] } lappend result {*}$args dict set tree $node $key $result return $result } # $tree walk node bfs|dfs {action loopvar} # tree method walk {node type vars code} { # set up vars lassign $vars actionvar namevar set n $node if {$type ne "child"} { upvar 2 $namevar name $actionvar action # Enter this node set name $node set action enter uplevel 2 $code } if {$type eq "dfs"} { # Depth-first so do the children foreach child [$self children $n] { uplevel 2 [list $self walk $child $type $vars $code] } } elseif {$type ne "none"} { # Breadth-first so do the children to one level only foreach child [$self children $n] { uplevel 2 [list $self walk $child none $vars $code] } # Now our grandchildren foreach child [$self children $n] { uplevel 2 [list $self walk $child child $vars $code] } } if {$type ne "child"} { # Exit this node set name $node set action exit uplevel 2 $code } } tree method dump {} { $self walk root dfs {action n} { set indent [string repeat " " [$self depth $n]] if {$action eq "enter"} { puts "$indent$n ([$self getall $n])" } } puts "" } openocd-0.9.0/jimtcl/tclcompat.tcl0000644000175000017500000001301412516456444014056 00000000000000# Loads some Tcl-compatible features. # I/O commands, case, lassign, parray, errorInfo, ::tcl_platform, ::env # try, throw, file copy, file delete -force # # (c) 2008 Steve Bennett # Set up the ::env array set env [env] # Provide Tcl-compatible I/O commands if {[info commands stdout] ne ""} { # Tcl-compatible I/O commands foreach p {gets flush close eof seek tell} { proc $p {chan args} {p} { tailcall $chan $p {*}$args } } unset p # puts is complicated by -nonewline # proc puts {{-nonewline {}} {chan stdout} msg} { if {${-nonewline} ni {-nonewline {}}} { tailcall ${-nonewline} puts $msg } tailcall $chan puts {*}${-nonewline} $msg } # read is complicated by -nonewline # # read chan ?maxchars? # read -nonewline chan proc read {{-nonewline {}} chan} { if {${-nonewline} ni {-nonewline {}}} { tailcall ${-nonewline} read {*}${chan} } tailcall $chan read {*}${-nonewline} } proc fconfigure {f args} { foreach {n v} $args { switch -glob -- $n { -bl* { $f ndelay $(!$v) } -bu* { $f buffering $v } -tr* { # Just ignore -translation } default { return -code error "fconfigure: unknown option $n" } } } } } # fileevent isn't needed in Jim, but provide it for compatibility proc fileevent {args} { tailcall {*}$args } # Second, option argument is a glob pattern # Third, optional argument is a "putter" function # proc parray {arrayname {pattern *} {puts puts}} { upvar $arrayname a set max 0 foreach name [array names a $pattern]] { if {[string length $name] > $max} { set max [string length $name] } } incr max [string length $arrayname] incr max 2 foreach name [lsort [array names a $pattern]] { $puts [format "%-${max}s = %s" $arrayname\($name\) $a($name)] } } # Implements 'file copy' - single file mode only proc {file copy} {{force {}} source target} { try { if {$force ni {{} -force}} { error "bad option \"$force\": should be -force" } set in [open $source rb] if {[file exists $target]} { if {$force eq ""} { error "error copying \"$source\" to \"$target\": file already exists" } # If source and target are the same, nothing to do if {$source eq $target} { return } # Hard linked, or case-insensitive filesystem # Note: mingw returns ino=0 for every file :-( file stat $source ss file stat $target ts if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} { return } } set out [open $target wb] $in copyto $out $out close } on error {msg opts} { incr opts(-level) return {*}$opts $msg } finally { catch {$in close} } } # 'open "|..." ?mode?" will invoke this wrapper around exec/pipe # Note that we return a lambda which also provides the 'pid' command proc popen {cmd {mode r}} { lassign [socket pipe] r w try { if {[string match "w*" $mode]} { lappend cmd <@$r & set pids [exec {*}$cmd] $r close set f $w } else { lappend cmd >@$w & set pids [exec {*}$cmd] $w close set f $r } lambda {cmd args} {f pids} { if {$cmd eq "pid"} { return $pids } if {$cmd eq "close"} { $f close # And wait for the child processes to complete foreach p $pids { os.wait $p } return } tailcall $f $cmd {*}$args } } on error {error opts} { $r close $w close error $error } } # A wrapper around 'pid' which can return the pids for 'popen' local proc pid {{channelId {}}} { if {$channelId eq ""} { tailcall upcall pid } if {[catch {$channelId tell}]} { return -code error "can not find channel named \"$channelId\"" } if {[catch {$channelId pid} pids]} { return "" } return $pids } # try/on/finally conceptually similar to Tcl 8.6 # # Usage: try ?catchopts? script ?onclause ...? ?finallyclause? # # Where: # onclause is: on codes {?resultvar? ?optsvar?} script # # codes is: a list of return codes (ok, error, etc. or integers), or * for any # # finallyclause is: finally script # # # Where onclause is: on codes {?resultvar? ?optsvar?} proc try {args} { set catchopts {} while {[string match -* [lindex $args 0]]} { set args [lassign $args opt] if {$opt eq "--"} { break } lappend catchopts $opt } if {[llength $args] == 0} { return -code error {wrong # args: should be "try ?options? script ?argument ...?"} } set args [lassign $args script] set code [catch -eval {*}$catchopts {uplevel 1 $script} msg opts] set handled 0 foreach {on codes vars script} $args { switch -- $on \ on { if {!$handled && ($codes eq "*" || [info returncode $code] in $codes)} { lassign $vars msgvar optsvar if {$msgvar ne ""} { upvar $msgvar hmsg set hmsg $msg } if {$optsvar ne ""} { upvar $optsvar hopts set hopts $opts } # Override any body result set code [catch {uplevel 1 $script} msg opts] incr handled } } \ finally { set finalcode [catch {uplevel 1 $codes} finalmsg finalopts] if {$finalcode} { # Override any body or handler result set code $finalcode set msg $finalmsg set opts $finalopts } break } \ default { return -code error "try: expected 'on' or 'finally', got '$on'" } } if {$code} { incr opts(-level) return {*}$opts $msg } return $msg } # Generates an exception with the given code (ok, error, etc. or an integer) # and the given message proc throw {code {msg ""}} { return -code $code $msg } # Helper for "file delete -force" proc {file delete force} {path} { foreach e [readdir $path] { file delete -force $path/$e } file delete $path } openocd-0.9.0/jimtcl/jim-package.c0000644000175000017500000001643712516456444013714 00000000000000#include #include "jimautoconf.h" #include #ifdef HAVE_UNISTD_H #include #else #define R_OK 4 #endif /* All packages have a fixed, dummy version */ static const char *package_version_1 = "1.0"; /* ----------------------------------------------------------------------------- * Packages handling * ---------------------------------------------------------------------------*/ int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) { /* If the package was already provided returns an error. */ Jim_HashEntry *he = Jim_FindHashEntry(&interp->packages, name); /* An empty result means the automatic entry. This can be replaced */ if (he && *(const char *)he->u.val) { if (flags & JIM_ERRMSG) { Jim_SetResultFormatted(interp, "package \"%s\" was already provided", name); } return JIM_ERR; } Jim_ReplaceHashEntry(&interp->packages, name, (char *)ver); return JIM_OK; } /** * Searches along a of paths for the given package. * * Returns the allocated path to the package file if found, * or NULL if not found. */ static char *JimFindPackage(Jim_Interp *interp, Jim_Obj *prefixListObj, const char *pkgName) { int i; char *buf = Jim_Alloc(JIM_PATH_LEN); int prefixc = Jim_ListLength(interp, prefixListObj); for (i = 0; i < prefixc; i++) { Jim_Obj *prefixObjPtr = Jim_ListGetIndex(interp, prefixListObj, i); const char *prefix = Jim_String(prefixObjPtr); /* Loadable modules are tried first */ #ifdef jim_ext_load snprintf(buf, JIM_PATH_LEN, "%s/%s.so", prefix, pkgName); if (access(buf, R_OK) == 0) { return buf; } #endif if (strcmp(prefix, ".") == 0) { snprintf(buf, JIM_PATH_LEN, "%s.tcl", pkgName); } else { snprintf(buf, JIM_PATH_LEN, "%s/%s.tcl", prefix, pkgName); } if (access(buf, R_OK) == 0) { return buf; } } Jim_Free(buf); return NULL; } /* Search for a suitable package under every dir specified by JIM_LIBPATH, * and load it if possible. If a suitable package was loaded with success * JIM_OK is returned, otherwise JIM_ERR is returned. */ static int JimLoadPackage(Jim_Interp *interp, const char *name, int flags) { int retCode = JIM_ERR; Jim_Obj *libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE); if (libPathObjPtr) { char *path; /* Scan every directory for the the first match */ path = JimFindPackage(interp, libPathObjPtr, name); if (path) { const char *p; /* Note: Even if the file fails to load, we consider the package loaded. * This prevents issues with recursion. * Use a dummy version of "" to signify this case. */ Jim_PackageProvide(interp, name, "", 0); /* Try to load/source it */ p = strrchr(path, '.'); if (p && strcmp(p, ".tcl") == 0) { Jim_IncrRefCount(libPathObjPtr); retCode = Jim_EvalFileGlobal(interp, path); Jim_DecrRefCount(interp, libPathObjPtr); } #ifdef jim_ext_load else { retCode = Jim_LoadLibrary(interp, path); } #endif if (retCode != JIM_OK) { /* Upon failure, remove the dummy entry */ Jim_DeleteHashEntry(&interp->packages, name); } Jim_Free(path); } return retCode; } return JIM_ERR; } int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags) { Jim_HashEntry *he; /* Start with an empty error string */ Jim_SetEmptyResult(interp); he = Jim_FindHashEntry(&interp->packages, name); if (he == NULL) { /* Try to load the package. */ int retcode = JimLoadPackage(interp, name, flags); if (retcode != JIM_OK) { if (flags & JIM_ERRMSG) { int len = Jim_Length(Jim_GetResult(interp)); Jim_SetResultFormatted(interp, "%#s%sCan't load package %s", Jim_GetResult(interp), len ? "\n" : "", name); } return retcode; } /* In case the package did not 'package provide' */ Jim_PackageProvide(interp, name, package_version_1, 0); /* Now it must exist */ he = Jim_FindHashEntry(&interp->packages, name); } Jim_SetResultString(interp, he->u.val, -1); return JIM_OK; } /* *---------------------------------------------------------------------- * * package provide name ?version? * * This procedure is invoked to declare that * a particular package is now present in an interpreter. * The package must not already be provided in the interpreter. * * Results: * Returns JIM_OK and sets results as "1.0" (the given version is ignored) * *---------------------------------------------------------------------- */ static int package_cmd_provide(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return Jim_PackageProvide(interp, Jim_String(argv[0]), package_version_1, JIM_ERRMSG); } /* *---------------------------------------------------------------------- * * package require name ?version? * * This procedure is load a given package. * Note that the version is ignored. * * Results: * Returns JIM_OK and sets the package version. * *---------------------------------------------------------------------- */ static int package_cmd_require(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* package require failing is important enough to add to the stack */ interp->addStackTrace++; return Jim_PackageRequire(interp, Jim_String(argv[0]), JIM_ERRMSG); } /* *---------------------------------------------------------------------- * * package list * * Returns a list of known packages * * Results: * Returns JIM_OK and sets a list of known packages. * *---------------------------------------------------------------------- */ static int package_cmd_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_HashTableIterator *htiter; Jim_HashEntry *he; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); htiter = Jim_GetHashTableIterator(&interp->packages); while ((he = Jim_NextHashEntry(htiter)) != NULL) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); } Jim_FreeHashTableIterator(htiter); Jim_SetResult(interp, listObjPtr); return JIM_OK; } static const jim_subcmd_type package_command_table[] = { { "provide", "name ?version?", package_cmd_provide, 1, 2, /* Description: Indicates that the current script provides the given package */ }, { "require", "name ?version?", package_cmd_require, 1, 2, /* Description: Loads the given package by looking in standard places */ }, { "list", NULL, package_cmd_list, 0, 0, /* Description: Lists all known packages */ }, { NULL } }; int Jim_packageInit(Jim_Interp *interp) { Jim_CreateCommand(interp, "package", Jim_SubCmdProc, (void *)package_command_table, NULL); return JIM_OK; } openocd-0.9.0/jimtcl/STYLE0000644000175000017500000000326212315602574012205 00000000000000This file summarizes the C style used for Jim. Copyright (C) 2005 Salvatore Sanfilippo. ----------- INDENTATION ----------- Indentation is 4 spaces, no smart-tabs are used (i.e. two indentation steps of 4 spaces will not be converted into a real tab, but 8 spaces). --------------- FUNCTIONS NAMES --------------- Functions names of exported functions are in the form: Jim_ExportedFunctionName() The prefix is "Jim_", every word composing the function name is capitalized. Not exported functions that are of general interest for the Jim core, like JimFreeInterp() are capitalized the same way, but the prefix used for this functions is "Jim" instead of "Jim_". Another example is: JimNotExportedFunction() Not exported functions that are not general, like functions implementing hashtables or Jim objects methods can be named in any prefix as long as capitalization rules are followed, like in: ListSetIndex() --------------- VARIABLES NAMES --------------- Global variables follow the same names convention of functions. Local variables have usually short names. A counter is just 'i', or 'j', or something like this. When a longer name is required, composed of more words, capitalization is used, but the first word starts in lowcase: thisIsALogVarName ---- GOTO ---- Goto is allowed every time it makes the code cleaner, like in complex functions that need to handle exceptions, there is often an "err" label at the end of the function where allocated resources are freed before to exit with an error. Goto is also used in order to escape multiple nested loops. ---------- C FEATURES ---------- Only C89 ANSI C is allowed. C99 features can't be used currently. GCC extensions are not allowed. openocd-0.9.0/jimtcl/rlprompt.tcl0000644000175000017500000000177412315602574013753 00000000000000# Readline-based interactive shell for Jim # Copyright(C) 2005 Salvatore Sanfilippo # # In order to automatically have readline-editing features # put this in your $HOME/.jimrc # # if {$jim_interactive} { # if {[catch {package require rlprompt}] == 0} { # rlprompt.shell # } # } package require readline proc rlprompt.shell {} { puts "Readline shell loaded" puts "Welcome to Jim [info version]!" set prompt ". " set buf "" while 1 { set line [readline.readline $prompt] if {[string length $line] == 0} { continue } if {$buf eq ""} { set buf $line } else { append buf \n $line } if {![info complete $buf]} { set prompt "> " continue } readline.addhistory $buf catch { uplevel #0 $buf } error if {$error ne ""} { puts $error } set buf "" set prompt ". " } } openocd-0.9.0/jimtcl/LICENSE0000644000175000017500000000434412516456443012376 00000000000000Unless explicitly stated, all files within Jim repository are released under following license: /* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * Copyright 2008 Steve Bennett * Copyright 2009 Nico Coesel * Copyright 2009 Zachary T Welch zw@superlucidity.net * Copyright 2009 David Brownell * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. */ openocd-0.9.0/jimtcl/jim.c0000644000175000017500000164271712516456444012332 00000000000000/* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008,2009 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * Copyright 2008 Steve Bennett * Copyright 2009 Nico Coesel * Copyright 2009 Zachary T Welch zw@superlucidity.net * Copyright 2009 David Brownell * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. **/ #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */ #include #include #include #include #include #include #include #include #include #include #include "jim.h" #include "jimautoconf.h" #include "utf8.h" #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_BACKTRACE #include #endif #ifdef HAVE_CRT_EXTERNS_H #include #endif /* For INFINITY, even if math functions are not enabled */ #include /* We may decide to switch to using $[...] after all, so leave it as an option */ /*#define EXPRSUGAR_BRACKET*/ /* For the no-autoconf case */ #ifndef TCL_LIBRARY #define TCL_LIBRARY "." #endif #ifndef TCL_PLATFORM_OS #define TCL_PLATFORM_OS "unknown" #endif #ifndef TCL_PLATFORM_PLATFORM #define TCL_PLATFORM_PLATFORM "unknown" #endif #ifndef TCL_PLATFORM_PATH_SEPARATOR #define TCL_PLATFORM_PATH_SEPARATOR ":" #endif /*#define DEBUG_SHOW_SCRIPT*/ /*#define DEBUG_SHOW_SCRIPT_TOKENS*/ /*#define DEBUG_SHOW_SUBST*/ /*#define DEBUG_SHOW_EXPR*/ /*#define DEBUG_SHOW_EXPR_TOKENS*/ /*#define JIM_DEBUG_GC*/ #ifdef JIM_MAINTAINER #define JIM_DEBUG_COMMAND #define JIM_DEBUG_PANIC #endif /* Enable this (in conjunction with valgrind) to help debug * reference counting issues */ /*#define JIM_DISABLE_OBJECT_POOL*/ /* Maximum size of an integer */ #define JIM_INTEGER_SPACE 24 const char *jim_tt_name(int type); #ifdef JIM_DEBUG_PANIC static void JimPanicDump(int fail_condition, const char *fmt, ...); #define JimPanic(X) JimPanicDump X #else #define JimPanic(X) #endif /* ----------------------------------------------------------------------------- * Global variables * ---------------------------------------------------------------------------*/ /* A shared empty string for the objects string representation. * Jim_InvalidateStringRep knows about it and doesn't try to free it. */ static char JimEmptyStringRep[] = ""; /* ----------------------------------------------------------------------------- * Required prototypes of not exported functions * ---------------------------------------------------------------------------*/ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, int flags); static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len); static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, const char *prefix, const char *const *tablePtr, const char *name); static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); static int JimSign(jim_wide w); static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len); /* Fast access to the int (wide) value of an object which is known to be of int type */ #define JimWideValue(objPtr) (objPtr)->internalRep.wideValue #define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none") static int utf8_tounicode_case(const char *s, int *uc, int upper) { int l = utf8_tounicode(s, uc); if (upper) { *uc = utf8_upper(*uc); } return l; } /* These can be used in addition to JIM_CASESENS/JIM_NOCASE */ #define JIM_CHARSET_SCAN 2 #define JIM_CHARSET_GLOB 0 /** * pattern points to a string like "[^a-z\ub5]" * * The pattern may contain trailing chars, which are ignored. * * The pattern is matched against unicode char 'c'. * * If (flags & JIM_NOCASE), case is ignored when matching. * If (flags & JIM_CHARSET_SCAN), the considers ^ and ] special at the start * of the charset, per scan, rather than glob/string match. * * If the unicode char 'c' matches that set, returns a pointer to the ']' character, * or the null character if the ']' is missing. * * Returns NULL on no match. */ static const char *JimCharsetMatch(const char *pattern, int c, int flags) { int not = 0; int pchar; int match = 0; int nocase = 0; if (flags & JIM_NOCASE) { nocase++; c = utf8_upper(c); } if (flags & JIM_CHARSET_SCAN) { if (*pattern == '^') { not++; pattern++; } /* Special case. If the first char is ']', it is part of the set */ if (*pattern == ']') { goto first; } } while (*pattern && *pattern != ']') { /* Exact match */ if (pattern[0] == '\\') { first: pattern += utf8_tounicode_case(pattern, &pchar, nocase); } else { /* Is this a range? a-z */ int start; int end; pattern += utf8_tounicode_case(pattern, &start, nocase); if (pattern[0] == '-' && pattern[1]) { /* skip '-' */ pattern += utf8_tounicode(pattern, &pchar); pattern += utf8_tounicode_case(pattern, &end, nocase); /* Handle reversed range too */ if ((c >= start && c <= end) || (c >= end && c <= start)) { match = 1; } continue; } pchar = start; } if (pchar == c) { match = 1; } } if (not) { match = !match; } return match ? pattern : NULL; } /* Glob-style pattern matching. */ /* Note: string *must* be valid UTF-8 sequences */ static int JimGlobMatch(const char *pattern, const char *string, int nocase) { int c; int pchar; while (*pattern) { switch (pattern[0]) { case '*': while (pattern[1] == '*') { pattern++; } pattern++; if (!pattern[0]) { return 1; /* match */ } while (*string) { /* Recursive call - Does the remaining pattern match anywhere? */ if (JimGlobMatch(pattern, string, nocase)) return 1; /* match */ string += utf8_tounicode(string, &c); } return 0; /* no match */ case '?': string += utf8_tounicode(string, &c); break; case '[': { string += utf8_tounicode(string, &c); pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); if (!pattern) { return 0; } if (!*pattern) { /* Ran out of pattern (no ']') */ continue; } break; } case '\\': if (pattern[1]) { pattern++; } /* fall through */ default: string += utf8_tounicode_case(string, &c, nocase); utf8_tounicode_case(pattern, &pchar, nocase); if (pchar != c) { return 0; } break; } pattern += utf8_tounicode_case(pattern, &pchar, nocase); if (!*string) { while (*pattern == '*') { pattern++; } break; } } if (!*pattern && !*string) { return 1; } return 0; } /** * string comparison. Works on binary data. * * Returns -1, 0 or 1 * * Note that the lengths are byte lengths, not char lengths. */ static int JimStringCompare(const char *s1, int l1, const char *s2, int l2) { if (l1 < l2) { return memcmp(s1, s2, l1) <= 0 ? -1 : 1; } else if (l2 < l1) { return memcmp(s1, s2, l2) >= 0 ? 1 : -1; } else { return JimSign(memcmp(s1, s2, l1)); } } /** * Compare null terminated strings, up to a maximum of 'maxchars' characters, * (or end of string if 'maxchars' is -1). * * Returns -1, 0, 1 for s1 < s2, s1 == s2, s1 > s2 respectively. * * Note: does not support embedded nulls. */ static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase) { while (*s1 && *s2 && maxchars) { int c1, c2; s1 += utf8_tounicode_case(s1, &c1, nocase); s2 += utf8_tounicode_case(s2, &c2, nocase); if (c1 != c2) { return JimSign(c1 - c2); } maxchars--; } if (!maxchars) { return 0; } /* One string or both terminated */ if (*s1) { return 1; } if (*s2) { return -1; } return 0; } /* Search 's1' inside 's2', starting to search from char 'index' of 's2'. * The index of the first occurrence of s1 in s2 is returned. * If s1 is not found inside s2, -1 is returned. */ static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx) { int i; int l1bytelen; if (!l1 || !l2 || l1 > l2) { return -1; } if (idx < 0) idx = 0; s2 += utf8_index(s2, idx); l1bytelen = utf8_index(s1, l1); for (i = idx; i <= l2 - l1; i++) { int c; if (memcmp(s2, s1, l1bytelen) == 0) { return i; } s2 += utf8_tounicode(s2, &c); } return -1; } /** * Note: Lengths and return value are in bytes, not chars. */ static int JimStringLast(const char *s1, int l1, const char *s2, int l2) { const char *p; if (!l1 || !l2 || l1 > l2) return -1; /* Now search for the needle */ for (p = s2 + l2 - 1; p != s2 - 1; p--) { if (*p == *s1 && memcmp(s1, p, l1) == 0) { return p - s2; } } return -1; } #ifdef JIM_UTF8 /** * Note: Lengths and return value are in chars. */ static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2) { int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2)); if (n > 0) { n = utf8_strlen(s2, n); } return n; } #endif /** * After an strtol()/strtod()-like conversion, * check whether something was converted and that * the only thing left is white space. * * Returns JIM_OK or JIM_ERR. */ static int JimCheckConversion(const char *str, const char *endptr) { if (str[0] == '\0' || str == endptr) { return JIM_ERR; } if (endptr[0] != '\0') { while (*endptr) { if (!isspace(UCHAR(*endptr))) { return JIM_ERR; } endptr++; } } return JIM_OK; } /* Parses the front of a number to determine it's sign and base * Returns the index to start parsing according to the given base */ static int JimNumberBase(const char *str, int *base, int *sign) { int i = 0; *base = 10; while (isspace(UCHAR(str[i]))) { i++; } if (str[i] == '-') { *sign = -1; i++; } else { if (str[i] == '+') { i++; } *sign = 1; } if (str[i] != '0') { /* base 10 */ return 0; } /* We have 0, so see if we can convert it */ switch (str[i + 1]) { case 'x': case 'X': *base = 16; break; case 'o': case 'O': *base = 8; break; case 'b': case 'B': *base = 2; break; default: return 0; } i += 2; /* Ensure that (e.g.) 0x-5 fails to parse */ if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { /* Parse according to this base */ return i; } /* Parse as base 10 */ *base = 10; return 0; } /* Converts a number as per strtol(..., 0) except leading zeros do *not* * imply octal. Instead, decimal is assumed unless the number begins with 0x, 0o or 0b */ static long jim_strtol(const char *str, char **endptr) { int sign; int base; int i = JimNumberBase(str, &base, &sign); if (base != 10) { long value = strtol(str + i, endptr, base); if (endptr == NULL || *endptr != str + i) { return value * sign; } } /* Can just do a regular base-10 conversion */ return strtol(str, endptr, 10); } /* Converts a number as per strtoull(..., 0) except leading zeros do *not* * imply octal. Instead, decimal is assumed unless the number begins with 0x, 0o or 0b */ static jim_wide jim_strtoull(const char *str, char **endptr) { #ifdef HAVE_LONG_LONG int sign; int base; int i = JimNumberBase(str, &base, &sign); if (base != 10) { jim_wide value = strtoull(str + i, endptr, base); if (endptr == NULL || *endptr != str + i) { return value * sign; } } /* Can just do a regular base-10 conversion */ return strtoull(str, endptr, 10); #else return (unsigned long)jim_strtol(str, endptr); #endif } int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) { char *endptr; if (base) { *widePtr = strtoull(str, &endptr, base); } else { *widePtr = jim_strtoull(str, &endptr); } return JimCheckConversion(str, endptr); } int Jim_StringToDouble(const char *str, double *doublePtr) { char *endptr; /* Callers can check for underflow via ERANGE */ errno = 0; *doublePtr = strtod(str, &endptr); return JimCheckConversion(str, endptr); } static jim_wide JimPowWide(jim_wide b, jim_wide e) { jim_wide i, res = 1; if ((b == 0 && e != 0) || (e < 0)) return 0; for (i = 0; i < e; i++) { res *= b; } return res; } /* ----------------------------------------------------------------------------- * Special functions * ---------------------------------------------------------------------------*/ #ifdef JIM_DEBUG_PANIC static void JimPanicDump(int condition, const char *fmt, ...) { va_list ap; if (!condition) { return; } va_start(ap, fmt); fprintf(stderr, "\nJIM INTERPRETER PANIC: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n\n"); va_end(ap); #ifdef HAVE_BACKTRACE { void *array[40]; int size, i; char **strings; size = backtrace(array, 40); strings = backtrace_symbols(array, size); for (i = 0; i < size; i++) fprintf(stderr, "[backtrace] %s\n", strings[i]); fprintf(stderr, "[backtrace] Include the above lines and the output\n"); fprintf(stderr, "[backtrace] of 'nm ' in the bug report.\n"); } #endif exit(1); } #endif /* ----------------------------------------------------------------------------- * Memory allocation * ---------------------------------------------------------------------------*/ void *Jim_Alloc(int size) { return size ? malloc(size) : NULL; } void Jim_Free(void *ptr) { free(ptr); } void *Jim_Realloc(void *ptr, int size) { return realloc(ptr, size); } char *Jim_StrDup(const char *s) { return strdup(s); } char *Jim_StrDupLen(const char *s, int l) { char *copy = Jim_Alloc(l + 1); memcpy(copy, s, l + 1); copy[l] = 0; /* Just to be sure, original could be substring */ return copy; } /* ----------------------------------------------------------------------------- * Time related functions * ---------------------------------------------------------------------------*/ /* Returns current time in microseconds */ static jim_wide JimClock(void) { struct timeval tv; gettimeofday(&tv, NULL); return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec; } /* ----------------------------------------------------------------------------- * Hash Tables * ---------------------------------------------------------------------------*/ /* -------------------------- private prototypes ---------------------------- */ static void JimExpandHashTableIfNeeded(Jim_HashTable *ht); static unsigned int JimHashTableNextPower(unsigned int size); static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace); /* -------------------------- hash functions -------------------------------- */ /* Thomas Wang's 32 bit Mix Function */ unsigned int Jim_IntHashFunction(unsigned int key) { key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); return key; } /* Generic hash function (we are using to multiply by 9 and add the byte * as Tcl) */ unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) { unsigned int h = 0; while (len--) h += (h << 3) + *buf++; return h; } /* ----------------------------- API implementation ------------------------- */ /* reset a hashtable already initialized */ static void JimResetHashTable(Jim_HashTable *ht) { ht->table = NULL; ht->size = 0; ht->sizemask = 0; ht->used = 0; ht->collisions = 0; #ifdef JIM_RANDOMISE_HASH /* This is initialised to a random value to avoid a hash collision attack. * See: n.runs-SA-2011.004 */ ht->uniq = (rand() ^ time(NULL) ^ clock()); #else ht->uniq = 0; #endif } static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) { iter->ht = ht; iter->index = -1; iter->entry = NULL; iter->nextEntry = NULL; } /* Initialize the hash table */ int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) { JimResetHashTable(ht); ht->type = type; ht->privdata = privDataPtr; return JIM_OK; } /* Resize the table to the minimal size that contains all the elements, * but with the invariant of a USER/BUCKETS ration near to <= 1 */ void Jim_ResizeHashTable(Jim_HashTable *ht) { int minimal = ht->used; if (minimal < JIM_HT_INITIAL_SIZE) minimal = JIM_HT_INITIAL_SIZE; Jim_ExpandHashTable(ht, minimal); } /* Expand or create the hashtable */ void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) { Jim_HashTable n; /* the new hashtable */ unsigned int realsize = JimHashTableNextPower(size), i; /* the size is invalid if it is smaller than the number of * elements already inside the hashtable */ if (size <= ht->used) return; Jim_InitHashTable(&n, ht->type, ht->privdata); n.size = realsize; n.sizemask = realsize - 1; n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); /* Keep the same 'uniq' as the original */ n.uniq = ht->uniq; /* Initialize all the pointers to NULL */ memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); /* Copy all the elements from the old to the new table: * note that if the old hash table is empty ht->used is zero, * so Jim_ExpandHashTable just creates an empty hash table. */ n.used = ht->used; for (i = 0; ht->used > 0; i++) { Jim_HashEntry *he, *nextHe; if (ht->table[i] == NULL) continue; /* For each hash entry on this slot... */ he = ht->table[i]; while (he) { unsigned int h; nextHe = he->next; /* Get the new element index */ h = Jim_HashKey(ht, he->key) & n.sizemask; he->next = n.table[h]; n.table[h] = he; ht->used--; /* Pass to the next element */ he = nextHe; } } assert(ht->used == 0); Jim_Free(ht->table); /* Remap the new hashtable in the old */ *ht = n; } /* Add an element to the target hash table */ int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) { Jim_HashEntry *entry; /* Get the index of the new element, or -1 if * the element already exists. */ entry = JimInsertHashEntry(ht, key, 0); if (entry == NULL) return JIM_ERR; /* Set the hash entry fields. */ Jim_SetHashKey(ht, entry, key); Jim_SetHashVal(ht, entry, val); return JIM_OK; } /* Add an element, discarding the old if the key already exists */ int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val) { int existed; Jim_HashEntry *entry; /* Get the index of the new element, or -1 if * the element already exists. */ entry = JimInsertHashEntry(ht, key, 1); if (entry->key) { /* It already exists, so only replace the value. * Note if both a destructor and a duplicate function exist, * need to dup before destroy. perhaps they are the same * reference counted object */ if (ht->type->valDestructor && ht->type->valDup) { void *newval = ht->type->valDup(ht->privdata, val); ht->type->valDestructor(ht->privdata, entry->u.val); entry->u.val = newval; } else { Jim_FreeEntryVal(ht, entry); Jim_SetHashVal(ht, entry, val); } existed = 1; } else { /* Doesn't exist, so set the key */ Jim_SetHashKey(ht, entry, key); Jim_SetHashVal(ht, entry, val); existed = 0; } return existed; } /* Search and remove an element */ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key) { unsigned int h; Jim_HashEntry *he, *prevHe; if (ht->used == 0) return JIM_ERR; h = Jim_HashKey(ht, key) & ht->sizemask; he = ht->table[h]; prevHe = NULL; while (he) { if (Jim_CompareHashKeys(ht, key, he->key)) { /* Unlink the element from the list */ if (prevHe) prevHe->next = he->next; else ht->table[h] = he->next; Jim_FreeEntryKey(ht, he); Jim_FreeEntryVal(ht, he); Jim_Free(he); ht->used--; return JIM_OK; } prevHe = he; he = he->next; } return JIM_ERR; /* not found */ } /* Destroy an entire hash table and leave it ready for reuse */ int Jim_FreeHashTable(Jim_HashTable *ht) { unsigned int i; /* Free all the elements */ for (i = 0; ht->used > 0; i++) { Jim_HashEntry *he, *nextHe; if ((he = ht->table[i]) == NULL) continue; while (he) { nextHe = he->next; Jim_FreeEntryKey(ht, he); Jim_FreeEntryVal(ht, he); Jim_Free(he); ht->used--; he = nextHe; } } /* Free the table and the allocated cache structure */ Jim_Free(ht->table); /* Re-initialize the table */ JimResetHashTable(ht); return JIM_OK; /* never fails */ } Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) { Jim_HashEntry *he; unsigned int h; if (ht->used == 0) return NULL; h = Jim_HashKey(ht, key) & ht->sizemask; he = ht->table[h]; while (he) { if (Jim_CompareHashKeys(ht, key, he->key)) return he; he = he->next; } return NULL; } Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) { Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); JimInitHashTableIterator(ht, iter); return iter; } Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) { while (1) { if (iter->entry == NULL) { iter->index++; if (iter->index >= (signed)iter->ht->size) break; iter->entry = iter->ht->table[iter->index]; } else { iter->entry = iter->nextEntry; } if (iter->entry) { /* We need to save the 'next' here, the iterator user * may delete the entry we are returning. */ iter->nextEntry = iter->entry->next; return iter->entry; } } return NULL; } /* ------------------------- private functions ------------------------------ */ /* Expand the hash table if needed */ static void JimExpandHashTableIfNeeded(Jim_HashTable *ht) { /* If the hash table is empty expand it to the intial size, * if the table is "full" dobule its size. */ if (ht->size == 0) Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE); if (ht->size == ht->used) Jim_ExpandHashTable(ht, ht->size * 2); } /* Our hash table capability is a power of two */ static unsigned int JimHashTableNextPower(unsigned int size) { unsigned int i = JIM_HT_INITIAL_SIZE; if (size >= 2147483648U) return 2147483648U; while (1) { if (i >= size) return i; i *= 2; } } /* Returns the index of a free slot that can be populated with * a hash entry for the given 'key'. * If the key already exists, -1 is returned. */ static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace) { unsigned int h; Jim_HashEntry *he; /* Expand the hashtable if needed */ JimExpandHashTableIfNeeded(ht); /* Compute the key hash value */ h = Jim_HashKey(ht, key) & ht->sizemask; /* Search if this slot does not already contain the given key */ he = ht->table[h]; while (he) { if (Jim_CompareHashKeys(ht, key, he->key)) return replace ? he : NULL; he = he->next; } /* Allocates the memory and stores key */ he = Jim_Alloc(sizeof(*he)); he->next = ht->table[h]; ht->table[h] = he; ht->used++; he->key = NULL; return he; } /* ----------------------- StringCopy Hash Table Type ------------------------*/ static unsigned int JimStringCopyHTHashFunction(const void *key) { return Jim_GenHashFunction(key, strlen(key)); } static void *JimStringCopyHTDup(void *privdata, const void *key) { return Jim_StrDup(key); } static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) { return strcmp(key1, key2) == 0; } static void JimStringCopyHTKeyDestructor(void *privdata, void *key) { Jim_Free(key); } static const Jim_HashTableType JimPackageHashTableType = { JimStringCopyHTHashFunction, /* hash function */ JimStringCopyHTDup, /* key dup */ NULL, /* val dup */ JimStringCopyHTKeyCompare, /* key compare */ JimStringCopyHTKeyDestructor, /* key destructor */ NULL /* val destructor */ }; typedef struct AssocDataValue { Jim_InterpDeleteProc *delProc; void *data; } AssocDataValue; static void JimAssocDataHashTableValueDestructor(void *privdata, void *data) { AssocDataValue *assocPtr = (AssocDataValue *) data; if (assocPtr->delProc != NULL) assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); Jim_Free(data); } static const Jim_HashTableType JimAssocDataHashTableType = { JimStringCopyHTHashFunction, /* hash function */ JimStringCopyHTDup, /* key dup */ NULL, /* val dup */ JimStringCopyHTKeyCompare, /* key compare */ JimStringCopyHTKeyDestructor, /* key destructor */ JimAssocDataHashTableValueDestructor /* val destructor */ }; /* ----------------------------------------------------------------------------- * Stack - This is a simple generic stack implementation. It is used for * example in the 'expr' expression compiler. * ---------------------------------------------------------------------------*/ void Jim_InitStack(Jim_Stack *stack) { stack->len = 0; stack->maxlen = 0; stack->vector = NULL; } void Jim_FreeStack(Jim_Stack *stack) { Jim_Free(stack->vector); } int Jim_StackLen(Jim_Stack *stack) { return stack->len; } void Jim_StackPush(Jim_Stack *stack, void *element) { int neededLen = stack->len + 1; if (neededLen > stack->maxlen) { stack->maxlen = neededLen < 20 ? 20 : neededLen * 2; stack->vector = Jim_Realloc(stack->vector, sizeof(void *) * stack->maxlen); } stack->vector[stack->len] = element; stack->len++; } void *Jim_StackPop(Jim_Stack *stack) { if (stack->len == 0) return NULL; stack->len--; return stack->vector[stack->len]; } void *Jim_StackPeek(Jim_Stack *stack) { if (stack->len == 0) return NULL; return stack->vector[stack->len - 1]; } void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr)) { int i; for (i = 0; i < stack->len; i++) freeFunc(stack->vector[i]); } /* ----------------------------------------------------------------------------- * Tcl Parser * ---------------------------------------------------------------------------*/ /* Token types */ #define JIM_TT_NONE 0 /* No token returned */ #define JIM_TT_STR 1 /* simple string */ #define JIM_TT_ESC 2 /* string that needs escape chars conversion */ #define JIM_TT_VAR 3 /* var substitution */ #define JIM_TT_DICTSUGAR 4 /* Syntax sugar for [dict get], $foo(bar) */ #define JIM_TT_CMD 5 /* command substitution */ /* Note: Keep these three together for TOKEN_IS_SEP() */ #define JIM_TT_SEP 6 /* word separator (white space) */ #define JIM_TT_EOL 7 /* line separator */ #define JIM_TT_EOF 8 /* end of script */ #define JIM_TT_LINE 9 /* special 'start-of-line' token. arg is # of arguments to the command. -ve if {*} */ #define JIM_TT_WORD 10 /* special 'start-of-word' token. arg is # of tokens to combine. -ve if {*} */ /* Additional token types needed for expressions */ #define JIM_TT_SUBEXPR_START 11 #define JIM_TT_SUBEXPR_END 12 #define JIM_TT_SUBEXPR_COMMA 13 #define JIM_TT_EXPR_INT 14 #define JIM_TT_EXPR_DOUBLE 15 #define JIM_TT_EXPRSUGAR 16 /* $(expression) */ /* Operator token types start here */ #define JIM_TT_EXPR_OP 20 #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) /* Parser states */ #define JIM_PS_DEF 0 /* Default state */ #define JIM_PS_QUOTE 1 /* Inside "" */ #define JIM_PS_DICTSUGAR 2 /* Tokenising abc(def) into 4 separate tokens */ /** * Results of missing quotes, braces, etc. from parsing. */ struct JimParseMissing { int ch; /* At end of parse, ' ' if complete or '{', '[', '"', '\\' , '{' if incomplete */ int line; /* Line number starting the missing token */ }; /* Parser context structure. The same context is used both to parse * Tcl scripts and lists. */ struct JimParserCtx { const char *p; /* Pointer to the point of the program we are parsing */ int len; /* Remaining length */ int linenr; /* Current line number */ const char *tstart; const char *tend; /* Returned token is at tstart-tend in 'prg'. */ int tline; /* Line number of the returned token */ int tt; /* Token type */ int eof; /* Non zero if EOF condition is true. */ int state; /* Parser state */ int comment; /* Non zero if the next chars may be a comment. */ struct JimParseMissing missing; /* Details of any missing quotes, etc. */ }; static int JimParseScript(struct JimParserCtx *pc); static int JimParseSep(struct JimParserCtx *pc); static int JimParseEol(struct JimParserCtx *pc); static int JimParseCmd(struct JimParserCtx *pc); static int JimParseQuote(struct JimParserCtx *pc); static int JimParseVar(struct JimParserCtx *pc); static int JimParseBrace(struct JimParserCtx *pc); static int JimParseStr(struct JimParserCtx *pc); static int JimParseComment(struct JimParserCtx *pc); static void JimParseSubCmd(struct JimParserCtx *pc); static int JimParseSubQuote(struct JimParserCtx *pc); static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); /* Initialize a parser context. * 'prg' is a pointer to the program text, linenr is the line * number of the first line contained in the program. */ static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) { pc->p = prg; pc->len = len; pc->tstart = NULL; pc->tend = NULL; pc->tline = 0; pc->tt = JIM_TT_NONE; pc->eof = 0; pc->state = JIM_PS_DEF; pc->linenr = linenr; pc->comment = 1; pc->missing.ch = ' '; pc->missing.line = linenr; } static int JimParseScript(struct JimParserCtx *pc) { while (1) { /* the while is used to reiterate with continue if needed */ if (!pc->len) { pc->tstart = pc->p; pc->tend = pc->p - 1; pc->tline = pc->linenr; pc->tt = JIM_TT_EOL; pc->eof = 1; return JIM_OK; } switch (*(pc->p)) { case '\\': if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) { return JimParseSep(pc); } pc->comment = 0; return JimParseStr(pc); case ' ': case '\t': case '\r': case '\f': if (pc->state == JIM_PS_DEF) return JimParseSep(pc); pc->comment = 0; return JimParseStr(pc); case '\n': case ';': pc->comment = 1; if (pc->state == JIM_PS_DEF) return JimParseEol(pc); return JimParseStr(pc); case '[': pc->comment = 0; return JimParseCmd(pc); case '$': pc->comment = 0; if (JimParseVar(pc) == JIM_ERR) { /* An orphan $. Create as a separate token */ pc->tstart = pc->tend = pc->p++; pc->len--; pc->tt = JIM_TT_ESC; } return JIM_OK; case '#': if (pc->comment) { JimParseComment(pc); continue; } return JimParseStr(pc); default: pc->comment = 0; return JimParseStr(pc); } return JIM_OK; } } static int JimParseSep(struct JimParserCtx *pc) { pc->tstart = pc->p; pc->tline = pc->linenr; while (isspace(UCHAR(*pc->p)) || (*pc->p == '\\' && *(pc->p + 1) == '\n')) { if (*pc->p == '\n') { break; } if (*pc->p == '\\') { pc->p++; pc->len--; pc->linenr++; } pc->p++; pc->len--; } pc->tend = pc->p - 1; pc->tt = JIM_TT_SEP; return JIM_OK; } static int JimParseEol(struct JimParserCtx *pc) { pc->tstart = pc->p; pc->tline = pc->linenr; while (isspace(UCHAR(*pc->p)) || *pc->p == ';') { if (*pc->p == '\n') pc->linenr++; pc->p++; pc->len--; } pc->tend = pc->p - 1; pc->tt = JIM_TT_EOL; return JIM_OK; } /* ** Here are the rules for parsing: ** {braced expression} ** - Count open and closing braces ** - Backslash escapes meaning of braces ** ** "quoted expression" ** - First double quote at start of word terminates the expression ** - Backslash escapes quote and bracket ** - [commands brackets] are counted/nested ** - command rules apply within [brackets], not quoting rules (i.e. quotes have their own rules) ** ** [command expression] ** - Count open and closing brackets ** - Backslash escapes quote, bracket and brace ** - [commands brackets] are counted/nested ** - "quoted expressions" are parsed according to quoting rules ** - {braced expressions} are parsed according to brace rules ** ** For everything, backslash escapes the next char, newline increments current line */ /** * Parses a braced expression starting at pc->p. * * Positions the parser at the end of the braced expression, * sets pc->tend and possibly pc->missing. */ static void JimParseSubBrace(struct JimParserCtx *pc) { int level = 1; /* Skip the brace */ pc->p++; pc->len--; while (pc->len) { switch (*pc->p) { case '\\': if (pc->len > 1) { if (*++pc->p == '\n') { pc->linenr++; } pc->len--; } break; case '{': level++; break; case '}': if (--level == 0) { pc->tend = pc->p - 1; pc->p++; pc->len--; return; } break; case '\n': pc->linenr++; break; } pc->p++; pc->len--; } pc->missing.ch = '{'; pc->missing.line = pc->tline; pc->tend = pc->p - 1; } /** * Parses a quoted expression starting at pc->p. * * Positions the parser at the end of the quoted expression, * sets pc->tend and possibly pc->missing. * * Returns the type of the token of the string, * either JIM_TT_ESC (if it contains values which need to be [subst]ed) * or JIM_TT_STR. */ static int JimParseSubQuote(struct JimParserCtx *pc) { int tt = JIM_TT_STR; int line = pc->tline; /* Skip the quote */ pc->p++; pc->len--; while (pc->len) { switch (*pc->p) { case '\\': if (pc->len > 1) { if (*++pc->p == '\n') { pc->linenr++; } pc->len--; tt = JIM_TT_ESC; } break; case '"': pc->tend = pc->p - 1; pc->p++; pc->len--; return tt; case '[': JimParseSubCmd(pc); tt = JIM_TT_ESC; continue; case '\n': pc->linenr++; break; case '$': tt = JIM_TT_ESC; break; } pc->p++; pc->len--; } pc->missing.ch = '"'; pc->missing.line = line; pc->tend = pc->p - 1; return tt; } /** * Parses a [command] expression starting at pc->p. * * Positions the parser at the end of the command expression, * sets pc->tend and possibly pc->missing. */ static void JimParseSubCmd(struct JimParserCtx *pc) { int level = 1; int startofword = 1; int line = pc->tline; /* Skip the bracket */ pc->p++; pc->len--; while (pc->len) { switch (*pc->p) { case '\\': if (pc->len > 1) { if (*++pc->p == '\n') { pc->linenr++; } pc->len--; } break; case '[': level++; break; case ']': if (--level == 0) { pc->tend = pc->p - 1; pc->p++; pc->len--; return; } break; case '"': if (startofword) { JimParseSubQuote(pc); continue; } break; case '{': JimParseSubBrace(pc); startofword = 0; continue; case '\n': pc->linenr++; break; } startofword = isspace(UCHAR(*pc->p)); pc->p++; pc->len--; } pc->missing.ch = '['; pc->missing.line = line; pc->tend = pc->p - 1; } static int JimParseBrace(struct JimParserCtx *pc) { pc->tstart = pc->p + 1; pc->tline = pc->linenr; pc->tt = JIM_TT_STR; JimParseSubBrace(pc); return JIM_OK; } static int JimParseCmd(struct JimParserCtx *pc) { pc->tstart = pc->p + 1; pc->tline = pc->linenr; pc->tt = JIM_TT_CMD; JimParseSubCmd(pc); return JIM_OK; } static int JimParseQuote(struct JimParserCtx *pc) { pc->tstart = pc->p + 1; pc->tline = pc->linenr; pc->tt = JimParseSubQuote(pc); return JIM_OK; } static int JimParseVar(struct JimParserCtx *pc) { /* skip the $ */ pc->p++; pc->len--; #ifdef EXPRSUGAR_BRACKET if (*pc->p == '[') { /* Parse $[...] expr shorthand syntax */ JimParseCmd(pc); pc->tt = JIM_TT_EXPRSUGAR; return JIM_OK; } #endif pc->tstart = pc->p; pc->tt = JIM_TT_VAR; pc->tline = pc->linenr; if (*pc->p == '{') { pc->tstart = ++pc->p; pc->len--; while (pc->len && *pc->p != '}') { if (*pc->p == '\n') { pc->linenr++; } pc->p++; pc->len--; } pc->tend = pc->p - 1; if (pc->len) { pc->p++; pc->len--; } } else { while (1) { /* Skip double colon, but not single colon! */ if (pc->p[0] == ':' && pc->p[1] == ':') { while (*pc->p == ':') { pc->p++; pc->len--; } continue; } /* Note that any char >= 0x80 must be part of a utf-8 char. * We consider all unicode points outside of ASCII as letters */ if (isalnum(UCHAR(*pc->p)) || *pc->p == '_' || UCHAR(*pc->p) >= 0x80) { pc->p++; pc->len--; continue; } break; } /* Parse [dict get] syntax sugar. */ if (*pc->p == '(') { int count = 1; const char *paren = NULL; pc->tt = JIM_TT_DICTSUGAR; while (count && pc->len) { pc->p++; pc->len--; if (*pc->p == '\\' && pc->len >= 1) { pc->p++; pc->len--; } else if (*pc->p == '(') { count++; } else if (*pc->p == ')') { paren = pc->p; count--; } } if (count == 0) { pc->p++; pc->len--; } else if (paren) { /* Did not find a matching paren. Back up */ paren++; pc->len += (pc->p - paren); pc->p = paren; } #ifndef EXPRSUGAR_BRACKET if (*pc->tstart == '(') { pc->tt = JIM_TT_EXPRSUGAR; } #endif } pc->tend = pc->p - 1; } /* Check if we parsed just the '$' character. * That's not a variable so an error is returned * to tell the state machine to consider this '$' just * a string. */ if (pc->tstart == pc->p) { pc->p--; pc->len++; return JIM_ERR; } return JIM_OK; } static int JimParseStr(struct JimParserCtx *pc) { if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) { /* Starting a new word */ if (*pc->p == '{') { return JimParseBrace(pc); } if (*pc->p == '"') { pc->state = JIM_PS_QUOTE; pc->p++; pc->len--; /* In case the end quote is missing */ pc->missing.line = pc->tline; } } pc->tstart = pc->p; pc->tline = pc->linenr; while (1) { if (pc->len == 0) { if (pc->state == JIM_PS_QUOTE) { pc->missing.ch = '"'; } pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; return JIM_OK; } switch (*pc->p) { case '\\': if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') { pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; return JIM_OK; } if (pc->len >= 2) { if (*(pc->p + 1) == '\n') { pc->linenr++; } pc->p++; pc->len--; } else if (pc->len == 1) { /* End of script with trailing backslash */ pc->missing.ch = '\\'; } break; case '(': /* If the following token is not '$' just keep going */ if (pc->len > 1 && pc->p[1] != '$') { break; } case ')': /* Only need a separate ')' token if the previous was a var */ if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { if (pc->p == pc->tstart) { /* At the start of the token, so just return this char */ pc->p++; pc->len--; } pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; return JIM_OK; } break; case '$': case '[': pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; return JIM_OK; case ' ': case '\t': case '\n': case '\r': case '\f': case ';': if (pc->state == JIM_PS_DEF) { pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; return JIM_OK; } else if (*pc->p == '\n') { pc->linenr++; } break; case '"': if (pc->state == JIM_PS_QUOTE) { pc->tend = pc->p - 1; pc->tt = JIM_TT_ESC; pc->p++; pc->len--; pc->state = JIM_PS_DEF; return JIM_OK; } break; } pc->p++; pc->len--; } return JIM_OK; /* unreached */ } static int JimParseComment(struct JimParserCtx *pc) { while (*pc->p) { if (*pc->p == '\\') { pc->p++; pc->len--; if (pc->len == 0) { pc->missing.ch = '\\'; return JIM_OK; } if (*pc->p == '\n') { pc->linenr++; } } else if (*pc->p == '\n') { pc->p++; pc->len--; pc->linenr++; break; } pc->p++; pc->len--; } return JIM_OK; } /* xdigitval and odigitval are helper functions for JimEscape() */ static int xdigitval(int c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static int odigitval(int c) { if (c >= '0' && c <= '7') return c - '0'; return -1; } /* Perform Tcl escape substitution of 's', storing the result * string into 'dest'. The escaped string is guaranteed to * be the same length or shorted than the source string. * Slen is the length of the string at 's', if it's -1 the string * length will be calculated by the function. * * The function returns the length of the resulting string. */ static int JimEscape(char *dest, const char *s, int slen) { char *p = dest; int i, len; if (slen == -1) slen = strlen(s); for (i = 0; i < slen; i++) { switch (s[i]) { case '\\': switch (s[i + 1]) { case 'a': *p++ = 0x7; i++; break; case 'b': *p++ = 0x8; i++; break; case 'f': *p++ = 0xc; i++; break; case 'n': *p++ = 0xa; i++; break; case 'r': *p++ = 0xd; i++; break; case 't': *p++ = 0x9; i++; break; case 'u': case 'U': case 'x': /* A unicode or hex sequence. * \x Expect 1-2 hex chars and convert to hex. * \u Expect 1-4 hex chars and convert to utf-8. * \U Expect 1-8 hex chars and convert to utf-8. * \u{NNN} supports 1-6 hex chars and convert to utf-8. * An invalid sequence means simply the escaped char. */ { unsigned val = 0; int k; int maxchars = 2; i++; if (s[i] == 'U') { maxchars = 8; } else if (s[i] == 'u') { if (s[i + 1] == '{') { maxchars = 6; i++; } else { maxchars = 4; } } for (k = 0; k < maxchars; k++) { int c = xdigitval(s[i + k + 1]); if (c == -1) { break; } val = (val << 4) | c; } /* The \u{nnn} syntax supports up to 21 bit codepoints. */ if (s[i] == '{') { if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') { /* Back up */ i--; k = 0; } else { /* Skip the closing brace */ k++; } } if (k) { /* Got a valid sequence, so convert */ if (s[i] == 'x') { *p++ = val; } else { p += utf8_fromunicode(p, val); } i += k; break; } /* Not a valid codepoint, just an escaped char */ *p++ = s[i]; } break; case 'v': *p++ = 0xb; i++; break; case '\0': *p++ = '\\'; i++; break; case '\n': /* Replace all spaces and tabs after backslash newline with a single space*/ *p++ = ' '; do { i++; } while (s[i + 1] == ' ' || s[i + 1] == '\t'); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* octal escape */ { int val = 0; int c = odigitval(s[i + 1]); val = c; c = odigitval(s[i + 2]); if (c == -1) { *p++ = val; i++; break; } val = (val * 8) + c; c = odigitval(s[i + 3]); if (c == -1) { *p++ = val; i += 2; break; } val = (val * 8) + c; *p++ = val; i += 3; } break; default: *p++ = s[i + 1]; i++; break; } break; default: *p++ = s[i]; break; } } len = p - dest; *p = '\0'; return len; } /* Returns a dynamically allocated copy of the current token in the * parser context. The function performs conversion of escapes if * the token is of type JIM_TT_ESC. * * Note that after the conversion, tokens that are grouped with * braces in the source code, are always recognizable from the * identical string obtained in a different way from the type. * * For example the string: * * {*}$a * * will return as first token "*", of type JIM_TT_STR * * While the string: * * *$a * * will return as first token "*", of type JIM_TT_ESC */ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc) { const char *start, *end; char *token; int len; start = pc->tstart; end = pc->tend; if (start > end) { len = 0; token = Jim_Alloc(1); token[0] = '\0'; } else { len = (end - start) + 1; token = Jim_Alloc(len + 1); if (pc->tt != JIM_TT_ESC) { /* No escape conversion needed? Just copy it. */ memcpy(token, start, len); token[len] = '\0'; } else { /* Else convert the escape chars. */ len = JimEscape(token, start, len); } } return Jim_NewStringObjNoAlloc(interp, token, len); } /* Parses the given string to determine if it represents a complete script. * * This is useful for interactive shells implementation, for [info complete]. * * If 'stateCharPtr' != NULL, the function stores ' ' on complete script, * '{' on scripts incomplete missing one or more '}' to be balanced. * '[' on scripts incomplete missing one or more ']' to be balanced. * '"' on scripts incomplete missing a '"' char. * '\\' on scripts with a trailing backslash. * * If the script is complete, 1 is returned, otherwise 0. */ int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr) { struct JimParserCtx parser; JimParserInit(&parser, s, len, 1); while (!parser.eof) { JimParseScript(&parser); } if (stateCharPtr) { *stateCharPtr = parser.missing.ch; } return parser.missing.ch == ' '; } /* ----------------------------------------------------------------------------- * Tcl Lists parsing * ---------------------------------------------------------------------------*/ static int JimParseListSep(struct JimParserCtx *pc); static int JimParseListStr(struct JimParserCtx *pc); static int JimParseListQuote(struct JimParserCtx *pc); static int JimParseList(struct JimParserCtx *pc) { if (isspace(UCHAR(*pc->p))) { return JimParseListSep(pc); } switch (*pc->p) { case '"': return JimParseListQuote(pc); case '{': return JimParseBrace(pc); default: if (pc->len) { return JimParseListStr(pc); } break; } pc->tstart = pc->tend = pc->p; pc->tline = pc->linenr; pc->tt = JIM_TT_EOL; pc->eof = 1; return JIM_OK; } static int JimParseListSep(struct JimParserCtx *pc) { pc->tstart = pc->p; pc->tline = pc->linenr; while (isspace(UCHAR(*pc->p))) { if (*pc->p == '\n') { pc->linenr++; } pc->p++; pc->len--; } pc->tend = pc->p - 1; pc->tt = JIM_TT_SEP; return JIM_OK; } static int JimParseListQuote(struct JimParserCtx *pc) { pc->p++; pc->len--; pc->tstart = pc->p; pc->tline = pc->linenr; pc->tt = JIM_TT_STR; while (pc->len) { switch (*pc->p) { case '\\': pc->tt = JIM_TT_ESC; if (--pc->len == 0) { /* Trailing backslash */ pc->tend = pc->p; return JIM_OK; } pc->p++; break; case '\n': pc->linenr++; break; case '"': pc->tend = pc->p - 1; pc->p++; pc->len--; return JIM_OK; } pc->p++; pc->len--; } pc->tend = pc->p - 1; return JIM_OK; } static int JimParseListStr(struct JimParserCtx *pc) { pc->tstart = pc->p; pc->tline = pc->linenr; pc->tt = JIM_TT_STR; while (pc->len) { if (isspace(UCHAR(*pc->p))) { pc->tend = pc->p - 1; return JIM_OK; } if (*pc->p == '\\') { if (--pc->len == 0) { /* Trailing backslash */ pc->tend = pc->p; return JIM_OK; } pc->tt = JIM_TT_ESC; pc->p++; } pc->p++; pc->len--; } pc->tend = pc->p - 1; return JIM_OK; } /* ----------------------------------------------------------------------------- * Jim_Obj related functions * ---------------------------------------------------------------------------*/ /* Return a new initialized object. */ Jim_Obj *Jim_NewObj(Jim_Interp *interp) { Jim_Obj *objPtr; /* -- Check if there are objects in the free list -- */ if (interp->freeList != NULL) { /* -- Unlink the object from the free list -- */ objPtr = interp->freeList; interp->freeList = objPtr->nextObjPtr; } else { /* -- No ready to use objects: allocate a new one -- */ objPtr = Jim_Alloc(sizeof(*objPtr)); } /* Object is returned with refCount of 0. Every * kind of GC implemented should take care to don't try * to scan objects with refCount == 0. */ objPtr->refCount = 0; /* All the other fields are left not initialized to save time. * The caller will probably want to set them to the right * value anyway. */ /* -- Put the object into the live list -- */ objPtr->prevObjPtr = NULL; objPtr->nextObjPtr = interp->liveList; if (interp->liveList) interp->liveList->prevObjPtr = objPtr; interp->liveList = objPtr; return objPtr; } /* Free an object. Actually objects are never freed, but * just moved to the free objects list, where they will be * reused by Jim_NewObj(). */ void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) { /* Check if the object was already freed, panic. */ JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "")); /* Free the internal representation */ Jim_FreeIntRep(interp, objPtr); /* Free the string representation */ if (objPtr->bytes != NULL) { if (objPtr->bytes != JimEmptyStringRep) Jim_Free(objPtr->bytes); } /* Unlink the object from the live objects list */ if (objPtr->prevObjPtr) objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; if (objPtr->nextObjPtr) objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; if (interp->liveList == objPtr) interp->liveList = objPtr->nextObjPtr; #ifdef JIM_DISABLE_OBJECT_POOL Jim_Free(objPtr); #else /* Link the object into the free objects list */ objPtr->prevObjPtr = NULL; objPtr->nextObjPtr = interp->freeList; if (interp->freeList) interp->freeList->prevObjPtr = objPtr; interp->freeList = objPtr; objPtr->refCount = -1; #endif } /* Invalidate the string representation of an object. */ void Jim_InvalidateStringRep(Jim_Obj *objPtr) { if (objPtr->bytes != NULL) { if (objPtr->bytes != JimEmptyStringRep) Jim_Free(objPtr->bytes); } objPtr->bytes = NULL; } /* Duplicate an object. The returned object has refcount = 0. */ Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_Obj *dupPtr; dupPtr = Jim_NewObj(interp); if (objPtr->bytes == NULL) { /* Object does not have a valid string representation. */ dupPtr->bytes = NULL; } else if (objPtr->length == 0) { /* Zero length, so don't even bother with the type-specific dup, since all zero length objects look the same */ dupPtr->bytes = JimEmptyStringRep; dupPtr->length = 0; dupPtr->typePtr = NULL; return dupPtr; } else { dupPtr->bytes = Jim_Alloc(objPtr->length + 1); dupPtr->length = objPtr->length; /* Copy the null byte too */ memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1); } /* By default, the new object has the same type as the old object */ dupPtr->typePtr = objPtr->typePtr; if (objPtr->typePtr != NULL) { if (objPtr->typePtr->dupIntRepProc == NULL) { dupPtr->internalRep = objPtr->internalRep; } else { /* The dup proc may set a different type, e.g. NULL */ objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); } } return dupPtr; } /* Return the string representation for objPtr. If the object's * string representation is invalid, calls the updateStringProc method to create * a new one from the internal representation of the object. */ const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) { if (objPtr->bytes == NULL) { /* Invalid string repr. Generate it. */ JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); objPtr->typePtr->updateStringProc(objPtr); } if (lenPtr) *lenPtr = objPtr->length; return objPtr->bytes; } /* Just returns the length of the object's string rep */ int Jim_Length(Jim_Obj *objPtr) { if (objPtr->bytes == NULL) { /* Invalid string repr. Generate it. */ JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); objPtr->typePtr->updateStringProc(objPtr); } return objPtr->length; } /* Just returns the length of the object's string rep */ const char *Jim_String(Jim_Obj *objPtr) { if (objPtr->bytes == NULL) { /* Invalid string repr. Generate it. */ JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value.")); JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); objPtr->typePtr->updateStringProc(objPtr); } return objPtr->bytes; } static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) { objPtr->bytes = Jim_StrDup(str); objPtr->length = strlen(str); } static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static const Jim_ObjType dictSubstObjType = { "dict-substitution", FreeDictSubstInternalRep, DupDictSubstInternalRep, NULL, JIM_TYPE_NONE, }; static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); } static const Jim_ObjType interpolatedObjType = { "interpolated", FreeInterpolatedInternalRep, NULL, NULL, JIM_TYPE_NONE, }; /* ----------------------------------------------------------------------------- * String Object * ---------------------------------------------------------------------------*/ static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static const Jim_ObjType stringObjType = { "string", NULL, DupStringInternalRep, NULL, JIM_TYPE_REFERENCES, }; static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { JIM_NOTUSED(interp); /* This is a bit subtle: the only caller of this function * should be Jim_DuplicateObj(), that will copy the * string representaion. After the copy, the duplicated * object will not have more room in the buffer than * srcPtr->length bytes. So we just set it to length. */ dupPtr->internalRep.strValue.maxLength = srcPtr->length; dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; } static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &stringObjType) { /* Get a fresh string representation. */ if (objPtr->bytes == NULL) { /* Invalid string repr. Generate it. */ JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); objPtr->typePtr->updateStringProc(objPtr); } /* Free any other internal representation. */ Jim_FreeIntRep(interp, objPtr); /* Set it as string, i.e. just set the maxLength field. */ objPtr->typePtr = &stringObjType; objPtr->internalRep.strValue.maxLength = objPtr->length; /* Don't know the utf-8 length yet */ objPtr->internalRep.strValue.charLength = -1; } return JIM_OK; } /** * Returns the length of the object string in chars, not bytes. * * These may be different for a utf-8 string. */ int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr) { #ifdef JIM_UTF8 SetStringFromAny(interp, objPtr); if (objPtr->internalRep.strValue.charLength < 0) { objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length); } return objPtr->internalRep.strValue.charLength; #else return Jim_Length(objPtr); #endif } /* len is in bytes -- see also Jim_NewStringObjUtf8() */ Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) { Jim_Obj *objPtr = Jim_NewObj(interp); /* Need to find out how many bytes the string requires */ if (len == -1) len = strlen(s); /* Alloc/Set the string rep. */ if (len == 0) { objPtr->bytes = JimEmptyStringRep; } else { objPtr->bytes = Jim_Alloc(len + 1); memcpy(objPtr->bytes, s, len); objPtr->bytes[len] = '\0'; } objPtr->length = len; /* No typePtr field for the vanilla string object. */ objPtr->typePtr = NULL; return objPtr; } /* charlen is in characters -- see also Jim_NewStringObj() */ Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) { #ifdef JIM_UTF8 /* Need to find out how many bytes the string requires */ int bytelen = utf8_index(s, charlen); Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); /* Remember the utf8 length, so set the type */ objPtr->typePtr = &stringObjType; objPtr->internalRep.strValue.maxLength = bytelen; objPtr->internalRep.strValue.charLength = charlen; return objPtr; #else return Jim_NewStringObj(interp, s, charlen); #endif } /* This version does not try to duplicate the 's' pointer, but * use it directly. */ Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) { Jim_Obj *objPtr = Jim_NewObj(interp); objPtr->bytes = s; objPtr->length = (len == -1) ? strlen(s) : len; objPtr->typePtr = NULL; return objPtr; } /* Low-level string append. Use it only against unshared objects * of type "string". */ static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) { int needlen; if (len == -1) len = strlen(str); needlen = objPtr->length + len; if (objPtr->internalRep.strValue.maxLength < needlen || objPtr->internalRep.strValue.maxLength == 0) { needlen *= 2; /* Inefficient to malloc() for less than 8 bytes */ if (needlen < 7) { needlen = 7; } if (objPtr->bytes == JimEmptyStringRep) { objPtr->bytes = Jim_Alloc(needlen + 1); } else { objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1); } objPtr->internalRep.strValue.maxLength = needlen; } memcpy(objPtr->bytes + objPtr->length, str, len); objPtr->bytes[objPtr->length + len] = '\0'; if (objPtr->internalRep.strValue.charLength >= 0) { /* Update the utf-8 char length */ objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); } objPtr->length += len; } /* Higher level API to append strings to objects. * Object must not be unshared for each of these. */ void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) { JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); SetStringFromAny(interp, objPtr); StringAppendString(objPtr, str, len); } void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) { int len; const char *str = Jim_GetString(appendObjPtr, &len); Jim_AppendString(interp, objPtr, str, len); } void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) { va_list ap; SetStringFromAny(interp, objPtr); va_start(ap, objPtr); while (1) { const char *s = va_arg(ap, const char *); if (s == NULL) break; Jim_AppendString(interp, objPtr, s, -1); } va_end(ap); } int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) { if (aObjPtr == bObjPtr) { return 1; } else { int Alen, Blen; const char *sA = Jim_GetString(aObjPtr, &Alen); const char *sB = Jim_GetString(bObjPtr, &Blen); return Alen == Blen && memcmp(sA, sB, Alen) == 0; } } /** * Note. Does not support embedded nulls in either the pattern or the object. */ int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) { return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); } /* * Note: does not support embedded nulls for the nocase option. */ int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) { int l1, l2; const char *s1 = Jim_GetString(firstObjPtr, &l1); const char *s2 = Jim_GetString(secondObjPtr, &l2); if (nocase) { /* Do a character compare for nocase */ return JimStringCompareLen(s1, s2, -1, nocase); } return JimStringCompare(s1, l1, s2, l2); } /** * Like Jim_StringCompareObj() except compares to a maximum of the length of firstObjPtr. * * Note: does not support embedded nulls */ int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) { const char *s1 = Jim_String(firstObjPtr); const char *s2 = Jim_String(secondObjPtr); return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase); } /* Convert a range, as returned by Jim_GetRange(), into * an absolute index into an object of the specified length. * This function may return negative values, or values * greater than or equal to the length of the list if the index * is out of range. */ static int JimRelToAbsIndex(int len, int idx) { if (idx < 0) return len + idx; return idx; } /* Convert a pair of indexes (*firstPtr, *lastPtr) as normalized by JimRelToAbsIndex(), * into a form suitable for implementation of commands like [string range] and [lrange]. * * The resulting range is guaranteed to address valid elements of * the structure. */ static void JimRelToAbsRange(int len, int *firstPtr, int *lastPtr, int *rangeLenPtr) { int rangeLen; if (*firstPtr > *lastPtr) { rangeLen = 0; } else { rangeLen = *lastPtr - *firstPtr + 1; if (rangeLen) { if (*firstPtr < 0) { rangeLen += *firstPtr; *firstPtr = 0; } if (*lastPtr >= len) { rangeLen -= (*lastPtr - (len - 1)); *lastPtr = len - 1; } } } if (rangeLen < 0) rangeLen = 0; *rangeLenPtr = rangeLen; } static int JimStringGetRange(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, int len, int *first, int *last, int *range) { if (Jim_GetIndex(interp, firstObjPtr, first) != JIM_OK) { return JIM_ERR; } if (Jim_GetIndex(interp, lastObjPtr, last) != JIM_OK) { return JIM_ERR; } *first = JimRelToAbsIndex(len, *first); *last = JimRelToAbsIndex(len, *last); JimRelToAbsRange(len, first, last, range); return JIM_OK; } Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) { int first, last; const char *str; int rangeLen; int bytelen; str = Jim_GetString(strObjPtr, &bytelen); if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, bytelen, &first, &last, &rangeLen) != JIM_OK) { return NULL; } if (first == 0 && rangeLen == bytelen) { return strObjPtr; } return Jim_NewStringObj(interp, str + first, rangeLen); } Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) { #ifdef JIM_UTF8 int first, last; const char *str; int len, rangeLen; int bytelen; str = Jim_GetString(strObjPtr, &bytelen); len = Jim_Utf8Length(interp, strObjPtr); if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) { return NULL; } if (first == 0 && rangeLen == len) { return strObjPtr; } if (len == bytelen) { /* ASCII optimisation */ return Jim_NewStringObj(interp, str + first, rangeLen); } return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); #else return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); #endif } Jim_Obj *JimStringReplaceObj(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, Jim_Obj *newStrObj) { int first, last; const char *str; int len, rangeLen; Jim_Obj *objPtr; len = Jim_Utf8Length(interp, strObjPtr); if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) { return NULL; } if (last < first) { return strObjPtr; } str = Jim_String(strObjPtr); /* Before part */ objPtr = Jim_NewStringObjUtf8(interp, str, first); /* Replacement */ if (newStrObj) { Jim_AppendObj(interp, objPtr, newStrObj); } /* After part */ Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1); return objPtr; } /** * Note: does not support embedded nulls. */ static void JimStrCopyUpperLower(char *dest, const char *str, int uc) { while (*str) { int c; str += utf8_tounicode(str, &c); dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c)); } *dest = 0; } /** * Note: does not support embedded nulls. */ static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf; int len; const char *str; SetStringFromAny(interp, strObjPtr); str = Jim_GetString(strObjPtr, &len); #ifdef JIM_UTF8 /* Case mapping can change the utf-8 length of the string. * But at worst it will be by one extra byte per char */ len *= 2; #endif buf = Jim_Alloc(len + 1); JimStrCopyUpperLower(buf, str, 0); return Jim_NewStringObjNoAlloc(interp, buf, -1); } /** * Note: does not support embedded nulls. */ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf; const char *str; int len; if (strObjPtr->typePtr != &stringObjType) { SetStringFromAny(interp, strObjPtr); } str = Jim_GetString(strObjPtr, &len); #ifdef JIM_UTF8 /* Case mapping can change the utf-8 length of the string. * But at worst it will be by one extra byte per char */ len *= 2; #endif buf = Jim_Alloc(len + 1); JimStrCopyUpperLower(buf, str, 1); return Jim_NewStringObjNoAlloc(interp, buf, -1); } /** * Note: does not support embedded nulls. */ static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf, *p; int len; int c; const char *str; str = Jim_GetString(strObjPtr, &len); if (len == 0) { return strObjPtr; } #ifdef JIM_UTF8 /* Case mapping can change the utf-8 length of the string. * But at worst it will be by one extra byte per char */ len *= 2; #endif buf = p = Jim_Alloc(len + 1); str += utf8_tounicode(str, &c); p += utf8_getchars(p, utf8_title(c)); JimStrCopyUpperLower(p, str, 0); return Jim_NewStringObjNoAlloc(interp, buf, -1); } /* Similar to memchr() except searches a UTF-8 string 'str' of byte length 'len' * for unicode character 'c'. * Returns the position if found or NULL if not */ static const char *utf8_memchr(const char *str, int len, int c) { #ifdef JIM_UTF8 while (len) { int sc; int n = utf8_tounicode(str, &sc); if (sc == c) { return str; } str += n; len -= n; } return NULL; #else return memchr(str, c, len); #endif } /** * Searches for the first non-trim char in string (str, len) * * If none is found, returns just past the last char. * * Lengths are in bytes. */ static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen) { while (len) { int c; int n = utf8_tounicode(str, &c); if (utf8_memchr(trimchars, trimlen, c) == NULL) { /* Not a trim char, so stop */ break; } str += n; len -= n; } return str; } /** * Searches backwards for a non-trim char in string (str, len). * * Returns a pointer to just after the non-trim char, or NULL if not found. * * Lengths are in bytes. */ static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen) { str += len; while (len) { int c; int n = utf8_prev_len(str, len); len -= n; str -= n; n = utf8_tounicode(str, &c); if (utf8_memchr(trimchars, trimlen, c) == NULL) { return str + n; } } return NULL; } static const char default_trim_chars[] = " \t\n\r"; /* sizeof() here includes the null byte */ static int default_trim_chars_len = sizeof(default_trim_chars); static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) { int len; const char *str = Jim_GetString(strObjPtr, &len); const char *trimchars = default_trim_chars; int trimcharslen = default_trim_chars_len; const char *newstr; if (trimcharsObjPtr) { trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); } newstr = JimFindTrimLeft(str, len, trimchars, trimcharslen); if (newstr == str) { return strObjPtr; } return Jim_NewStringObj(interp, newstr, len - (newstr - str)); } static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) { int len; const char *trimchars = default_trim_chars; int trimcharslen = default_trim_chars_len; const char *nontrim; if (trimcharsObjPtr) { trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); } SetStringFromAny(interp, strObjPtr); len = Jim_Length(strObjPtr); nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); if (nontrim == NULL) { /* All trim, so return a zero-length string */ return Jim_NewEmptyStringObj(interp); } if (nontrim == strObjPtr->bytes + len) { /* All non-trim, so return the original object */ return strObjPtr; } if (Jim_IsShared(strObjPtr)) { strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); } else { /* Can modify this string in place */ strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; strObjPtr->length = (nontrim - strObjPtr->bytes); } return strObjPtr; } static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) { /* First trim left. */ Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); /* Now trim right */ strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); /* Note: refCount check is needed since objPtr may be emptyObj */ if (objPtr != strObjPtr && objPtr->refCount == 0) { /* We don't want this object to be leaked */ Jim_FreeNewObj(interp, objPtr); } return strObjPtr; } /* Some platforms don't have isascii - need a non-macro version */ #ifdef HAVE_ISASCII #define jim_isascii isascii #else static int jim_isascii(int c) { return !(c & ~0x7f); } #endif static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) { static const char * const strclassnames[] = { "integer", "alpha", "alnum", "ascii", "digit", "double", "lower", "upper", "space", "xdigit", "control", "print", "graph", "punct", NULL }; enum { STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT }; int strclass; int len; int i; const char *str; int (*isclassfunc)(int c) = NULL; if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } str = Jim_GetString(strObjPtr, &len); if (len == 0) { Jim_SetResultBool(interp, !strict); return JIM_OK; } switch (strclass) { case STR_IS_INTEGER: { jim_wide w; Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); return JIM_OK; } case STR_IS_DOUBLE: { double d; Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); return JIM_OK; } case STR_IS_ALPHA: isclassfunc = isalpha; break; case STR_IS_ALNUM: isclassfunc = isalnum; break; case STR_IS_ASCII: isclassfunc = jim_isascii; break; case STR_IS_DIGIT: isclassfunc = isdigit; break; case STR_IS_LOWER: isclassfunc = islower; break; case STR_IS_UPPER: isclassfunc = isupper; break; case STR_IS_SPACE: isclassfunc = isspace; break; case STR_IS_XDIGIT: isclassfunc = isxdigit; break; case STR_IS_CONTROL: isclassfunc = iscntrl; break; case STR_IS_PRINT: isclassfunc = isprint; break; case STR_IS_GRAPH: isclassfunc = isgraph; break; case STR_IS_PUNCT: isclassfunc = ispunct; break; default: return JIM_ERR; } for (i = 0; i < len; i++) { if (!isclassfunc(str[i])) { Jim_SetResultBool(interp, 0); return JIM_OK; } } Jim_SetResultBool(interp, 1); return JIM_OK; } /* ----------------------------------------------------------------------------- * Compared String Object * ---------------------------------------------------------------------------*/ /* This is strange object that allows comparison of a C literal string * with a Jim object in a very short time if the same comparison is done * multiple times. For example every time the [if] command is executed, * Jim has to check if a given argument is "else". * If the code has no errors, this comparison is true most of the time, * so we can cache the pointer of the string of the last matching * comparison inside the object. Because most C compilers perform literal sharing, * so that: char *x = "foo", char *y = "foo", will lead to x == y, * this works pretty well even if comparisons are at different places * inside the C code. */ static const Jim_ObjType comparedStringObjType = { "compared-string", NULL, NULL, NULL, JIM_TYPE_REFERENCES, }; /* The only way this object is exposed to the API is via the following * function. Returns true if the string and the object string repr. * are the same, otherwise zero is returned. * * Note: this isn't binary safe, but it hardly needs to be.*/ int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) { if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { return 1; } else { const char *objStr = Jim_String(objPtr); if (strcmp(str, objStr) != 0) return 0; if (objPtr->typePtr != &comparedStringObjType) { Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &comparedStringObjType; } objPtr->internalRep.ptr = (char *)str; /*ATTENTION: const cast */ return 1; } } static int qsortCompareStringPointers(const void *a, const void *b) { char *const *sa = (char *const *)a; char *const *sb = (char *const *)b; return strcmp(*sa, *sb); } /* ----------------------------------------------------------------------------- * Source Object * * This object is just a string from the language point of view, but * the internal representation contains the filename and line number * where this token was read. This information is used by * Jim_EvalObj() if the object passed happens to be of type "source". * * This allows propagation of the information about line numbers and file * names and gives error messages with absolute line numbers. * * Note that this object uses the internal representation of the Jim_Object, * so there is almost no memory overhead. (One Jim_Obj for each filename). * * Also the object will be converted to something else if the given * token it represents in the source file is not something to be * evaluated (not a script), and will be specialized in some other way, * so the time overhead is also almost zero. * ---------------------------------------------------------------------------*/ static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static const Jim_ObjType sourceObjType = { "source", FreeSourceInternalRep, DupSourceInternalRep, NULL, JIM_TYPE_REFERENCES, }; void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj); } void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue; Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); } static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *fileNameObj, int lineNumber) { JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); Jim_IncrRefCount(fileNameObj); objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; objPtr->internalRep.sourceValue.lineNumber = lineNumber; objPtr->typePtr = &sourceObjType; } /* ----------------------------------------------------------------------------- * ScriptLine Object * * This object is used only in the Script internal represenation. * For each line of the script, it holds the number of tokens on the line * and the source line number. */ static const Jim_ObjType scriptLineObjType = { "scriptline", NULL, NULL, NULL, JIM_NONE, }; static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) { Jim_Obj *objPtr; #ifdef DEBUG_SHOW_SCRIPT char buf[100]; snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc); objPtr = Jim_NewStringObj(interp, buf, -1); #else objPtr = Jim_NewEmptyStringObj(interp); #endif objPtr->typePtr = &scriptLineObjType; objPtr->internalRep.scriptLineValue.argc = argc; objPtr->internalRep.scriptLineValue.line = line; return objPtr; } /* ----------------------------------------------------------------------------- * Script Object * * This object holds the parsed internal representation of a script. * This representation is help within an allocated ScriptObj (see below) */ static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static int JimParseCheckMissing(Jim_Interp *interp, int ch); static const Jim_ObjType scriptObjType = { "script", FreeScriptInternalRep, DupScriptInternalRep, NULL, JIM_TYPE_REFERENCES, }; /* Each token of a script is represented by a ScriptToken. * The ScriptToken contains a type and a Jim_Obj. The Jim_Obj * can be specialized by commands operating on it. */ typedef struct ScriptToken { Jim_Obj *objPtr; int type; } ScriptToken; /* This is the script object internal representation. An array of * ScriptToken structures, including a pre-computed representation of the * command length and arguments. * * For example the script: * * puts hello * set $i $x$y [foo]BAR * * will produce a ScriptObj with the following ScriptToken's: * * LIN 2 * ESC puts * ESC hello * LIN 4 * ESC set * VAR i * WRD 2 * VAR x * VAR y * WRD 2 * CMD foo * ESC BAR * * "puts hello" has two args (LIN 2), composed of single tokens. * (Note that the WRD token is omitted for the common case of a single token.) * * "set $i $x$y [foo]BAR" has four (LIN 4) args, the first word * has 1 token (ESC SET), and the last has two tokens (WRD 2 CMD foo ESC BAR) * * The precomputation of the command structure makes Jim_Eval() faster, * and simpler because there aren't dynamic lengths / allocations. * * -- {expand}/{*} handling -- * * Expand is handled in a special way. * * If a "word" begins with {*}, the word token count is -ve. * * For example the command: * * list {*}{a b} * * Will produce the following cmdstruct array: * * LIN 2 * ESC list * WRD -1 * STR a b * * Note that the 'LIN' token also contains the source information for the * first word of the line for error reporting purposes * * -- the substFlags field of the structure -- * * The scriptObj structure is used to represent both "script" objects * and "subst" objects. In the second case, the there are no LIN and WRD * tokens. Instead SEP and EOL tokens are added as-is. * In addition, the field 'substFlags' is used to represent the flags used to turn * the string into the internal representation. * If these flags do not match what the application requires, * the scriptObj is created again. For example the script: * * subst -nocommands $string * subst -novariables $string * * Will (re)create the internal representation of the $string object * two times. */ typedef struct ScriptObj { ScriptToken *token; /* Tokens array. */ Jim_Obj *fileNameObj; /* Filename */ int len; /* Length of token[] */ int substFlags; /* flags used for the compilation of "subst" objects */ int inUse; /* Used to share a ScriptObj. Currently only used by Jim_EvalObj() as protection against shimmering of the currently evaluated object. */ int firstline; /* Line number of the first line */ int linenr; /* Error line number, if any */ int missing; /* Missing char if script failed to parse, (or space or backslash if OK) */ } ScriptObj; void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { int i; struct ScriptObj *script = (void *)objPtr->internalRep.ptr; if (--script->inUse != 0) return; for (i = 0; i < script->len; i++) { Jim_DecrRefCount(interp, script->token[i].objPtr); } Jim_Free(script->token); Jim_DecrRefCount(interp, script->fileNameObj); Jim_Free(script); } void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { JIM_NOTUSED(interp); JIM_NOTUSED(srcPtr); /* Just return a simple string. We don't try to preserve the source info * since in practice scripts are never duplicated */ dupPtr->typePtr = NULL; } /* A simple parse token. * As the script is parsed, the created tokens point into the script string rep. */ typedef struct { const char *token; /* Pointer to the start of the token */ int len; /* Length of this token */ int type; /* Token type */ int line; /* Line number */ } ParseToken; /* A list of parsed tokens representing a script. * Tokens are added to this list as the script is parsed. * It grows as needed. */ typedef struct { /* Start with a statically allocated list of tokens which will be expanded with realloc if needed */ ParseToken *list; /* Array of tokens */ int size; /* Current size of the list */ int count; /* Number of entries used */ ParseToken static_list[20]; /* Small initial token space to avoid allocation */ } ParseTokenList; static void ScriptTokenListInit(ParseTokenList *tokenlist) { tokenlist->list = tokenlist->static_list; tokenlist->size = sizeof(tokenlist->static_list) / sizeof(ParseToken); tokenlist->count = 0; } static void ScriptTokenListFree(ParseTokenList *tokenlist) { if (tokenlist->list != tokenlist->static_list) { Jim_Free(tokenlist->list); } } /** * Adds the new token to the tokenlist. * The token has the given length, type and line number. * The token list is resized as necessary. */ static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type, int line) { ParseToken *t; if (tokenlist->count == tokenlist->size) { /* Resize the list */ tokenlist->size *= 2; if (tokenlist->list != tokenlist->static_list) { tokenlist->list = Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); } else { /* The list needs to become allocated */ tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); memcpy(tokenlist->list, tokenlist->static_list, tokenlist->count * sizeof(*tokenlist->list)); } } t = &tokenlist->list[tokenlist->count++]; t->token = token; t->len = len; t->type = type; t->line = line; } /* Counts the number of adjoining non-separator tokens. * * Returns -ve if the first token is the expansion * operator (in which case the count doesn't include * that token). */ static int JimCountWordTokens(ParseToken *t) { int expand = 1; int count = 0; /* Is the first word {*} or {expand}? */ if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { /* Create an expand token */ expand = -1; t++; } } /* Now count non-separator words */ while (!TOKEN_IS_SEP(t->type)) { t++; count++; } return count * expand; } /** * Create a script/subst object from the given token. */ static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) { Jim_Obj *objPtr; if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { /* Convert backlash escapes. The result will never be longer than the original */ int len = t->len; char *str = Jim_Alloc(len + 1); len = JimEscape(str, t->token, len); objPtr = Jim_NewStringObjNoAlloc(interp, str, len); } else { /* XXX: For strict Tcl compatibility, JIM_TT_STR should replace * with a single space. */ objPtr = Jim_NewStringObj(interp, t->token, t->len); } return objPtr; } /** * Takes a tokenlist and creates the allocated list of script tokens * in script->token, of length script->len. * * Unnecessary tokens are discarded, and LINE and WORD tokens are inserted * as required. * * Also sets script->line to the line number of the first token */ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, ParseTokenList *tokenlist) { int i; struct ScriptToken *token; /* Number of tokens so far for the current command */ int lineargs = 0; /* This is the first token for the current command */ ScriptToken *linefirst; int count; int linenr; #ifdef DEBUG_SHOW_SCRIPT_TOKENS printf("==== Tokens ====\n"); for (i = 0; i < tokenlist->count; i++) { printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), tokenlist->list[i].len, tokenlist->list[i].token); } #endif /* May need up to one extra script token for each EOL in the worst case */ count = tokenlist->count; for (i = 0; i < tokenlist->count; i++) { if (tokenlist->list[i].type == JIM_TT_EOL) { count++; } } linenr = script->firstline = tokenlist->list[0].line; token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); /* This is the first token for the current command */ linefirst = token++; for (i = 0; i < tokenlist->count; ) { /* Look ahead to find out how many tokens make up the next word */ int wordtokens; /* Skip any leading separators */ while (tokenlist->list[i].type == JIM_TT_SEP) { i++; } wordtokens = JimCountWordTokens(tokenlist->list + i); if (wordtokens == 0) { /* None, so at end of line */ if (lineargs) { linefirst->type = JIM_TT_LINE; linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); Jim_IncrRefCount(linefirst->objPtr); /* Reset for new line */ lineargs = 0; linefirst = token++; } i++; continue; } else if (wordtokens != 1) { /* More than 1, or {*}, so insert a WORD token */ token->type = JIM_TT_WORD; token->objPtr = Jim_NewIntObj(interp, wordtokens); Jim_IncrRefCount(token->objPtr); token++; if (wordtokens < 0) { /* Skip the expand token */ i++; wordtokens = -wordtokens - 1; lineargs--; } } if (lineargs == 0) { /* First real token on the line, so record the line number */ linenr = tokenlist->list[i].line; } lineargs++; /* Add each non-separator word token to the line */ while (wordtokens--) { const ParseToken *t = &tokenlist->list[i++]; token->type = t->type; token->objPtr = JimMakeScriptObj(interp, t); Jim_IncrRefCount(token->objPtr); /* Every object is initially a string of type 'source', but the * internal type may be specialized during execution of the * script. */ JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); token++; } } if (lineargs == 0) { token--; } script->len = token - script->token; JimPanic((script->len >= count, "allocated script array is too short")); #ifdef DEBUG_SHOW_SCRIPT printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); for (i = 0; i < script->len; i++) { const ScriptToken *t = &script->token[i]; printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); } #endif } /** * Sets an appropriate error message for a missing script/expression terminator. * * Returns JIM_ERR if 'ch' represents an unmatched/missing character. * * Note that a trailing backslash is not considered to be an error. */ static int JimParseCheckMissing(Jim_Interp *interp, int ch) { const char *msg; switch (ch) { case '\\': case ' ': return JIM_OK; case '[': msg = "unmatched \"[\""; break; case '{': msg = "missing close-brace"; break; case '"': default: msg = "missing quote"; break; } Jim_SetResultString(interp, msg, -1); return JIM_ERR; } /** * Similar to ScriptObjAddTokens(), but for subst objects. */ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, ParseTokenList *tokenlist) { int i; struct ScriptToken *token; token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); for (i = 0; i < tokenlist->count; i++) { const ParseToken *t = &tokenlist->list[i]; /* Create a token for 't' */ token->type = t->type; token->objPtr = JimMakeScriptObj(interp, t); Jim_IncrRefCount(token->objPtr); token++; } script->len = i; } /* This method takes the string representation of an object * as a Tcl script, and generates the pre-parsed internal representation * of the script. * * On parse error, sets an error message and returns JIM_ERR * (Note: the object is still converted to a script, even if an error occurs) */ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { int scriptTextLen; const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); struct JimParserCtx parser; struct ScriptObj *script; ParseTokenList tokenlist; int line = 1; /* Try to get information about filename / line number */ if (objPtr->typePtr == &sourceObjType) { line = objPtr->internalRep.sourceValue.lineNumber; } /* Initially parse the script into tokens (in tokenlist) */ ScriptTokenListInit(&tokenlist); JimParserInit(&parser, scriptText, scriptTextLen, line); while (!parser.eof) { JimParseScript(&parser); ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, parser.tline); } /* Add a final EOF token */ ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); /* Create the "real" script tokens from the parsed tokens */ script = Jim_Alloc(sizeof(*script)); memset(script, 0, sizeof(*script)); script->inUse = 1; if (objPtr->typePtr == &sourceObjType) { script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; } else { script->fileNameObj = interp->emptyObj; } Jim_IncrRefCount(script->fileNameObj); script->missing = parser.missing.ch; script->linenr = parser.missing.line; ScriptObjAddTokens(interp, script, &tokenlist); /* No longer need the token list */ ScriptTokenListFree(&tokenlist); /* Free the old internal rep and set the new one. */ Jim_FreeIntRep(interp, objPtr); Jim_SetIntRepPtr(objPtr, script); objPtr->typePtr = &scriptObjType; } static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); /** * Returns the parsed script. * Note that if there is any possibility that the script is not valid, * call JimScriptValid() to check */ ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr == interp->emptyObj) { /* Avoid converting emptyObj to a script. use nullScriptObj instead. */ objPtr = interp->nullScriptObj; } if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { JimSetScriptFromAny(interp, objPtr); } return (ScriptObj *)Jim_GetIntRepPtr(objPtr); } /** * Returns 1 if the script is valid (parsed ok), otherwise returns 0 * and leaves an error message in the interp result. * */ static int JimScriptValid(Jim_Interp *interp, ScriptObj *script) { if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) { JimAddErrorToStack(interp, script); return 0; } return 1; } /* ----------------------------------------------------------------------------- * Commands * ---------------------------------------------------------------------------*/ static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) { cmdPtr->inUse++; } static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr) { if (--cmdPtr->inUse == 0) { if (cmdPtr->isproc) { Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr); Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr); Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); if (cmdPtr->u.proc.staticVars) { Jim_FreeHashTable(cmdPtr->u.proc.staticVars); Jim_Free(cmdPtr->u.proc.staticVars); } } else { /* native (C) */ if (cmdPtr->u.native.delProc) { cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); } } if (cmdPtr->prevCmd) { /* Delete any pushed command too */ JimDecrCmdRefCount(interp, cmdPtr->prevCmd); } Jim_Free(cmdPtr); } } /* Variables HashTable Type. * * Keys are dynamically allocated strings, Values are Jim_Var structures. */ /* Variables HashTable Type. * * Keys are dynamic allocated strings, Values are Jim_Var structures. */ static void JimVariablesHTValDestructor(void *interp, void *val) { Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); Jim_Free(val); } static const Jim_HashTableType JimVariablesHashTableType = { JimStringCopyHTHashFunction, /* hash function */ JimStringCopyHTDup, /* key dup */ NULL, /* val dup */ JimStringCopyHTKeyCompare, /* key compare */ JimStringCopyHTKeyDestructor, /* key destructor */ JimVariablesHTValDestructor /* val destructor */ }; /* Commands HashTable Type. * * Keys are dynamic allocated strings, Values are Jim_Cmd structures. */ static void JimCommandsHT_ValDestructor(void *interp, void *val) { JimDecrCmdRefCount(interp, val); } static const Jim_HashTableType JimCommandsHashTableType = { JimStringCopyHTHashFunction, /* hash function */ JimStringCopyHTDup, /* key dup */ NULL, /* val dup */ JimStringCopyHTKeyCompare, /* key compare */ JimStringCopyHTKeyDestructor, /* key destructor */ JimCommandsHT_ValDestructor /* val destructor */ }; /* ------------------------- Commands related functions --------------------- */ #ifdef jim_ext_namespace /** * Returns the "unscoped" version of the given namespace. * That is, the fully qualfied name without the leading :: * The returned value is either nsObj, or an object with a zero ref count. */ static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) { const char *name = Jim_String(nsObj); if (name[0] == ':' && name[1] == ':') { /* This command is being defined in the global namespace */ while (*++name == ':') { } nsObj = Jim_NewStringObj(interp, name, -1); } else if (Jim_Length(interp->framePtr->nsObj)) { /* This command is being defined in a non-global namespace */ nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); Jim_AppendStrings(interp, nsObj, "::", name, NULL); } return nsObj; } Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) { Jim_Obj *resultObj; const char *name = Jim_String(nameObjPtr); if (name[0] == ':' && name[1] == ':') { return nameObjPtr; } Jim_IncrRefCount(nameObjPtr); resultObj = Jim_NewStringObj(interp, "::", -1); Jim_AppendObj(interp, resultObj, nameObjPtr); Jim_DecrRefCount(interp, nameObjPtr); return resultObj; } /** * An efficient version of JimQualifyNameObj() where the name is * available (and needed) as a 'const char *'. * Avoids creating an object if not necessary. * The object stored in *objPtrPtr should be disposed of with JimFreeQualifiedName() after use. */ static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) { Jim_Obj *objPtr = interp->emptyObj; if (name[0] == ':' && name[1] == ':') { /* This command is being defined in the global namespace */ while (*++name == ':') { } } else if (Jim_Length(interp->framePtr->nsObj)) { /* This command is being defined in a non-global namespace */ objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); Jim_AppendStrings(interp, objPtr, "::", name, NULL); name = Jim_String(objPtr); } Jim_IncrRefCount(objPtr); *objPtrPtr = objPtr; return name; } #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) #else /* We can be more efficient in the no-namespace case */ #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) { return nameObjPtr; } #endif static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) { /* It may already exist, so we try to delete the old one. * Note that reference count means that it won't be deleted yet if * it exists in the call stack. * * BUT, if 'local' is in force, instead of deleting the existing * proc, we stash a reference to the old proc here. */ Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); if (he) { /* There was an old cmd with the same name, * so this requires a 'proc epoch' update. */ /* If a procedure with the same name didn't exist there is no need * to increment the 'proc epoch' because creation of a new procedure * can never affect existing cached commands. We don't do * negative caching. */ Jim_InterpIncrProcEpoch(interp); } if (he && interp->local) { /* Push this command over the top of the previous one */ cmd->prevCmd = Jim_GetHashEntryVal(he); Jim_SetHashVal(&interp->commands, he, cmd); } else { if (he) { /* Replace the existing command */ Jim_DeleteHashEntry(&interp->commands, name); } Jim_AddHashEntry(&interp->commands, name, cmd); } return JIM_OK; } int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc) { Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); /* Store the new details for this command */ memset(cmdPtr, 0, sizeof(*cmdPtr)); cmdPtr->inUse = 1; cmdPtr->u.native.delProc = delProc; cmdPtr->u.native.cmdProc = cmdProc; cmdPtr->u.native.privData = privData; JimCreateCommand(interp, cmdNameStr, cmdPtr); return JIM_OK; } static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr) { int len, i; len = Jim_ListLength(interp, staticsListObjPtr); if (len == 0) { return JIM_OK; } cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); for (i = 0; i < len; i++) { Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; Jim_Var *varPtr; int subLen; objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); /* Check if it's composed of two elements. */ subLen = Jim_ListLength(interp, objPtr); if (subLen == 1 || subLen == 2) { /* Try to get the variable value from the current * environment. */ nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); if (subLen == 1) { initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); if (initObjPtr == NULL) { Jim_SetResultFormatted(interp, "variable for initialization of static \"%#s\" not found in the local context", nameObjPtr); return JIM_ERR; } } else { initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); } if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { return JIM_ERR; } varPtr = Jim_Alloc(sizeof(*varPtr)); varPtr->objPtr = initObjPtr; Jim_IncrRefCount(initObjPtr); varPtr->linkFramePtr = NULL; if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars, Jim_String(nameObjPtr), varPtr) != JIM_OK) { Jim_SetResultFormatted(interp, "static variable name \"%#s\" duplicated in statics list", nameObjPtr); Jim_DecrRefCount(interp, initObjPtr); Jim_Free(varPtr); return JIM_ERR; } } else { Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"", objPtr); return JIM_ERR; } } return JIM_OK; } static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) { #ifdef jim_ext_namespace if (cmdPtr->isproc) { /* XXX: Really need JimNamespaceSplit() */ const char *pt = strrchr(cmdname, ':'); if (pt && pt != cmdname && pt[-1] == ':') { Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); Jim_IncrRefCount(cmdPtr->u.proc.nsObj); if (Jim_FindHashEntry(&interp->commands, pt + 1)) { /* This commands shadows a global command, so a proc epoch update is required */ Jim_InterpIncrProcEpoch(interp); } } } #endif } static Jim_Cmd *JimCreateProcedureCmd(Jim_Interp *interp, Jim_Obj *argListObjPtr, Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr, Jim_Obj *nsObj) { Jim_Cmd *cmdPtr; int argListLen; int i; argListLen = Jim_ListLength(interp, argListObjPtr); /* Allocate space for both the command pointer and the arg list */ cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); memset(cmdPtr, 0, sizeof(*cmdPtr)); cmdPtr->inUse = 1; cmdPtr->isproc = 1; cmdPtr->u.proc.argListObjPtr = argListObjPtr; cmdPtr->u.proc.argListLen = argListLen; cmdPtr->u.proc.bodyObjPtr = bodyObjPtr; cmdPtr->u.proc.argsPos = -1; cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1); cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj; Jim_IncrRefCount(argListObjPtr); Jim_IncrRefCount(bodyObjPtr); Jim_IncrRefCount(cmdPtr->u.proc.nsObj); /* Create the statics hash table. */ if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) { goto err; } /* Parse the args out into arglist, validating as we go */ /* Examine the argument list for default parameters and 'args' */ for (i = 0; i < argListLen; i++) { Jim_Obj *argPtr; Jim_Obj *nameObjPtr; Jim_Obj *defaultObjPtr; int len; /* Examine a parameter */ argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); len = Jim_ListLength(interp, argPtr); if (len == 0) { Jim_SetResultString(interp, "argument with no name", -1); err: JimDecrCmdRefCount(interp, cmdPtr); return NULL; } if (len > 2) { Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr); goto err; } if (len == 2) { /* Optional parameter */ nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); } else { /* Required parameter */ nameObjPtr = argPtr; defaultObjPtr = NULL; } if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) { if (cmdPtr->u.proc.argsPos >= 0) { Jim_SetResultString(interp, "'args' specified more than once", -1); goto err; } cmdPtr->u.proc.argsPos = i; } else { if (len == 2) { cmdPtr->u.proc.optArity++; } else { cmdPtr->u.proc.reqArity++; } } cmdPtr->u.proc.arglist[i].nameObjPtr = nameObjPtr; cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr; } return cmdPtr; } int Jim_DeleteCommand(Jim_Interp *interp, const char *name) { int ret = JIM_OK; Jim_Obj *qualifiedNameObj; const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj); if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) { Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name); ret = JIM_ERR; } else { Jim_InterpIncrProcEpoch(interp); } JimFreeQualifiedName(interp, qualifiedNameObj); return ret; } int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName) { int ret = JIM_ERR; Jim_HashEntry *he; Jim_Cmd *cmdPtr; Jim_Obj *qualifiedOldNameObj; Jim_Obj *qualifiedNewNameObj; const char *fqold; const char *fqnew; if (newName[0] == 0) { return Jim_DeleteCommand(interp, oldName); } fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); /* Does it exist? */ he = Jim_FindHashEntry(&interp->commands, fqold); if (he == NULL) { Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); } else if (Jim_FindHashEntry(&interp->commands, fqnew)) { Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); } else { /* Add the new name first */ cmdPtr = Jim_GetHashEntryVal(he); JimIncrCmdRefCount(cmdPtr); JimUpdateProcNamespace(interp, cmdPtr, fqnew); Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); /* Now remove the old name */ Jim_DeleteHashEntry(&interp->commands, fqold); /* Increment the epoch */ Jim_InterpIncrProcEpoch(interp); ret = JIM_OK; } JimFreeQualifiedName(interp, qualifiedOldNameObj); JimFreeQualifiedName(interp, qualifiedNewNameObj); return ret; } /* ----------------------------------------------------------------------------- * Command object * ---------------------------------------------------------------------------*/ static void FreeCommandInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.cmdValue.nsObj); } static void DupCommandInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { dupPtr->internalRep.cmdValue = srcPtr->internalRep.cmdValue; dupPtr->typePtr = srcPtr->typePtr; Jim_IncrRefCount(dupPtr->internalRep.cmdValue.nsObj); } static const Jim_ObjType commandObjType = { "command", FreeCommandInternalRep, DupCommandInternalRep, NULL, JIM_TYPE_REFERENCES, }; /* This function returns the command structure for the command name * stored in objPtr. It tries to specialize the objPtr to contain * a cached info instead to perform the lookup into the hash table * every time. The information cached may not be uptodate, in such * a case the lookup is performed and the cache updated. * * Respects the 'upcall' setting */ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { Jim_Cmd *cmd; /* In order to be valid, the proc epoch must match and * the lookup must have occurred in the same namespace */ if (objPtr->typePtr != &commandObjType || objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch #ifdef jim_ext_namespace || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) #endif ) { /* Not cached or out of date, so lookup */ /* Do we need to try the local namespace? */ const char *name = Jim_String(objPtr); Jim_HashEntry *he; if (name[0] == ':' && name[1] == ':') { while (*++name == ':') { } } #ifdef jim_ext_namespace else if (Jim_Length(interp->framePtr->nsObj)) { /* This command is being defined in a non-global namespace */ Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); Jim_AppendStrings(interp, nameObj, "::", name, NULL); he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); Jim_FreeNewObj(interp, nameObj); if (he) { goto found; } } #endif /* Lookup in the global namespace */ he = Jim_FindHashEntry(&interp->commands, name); if (he == NULL) { if (flags & JIM_ERRMSG) { Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); } return NULL; } #ifdef jim_ext_namespace found: #endif cmd = Jim_GetHashEntryVal(he); /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &commandObjType; objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; objPtr->internalRep.cmdValue.cmdPtr = cmd; objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; Jim_IncrRefCount(interp->framePtr->nsObj); } else { cmd = objPtr->internalRep.cmdValue.cmdPtr; } while (cmd->u.proc.upcall) { cmd = cmd->prevCmd; } return cmd; } /* ----------------------------------------------------------------------------- * Variables * ---------------------------------------------------------------------------*/ /* ----------------------------------------------------------------------------- * Variable object * ---------------------------------------------------------------------------*/ #define JIM_DICT_SUGAR 100 /* Only returned by SetVariableFromAny() */ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static const Jim_ObjType variableObjType = { "variable", NULL, NULL, NULL, JIM_TYPE_REFERENCES, }; /** * Check that the name does not contain embedded nulls. * * Variable and procedure names are maniplated as null terminated strings, so * don't allow names with embedded nulls. */ static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) { /* Variable names and proc names can't contain embedded nulls */ if (nameObjPtr->typePtr != &variableObjType) { int len; const char *str = Jim_GetString(nameObjPtr, &len); if (memchr(str, '\0', len)) { Jim_SetResultFormatted(interp, "%s name contains embedded null", type); return JIM_ERR; } } return JIM_OK; } /* This method should be called only by the variable API. * It returns JIM_OK on success (variable already exists), * JIM_ERR if it does not exists, JIM_DICT_SUGAR if it's not * a variable name, but syntax glue for [dict] i.e. the last * character is ')' */ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { const char *varName; Jim_CallFrame *framePtr; Jim_HashEntry *he; int global; int len; /* Check if the object is already an uptodate variable */ if (objPtr->typePtr == &variableObjType) { framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { /* nothing to do */ return JIM_OK; } /* Need to re-resolve the variable in the updated callframe */ } else if (objPtr->typePtr == &dictSubstObjType) { return JIM_DICT_SUGAR; } else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { return JIM_ERR; } varName = Jim_GetString(objPtr, &len); /* Make sure it's not syntax glue to get/set dict. */ if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { return JIM_DICT_SUGAR; } if (varName[0] == ':' && varName[1] == ':') { while (*++varName == ':') { } global = 1; framePtr = interp->topFramePtr; } else { global = 0; framePtr = interp->framePtr; } /* Resolve this name in the variables hash table */ he = Jim_FindHashEntry(&framePtr->vars, varName); if (he == NULL) { if (!global && framePtr->staticVars) { /* Try with static vars. */ he = Jim_FindHashEntry(framePtr->staticVars, varName); } if (he == NULL) { return JIM_ERR; } } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &variableObjType; objPtr->internalRep.varValue.callFrameId = framePtr->id; objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); objPtr->internalRep.varValue.global = global; return JIM_OK; } /* -------------------- Variables related functions ------------------------- */ static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr); static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags); static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) { const char *name; Jim_CallFrame *framePtr; int global; /* New variable to create */ Jim_Var *var = Jim_Alloc(sizeof(*var)); var->objPtr = valObjPtr; Jim_IncrRefCount(valObjPtr); var->linkFramePtr = NULL; name = Jim_String(nameObjPtr); if (name[0] == ':' && name[1] == ':') { while (*++name == ':') { } framePtr = interp->topFramePtr; global = 1; } else { framePtr = interp->framePtr; global = 0; } /* Insert the new variable */ Jim_AddHashEntry(&framePtr->vars, name, var); /* Make the object int rep a variable */ Jim_FreeIntRep(interp, nameObjPtr); nameObjPtr->typePtr = &variableObjType; nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; nameObjPtr->internalRep.varValue.varPtr = var; nameObjPtr->internalRep.varValue.global = global; return var; } /* For now that's dummy. Variables lookup should be optimized * in many ways, with caching of lookups, and possibly with * a table of pre-allocated vars in every CallFrame for local vars. * All the caching should also have an 'epoch' mechanism similar * to the one used by Tcl for procedures lookup caching. */ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) { int err; Jim_Var *var; switch (SetVariableFromAny(interp, nameObjPtr)) { case JIM_DICT_SUGAR: return JimDictSugarSet(interp, nameObjPtr, valObjPtr); case JIM_ERR: if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) { return JIM_ERR; } JimCreateVariable(interp, nameObjPtr, valObjPtr); break; case JIM_OK: var = nameObjPtr->internalRep.varValue.varPtr; if (var->linkFramePtr == NULL) { Jim_IncrRefCount(valObjPtr); Jim_DecrRefCount(interp, var->objPtr); var->objPtr = valObjPtr; } else { /* Else handle the link */ Jim_CallFrame *savedCallFrame; savedCallFrame = interp->framePtr; interp->framePtr = var->linkFramePtr; err = Jim_SetVariable(interp, var->objPtr, valObjPtr); interp->framePtr = savedCallFrame; if (err != JIM_OK) return err; } } return JIM_OK; } int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) { Jim_Obj *nameObjPtr; int result; nameObjPtr = Jim_NewStringObj(interp, name, -1); Jim_IncrRefCount(nameObjPtr); result = Jim_SetVariable(interp, nameObjPtr, objPtr); Jim_DecrRefCount(interp, nameObjPtr); return result; } int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) { Jim_CallFrame *savedFramePtr; int result; savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; result = Jim_SetVariableStr(interp, name, objPtr); interp->framePtr = savedFramePtr; return result; } int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) { Jim_Obj *nameObjPtr, *valObjPtr; int result; nameObjPtr = Jim_NewStringObj(interp, name, -1); valObjPtr = Jim_NewStringObj(interp, val, -1); Jim_IncrRefCount(nameObjPtr); Jim_IncrRefCount(valObjPtr); result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); Jim_DecrRefCount(interp, nameObjPtr); Jim_DecrRefCount(interp, valObjPtr); return result; } int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) { const char *varName; const char *targetName; Jim_CallFrame *framePtr; Jim_Var *varPtr; /* Check for an existing variable or link */ switch (SetVariableFromAny(interp, nameObjPtr)) { case JIM_DICT_SUGAR: /* XXX: This message seem unnecessarily verbose, but it matches Tcl */ Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); return JIM_ERR; case JIM_OK: varPtr = nameObjPtr->internalRep.varValue.varPtr; if (varPtr->linkFramePtr == NULL) { Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); return JIM_ERR; } /* It exists, but is a link, so first delete the link */ varPtr->linkFramePtr = NULL; break; } /* Resolve the call frames for both variables */ /* XXX: SetVariableFromAny() already did this! */ varName = Jim_String(nameObjPtr); if (varName[0] == ':' && varName[1] == ':') { while (*++varName == ':') { } /* Linking a global var does nothing */ framePtr = interp->topFramePtr; } else { framePtr = interp->framePtr; } targetName = Jim_String(targetNameObjPtr); if (targetName[0] == ':' && targetName[1] == ':') { while (*++targetName == ':') { } targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1); targetCallFrame = interp->topFramePtr; } Jim_IncrRefCount(targetNameObjPtr); if (framePtr->level < targetCallFrame->level) { Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create namespace variable that refers to procedure variable", nameObjPtr); Jim_DecrRefCount(interp, targetNameObjPtr); return JIM_ERR; } /* Check for cycles. */ if (framePtr == targetCallFrame) { Jim_Obj *objPtr = targetNameObjPtr; /* Cycles are only possible with 'uplevel 0' */ while (1) { if (strcmp(Jim_String(objPtr), varName) == 0) { Jim_SetResultString(interp, "can't upvar from variable to itself", -1); Jim_DecrRefCount(interp, targetNameObjPtr); return JIM_ERR; } if (SetVariableFromAny(interp, objPtr) != JIM_OK) break; varPtr = objPtr->internalRep.varValue.varPtr; if (varPtr->linkFramePtr != targetCallFrame) break; objPtr = varPtr->objPtr; } } /* Perform the binding */ Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); /* We are now sure 'nameObjPtr' type is variableObjType */ nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; Jim_DecrRefCount(interp, targetNameObjPtr); return JIM_OK; } /* Return the Jim_Obj pointer associated with a variable name, * or NULL if the variable was not found in the current context. * The same optimization discussed in the comment to the * 'SetVariable' function should apply here. * * If JIM_UNSHARED is set and the variable is an array element (dict sugar) * in a dictionary which is shared, the array variable value is duplicated first. * This allows the array element to be updated (e.g. append, lappend) without * affecting other references to the dictionary. */ Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) { switch (SetVariableFromAny(interp, nameObjPtr)) { case JIM_OK:{ Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; if (varPtr->linkFramePtr == NULL) { return varPtr->objPtr; } else { Jim_Obj *objPtr; /* The variable is a link? Resolve it. */ Jim_CallFrame *savedCallFrame = interp->framePtr; interp->framePtr = varPtr->linkFramePtr; objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); interp->framePtr = savedCallFrame; if (objPtr) { return objPtr; } /* Error, so fall through to the error message */ } } break; case JIM_DICT_SUGAR: /* [dict] syntax sugar. */ return JimDictSugarGet(interp, nameObjPtr, flags); } if (flags & JIM_ERRMSG) { Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); } return NULL; } Jim_Obj *Jim_GetGlobalVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) { Jim_CallFrame *savedFramePtr; Jim_Obj *objPtr; savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; objPtr = Jim_GetVariable(interp, nameObjPtr, flags); interp->framePtr = savedFramePtr; return objPtr; } Jim_Obj *Jim_GetVariableStr(Jim_Interp *interp, const char *name, int flags) { Jim_Obj *nameObjPtr, *varObjPtr; nameObjPtr = Jim_NewStringObj(interp, name, -1); Jim_IncrRefCount(nameObjPtr); varObjPtr = Jim_GetVariable(interp, nameObjPtr, flags); Jim_DecrRefCount(interp, nameObjPtr); return varObjPtr; } Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flags) { Jim_CallFrame *savedFramePtr; Jim_Obj *objPtr; savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; objPtr = Jim_GetVariableStr(interp, name, flags); interp->framePtr = savedFramePtr; return objPtr; } /* Unset a variable. * Note: On success unset invalidates all the variable objects created * in the current call frame incrementing. */ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) { Jim_Var *varPtr; int retval; Jim_CallFrame *framePtr; retval = SetVariableFromAny(interp, nameObjPtr); if (retval == JIM_DICT_SUGAR) { /* [dict] syntax sugar. */ return JimDictSugarSet(interp, nameObjPtr, NULL); } else if (retval == JIM_OK) { varPtr = nameObjPtr->internalRep.varValue.varPtr; /* If it's a link call UnsetVariable recursively */ if (varPtr->linkFramePtr) { framePtr = interp->framePtr; interp->framePtr = varPtr->linkFramePtr; retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); interp->framePtr = framePtr; } else { const char *name = Jim_String(nameObjPtr); if (nameObjPtr->internalRep.varValue.global) { name += 2; framePtr = interp->topFramePtr; } else { framePtr = interp->framePtr; } retval = Jim_DeleteHashEntry(&framePtr->vars, name); if (retval == JIM_OK) { /* Change the callframe id, invalidating var lookup caching */ framePtr->id = interp->callFrameEpoch++; } } } if (retval != JIM_OK && (flags & JIM_ERRMSG)) { Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); } return retval; } /* ---------- Dict syntax sugar (similar to array Tcl syntax) -------------- */ /* Given a variable name for [dict] operation syntax sugar, * this function returns two objects, the first with the name * of the variable to set, and the second with the rispective key. * For example "foo(bar)" will return objects with string repr. of * "foo" and "bar". * * The returned objects have refcount = 1. The function can't fail. */ static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr) { const char *str, *p; int len, keyLen; Jim_Obj *varObjPtr, *keyObjPtr; str = Jim_GetString(objPtr, &len); p = strchr(str, '('); JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str)); varObjPtr = Jim_NewStringObj(interp, str, p - str); p++; keyLen = (str + len) - p; if (str[len - 1] == ')') { keyLen--; } /* Create the objects with the variable name and key. */ keyObjPtr = Jim_NewStringObj(interp, p, keyLen); Jim_IncrRefCount(varObjPtr); Jim_IncrRefCount(keyObjPtr); *varPtrPtr = varObjPtr; *keyPtrPtr = keyObjPtr; } /* Helper of Jim_SetVariable() to deal with dict-syntax variable names. * Also used by Jim_UnsetVariable() with valObjPtr = NULL. */ static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr) { int err; SetDictSubstFromAny(interp, objPtr); err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST); if (err == JIM_OK) { /* Don't keep an extra ref to the result */ Jim_SetEmptyResult(interp); } else { if (!valObjPtr) { /* Better error message for unset a(2) where a exists but a(2) doesn't */ if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", objPtr); return err; } } /* Make the error more informative and Tcl-compatible */ Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", (valObjPtr ? "set" : "unset"), objPtr); } return err; } /** * Expands the array variable (dict sugar) and returns the result, or NULL on error. * * If JIM_UNSHARED is set and the dictionary is shared, it will be duplicated * and stored back to the variable before expansion. */ static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr, Jim_Obj *keyObjPtr, int flags) { Jim_Obj *dictObjPtr; Jim_Obj *resObjPtr = NULL; int ret; dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG); if (!dictObjPtr) { return NULL; } ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); if (ret != JIM_OK) { Jim_SetResultFormatted(interp, "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, ret < 0 ? "variable isn't" : "no such element in"); } else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { /* Update the variable to have an unshared copy */ Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); } return resObjPtr; } /* Helper of Jim_GetVariable() to deal with dict-syntax variable names */ static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { SetDictSubstFromAny(interp, objPtr); return JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, objPtr->internalRep.dictSubstValue.indexObjPtr, flags); } /* --------- $var(INDEX) substitution, using a specialized object ----------- */ void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); } void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { JIM_NOTUSED(interp); dupPtr->internalRep.dictSubstValue.varNameObjPtr = srcPtr->internalRep.dictSubstValue.varNameObjPtr; dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; dupPtr->typePtr = &dictSubstObjType; } /* Note: The object *must* be in dict-sugar format */ static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &dictSubstObjType) { Jim_Obj *varObjPtr, *keyObjPtr; if (objPtr->typePtr == &interpolatedObjType) { /* An interpolated object in dict-sugar form */ varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr; keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr; Jim_IncrRefCount(varObjPtr); Jim_IncrRefCount(keyObjPtr); } else { JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr); } Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &dictSubstObjType; objPtr->internalRep.dictSubstValue.varNameObjPtr = varObjPtr; objPtr->internalRep.dictSubstValue.indexObjPtr = keyObjPtr; } } /* This function is used to expand [dict get] sugar in the form * of $var(INDEX). The function is mainly used by Jim_EvalObj() * to deal with tokens of type JIM_TT_DICTSUGAR. objPtr points to an * object that is *guaranteed* to be in the form VARNAME(INDEX). * The 'index' part is [subst]ituted, and is used to lookup a key inside * the [dict]ionary contained in variable VARNAME. */ static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_Obj *resObjPtr = NULL; Jim_Obj *substKeyObjPtr = NULL; SetDictSubstFromAny(interp, objPtr); if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr, &substKeyObjPtr, JIM_NONE) != JIM_OK) { return NULL; } Jim_IncrRefCount(substKeyObjPtr); resObjPtr = JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, substKeyObjPtr, 0); Jim_DecrRefCount(interp, substKeyObjPtr); return resObjPtr; } static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_Obj *resultObjPtr; if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { /* Note that the result has a ref count of 1, but we need a ref count of 0 */ resultObjPtr->refCount--; return resultObjPtr; } return NULL; } /* ----------------------------------------------------------------------------- * CallFrame * ---------------------------------------------------------------------------*/ static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj) { Jim_CallFrame *cf; if (interp->freeFramesList) { cf = interp->freeFramesList; interp->freeFramesList = cf->next; cf->argv = NULL; cf->argc = 0; cf->procArgsObjPtr = NULL; cf->procBodyObjPtr = NULL; cf->next = NULL; cf->staticVars = NULL; cf->localCommands = NULL; cf->tailcall = 0; cf->tailcallObj = NULL; cf->tailcallCmd = NULL; } else { cf = Jim_Alloc(sizeof(*cf)); memset(cf, 0, sizeof(*cf)); Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); } cf->id = interp->callFrameEpoch++; cf->parent = parent; cf->level = parent ? parent->level + 1 : 0; cf->nsObj = nsObj; Jim_IncrRefCount(nsObj); return cf; } static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) { /* Delete any local procs */ if (localCommands) { Jim_Obj *cmdNameObj; while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { Jim_HashEntry *he; Jim_Obj *fqObjName; Jim_HashTable *ht = &interp->commands; const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); he = Jim_FindHashEntry(ht, fqname); if (he) { Jim_Cmd *cmd = Jim_GetHashEntryVal(he); if (cmd->prevCmd) { Jim_Cmd *prevCmd = cmd->prevCmd; cmd->prevCmd = NULL; /* Delete the old command */ JimDecrCmdRefCount(interp, cmd); /* And restore the original */ Jim_SetHashVal(ht, he, prevCmd); } else { Jim_DeleteHashEntry(ht, fqname); Jim_InterpIncrProcEpoch(interp); } } Jim_DecrRefCount(interp, cmdNameObj); JimFreeQualifiedName(interp, fqObjName); } Jim_FreeStack(localCommands); Jim_Free(localCommands); } return JIM_OK; } #define JIM_FCF_FULL 0 /* Always free the vars hash table */ #define JIM_FCF_REUSE 1 /* Reuse the vars hash table if possible */ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) { JimDeleteLocalProcs(interp, cf->localCommands); if (cf->procArgsObjPtr) Jim_DecrRefCount(interp, cf->procArgsObjPtr); if (cf->procBodyObjPtr) Jim_DecrRefCount(interp, cf->procBodyObjPtr); Jim_DecrRefCount(interp, cf->nsObj); if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) Jim_FreeHashTable(&cf->vars); else { int i; Jim_HashEntry **table = cf->vars.table, *he; for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { he = table[i]; while (he != NULL) { Jim_HashEntry *nextEntry = he->next; Jim_Var *varPtr = Jim_GetHashEntryVal(he); Jim_DecrRefCount(interp, varPtr->objPtr); Jim_Free(Jim_GetHashEntryKey(he)); Jim_Free(varPtr); Jim_Free(he); table[i] = NULL; he = nextEntry; } } cf->vars.used = 0; } cf->next = interp->freeFramesList; interp->freeFramesList = cf; } /* ----------------------------------------------------------------------------- * References * ---------------------------------------------------------------------------*/ #ifdef JIM_REFERENCES /* References HashTable Type. * * Keys are unsigned long integers, dynamically allocated for now but in the * future it's worth to cache this 4 bytes objects. Values are pointers * to Jim_References. */ static void JimReferencesHTValDestructor(void *interp, void *val) { Jim_Reference *refPtr = (void *)val; Jim_DecrRefCount(interp, refPtr->objPtr); if (refPtr->finalizerCmdNamePtr != NULL) { Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); } Jim_Free(val); } static unsigned int JimReferencesHTHashFunction(const void *key) { /* Only the least significant bits are used. */ const unsigned long *widePtr = key; unsigned int intValue = (unsigned int)*widePtr; return Jim_IntHashFunction(intValue); } static void *JimReferencesHTKeyDup(void *privdata, const void *key) { void *copy = Jim_Alloc(sizeof(unsigned long)); JIM_NOTUSED(privdata); memcpy(copy, key, sizeof(unsigned long)); return copy; } static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) { JIM_NOTUSED(privdata); return memcmp(key1, key2, sizeof(unsigned long)) == 0; } static void JimReferencesHTKeyDestructor(void *privdata, void *key) { JIM_NOTUSED(privdata); Jim_Free(key); } static const Jim_HashTableType JimReferencesHashTableType = { JimReferencesHTHashFunction, /* hash function */ JimReferencesHTKeyDup, /* key dup */ NULL, /* val dup */ JimReferencesHTKeyCompare, /* key compare */ JimReferencesHTKeyDestructor, /* key destructor */ JimReferencesHTValDestructor /* val destructor */ }; /* ----------------------------------------------------------------------------- * Reference object type and References API * ---------------------------------------------------------------------------*/ /* The string representation of references has two features in order * to make the GC faster. The first is that every reference starts * with a non common character '<', in order to make the string matching * faster. The second is that the reference string rep is 42 characters * in length, this means that it is not necessary to check any object with a string * repr < 42, and usually there aren't many of these objects. */ #define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id) { const char *fmt = ".%020lu>"; sprintf(buf, fmt, refPtr->tag, id); return JIM_REFERENCE_SPACE; } static void UpdateStringOfReference(struct Jim_Obj *objPtr); static const Jim_ObjType referenceObjType = { "reference", NULL, NULL, UpdateStringOfReference, JIM_TYPE_REFERENCES, }; static void UpdateStringOfReference(struct Jim_Obj *objPtr) { char buf[JIM_REFERENCE_SPACE + 1]; JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); JimSetStringBytes(objPtr, buf); } /* returns true if 'c' is a valid reference tag character. * i.e. inside the range [_a-zA-Z0-9] */ static int isrefchar(int c) { return (c == '_' || isalnum(c)); } static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { unsigned long value; int i, len; const char *str, *start, *end; char refId[21]; Jim_Reference *refPtr; Jim_HashEntry *he; char *endptr; /* Get the string representation */ str = Jim_GetString(objPtr, &len); /* Check if it looks like a reference */ if (len < JIM_REFERENCE_SPACE) goto badformat; /* Trim spaces */ start = str; end = str + len - 1; while (*start == ' ') start++; while (*end == ' ' && end > start) end--; if (end - start + 1 != JIM_REFERENCE_SPACE) goto badformat; /* .%020> */ if (memcmp(start, "references, &value); if (he == NULL) { Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); return JIM_ERR; } refPtr = Jim_GetHashEntryVal(he); /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &referenceObjType; objPtr->internalRep.refValue.id = value; objPtr->internalRep.refValue.refPtr = refPtr; return JIM_OK; badformat: Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); return JIM_ERR; } /* Returns a new reference pointing to objPtr, having cmdNamePtr * as finalizer command (or NULL if there is no finalizer). * The returned reference object has refcount = 0. */ Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) { struct Jim_Reference *refPtr; unsigned long id; Jim_Obj *refObjPtr; const char *tag; int tagLen, i; /* Perform the Garbage Collection if needed. */ Jim_CollectIfNeeded(interp); refPtr = Jim_Alloc(sizeof(*refPtr)); refPtr->objPtr = objPtr; Jim_IncrRefCount(objPtr); refPtr->finalizerCmdNamePtr = cmdNamePtr; if (cmdNamePtr) Jim_IncrRefCount(cmdNamePtr); id = interp->referenceNextId++; Jim_AddHashEntry(&interp->references, &id, refPtr); refObjPtr = Jim_NewObj(interp); refObjPtr->typePtr = &referenceObjType; refObjPtr->bytes = NULL; refObjPtr->internalRep.refValue.id = id; refObjPtr->internalRep.refValue.refPtr = refPtr; interp->referenceNextId++; /* Set the tag. Trimmed at JIM_REFERENCE_TAGLEN. Everything * that does not pass the 'isrefchar' test is replaced with '_' */ tag = Jim_GetString(tagPtr, &tagLen); if (tagLen > JIM_REFERENCE_TAGLEN) tagLen = JIM_REFERENCE_TAGLEN; for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { if (i < tagLen && isrefchar(tag[i])) refPtr->tag[i] = tag[i]; else refPtr->tag[i] = '_'; } refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; return refObjPtr; } Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) return NULL; return objPtr->internalRep.refValue.refPtr; } int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) { Jim_Reference *refPtr; if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) return JIM_ERR; Jim_IncrRefCount(cmdNamePtr); if (refPtr->finalizerCmdNamePtr) Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); refPtr->finalizerCmdNamePtr = cmdNamePtr; return JIM_OK; } int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) { Jim_Reference *refPtr; if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) return JIM_ERR; *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; return JIM_OK; } /* ----------------------------------------------------------------------------- * References Garbage Collection * ---------------------------------------------------------------------------*/ /* This the hash table type for the "MARK" phase of the GC */ static const Jim_HashTableType JimRefMarkHashTableType = { JimReferencesHTHashFunction, /* hash function */ JimReferencesHTKeyDup, /* key dup */ NULL, /* val dup */ JimReferencesHTKeyCompare, /* key compare */ JimReferencesHTKeyDestructor, /* key destructor */ NULL /* val destructor */ }; /* Performs the garbage collection. */ int Jim_Collect(Jim_Interp *interp) { int collected = 0; #ifndef JIM_BOOTSTRAP Jim_HashTable marks; Jim_HashTableIterator htiter; Jim_HashEntry *he; Jim_Obj *objPtr; /* Avoid recursive calls */ if (interp->lastCollectId == -1) { /* Jim_Collect() already running. Return just now. */ return 0; } interp->lastCollectId = -1; /* Mark all the references found into the 'mark' hash table. * The references are searched in every live object that * is of a type that can contain references. */ Jim_InitHashTable(&marks, &JimRefMarkHashTableType, NULL); objPtr = interp->liveList; while (objPtr) { if (objPtr->typePtr == NULL || objPtr->typePtr->flags & JIM_TYPE_REFERENCES) { const char *str, *p; int len; /* If the object is of type reference, to get the * Id is simple... */ if (objPtr->typePtr == &referenceObjType) { Jim_AddHashEntry(&marks, &objPtr->internalRep.refValue.id, NULL); #ifdef JIM_DEBUG_GC printf("MARK (reference): %d refcount: %d\n", (int)objPtr->internalRep.refValue.id, objPtr->refCount); #endif objPtr = objPtr->nextObjPtr; continue; } /* Get the string repr of the object we want * to scan for references. */ p = str = Jim_GetString(objPtr, &len); /* Skip objects too little to contain references. */ if (len < JIM_REFERENCE_SPACE) { objPtr = objPtr->nextObjPtr; continue; } /* Extract references from the object string repr. */ while (1) { int i; unsigned long id; if ((p = strstr(p, "nextObjPtr; } /* Run the references hash table to destroy every reference that * is not referenced outside (not present in the mark HT). */ JimInitHashTableIterator(&interp->references, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { const unsigned long *refId; Jim_Reference *refPtr; refId = he->key; /* Check if in the mark phase we encountered * this reference. */ if (Jim_FindHashEntry(&marks, refId) == NULL) { #ifdef JIM_DEBUG_GC printf("COLLECTING %d\n", (int)*refId); #endif collected++; /* Drop the reference, but call the * finalizer first if registered. */ refPtr = Jim_GetHashEntryVal(he); if (refPtr->finalizerCmdNamePtr) { char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1); Jim_Obj *objv[3], *oldResult; JimFormatReference(refstr, refPtr, *refId); objv[0] = refPtr->finalizerCmdNamePtr; objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, JIM_REFERENCE_SPACE); objv[2] = refPtr->objPtr; /* Drop the reference itself */ /* Avoid the finaliser being freed here */ Jim_IncrRefCount(objv[0]); /* Don't remove the reference from the hash table just yet * since that will free refPtr, and hence refPtr->objPtr */ /* Call the finalizer. Errors ignored. (should we use bgerror?) */ oldResult = interp->result; Jim_IncrRefCount(oldResult); Jim_EvalObjVector(interp, 3, objv); Jim_SetResult(interp, oldResult); Jim_DecrRefCount(interp, oldResult); Jim_DecrRefCount(interp, objv[0]); } Jim_DeleteHashEntry(&interp->references, refId); } } Jim_FreeHashTable(&marks); interp->lastCollectId = interp->referenceNextId; interp->lastCollectTime = time(NULL); #endif /* JIM_BOOTSTRAP */ return collected; } #define JIM_COLLECT_ID_PERIOD 5000 #define JIM_COLLECT_TIME_PERIOD 300 void Jim_CollectIfNeeded(Jim_Interp *interp) { unsigned long elapsedId; int elapsedTime; elapsedId = interp->referenceNextId - interp->lastCollectId; elapsedTime = time(NULL) - interp->lastCollectTime; if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { Jim_Collect(interp); } } #endif int Jim_IsBigEndian(void) { union { unsigned short s; unsigned char c[2]; } uval = {0x0102}; return uval.c[0] == 1; } /* ----------------------------------------------------------------------------- * Interpreter related functions * ---------------------------------------------------------------------------*/ Jim_Interp *Jim_CreateInterp(void) { Jim_Interp *i = Jim_Alloc(sizeof(*i)); memset(i, 0, sizeof(*i)); i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH; i->maxEvalDepth = JIM_MAX_EVAL_DEPTH; i->lastCollectTime = time(NULL); /* Note that we can create objects only after the * interpreter liveList and freeList pointers are * initialized to NULL. */ Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i); #ifdef JIM_REFERENCES Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); #endif Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); Jim_InitHashTable(&i->packages, &JimPackageHashTableType, NULL); i->emptyObj = Jim_NewEmptyStringObj(i); i->trueObj = Jim_NewIntObj(i, 1); i->falseObj = Jim_NewIntObj(i, 0); i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj); i->errorFileNameObj = i->emptyObj; i->result = i->emptyObj; i->stackTrace = Jim_NewListObj(i, NULL, 0); i->unknown = Jim_NewStringObj(i, "unknown", -1); i->errorProc = i->emptyObj; i->currentScriptObj = Jim_NewEmptyStringObj(i); i->nullScriptObj = Jim_NewEmptyStringObj(i); Jim_IncrRefCount(i->emptyObj); Jim_IncrRefCount(i->errorFileNameObj); Jim_IncrRefCount(i->result); Jim_IncrRefCount(i->stackTrace); Jim_IncrRefCount(i->unknown); Jim_IncrRefCount(i->currentScriptObj); Jim_IncrRefCount(i->nullScriptObj); Jim_IncrRefCount(i->errorProc); Jim_IncrRefCount(i->trueObj); Jim_IncrRefCount(i->falseObj); /* Initialize key variables every interpreter should contain */ Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian"); Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); return i; } void Jim_FreeInterp(Jim_Interp *i) { Jim_CallFrame *cf, *cfx; Jim_Obj *objPtr, *nextObjPtr; /* Free the active call frames list - must be done before i->commands is destroyed */ for (cf = i->framePtr; cf; cf = cfx) { cfx = cf->parent; JimFreeCallFrame(i, cf, JIM_FCF_FULL); } Jim_DecrRefCount(i, i->emptyObj); Jim_DecrRefCount(i, i->trueObj); Jim_DecrRefCount(i, i->falseObj); Jim_DecrRefCount(i, i->result); Jim_DecrRefCount(i, i->stackTrace); Jim_DecrRefCount(i, i->errorProc); Jim_DecrRefCount(i, i->unknown); Jim_DecrRefCount(i, i->errorFileNameObj); Jim_DecrRefCount(i, i->currentScriptObj); Jim_DecrRefCount(i, i->nullScriptObj); Jim_FreeHashTable(&i->commands); #ifdef JIM_REFERENCES Jim_FreeHashTable(&i->references); #endif Jim_FreeHashTable(&i->packages); Jim_Free(i->prngState); Jim_FreeHashTable(&i->assocData); /* Check that the live object list is empty, otherwise * there is a memory leak. */ #ifdef JIM_MAINTAINER if (i->liveList != NULL) { objPtr = i->liveList; printf("\n-------------------------------------\n"); printf("Objects still in the free list:\n"); while (objPtr) { const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; if (objPtr->bytes && strlen(objPtr->bytes) > 20) { printf("%p (%d) %-10s: '%.20s...'\n", (void *)objPtr, objPtr->refCount, type, objPtr->bytes); } else { printf("%p (%d) %-10s: '%s'\n", (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); } if (objPtr->typePtr == &sourceObjType) { printf("FILE %s LINE %d\n", Jim_String(objPtr->internalRep.sourceValue.fileNameObj), objPtr->internalRep.sourceValue.lineNumber); } objPtr = objPtr->nextObjPtr; } printf("-------------------------------------\n\n"); JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); } #endif /* Free all the freed objects. */ objPtr = i->freeList; while (objPtr) { nextObjPtr = objPtr->nextObjPtr; Jim_Free(objPtr); objPtr = nextObjPtr; } /* Free the free call frames list */ for (cf = i->freeFramesList; cf; cf = cfx) { cfx = cf->next; if (cf->vars.table) Jim_FreeHashTable(&cf->vars); Jim_Free(cf); } /* Free the interpreter structure. */ Jim_Free(i); } /* Returns the call frame relative to the level represented by * levelObjPtr. If levelObjPtr == NULL, the level is assumed to be '1'. * * This function accepts the 'level' argument in the form * of the commands [uplevel] and [upvar]. * * Returns NULL on error. * * Note: for a function accepting a relative integer as level suitable * for implementation of [info level ?level?], see JimGetCallFrameByInteger() */ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) { long level; const char *str; Jim_CallFrame *framePtr; if (levelObjPtr) { str = Jim_String(levelObjPtr); if (str[0] == '#') { char *endptr; level = jim_strtol(str + 1, &endptr); if (str[1] == '\0' || endptr[0] != '\0') { level = -1; } } else { if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { level = -1; } else { /* Convert from a relative to an absolute level */ level = interp->framePtr->level - level; } } } else { str = "1"; /* Needed to format the error message. */ level = interp->framePtr->level - 1; } if (level == 0) { return interp->topFramePtr; } if (level > 0) { /* Lookup */ for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { if (framePtr->level == level) { return framePtr; } } } Jim_SetResultFormatted(interp, "bad level \"%s\"", str); return NULL; } /* Similar to Jim_GetCallFrameByLevel() but the level is specified * as a relative integer like in the [info level ?level?] command. **/ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr) { long level; Jim_CallFrame *framePtr; if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { if (level <= 0) { /* Convert from a relative to an absolute level */ level = interp->framePtr->level + level; } if (level == 0) { return interp->topFramePtr; } /* Lookup */ for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { if (framePtr->level == level) { return framePtr; } } } Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); return NULL; } static void JimResetStackTrace(Jim_Interp *interp) { Jim_DecrRefCount(interp, interp->stackTrace); interp->stackTrace = Jim_NewListObj(interp, NULL, 0); Jim_IncrRefCount(interp->stackTrace); } static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) { int len; /* Increment reference first in case these are the same object */ Jim_IncrRefCount(stackTraceObj); Jim_DecrRefCount(interp, interp->stackTrace); interp->stackTrace = stackTraceObj; interp->errorFlag = 1; /* This is a bit ugly. * If the filename of the last entry of the stack trace is empty, * the next stack level should be added. */ len = Jim_ListLength(interp, interp->stackTrace); if (len >= 3) { if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) { interp->addStackTrace = 1; } } } static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, Jim_Obj *fileNameObj, int linenr) { if (strcmp(procname, "unknown") == 0) { procname = ""; } if (!*procname && !Jim_Length(fileNameObj)) { /* No useful info here */ return; } if (Jim_IsShared(interp->stackTrace)) { Jim_DecrRefCount(interp, interp->stackTrace); interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); Jim_IncrRefCount(interp->stackTrace); } /* If we have no procname but the previous element did, merge with that frame */ if (!*procname && Jim_Length(fileNameObj)) { /* Just a filename. Check the previous entry */ int len = Jim_ListLength(interp, interp->stackTrace); if (len >= 3) { Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); if (Jim_Length(objPtr)) { /* Yes, the previous level had procname */ objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); if (Jim_Length(objPtr) == 0) { /* But no filename, so merge the new info with that frame */ ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); return; } } } } Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1)); Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj); Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr)); } int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc, void *data) { AssocDataValue *assocEntryPtr = (AssocDataValue *) Jim_Alloc(sizeof(AssocDataValue)); assocEntryPtr->delProc = delProc; assocEntryPtr->data = data; return Jim_AddHashEntry(&interp->assocData, key, assocEntryPtr); } void *Jim_GetAssocData(Jim_Interp *interp, const char *key) { Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); if (entryPtr != NULL) { AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr); return assocEntryPtr->data; } return NULL; } int Jim_DeleteAssocData(Jim_Interp *interp, const char *key) { return Jim_DeleteHashEntry(&interp->assocData, key); } int Jim_GetExitCode(Jim_Interp *interp) { return interp->exitCode; } /* ----------------------------------------------------------------------------- * Integer object * ---------------------------------------------------------------------------*/ static void UpdateStringOfInt(struct Jim_Obj *objPtr); static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); static const Jim_ObjType intObjType = { "int", NULL, NULL, UpdateStringOfInt, JIM_TYPE_NONE, }; /* A coerced double is closer to an int than a double. * It is an int value temporarily masquerading as a double value. * i.e. it has the same string value as an int and Jim_GetWide() * succeeds, but also Jim_GetDouble() returns the value directly. */ static const Jim_ObjType coercedDoubleObjType = { "coerced-double", NULL, NULL, UpdateStringOfInt, JIM_TYPE_NONE, }; static void UpdateStringOfInt(struct Jim_Obj *objPtr) { char buf[JIM_INTEGER_SPACE + 1]; jim_wide wideValue = JimWideValue(objPtr); int pos = 0; if (wideValue == 0) { buf[pos++] = '0'; } else { char tmp[JIM_INTEGER_SPACE]; int num = 0; int i; if (wideValue < 0) { buf[pos++] = '-'; i = wideValue % 10; /* C89 is implementation defined as to whether (-106 % 10) is -6 or 4, * whereas C99 is always -6 * coverity[dead_error_line] */ tmp[num++] = (i > 0) ? (10 - i) : -i; wideValue /= -10; } while (wideValue) { tmp[num++] = wideValue % 10; wideValue /= 10; } for (i = 0; i < num; i++) { buf[pos++] = '0' + tmp[num - i - 1]; } } buf[pos] = 0; JimSetStringBytes(objPtr, buf); } static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { jim_wide wideValue; const char *str; if (objPtr->typePtr == &coercedDoubleObjType) { /* Simple switcheroo */ objPtr->typePtr = &intObjType; return JIM_OK; } /* Get the string representation */ str = Jim_String(objPtr); /* Try to convert into a jim_wide */ if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { if (flags & JIM_ERRMSG) { Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); } return JIM_ERR; } if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { Jim_SetResultString(interp, "Integer value too big to be represented", -1); return JIM_ERR; } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &intObjType; objPtr->internalRep.wideValue = wideValue; return JIM_OK; } #ifdef JIM_OPTIMIZATION static int JimIsWide(Jim_Obj *objPtr) { return objPtr->typePtr == &intObjType; } #endif int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) { if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) return JIM_ERR; *widePtr = JimWideValue(objPtr); return JIM_OK; } /* Get a wide but does not set an error if the format is bad. */ static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) { if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR) return JIM_ERR; *widePtr = JimWideValue(objPtr); return JIM_OK; } int Jim_GetLong(Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr) { jim_wide wideValue; int retval; retval = Jim_GetWide(interp, objPtr, &wideValue); if (retval == JIM_OK) { *longPtr = (long)wideValue; return JIM_OK; } return JIM_ERR; } Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue) { Jim_Obj *objPtr; objPtr = Jim_NewObj(interp); objPtr->typePtr = &intObjType; objPtr->bytes = NULL; objPtr->internalRep.wideValue = wideValue; return objPtr; } /* ----------------------------------------------------------------------------- * Double object * ---------------------------------------------------------------------------*/ #define JIM_DOUBLE_SPACE 30 static void UpdateStringOfDouble(struct Jim_Obj *objPtr); static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr); static const Jim_ObjType doubleObjType = { "double", NULL, NULL, UpdateStringOfDouble, JIM_TYPE_NONE, }; #ifndef HAVE_ISNAN #undef isnan #define isnan(X) ((X) != (X)) #endif #ifndef HAVE_ISINF #undef isinf #define isinf(X) (1.0 / (X) == 0.0) #endif static void UpdateStringOfDouble(struct Jim_Obj *objPtr) { double value = objPtr->internalRep.doubleValue; if (isnan(value)) { JimSetStringBytes(objPtr, "NaN"); return; } if (isinf(value)) { if (value < 0) { JimSetStringBytes(objPtr, "-Inf"); } else { JimSetStringBytes(objPtr, "Inf"); } return; } { char buf[JIM_DOUBLE_SPACE + 1]; int i; int len = sprintf(buf, "%.12g", value); /* Add a final ".0" if necessary */ for (i = 0; i < len; i++) { if (buf[i] == '.' || buf[i] == 'e') { #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) /* If 'buf' ends in e-0nn or e+0nn, remove * the 0 after the + or - and reduce the length by 1 */ char *e = strchr(buf, 'e'); if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { /* Move it up */ e += 2; memmove(e, e + 1, len - (e - buf)); } #endif break; } } if (buf[i] == '\0') { buf[i++] = '.'; buf[i++] = '0'; buf[i] = '\0'; } JimSetStringBytes(objPtr, buf); } } static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { double doubleValue; jim_wide wideValue; const char *str; /* Preserve the string representation. * Needed so we can convert back to int without loss */ str = Jim_String(objPtr); #ifdef HAVE_LONG_LONG /* Assume a 53 bit mantissa */ #define MIN_INT_IN_DOUBLE -(1LL << 53) #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) if (objPtr->typePtr == &intObjType && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { /* Direct conversion to coerced double */ objPtr->typePtr = &coercedDoubleObjType; return JIM_OK; } else #endif if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { /* Managed to convert to an int, so we can use this as a cooerced double */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &coercedDoubleObjType; objPtr->internalRep.wideValue = wideValue; return JIM_OK; } else { /* Try to convert into a double */ if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr); return JIM_ERR; } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); } objPtr->typePtr = &doubleObjType; objPtr->internalRep.doubleValue = doubleValue; return JIM_OK; } int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr) { if (objPtr->typePtr == &coercedDoubleObjType) { *doublePtr = JimWideValue(objPtr); return JIM_OK; } if (objPtr->typePtr != &doubleObjType && SetDoubleFromAny(interp, objPtr) == JIM_ERR) return JIM_ERR; if (objPtr->typePtr == &coercedDoubleObjType) { *doublePtr = JimWideValue(objPtr); } else { *doublePtr = objPtr->internalRep.doubleValue; } return JIM_OK; } Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue) { Jim_Obj *objPtr; objPtr = Jim_NewObj(interp); objPtr->typePtr = &doubleObjType; objPtr->bytes = NULL; objPtr->internalRep.doubleValue = doubleValue; return objPtr; } /* ----------------------------------------------------------------------------- * List object * ---------------------------------------------------------------------------*/ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static void UpdateStringOfList(struct Jim_Obj *objPtr); static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); /* Note that while the elements of the list may contain references, * the list object itself can't. This basically means that the * list object string representation as a whole can't contain references * that are not presents in the single elements. */ static const Jim_ObjType listObjType = { "list", FreeListInternalRep, DupListInternalRep, UpdateStringOfList, JIM_TYPE_NONE, }; void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { int i; for (i = 0; i < objPtr->internalRep.listValue.len; i++) { Jim_DecrRefCount(interp, objPtr->internalRep.listValue.ele[i]); } Jim_Free(objPtr->internalRep.listValue.ele); } void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { int i; JIM_NOTUSED(interp); dupPtr->internalRep.listValue.len = srcPtr->internalRep.listValue.len; dupPtr->internalRep.listValue.maxLen = srcPtr->internalRep.listValue.maxLen; dupPtr->internalRep.listValue.ele = Jim_Alloc(sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.maxLen); memcpy(dupPtr->internalRep.listValue.ele, srcPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.len); for (i = 0; i < dupPtr->internalRep.listValue.len; i++) { Jim_IncrRefCount(dupPtr->internalRep.listValue.ele[i]); } dupPtr->typePtr = &listObjType; } /* The following function checks if a given string can be encoded * into a list element without any kind of quoting, surrounded by braces, * or using escapes to quote. */ #define JIM_ELESTR_SIMPLE 0 #define JIM_ELESTR_BRACE 1 #define JIM_ELESTR_QUOTE 2 static unsigned char ListElementQuotingType(const char *s, int len) { int i, level, blevel, trySimple = 1; /* Try with the SIMPLE case */ if (len == 0) return JIM_ELESTR_BRACE; if (s[0] == '"' || s[0] == '{') { trySimple = 0; goto testbrace; } for (i = 0; i < len; i++) { switch (s[i]) { case ' ': case '$': case '"': case '[': case ']': case ';': case '\\': case '\r': case '\n': case '\t': case '\f': case '\v': trySimple = 0; case '{': case '}': goto testbrace; } } return JIM_ELESTR_SIMPLE; testbrace: /* Test if it's possible to do with braces */ if (s[len - 1] == '\\') return JIM_ELESTR_QUOTE; level = 0; blevel = 0; for (i = 0; i < len; i++) { switch (s[i]) { case '{': level++; break; case '}': level--; if (level < 0) return JIM_ELESTR_QUOTE; break; case '[': blevel++; break; case ']': blevel--; break; case '\\': if (s[i + 1] == '\n') return JIM_ELESTR_QUOTE; else if (s[i + 1] != '\0') i++; break; } } if (blevel < 0) { return JIM_ELESTR_QUOTE; } if (level == 0) { if (!trySimple) return JIM_ELESTR_BRACE; for (i = 0; i < len; i++) { switch (s[i]) { case ' ': case '$': case '"': case '[': case ']': case ';': case '\\': case '\r': case '\n': case '\t': case '\f': case '\v': return JIM_ELESTR_BRACE; break; } } return JIM_ELESTR_SIMPLE; } return JIM_ELESTR_QUOTE; } /* Backslashes-escapes the null-terminated string 's' into the buffer at 'q' * The buffer must be at least strlen(s) * 2 + 1 bytes long for the worst-case * scenario. * Returns the length of the result. */ static int BackslashQuoteString(const char *s, int len, char *q) { char *p = q; while (len--) { switch (*s) { case ' ': case '$': case '"': case '[': case ']': case '{': case '}': case ';': case '\\': *p++ = '\\'; *p++ = *s++; break; case '\n': *p++ = '\\'; *p++ = 'n'; s++; break; case '\r': *p++ = '\\'; *p++ = 'r'; s++; break; case '\t': *p++ = '\\'; *p++ = 't'; s++; break; case '\f': *p++ = '\\'; *p++ = 'f'; s++; break; case '\v': *p++ = '\\'; *p++ = 'v'; s++; break; default: *p++ = *s++; break; } } *p = '\0'; return p - q; } static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc) { #define STATIC_QUOTING_LEN 32 int i, bufLen, realLength; const char *strRep; char *p; unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; /* Estimate the space needed. */ if (objc > STATIC_QUOTING_LEN) { quotingType = Jim_Alloc(objc); } else { quotingType = staticQuoting; } bufLen = 0; for (i = 0; i < objc; i++) { int len; strRep = Jim_GetString(objv[i], &len); quotingType[i] = ListElementQuotingType(strRep, len); switch (quotingType[i]) { case JIM_ELESTR_SIMPLE: if (i != 0 || strRep[0] != '#') { bufLen += len; break; } /* Special case '#' on first element needs braces */ quotingType[i] = JIM_ELESTR_BRACE; /* fall through */ case JIM_ELESTR_BRACE: bufLen += len + 2; break; case JIM_ELESTR_QUOTE: bufLen += len * 2; break; } bufLen++; /* elements separator. */ } bufLen++; /* Generate the string rep. */ p = objPtr->bytes = Jim_Alloc(bufLen + 1); realLength = 0; for (i = 0; i < objc; i++) { int len, qlen; strRep = Jim_GetString(objv[i], &len); switch (quotingType[i]) { case JIM_ELESTR_SIMPLE: memcpy(p, strRep, len); p += len; realLength += len; break; case JIM_ELESTR_BRACE: *p++ = '{'; memcpy(p, strRep, len); p += len; *p++ = '}'; realLength += len + 2; break; case JIM_ELESTR_QUOTE: if (i == 0 && strRep[0] == '#') { *p++ = '\\'; realLength++; } qlen = BackslashQuoteString(strRep, len, p); p += qlen; realLength += qlen; break; } /* Add a separating space */ if (i + 1 != objc) { *p++ = ' '; realLength++; } } *p = '\0'; /* nul term. */ objPtr->length = realLength; if (quotingType != staticQuoting) { Jim_Free(quotingType); } } static void UpdateStringOfList(struct Jim_Obj *objPtr) { JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len); } static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { struct JimParserCtx parser; const char *str; int strLen; Jim_Obj *fileNameObj; int linenr; if (objPtr->typePtr == &listObjType) { return JIM_OK; } /* Optimise dict -> list for object with no string rep. Note that this may only save a little time, but * it also preserves any source location of the dict elements * which can be very useful */ if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { Jim_Obj **listObjPtrPtr; int len; int i; listObjPtrPtr = JimDictPairs(objPtr, &len); for (i = 0; i < len; i++) { Jim_IncrRefCount(listObjPtrPtr[i]); } /* Now just switch the internal rep */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &listObjType; objPtr->internalRep.listValue.len = len; objPtr->internalRep.listValue.maxLen = len; objPtr->internalRep.listValue.ele = listObjPtrPtr; return JIM_OK; } /* Try to preserve information about filename / line number */ if (objPtr->typePtr == &sourceObjType) { fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; linenr = objPtr->internalRep.sourceValue.lineNumber; } else { fileNameObj = interp->emptyObj; linenr = 1; } Jim_IncrRefCount(fileNameObj); /* Get the string representation */ str = Jim_GetString(objPtr, &strLen); /* Free the old internal repr just now and initialize the * new one just now. The string->list conversion can't fail. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &listObjType; objPtr->internalRep.listValue.len = 0; objPtr->internalRep.listValue.maxLen = 0; objPtr->internalRep.listValue.ele = NULL; /* Convert into a list */ if (strLen) { JimParserInit(&parser, str, strLen, linenr); while (!parser.eof) { Jim_Obj *elementPtr; JimParseList(&parser); if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC) continue; elementPtr = JimParserGetTokenObj(interp, &parser); JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); ListAppendElement(objPtr, elementPtr); } } Jim_DecrRefCount(interp, fileNameObj); return JIM_OK; } Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) { Jim_Obj *objPtr; objPtr = Jim_NewObj(interp); objPtr->typePtr = &listObjType; objPtr->bytes = NULL; objPtr->internalRep.listValue.ele = NULL; objPtr->internalRep.listValue.len = 0; objPtr->internalRep.listValue.maxLen = 0; if (len) { ListInsertElements(objPtr, 0, len, elements); } return objPtr; } /* Return a vector of Jim_Obj with the elements of a Jim list, and the * length of the vector. Note that the user of this function should make * sure that the list object can't shimmer while the vector returned * is in use, this vector is the one stored inside the internal representation * of the list object. This function is not exported, extensions should * always access to the List object elements using Jim_ListIndex(). */ static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen, Jim_Obj ***listVec) { *listLen = Jim_ListLength(interp, listObj); *listVec = listObj->internalRep.listValue.ele; } /* Sorting uses ints, but commands may return wide */ static int JimSign(jim_wide w) { if (w == 0) { return 0; } else if (w < 0) { return -1; } return 1; } /* ListSortElements type values */ struct lsort_info { jmp_buf jmpbuf; Jim_Obj *command; Jim_Interp *interp; enum { JIM_LSORT_ASCII, JIM_LSORT_NOCASE, JIM_LSORT_INTEGER, JIM_LSORT_REAL, JIM_LSORT_COMMAND } type; int order; int index; int indexed; int unique; int (*subfn)(Jim_Obj **, Jim_Obj **); }; static struct lsort_info *sort_info; static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { Jim_Obj *lObj, *rObj; if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK || Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) { longjmp(sort_info->jmpbuf, JIM_ERR); } return sort_info->subfn(&lObj, &rObj); } /* Sort the internal rep of a list. */ static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order; } static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order; } static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { jim_wide lhs = 0, rhs = 0; if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK || Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { longjmp(sort_info->jmpbuf, JIM_ERR); } return JimSign(lhs - rhs) * sort_info->order; } static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { double lhs = 0, rhs = 0; if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK || Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { longjmp(sort_info->jmpbuf, JIM_ERR); } if (lhs == rhs) { return 0; } if (lhs > rhs) { return sort_info->order; } return -sort_info->order; } static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { Jim_Obj *compare_script; int rc; jim_wide ret = 0; /* This must be a valid list */ compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); rc = Jim_EvalObj(sort_info->interp, compare_script); if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) { longjmp(sort_info->jmpbuf, rc); } return JimSign(ret) * sort_info->order; } /* Remove duplicate elements from the (sorted) list in-place, according to the * comparison function, comp. * * Note that the last unique value is kept, not the first */ static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs)) { int src; int dst = 0; Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { if (comp(&ele[dst], &ele[src]) == 0) { /* Match, so replace the dest with the current source */ Jim_DecrRefCount(sort_info->interp, ele[dst]); } else { /* No match, so keep the current source and move to the next destination */ dst++; } ele[dst] = ele[src]; } /* At end of list, keep the final element */ ele[++dst] = ele[src]; /* Set the new length */ listObjPtr->internalRep.listValue.len = dst; } /* Sort a list *in place*. MUST be called with a non-shared list. */ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) { struct lsort_info *prev_info; typedef int (qsort_comparator) (const void *, const void *); int (*fn) (Jim_Obj **, Jim_Obj **); Jim_Obj **vector; int len; int rc; JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); SetListFromAny(interp, listObjPtr); /* Allow lsort to be called reentrantly */ prev_info = sort_info; sort_info = info; vector = listObjPtr->internalRep.listValue.ele; len = listObjPtr->internalRep.listValue.len; switch (info->type) { case JIM_LSORT_ASCII: fn = ListSortString; break; case JIM_LSORT_NOCASE: fn = ListSortStringNoCase; break; case JIM_LSORT_INTEGER: fn = ListSortInteger; break; case JIM_LSORT_REAL: fn = ListSortReal; break; case JIM_LSORT_COMMAND: fn = ListSortCommand; break; default: fn = NULL; /* avoid warning */ JimPanic((1, "ListSort called with invalid sort type")); } if (info->indexed) { /* Need to interpose a "list index" function */ info->subfn = fn; fn = ListSortIndexHelper; } if ((rc = setjmp(info->jmpbuf)) == 0) { qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); if (info->unique && len > 1) { ListRemoveDuplicates(listObjPtr, fn); } Jim_InvalidateStringRep(listObjPtr); } sort_info = prev_info; return rc; } /* This is the low-level function to insert elements into a list. * The higher-level Jim_ListInsertElements() performs shared object * check and invalidates the string repr. This version is used * in the internals of the List Object and is not exported. * * NOTE: this function can be called only against objects * with internal type of List. * * An insertion point (idx) of -1 means end-of-list. */ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec) { int currentLen = listPtr->internalRep.listValue.len; int requiredLen = currentLen + elemc; int i; Jim_Obj **point; if (requiredLen > listPtr->internalRep.listValue.maxLen) { if (requiredLen < 2) { /* Don't do allocations of under 4 pointers. */ requiredLen = 4; } else { requiredLen *= 2; } listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * requiredLen); listPtr->internalRep.listValue.maxLen = requiredLen; } if (idx < 0) { idx = currentLen; } point = listPtr->internalRep.listValue.ele + idx; memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *)); for (i = 0; i < elemc; ++i) { point[i] = elemVec[i]; Jim_IncrRefCount(point[i]); } listPtr->internalRep.listValue.len += elemc; } /* Convenience call to ListInsertElements() to append a single element. */ static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr) { ListInsertElements(listPtr, -1, 1, &objPtr); } /* Appends every element of appendListPtr into listPtr. * Both have to be of the list type. * Convenience call to ListInsertElements() */ static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr) { ListInsertElements(listPtr, -1, appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele); } void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr) { JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object")); SetListFromAny(interp, listPtr); Jim_InvalidateStringRep(listPtr); ListAppendElement(listPtr, objPtr); } void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr) { JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object")); SetListFromAny(interp, listPtr); SetListFromAny(interp, appendListPtr); Jim_InvalidateStringRep(listPtr); ListAppendList(listPtr, appendListPtr); } int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr) { SetListFromAny(interp, objPtr); return objPtr->internalRep.listValue.len; } void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx, int objc, Jim_Obj *const *objVec) { JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object")); SetListFromAny(interp, listPtr); if (idx >= 0 && idx > listPtr->internalRep.listValue.len) idx = listPtr->internalRep.listValue.len; else if (idx < 0) idx = 0; Jim_InvalidateStringRep(listPtr); ListInsertElements(listPtr, idx, objc, objVec); } Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx) { SetListFromAny(interp, listPtr); if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { return NULL; } if (idx < 0) idx = listPtr->internalRep.listValue.len + idx; return listPtr->internalRep.listValue.ele[idx]; } int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags) { *objPtrPtr = Jim_ListGetIndex(interp, listPtr, idx); if (*objPtrPtr == NULL) { if (flags & JIM_ERRMSG) { Jim_SetResultString(interp, "list index out of range", -1); } return JIM_ERR; } return JIM_OK; } static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj *newObjPtr, int flags) { SetListFromAny(interp, listPtr); if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { if (flags & JIM_ERRMSG) { Jim_SetResultString(interp, "list index out of range", -1); } return JIM_ERR; } if (idx < 0) idx = listPtr->internalRep.listValue.len + idx; Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]); listPtr->internalRep.listValue.ele[idx] = newObjPtr; Jim_IncrRefCount(newObjPtr); return JIM_OK; } /* Modify the list stored in the variable named 'varNamePtr' * setting the element specified by the 'indexc' indexes objects in 'indexv', * with the new element 'newObjptr'. (implements the [lset] command) */ int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) { Jim_Obj *varObjPtr, *objPtr, *listObjPtr; int shared, i, idx; varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED); if (objPtr == NULL) return JIM_ERR; if ((shared = Jim_IsShared(objPtr))) varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); for (i = 0; i < indexc - 1; i++) { listObjPtr = objPtr; if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK) goto err; if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) { goto err; } if (Jim_IsShared(objPtr)) { objPtr = Jim_DuplicateObj(interp, objPtr); ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE); } Jim_InvalidateStringRep(listObjPtr); } if (Jim_GetIndex(interp, indexv[indexc - 1], &idx) != JIM_OK) goto err; if (ListSetIndex(interp, objPtr, idx, newObjPtr, JIM_ERRMSG) == JIM_ERR) goto err; Jim_InvalidateStringRep(objPtr); Jim_InvalidateStringRep(varObjPtr); if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) goto err; Jim_SetResult(interp, varObjPtr); return JIM_OK; err: if (shared) { Jim_FreeNewObj(interp, varObjPtr); } return JIM_ERR; } Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen) { int i; int listLen = Jim_ListLength(interp, listObjPtr); Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); for (i = 0; i < listLen; ) { Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i)); if (++i != listLen) { Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); } } return resObjPtr; } Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv) { int i; /* If all the objects in objv are lists, * it's possible to return a list as result, that's the * concatenation of all the lists. */ for (i = 0; i < objc; i++) { if (!Jim_IsList(objv[i])) break; } if (i == objc) { Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < objc; i++) ListAppendList(objPtr, objv[i]); return objPtr; } else { /* Else... we have to glue strings together */ int len = 0, objLen; char *bytes, *p; /* Compute the length */ for (i = 0; i < objc; i++) { len += Jim_Length(objv[i]); } if (objc) len += objc - 1; /* Create the string rep, and a string object holding it. */ p = bytes = Jim_Alloc(len + 1); for (i = 0; i < objc; i++) { const char *s = Jim_GetString(objv[i], &objLen); /* Remove leading space */ while (objLen && isspace(UCHAR(*s))) { s++; objLen--; len--; } /* And trailing space */ while (objLen && isspace(UCHAR(s[objLen - 1]))) { /* Handle trailing backslash-space case */ if (objLen > 1 && s[objLen - 2] == '\\') { break; } objLen--; len--; } memcpy(p, s, objLen); p += objLen; if (i + 1 != objc) { if (objLen) *p++ = ' '; else { /* Drop the space calcuated for this * element that is instead null. */ len--; } } } *p = '\0'; return Jim_NewStringObjNoAlloc(interp, bytes, len); } } /* Returns a list composed of the elements in the specified range. * first and start are directly accepted as Jim_Objects and * processed for the end?-index? case. */ Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) { int first, last; int len, rangeLen; if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) return NULL; len = Jim_ListLength(interp, listObjPtr); /* will convert into list */ first = JimRelToAbsIndex(len, first); last = JimRelToAbsIndex(len, last); JimRelToAbsRange(len, &first, &last, &rangeLen); if (first == 0 && last == len) { return listObjPtr; } return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen); } /* ----------------------------------------------------------------------------- * Dict object * ---------------------------------------------------------------------------*/ static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static void UpdateStringOfDict(struct Jim_Obj *objPtr); static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); /* Dict HashTable Type. * * Keys and Values are Jim objects. */ static unsigned int JimObjectHTHashFunction(const void *key) { int len; const char *str = Jim_GetString((Jim_Obj *)key, &len); return Jim_GenHashFunction((const unsigned char *)str, len); } static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) { return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); } static void *JimObjectHTKeyValDup(void *privdata, const void *val) { Jim_IncrRefCount((Jim_Obj *)val); return (void *)val; } static void JimObjectHTKeyValDestructor(void *interp, void *val) { Jim_DecrRefCount(interp, (Jim_Obj *)val); } static const Jim_HashTableType JimDictHashTableType = { JimObjectHTHashFunction, /* hash function */ JimObjectHTKeyValDup, /* key dup */ JimObjectHTKeyValDup, /* val dup */ JimObjectHTKeyCompare, /* key compare */ JimObjectHTKeyValDestructor, /* key destructor */ JimObjectHTKeyValDestructor /* val destructor */ }; /* Note that while the elements of the dict may contain references, * the list object itself can't. This basically means that the * dict object string representation as a whole can't contain references * that are not presents in the single elements. */ static const Jim_ObjType dictObjType = { "dict", FreeDictInternalRep, DupDictInternalRep, UpdateStringOfDict, JIM_TYPE_NONE, }; void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { JIM_NOTUSED(interp); Jim_FreeHashTable(objPtr->internalRep.ptr); Jim_Free(objPtr->internalRep.ptr); } void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { Jim_HashTable *ht, *dupHt; Jim_HashTableIterator htiter; Jim_HashEntry *he; /* Create a new hash table */ ht = srcPtr->internalRep.ptr; dupHt = Jim_Alloc(sizeof(*dupHt)); Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); if (ht->size != 0) Jim_ExpandHashTable(dupHt, ht->size); /* Copy every element from the source to the dup hash table */ JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { Jim_AddHashEntry(dupHt, he->key, he->u.val); } dupPtr->internalRep.ptr = dupHt; dupPtr->typePtr = &dictObjType; } static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len) { Jim_HashTable *ht; Jim_HashTableIterator htiter; Jim_HashEntry *he; Jim_Obj **objv; int i; ht = dictPtr->internalRep.ptr; /* Turn the hash table into a flat vector of Jim_Objects. */ objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); JimInitHashTableIterator(ht, &htiter); i = 0; while ((he = Jim_NextHashEntry(&htiter)) != NULL) { objv[i++] = Jim_GetHashEntryKey(he); objv[i++] = Jim_GetHashEntryVal(he); } *len = i; return objv; } static void UpdateStringOfDict(struct Jim_Obj *objPtr) { /* Turn the hash table into a flat vector of Jim_Objects. */ int len; Jim_Obj **objv = JimDictPairs(objPtr, &len); /* And now generate the string rep as a list */ JimMakeListStringRep(objPtr, objv, len); Jim_Free(objv); } static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { int listlen; if (objPtr->typePtr == &dictObjType) { return JIM_OK; } if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { /* A shared list, so get the string representation now to avoid * changing the order in case of fast conversion to dict. */ Jim_String(objPtr); } /* For simplicity, convert a non-list object to a list and then to a dict */ listlen = Jim_ListLength(interp, objPtr); if (listlen % 2) { Jim_SetResultString(interp, "missing value to go with key", -1); return JIM_ERR; } else { /* Converting from a list to a dict can't fail */ Jim_HashTable *ht; int i; ht = Jim_Alloc(sizeof(*ht)); Jim_InitHashTable(ht, &JimDictHashTableType, interp); for (i = 0; i < listlen; i += 2) { Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); } Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &dictObjType; objPtr->internalRep.ptr = ht; return JIM_OK; } } /* Dict object API */ /* Add an element to a dict. objPtr must be of the "dict" type. * The higer-level exported function is Jim_DictAddElement(). * If an element with the specified key already exists, the value * associated is replaced with the new one. * * if valueObjPtr == NULL, the key is instead removed if it exists. */ static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) { Jim_HashTable *ht = objPtr->internalRep.ptr; if (valueObjPtr == NULL) { /* unset */ return Jim_DeleteHashEntry(ht, keyObjPtr); } Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); return JIM_OK; } /* Add an element, higher-level interface for DictAddElement(). * If valueObjPtr == NULL, the key is removed if it exists. */ int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) { JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); if (SetDictFromAny(interp, objPtr) != JIM_OK) { return JIM_ERR; } Jim_InvalidateStringRep(objPtr); return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); } Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) { Jim_Obj *objPtr; int i; JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even")); objPtr = Jim_NewObj(interp); objPtr->typePtr = &dictObjType; objPtr->bytes = NULL; objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable)); Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp); for (i = 0; i < len; i += 2) DictAddElement(interp, objPtr, elements[i], elements[i + 1]); return objPtr; } /* Return the value associated to the specified dict key * Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value * * Sets *objPtrPtr to non-NULL only upon success. */ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags) { Jim_HashEntry *he; Jim_HashTable *ht; if (SetDictFromAny(interp, dictPtr) != JIM_OK) { return -1; } ht = dictPtr->internalRep.ptr; if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) { if (flags & JIM_ERRMSG) { Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); } return JIM_ERR; } *objPtrPtr = he->u.val; return JIM_OK; } /* Return an allocated array of key/value pairs for the dictionary. Stores the length in *len */ int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) { if (SetDictFromAny(interp, dictPtr) != JIM_OK) { return JIM_ERR; } *objPtrPtr = JimDictPairs(dictPtr, len); return JIM_OK; } /* Return the value associated to the specified dict keys */ int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags) { int i; if (keyc == 0) { *objPtrPtr = dictPtr; return JIM_OK; } for (i = 0; i < keyc; i++) { Jim_Obj *objPtr; int rc = Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags); if (rc != JIM_OK) { return rc; } dictPtr = objPtr; } *objPtrPtr = dictPtr; return JIM_OK; } /* Modify the dict stored into the variable named 'varNamePtr' * setting the element specified by the 'keyc' keys objects in 'keyv', * with the new value of the element 'newObjPtr'. * * If newObjPtr == NULL the operation is to remove the given key * from the dictionary. * * If flags & JIM_ERRMSG, then failure to remove the key is considered an error * and JIM_ERR is returned. Otherwise it is ignored and JIM_OK is returned. */ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags) { Jim_Obj *varObjPtr, *objPtr, *dictObjPtr; int shared, i; varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags); if (objPtr == NULL) { if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) { /* Cannot remove a key from non existing var */ return JIM_ERR; } varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { Jim_FreeNewObj(interp, varObjPtr); return JIM_ERR; } } if ((shared = Jim_IsShared(objPtr))) varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); for (i = 0; i < keyc; i++) { dictObjPtr = objPtr; /* Check if it's a valid dictionary */ if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { goto err; } if (i == keyc - 1) { /* Last key: Note that error on unset with missing last key is OK */ if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { if (newObjPtr || (flags & JIM_MUSTEXIST)) { goto err; } } break; } /* Check if the given key exists. */ Jim_InvalidateStringRep(dictObjPtr); if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { /* This key exists at the current level. * Make sure it's not shared!. */ if (Jim_IsShared(objPtr)) { objPtr = Jim_DuplicateObj(interp, objPtr); DictAddElement(interp, dictObjPtr, keyv[i], objPtr); } } else { /* Key not found. If it's an [unset] operation * this is an error. Only the last key may not * exist. */ if (newObjPtr == NULL) { goto err; } /* Otherwise set an empty dictionary * as key's value. */ objPtr = Jim_NewDictObj(interp, NULL, 0); DictAddElement(interp, dictObjPtr, keyv[i], objPtr); } } /* XXX: Is this necessary? */ Jim_InvalidateStringRep(objPtr); Jim_InvalidateStringRep(varObjPtr); if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { goto err; } Jim_SetResult(interp, varObjPtr); return JIM_OK; err: if (shared) { Jim_FreeNewObj(interp, varObjPtr); } return JIM_ERR; } /* ----------------------------------------------------------------------------- * Index object * ---------------------------------------------------------------------------*/ static void UpdateStringOfIndex(struct Jim_Obj *objPtr); static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static const Jim_ObjType indexObjType = { "index", NULL, NULL, UpdateStringOfIndex, JIM_TYPE_NONE, }; static void UpdateStringOfIndex(struct Jim_Obj *objPtr) { if (objPtr->internalRep.intValue == -1) { JimSetStringBytes(objPtr, "end"); } else { char buf[JIM_INTEGER_SPACE + 1]; if (objPtr->internalRep.intValue >= 0) { sprintf(buf, "%d", objPtr->internalRep.intValue); } else { /* Must be <= -2 */ sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); } JimSetStringBytes(objPtr, buf); } } static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { int idx, end = 0; const char *str; char *endptr; /* Get the string representation */ str = Jim_String(objPtr); /* Try to convert into an index */ if (strncmp(str, "end", 3) == 0) { end = 1; str += 3; idx = 0; } else { idx = jim_strtol(str, &endptr); if (endptr == str) { goto badindex; } str = endptr; } /* Now str may include or + or - */ if (*str == '+' || *str == '-') { int sign = (*str == '+' ? 1 : -1); idx += sign * jim_strtol(++str, &endptr); if (str == endptr || *endptr) { goto badindex; } str = endptr; } /* The only thing left should be spaces */ while (isspace(UCHAR(*str))) { str++; } if (*str) { goto badindex; } if (end) { if (idx > 0) { idx = INT_MAX; } else { /* end-1 is repesented as -2 */ idx--; } } else if (idx < 0) { idx = -INT_MAX; } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &indexObjType; objPtr->internalRep.intValue = idx; return JIM_OK; badindex: Jim_SetResultFormatted(interp, "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr); return JIM_ERR; } int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) { /* Avoid shimmering if the object is an integer. */ if (objPtr->typePtr == &intObjType) { jim_wide val = JimWideValue(objPtr); if (val < 0) *indexPtr = -INT_MAX; else if (val > INT_MAX) *indexPtr = INT_MAX; else *indexPtr = (int)val; return JIM_OK; } if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) return JIM_ERR; *indexPtr = objPtr->internalRep.intValue; return JIM_OK; } /* ----------------------------------------------------------------------------- * Return Code Object. * ---------------------------------------------------------------------------*/ /* NOTE: These must be kept in the same order as JIM_OK, JIM_ERR, ... */ static const char * const jimReturnCodes[] = { "ok", "error", "return", "break", "continue", "signal", "exit", "eval", NULL }; #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) static const Jim_ObjType returnCodeObjType = { "return-code", NULL, NULL, NULL, JIM_TYPE_NONE, }; /* Converts a (standard) return code to a string. Returns "?" for * non-standard return codes. */ const char *Jim_ReturnCode(int code) { if (code < 0 || code >= (int)jimReturnCodesSize) { return "?"; } else { return jimReturnCodes[code]; } } static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { int returnCode; jim_wide wideValue; /* Try to convert into an integer */ if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) returnCode = (int)wideValue; else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); return JIM_ERR; } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &returnCodeObjType; objPtr->internalRep.intValue = returnCode; return JIM_OK; } int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr) { if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR) return JIM_ERR; *intPtr = objPtr->internalRep.intValue; return JIM_OK; } /* ----------------------------------------------------------------------------- * Expression Parsing * ---------------------------------------------------------------------------*/ static int JimParseExprOperator(struct JimParserCtx *pc); static int JimParseExprNumber(struct JimParserCtx *pc); static int JimParseExprIrrational(struct JimParserCtx *pc); /* Exrp's Stack machine operators opcodes. */ /* Binary operators (numbers) */ enum { /* Continues on from the JIM_TT_ space */ /* Operations */ JIM_EXPROP_MUL = JIM_TT_EXPR_OP, /* 20 */ JIM_EXPROP_DIV, JIM_EXPROP_MOD, JIM_EXPROP_SUB, JIM_EXPROP_ADD, JIM_EXPROP_LSHIFT, JIM_EXPROP_RSHIFT, JIM_EXPROP_ROTL, JIM_EXPROP_ROTR, JIM_EXPROP_LT, JIM_EXPROP_GT, JIM_EXPROP_LTE, JIM_EXPROP_GTE, JIM_EXPROP_NUMEQ, JIM_EXPROP_NUMNE, JIM_EXPROP_BITAND, /* 35 */ JIM_EXPROP_BITXOR, JIM_EXPROP_BITOR, /* Note must keep these together */ JIM_EXPROP_LOGICAND, /* 38 */ JIM_EXPROP_LOGICAND_LEFT, JIM_EXPROP_LOGICAND_RIGHT, /* and these */ JIM_EXPROP_LOGICOR, /* 41 */ JIM_EXPROP_LOGICOR_LEFT, JIM_EXPROP_LOGICOR_RIGHT, /* and these */ /* Ternary operators */ JIM_EXPROP_TERNARY, /* 44 */ JIM_EXPROP_TERNARY_LEFT, JIM_EXPROP_TERNARY_RIGHT, /* and these */ JIM_EXPROP_COLON, /* 47 */ JIM_EXPROP_COLON_LEFT, JIM_EXPROP_COLON_RIGHT, JIM_EXPROP_POW, /* 50 */ /* Binary operators (strings) */ JIM_EXPROP_STREQ, /* 51 */ JIM_EXPROP_STRNE, JIM_EXPROP_STRIN, JIM_EXPROP_STRNI, /* Unary operators (numbers) */ JIM_EXPROP_NOT, /* 55 */ JIM_EXPROP_BITNOT, JIM_EXPROP_UNARYMINUS, JIM_EXPROP_UNARYPLUS, /* Functions */ JIM_EXPROP_FUNC_FIRST, /* 59 */ JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, JIM_EXPROP_FUNC_WIDE, JIM_EXPROP_FUNC_ABS, JIM_EXPROP_FUNC_DOUBLE, JIM_EXPROP_FUNC_ROUND, JIM_EXPROP_FUNC_RAND, JIM_EXPROP_FUNC_SRAND, /* math functions from libm */ JIM_EXPROP_FUNC_SIN, /* 65 */ JIM_EXPROP_FUNC_COS, JIM_EXPROP_FUNC_TAN, JIM_EXPROP_FUNC_ASIN, JIM_EXPROP_FUNC_ACOS, JIM_EXPROP_FUNC_ATAN, JIM_EXPROP_FUNC_SINH, JIM_EXPROP_FUNC_COSH, JIM_EXPROP_FUNC_TANH, JIM_EXPROP_FUNC_CEIL, JIM_EXPROP_FUNC_FLOOR, JIM_EXPROP_FUNC_EXP, JIM_EXPROP_FUNC_LOG, JIM_EXPROP_FUNC_LOG10, JIM_EXPROP_FUNC_SQRT, JIM_EXPROP_FUNC_POW, }; struct JimExprState { Jim_Obj **stack; int stacklen; int opcode; int skip; }; /* Operators table */ typedef struct Jim_ExprOperator { const char *name; int (*funcop) (Jim_Interp *interp, struct JimExprState * e); unsigned char precedence; unsigned char arity; unsigned char lazy; unsigned char namelen; } Jim_ExprOperator; static void ExprPush(struct JimExprState *e, Jim_Obj *obj) { Jim_IncrRefCount(obj); e->stack[e->stacklen++] = obj; } static Jim_Obj *ExprPop(struct JimExprState *e) { return e->stack[--e->stacklen]; } static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) { int intresult = 1; int rc = JIM_OK; Jim_Obj *A = ExprPop(e); double dA, dC = 0; jim_wide wA, wC = 0; if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { switch (e->opcode) { case JIM_EXPROP_FUNC_INT: case JIM_EXPROP_FUNC_WIDE: case JIM_EXPROP_FUNC_ROUND: case JIM_EXPROP_UNARYPLUS: wC = wA; break; case JIM_EXPROP_FUNC_DOUBLE: dC = wA; intresult = 0; break; case JIM_EXPROP_FUNC_ABS: wC = wA >= 0 ? wA : -wA; break; case JIM_EXPROP_UNARYMINUS: wC = -wA; break; case JIM_EXPROP_NOT: wC = !wA; break; default: abort(); } } else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { switch (e->opcode) { case JIM_EXPROP_FUNC_INT: case JIM_EXPROP_FUNC_WIDE: wC = dA; break; case JIM_EXPROP_FUNC_ROUND: wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); break; case JIM_EXPROP_FUNC_DOUBLE: case JIM_EXPROP_UNARYPLUS: dC = dA; intresult = 0; break; case JIM_EXPROP_FUNC_ABS: dC = dA >= 0 ? dA : -dA; intresult = 0; break; case JIM_EXPROP_UNARYMINUS: dC = -dA; intresult = 0; break; case JIM_EXPROP_NOT: wC = !dA; break; default: abort(); } } if (rc == JIM_OK) { if (intresult) { ExprPush(e, Jim_NewIntObj(interp, wC)); } else { ExprPush(e, Jim_NewDoubleObj(interp, dC)); } } Jim_DecrRefCount(interp, A); return rc; } static double JimRandDouble(Jim_Interp *interp) { unsigned long x; JimRandomBytes(interp, &x, sizeof(x)); return (double)x / (unsigned long)~0; } static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *A = ExprPop(e); jim_wide wA; int rc = Jim_GetWide(interp, A, &wA); if (rc == JIM_OK) { switch (e->opcode) { case JIM_EXPROP_BITNOT: ExprPush(e, Jim_NewIntObj(interp, ~wA)); break; case JIM_EXPROP_FUNC_SRAND: JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); break; default: abort(); } } Jim_DecrRefCount(interp, A); return rc; } static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) { JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); return JIM_OK; } #ifdef JIM_MATH_FUNCTIONS static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) { int rc; Jim_Obj *A = ExprPop(e); double dA, dC; rc = Jim_GetDouble(interp, A, &dA); if (rc == JIM_OK) { switch (e->opcode) { case JIM_EXPROP_FUNC_SIN: dC = sin(dA); break; case JIM_EXPROP_FUNC_COS: dC = cos(dA); break; case JIM_EXPROP_FUNC_TAN: dC = tan(dA); break; case JIM_EXPROP_FUNC_ASIN: dC = asin(dA); break; case JIM_EXPROP_FUNC_ACOS: dC = acos(dA); break; case JIM_EXPROP_FUNC_ATAN: dC = atan(dA); break; case JIM_EXPROP_FUNC_SINH: dC = sinh(dA); break; case JIM_EXPROP_FUNC_COSH: dC = cosh(dA); break; case JIM_EXPROP_FUNC_TANH: dC = tanh(dA); break; case JIM_EXPROP_FUNC_CEIL: dC = ceil(dA); break; case JIM_EXPROP_FUNC_FLOOR: dC = floor(dA); break; case JIM_EXPROP_FUNC_EXP: dC = exp(dA); break; case JIM_EXPROP_FUNC_LOG: dC = log(dA); break; case JIM_EXPROP_FUNC_LOG10: dC = log10(dA); break; case JIM_EXPROP_FUNC_SQRT: dC = sqrt(dA); break; default: abort(); } ExprPush(e, Jim_NewDoubleObj(interp, dC)); } Jim_DecrRefCount(interp, A); return rc; } #endif /* A binary operation on two ints */ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *B = ExprPop(e); Jim_Obj *A = ExprPop(e); jim_wide wA, wB; int rc = JIM_ERR; if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { jim_wide wC; rc = JIM_OK; switch (e->opcode) { case JIM_EXPROP_LSHIFT: wC = wA << wB; break; case JIM_EXPROP_RSHIFT: wC = wA >> wB; break; case JIM_EXPROP_BITAND: wC = wA & wB; break; case JIM_EXPROP_BITXOR: wC = wA ^ wB; break; case JIM_EXPROP_BITOR: wC = wA | wB; break; case JIM_EXPROP_MOD: if (wB == 0) { wC = 0; Jim_SetResultString(interp, "Division by zero", -1); rc = JIM_ERR; } else { /* * From Tcl 8.x * * This code is tricky: C doesn't guarantee much * about the quotient or remainder, but Tcl does. * The remainder always has the same sign as the * divisor and a smaller absolute value. */ int negative = 0; if (wB < 0) { wB = -wB; wA = -wA; negative = 1; } wC = wA % wB; if (wC < 0) { wC += wB; } if (negative) { wC = -wC; } } break; case JIM_EXPROP_ROTL: case JIM_EXPROP_ROTR:{ /* uint32_t would be better. But not everyone has inttypes.h? */ unsigned long uA = (unsigned long)wA; unsigned long uB = (unsigned long)wB; const unsigned int S = sizeof(unsigned long) * 8; /* Shift left by the word size or more is undefined. */ uB %= S; if (e->opcode == JIM_EXPROP_ROTR) { uB = S - uB; } wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); break; } default: abort(); } ExprPush(e, Jim_NewIntObj(interp, wC)); } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; } /* A binary operation on two ints or two doubles (or two strings for some ops) */ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) { int intresult = 1; int rc = JIM_OK; double dA, dB, dC = 0; jim_wide wA, wB, wC = 0; Jim_Obj *B = ExprPop(e); Jim_Obj *A = ExprPop(e); if ((A->typePtr != &doubleObjType || A->bytes) && (B->typePtr != &doubleObjType || B->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { /* Both are ints */ switch (e->opcode) { case JIM_EXPROP_POW: case JIM_EXPROP_FUNC_POW: wC = JimPowWide(wA, wB); break; case JIM_EXPROP_ADD: wC = wA + wB; break; case JIM_EXPROP_SUB: wC = wA - wB; break; case JIM_EXPROP_MUL: wC = wA * wB; break; case JIM_EXPROP_DIV: if (wB == 0) { Jim_SetResultString(interp, "Division by zero", -1); rc = JIM_ERR; } else { /* * From Tcl 8.x * * This code is tricky: C doesn't guarantee much * about the quotient or remainder, but Tcl does. * The remainder always has the same sign as the * divisor and a smaller absolute value. */ if (wB < 0) { wB = -wB; wA = -wA; } wC = wA / wB; if (wA % wB < 0) { wC--; } } break; case JIM_EXPROP_LT: wC = wA < wB; break; case JIM_EXPROP_GT: wC = wA > wB; break; case JIM_EXPROP_LTE: wC = wA <= wB; break; case JIM_EXPROP_GTE: wC = wA >= wB; break; case JIM_EXPROP_NUMEQ: wC = wA == wB; break; case JIM_EXPROP_NUMNE: wC = wA != wB; break; default: abort(); } } else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { intresult = 0; switch (e->opcode) { case JIM_EXPROP_POW: case JIM_EXPROP_FUNC_POW: #ifdef JIM_MATH_FUNCTIONS dC = pow(dA, dB); #else Jim_SetResultString(interp, "unsupported", -1); rc = JIM_ERR; #endif break; case JIM_EXPROP_ADD: dC = dA + dB; break; case JIM_EXPROP_SUB: dC = dA - dB; break; case JIM_EXPROP_MUL: dC = dA * dB; break; case JIM_EXPROP_DIV: if (dB == 0) { #ifdef INFINITY dC = dA < 0 ? -INFINITY : INFINITY; #else dC = (dA < 0 ? -1.0 : 1.0) * strtod("Inf", NULL); #endif } else { dC = dA / dB; } break; case JIM_EXPROP_LT: wC = dA < dB; intresult = 1; break; case JIM_EXPROP_GT: wC = dA > dB; intresult = 1; break; case JIM_EXPROP_LTE: wC = dA <= dB; intresult = 1; break; case JIM_EXPROP_GTE: wC = dA >= dB; intresult = 1; break; case JIM_EXPROP_NUMEQ: wC = dA == dB; intresult = 1; break; case JIM_EXPROP_NUMNE: wC = dA != dB; intresult = 1; break; default: abort(); } } else { /* Handle the string case */ /* XXX: Could optimise the eq/ne case by checking lengths */ int i = Jim_StringCompareObj(interp, A, B, 0); switch (e->opcode) { case JIM_EXPROP_LT: wC = i < 0; break; case JIM_EXPROP_GT: wC = i > 0; break; case JIM_EXPROP_LTE: wC = i <= 0; break; case JIM_EXPROP_GTE: wC = i >= 0; break; case JIM_EXPROP_NUMEQ: wC = i == 0; break; case JIM_EXPROP_NUMNE: wC = i != 0; break; default: rc = JIM_ERR; break; } } if (rc == JIM_OK) { if (intresult) { ExprPush(e, Jim_NewIntObj(interp, wC)); } else { ExprPush(e, Jim_NewDoubleObj(interp, dC)); } } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; } static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) { int listlen; int i; listlen = Jim_ListLength(interp, listObjPtr); for (i = 0; i < listlen; i++) { if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { return 1; } } return 0; } static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *B = ExprPop(e); Jim_Obj *A = ExprPop(e); jim_wide wC; switch (e->opcode) { case JIM_EXPROP_STREQ: case JIM_EXPROP_STRNE: wC = Jim_StringEqObj(A, B); if (e->opcode == JIM_EXPROP_STRNE) { wC = !wC; } break; case JIM_EXPROP_STRIN: wC = JimSearchList(interp, B, A); break; case JIM_EXPROP_STRNI: wC = !JimSearchList(interp, B, A); break; default: abort(); } ExprPush(e, Jim_NewIntObj(interp, wC)); Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return JIM_OK; } static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) { long l; double d; if (Jim_GetLong(interp, obj, &l) == JIM_OK) { return l != 0; } if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { return d != 0; } return -1; } static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *skip = ExprPop(e); Jim_Obj *A = ExprPop(e); int rc = JIM_OK; switch (ExprBool(interp, A)) { case 0: /* false, so skip RHS opcodes with a 0 result */ e->skip = JimWideValue(skip); ExprPush(e, Jim_NewIntObj(interp, 0)); break; case 1: /* true so continue */ break; case -1: /* Invalid */ rc = JIM_ERR; } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, skip); return rc; } static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *skip = ExprPop(e); Jim_Obj *A = ExprPop(e); int rc = JIM_OK; switch (ExprBool(interp, A)) { case 0: /* false, so do nothing */ break; case 1: /* true so skip RHS opcodes with a 1 result */ e->skip = JimWideValue(skip); ExprPush(e, Jim_NewIntObj(interp, 1)); break; case -1: /* Invalid */ rc = JIM_ERR; break; } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, skip); return rc; } static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *A = ExprPop(e); int rc = JIM_OK; switch (ExprBool(interp, A)) { case 0: ExprPush(e, Jim_NewIntObj(interp, 0)); break; case 1: ExprPush(e, Jim_NewIntObj(interp, 1)); break; case -1: /* Invalid */ rc = JIM_ERR; break; } Jim_DecrRefCount(interp, A); return rc; } static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *skip = ExprPop(e); Jim_Obj *A = ExprPop(e); int rc = JIM_OK; /* Repush A */ ExprPush(e, A); switch (ExprBool(interp, A)) { case 0: /* false, skip RHS opcodes */ e->skip = JimWideValue(skip); /* Push a dummy value */ ExprPush(e, Jim_NewIntObj(interp, 0)); break; case 1: /* true so do nothing */ break; case -1: /* Invalid */ rc = JIM_ERR; break; } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, skip); return rc; } static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) { Jim_Obj *skip = ExprPop(e); Jim_Obj *B = ExprPop(e); Jim_Obj *A = ExprPop(e); /* No need to check for A as non-boolean */ if (ExprBool(interp, A)) { /* true, so skip RHS opcodes */ e->skip = JimWideValue(skip); /* Repush B as the answer */ ExprPush(e, B); } Jim_DecrRefCount(interp, skip); Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return JIM_OK; } static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) { return JIM_OK; } enum { LAZY_NONE, LAZY_OP, LAZY_LEFT, LAZY_RIGHT }; /* name - precedence - arity - opcode * * This array *must* be kept in sync with the JIM_EXPROP enum. * * The following macros pre-compute the string length at compile time. */ #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} static const struct Jim_ExprOperator Jim_ExprOperators[] = { OPRINIT("*", 110, 2, JimExprOpBin), OPRINIT("/", 110, 2, JimExprOpBin), OPRINIT("%", 110, 2, JimExprOpIntBin), OPRINIT("-", 100, 2, JimExprOpBin), OPRINIT("+", 100, 2, JimExprOpBin), OPRINIT("<<", 90, 2, JimExprOpIntBin), OPRINIT(">>", 90, 2, JimExprOpIntBin), OPRINIT("<<<", 90, 2, JimExprOpIntBin), OPRINIT(">>>", 90, 2, JimExprOpIntBin), OPRINIT("<", 80, 2, JimExprOpBin), OPRINIT(">", 80, 2, JimExprOpBin), OPRINIT("<=", 80, 2, JimExprOpBin), OPRINIT(">=", 80, 2, JimExprOpBin), OPRINIT("==", 70, 2, JimExprOpBin), OPRINIT("!=", 70, 2, JimExprOpBin), OPRINIT("&", 50, 2, JimExprOpIntBin), OPRINIT("^", 49, 2, JimExprOpIntBin), OPRINIT("|", 48, 2, JimExprOpIntBin), OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), OPRINIT("**", 250, 2, JimExprOpBin), OPRINIT("eq", 60, 2, JimExprOpStrBin), OPRINIT("ne", 60, 2, JimExprOpStrBin), OPRINIT("in", 55, 2, JimExprOpStrBin), OPRINIT("ni", 55, 2, JimExprOpStrBin), OPRINIT("!", 150, 1, JimExprOpNumUnary), OPRINIT("~", 150, 1, JimExprOpIntUnary), OPRINIT(NULL, 150, 1, JimExprOpNumUnary), OPRINIT(NULL, 150, 1, JimExprOpNumUnary), OPRINIT("int", 200, 1, JimExprOpNumUnary), OPRINIT("wide", 200, 1, JimExprOpNumUnary), OPRINIT("abs", 200, 1, JimExprOpNumUnary), OPRINIT("double", 200, 1, JimExprOpNumUnary), OPRINIT("round", 200, 1, JimExprOpNumUnary), OPRINIT("rand", 200, 0, JimExprOpNone), OPRINIT("srand", 200, 1, JimExprOpIntUnary), #ifdef JIM_MATH_FUNCTIONS OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), OPRINIT("log", 200, 1, JimExprOpDoubleUnary), OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), OPRINIT("pow", 200, 2, JimExprOpBin), #endif }; #undef OPRINIT #undef OPRINIT_LAZY #define JIM_EXPR_OPERATORS_NUM \ (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) static int JimParseExpression(struct JimParserCtx *pc) { /* Discard spaces and quoted newline */ while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { if (*pc->p == '\n') { pc->linenr++; } pc->p++; pc->len--; } /* Common case */ pc->tline = pc->linenr; pc->tstart = pc->p; if (pc->len == 0) { pc->tend = pc->p; pc->tt = JIM_TT_EOL; pc->eof = 1; return JIM_OK; } switch (*(pc->p)) { case '(': pc->tt = JIM_TT_SUBEXPR_START; goto singlechar; case ')': pc->tt = JIM_TT_SUBEXPR_END; goto singlechar; case ',': pc->tt = JIM_TT_SUBEXPR_COMMA; singlechar: pc->tend = pc->p; pc->p++; pc->len--; break; case '[': return JimParseCmd(pc); case '$': if (JimParseVar(pc) == JIM_ERR) return JimParseExprOperator(pc); else { /* Don't allow expr sugar in expressions */ if (pc->tt == JIM_TT_EXPRSUGAR) { return JIM_ERR; } return JIM_OK; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': return JimParseExprNumber(pc); case '"': return JimParseQuote(pc); case '{': return JimParseBrace(pc); case 'N': case 'I': case 'n': case 'i': if (JimParseExprIrrational(pc) == JIM_ERR) return JimParseExprOperator(pc); break; default: return JimParseExprOperator(pc); break; } return JIM_OK; } static int JimParseExprNumber(struct JimParserCtx *pc) { char *end; /* Assume an integer for now */ pc->tt = JIM_TT_EXPR_INT; jim_strtoull(pc->p, (char **)&pc->p); /* Tried as an integer, but perhaps it parses as a double */ if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { /* Some stupid compilers insist they are cleverer that * we are. Even a (void) cast doesn't prevent this warning! */ if (strtod(pc->tstart, &end)) { /* nothing */ } if (end == pc->tstart) return JIM_ERR; if (end > pc->p) { /* Yes, double captured more chars */ pc->tt = JIM_TT_EXPR_DOUBLE; pc->p = end; } } pc->tend = pc->p - 1; pc->len -= (pc->p - pc->tstart); return JIM_OK; } static int JimParseExprIrrational(struct JimParserCtx *pc) { const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; int i; for (i = 0; irrationals[i]; i++) { const char *irr = irrationals[i]; if (strncmp(irr, pc->p, 3) == 0) { pc->p += 3; pc->len -= 3; pc->tend = pc->p - 1; pc->tt = JIM_TT_EXPR_DOUBLE; return JIM_OK; } } return JIM_ERR; } static int JimParseExprOperator(struct JimParserCtx *pc) { int i; int bestIdx = -1, bestLen = 0; /* Try to get the longest match. */ for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { const char * const opname = Jim_ExprOperators[i].name; const int oplen = Jim_ExprOperators[i].namelen; if (opname == NULL || opname[0] != pc->p[0]) { continue; } if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { bestIdx = i + JIM_TT_EXPR_OP; bestLen = oplen; } } if (bestIdx == -1) { return JIM_ERR; } /* Validate paretheses around function arguments */ if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { const char *p = pc->p + bestLen; int len = pc->len - bestLen; while (len && isspace(UCHAR(*p))) { len--; p++; } if (*p != '(') { return JIM_ERR; } } pc->tend = pc->p + bestLen - 1; pc->p += bestLen; pc->len -= bestLen; pc->tt = bestIdx; return JIM_OK; } static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) { static Jim_ExprOperator dummy_op; if (opcode < JIM_TT_EXPR_OP) { return &dummy_op; } return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; } const char *jim_tt_name(int type) { static const char * const tt_names[JIM_TT_EXPR_OP] = { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", "DBL", "$()" }; if (type < JIM_TT_EXPR_OP) { return tt_names[type]; } else { const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); static char buf[20]; if (op->name) { return op->name; } sprintf(buf, "(%d)", type); return buf; } } /* ----------------------------------------------------------------------------- * Expression Object * ---------------------------------------------------------------------------*/ static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static const Jim_ObjType exprObjType = { "expression", FreeExprInternalRep, DupExprInternalRep, NULL, JIM_TYPE_REFERENCES, }; /* Expr bytecode structure */ typedef struct ExprByteCode { ScriptToken *token; /* Tokens array. */ int len; /* Length as number of tokens. */ int inUse; /* Used for sharing. */ } ExprByteCode; static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) { int i; for (i = 0; i < expr->len; i++) { Jim_DecrRefCount(interp, expr->token[i].objPtr); } Jim_Free(expr->token); Jim_Free(expr); } static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { ExprByteCode *expr = (void *)objPtr->internalRep.ptr; if (expr) { if (--expr->inUse != 0) { return; } ExprFreeByteCode(interp, expr); } } static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { JIM_NOTUSED(interp); JIM_NOTUSED(srcPtr); /* Just returns an simple string. */ dupPtr->typePtr = NULL; } /* Check if an expr program looks correct. */ static int ExprCheckCorrectness(ExprByteCode * expr) { int i; int stacklen = 0; int ternary = 0; /* Try to check if there are stack underflows, * and make sure at the end of the program there is * a single result on the stack. */ for (i = 0; i < expr->len; i++) { ScriptToken *t = &expr->token[i]; const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); stacklen -= op->arity; if (stacklen < 0) { break; } if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { ternary++; } else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { ternary--; } /* All operations and operands add one to the stack */ stacklen++; } if (stacklen != 1 || ternary != 0) { return JIM_ERR; } return JIM_OK; } /* This procedure converts every occurrence of || and && opereators * in lazy unary versions. * * a b || is converted into: * * a |L b |R * * a b && is converted into: * * a &L b &R * * "|L" checks if 'a' is true: * 1) if it is true pushes 1 and skips instructions to reach * the opcode just after |R. * 2) if it is false does nothing. * "|R" checks if 'b' is true: * 1) if it is true pushes 1, otherwise pushes 0. * * "&L" checks if 'a' is true: * 1) if it is true does nothing. * 2) If it is false pushes 0 and skips instructions to reach * the opcode just after &R * "&R" checks if 'a' is true: * if it is true pushes 1, otherwise pushes 0. */ static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) { int i; int leftindex, arity, offset; /* Search for the end of the first operator */ leftindex = expr->len - 1; arity = 1; while (arity) { ScriptToken *tt = &expr->token[leftindex]; if (tt->type >= JIM_TT_EXPR_OP) { arity += JimExprOperatorInfoByOpcode(tt->type)->arity; } arity--; if (--leftindex < 0) { return JIM_ERR; } } leftindex++; /* Move them up */ memmove(&expr->token[leftindex + 2], &expr->token[leftindex], sizeof(*expr->token) * (expr->len - leftindex)); expr->len += 2; offset = (expr->len - leftindex) - 1; /* Now we rely on the fact the the left and right version have opcodes * 1 and 2 after the main opcode respectively */ expr->token[leftindex + 1].type = t->type + 1; expr->token[leftindex + 1].objPtr = interp->emptyObj; expr->token[leftindex].type = JIM_TT_EXPR_INT; expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); /* Now add the 'R' operator */ expr->token[expr->len].objPtr = interp->emptyObj; expr->token[expr->len].type = t->type + 2; expr->len++; /* Do we need to adjust the skip count for any &L, |L, ?L or :L in the left operand? */ for (i = leftindex - 1; i > 0; i--) { const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type); if (op->lazy == LAZY_LEFT) { if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { JimWideValue(expr->token[i - 1].objPtr) += 2; } } } return JIM_OK; } static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) { struct ScriptToken *token = &expr->token[expr->len]; const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); if (op->lazy == LAZY_OP) { if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); return JIM_ERR; } } else { token->objPtr = interp->emptyObj; token->type = t->type; expr->len++; } return JIM_OK; } /** * Returns the index of the COLON_LEFT to the left of 'right_index' * taking into account nesting. * * The expression *must* be well formed, thus a COLON_LEFT will always be found. */ static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) { int ternary_count = 1; right_index--; while (right_index > 1) { if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { ternary_count--; } else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { ternary_count++; } else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { return right_index; } right_index--; } /*notreached*/ return -1; } /** * Find the left/right indices for the ternary expression to the left of 'right_index'. * * Returns 1 if found, and fills in *prev_right_index and *prev_left_index. * Otherwise returns 0. */ static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) { int i = right_index - 1; int ternary_count = 1; while (i > 1) { if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { *prev_right_index = i - 2; *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); return 1; } } else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { if (ternary_count == 0) { return 0; } ternary_count++; } i--; } return 0; } /* * ExprTernaryReorderExpression description * ======================================== * * ?: is right-to-left associative which doesn't work with the stack-based * expression engine. The fix is to reorder the bytecode. * * The expression: * * expr 1?2:0?3:4 * * Has initial bytecode: * * '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '0' (44=COLON_RIGHT) * '2' (40=TERNARY_LEFT) '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) * * The fix involves simulating this expression instead: * * expr 1?2:(0?3:4) * * With the following bytecode: * * '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '10' (43=COLON_LEFT) '0' '2' (40=TERNARY_LEFT) * '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) (44=COLON_RIGHT) * * i.e. The token COLON_RIGHT at index 8 is moved towards the end of the stack, all tokens above 8 * are shifted down and the skip count of the token JIM_EXPROP_COLON_LEFT at index 5 is * incremented by the amount tokens shifted down. The token JIM_EXPROP_COLON_RIGHT that is moved * is identified as immediately preceeding a token JIM_EXPROP_TERNARY_LEFT * * ExprTernaryReorderExpression works thus as follows : * - start from the end of the stack * - while walking towards the beginning of the stack * if token=JIM_EXPROP_COLON_RIGHT then * find the associated token JIM_EXPROP_TERNARY_LEFT, which allows to * find the associated token previous(JIM_EXPROP_COLON_RIGHT) * find the associated token previous(JIM_EXPROP_LEFT_RIGHT) * if all found then * perform the rotation * update the skip count of the token previous(JIM_EXPROP_LEFT_RIGHT) * end if * end if * * Note: care has to be taken for nested ternary constructs!!! */ static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) { int i; for (i = expr->len - 1; i > 1; i--) { int prev_right_index; int prev_left_index; int j; ScriptToken tmp; if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { continue; } /* COLON_RIGHT found: get the indexes needed to move the tokens in the stack (if any) */ if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { continue; } /* ** rotate tokens down ** ** +-> [i] : JIM_EXPROP_COLON_RIGHT ** | | | ** | V V ** | [...] : ... ** | | | ** | V V ** | [...] : ... ** | | | ** | V V ** +- [prev_right_index] : JIM_EXPROP_COLON_RIGHT */ tmp = expr->token[prev_right_index]; for (j = prev_right_index; j < i; j++) { expr->token[j] = expr->token[j + 1]; } expr->token[i] = tmp; /* Increment the 'skip' count associated to the previous JIM_EXPROP_COLON_LEFT token * * This is 'colon left increment' = i - prev_right_index * * [prev_left_index] : JIM_EXPROP_LEFT_RIGHT * [prev_left_index-1] : skip_count * */ JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); /* Adjust for i-- in the loop */ i++; } } static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) { Jim_Stack stack; ExprByteCode *expr; int ok = 1; int i; int prevtt = JIM_TT_NONE; int have_ternary = 0; /* -1 for EOL */ int count = tokenlist->count - 1; expr = Jim_Alloc(sizeof(*expr)); expr->inUse = 1; expr->len = 0; Jim_InitStack(&stack); /* Need extra bytecodes for lazy operators. * Also check for the ternary operator */ for (i = 0; i < tokenlist->count; i++) { ParseToken *t = &tokenlist->list[i]; const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); if (op->lazy == LAZY_OP) { count += 2; /* Ternary is a lazy op but also needs reordering */ if (t->type == JIM_EXPROP_TERNARY) { have_ternary = 1; } } } expr->token = Jim_Alloc(sizeof(ScriptToken) * count); for (i = 0; i < tokenlist->count && ok; i++) { ParseToken *t = &tokenlist->list[i]; /* Next token will be stored here */ struct ScriptToken *token = &expr->token[expr->len]; if (t->type == JIM_TT_EOL) { break; } switch (t->type) { case JIM_TT_STR: case JIM_TT_ESC: case JIM_TT_VAR: case JIM_TT_DICTSUGAR: case JIM_TT_EXPRSUGAR: case JIM_TT_CMD: token->type = t->type; strexpr: token->objPtr = Jim_NewStringObj(interp, t->token, t->len); if (t->type == JIM_TT_CMD) { /* Only commands need source info */ JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); } expr->len++; break; case JIM_TT_EXPR_INT: case JIM_TT_EXPR_DOUBLE: { char *endptr; if (t->type == JIM_TT_EXPR_INT) { token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); } else { token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); } if (endptr != t->token + t->len) { /* Conversion failed, so just store it as a string */ Jim_FreeNewObj(interp, token->objPtr); token->type = JIM_TT_STR; goto strexpr; } token->type = t->type; expr->len++; } break; case JIM_TT_SUBEXPR_START: Jim_StackPush(&stack, t); prevtt = JIM_TT_NONE; continue; case JIM_TT_SUBEXPR_COMMA: /* Simple approach. Comma is simply ignored */ continue; case JIM_TT_SUBEXPR_END: ok = 0; while (Jim_StackLen(&stack)) { ParseToken *tt = Jim_StackPop(&stack); if (tt->type == JIM_TT_SUBEXPR_START) { ok = 1; break; } if (ExprAddOperator(interp, expr, tt) != JIM_OK) { goto err; } } if (!ok) { Jim_SetResultString(interp, "Unexpected close parenthesis", -1); goto err; } break; default:{ /* Must be an operator */ const struct Jim_ExprOperator *op; ParseToken *tt; /* Convert -/+ to unary minus or unary plus if necessary */ if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { if (t->type == JIM_EXPROP_SUB) { t->type = JIM_EXPROP_UNARYMINUS; } else if (t->type == JIM_EXPROP_ADD) { t->type = JIM_EXPROP_UNARYPLUS; } } op = JimExprOperatorInfoByOpcode(t->type); /* Now handle precedence */ while ((tt = Jim_StackPeek(&stack)) != NULL) { const struct Jim_ExprOperator *tt_op = JimExprOperatorInfoByOpcode(tt->type); /* Note that right-to-left associativity of ?: operator is handled later */ if (op->arity != 1 && tt_op->precedence >= op->precedence) { if (ExprAddOperator(interp, expr, tt) != JIM_OK) { ok = 0; goto err; } Jim_StackPop(&stack); } else { break; } } Jim_StackPush(&stack, t); break; } } prevtt = t->type; } /* Reduce any remaining subexpr */ while (Jim_StackLen(&stack)) { ParseToken *tt = Jim_StackPop(&stack); if (tt->type == JIM_TT_SUBEXPR_START) { ok = 0; Jim_SetResultString(interp, "Missing close parenthesis", -1); goto err; } if (ExprAddOperator(interp, expr, tt) != JIM_OK) { ok = 0; goto err; } } if (have_ternary) { ExprTernaryReorderExpression(interp, expr); } err: /* Free the stack used for the compilation. */ Jim_FreeStack(&stack); for (i = 0; i < expr->len; i++) { Jim_IncrRefCount(expr->token[i].objPtr); } if (!ok) { ExprFreeByteCode(interp, expr); return NULL; } return expr; } /* This method takes the string representation of an expression * and generates a program for the Expr's stack-based VM. */ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { int exprTextLen; const char *exprText; struct JimParserCtx parser; struct ExprByteCode *expr; ParseTokenList tokenlist; int line; Jim_Obj *fileNameObj; int rc = JIM_ERR; /* Try to get information about filename / line number */ if (objPtr->typePtr == &sourceObjType) { fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; line = objPtr->internalRep.sourceValue.lineNumber; } else { fileNameObj = interp->emptyObj; line = 1; } Jim_IncrRefCount(fileNameObj); exprText = Jim_GetString(objPtr, &exprTextLen); /* Initially tokenise the expression into tokenlist */ ScriptTokenListInit(&tokenlist); JimParserInit(&parser, exprText, exprTextLen, line); while (!parser.eof) { if (JimParseExpression(&parser) != JIM_OK) { ScriptTokenListFree(&tokenlist); invalidexpr: Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); expr = NULL; goto err; } ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, parser.tline); } #ifdef DEBUG_SHOW_EXPR_TOKENS { int i; printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj)); for (i = 0; i < tokenlist.count; i++) { printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), tokenlist.list[i].len, tokenlist.list[i].token); } } #endif if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { ScriptTokenListFree(&tokenlist); Jim_DecrRefCount(interp, fileNameObj); return JIM_ERR; } /* Now create the expression bytecode from the tokenlist */ expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); /* No longer need the token list */ ScriptTokenListFree(&tokenlist); if (!expr) { goto err; } #ifdef DEBUG_SHOW_EXPR { int i; printf("==== Expr ====\n"); for (i = 0; i < expr->len; i++) { ScriptToken *t = &expr->token[i]; printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); } } #endif /* Check program correctness. */ if (ExprCheckCorrectness(expr) != JIM_OK) { ExprFreeByteCode(interp, expr); goto invalidexpr; } rc = JIM_OK; err: /* Free the old internal rep and set the new one. */ Jim_DecrRefCount(interp, fileNameObj); Jim_FreeIntRep(interp, objPtr); Jim_SetIntRepPtr(objPtr, expr); objPtr->typePtr = &exprObjType; return rc; } static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &exprObjType) { if (SetExprFromAny(interp, objPtr) != JIM_OK) { return NULL; } } return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); } #ifdef JIM_OPTIMIZATION static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) { if (token->type == JIM_TT_EXPR_INT) return token->objPtr; else if (token->type == JIM_TT_VAR) return Jim_GetVariable(interp, token->objPtr, JIM_NONE); else if (token->type == JIM_TT_DICTSUGAR) return JimExpandDictSugar(interp, token->objPtr); else return NULL; } #endif /* ----------------------------------------------------------------------------- * Expressions evaluation. * Jim uses a specialized stack-based virtual machine for expressions, * that takes advantage of the fact that expr's operators * can't be redefined. * * Jim_EvalExpression() uses the bytecode compiled by * SetExprFromAny() method of the "expression" object. * * On success a Tcl Object containing the result of the evaluation * is stored into expResultPtrPtr (having refcount of 1), and JIM_OK is * returned. * On error the function returns a retcode != to JIM_OK and set a suitable * error on the interp. * ---------------------------------------------------------------------------*/ #define JIM_EE_STATICSTACK_LEN 10 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) { ExprByteCode *expr; Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; int i; int retcode = JIM_OK; struct JimExprState e; expr = JimGetExpression(interp, exprObjPtr); if (!expr) { return JIM_ERR; /* error in expression. */ } #ifdef JIM_OPTIMIZATION /* Check for one of the following common expressions used by while/for * * CONST * $a * !$a * $a < CONST, $a < $b * $a <= CONST, $a <= $b * $a > CONST, $a > $b * $a >= CONST, $a >= $b * $a != CONST, $a != $b * $a == CONST, $a == $b */ { Jim_Obj *objPtr; /* STEP 1 -- Check if there are the conditions to run the specialized * version of while */ switch (expr->len) { case 1: objPtr = JimExprIntValOrVar(interp, &expr->token[0]); if (objPtr) { Jim_IncrRefCount(objPtr); *exprResultPtrPtr = objPtr; return JIM_OK; } break; case 2: if (expr->token[1].type == JIM_EXPROP_NOT) { objPtr = JimExprIntValOrVar(interp, &expr->token[0]); if (objPtr && JimIsWide(objPtr)) { *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; Jim_IncrRefCount(*exprResultPtrPtr); return JIM_OK; } } break; case 3: objPtr = JimExprIntValOrVar(interp, &expr->token[0]); if (objPtr && JimIsWide(objPtr)) { Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); if (objPtr2 && JimIsWide(objPtr2)) { jim_wide wideValueA = JimWideValue(objPtr); jim_wide wideValueB = JimWideValue(objPtr2); int cmpRes; switch (expr->token[2].type) { case JIM_EXPROP_LT: cmpRes = wideValueA < wideValueB; break; case JIM_EXPROP_LTE: cmpRes = wideValueA <= wideValueB; break; case JIM_EXPROP_GT: cmpRes = wideValueA > wideValueB; break; case JIM_EXPROP_GTE: cmpRes = wideValueA >= wideValueB; break; case JIM_EXPROP_NUMEQ: cmpRes = wideValueA == wideValueB; break; case JIM_EXPROP_NUMNE: cmpRes = wideValueA != wideValueB; break; default: goto noopt; } *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; Jim_IncrRefCount(*exprResultPtrPtr); return JIM_OK; } } break; } } noopt: #endif /* In order to avoid that the internal repr gets freed due to * shimmering of the exprObjPtr's object, we make the internal rep * shared. */ expr->inUse++; /* The stack-based expr VM itself */ /* Stack allocation. Expr programs have the feature that * a program of length N can't require a stack longer than * N. */ if (expr->len > JIM_EE_STATICSTACK_LEN) e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); else e.stack = staticStack; e.stacklen = 0; /* Execute every instruction */ for (i = 0; i < expr->len && retcode == JIM_OK; i++) { Jim_Obj *objPtr; switch (expr->token[i].type) { case JIM_TT_EXPR_INT: case JIM_TT_EXPR_DOUBLE: case JIM_TT_STR: ExprPush(&e, expr->token[i].objPtr); break; case JIM_TT_VAR: objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); if (objPtr) { ExprPush(&e, objPtr); } else { retcode = JIM_ERR; } break; case JIM_TT_DICTSUGAR: objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); if (objPtr) { ExprPush(&e, objPtr); } else { retcode = JIM_ERR; } break; case JIM_TT_ESC: retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); if (retcode == JIM_OK) { ExprPush(&e, objPtr); } break; case JIM_TT_CMD: retcode = Jim_EvalObj(interp, expr->token[i].objPtr); if (retcode == JIM_OK) { ExprPush(&e, Jim_GetResult(interp)); } break; default:{ /* Find and execute the operation */ e.skip = 0; e.opcode = expr->token[i].type; retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); /* Skip some opcodes if necessary */ i += e.skip; continue; } } } expr->inUse--; if (retcode == JIM_OK) { *exprResultPtrPtr = ExprPop(&e); } else { for (i = 0; i < e.stacklen; i++) { Jim_DecrRefCount(interp, e.stack[i]); } } if (e.stack != staticStack) { Jim_Free(e.stack); } return retcode; } int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) { int retcode; jim_wide wideValue; double doubleValue; Jim_Obj *exprResultPtr; retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); if (retcode != JIM_OK) return retcode; if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { Jim_DecrRefCount(interp, exprResultPtr); return JIM_ERR; } else { Jim_DecrRefCount(interp, exprResultPtr); *boolPtr = doubleValue != 0; return JIM_OK; } } *boolPtr = wideValue != 0; Jim_DecrRefCount(interp, exprResultPtr); return JIM_OK; } /* ----------------------------------------------------------------------------- * ScanFormat String Object * ---------------------------------------------------------------------------*/ /* This Jim_Obj will held a parsed representation of a format string passed to * the Jim_ScanString command. For error diagnostics, the scanformat string has * to be parsed in its entirely first and then, if correct, can be used for * scanning. To avoid endless re-parsing, the parsed representation will be * stored in an internal representation and re-used for performance reason. */ /* A ScanFmtPartDescr will held the information of /one/ part of the whole * scanformat string. This part will later be used to extract information * out from the string to be parsed by Jim_ScanString */ typedef struct ScanFmtPartDescr { char *arg; /* Specification of a CHARSET conversion */ char *prefix; /* Prefix to be scanned literally before conversion */ size_t width; /* Maximal width of input to be converted */ int pos; /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */ char type; /* Type of conversion (e.g. c, d, f) */ char modifier; /* Modify type (e.g. l - long, h - short */ } ScanFmtPartDescr; /* The ScanFmtStringObj will hold the internal representation of a scanformat * string parsed and separated in part descriptions. Furthermore it contains * the original string representation of the scanformat string to allow for * fast update of the Jim_Obj's string representation part. * * As an add-on the internal object representation adds some scratch pad area * for usage by Jim_ScanString to avoid endless allocating and freeing of * memory for purpose of string scanning. * * The error member points to a static allocated string in case of a mal- * formed scanformat string or it contains '0' (NULL) in case of a valid * parse representation. * * The whole memory of the internal representation is allocated as a single * area of memory that will be internally separated. So freeing and duplicating * of such an object is cheap */ typedef struct ScanFmtStringObj { jim_wide size; /* Size of internal repr in bytes */ char *stringRep; /* Original string representation */ size_t count; /* Number of ScanFmtPartDescr contained */ size_t convCount; /* Number of conversions that will assign */ size_t maxPos; /* Max position index if XPG3 is used */ const char *error; /* Ptr to error text (NULL if no error */ char *scratch; /* Some scratch pad used by Jim_ScanString */ ScanFmtPartDescr descr[1]; /* The vector of partial descriptions */ } ScanFmtStringObj; static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static void UpdateStringOfScanFmt(Jim_Obj *objPtr); static const Jim_ObjType scanFmtStringObjType = { "scanformatstring", FreeScanFmtInternalRep, DupScanFmtInternalRep, UpdateStringOfScanFmt, JIM_TYPE_NONE, }; void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { JIM_NOTUSED(interp); Jim_Free((char *)objPtr->internalRep.ptr); objPtr->internalRep.ptr = 0; } void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { size_t size = (size_t) ((ScanFmtStringObj *) srcPtr->internalRep.ptr)->size; ScanFmtStringObj *newVec = (ScanFmtStringObj *) Jim_Alloc(size); JIM_NOTUSED(interp); memcpy(newVec, srcPtr->internalRep.ptr, size); dupPtr->internalRep.ptr = newVec; dupPtr->typePtr = &scanFmtStringObjType; } static void UpdateStringOfScanFmt(Jim_Obj *objPtr) { JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep); } /* SetScanFmtFromAny will parse a given string and create the internal * representation of the format specification. In case of an error * the error data member of the internal representation will be set * to an descriptive error text and the function will be left with * JIM_ERR to indicate unsucessful parsing (aka. malformed scanformat * specification */ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { ScanFmtStringObj *fmtObj; char *buffer; int maxCount, i, approxSize, lastPos = -1; const char *fmt = objPtr->bytes; int maxFmtLen = objPtr->length; const char *fmtEnd = fmt + maxFmtLen; int curr; Jim_FreeIntRep(interp, objPtr); /* Count how many conversions could take place maximally */ for (i = 0, maxCount = 0; i < maxFmtLen; ++i) if (fmt[i] == '%') ++maxCount; /* Calculate an approximation of the memory necessary */ approxSize = sizeof(ScanFmtStringObj) /* Size of the container */ +(maxCount + 1) * sizeof(ScanFmtPartDescr) /* Size of all partials */ +maxFmtLen * sizeof(char) + 3 + 1 /* Scratch + "%n" + '\0' */ + maxFmtLen * sizeof(char) + 1 /* Original stringrep */ + maxFmtLen * sizeof(char) /* Arg for CHARSETs */ +(maxCount + 1) * sizeof(char) /* '\0' for every partial */ +1; /* safety byte */ fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); memset(fmtObj, 0, approxSize); fmtObj->size = approxSize; fmtObj->maxPos = 0; fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; fmtObj->stringRep = fmtObj->scratch + maxFmtLen + 3 + 1; memcpy(fmtObj->stringRep, fmt, maxFmtLen); buffer = fmtObj->stringRep + maxFmtLen + 1; objPtr->internalRep.ptr = fmtObj; objPtr->typePtr = &scanFmtStringObjType; for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { int width = 0, skip; ScanFmtPartDescr *descr = &fmtObj->descr[curr]; fmtObj->count++; descr->width = 0; /* Assume width unspecified */ /* Overread and store any "literal" prefix */ if (*fmt != '%' || fmt[1] == '%') { descr->type = 0; descr->prefix = &buffer[i]; for (; fmt < fmtEnd; ++fmt) { if (*fmt == '%') { if (fmt[1] != '%') break; ++fmt; } buffer[i++] = *fmt; } buffer[i++] = 0; } /* Skip the conversion introducing '%' sign */ ++fmt; /* End reached due to non-conversion literal only? */ if (fmt >= fmtEnd) goto done; descr->pos = 0; /* Assume "natural" positioning */ if (*fmt == '*') { descr->pos = -1; /* Okay, conversion will not be assigned */ ++fmt; } else fmtObj->convCount++; /* Otherwise count as assign-conversion */ /* Check if next token is a number (could be width or pos */ if (sscanf(fmt, "%d%n", &width, &skip) == 1) { fmt += skip; /* Was the number a XPG3 position specifier? */ if (descr->pos != -1 && *fmt == '$') { int prev; ++fmt; descr->pos = width; width = 0; /* Look if "natural" postioning and XPG3 one was mixed */ if ((lastPos == 0 && descr->pos > 0) || (lastPos > 0 && descr->pos == 0)) { fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; return JIM_ERR; } /* Look if this position was already used */ for (prev = 0; prev < curr; ++prev) { if (fmtObj->descr[prev].pos == -1) continue; if (fmtObj->descr[prev].pos == descr->pos) { fmtObj->error = "variable is assigned by multiple \"%n$\" conversion specifiers"; return JIM_ERR; } } /* Try to find a width after the XPG3 specifier */ if (sscanf(fmt, "%d%n", &width, &skip) == 1) { descr->width = width; fmt += skip; } if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) fmtObj->maxPos = descr->pos; } else { /* Number was not a XPG3, so it has to be a width */ descr->width = width; } } /* If positioning mode was undetermined yet, fix this */ if (lastPos == -1) lastPos = descr->pos; /* Handle CHARSET conversion type ... */ if (*fmt == '[') { int swapped = 1, beg = i, end, j; descr->type = '['; descr->arg = &buffer[i]; ++fmt; if (*fmt == '^') buffer[i++] = *fmt++; if (*fmt == ']') buffer[i++] = *fmt++; while (*fmt && *fmt != ']') buffer[i++] = *fmt++; if (*fmt != ']') { fmtObj->error = "unmatched [ in format string"; return JIM_ERR; } end = i; buffer[i++] = 0; /* In case a range fence was given "backwards", swap it */ while (swapped) { swapped = 0; for (j = beg + 1; j < end - 1; ++j) { if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { char tmp = buffer[j - 1]; buffer[j - 1] = buffer[j + 1]; buffer[j + 1] = tmp; swapped = 1; } } } } else { /* Remember any valid modifier if given */ if (strchr("hlL", *fmt) != 0) descr->modifier = tolower((int)*fmt++); descr->type = *fmt; if (strchr("efgcsndoxui", *fmt) == 0) { fmtObj->error = "bad scan conversion character"; return JIM_ERR; } else if (*fmt == 'c' && descr->width != 0) { fmtObj->error = "field width may not be specified in %c " "conversion"; return JIM_ERR; } else if (*fmt == 'u' && descr->modifier == 'l') { fmtObj->error = "unsigned wide not supported"; return JIM_ERR; } } curr++; } done: return JIM_OK; } /* Some accessor macros to allow lowlevel access to fields of internal repr */ #define FormatGetCnvCount(_fo_) \ ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount #define FormatGetMaxPos(_fo_) \ ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->maxPos #define FormatGetError(_fo_) \ ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error /* JimScanAString is used to scan an unspecified string that ends with * next WS, or a string that is specified via a charset. * */ static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str) { char *buffer = Jim_StrDup(str); char *p = buffer; while (*str) { int c; int n; if (!sdescr && isspace(UCHAR(*str))) break; /* EOS via WS if unspecified */ n = utf8_tounicode(str, &c); if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) break; while (n--) *p++ = *str++; } *p = 0; return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer); } /* ScanOneEntry will scan one entry out of the string passed as argument. * It use the sscanf() function for this task. After extracting and * converting of the value, the count of scanned characters will be * returned of -1 in case of no conversion tool place and string was * already scanned thru */ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen, ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr) { const char *tok; const ScanFmtPartDescr *descr = &fmtObj->descr[idx]; size_t scanned = 0; size_t anchor = pos; int i; Jim_Obj *tmpObj = NULL; /* First pessimistically assume, we will not scan anything :-) */ *valObjPtr = 0; if (descr->prefix) { /* There was a prefix given before the conversion, skip it and adjust * the string-to-be-parsed accordingly */ for (i = 0; pos < strLen && descr->prefix[i]; ++i) { /* If prefix require, skip WS */ if (isspace(UCHAR(descr->prefix[i]))) while (pos < strLen && isspace(UCHAR(str[pos]))) ++pos; else if (descr->prefix[i] != str[pos]) break; /* Prefix do not match here, leave the loop */ else ++pos; /* Prefix matched so far, next round */ } if (pos >= strLen) { return -1; /* All of str consumed: EOF condition */ } else if (descr->prefix[i] != 0) return 0; /* Not whole prefix consumed, no conversion possible */ } /* For all but following conversion, skip leading WS */ if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') while (isspace(UCHAR(str[pos]))) ++pos; /* Determine how much skipped/scanned so far */ scanned = pos - anchor; /* %c is a special, simple case. no width */ if (descr->type == 'n') { /* Return pseudo conversion means: how much scanned so far? */ *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); } else if (pos >= strLen) { /* Cannot scan anything, as str is totally consumed */ return -1; } else if (descr->type == 'c') { int c; scanned += utf8_tounicode(&str[pos], &c); *valObjPtr = Jim_NewIntObj(interp, c); return scanned; } else { /* Processing of conversions follows ... */ if (descr->width > 0) { /* Do not try to scan as fas as possible but only the given width. * To ensure this, we copy the part that should be scanned. */ size_t sLen = utf8_strlen(&str[pos], strLen - pos); size_t tLen = descr->width > sLen ? sLen : descr->width; tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); tok = tmpObj->bytes; } else { /* As no width was given, simply refer to the original string */ tok = &str[pos]; } switch (descr->type) { case 'd': case 'o': case 'x': case 'u': case 'i':{ char *endp; /* Position where the number finished */ jim_wide w; int base = descr->type == 'o' ? 8 : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; /* Try to scan a number with the given base */ if (base == 0) { w = jim_strtoull(tok, &endp); } else { w = strtoull(tok, &endp, base); } if (endp != tok) { /* There was some number sucessfully scanned! */ *valObjPtr = Jim_NewIntObj(interp, w); /* Adjust the number-of-chars scanned so far */ scanned += endp - tok; } else { /* Nothing was scanned. We have to determine if this * happened due to e.g. prefix mismatch or input str * exhausted */ scanned = *tok ? 0 : -1; } break; } case 's': case '[':{ *valObjPtr = JimScanAString(interp, descr->arg, tok); scanned += Jim_Length(*valObjPtr); break; } case 'e': case 'f': case 'g':{ char *endp; double value = strtod(tok, &endp); if (endp != tok) { /* There was some number sucessfully scanned! */ *valObjPtr = Jim_NewDoubleObj(interp, value); /* Adjust the number-of-chars scanned so far */ scanned += endp - tok; } else { /* Nothing was scanned. We have to determine if this * happened due to e.g. prefix mismatch or input str * exhausted */ scanned = *tok ? 0 : -1; } break; } } /* If a substring was allocated (due to pre-defined width) do not * forget to free it */ if (tmpObj) { Jim_FreeNewObj(interp, tmpObj); } } return scanned; } /* Jim_ScanString is the workhorse of string scanning. It will scan a given * string and returns all converted (and not ignored) values in a list back * to the caller. If an error occured, a NULL pointer will be returned */ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags) { size_t i, pos; int scanned = 1; const char *str = Jim_String(strObjPtr); int strLen = Jim_Utf8Length(interp, strObjPtr); Jim_Obj *resultList = 0; Jim_Obj **resultVec = 0; int resultc; Jim_Obj *emptyStr = 0; ScanFmtStringObj *fmtObj; /* This should never happen. The format object should already be of the correct type */ JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; /* Check if format specification was valid */ if (fmtObj->error != 0) { if (flags & JIM_ERRMSG) Jim_SetResultString(interp, fmtObj->error, -1); return 0; } /* Allocate a new "shared" empty string for all unassigned conversions */ emptyStr = Jim_NewEmptyStringObj(interp); Jim_IncrRefCount(emptyStr); /* Create a list and fill it with empty strings up to max specified XPG3 */ resultList = Jim_NewListObj(interp, NULL, 0); if (fmtObj->maxPos > 0) { for (i = 0; i < fmtObj->maxPos; ++i) Jim_ListAppendElement(interp, resultList, emptyStr); JimListGetElements(interp, resultList, &resultc, &resultVec); } /* Now handle every partial format description */ for (i = 0, pos = 0; i < fmtObj->count; ++i) { ScanFmtPartDescr *descr = &(fmtObj->descr[i]); Jim_Obj *value = 0; /* Only last type may be "literal" w/o conversion - skip it! */ if (descr->type == 0) continue; /* As long as any conversion could be done, we will proceed */ if (scanned > 0) scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); /* In case our first try results in EOF, we will leave */ if (scanned == -1 && i == 0) goto eof; /* Advance next pos-to-be-scanned for the amount scanned already */ pos += scanned; /* value == 0 means no conversion took place so take empty string */ if (value == 0) value = Jim_NewEmptyStringObj(interp); /* If value is a non-assignable one, skip it */ if (descr->pos == -1) { Jim_FreeNewObj(interp, value); } else if (descr->pos == 0) /* Otherwise append it to the result list if no XPG3 was given */ Jim_ListAppendElement(interp, resultList, value); else if (resultVec[descr->pos - 1] == emptyStr) { /* But due to given XPG3, put the value into the corr. slot */ Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); Jim_IncrRefCount(value); resultVec[descr->pos - 1] = value; } else { /* Otherwise, the slot was already used - free obj and ERROR */ Jim_FreeNewObj(interp, value); goto err; } } Jim_DecrRefCount(interp, emptyStr); return resultList; eof: Jim_DecrRefCount(interp, emptyStr); Jim_FreeNewObj(interp, resultList); return (Jim_Obj *)EOF; err: Jim_DecrRefCount(interp, emptyStr); Jim_FreeNewObj(interp, resultList); return 0; } /* ----------------------------------------------------------------------------- * Pseudo Random Number Generation * ---------------------------------------------------------------------------*/ /* Initialize the sbox with the numbers from 0 to 255 */ static void JimPrngInit(Jim_Interp *interp) { #define PRNG_SEED_SIZE 256 int i; unsigned int *seed; time_t t = time(NULL); interp->prngState = Jim_Alloc(sizeof(Jim_PrngState)); seed = Jim_Alloc(PRNG_SEED_SIZE * sizeof(*seed)); for (i = 0; i < PRNG_SEED_SIZE; i++) { seed[i] = (rand() ^ t ^ clock()); } JimPrngSeed(interp, (unsigned char *)seed, PRNG_SEED_SIZE * sizeof(*seed)); Jim_Free(seed); } /* Generates N bytes of random data */ static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len) { Jim_PrngState *prng; unsigned char *destByte = (unsigned char *)dest; unsigned int si, sj, x; /* initialization, only needed the first time */ if (interp->prngState == NULL) JimPrngInit(interp); prng = interp->prngState; /* generates 'len' bytes of pseudo-random numbers */ for (x = 0; x < len; x++) { prng->i = (prng->i + 1) & 0xff; si = prng->sbox[prng->i]; prng->j = (prng->j + si) & 0xff; sj = prng->sbox[prng->j]; prng->sbox[prng->i] = sj; prng->sbox[prng->j] = si; *destByte++ = prng->sbox[(si + sj) & 0xff]; } } /* Re-seed the generator with user-provided bytes */ static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) { int i; Jim_PrngState *prng; /* initialization, only needed the first time */ if (interp->prngState == NULL) JimPrngInit(interp); prng = interp->prngState; /* Set the sbox[i] with i */ for (i = 0; i < 256; i++) prng->sbox[i] = i; /* Now use the seed to perform a random permutation of the sbox */ for (i = 0; i < seedLen; i++) { unsigned char t; t = prng->sbox[i & 0xFF]; prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; prng->sbox[seed[i]] = t; } prng->i = prng->j = 0; /* discard at least the first 256 bytes of stream. * borrow the seed buffer for this */ for (i = 0; i < 256; i += seedLen) { JimRandomBytes(interp, seed, seedLen); } } /* [incr] */ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { jim_wide wideValue, increment = 1; Jim_Obj *intObjPtr; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?"); return JIM_ERR; } if (argc == 3) { if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) return JIM_ERR; } intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); if (!intObjPtr) { /* Set missing variable to 0 */ wideValue = 0; } else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { return JIM_ERR; } if (!intObjPtr || Jim_IsShared(intObjPtr)) { intObjPtr = Jim_NewIntObj(interp, wideValue + increment); if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) { Jim_FreeNewObj(interp, intObjPtr); return JIM_ERR; } } else { /* Can do it the quick way */ Jim_InvalidateStringRep(intObjPtr); JimWideValue(intObjPtr) = wideValue + increment; /* The following step is required in order to invalidate the * string repr of "FOO" if the var name is on the form of "FOO(IDX)" */ if (argv[1]->typePtr != &variableObjType) { /* Note that this can't fail since GetVariable already succeeded */ Jim_SetVariable(interp, argv[1], intObjPtr); } } Jim_SetResult(interp, intObjPtr); return JIM_OK; } /* ----------------------------------------------------------------------------- * Eval * ---------------------------------------------------------------------------*/ #define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */ #define JIM_EVAL_SINTV_LEN 8 /* static interpolation vector length */ /* Handle calls to the [unknown] command */ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retcode; /* If JimUnknown() is recursively called too many times... * done here */ if (interp->unknown_called > 50) { return JIM_ERR; } /* The object interp->unknown just contains * the "unknown" string, it is used in order to * avoid to lookup the unknown command every time * but instead to cache the result. */ /* If the [unknown] command does not exist ... */ if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) return JIM_ERR; interp->unknown_called++; /* XXX: Are we losing fileNameObj and linenr? */ retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); interp->unknown_called--; return retcode; } static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) { int retcode; Jim_Cmd *cmdPtr; #if 0 printf("invoke"); int j; for (j = 0; j < objc; j++) { printf(" '%s'", Jim_String(objv[j])); } printf("\n"); #endif if (interp->framePtr->tailcallCmd) { /* Special tailcall command was pre-resolved */ cmdPtr = interp->framePtr->tailcallCmd; interp->framePtr->tailcallCmd = NULL; } else { cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); if (cmdPtr == NULL) { return JimUnknown(interp, objc, objv); } JimIncrCmdRefCount(cmdPtr); } if (interp->evalDepth == interp->maxEvalDepth) { Jim_SetResultString(interp, "Infinite eval recursion", -1); retcode = JIM_ERR; goto out; } interp->evalDepth++; /* Call it -- Make sure result is an empty object. */ Jim_SetEmptyResult(interp); if (cmdPtr->isproc) { retcode = JimCallProcedure(interp, cmdPtr, objc, objv); } else { interp->cmdPrivData = cmdPtr->u.native.privData; retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); } interp->evalDepth--; out: JimDecrCmdRefCount(interp, cmdPtr); return retcode; } /* Eval the object vector 'objv' composed of 'objc' elements. * Every element is used as single argument. * Jim_EvalObj() will call this function every time its object * argument is of "list" type, with no string representation. * * This is possible because the string representation of a * list object generated by the UpdateStringOfList is made * in a way that ensures that every list element is a different * command argument. */ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) { int i, retcode; /* Incr refcount of arguments. */ for (i = 0; i < objc; i++) Jim_IncrRefCount(objv[i]); retcode = JimInvokeCommand(interp, objc, objv); /* Decr refcount of arguments and return the retcode */ for (i = 0; i < objc; i++) Jim_DecrRefCount(interp, objv[i]); return retcode; } /** * Invokes 'prefix' as a command with the objv array as arguments. */ int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv) { int ret; Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv)); nargv[0] = prefix; memcpy(&nargv[1], &objv[0], sizeof(nargv[0]) * objc); ret = Jim_EvalObjVector(interp, objc + 1, nargv); Jim_Free(nargv); return ret; } static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) { if (!interp->errorFlag) { /* This is the first error, so save the file/line information and reset the stack */ interp->errorFlag = 1; Jim_IncrRefCount(script->fileNameObj); Jim_DecrRefCount(interp, interp->errorFileNameObj); interp->errorFileNameObj = script->fileNameObj; interp->errorLine = script->linenr; JimResetStackTrace(interp); /* Always add a level where the error first occurs */ interp->addStackTrace++; } /* Now if this is an "interesting" level, add it to the stack trace */ if (interp->addStackTrace > 0) { /* Add the stack info for the current level */ JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); /* Note: if we didn't have a filename for this level, * don't clear the addStackTrace flag * so we can pick it up at the next level */ if (Jim_Length(script->fileNameObj)) { interp->addStackTrace = 0; } Jim_DecrRefCount(interp, interp->errorProc); interp->errorProc = interp->emptyObj; Jim_IncrRefCount(interp->errorProc); } } static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr) { Jim_Obj *objPtr; switch (token->type) { case JIM_TT_STR: case JIM_TT_ESC: objPtr = token->objPtr; break; case JIM_TT_VAR: objPtr = Jim_GetVariable(interp, token->objPtr, JIM_ERRMSG); break; case JIM_TT_DICTSUGAR: objPtr = JimExpandDictSugar(interp, token->objPtr); break; case JIM_TT_EXPRSUGAR: objPtr = JimExpandExprSugar(interp, token->objPtr); break; case JIM_TT_CMD: switch (Jim_EvalObj(interp, token->objPtr)) { case JIM_OK: case JIM_RETURN: objPtr = interp->result; break; case JIM_BREAK: /* Stop substituting */ return JIM_BREAK; case JIM_CONTINUE: /* just skip this one */ return JIM_CONTINUE; default: return JIM_ERR; } break; default: JimPanic((1, "default token type (%d) reached " "in Jim_SubstObj().", token->type)); objPtr = NULL; break; } if (objPtr) { *objPtrPtr = objPtr; return JIM_OK; } return JIM_ERR; } /* Interpolate the given tokens into a unique Jim_Obj returned by reference * via *objPtrPtr. This function is only called by Jim_EvalObj() and Jim_SubstObj() * The returned object has refcount = 0. */ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags) { int totlen = 0, i; Jim_Obj **intv; Jim_Obj *sintv[JIM_EVAL_SINTV_LEN]; Jim_Obj *objPtr; char *s; if (tokens <= JIM_EVAL_SINTV_LEN) intv = sintv; else intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens); /* Compute every token forming the argument * in the intv objects vector. */ for (i = 0; i < tokens; i++) { switch (JimSubstOneToken(interp, &token[i], &intv[i])) { case JIM_OK: case JIM_RETURN: break; case JIM_BREAK: if (flags & JIM_SUBST_FLAG) { /* Stop here */ tokens = i; continue; } /* XXX: Should probably set an error about break outside loop */ /* fall through to error */ case JIM_CONTINUE: if (flags & JIM_SUBST_FLAG) { intv[i] = NULL; continue; } /* XXX: Ditto continue outside loop */ /* fall through to error */ default: while (i--) { Jim_DecrRefCount(interp, intv[i]); } if (intv != sintv) { Jim_Free(intv); } return NULL; } Jim_IncrRefCount(intv[i]); Jim_String(intv[i]); totlen += intv[i]->length; } /* Fast path return for a single token */ if (tokens == 1 && intv[0] && intv == sintv) { Jim_DecrRefCount(interp, intv[0]); return intv[0]; } /* Concatenate every token in an unique * object. */ objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC && token[2].type == JIM_TT_VAR) { /* May be able to do fast interpolated object -> dictSubst */ objPtr->typePtr = &interpolatedObjType; objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; Jim_IncrRefCount(intv[2]); } else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { /* The first interpolated token is source, so preserve the source info */ JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); } s = objPtr->bytes = Jim_Alloc(totlen + 1); objPtr->length = totlen; for (i = 0; i < tokens; i++) { if (intv[i]) { memcpy(s, intv[i]->bytes, intv[i]->length); s += intv[i]->length; Jim_DecrRefCount(interp, intv[i]); } } objPtr->bytes[totlen] = '\0'; /* Free the intv vector if not static. */ if (intv != sintv) { Jim_Free(intv); } return objPtr; } /* listPtr *must* be a list. * The contents of the list is evaluated with the first element as the command and * the remaining elements as the arguments. */ static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) { int retcode = JIM_OK; JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list.")); if (listPtr->internalRep.listValue.len) { Jim_IncrRefCount(listPtr); retcode = JimInvokeCommand(interp, listPtr->internalRep.listValue.len, listPtr->internalRep.listValue.ele); Jim_DecrRefCount(interp, listPtr); } return retcode; } int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) { SetListFromAny(interp, listPtr); return JimEvalObjList(interp, listPtr); } int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) { int i; ScriptObj *script; ScriptToken *token; int retcode = JIM_OK; Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL; Jim_Obj *prevScriptObj; /* If the object is of type "list", with no string rep we can call * a specialized version of Jim_EvalObj() */ if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { return JimEvalObjList(interp, scriptObjPtr); } Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */ script = JimGetScript(interp, scriptObjPtr); if (!JimScriptValid(interp, script)) { Jim_DecrRefCount(interp, scriptObjPtr); return JIM_ERR; } /* Reset the interpreter result. This is useful to * return the empty result in the case of empty program. */ Jim_SetEmptyResult(interp); token = script->token; #ifdef JIM_OPTIMIZATION /* Check for one of the following common scripts used by for, while * * {} * incr a */ if (script->len == 0) { Jim_DecrRefCount(interp, scriptObjPtr); return JIM_OK; } if (script->len == 3 && token[1].objPtr->typePtr == &commandObjType && token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0 && token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand && token[2].objPtr->typePtr == &variableObjType) { Jim_Obj *objPtr = Jim_GetVariable(interp, token[2].objPtr, JIM_NONE); if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { JimWideValue(objPtr)++; Jim_InvalidateStringRep(objPtr); Jim_DecrRefCount(interp, scriptObjPtr); Jim_SetResult(interp, objPtr); return JIM_OK; } } #endif /* Now we have to make sure the internal repr will not be * freed on shimmering. * * Think for example to this: * * set x {llength $x; ... some more code ...}; eval $x * * In order to preserve the internal rep, we increment the * inUse field of the script internal rep structure. */ script->inUse++; /* Stash the current script */ prevScriptObj = interp->currentScriptObj; interp->currentScriptObj = scriptObjPtr; interp->errorFlag = 0; argv = sargv; /* Execute every command sequentially until the end of the script * or an error occurs. */ for (i = 0; i < script->len && retcode == JIM_OK; ) { int argc; int j; /* First token of the line is always JIM_TT_LINE */ argc = token[i].objPtr->internalRep.scriptLineValue.argc; script->linenr = token[i].objPtr->internalRep.scriptLineValue.line; /* Allocate the arguments vector if required */ if (argc > JIM_EVAL_SARGV_LEN) argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); /* Skip the JIM_TT_LINE token */ i++; /* Populate the arguments objects. * If an error occurs, retcode will be set and * 'j' will be set to the number of args expanded */ for (j = 0; j < argc; j++) { long wordtokens = 1; int expand = 0; Jim_Obj *wordObjPtr = NULL; if (token[i].type == JIM_TT_WORD) { wordtokens = JimWideValue(token[i++].objPtr); if (wordtokens < 0) { expand = 1; wordtokens = -wordtokens; } } if (wordtokens == 1) { /* Fast path if the token does not * need interpolation */ switch (token[i].type) { case JIM_TT_ESC: case JIM_TT_STR: wordObjPtr = token[i].objPtr; break; case JIM_TT_VAR: wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG); break; case JIM_TT_EXPRSUGAR: wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr); break; case JIM_TT_DICTSUGAR: wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr); break; case JIM_TT_CMD: retcode = Jim_EvalObj(interp, token[i].objPtr); if (retcode == JIM_OK) { wordObjPtr = Jim_GetResult(interp); } break; default: JimPanic((1, "default token type reached " "in Jim_EvalObj().")); } } else { /* For interpolation we call a helper * function to do the work for us. */ wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE); } if (!wordObjPtr) { if (retcode == JIM_OK) { retcode = JIM_ERR; } break; } Jim_IncrRefCount(wordObjPtr); i += wordtokens; if (!expand) { argv[j] = wordObjPtr; } else { /* Need to expand wordObjPtr into multiple args from argv[j] ... */ int len = Jim_ListLength(interp, wordObjPtr); int newargc = argc + len - 1; int k; if (len > 1) { if (argv == sargv) { if (newargc > JIM_EVAL_SARGV_LEN) { argv = Jim_Alloc(sizeof(*argv) * newargc); memcpy(argv, sargv, sizeof(*argv) * j); } } else { /* Need to realloc to make room for (len - 1) more entries */ argv = Jim_Realloc(argv, sizeof(*argv) * newargc); } } /* Now copy in the expanded version */ for (k = 0; k < len; k++) { argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); } /* The original object reference is no longer needed, * after the expansion it is no longer present on * the argument vector, but the single elements are * in its place. */ Jim_DecrRefCount(interp, wordObjPtr); /* And update the indexes */ j--; argc += len - 1; } } if (retcode == JIM_OK && argc) { /* Invoke the command */ retcode = JimInvokeCommand(interp, argc, argv); /* Check for a signal after each command */ if (Jim_CheckSignal(interp)) { retcode = JIM_SIGNAL; } } /* Finished with the command, so decrement ref counts of each argument */ while (j-- > 0) { Jim_DecrRefCount(interp, argv[j]); } if (argv != sargv) { Jim_Free(argv); argv = sargv; } } /* Possibly add to the error stack trace */ if (retcode == JIM_ERR) { JimAddErrorToStack(interp, script); } /* Propagate the addStackTrace value through 'return -code error' */ else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { /* No need to add stack trace */ interp->addStackTrace = 0; } /* Restore the current script */ interp->currentScriptObj = prevScriptObj; /* Note that we don't have to decrement inUse, because the * following code transfers our use of the reference again to * the script object. */ Jim_FreeIntRep(interp, scriptObjPtr); scriptObjPtr->typePtr = &scriptObjType; Jim_SetIntRepPtr(scriptObjPtr, script); Jim_DecrRefCount(interp, scriptObjPtr); return retcode; } static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) { int retcode; /* If argObjPtr begins with '&', do an automatic upvar */ const char *varname = Jim_String(argNameObj); if (*varname == '&') { /* First check that the target variable exists */ Jim_Obj *objPtr; Jim_CallFrame *savedCallFrame = interp->framePtr; interp->framePtr = interp->framePtr->parent; objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); interp->framePtr = savedCallFrame; if (!objPtr) { return JIM_ERR; } /* It exists, so perform the binding. */ objPtr = Jim_NewStringObj(interp, varname + 1, -1); Jim_IncrRefCount(objPtr); retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent); Jim_DecrRefCount(interp, objPtr); } else { retcode = Jim_SetVariable(interp, argNameObj, argValObj); } return retcode; } /** * Sets the interp result to be an error message indicating the required proc args. */ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) { /* Create a nice error message, consistent with Tcl 8.5 */ Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); int i; for (i = 0; i < cmd->u.proc.argListLen; i++) { Jim_AppendString(interp, argmsg, " ", 1); if (i == cmd->u.proc.argsPos) { if (cmd->u.proc.arglist[i].defaultObjPtr) { /* Renamed args */ Jim_AppendString(interp, argmsg, "?", 1); Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); Jim_AppendString(interp, argmsg, " ...?", -1); } else { /* We have plain args */ Jim_AppendString(interp, argmsg, "?arg...?", -1); } } else { if (cmd->u.proc.arglist[i].defaultObjPtr) { Jim_AppendString(interp, argmsg, "?", 1); Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); Jim_AppendString(interp, argmsg, "?", 1); } else { const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr); if (*arg == '&') { arg++; } Jim_AppendString(interp, argmsg, arg, -1); } } } Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); Jim_FreeNewObj(interp, argmsg); } #ifdef jim_ext_namespace /* * [namespace eval] */ int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj) { Jim_CallFrame *callFramePtr; int retcode; /* Create a new callframe */ callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); callFramePtr->argv = &interp->emptyObj; callFramePtr->argc = 0; callFramePtr->procArgsObjPtr = NULL; callFramePtr->procBodyObjPtr = scriptObj; callFramePtr->staticVars = NULL; callFramePtr->fileNameObj = interp->emptyObj; callFramePtr->line = 0; Jim_IncrRefCount(scriptObj); interp->framePtr = callFramePtr; /* Check if there are too nested calls */ if (interp->framePtr->level == interp->maxCallFrameDepth) { Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); retcode = JIM_ERR; } else { /* Eval the body */ retcode = Jim_EvalObj(interp, scriptObj); } /* Destroy the callframe */ interp->framePtr = interp->framePtr->parent; JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); return retcode; } #endif /* Call a procedure implemented in Tcl. * It's possible to speed-up a lot this function, currently * the callframes are not cached, but allocated and * destroied every time. What is expecially costly is * to create/destroy the local vars hash table every time. * * This can be fixed just implementing callframes caching * in JimCreateCallFrame() and JimFreeCallFrame(). */ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) { Jim_CallFrame *callFramePtr; int i, d, retcode, optargs; ScriptObj *script; /* Check arity */ if (argc - 1 < cmd->u.proc.reqArity || (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { JimSetProcWrongArgs(interp, argv[0], cmd); return JIM_ERR; } if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) { /* Optimise for procedure with no body - useful for optional debugging */ return JIM_OK; } /* Check if there are too nested calls */ if (interp->framePtr->level == interp->maxCallFrameDepth) { Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); return JIM_ERR; } /* Create a new callframe */ callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj); callFramePtr->argv = argv; callFramePtr->argc = argc; callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; callFramePtr->staticVars = cmd->u.proc.staticVars; /* Remember where we were called from. */ script = JimGetScript(interp, interp->currentScriptObj); callFramePtr->fileNameObj = script->fileNameObj; callFramePtr->line = script->linenr; Jim_IncrRefCount(cmd->u.proc.argListObjPtr); Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); interp->framePtr = callFramePtr; /* How many optional args are available */ optargs = (argc - 1 - cmd->u.proc.reqArity); /* Step 'i' along the actual args, and step 'd' along the formal args */ i = 1; for (d = 0; d < cmd->u.proc.argListLen; d++) { Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; if (d == cmd->u.proc.argsPos) { /* assign $args */ Jim_Obj *listObjPtr; int argsLen = 0; if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); } listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); /* It is possible to rename args. */ if (cmd->u.proc.arglist[d].defaultObjPtr) { nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; } retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); if (retcode != JIM_OK) { goto badargset; } i += argsLen; continue; } /* Optional or required? */ if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); } else { /* Ran out, so use the default */ retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); } if (retcode != JIM_OK) { goto badargset; } } /* Eval the body */ retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); badargset: /* Free the callframe */ interp->framePtr = interp->framePtr->parent; JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); if (interp->framePtr->tailcallObj) { /* If a tailcall is already being executed, merge this tailcall with that one */ if (interp->framePtr->tailcall++ == 0) { /* No current tailcall in this frame, so invoke the tailcall command */ do { Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; interp->framePtr->tailcallObj = NULL; if (retcode == JIM_EVAL) { retcode = Jim_EvalObjList(interp, tailcallObj); if (retcode == JIM_RETURN) { /* If the result of the tailcall is 'return', push * it up to the caller */ interp->returnLevel++; } } Jim_DecrRefCount(interp, tailcallObj); } while (interp->framePtr->tailcallObj); /* If the tailcall chain finished early, may need to manually discard the command */ if (interp->framePtr->tailcallCmd) { JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); interp->framePtr->tailcallCmd = NULL; } } interp->framePtr->tailcall--; } /* Handle the JIM_RETURN return code */ if (retcode == JIM_RETURN) { if (--interp->returnLevel <= 0) { retcode = interp->returnCode; interp->returnCode = JIM_OK; interp->returnLevel = 0; } } else if (retcode == JIM_ERR) { interp->addStackTrace++; Jim_DecrRefCount(interp, interp->errorProc); interp->errorProc = argv[0]; Jim_IncrRefCount(interp->errorProc); } return retcode; } int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) { int retval; Jim_Obj *scriptObjPtr; scriptObjPtr = Jim_NewStringObj(interp, script, -1); Jim_IncrRefCount(scriptObjPtr); if (filename) { Jim_Obj *prevScriptObj; JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); prevScriptObj = interp->currentScriptObj; interp->currentScriptObj = scriptObjPtr; retval = Jim_EvalObj(interp, scriptObjPtr); interp->currentScriptObj = prevScriptObj; } else { retval = Jim_EvalObj(interp, scriptObjPtr); } Jim_DecrRefCount(interp, scriptObjPtr); return retval; } int Jim_Eval(Jim_Interp *interp, const char *script) { return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1)); } /* Execute script in the scope of the global level */ int Jim_EvalGlobal(Jim_Interp *interp, const char *script) { int retval; Jim_CallFrame *savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; retval = Jim_Eval(interp, script); interp->framePtr = savedFramePtr; return retval; } int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename) { int retval; Jim_CallFrame *savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; retval = Jim_EvalFile(interp, filename); interp->framePtr = savedFramePtr; return retval; } #include int Jim_EvalFile(Jim_Interp *interp, const char *filename) { FILE *fp; char *buf; Jim_Obj *scriptObjPtr; Jim_Obj *prevScriptObj; struct stat sb; int retcode; int readlen; if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); return JIM_ERR; } if (sb.st_size == 0) { fclose(fp); return JIM_OK; } buf = Jim_Alloc(sb.st_size + 1); readlen = fread(buf, 1, sb.st_size, fp); if (ferror(fp)) { fclose(fp); Jim_Free(buf); Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno)); return JIM_ERR; } fclose(fp); buf[readlen] = 0; scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); Jim_IncrRefCount(scriptObjPtr); prevScriptObj = interp->currentScriptObj; interp->currentScriptObj = scriptObjPtr; retcode = Jim_EvalObj(interp, scriptObjPtr); /* Handle the JIM_RETURN return code */ if (retcode == JIM_RETURN) { if (--interp->returnLevel <= 0) { retcode = interp->returnCode; interp->returnCode = JIM_OK; interp->returnLevel = 0; } } if (retcode == JIM_ERR) { /* EvalFile changes context, so add a stack frame here */ interp->addStackTrace++; } interp->currentScriptObj = prevScriptObj; Jim_DecrRefCount(interp, scriptObjPtr); return retcode; } /* ----------------------------------------------------------------------------- * Subst * ---------------------------------------------------------------------------*/ static void JimParseSubst(struct JimParserCtx *pc, int flags) { pc->tstart = pc->p; pc->tline = pc->linenr; if (pc->len == 0) { pc->tend = pc->p; pc->tt = JIM_TT_EOL; pc->eof = 1; return; } if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) { JimParseCmd(pc); return; } if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { if (JimParseVar(pc) == JIM_OK) { return; } /* Not a var, so treat as a string */ pc->tstart = pc->p; flags |= JIM_SUBST_NOVAR; } while (pc->len) { if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { break; } if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) { break; } if (*pc->p == '\\' && pc->len > 1) { pc->p++; pc->len--; } pc->p++; pc->len--; } pc->tend = pc->p - 1; pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC; } /* The subst object type reuses most of the data structures and functions * of the script object. Script's data structures are a bit more complex * for what is needed for [subst]itution tasks, but the reuse helps to * deal with a single data structure at the cost of some more memory * usage for substitutions. */ /* This method takes the string representation of an object * as a Tcl string where to perform [subst]itution, and generates * the pre-parsed internal representation. */ static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags) { int scriptTextLen; const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); struct JimParserCtx parser; struct ScriptObj *script = Jim_Alloc(sizeof(*script)); ParseTokenList tokenlist; /* Initially parse the subst into tokens (in tokenlist) */ ScriptTokenListInit(&tokenlist); JimParserInit(&parser, scriptText, scriptTextLen, 1); while (1) { JimParseSubst(&parser, flags); if (parser.eof) { /* Note that subst doesn't need the EOL token */ break; } ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, parser.tline); } /* Create the "real" subst/script tokens from the initial token list */ script->inUse = 1; script->substFlags = flags; script->fileNameObj = interp->emptyObj; Jim_IncrRefCount(script->fileNameObj); SubstObjAddTokens(interp, script, &tokenlist); /* No longer need the token list */ ScriptTokenListFree(&tokenlist); #ifdef DEBUG_SHOW_SUBST { int i; printf("==== Subst ====\n"); for (i = 0; i < script->len; i++) { printf("[%2d] %s '%s'\n", i, jim_tt_name(script->token[i].type), Jim_String(script->token[i].objPtr)); } } #endif /* Free the old internal rep and set the new one. */ Jim_FreeIntRep(interp, objPtr); Jim_SetIntRepPtr(objPtr, script); objPtr->typePtr = &scriptObjType; return JIM_OK; } static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { if (objPtr->typePtr != &scriptObjType || ((ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags != flags) SetSubstFromAny(interp, objPtr, flags); return (ScriptObj *) Jim_GetIntRepPtr(objPtr); } /* Performs commands,variables,blackslashes substitution, * storing the result object (with refcount 0) into * resObjPtrPtr. */ int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) { ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); Jim_IncrRefCount(substObjPtr); /* Make sure it's shared. */ /* In order to preserve the internal rep, we increment the * inUse field of the script internal rep structure. */ script->inUse++; *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); script->inUse--; Jim_DecrRefCount(interp, substObjPtr); if (*resObjPtrPtr == NULL) { return JIM_ERR; } return JIM_OK; } /* ----------------------------------------------------------------------------- * Core commands utility functions * ---------------------------------------------------------------------------*/ void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) { Jim_Obj *objPtr; Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc); if (*msg) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); } Jim_IncrRefCount(listObjPtr); objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); Jim_DecrRefCount(interp, listObjPtr); Jim_IncrRefCount(objPtr); Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); Jim_DecrRefCount(interp, objPtr); } /** * May add the key and/or value to the list. */ typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type); #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) /** * For each key of the hash table 'ht' (with string keys) which matches the glob pattern (all if NULL), * invoke the callback to add entries to a list. * Returns the list. */ static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, JimHashtableIteratorCallbackType *callback, int type) { Jim_HashEntry *he; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); /* Check for the non-pattern case. We can do this much more efficiently. */ if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); if (he) { callback(interp, listObjPtr, he, type); } } else { Jim_HashTableIterator htiter; JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) { callback(interp, listObjPtr, he, type); } } } return listObjPtr; } /* Keep these in order */ #define JIM_CMDLIST_COMMANDS 0 #define JIM_CMDLIST_PROCS 1 #define JIM_CMDLIST_CHANNELS 2 /** * Adds matching command names (procs, channels) to the list. */ static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) { Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); Jim_Obj *objPtr; if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { /* not a proc */ return; } objPtr = Jim_NewStringObj(interp, he->key, -1); Jim_IncrRefCount(objPtr); if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) { Jim_ListAppendElement(interp, listObjPtr, objPtr); } Jim_DecrRefCount(interp, objPtr); } /* type is JIM_CMDLIST_xxx */ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type) { return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type); } /* Keep these in order */ #define JIM_VARLIST_GLOBALS 0 #define JIM_VARLIST_LOCALS 1 #define JIM_VARLIST_VARS 2 #define JIM_VARLIST_VALUES 0x1000 /** * Adds matching variable names to the list. */ static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) { Jim_Var *varPtr = Jim_GetHashEntryVal(he); if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); if (type & JIM_VARLIST_VALUES) { Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); } } } /* mode is JIM_VARLIST_xxx */ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode) { if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) { /* For [info locals], if we are at top level an emtpy list * is returned. I don't agree, but we aim at compatibility (SS) */ return interp->emptyObj; } else { Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr; return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode); } } static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objPtrPtr, int info_level_cmd) { Jim_CallFrame *targetCallFrame; targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); if (targetCallFrame == NULL) { return JIM_ERR; } /* No proc call at toplevel callframe */ if (targetCallFrame == interp->topFramePtr) { Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); return JIM_ERR; } if (info_level_cmd) { *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); } else { Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj); Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); *objPtrPtr = listObj; } return JIM_OK; } /* ----------------------------------------------------------------------------- * Core commands * ---------------------------------------------------------------------------*/ /* fake [puts] -- not the real puts, just for debugging. */ static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string"); return JIM_ERR; } if (argc == 3) { if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) { Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1); return JIM_ERR; } else { fputs(Jim_String(argv[2]), stdout); } } else { puts(Jim_String(argv[1])); } return JIM_OK; } /* Helper for [+] and [*] */ static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) { jim_wide wideValue, res; double doubleValue, doubleRes; int i; res = (op == JIM_EXPROP_ADD) ? 0 : 1; for (i = 1; i < argc; i++) { if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) goto trydouble; if (op == JIM_EXPROP_ADD) res += wideValue; else res *= wideValue; } Jim_SetResultInt(interp, res); return JIM_OK; trydouble: doubleRes = (double)res; for (; i < argc; i++) { if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) return JIM_ERR; if (op == JIM_EXPROP_ADD) doubleRes += doubleValue; else doubleRes *= doubleValue; } Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); return JIM_OK; } /* Helper for [-] and [/] */ static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) { jim_wide wideValue, res = 0; double doubleValue, doubleRes = 0; int i = 2; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?"); return JIM_ERR; } else if (argc == 2) { /* The arity = 2 case is different. For [- x] returns -x, * while [/ x] returns 1/x. */ if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) { if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) { return JIM_ERR; } else { if (op == JIM_EXPROP_SUB) doubleRes = -doubleValue; else doubleRes = 1.0 / doubleValue; Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); return JIM_OK; } } if (op == JIM_EXPROP_SUB) { res = -wideValue; Jim_SetResultInt(interp, res); } else { doubleRes = 1.0 / wideValue; Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); } return JIM_OK; } else { if (Jim_GetWide(interp, argv[1], &res) != JIM_OK) { if (Jim_GetDouble(interp, argv[1], &doubleRes) != JIM_OK) { return JIM_ERR; } else { goto trydouble; } } } for (i = 2; i < argc; i++) { if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { doubleRes = (double)res; goto trydouble; } if (op == JIM_EXPROP_SUB) res -= wideValue; else res /= wideValue; } Jim_SetResultInt(interp, res); return JIM_OK; trydouble: for (; i < argc; i++) { if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) return JIM_ERR; if (op == JIM_EXPROP_SUB) doubleRes -= doubleValue; else doubleRes /= doubleValue; } Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); return JIM_OK; } /* [+] */ static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD); } /* [*] */ static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL); } /* [-] */ static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB); } /* [/] */ static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV); } /* [set] */ static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?"); return JIM_ERR; } if (argc == 2) { Jim_Obj *objPtr; objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); if (!objPtr) return JIM_ERR; Jim_SetResult(interp, objPtr); return JIM_OK; } /* argc == 3 case. */ if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) return JIM_ERR; Jim_SetResult(interp, argv[2]); return JIM_OK; } /* [unset] * * unset ?-nocomplain? ?--? ?varName ...? */ static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i = 1; int complain = 1; while (i < argc) { if (Jim_CompareStringImmediate(interp, argv[i], "--")) { i++; break; } if (Jim_CompareStringImmediate(interp, argv[i], "-nocomplain")) { complain = 0; i++; continue; } break; } while (i < argc) { if (Jim_UnsetVariable(interp, argv[i], complain ? JIM_ERRMSG : JIM_NONE) != JIM_OK && complain) { return JIM_ERR; } i++; } return JIM_OK; } /* [while] */ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "condition body"); return JIM_ERR; } /* The general purpose implementation of while starts here */ while (1) { int boolean, retval; if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) return retval; if (!boolean) break; if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) { switch (retval) { case JIM_BREAK: goto out; break; case JIM_CONTINUE: continue; break; default: return retval; } } } out: Jim_SetEmptyResult(interp); return JIM_OK; } /* [for] */ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retval; int boolean = 1; Jim_Obj *varNamePtr = NULL; Jim_Obj *stopVarNamePtr = NULL; if (argc != 5) { Jim_WrongNumArgs(interp, 1, argv, "start test next body"); return JIM_ERR; } /* Do the initialisation */ if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { return retval; } /* And do the first test now. Better for optimisation * if we can do next/test at the bottom of the loop */ retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); /* Ready to do the body as follows: * while (1) { * body // check retcode * next // check retcode * test // check retcode/test bool * } */ #ifdef JIM_OPTIMIZATION /* Check if the for is on the form: * for ... {$i < CONST} {incr i} * for ... {$i < $j} {incr i} */ if (retval == JIM_OK && boolean) { ScriptObj *incrScript; ExprByteCode *expr; jim_wide stop, currentVal; Jim_Obj *objPtr; int cmpOffset; /* Do it only if there aren't shared arguments */ expr = JimGetExpression(interp, argv[2]); incrScript = JimGetScript(interp, argv[3]); /* Ensure proper lengths to start */ if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { goto evalstart; } /* Ensure proper token types. */ if (incrScript->token[1].type != JIM_TT_ESC || expr->token[0].type != JIM_TT_VAR || (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { goto evalstart; } if (expr->token[2].type == JIM_EXPROP_LT) { cmpOffset = 0; } else if (expr->token[2].type == JIM_EXPROP_LTE) { cmpOffset = 1; } else { goto evalstart; } /* Update command must be incr */ if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { goto evalstart; } /* incr, expression must be about the same variable */ if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { goto evalstart; } /* Get the stop condition (must be a variable or integer) */ if (expr->token[1].type == JIM_TT_EXPR_INT) { if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { goto evalstart; } } else { stopVarNamePtr = expr->token[1].objPtr; Jim_IncrRefCount(stopVarNamePtr); /* Keep the compiler happy */ stop = 0; } /* Initialization */ varNamePtr = expr->token[0].objPtr; Jim_IncrRefCount(varNamePtr); objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { goto testcond; } /* --- OPTIMIZED FOR --- */ while (retval == JIM_OK) { /* === Check condition === */ /* Note that currentVal is already set here */ /* Immediate or Variable? get the 'stop' value if the latter. */ if (stopVarNamePtr) { objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { goto testcond; } } if (currentVal >= stop + cmpOffset) { break; } /* Eval body */ retval = Jim_EvalObj(interp, argv[4]); if (retval == JIM_OK || retval == JIM_CONTINUE) { retval = JIM_OK; objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); /* Increment */ if (objPtr == NULL) { retval = JIM_ERR; goto out; } if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { currentVal = ++JimWideValue(objPtr); Jim_InvalidateStringRep(objPtr); } else { if (Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK || Jim_SetVariable(interp, varNamePtr, Jim_NewIntObj(interp, ++currentVal)) != JIM_OK) { goto evalnext; } } } } goto out; } evalstart: #endif while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { /* Body */ retval = Jim_EvalObj(interp, argv[4]); if (retval == JIM_OK || retval == JIM_CONTINUE) { /* increment */ evalnext: retval = Jim_EvalObj(interp, argv[3]); if (retval == JIM_OK || retval == JIM_CONTINUE) { /* test */ testcond: retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); } } } out: if (stopVarNamePtr) { Jim_DecrRefCount(interp, stopVarNamePtr); } if (varNamePtr) { Jim_DecrRefCount(interp, varNamePtr); } if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { Jim_SetEmptyResult(interp); return JIM_OK; } return retval; } /* [loop] */ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retval; jim_wide i; jim_wide limit; jim_wide incr = 1; Jim_Obj *bodyObjPtr; if (argc != 5 && argc != 6) { Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body"); return JIM_ERR; } if (Jim_GetWide(interp, argv[2], &i) != JIM_OK || Jim_GetWide(interp, argv[3], &limit) != JIM_OK || (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) { return JIM_ERR; } bodyObjPtr = (argc == 5) ? argv[4] : argv[5]; retval = Jim_SetVariable(interp, argv[1], argv[2]); while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) { retval = Jim_EvalObj(interp, bodyObjPtr); if (retval == JIM_OK || retval == JIM_CONTINUE) { Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); retval = JIM_OK; /* Increment */ i += incr; if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { if (argv[1]->typePtr != &variableObjType) { if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { return JIM_ERR; } } JimWideValue(objPtr) = i; Jim_InvalidateStringRep(objPtr); /* The following step is required in order to invalidate the * string repr of "FOO" if the var name is of the form of "FOO(IDX)" */ if (argv[1]->typePtr != &variableObjType) { if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { retval = JIM_ERR; break; } } } else { objPtr = Jim_NewIntObj(interp, i); retval = Jim_SetVariable(interp, argv[1], objPtr); if (retval != JIM_OK) { Jim_FreeNewObj(interp, objPtr); } } } } if (retval == JIM_OK || retval == JIM_CONTINUE || retval == JIM_BREAK) { Jim_SetEmptyResult(interp); return JIM_OK; } return retval; } /* List iterators make it easy to iterate over a list. * At some point iterators will be expanded to support generators. */ typedef struct { Jim_Obj *objPtr; int idx; } Jim_ListIter; /** * Initialise the iterator at the start of the list. */ static void JimListIterInit(Jim_ListIter *iter, Jim_Obj *objPtr) { iter->objPtr = objPtr; iter->idx = 0; } /** * Returns the next object from the list, or NULL on end-of-list. */ static Jim_Obj *JimListIterNext(Jim_Interp *interp, Jim_ListIter *iter) { if (iter->idx >= Jim_ListLength(interp, iter->objPtr)) { return NULL; } return iter->objPtr->internalRep.listValue.ele[iter->idx++]; } /** * Returns 1 if end-of-list has been reached. */ static int JimListIterDone(Jim_Interp *interp, Jim_ListIter *iter) { return iter->idx >= Jim_ListLength(interp, iter->objPtr); } /* foreach + lmap implementation. */ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) { int result = JIM_OK; int i, numargs; Jim_ListIter twoiters[2]; /* Avoid allocation for a single list */ Jim_ListIter *iters; Jim_Obj *script; Jim_Obj *resultObj; if (argc < 4 || argc % 2 != 0) { Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); return JIM_ERR; } script = argv[argc - 1]; /* Last argument is a script */ numargs = (argc - 1 - 1); /* argc - 'foreach' - script */ if (numargs == 2) { iters = twoiters; } else { iters = Jim_Alloc(numargs * sizeof(*iters)); } for (i = 0; i < numargs; i++) { JimListIterInit(&iters[i], argv[i + 1]); if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { result = JIM_ERR; } } if (result != JIM_OK) { Jim_SetResultString(interp, "foreach varlist is empty", -1); return result; } if (doMap) { resultObj = Jim_NewListObj(interp, NULL, 0); } else { resultObj = interp->emptyObj; } Jim_IncrRefCount(resultObj); while (1) { /* Have we expired all lists? */ for (i = 0; i < numargs; i += 2) { if (!JimListIterDone(interp, &iters[i + 1])) { break; } } if (i == numargs) { /* All done */ break; } /* For each list */ for (i = 0; i < numargs; i += 2) { Jim_Obj *varName; /* foreach var */ JimListIterInit(&iters[i], argv[i + 1]); while ((varName = JimListIterNext(interp, &iters[i])) != NULL) { Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]); if (!valObj) { /* Ran out, so store the empty string */ valObj = interp->emptyObj; } /* Avoid shimmering */ Jim_IncrRefCount(valObj); result = Jim_SetVariable(interp, varName, valObj); Jim_DecrRefCount(interp, valObj); if (result != JIM_OK) { goto err; } } } switch (result = Jim_EvalObj(interp, script)) { case JIM_OK: if (doMap) { Jim_ListAppendElement(interp, resultObj, interp->result); } break; case JIM_CONTINUE: break; case JIM_BREAK: goto out; default: goto err; } } out: result = JIM_OK; Jim_SetResult(interp, resultObj); err: Jim_DecrRefCount(interp, resultObj); if (numargs > 2) { Jim_Free(iters); } return result; } /* [foreach] */ static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimForeachMapHelper(interp, argc, argv, 0); } /* [lmap] */ static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return JimForeachMapHelper(interp, argc, argv, 1); } /* [lassign] */ static int Jim_LassignCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int result = JIM_ERR; int i; Jim_ListIter iter; Jim_Obj *resultObj; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "varList list ?varName ...?"); return JIM_ERR; } JimListIterInit(&iter, argv[1]); for (i = 2; i < argc; i++) { Jim_Obj *valObj = JimListIterNext(interp, &iter); result = Jim_SetVariable(interp, argv[i], valObj ? valObj : interp->emptyObj); if (result != JIM_OK) { return result; } } resultObj = Jim_NewListObj(interp, NULL, 0); while (!JimListIterDone(interp, &iter)) { Jim_ListAppendElement(interp, resultObj, JimListIterNext(interp, &iter)); } Jim_SetResult(interp, resultObj); return JIM_OK; } /* [if] */ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int boolean, retval, current = 1, falsebody = 0; if (argc >= 3) { while (1) { /* Far not enough arguments given! */ if (current >= argc) goto err; if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) != JIM_OK) return retval; /* There lacks something, isn't it? */ if (current >= argc) goto err; if (Jim_CompareStringImmediate(interp, argv[current], "then")) current++; /* Tsk tsk, no then-clause? */ if (current >= argc) goto err; if (boolean) return Jim_EvalObj(interp, argv[current]); /* Ok: no else-clause follows */ if (++current >= argc) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); return JIM_OK; } falsebody = current++; if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { /* IIICKS - else-clause isn't last cmd? */ if (current != argc - 1) goto err; return Jim_EvalObj(interp, argv[current]); } else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) /* Ok: elseif follows meaning all the stuff * again (how boring...) */ continue; /* OOPS - else-clause is not last cmd? */ else if (falsebody != argc - 1) goto err; return Jim_EvalObj(interp, argv[falsebody]); } return JIM_OK; } err: Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody"); return JIM_ERR; } /* Returns 1 if match, 0 if no match or - on error (e.g. -JIM_ERR, -JIM_BREAK)*/ int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, Jim_Obj *stringObj, int nocase) { Jim_Obj *parms[4]; int argc = 0; long eq; int rc; parms[argc++] = commandObj; if (nocase) { parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); } parms[argc++] = patternObj; parms[argc++] = stringObj; rc = Jim_EvalObjVector(interp, argc, parms); if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { eq = -rc; } return eq; } enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; /* [switch] */ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; Jim_Obj *command = 0, *const *caseList = 0, *strObj; Jim_Obj *script = 0; if (argc < 3) { wrongnumargs: Jim_WrongNumArgs(interp, 1, argv, "?options? string " "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); return JIM_ERR; } for (opt = 1; opt < argc; ++opt) { const char *option = Jim_String(argv[opt]); if (*option != '-') break; else if (strncmp(option, "--", 2) == 0) { ++opt; break; } else if (strncmp(option, "-exact", 2) == 0) matchOpt = SWITCH_EXACT; else if (strncmp(option, "-glob", 2) == 0) matchOpt = SWITCH_GLOB; else if (strncmp(option, "-regexp", 2) == 0) matchOpt = SWITCH_RE; else if (strncmp(option, "-command", 2) == 0) { matchOpt = SWITCH_CMD; if ((argc - opt) < 2) goto wrongnumargs; command = argv[++opt]; } else { Jim_SetResultFormatted(interp, "bad option \"%#s\": must be -exact, -glob, -regexp, -command procname or --", argv[opt]); return JIM_ERR; } if ((argc - opt) < 2) goto wrongnumargs; } strObj = argv[opt++]; patCount = argc - opt; if (patCount == 1) { Jim_Obj **vector; JimListGetElements(interp, argv[opt], &patCount, &vector); caseList = vector; } else caseList = &argv[opt]; if (patCount == 0 || patCount % 2 != 0) goto wrongnumargs; for (i = 0; script == 0 && i < patCount; i += 2) { Jim_Obj *patObj = caseList[i]; if (!Jim_CompareStringImmediate(interp, patObj, "default") || i < (patCount - 2)) { switch (matchOpt) { case SWITCH_EXACT: if (Jim_StringEqObj(strObj, patObj)) script = caseList[i + 1]; break; case SWITCH_GLOB: if (Jim_StringMatchObj(interp, patObj, strObj, 0)) script = caseList[i + 1]; break; case SWITCH_RE: command = Jim_NewStringObj(interp, "regexp", -1); /* Fall thru intentionally */ case SWITCH_CMD:{ int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); /* After the execution of a command we need to * make sure to reconvert the object into a list * again. Only for the single-list style [switch]. */ if (argc - opt == 1) { Jim_Obj **vector; JimListGetElements(interp, argv[opt], &patCount, &vector); caseList = vector; } /* command is here already decref'd */ if (rc < 0) { return -rc; } if (rc) script = caseList[i + 1]; break; } } } else { script = caseList[i + 1]; } } for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) script = caseList[i + 1]; if (script && Jim_CompareStringImmediate(interp, script, "-")) { Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); return JIM_ERR; } Jim_SetEmptyResult(interp); if (script) { return Jim_EvalObj(interp, script); } return JIM_OK; } /* [list] */ static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listObjPtr; listObjPtr = Jim_NewListObj(interp, argv + 1, argc - 1); Jim_SetResult(interp, listObjPtr); return JIM_OK; } /* [lindex] */ static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr, *listObjPtr; int i; int idx; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); return JIM_ERR; } objPtr = argv[1]; Jim_IncrRefCount(objPtr); for (i = 2; i < argc; i++) { listObjPtr = objPtr; if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) { Jim_DecrRefCount(interp, listObjPtr); return JIM_ERR; } if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) { /* Returns an empty object if the index * is out of range. */ Jim_DecrRefCount(interp, listObjPtr); Jim_SetEmptyResult(interp); return JIM_OK; } Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, listObjPtr); } Jim_SetResult(interp, objPtr); Jim_DecrRefCount(interp, objPtr); return JIM_OK; } /* [llength] */ static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "list"); return JIM_ERR; } Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1])); return JIM_OK; } /* [lsearch] */ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { static const char * const options[] = { "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command", NULL }; enum { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE, OPT_COMMAND }; int i; int opt_bool = 0; int opt_not = 0; int opt_nocase = 0; int opt_all = 0; int opt_inline = 0; int opt_match = OPT_EXACT; int listlen; int rc = JIM_OK; Jim_Obj *listObjPtr = NULL; Jim_Obj *commandObj = NULL; if (argc < 3) { wrongargs: Jim_WrongNumArgs(interp, 1, argv, "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value"); return JIM_ERR; } for (i = 1; i < argc - 2; i++) { int option; if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_BOOL: opt_bool = 1; opt_inline = 0; break; case OPT_NOT: opt_not = 1; break; case OPT_NOCASE: opt_nocase = 1; break; case OPT_INLINE: opt_inline = 1; opt_bool = 0; break; case OPT_ALL: opt_all = 1; break; case OPT_COMMAND: if (i >= argc - 2) { goto wrongargs; } commandObj = argv[++i]; /* fallthru */ case OPT_EXACT: case OPT_GLOB: case OPT_REGEXP: opt_match = option; break; } } argv += i; if (opt_all) { listObjPtr = Jim_NewListObj(interp, NULL, 0); } if (opt_match == OPT_REGEXP) { commandObj = Jim_NewStringObj(interp, "regexp", -1); } if (commandObj) { Jim_IncrRefCount(commandObj); } listlen = Jim_ListLength(interp, argv[0]); for (i = 0; i < listlen; i++) { int eq = 0; Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); switch (opt_match) { case OPT_EXACT: eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; break; case OPT_GLOB: eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); break; case OPT_REGEXP: case OPT_COMMAND: eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); if (eq < 0) { if (listObjPtr) { Jim_FreeNewObj(interp, listObjPtr); } rc = JIM_ERR; goto done; } break; } /* If we have a non-match with opt_bool, opt_not, !opt_all, can't exit early */ if (!eq && opt_bool && opt_not && !opt_all) { continue; } if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { /* Got a match (or non-match for opt_not), or (opt_bool && opt_all) */ Jim_Obj *resultObj; if (opt_bool) { resultObj = Jim_NewIntObj(interp, eq ^ opt_not); } else if (!opt_inline) { resultObj = Jim_NewIntObj(interp, i); } else { resultObj = objPtr; } if (opt_all) { Jim_ListAppendElement(interp, listObjPtr, resultObj); } else { Jim_SetResult(interp, resultObj); goto done; } } } if (opt_all) { Jim_SetResult(interp, listObjPtr); } else { /* No match */ if (opt_bool) { Jim_SetResultBool(interp, opt_not); } else if (!opt_inline) { Jim_SetResultInt(interp, -1); } } done: if (commandObj) { Jim_DecrRefCount(interp, commandObj); } return rc; } /* [lappend] */ static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listObjPtr; int shared, i; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); return JIM_ERR; } listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); if (!listObjPtr) { /* Create the list if it does not exists */ listObjPtr = Jim_NewListObj(interp, NULL, 0); if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { Jim_FreeNewObj(interp, listObjPtr); return JIM_ERR; } } shared = Jim_IsShared(listObjPtr); if (shared) listObjPtr = Jim_DuplicateObj(interp, listObjPtr); for (i = 2; i < argc; i++) Jim_ListAppendElement(interp, listObjPtr, argv[i]); if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { if (shared) Jim_FreeNewObj(interp, listObjPtr); return JIM_ERR; } Jim_SetResult(interp, listObjPtr); return JIM_OK; } /* [linsert] */ static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int idx, len; Jim_Obj *listPtr; if (argc < 3) { Jim_WrongNumArgs(interp, 1, argv, "list index ?element ...?"); return JIM_ERR; } listPtr = argv[1]; if (Jim_IsShared(listPtr)) listPtr = Jim_DuplicateObj(interp, listPtr); if (Jim_GetIndex(interp, argv[2], &idx) != JIM_OK) goto err; len = Jim_ListLength(interp, listPtr); if (idx >= len) idx = len; else if (idx < 0) idx = len + idx + 1; Jim_ListInsertElements(interp, listPtr, idx, argc - 3, &argv[3]); Jim_SetResult(interp, listPtr); return JIM_OK; err: if (listPtr != argv[1]) { Jim_FreeNewObj(interp, listPtr); } return JIM_ERR; } /* [lreplace] */ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int first, last, len, rangeLen; Jim_Obj *listObj; Jim_Obj *newListObj; if (argc < 4) { Jim_WrongNumArgs(interp, 1, argv, "list first last ?element ...?"); return JIM_ERR; } if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK || Jim_GetIndex(interp, argv[3], &last) != JIM_OK) { return JIM_ERR; } listObj = argv[1]; len = Jim_ListLength(interp, listObj); first = JimRelToAbsIndex(len, first); last = JimRelToAbsIndex(len, last); JimRelToAbsRange(len, &first, &last, &rangeLen); /* Now construct a new list which consists of: * */ /* Check to see if trying to replace past the end of the list */ if (first < len) { /* OK. Not past the end */ } else if (len == 0) { /* Special for empty list, adjust first to 0 */ first = 0; } else { Jim_SetResultString(interp, "list doesn't contain element ", -1); Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); return JIM_ERR; } /* Add the first set of elements */ newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); /* Add supplied elements */ ListInsertElements(newListObj, -1, argc - 4, argv + 4); /* Add the remaining elements */ ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen); Jim_SetResult(interp, newListObj); return JIM_OK; } /* [lset] */ static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc < 3) { Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); return JIM_ERR; } else if (argc == 3) { /* With no indexes, simply implements [set] */ if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) return JIM_ERR; Jim_SetResult(interp, argv[2]); return JIM_OK; } return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]); } /* [lsort] */ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) { static const char * const options[] = { "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL }; enum { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; Jim_Obj *resObj; int i; int retCode; struct lsort_info info; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "?options? list"); return JIM_ERR; } info.type = JIM_LSORT_ASCII; info.order = 1; info.indexed = 0; info.unique = 0; info.command = NULL; info.interp = interp; for (i = 1; i < (argc - 1); i++) { int option; if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) != JIM_OK) return JIM_ERR; switch (option) { case OPT_ASCII: info.type = JIM_LSORT_ASCII; break; case OPT_NOCASE: info.type = JIM_LSORT_NOCASE; break; case OPT_INTEGER: info.type = JIM_LSORT_INTEGER; break; case OPT_REAL: info.type = JIM_LSORT_REAL; break; case OPT_INCREASING: info.order = 1; break; case OPT_DECREASING: info.order = -1; break; case OPT_UNIQUE: info.unique = 1; break; case OPT_COMMAND: if (i >= (argc - 2)) { Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); return JIM_ERR; } info.type = JIM_LSORT_COMMAND; info.command = argv[i + 1]; i++; break; case OPT_INDEX: if (i >= (argc - 2)) { Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1); return JIM_ERR; } if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) { return JIM_ERR; } info.indexed = 1; i++; break; } } resObj = Jim_DuplicateObj(interp, argv[argc - 1]); retCode = ListSortElements(interp, resObj, &info); if (retCode == JIM_OK) { Jim_SetResult(interp, resObj); } else { Jim_FreeNewObj(interp, resObj); } return retCode; } /* [append] */ static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *stringObjPtr; int i; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "varName ?value ...?"); return JIM_ERR; } if (argc == 2) { stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); if (!stringObjPtr) return JIM_ERR; } else { int freeobj = 0; stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); if (!stringObjPtr) { /* Create the string if it doesn't exist */ stringObjPtr = Jim_NewEmptyStringObj(interp); freeobj = 1; } else if (Jim_IsShared(stringObjPtr)) { freeobj = 1; stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); } for (i = 2; i < argc; i++) { Jim_AppendObj(interp, stringObjPtr, argv[i]); } if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { if (freeobj) { Jim_FreeNewObj(interp, stringObjPtr); } return JIM_ERR; } } Jim_SetResult(interp, stringObjPtr); return JIM_OK; } /* [debug] */ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { #if defined(JIM_DEBUG_COMMAND) && !defined(JIM_BOOTSTRAP) static const char * const options[] = { "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen", "exprbc", "show", NULL }; enum { OPT_REFCOUNT, OPT_OBJCOUNT, OPT_OBJECTS, OPT_INVSTR, OPT_SCRIPTLEN, OPT_EXPRLEN, OPT_EXPRBC, OPT_SHOW, }; int option; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "subcommand ?...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) return JIM_ERR; if (option == OPT_REFCOUNT) { if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "object"); return JIM_ERR; } Jim_SetResultInt(interp, argv[2]->refCount); return JIM_OK; } else if (option == OPT_OBJCOUNT) { int freeobj = 0, liveobj = 0; char buf[256]; Jim_Obj *objPtr; if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } /* Count the number of free objects. */ objPtr = interp->freeList; while (objPtr) { freeobj++; objPtr = objPtr->nextObjPtr; } /* Count the number of live objects. */ objPtr = interp->liveList; while (objPtr) { liveobj++; objPtr = objPtr->nextObjPtr; } /* Set the result string and return. */ sprintf(buf, "free %d used %d", freeobj, liveobj); Jim_SetResultString(interp, buf, -1); return JIM_OK; } else if (option == OPT_OBJECTS) { Jim_Obj *objPtr, *listObjPtr, *subListObjPtr; /* Count the number of live objects. */ objPtr = interp->liveList; listObjPtr = Jim_NewListObj(interp, NULL, 0); while (objPtr) { char buf[128]; const char *type = objPtr->typePtr ? objPtr->typePtr->name : ""; subListObjPtr = Jim_NewListObj(interp, NULL, 0); sprintf(buf, "%p", objPtr); Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, buf, -1)); Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, type, -1)); Jim_ListAppendElement(interp, subListObjPtr, Jim_NewIntObj(interp, objPtr->refCount)); Jim_ListAppendElement(interp, subListObjPtr, objPtr); Jim_ListAppendElement(interp, listObjPtr, subListObjPtr); objPtr = objPtr->nextObjPtr; } Jim_SetResult(interp, listObjPtr); return JIM_OK; } else if (option == OPT_INVSTR) { Jim_Obj *objPtr; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "object"); return JIM_ERR; } objPtr = argv[2]; if (objPtr->typePtr != NULL) Jim_InvalidateStringRep(objPtr); Jim_SetEmptyResult(interp); return JIM_OK; } else if (option == OPT_SHOW) { const char *s; int len, charlen; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "object"); return JIM_ERR; } s = Jim_GetString(argv[2], &len); #ifdef JIM_UTF8 charlen = utf8_strlen(s, len); #else charlen = len; #endif printf("refcount: %d, type: %s\n", argv[2]->refCount, JimObjTypeName(argv[2])); printf("chars (%d): <<%s>>\n", charlen, s); printf("bytes (%d):", len); while (len--) { printf(" %02x", (unsigned char)*s++); } printf("\n"); return JIM_OK; } else if (option == OPT_SCRIPTLEN) { ScriptObj *script; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "script"); return JIM_ERR; } script = JimGetScript(interp, argv[2]); if (script == NULL) return JIM_ERR; Jim_SetResultInt(interp, script->len); return JIM_OK; } else if (option == OPT_EXPRLEN) { ExprByteCode *expr; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "expression"); return JIM_ERR; } expr = JimGetExpression(interp, argv[2]); if (expr == NULL) return JIM_ERR; Jim_SetResultInt(interp, expr->len); return JIM_OK; } else if (option == OPT_EXPRBC) { Jim_Obj *objPtr; ExprByteCode *expr; int i; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "expression"); return JIM_ERR; } expr = JimGetExpression(interp, argv[2]); if (expr == NULL) return JIM_ERR; objPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < expr->len; i++) { const char *type; const Jim_ExprOperator *op; Jim_Obj *obj = expr->token[i].objPtr; switch (expr->token[i].type) { case JIM_TT_EXPR_INT: type = "int"; break; case JIM_TT_EXPR_DOUBLE: type = "double"; break; case JIM_TT_CMD: type = "command"; break; case JIM_TT_VAR: type = "variable"; break; case JIM_TT_DICTSUGAR: type = "dictsugar"; break; case JIM_TT_EXPRSUGAR: type = "exprsugar"; break; case JIM_TT_ESC: type = "subst"; break; case JIM_TT_STR: type = "string"; break; default: op = JimExprOperatorInfoByOpcode(expr->token[i].type); if (op == NULL) { type = "private"; } else { type = "operator"; } obj = Jim_NewStringObj(interp, op ? op->name : "", -1); break; } Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, type, -1)); Jim_ListAppendElement(interp, objPtr, obj); } Jim_SetResult(interp, objPtr); return JIM_OK; } else { Jim_SetResultString(interp, "bad option. Valid options are refcount, " "objcount, objects, invstr", -1); return JIM_ERR; } /* unreached */ #endif /* JIM_BOOTSTRAP */ #if !defined(JIM_DEBUG_COMMAND) Jim_SetResultString(interp, "unsupported", -1); return JIM_ERR; #endif } /* [eval] */ static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int rc; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "arg ?arg ...?"); return JIM_ERR; } if (argc == 2) { rc = Jim_EvalObj(interp, argv[1]); } else { rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); } if (rc == JIM_ERR) { /* eval is "interesting", so add a stack frame here */ interp->addStackTrace++; } return rc; } /* [uplevel] */ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc >= 2) { int retcode; Jim_CallFrame *savedCallFrame, *targetCallFrame; int savedTailcall; const char *str; /* Save the old callframe pointer */ savedCallFrame = interp->framePtr; /* Lookup the target frame pointer */ str = Jim_String(argv[1]); if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); argc--; argv++; } else { targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); } if (targetCallFrame == NULL) { return JIM_ERR; } if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); return JIM_ERR; } /* Eval the code in the target callframe. */ interp->framePtr = targetCallFrame; /* Can't merge tailcalls across upcall */ savedTailcall = interp->framePtr->tailcall; interp->framePtr->tailcall = 0; if (argc == 2) { retcode = Jim_EvalObj(interp, argv[1]); } else { retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); } interp->framePtr->tailcall = savedTailcall; interp->framePtr = savedCallFrame; return retcode; } else { Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); return JIM_ERR; } } /* [expr] */ static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *exprResultPtr; int retcode; if (argc == 2) { retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); } else if (argc > 2) { Jim_Obj *objPtr; objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); Jim_IncrRefCount(objPtr); retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); Jim_DecrRefCount(interp, objPtr); } else { Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); return JIM_ERR; } if (retcode != JIM_OK) return retcode; Jim_SetResult(interp, exprResultPtr); Jim_DecrRefCount(interp, exprResultPtr); return JIM_OK; } /* [break] */ static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } return JIM_BREAK; } /* [continue] */ static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } return JIM_CONTINUE; } /* [return] */ static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; Jim_Obj *stackTraceObj = NULL; Jim_Obj *errorCodeObj = NULL; int returnCode = JIM_OK; long level = 1; for (i = 1; i < argc - 1; i += 2) { if (Jim_CompareStringImmediate(interp, argv[i], "-code")) { if (Jim_GetReturnCode(interp, argv[i + 1], &returnCode) == JIM_ERR) { return JIM_ERR; } } else if (Jim_CompareStringImmediate(interp, argv[i], "-errorinfo")) { stackTraceObj = argv[i + 1]; } else if (Jim_CompareStringImmediate(interp, argv[i], "-errorcode")) { errorCodeObj = argv[i + 1]; } else if (Jim_CompareStringImmediate(interp, argv[i], "-level")) { if (Jim_GetLong(interp, argv[i + 1], &level) != JIM_OK || level < 0) { Jim_SetResultFormatted(interp, "bad level \"%#s\"", argv[i + 1]); return JIM_ERR; } } else { break; } } if (i != argc - 1 && i != argc) { Jim_WrongNumArgs(interp, 1, argv, "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); } /* If a stack trace is supplied and code is error, set the stack trace */ if (stackTraceObj && returnCode == JIM_ERR) { JimSetStackTrace(interp, stackTraceObj); } /* If an error code list is supplied, set the global $errorCode */ if (errorCodeObj && returnCode == JIM_ERR) { Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); } interp->returnCode = returnCode; interp->returnLevel = level; if (i == argc - 1) { Jim_SetResult(interp, argv[i]); } return JIM_RETURN; } /* [tailcall] */ static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (interp->framePtr->level == 0) { Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); return JIM_ERR; } else if (argc >= 2) { /* Need to resolve the tailcall command in the current context */ Jim_CallFrame *cf = interp->framePtr->parent; Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); if (cmdPtr == NULL) { return JIM_ERR; } JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); /* And stash this pre-resolved command */ JimIncrCmdRefCount(cmdPtr); cf->tailcallCmd = cmdPtr; /* And stash the command list */ JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); Jim_IncrRefCount(cf->tailcallObj); /* When the stack unwinds to the previous proc, the stashed command will be evaluated */ return JIM_EVAL; } return JIM_OK; } static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *cmdList; Jim_Obj *prefixListObj = Jim_CmdPrivData(interp); /* prefixListObj is a list to which the args need to be appended */ cmdList = Jim_DuplicateObj(interp, prefixListObj); Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1); return JimEvalObjList(interp, cmdList); } static void JimAliasCmdDelete(Jim_Interp *interp, void *privData) { Jim_Obj *prefixListObj = privData; Jim_DecrRefCount(interp, prefixListObj); } static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *prefixListObj; const char *newname; if (argc < 3) { Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?"); return JIM_ERR; } prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2); Jim_IncrRefCount(prefixListObj); newname = Jim_String(argv[1]); if (newname[0] == ':' && newname[1] == ':') { while (*++newname == ':') { } } Jim_SetResult(interp, argv[1]); return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete); } /* [proc] */ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Cmd *cmd; if (argc != 4 && argc != 5) { Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body"); return JIM_ERR; } if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) { return JIM_ERR; } if (argc == 4) { cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL); } else { cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); } if (cmd) { /* Add the new command */ Jim_Obj *qualifiedCmdNameObj; const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); JimCreateCommand(interp, cmdname, cmd); /* Calculate and set the namespace for this proc */ JimUpdateProcNamespace(interp, cmd, cmdname); JimFreeQualifiedName(interp, qualifiedCmdNameObj); /* Unlike Tcl, set the name of the proc as the result */ Jim_SetResult(interp, argv[1]); return JIM_OK; } return JIM_ERR; } /* [local] */ static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retcode; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); return JIM_ERR; } /* Evaluate the arguments with 'local' in force */ interp->local++; retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); interp->local--; /* If OK, and the result is a proc, add it to the list of local procs */ if (retcode == 0) { Jim_Obj *cmdNameObj = Jim_GetResult(interp); if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) { return JIM_ERR; } if (interp->framePtr->localCommands == NULL) { interp->framePtr->localCommands = Jim_Alloc(sizeof(*interp->framePtr->localCommands)); Jim_InitStack(interp->framePtr->localCommands); } Jim_IncrRefCount(cmdNameObj); Jim_StackPush(interp->framePtr->localCommands, cmdNameObj); } return retcode; } /* [upcall] */ static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); return JIM_ERR; } else { int retcode; Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) { Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]); return JIM_ERR; } /* OK. Mark this command as being in an upcall */ cmdPtr->u.proc.upcall++; JimIncrCmdRefCount(cmdPtr); /* Invoke the command as normal */ retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); /* No longer in an upcall */ cmdPtr->u.proc.upcall--; JimDecrCmdRefCount(interp, cmdPtr); return retcode; } } /* [apply] */ static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "lambdaExpr ?arg ...?"); return JIM_ERR; } else { int ret; Jim_Cmd *cmd; Jim_Obj *argListObjPtr; Jim_Obj *bodyObjPtr; Jim_Obj *nsObj = NULL; Jim_Obj **nargv; int len = Jim_ListLength(interp, argv[1]); if (len != 2 && len != 3) { Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]); return JIM_ERR; } if (len == 3) { #ifdef jim_ext_namespace /* Need to canonicalise the given namespace. */ nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); #else Jim_SetResultString(interp, "namespaces not enabled", -1); return JIM_ERR; #endif } argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0); bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1); cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj); if (cmd) { /* Create a new argv array with a dummy argv[0], for error messages */ nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv)); nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1); Jim_IncrRefCount(nargv[0]); memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv)); ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv); Jim_DecrRefCount(interp, nargv[0]); Jim_Free(nargv); JimDecrCmdRefCount(interp, cmd); return ret; } return JIM_ERR; } } /* [concat] */ static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); return JIM_OK; } /* [upvar] */ static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; Jim_CallFrame *targetCallFrame; /* Lookup the target frame pointer */ if (argc > 3 && (argc % 2 == 0)) { targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); argc--; argv++; } else { targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); } if (targetCallFrame == NULL) { return JIM_ERR; } /* Check for arity */ if (argc < 3) { Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); return JIM_ERR; } /* Now... for every other/local couple: */ for (i = 1; i < argc; i += 2) { if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) return JIM_ERR; } return JIM_OK; } /* [global] */ static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); return JIM_ERR; } /* Link every var to the toplevel having the same name */ if (interp->framePtr->level == 0) return JIM_OK; /* global at toplevel... */ for (i = 1; i < argc; i++) { /* global ::blah does nothing */ const char *name = Jim_String(argv[i]); if (name[0] != ':' || name[1] != ':') { if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) return JIM_ERR; } } return JIM_OK; } /* does the [string map] operation. On error NULL is returned, * otherwise a new string object with the result, having refcount = 0, * is returned. */ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr, Jim_Obj *objPtr, int nocase) { int numMaps; const char *str, *noMatchStart = NULL; int strLen, i; Jim_Obj *resultObjPtr; numMaps = Jim_ListLength(interp, mapListObjPtr); if (numMaps % 2) { Jim_SetResultString(interp, "list must contain an even number of elements", -1); return NULL; } str = Jim_String(objPtr); strLen = Jim_Utf8Length(interp, objPtr); /* Map it */ resultObjPtr = Jim_NewStringObj(interp, "", 0); while (strLen) { for (i = 0; i < numMaps; i += 2) { Jim_Obj *objPtr; const char *k; int kl; objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); k = Jim_String(objPtr); kl = Jim_Utf8Length(interp, objPtr); if (strLen >= kl && kl) { int rc; rc = JimStringCompareLen(str, k, kl, nocase); if (rc == 0) { if (noMatchStart) { Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); noMatchStart = NULL; } Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1)); str += utf8_index(str, kl); strLen -= kl; break; } } } if (i == numMaps) { /* no match */ int c; if (noMatchStart == NULL) noMatchStart = str; str += utf8_tounicode(str, &c); strLen--; } } if (noMatchStart) { Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); } return resultObjPtr; } /* [string] */ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int len; int opt_case = 1; int option; static const char * const options[] = { "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace", "map", "repeat", "reverse", "index", "first", "last", "cat", "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL }; enum { OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE, OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, OPT_CAT, OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE }; static const char * const nocase_options[] = { "-nocase", NULL }; static const char * const nocase_length_options[] = { "-nocase", "-length", NULL }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) return JIM_ERR; switch (option) { case OPT_LENGTH: case OPT_BYTELENGTH: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } if (option == OPT_LENGTH) { len = Jim_Utf8Length(interp, argv[2]); } else { len = Jim_Length(argv[2]); } Jim_SetResultInt(interp, len); return JIM_OK; case OPT_CAT:{ Jim_Obj *objPtr; if (argc == 3) { /* optimise the one-arg case */ objPtr = argv[2]; } else { int i; objPtr = Jim_NewStringObj(interp, "", 0); for (i = 2; i < argc; i++) { Jim_AppendObj(interp, objPtr, argv[i]); } } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_COMPARE: case OPT_EQUAL: { /* n is the number of remaining option args */ long opt_length = -1; int n = argc - 4; int i = 2; while (n > 0) { int subopt; if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL, JIM_ENUM_ABBREV) != JIM_OK) { badcompareargs: Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); return JIM_ERR; } if (subopt == 0) { /* -nocase */ opt_case = 0; n--; } else { /* -length */ if (n < 2) { goto badcompareargs; } if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) { return JIM_ERR; } n -= 2; } } if (n) { goto badcompareargs; } argv += argc - 2; if (opt_length < 0 && option != OPT_COMPARE && opt_case) { /* Fast version - [string equal], case sensitive, no length */ Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); } else { if (opt_length >= 0) { n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); } else { n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case); } Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0); } return JIM_OK; } case OPT_MATCH: if (argc != 4 && (argc != 5 || Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, JIM_ENUM_ABBREV) != JIM_OK)) { Jim_WrongNumArgs(interp, 2, argv, "?-nocase? pattern string"); return JIM_ERR; } if (opt_case == 0) { argv++; } Jim_SetResultBool(interp, Jim_StringMatchObj(interp, argv[2], argv[3], !opt_case)); return JIM_OK; case OPT_MAP:{ Jim_Obj *objPtr; if (argc != 4 && (argc != 5 || Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, JIM_ENUM_ABBREV) != JIM_OK)) { Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList string"); return JIM_ERR; } if (opt_case == 0) { argv++; } objPtr = JimStringMap(interp, argv[2], argv[3], !opt_case); if (objPtr == NULL) { return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_RANGE: case OPT_BYTERANGE:{ Jim_Obj *objPtr; if (argc != 5) { Jim_WrongNumArgs(interp, 2, argv, "string first last"); return JIM_ERR; } if (option == OPT_RANGE) { objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); } else { objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); } if (objPtr == NULL) { return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_REPLACE:{ Jim_Obj *objPtr; if (argc != 5 && argc != 6) { Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?"); return JIM_ERR; } objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL); if (objPtr == NULL) { return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_REPEAT:{ Jim_Obj *objPtr; jim_wide count; if (argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "string count"); return JIM_ERR; } if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) { return JIM_ERR; } objPtr = Jim_NewStringObj(interp, "", 0); if (count > 0) { while (count--) { Jim_AppendObj(interp, objPtr, argv[2]); } } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_REVERSE:{ char *buf, *p; const char *str; int len; int i; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } str = Jim_GetString(argv[2], &len); buf = Jim_Alloc(len + 1); p = buf + len; *p = 0; for (i = 0; i < len; ) { int c; int l = utf8_tounicode(str, &c); memcpy(p - l, str, l); p -= l; i += l; str += l; } Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); return JIM_OK; } case OPT_INDEX:{ int idx; const char *str; if (argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "string index"); return JIM_ERR; } if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) { return JIM_ERR; } str = Jim_String(argv[2]); len = Jim_Utf8Length(interp, argv[2]); if (idx != INT_MIN && idx != INT_MAX) { idx = JimRelToAbsIndex(len, idx); } if (idx < 0 || idx >= len || str == NULL) { Jim_SetResultString(interp, "", 0); } else if (len == Jim_Length(argv[2])) { /* ASCII optimisation */ Jim_SetResultString(interp, str + idx, 1); } else { int c; int i = utf8_index(str, idx); Jim_SetResultString(interp, str + i, utf8_tounicode(str + i, &c)); } return JIM_OK; } case OPT_FIRST: case OPT_LAST:{ int idx = 0, l1, l2; const char *s1, *s2; if (argc != 4 && argc != 5) { Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?"); return JIM_ERR; } s1 = Jim_String(argv[2]); s2 = Jim_String(argv[3]); l1 = Jim_Utf8Length(interp, argv[2]); l2 = Jim_Utf8Length(interp, argv[3]); if (argc == 5) { if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) { return JIM_ERR; } idx = JimRelToAbsIndex(l2, idx); } else if (option == OPT_LAST) { idx = l2; } if (option == OPT_FIRST) { Jim_SetResultInt(interp, JimStringFirst(s1, l1, s2, l2, idx)); } else { #ifdef JIM_UTF8 Jim_SetResultInt(interp, JimStringLastUtf8(s1, l1, s2, idx)); #else Jim_SetResultInt(interp, JimStringLast(s1, l1, s2, idx)); #endif } return JIM_OK; } case OPT_TRIM: case OPT_TRIMLEFT: case OPT_TRIMRIGHT:{ Jim_Obj *trimchars; if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?"); return JIM_ERR; } trimchars = (argc == 4 ? argv[3] : NULL); if (option == OPT_TRIM) { Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars)); } else if (option == OPT_TRIMLEFT) { Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars)); } else if (option == OPT_TRIMRIGHT) { Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars)); } return JIM_OK; } case OPT_TOLOWER: case OPT_TOUPPER: case OPT_TOTITLE: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } if (option == OPT_TOLOWER) { Jim_SetResult(interp, JimStringToLower(interp, argv[2])); } else if (option == OPT_TOUPPER) { Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); } else { Jim_SetResult(interp, JimStringToTitle(interp, argv[2])); } return JIM_OK; case OPT_IS: if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); } Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); return JIM_ERR; } return JIM_OK; } /* [time] */ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { long i, count = 1; jim_wide start, elapsed; char buf[60]; const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration"; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "script ?count?"); return JIM_ERR; } if (argc == 3) { if (Jim_GetLong(interp, argv[2], &count) != JIM_OK) return JIM_ERR; } if (count < 0) return JIM_OK; i = count; start = JimClock(); while (i-- > 0) { int retval; retval = Jim_EvalObj(interp, argv[1]); if (retval != JIM_OK) { return retval; } } elapsed = JimClock() - start; sprintf(buf, fmt, count == 0 ? 0 : elapsed / count); Jim_SetResultString(interp, buf, -1); return JIM_OK; } /* [exit] */ static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { long exitCode = 0; if (argc > 2) { Jim_WrongNumArgs(interp, 1, argv, "?exitCode?"); return JIM_ERR; } if (argc == 2) { if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK) return JIM_ERR; } interp->exitCode = exitCode; return JIM_EXIT; } /* [catch] */ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int exitCode = 0; int i; int sig = 0; /* Which return codes are ignored (passed through)? By default, only exit, eval and signal */ jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); static const int max_ignore_code = sizeof(ignore_mask) * 8; /* Reset the error code before catch. * Note that this is not strictly correct. */ Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); for (i = 1; i < argc - 1; i++) { const char *arg = Jim_String(argv[i]); jim_wide option; int ignore; /* It's a pity we can't use Jim_GetEnum here :-( */ if (strcmp(arg, "--") == 0) { i++; break; } if (*arg != '-') { break; } if (strncmp(arg, "-no", 3) == 0) { arg += 3; ignore = 1; } else { arg++; ignore = 0; } if (Jim_StringToWide(arg, &option, 10) != JIM_OK) { option = -1; } if (option < 0) { option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize); } if (option < 0) { goto wrongargs; } if (ignore) { ignore_mask |= (1 << option); } else { ignore_mask &= ~(1 << option); } } argc -= i; if (argc < 1 || argc > 3) { wrongargs: Jim_WrongNumArgs(interp, 1, argv, "?-?no?code ... --? script ?resultVarName? ?optionVarName?"); return JIM_ERR; } argv += i; if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { sig++; } interp->signal_level += sig; if (Jim_CheckSignal(interp)) { /* If a signal is set, don't even try to execute the body */ exitCode = JIM_SIGNAL; } else { exitCode = Jim_EvalObj(interp, argv[0]); /* Don't want any caught error included in a later stack trace */ interp->errorFlag = 0; } interp->signal_level -= sig; /* Catch or pass through? Only the first 32/64 codes can be passed through */ if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { /* Not caught, pass it up */ return exitCode; } if (sig && exitCode == JIM_SIGNAL) { /* Catch the signal at this level */ if (interp->signal_set_result) { interp->signal_set_result(interp, interp->sigmask); } else { Jim_SetResultInt(interp, interp->sigmask); } interp->sigmask = 0; } if (argc >= 2) { if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) { return JIM_ERR; } if (argc == 3) { Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); if (exitCode == JIM_ERR) { Jim_Obj *errorCode; Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", -1)); Jim_ListAppendElement(interp, optListObj, interp->stackTrace); errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); if (errorCode) { Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); Jim_ListAppendElement(interp, optListObj, errorCode); } } if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) { return JIM_ERR; } } } Jim_SetResultInt(interp, exitCode); return JIM_OK; } #ifdef JIM_REFERENCES /* [ref] */ static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); return JIM_ERR; } if (argc == 3) { Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); } else { Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); } return JIM_OK; } /* [getref] */ static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Reference *refPtr; if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "reference"); return JIM_ERR; } if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) return JIM_ERR; Jim_SetResult(interp, refPtr->objPtr); return JIM_OK; } /* [setref] */ static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Reference *refPtr; if (argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); return JIM_ERR; } if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) return JIM_ERR; Jim_IncrRefCount(argv[2]); Jim_DecrRefCount(interp, refPtr->objPtr); refPtr->objPtr = argv[2]; Jim_SetResult(interp, argv[2]); return JIM_OK; } /* [collect] */ static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } Jim_SetResultInt(interp, Jim_Collect(interp)); /* Free all the freed objects. */ while (interp->freeList) { Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; Jim_Free(interp->freeList); interp->freeList = nextObjPtr; } return JIM_OK; } /* [finalize] reference ?newValue? */ static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); return JIM_ERR; } if (argc == 2) { Jim_Obj *cmdNamePtr; if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) return JIM_ERR; if (cmdNamePtr != NULL) /* otherwise the null string is returned. */ Jim_SetResult(interp, cmdNamePtr); } else { if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) return JIM_ERR; Jim_SetResult(interp, argv[2]); } return JIM_OK; } /* [info references] */ static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listObjPtr; Jim_HashTableIterator htiter; Jim_HashEntry *he; listObjPtr = Jim_NewListObj(interp, NULL, 0); JimInitHashTableIterator(&interp->references, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { char buf[JIM_REFERENCE_SPACE + 1]; Jim_Reference *refPtr = Jim_GetHashEntryVal(he); const unsigned long *refId = he->key; JimFormatReference(buf, refPtr, *refId); Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); } Jim_SetResult(interp, listObjPtr); return JIM_OK; } #endif /* [rename] */ static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "oldName newName"); return JIM_ERR; } if (JimValidName(interp, "new procedure", argv[2])) { return JIM_ERR; } return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); } #define JIM_DICTMATCH_VALUES 0x0001 typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type); static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) { Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); if (type & JIM_DICTMATCH_VALUES) { Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); } } /** * Like JimHashtablePatternMatch, but for dictionaries. */ static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, JimDictMatchCallbackType *callback, int type) { Jim_HashEntry *he; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); /* Check for the non-pattern case. We can do this much more efficiently. */ Jim_HashTableIterator htiter; JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { callback(interp, listObjPtr, he, type); } } return listObjPtr; } int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) { if (SetDictFromAny(interp, objPtr) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0)); return JIM_OK; } int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) { if (SetDictFromAny(interp, objPtr) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES)); return JIM_OK; } int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) { if (SetDictFromAny(interp, objPtr) != JIM_OK) { return -1; } return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; } int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_HashTable *ht; unsigned int i; if (SetDictFromAny(interp, objPtr) != JIM_OK) { return JIM_ERR; } ht = (Jim_HashTable *)objPtr->internalRep.ptr; /* Note that this uses internal knowledge of the hash table */ printf("%d entries in table, %d buckets\n", ht->used, ht->size); for (i = 0; i < ht->size; i++) { Jim_HashEntry *he = ht->table[i]; if (he) { printf("%d: ", i); while (he) { printf(" %s", Jim_String(he->key)); he = he->next; } printf("\n"); } } return JIM_OK; } static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) { Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1); Jim_AppendString(interp, prefixObj, " ", 1); Jim_AppendString(interp, prefixObj, subcmd, -1); return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); } /* [dict] */ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; int option; static const char * const options[] = { "create", "get", "set", "unset", "exists", "keys", "size", "info", "merge", "with", "append", "lappend", "incr", "remove", "values", "for", "replace", "update", NULL }; enum { OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, OPT_REPLACE, OPT_UPDATE, }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_GET: if (argc < 3) { Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); return JIM_ERR; } if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; case OPT_SET: if (argc < 5) { Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); return JIM_ERR; } return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); case OPT_EXISTS: if (argc < 4) { Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); return JIM_ERR; } else { int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); if (rc < 0) { return JIM_ERR; } Jim_SetResultBool(interp, rc == JIM_OK); return JIM_OK; } case OPT_UNSET: if (argc < 4) { Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); return JIM_ERR; } if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { return JIM_ERR; } return JIM_OK; case OPT_KEYS: if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); return JIM_ERR; } return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); case OPT_SIZE: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "dictionary"); return JIM_ERR; } else if (Jim_DictSize(interp, argv[2]) < 0) { return JIM_ERR; } Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); return JIM_OK; case OPT_MERGE: if (argc == 2) { return JIM_OK; } if (Jim_DictSize(interp, argv[2]) < 0) { return JIM_ERR; } /* Handle as ensemble */ break; case OPT_UPDATE: if (argc < 6 || argc % 2) { /* Better error message */ argc = 2; } break; case OPT_CREATE: if (argc % 2) { Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); return JIM_ERR; } objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); Jim_SetResult(interp, objPtr); return JIM_OK; case OPT_INFO: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "dictionary"); return JIM_ERR; } return Jim_DictInfo(interp, argv[2]); } /* Handle command as an ensemble */ return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); } /* [subst] */ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { static const char * const options[] = { "-nobackslashes", "-nocommands", "-novariables", NULL }; enum { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES }; int i; int flags = JIM_SUBST_FLAG; Jim_Obj *objPtr; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "?options? string"); return JIM_ERR; } for (i = 1; i < (argc - 1); i++) { int option; if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_NOBACKSLASHES: flags |= JIM_SUBST_NOESC; break; case OPT_NOCOMMANDS: flags |= JIM_SUBST_NOCMD; break; case OPT_NOVARIABLES: flags |= JIM_SUBST_NOVAR; break; } } if (Jim_SubstObj(interp, argv[argc - 1], &objPtr, flags) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; } /* [info] */ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int cmd; Jim_Obj *objPtr; int mode = 0; static const char * const commands[] = { "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals", "vars", "version", "patchlevel", "complete", "args", "hostname", "script", "source", "stacktrace", "nameofexecutable", "returncodes", "references", "alias", NULL }; enum { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, }; #ifdef jim_ext_namespace int nons = 0; if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { /* This is for internal use only */ argc--; argv++; nons = 1; } #endif if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } /* Test for the the most common commands first, just in case it makes a difference */ switch (cmd) { case INFO_EXISTS: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "varName"); return JIM_ERR; } Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL); break; case INFO_ALIAS:{ Jim_Cmd *cmdPtr; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "command"); return JIM_ERR; } if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { return JIM_ERR; } if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) { Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]); return JIM_ERR; } Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData); return JIM_OK; } case INFO_CHANNELS: mode++; /* JIM_CMDLIST_CHANNELS */ #ifndef jim_ext_aio Jim_SetResultString(interp, "aio not enabled", -1); return JIM_ERR; #endif case INFO_PROCS: mode++; /* JIM_CMDLIST_PROCS */ case INFO_COMMANDS: /* mode 0 => JIM_CMDLIST_COMMANDS */ if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); return JIM_ERR; } #ifdef jim_ext_namespace if (!nons) { if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); } } #endif Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); break; case INFO_VARS: mode++; /* JIM_VARLIST_VARS */ case INFO_LOCALS: mode++; /* JIM_VARLIST_LOCALS */ case INFO_GLOBALS: /* mode 0 => JIM_VARLIST_GLOBALS */ if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); return JIM_ERR; } #ifdef jim_ext_namespace if (!nons) { if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); } } #endif Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode)); break; case INFO_SCRIPT: if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, JimGetScript(interp, interp->currentScriptObj)->fileNameObj); break; case INFO_SOURCE:{ jim_wide line; Jim_Obj *resObjPtr; Jim_Obj *fileNameObj; if (argc != 3 && argc != 5) { Jim_WrongNumArgs(interp, 2, argv, "source ?filename line?"); return JIM_ERR; } if (argc == 5) { if (Jim_GetWide(interp, argv[4], &line) != JIM_OK) { return JIM_ERR; } resObjPtr = Jim_NewStringObj(interp, Jim_String(argv[2]), Jim_Length(argv[2])); JimSetSourceInfo(interp, resObjPtr, argv[3], line); } else { if (argv[2]->typePtr == &sourceObjType) { fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj; line = argv[2]->internalRep.sourceValue.lineNumber; } else if (argv[2]->typePtr == &scriptObjType) { ScriptObj *script = JimGetScript(interp, argv[2]); fileNameObj = script->fileNameObj; line = script->firstline; } else { fileNameObj = interp->emptyObj; line = 1; } resObjPtr = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, resObjPtr, fileNameObj); Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); } Jim_SetResult(interp, resObjPtr); break; } case INFO_STACKTRACE: Jim_SetResult(interp, interp->stackTrace); break; case INFO_LEVEL: case INFO_FRAME: switch (argc) { case 2: Jim_SetResultInt(interp, interp->framePtr->level); break; case 3: if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, objPtr); break; default: Jim_WrongNumArgs(interp, 2, argv, "?levelNum?"); return JIM_ERR; } break; case INFO_BODY: case INFO_STATICS: case INFO_ARGS:{ Jim_Cmd *cmdPtr; if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "procname"); return JIM_ERR; } if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { return JIM_ERR; } if (!cmdPtr->isproc) { Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]); return JIM_ERR; } switch (cmd) { case INFO_BODY: Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr); break; case INFO_ARGS: Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); break; case INFO_STATICS: if (cmdPtr->u.proc.staticVars) { int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES; Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, NULL, JimVariablesMatch, mode)); } break; } break; } case INFO_VERSION: case INFO_PATCHLEVEL:{ char buf[(JIM_INTEGER_SPACE * 2) + 1]; sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100); Jim_SetResultString(interp, buf, -1); break; } case INFO_COMPLETE: if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "script ?missing?"); return JIM_ERR; } else { int len; const char *s = Jim_GetString(argv[2], &len); char missing; Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing)); if (missing != ' ' && argc == 4) { Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1)); } } break; case INFO_HOSTNAME: /* Redirect to os.gethostname if it exists */ return Jim_Eval(interp, "os.gethostname"); case INFO_NAMEOFEXECUTABLE: /* Redirect to Tcl proc */ return Jim_Eval(interp, "{info nameofexecutable}"); case INFO_RETURNCODES: if (argc == 2) { int i; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; jimReturnCodes[i]; i++) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewIntObj(interp, i)); Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, jimReturnCodes[i], -1)); } Jim_SetResult(interp, listObjPtr); } else if (argc == 3) { long code; const char *name; if (Jim_GetLong(interp, argv[2], &code) != JIM_OK) { return JIM_ERR; } name = Jim_ReturnCode(code); if (*name == '?') { Jim_SetResultInt(interp, code); } else { Jim_SetResultString(interp, name, -1); } } else { Jim_WrongNumArgs(interp, 2, argv, "?code?"); return JIM_ERR; } break; case INFO_REFERENCES: #ifdef JIM_REFERENCES return JimInfoReferences(interp, argc, argv); #else Jim_SetResultString(interp, "not supported", -1); return JIM_ERR; #endif } return JIM_OK; } /* [exists] */ static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; int result = 0; static const char * const options[] = { "-command", "-proc", "-alias", "-var", NULL }; enum { OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_VAR }; int option; if (argc == 2) { option = OPT_VAR; objPtr = argv[1]; } else if (argc == 3) { if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } objPtr = argv[2]; } else { Jim_WrongNumArgs(interp, 1, argv, "?option? name"); return JIM_ERR; } if (option == OPT_VAR) { result = Jim_GetVariable(interp, objPtr, 0) != NULL; } else { /* Now different kinds of commands */ Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); if (cmd) { switch (option) { case OPT_COMMAND: result = 1; break; case OPT_ALIAS: result = cmd->isproc == 0 && cmd->u.native.cmdProc == JimAliasCmd; break; case OPT_PROC: result = cmd->isproc; break; } } } Jim_SetResultBool(interp, result); return JIM_OK; } /* [split] */ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *str, *splitChars, *noMatchStart; int splitLen, strLen; Jim_Obj *resObjPtr; int c; int len; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?"); return JIM_ERR; } str = Jim_GetString(argv[1], &len); if (len == 0) { return JIM_OK; } strLen = Jim_Utf8Length(interp, argv[1]); /* Init */ if (argc == 2) { splitChars = " \n\t\r"; splitLen = 4; } else { splitChars = Jim_String(argv[2]); splitLen = Jim_Utf8Length(interp, argv[2]); } noMatchStart = str; resObjPtr = Jim_NewListObj(interp, NULL, 0); /* Split */ if (splitLen) { Jim_Obj *objPtr; while (strLen--) { const char *sc = splitChars; int scLen = splitLen; int sl = utf8_tounicode(str, &c); while (scLen--) { int pc; sc += utf8_tounicode(sc, &pc); if (c == pc) { objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); Jim_ListAppendElement(interp, resObjPtr, objPtr); noMatchStart = str + sl; break; } } str += sl; } objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); Jim_ListAppendElement(interp, resObjPtr, objPtr); } else { /* This handles the special case of splitchars eq {} * Optimise by sharing common (ASCII) characters */ Jim_Obj **commonObj = NULL; #define NUM_COMMON (128 - 9) while (strLen--) { int n = utf8_tounicode(str, &c); #ifdef JIM_OPTIMIZATION if (c >= 9 && c < 128) { /* Common ASCII char. Note that 9 is the tab character */ c -= 9; if (!commonObj) { commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); } if (!commonObj[c]) { commonObj[c] = Jim_NewStringObj(interp, str, 1); } Jim_ListAppendElement(interp, resObjPtr, commonObj[c]); str++; continue; } #endif Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObjUtf8(interp, str, 1)); str += n; } Jim_Free(commonObj); } Jim_SetResult(interp, resObjPtr); return JIM_OK; } /* [join] */ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *joinStr; int joinStrLen; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); return JIM_ERR; } /* Init */ if (argc == 2) { joinStr = " "; joinStrLen = 1; } else { joinStr = Jim_GetString(argv[2], &joinStrLen); } Jim_SetResult(interp, Jim_ListJoin(interp, argv[1], joinStr, joinStrLen)); return JIM_OK; } /* [format] */ static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?"); return JIM_ERR; } objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2); if (objPtr == NULL) return JIM_ERR; Jim_SetResult(interp, objPtr); return JIM_OK; } /* [scan] */ static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listPtr, **outVec; int outc, i; if (argc < 3) { Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?"); return JIM_ERR; } if (argv[2]->typePtr != &scanFmtStringObjType) SetScanFmtFromAny(interp, argv[2]); if (FormatGetError(argv[2]) != 0) { Jim_SetResultString(interp, FormatGetError(argv[2]), -1); return JIM_ERR; } if (argc > 3) { int maxPos = FormatGetMaxPos(argv[2]); int count = FormatGetCnvCount(argv[2]); if (maxPos > argc - 3) { Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1); return JIM_ERR; } else if (count > argc - 3) { Jim_SetResultString(interp, "different numbers of variable names and " "field specifiers", -1); return JIM_ERR; } else if (count < argc - 3) { Jim_SetResultString(interp, "variable is not assigned by any " "conversion specifiers", -1); return JIM_ERR; } } listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG); if (listPtr == 0) return JIM_ERR; if (argc > 3) { int rc = JIM_OK; int count = 0; if (listPtr != 0 && listPtr != (Jim_Obj *)EOF) { int len = Jim_ListLength(interp, listPtr); if (len != 0) { JimListGetElements(interp, listPtr, &outc, &outVec); for (i = 0; i < outc; ++i) { if (Jim_Length(outVec[i]) > 0) { ++count; if (Jim_SetVariable(interp, argv[3 + i], outVec[i]) != JIM_OK) { rc = JIM_ERR; } } } } Jim_FreeNewObj(interp, listPtr); } else { count = -1; } if (rc == JIM_OK) { Jim_SetResultInt(interp, count); } return rc; } else { if (listPtr == (Jim_Obj *)EOF) { Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0)); return JIM_OK; } Jim_SetResult(interp, listPtr); } return JIM_OK; } /* [error] */ static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?"); return JIM_ERR; } Jim_SetResult(interp, argv[1]); if (argc == 3) { JimSetStackTrace(interp, argv[2]); return JIM_ERR; } interp->addStackTrace++; return JIM_ERR; } /* [lrange] */ static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; if (argc != 4) { Jim_WrongNumArgs(interp, 1, argv, "list first last"); return JIM_ERR; } if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL) return JIM_ERR; Jim_SetResult(interp, objPtr); return JIM_OK; } /* [lrepeat] */ static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; long count; if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) { Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?"); return JIM_ERR; } if (count == 0 || argc == 2) { return JIM_OK; } argc -= 2; argv += 2; objPtr = Jim_NewListObj(interp, argv, argc); while (--count) { ListInsertElements(objPtr, -1, argc, argv); } Jim_SetResult(interp, objPtr); return JIM_OK; } char **Jim_GetEnviron(void) { #if defined(HAVE__NSGETENVIRON) return *_NSGetEnviron(); #else #if !defined(NO_ENVIRON_EXTERN) extern char **environ; #endif return environ; #endif } void Jim_SetEnviron(char **env) { #if defined(HAVE__NSGETENVIRON) *_NSGetEnviron() = env; #else #if !defined(NO_ENVIRON_EXTERN) extern char **environ; #endif environ = env; #endif } /* [env] */ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *key; const char *val; if (argc == 1) { char **e = Jim_GetEnviron(); int i; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; e[i]; i++) { const char *equals = strchr(e[i], '='); if (equals) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, e[i], equals - e[i])); Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1)); } } Jim_SetResult(interp, listObjPtr); return JIM_OK; } if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "varName ?default?"); return JIM_ERR; } key = Jim_String(argv[1]); val = getenv(key); if (val == NULL) { if (argc < 3) { Jim_SetResultFormatted(interp, "environment variable \"%#s\" does not exist", argv[1]); return JIM_ERR; } val = Jim_String(argv[2]); } Jim_SetResult(interp, Jim_NewStringObj(interp, val, -1)); return JIM_OK; } /* [source] */ static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retval; if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "fileName"); return JIM_ERR; } retval = Jim_EvalFile(interp, Jim_String(argv[1])); if (retval == JIM_RETURN) return JIM_OK; return retval; } /* [lreverse] */ static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *revObjPtr, **ele; int len; if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "list"); return JIM_ERR; } JimListGetElements(interp, argv[1], &len, &ele); len--; revObjPtr = Jim_NewListObj(interp, NULL, 0); while (len >= 0) ListAppendElement(revObjPtr, ele[len--]); Jim_SetResult(interp, revObjPtr); return JIM_OK; } static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step) { jim_wide len; if (step == 0) return -1; if (start == end) return 0; else if (step > 0 && start > end) return -1; else if (step < 0 && end > start) return -1; len = end - start; if (len < 0) len = -len; /* abs(len) */ if (step < 0) step = -step; /* abs(step) */ len = 1 + ((len - 1) / step); /* We can truncate safely to INT_MAX, the range command * will always return an error for a such long range * because Tcl lists can't be so long. */ if (len > INT_MAX) len = INT_MAX; return (int)((len < 0) ? -1 : len); } /* [range] */ static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { jim_wide start = 0, end, step = 1; int len, i; Jim_Obj *objPtr; if (argc < 2 || argc > 4) { Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?"); return JIM_ERR; } if (argc == 2) { if (Jim_GetWide(interp, argv[1], &end) != JIM_OK) return JIM_ERR; } else { if (Jim_GetWide(interp, argv[1], &start) != JIM_OK || Jim_GetWide(interp, argv[2], &end) != JIM_OK) return JIM_ERR; if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK) return JIM_ERR; } if ((len = JimRangeLen(start, end, step)) == -1) { Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1); return JIM_ERR; } objPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < len; i++) ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step)); Jim_SetResult(interp, objPtr); return JIM_OK; } /* [rand] */ static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { jim_wide min = 0, max = 0, len, maxMul; if (argc < 1 || argc > 3) { Jim_WrongNumArgs(interp, 1, argv, "?min? max"); return JIM_ERR; } if (argc == 1) { max = JIM_WIDE_MAX; } else if (argc == 2) { if (Jim_GetWide(interp, argv[1], &max) != JIM_OK) return JIM_ERR; } else if (argc == 3) { if (Jim_GetWide(interp, argv[1], &min) != JIM_OK || Jim_GetWide(interp, argv[2], &max) != JIM_OK) return JIM_ERR; } len = max-min; if (len < 0) { Jim_SetResultString(interp, "Invalid arguments (max < min)", -1); return JIM_ERR; } maxMul = JIM_WIDE_MAX - (len ? (JIM_WIDE_MAX%len) : 0); while (1) { jim_wide r; JimRandomBytes(interp, &r, sizeof(jim_wide)); if (r < 0 || r >= maxMul) continue; r = (len == 0) ? 0 : r%len; Jim_SetResultInt(interp, min+r); return JIM_OK; } } static const struct { const char *name; Jim_CmdProc *cmdProc; } Jim_CoreCommandsTable[] = { {"alias", Jim_AliasCoreCommand}, {"set", Jim_SetCoreCommand}, {"unset", Jim_UnsetCoreCommand}, {"puts", Jim_PutsCoreCommand}, {"+", Jim_AddCoreCommand}, {"*", Jim_MulCoreCommand}, {"-", Jim_SubCoreCommand}, {"/", Jim_DivCoreCommand}, {"incr", Jim_IncrCoreCommand}, {"while", Jim_WhileCoreCommand}, {"loop", Jim_LoopCoreCommand}, {"for", Jim_ForCoreCommand}, {"foreach", Jim_ForeachCoreCommand}, {"lmap", Jim_LmapCoreCommand}, {"lassign", Jim_LassignCoreCommand}, {"if", Jim_IfCoreCommand}, {"switch", Jim_SwitchCoreCommand}, {"list", Jim_ListCoreCommand}, {"lindex", Jim_LindexCoreCommand}, {"lset", Jim_LsetCoreCommand}, {"lsearch", Jim_LsearchCoreCommand}, {"llength", Jim_LlengthCoreCommand}, {"lappend", Jim_LappendCoreCommand}, {"linsert", Jim_LinsertCoreCommand}, {"lreplace", Jim_LreplaceCoreCommand}, {"lsort", Jim_LsortCoreCommand}, {"append", Jim_AppendCoreCommand}, {"debug", Jim_DebugCoreCommand}, {"eval", Jim_EvalCoreCommand}, {"uplevel", Jim_UplevelCoreCommand}, {"expr", Jim_ExprCoreCommand}, {"break", Jim_BreakCoreCommand}, {"continue", Jim_ContinueCoreCommand}, {"proc", Jim_ProcCoreCommand}, {"concat", Jim_ConcatCoreCommand}, {"return", Jim_ReturnCoreCommand}, {"upvar", Jim_UpvarCoreCommand}, {"global", Jim_GlobalCoreCommand}, {"string", Jim_StringCoreCommand}, {"time", Jim_TimeCoreCommand}, {"exit", Jim_ExitCoreCommand}, {"catch", Jim_CatchCoreCommand}, #ifdef JIM_REFERENCES {"ref", Jim_RefCoreCommand}, {"getref", Jim_GetrefCoreCommand}, {"setref", Jim_SetrefCoreCommand}, {"finalize", Jim_FinalizeCoreCommand}, {"collect", Jim_CollectCoreCommand}, #endif {"rename", Jim_RenameCoreCommand}, {"dict", Jim_DictCoreCommand}, {"subst", Jim_SubstCoreCommand}, {"info", Jim_InfoCoreCommand}, {"exists", Jim_ExistsCoreCommand}, {"split", Jim_SplitCoreCommand}, {"join", Jim_JoinCoreCommand}, {"format", Jim_FormatCoreCommand}, {"scan", Jim_ScanCoreCommand}, {"error", Jim_ErrorCoreCommand}, {"lrange", Jim_LrangeCoreCommand}, {"lrepeat", Jim_LrepeatCoreCommand}, {"env", Jim_EnvCoreCommand}, {"source", Jim_SourceCoreCommand}, {"lreverse", Jim_LreverseCoreCommand}, {"range", Jim_RangeCoreCommand}, {"rand", Jim_RandCoreCommand}, {"tailcall", Jim_TailcallCoreCommand}, {"local", Jim_LocalCoreCommand}, {"upcall", Jim_UpcallCoreCommand}, {"apply", Jim_ApplyCoreCommand}, {NULL, NULL}, }; void Jim_RegisterCoreCommands(Jim_Interp *interp) { int i = 0; while (Jim_CoreCommandsTable[i].name != NULL) { Jim_CreateCommand(interp, Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL); i++; } } /* ----------------------------------------------------------------------------- * Interactive prompt * ---------------------------------------------------------------------------*/ void Jim_MakeErrorMessage(Jim_Interp *interp) { Jim_Obj *argv[2]; argv[0] = Jim_NewStringObj(interp, "errorInfo", -1); argv[1] = interp->result; Jim_EvalObjVector(interp, 2, argv); } static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, const char *prefix, const char *const *tablePtr, const char *name) { int count; char **tablePtrSorted; int i; for (count = 0; tablePtr[count]; count++) { } if (name == NULL) { name = "option"; } Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); tablePtrSorted = Jim_Alloc(sizeof(char *) * count); memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); for (i = 0; i < count; i++) { if (i + 1 == count && count > 1) { Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); } Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); if (i + 1 != count) { Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); } } Jim_Free(tablePtrSorted); } int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr, int *indexPtr, const char *name, int flags) { const char *bad = "bad "; const char *const *entryPtr = NULL; int i; int match = -1; int arglen; const char *arg = Jim_GetString(objPtr, &arglen); *indexPtr = -1; for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { /* Found an exact match */ *indexPtr = i; return JIM_OK; } if (flags & JIM_ENUM_ABBREV) { /* Accept an unambiguous abbreviation. * Note that '-' doesnt' consitute a valid abbreviation */ if (strncmp(arg, *entryPtr, arglen) == 0) { if (*arg == '-' && arglen == 1) { break; } if (match >= 0) { bad = "ambiguous "; goto ambiguous; } match = i; } } } /* If we had an unambiguous partial match */ if (match >= 0) { *indexPtr = match; return JIM_OK; } ambiguous: if (flags & JIM_ERRMSG) { JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name); } return JIM_ERR; } int Jim_FindByName(const char *name, const char * const array[], size_t len) { int i; for (i = 0; i < (int)len; i++) { if (array[i] && strcmp(array[i], name) == 0) { return i; } } return -1; } int Jim_IsDict(Jim_Obj *objPtr) { return objPtr->typePtr == &dictObjType; } int Jim_IsList(Jim_Obj *objPtr) { return objPtr->typePtr == &listObjType; } /** * Very simple printf-like formatting, designed for error messages. * * The format may contain up to 5 '%s' or '%#s', corresponding to variable arguments. * The resulting string is created and set as the result. * * Each '%s' should correspond to a regular string parameter. * Each '%#s' should correspond to a (Jim_Obj *) parameter. * Any other printf specifier is not allowed (but %% is allowed for the % character). * * e.g. Jim_SetResultFormatted(interp, "Bad option \"%#s\" in proc \"%#s\"", optionObjPtr, procNamePtr); * * Note: We take advantage of the fact that printf has the same behaviour for both %s and %#s */ void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) { /* Initial space needed */ int len = strlen(format); int extra = 0; int n = 0; const char *params[5]; char *buf; va_list args; int i; va_start(args, format); for (i = 0; i < len && n < 5; i++) { int l; if (strncmp(format + i, "%s", 2) == 0) { params[n] = va_arg(args, char *); l = strlen(params[n]); } else if (strncmp(format + i, "%#s", 3) == 0) { Jim_Obj *objPtr = va_arg(args, Jim_Obj *); params[n] = Jim_GetString(objPtr, &l); } else { if (format[i] == '%') { i++; } continue; } n++; extra += l; } len += extra; buf = Jim_Alloc(len + 1); len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); va_end(args); Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); } /* stubs */ #ifndef jim_ext_package int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) { return JIM_OK; } #endif #ifndef jim_ext_aio FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) { Jim_SetResultString(interp, "aio not enabled", -1); return NULL; } #endif /* * Local Variables: *** * c-basic-offset: 4 *** * tab-width: 4 *** * End: *** */ openocd-0.9.0/jimtcl/jim.h0000644000175000017500000011235512516456444012324 00000000000000/* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. * *--- Inline Header File Documentation --- * [By Duane Ellis, openocd@duaneellis.com, 8/18/8] * * Belief is "Jim" would greatly benifit if Jim Internals where * documented in some way - form whatever, and perhaps - the package: * 'doxygen' is the correct approach to do that. * * Details, see: http://www.stack.nl/~dimitri/doxygen/ * * To that end please follow these guide lines: * * (A) Document the PUBLIC api in the .H file. * * (B) Document JIM Internals, in the .C file. * * (C) Remember JIM is embedded in other packages, to that end do * not assume that your way of documenting is the right way, Jim's * public documentation should be agnostic, such that it is some * what agreeable with the "package" that is embedding JIM inside * of it's own doxygen documentation. * * (D) Use minimal Doxygen tags. * * This will be an "ongoing work in progress" for some time. **/ #ifndef __JIM__H #define __JIM__H #ifdef __cplusplus extern "C" { #endif #include #include #include /* for the FILE typedef definition */ #include /* In order to export the Jim_Free() macro */ #include /* In order to get type va_list */ /* ----------------------------------------------------------------------------- * System configuration * autoconf (configure) will set these * ---------------------------------------------------------------------------*/ #include #ifndef HAVE_NO_AUTOCONF #include #endif /* ----------------------------------------------------------------------------- * Compiler specific fixes. * ---------------------------------------------------------------------------*/ /* Long Long type and related issues */ #ifndef jim_wide # ifdef HAVE_LONG_LONG # define jim_wide long long # ifndef LLONG_MAX # define LLONG_MAX 9223372036854775807LL # endif # ifndef LLONG_MIN # define LLONG_MIN (-LLONG_MAX - 1LL) # endif # define JIM_WIDE_MIN LLONG_MIN # define JIM_WIDE_MAX LLONG_MAX # else # define jim_wide long # define JIM_WIDE_MIN LONG_MIN # define JIM_WIDE_MAX LONG_MAX # endif /* ----------------------------------------------------------------------------- * LIBC specific fixes * ---------------------------------------------------------------------------*/ # ifdef HAVE_LONG_LONG # define JIM_WIDE_MODIFIER "lld" # else # define JIM_WIDE_MODIFIER "ld" # define strtoull strtoul # endif #endif #define UCHAR(c) ((unsigned char)(c)) /* ----------------------------------------------------------------------------- * Exported defines * ---------------------------------------------------------------------------*/ #define JIM_OK 0 #define JIM_ERR 1 #define JIM_RETURN 2 #define JIM_BREAK 3 #define JIM_CONTINUE 4 #define JIM_SIGNAL 5 #define JIM_EXIT 6 /* The following are internal codes and should never been seen/used */ #define JIM_EVAL 7 #define JIM_MAX_CALLFRAME_DEPTH 1000 /* default max nesting depth for procs */ #define JIM_MAX_EVAL_DEPTH 2000 /* default max nesting depth for eval */ /* Some function get an integer argument with flags to change * the behaviour. */ /* Starting from 1 << 20 flags are reserved for private uses of * different calls. This way the same 'flags' argument may be used * to pass both global flags and private flags. */ #define JIM_PRIV_FLAG_SHIFT 20 #define JIM_NONE 0 /* no flags set */ #define JIM_ERRMSG 1 /* set an error message in the interpreter. */ #define JIM_ENUM_ABBREV 2 /* Jim_GetEnum() - Allow unambiguous abbreviation */ #define JIM_UNSHARED 4 /* Jim_GetVariable() - return unshared object */ #define JIM_MUSTEXIST 8 /* Jim_SetDictKeysVector() - fail if non-existent */ /* Flags for Jim_SubstObj() */ #define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */ #define JIM_SUBST_NOCMD 2 /* don't perform command substitutions */ #define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */ #define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */ /* Flags used by API calls getting a 'nocase' argument. */ #define JIM_CASESENS 0 /* case sensitive */ #define JIM_NOCASE 1 /* no case */ /* Filesystem related */ #define JIM_PATH_LEN 1024 /* Unused arguments generate annoying warnings... */ #define JIM_NOTUSED(V) ((void) V) #define JIM_LIBPATH "auto_path" #define JIM_INTERACTIVE "tcl_interactive" /* ----------------------------------------------------------------------------- * Stack * ---------------------------------------------------------------------------*/ typedef struct Jim_Stack { int len; int maxlen; void **vector; } Jim_Stack; /* ----------------------------------------------------------------------------- * Hash table * ---------------------------------------------------------------------------*/ typedef struct Jim_HashEntry { void *key; union { void *val; int intval; } u; struct Jim_HashEntry *next; } Jim_HashEntry; typedef struct Jim_HashTableType { unsigned int (*hashFunction)(const void *key); void *(*keyDup)(void *privdata, const void *key); void *(*valDup)(void *privdata, const void *obj); int (*keyCompare)(void *privdata, const void *key1, const void *key2); void (*keyDestructor)(void *privdata, void *key); void (*valDestructor)(void *privdata, void *obj); } Jim_HashTableType; typedef struct Jim_HashTable { Jim_HashEntry **table; const Jim_HashTableType *type; void *privdata; unsigned int size; unsigned int sizemask; unsigned int used; unsigned int collisions; unsigned int uniq; } Jim_HashTable; typedef struct Jim_HashTableIterator { Jim_HashTable *ht; Jim_HashEntry *entry, *nextEntry; int index; } Jim_HashTableIterator; /* This is the initial size of every hash table */ #define JIM_HT_INITIAL_SIZE 16 /* ------------------------------- Macros ------------------------------------*/ #define Jim_FreeEntryVal(ht, entry) \ if ((ht)->type->valDestructor) \ (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) #define Jim_SetHashVal(ht, entry, _val_) do { \ if ((ht)->type->valDup) \ (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ else \ (entry)->u.val = (_val_); \ } while(0) #define Jim_FreeEntryKey(ht, entry) \ if ((ht)->type->keyDestructor) \ (ht)->type->keyDestructor((ht)->privdata, (entry)->key) #define Jim_SetHashKey(ht, entry, _key_) do { \ if ((ht)->type->keyDup) \ (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \ else \ (entry)->key = (void *)(_key_); \ } while(0) #define Jim_CompareHashKeys(ht, key1, key2) \ (((ht)->type->keyCompare) ? \ (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \ (key1) == (key2)) #define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) #define Jim_GetHashEntryKey(he) ((he)->key) #define Jim_GetHashEntryVal(he) ((he)->u.val) #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) #define Jim_GetHashTableSize(ht) ((ht)->size) #define Jim_GetHashTableUsed(ht) ((ht)->used) /* ----------------------------------------------------------------------------- * Jim_Obj structure * ---------------------------------------------------------------------------*/ /* ----------------------------------------------------------------------------- * Jim object. This is mostly the same as Tcl_Obj itself, * with the addition of the 'prev' and 'next' pointers. * In Jim all the objects are stored into a linked list for GC purposes, * so that it's possible to access every object living in a given interpreter * sequentially. When an object is freed, it's moved into a different * linked list, used as object pool. * * The refcount of a freed object is always -1. * ---------------------------------------------------------------------------*/ typedef struct Jim_Obj { char *bytes; /* string representation buffer. NULL = no string repr. */ const struct Jim_ObjType *typePtr; /* object type. */ int refCount; /* reference count */ int length; /* number of bytes in 'bytes', not including the null term. */ /* Internal representation union */ union { /* integer number type */ jim_wide wideValue; /* generic integer value (e.g. index, return code) */ int intValue; /* double number type */ double doubleValue; /* Generic pointer */ void *ptr; /* Generic two pointers value */ struct { void *ptr1; void *ptr2; } twoPtrValue; /* Variable object */ struct { struct Jim_Var *varPtr; unsigned long callFrameId; /* for caching */ int global; /* If the variable name is globally scoped with :: */ } varValue; /* Command object */ struct { struct Jim_Obj *nsObj; struct Jim_Cmd *cmdPtr; unsigned long procEpoch; /* for caching */ } cmdValue; /* List object */ struct { struct Jim_Obj **ele; /* Elements vector */ int len; /* Length */ int maxLen; /* Allocated 'ele' length */ } listValue; /* String type */ struct { int maxLength; int charLength; /* utf-8 char length. -1 if unknown */ } strValue; /* Reference type */ struct { unsigned long id; struct Jim_Reference *refPtr; } refValue; /* Source type */ struct { struct Jim_Obj *fileNameObj; int lineNumber; } sourceValue; /* Dict substitution type */ struct { struct Jim_Obj *varNameObjPtr; struct Jim_Obj *indexObjPtr; } dictSubstValue; /* Regular expression pattern */ struct { void *compre; /* really an allocated (regex_t *) */ unsigned flags; } regexpValue; struct { int line; int argc; } scriptLineValue; } internalRep; /* This are 8 or 16 bytes more for every object * but this is required for efficient garbage collection * of Jim references. */ struct Jim_Obj *prevObjPtr; /* pointer to the prev object. */ struct Jim_Obj *nextObjPtr; /* pointer to the next object. */ } Jim_Obj; /* Jim_Obj related macros */ #define Jim_IncrRefCount(objPtr) \ ++(objPtr)->refCount #define Jim_DecrRefCount(interp, objPtr) \ if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr) #define Jim_IsShared(objPtr) \ ((objPtr)->refCount > 1) /* This macro is used when we allocate a new object using * Jim_New...Obj(), but for some error we need to destroy it. * Instead to use Jim_IncrRefCount() + Jim_DecrRefCount() we * can just call Jim_FreeNewObj. To call Jim_Free directly * seems too raw, the object handling may change and we want * that Jim_FreeNewObj() can be called only against objects * that are belived to have refcount == 0. */ #define Jim_FreeNewObj Jim_FreeObj /* Free the internal representation of the object. */ #define Jim_FreeIntRep(i,o) \ if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \ (o)->typePtr->freeIntRepProc(i, o) /* Get the internal representation pointer */ #define Jim_GetIntRepPtr(o) (o)->internalRep.ptr /* Set the internal representation pointer */ #define Jim_SetIntRepPtr(o, p) \ (o)->internalRep.ptr = (p) /* The object type structure. * There are three methods. * * - freeIntRepProc is used to free the internal representation of the object. * Can be NULL if there is nothing to free. * * - dupIntRepProc is used to duplicate the internal representation of the object. * If NULL, when an object is duplicated, the internalRep union is * directly copied from an object to another. * Note that it's up to the caller to free the old internal repr of the * object before to call the Dup method. * * - updateStringProc is used to create the string from the internal repr. */ struct Jim_Interp; typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp, struct Jim_Obj *objPtr); typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); typedef struct Jim_ObjType { const char *name; /* The name of the type. */ Jim_FreeInternalRepProc *freeIntRepProc; Jim_DupInternalRepProc *dupIntRepProc; Jim_UpdateStringProc *updateStringProc; int flags; } Jim_ObjType; /* Jim_ObjType flags */ #define JIM_TYPE_NONE 0 /* No flags */ #define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */ /* Starting from 1 << 20 flags are reserved for private uses of * different calls. This way the same 'flags' argument may be used * to pass both global flags and private flags. */ #define JIM_PRIV_FLAG_SHIFT 20 /* ----------------------------------------------------------------------------- * Call frame, vars, commands structures * ---------------------------------------------------------------------------*/ /* Call frame */ typedef struct Jim_CallFrame { unsigned long id; /* Call Frame ID. Used for caching. */ int level; /* Level of this call frame. 0 = global */ struct Jim_HashTable vars; /* Where local vars are stored */ struct Jim_HashTable *staticVars; /* pointer to procedure static vars */ struct Jim_CallFrame *parent; /* The parent callframe */ Jim_Obj *const *argv; /* object vector of the current procedure call. */ int argc; /* number of args of the current procedure call. */ Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */ Jim_Obj *procBodyObjPtr; /* body object of the running procedure */ struct Jim_CallFrame *next; /* Callframes are in a linked list */ Jim_Obj *nsObj; /* Namespace for this proc call frame */ Jim_Obj *fileNameObj; /* file and line of caller of this proc (if available) */ int line; Jim_Stack *localCommands; /* commands to be destroyed when the call frame is destroyed */ int tailcall; /* non-zero if a tailcall is being evaluated at this level */ struct Jim_Obj *tailcallObj; /* Pending tailcall invocation */ struct Jim_Cmd *tailcallCmd; /* Resolved command for pending tailcall invocation */ } Jim_CallFrame; /* The var structure. It just holds the pointer of the referenced * object. If linkFramePtr is not NULL the variable is a link * to a variable of name store on objPtr living on the given callframe * (this happens when the [global] or [upvar] command is used). * The interp in order to always know how to free the Jim_Obj associated * with a given variable because In Jim objects memory managment is * bound to interpreters. */ typedef struct Jim_Var { Jim_Obj *objPtr; struct Jim_CallFrame *linkFramePtr; } Jim_Var; /* The cmd structure. */ typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, Jim_Obj *const *argv); typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); /* A command is implemented in C if isproc is 0, otherwise * it's a Tcl procedure with the arglist and body represented by the * two objects referenced by arglistObjPtr and bodyoObjPtr. */ typedef struct Jim_Cmd { int inUse; /* Reference count */ int isproc; /* Is this a procedure? */ struct Jim_Cmd *prevCmd; /* Previous command defn if cmd created 'local' */ union { struct { /* native (C) command */ Jim_CmdProc *cmdProc; /* The command implementation */ Jim_DelCmdProc *delProc; /* Called when the command is deleted if != NULL */ void *privData; /* command-private data available via Jim_CmdPrivData() */ } native; struct { /* Tcl procedure */ Jim_Obj *argListObjPtr; Jim_Obj *bodyObjPtr; Jim_HashTable *staticVars; /* Static vars hash table. NULL if no statics. */ int argListLen; /* Length of argListObjPtr */ int reqArity; /* Number of required parameters */ int optArity; /* Number of optional parameters */ int argsPos; /* Position of 'args', if specified, or -1 */ int upcall; /* True if proc is currently in upcall */ struct Jim_ProcArg { Jim_Obj *nameObjPtr; /* Name of this arg */ Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */ } *arglist; Jim_Obj *nsObj; /* Namespace for this proc */ } proc; } u; } Jim_Cmd; /* Pseudo Random Number Generator State structure */ typedef struct Jim_PrngState { unsigned char sbox[256]; unsigned int i, j; } Jim_PrngState; /* ----------------------------------------------------------------------------- * Jim interpreter structure. * Fields similar to the real Tcl interpreter structure have the same names. * ---------------------------------------------------------------------------*/ typedef struct Jim_Interp { Jim_Obj *result; /* object returned by the last command called. */ int errorLine; /* Error line where an error occurred. */ Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */ int addStackTrace; /* > 0 If a level should be added to the stack trace */ int maxCallFrameDepth; /* Used for infinite loop detection. */ int maxEvalDepth; /* Used for infinite loop detection. */ int evalDepth; /* Current eval depth */ int returnCode; /* Completion code to return on JIM_RETURN. */ int returnLevel; /* Current level of 'return -level' */ int exitCode; /* Code to return to the OS on JIM_EXIT. */ long id; /* Hold unique id for various purposes */ int signal_level; /* A nesting level of catch -signal */ jim_wide sigmask; /* Bit mask of caught signals, or 0 if none */ int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); /* Set a result for the sigmask */ Jim_CallFrame *framePtr; /* Pointer to the current call frame */ Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */ struct Jim_HashTable commands; /* Commands hash table */ unsigned long procEpoch; /* Incremented every time the result of procedures names lookup caching may no longer be valid. */ unsigned long callFrameEpoch; /* Incremented every time a new callframe is created. This id is used for the 'ID' field contained in the Jim_CallFrame structure. */ int local; /* If 'local' is in effect, newly defined procs keep a reference to the old defn */ Jim_Obj *liveList; /* Linked list of all the live objects. */ Jim_Obj *freeList; /* Linked list of all the unused objects. */ Jim_Obj *currentScriptObj; /* Script currently in execution. */ Jim_Obj *nullScriptObj; /* script representation of an empty string */ Jim_Obj *emptyObj; /* Shared empty string object. */ Jim_Obj *trueObj; /* Shared true int object. */ Jim_Obj *falseObj; /* Shared false int object. */ unsigned long referenceNextId; /* Next id for reference. */ struct Jim_HashTable references; /* References hash table. */ unsigned long lastCollectId; /* reference max Id of the last GC execution. It's set to -1 while the collection is running as sentinel to avoid to recursive calls via the [collect] command inside finalizers. */ time_t lastCollectTime; /* unix time of the last GC execution */ Jim_Obj *stackTrace; /* Stack trace object. */ Jim_Obj *errorProc; /* Name of last procedure which returned an error */ Jim_Obj *unknown; /* Unknown command cache */ int unknown_called; /* The unknown command has been invoked */ int errorFlag; /* Set if an error occurred during execution. */ void *cmdPrivData; /* Used to pass the private data pointer to a command. It is set to what the user specified via Jim_CreateCommand(). */ struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ struct Jim_HashTable assocData; /* per-interp storage for use by packages */ Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ struct Jim_HashTable packages; /* Provided packages hash table */ Jim_Stack *loadHandles; /* handles of loaded modules [load] */ } Jim_Interp; /* Currently provided as macro that performs the increment. * At some point may be a real function doing more work. * The proc epoch is used in order to know when a command lookup * cached can no longer considered valid. */ #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) /* Note: Using trueObj and falseObj here makes some things slower...*/ #define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) #define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) #define Jim_GetResult(i) ((i)->result) #define Jim_CmdPrivData(i) ((i)->cmdPrivData) /* Note that 'o' is expanded only one time inside this macro, * so it's safe to use side effects. */ #define Jim_SetResult(i,o) do { \ Jim_Obj *_resultObjPtr_ = (o); \ Jim_IncrRefCount(_resultObjPtr_); \ Jim_DecrRefCount(i,(i)->result); \ (i)->result = _resultObjPtr_; \ } while(0) /* Use this for filehandles, etc. which need a unique id */ #define Jim_GetId(i) (++(i)->id) /* Reference structure. The interpreter pointer is held within privdata member in HashTable */ #define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference string representation must be fixed length. */ typedef struct Jim_Reference { Jim_Obj *objPtr; Jim_Obj *finalizerCmdNamePtr; char tag[JIM_REFERENCE_TAGLEN+1]; } Jim_Reference; /* ----------------------------------------------------------------------------- * Exported API prototypes. * ---------------------------------------------------------------------------*/ #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) #define Jim_FreeHashTableIterator(iter) Jim_Free(iter) #define JIM_EXPORT /* Memory allocation */ JIM_EXPORT void *Jim_Alloc (int size); JIM_EXPORT void *Jim_Realloc(void *ptr, int size); JIM_EXPORT void Jim_Free (void *ptr); JIM_EXPORT char * Jim_StrDup (const char *s); JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); /* environment */ JIM_EXPORT char **Jim_GetEnviron(void); JIM_EXPORT void Jim_SetEnviron(char **env); JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); /* evaluation */ JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); /* in C code, you can do this and get better error messages */ /* Jim_EvalSource( interp, __FILE__, __LINE__ , "some tcl commands"); */ JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); /* Backwards compatibility */ #define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S)) JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script); JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename); JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename); JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr); JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc, Jim_Obj *const *objv); JIM_EXPORT int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listObj); JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv); #define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov)) JIM_EXPORT int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj); JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags); /* stack */ JIM_EXPORT void Jim_InitStack(Jim_Stack *stack); JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack); JIM_EXPORT int Jim_StackLen(Jim_Stack *stack); JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element); JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack); JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack); JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr)); /* hash table */ JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht, const Jim_HashTableType *type, void *privdata); JIM_EXPORT void Jim_ExpandHashTable (Jim_HashTable *ht, unsigned int size); JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key, void *val); JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht, const void *key, void *val); JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, const void *key); JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, const void *key); JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht); JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator (Jim_HashTable *ht); JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry (Jim_HashTableIterator *iter); /* objects */ JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, int *lenPtr); JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr); JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); /* string object */ JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp, const char *s, int len); JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen); JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp, char *s, int len); JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len); JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr); JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp, Jim_Obj *objPtr, ...); JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr); JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase); JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr); JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv); JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags); JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, Jim_Obj *objPtr, const char *str); JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase); JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase); JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); /* reference object */ JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr); JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr); /* interpreter */ JIM_EXPORT Jim_Interp * Jim_CreateInterp (void); JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i); JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp); JIM_EXPORT const char *Jim_ReturnCode(int code); JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...); /* commands */ JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, const char *cmdName, Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc); JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, const char *cmdName); JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, const char *oldName, const char *newName); JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, Jim_Obj *objPtr, int flags); JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, const char *name, Jim_Obj *objPtr); JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp, const char *name, Jim_Obj *objPtr); JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, const char *name, const char *val); JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame); JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr); JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags); JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags); JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, const char *name, int flags); JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp, const char *name, int flags); JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags); /* call frame */ JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr); /* garbage collection */ JIM_EXPORT int Jim_Collect (Jim_Interp *interp); JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp); /* index object */ JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr); /* list object */ JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp, Jim_Obj *const *elements, int len); JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp, Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec); JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr); JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr); JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt, int listindex, Jim_Obj **objPtrPtr, int seterr); JIM_EXPORT Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx); JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp, Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr); JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc, Jim_Obj *const *objv); JIM_EXPORT Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen); /* dict object */ JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp, Jim_Obj *const *elements, int len); JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags); JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags); JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags); JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); /* return code object */ JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr); /* expression object */ JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr); /* integer object */ JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, jim_wide *widePtr); JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr); #define Jim_NewWideObj Jim_NewIntObj JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, jim_wide wideValue); /* double object */ JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr); JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double doubleValue); JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); /* commands utilities */ JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg); JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, const char * const *tablePtr, int *indexPtr, const char *name, int flags); JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len, char *stateCharPtr); /** * Find a matching name in the array of the given length. * * NULL entries are ignored. * * Returns the matching index if found, or -1 if not. */ JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); /* package utilities */ typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc *delProc, void *data); JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); /* Packages C API */ /* jim-package.c */ JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, const char *name, const char *ver, int flags); JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, const char *name, int flags); /* error messages */ JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); /* interactive mode */ JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); JIM_EXPORT void Jim_HistoryLoad(const char *filename); JIM_EXPORT void Jim_HistorySave(const char *filename); JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); JIM_EXPORT void Jim_HistoryAdd(const char *line); JIM_EXPORT void Jim_HistoryShow(void); /* Misc */ JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); JIM_EXPORT int Jim_IsBigEndian(void); /** * Returns 1 if a signal has been received while * in a catch -signal {} clause. */ #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) /* jim-load.c */ JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); /* jim-aio.c */ JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); /* type inspection - avoid where possible */ JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); #ifdef __cplusplus } #endif #endif /* __JIM__H */ /* * Local Variables: *** * c-basic-offset: 4 *** * tab-width: 4 *** * End: *** */ openocd-0.9.0/jimtcl/README.oo0000644000175000017500000002074712315602574012665 00000000000000OO Package for Jim Tcl ====================== Author: Steve Bennett Date: 1 Nov 2010 09:18:40 OVERVIEW -------- The pure-Tcl oo package leverages Jim's unique strengths to provide support for Object Oriented programming. The oo package can be statically linked with Jim or installed as a separate Tcl package and loaded with: package require oo DECLARING CLASSES ----------------- A class is declared with the 'class' proc as follows. class myclass ?baseclasses? classvars This declares a class named 'myclass' with the given dictionary, 'classvars', providing the initial state of all new objects. It is important to list all class variables in 'classvars', even if initialised only to the empty string, since the class makes these variables available in methods and via [myclass vars]. A list of zero or more base classes may also be specified from which methods and class variables are imported. See INHERITANCE below for more details. Declaring a class creates a procedure with the class name along with some related procedures. For example: . class Account {balance 0} Account . info procs Account* {Account get} {Account methods} {Account eval} Account {Account new} {Account destroy} {Account vars} {Account classname} {Account classvars} {Account method} Notice that apart from the main 'Account' procedure, all the remaining procedures (methods) are prefixed with 'Account' and a space. PREDEFINED CLASS METHODS ------------------------ Decaring a class pre-defines a number of "class" methods. i.e. those which don't require an object and simply return or manipulate properties of the class. These are: new ?instancevars?:: Creates and returns new object, optionally overriding the default class variable values. Note that the class name is an alias for 'classname new {}' and can be used as a shorthand for creating new objects with default values. method name arglist body:: Creates or redefines a method for the class with the given name, argument list and body. methods:: Returns a list of the methods supported by this class, including both class methods and instance methods. Also includes base class methods. vars:: Returns a list of the class variables for this class (names only). Also includes base class variables. classvars:: Returns a dictionary the class variables, including initial values, for this class. Also includes base class variables. classname:: Returns the classname. This can be useful as [$self classname]. Class methods may be invoked either via the class name or via an object of the class. For example: . class Account {balance 0} Account . Account methods classname classvars destroy eval get method methods new vars . set a [Account] .00000000000000000001> . $a methods classname classvars destroy eval get method methods new vars PREDEFINED OBJECT METHODS ------------------------- Decaring a class pre-defines a number of "object" methods. i.e. those which operate on a specific object. destroy:: Destroys the object. This method may be overridden, but note that it should delete the object with {rename $self ""}. This method will also be called if the object is reaped during garbage collection. get varname:: Returns the value of the given instance variable. eval ?locals? body:: Makes any given local variables available to the body, along with the instance variables, and evaluate the body in that context. This can be used for one-off evaluation to avoid declaring a method. CREATING OBJECTS ---------------- An object is created with the 'new' method, or simply by using the classname shortcut. If the 'new' method is used, the variables for the newly created object (instance variables) may be initialised. Otherwise they are set to the default values specified when the class was declared. For example: . class Account {balance 0} Account . set a [Account] .00000000000000000001> . set b [Account new {balance 1000}] .00000000000000000002> . $a get balance 0 . $b get balance 1000 DECLARING METHODS ----------------- In addition to the predefined methods, new methods may be decared, or existing methods redefined with the class method, method. Declaring a method is very similar to defining a proc, and the arglist has identical syntax. For example: . Account method show {{channel stdout}} { $channel puts "Balance of account is $balance" } . $b show Balance of account is 1000 All instance variables are available within the method and any changes to these variables are maintained by the object. In addition, the $self variables is defined and refers to the current object. This may be used to invoke further methods on the object. For example: . Account method show {} { puts "Balance of account is [$self get balance]" } . $b show Balance of account is 1000 Notes: * It is a bad idea to unset an instance variable. * In general, you should avoid redefining any of the pre-defined methods, except for 'destroy'. * When accessing the caller's scope with upvar or uplevel, note that there are two frame levels between the caller and the method. Thus it is necessary to use 'upvar 2' or 'uplevel 2' INHERITANCE ----------- For each base class given in a new class declaration, the methods and variables of those classes are imported into the new class being defined. Base classes are imported in left to right order, so that if a method is defined in more than one base class, the later definition is selected. This applies similarly to class variables. Within a method, 'super' may be used to explicitly invoke a base class method on the object. This applies only to the *last* base class given. For example: # Assumes the existence of classes Account and Client . Account method debit {amount} { incr balance -$amount } . class CreditAccount {Client Account} {type visa} CreditAccount . CreditAccount method debit {amount} { puts "Debit $type card" super debit $amount } . set a [CreditAccount] .00000000000000000001> . $a debit 20 Debit visa card . $a balance -20 In the CreditAccount debit method, the call to 'super debit' invokes the method 'Account debit' since Account is the last base class listed. OBJECT LIFETIME/GARBAGE COLLECTION ---------------------------------- Objects are implemented as lambdas. That is, they are procedures with state and are named as references. This means that when an object is no longer reachable by any name and garbage collection runs, the object will be discarded and the destructor will be invoked. Note that the garbage collector can be invoked manually with 'collect' if required. . class Account {} Account . Account method destroy {} { puts dying...; rename $self "" } Account destroy . proc a {} { set b [Account]; return "" } a . a . collect dying... 1 CLASS METHODS/CLASS STATIC VARIABLES ------------------------------------ All methods defined with 'method' operate on objects (instances). If a class method is required, it is possible to simply declare one with 'proc'. The method dispatcher will automatically be able to dispatch to this method. Using this approach, it is also possible to add class static variables by defining static variables to the proc. Although strictly these variables are accessible only to that proc, not the class as a whole. For example: . class Account {} Account . proc {Account nextid} {} {{id 0}} { incr id } Account nextid . Account nextid 1 . Account nextid 2 . set a [Account] .00000000000000000001> . $a nextid 3 . $a eval { $self nextid } 4 HOW METHOD DISPATCH WORKS ------------------------- All class and object methods are name "classname methodname". The class method dispatcher is named "classname". When invoked with a methodname, it simply invokes the method "classname methodname". The method dispatch is via a two step process. Firstly the object procedure is invoked with the method name. This procedure then invokes "classname method" which sets up the appropriate access to the object variables, and then invokes the method body. EXAMPLES -------- tree.tcl ~~~~~~~~ The 'tree' package is implemented using the 'oo' package. See the source code in tree.tcl and a usage example in tests/tree.test Of particular note is how callbacks and recursive invocation is used in the 'walk' method. examples/ootest.tcl ~~~~~~~~~~~~~~~~~~~ A comprehensive OO example is provided in examples/ootest.tcl. It can be run simply as: ./jimsh examples/ootest.tcl openocd-0.9.0/jimtcl/regtest.tcl0000644000175000017500000001214012516456444013544 00000000000000# These regression tests all provoked crashes at some point. # Thus they are kept separate from the regular test suite in tests/ # REGTEST 1 # 27Jan2005 - SIGSEGV for bug on Jim_DuplicateObj(). for {set i 0} {$i < 100} {incr i} { set a "x" lappend a n } puts "TEST 1 PASSED" # REGTEST 2 # 29Jan2005 - SEGFAULT parsing script composed of just one comment. eval {#foobar} puts "TEST 2 PASSED" # REGTEST 3 # 29Jan2005 - "Error in Expression" with correct expression set x 5 expr {$x-5} puts "TEST 3 PASSED" # REGTEST 4 # 29Jan2005 - SIGSEGV when run this code, due to expr's bug. proc fibonacci {x} { if {$x <= 1} { expr 1 } else { expr {[fibonacci [expr {$x-1}]] + [fibonacci [expr {$x-2}]]} } } fibonacci 6 puts "TEST 4 PASSED" # REGTEST 5 # 06Mar2005 - This looped forever... for {set i 0} {$i < 10} {incr i} {continue} puts "TEST 5 PASSED" # REGTEST 6 # 07Mar2005 - Unset create variable + dict is using dict syntax sugar at # currently non-existing variable catch {unset thisvardoesnotexists(thiskeytoo)} if {[catch {set thisvardoesnotexists}] == 0} { puts "TEST 6 FAILED - unset created dict for non-existing variable" break } puts "TEST 6 PASSED" # REGTEST 7 # 04Nov2008 - variable parsing does not eat last brace set a 1 list ${a} puts "TEST 7 PASSED" # REGTEST 8 # 04Nov2008 - string toupper/tolower do not convert to string rep string tolower [list a] string toupper [list a] puts "TEST 8 PASSED" # REGTEST 9 # 04Nov2008 - crash on exit when replacing Tcl proc with C command. # Requires the clock extension to be built as a loadable module. proc clock {args} {} catch {package require clock} # Note, crash on exit, so don't say we passed! # REGTEST 10 # 05Nov2008 - incorrect lazy expression evaluation with unary not expr {1 || !0} puts "TEST 10 PASSED" # REGTEST 11 # 14 Feb 2010 - access static variable in deleted proc proc a {} {{x 1}} { rename a ""; incr x } a puts "TEST 11 PASSED" # REGTEST 12 # 13 Sep 2010 - reference with invalid tag set a b[ref value "tag name"] getref [string range $a 1 end] puts "TEST 12 PASSED" # REGTEST 13 # 14 Sep 2010 - parse list with trailing backslash set x "switch -0 \$on \\" lindex $x 1 puts "TEST 13 PASSED" # REGTEST 14 # 14 Sep 2010 - command expands to nothing eval "{*}{}" puts "TEST 14 PASSED" # REGTEST 15 # 24 Feb 2010 - bad reference counting of the stack trace in 'error' proc a {msg stack} { tailcall error $msg $stack } catch {fail} msg opts catch {a $msg $opts(-errorinfo)} # REGTEST 16 # 24 Feb 2010 - rename the current proc # Leaves unfreed objects on the stack proc a {} { rename a newa} a # REGTEST 17 # 26 Nov 2010 - crashes on invalid dict sugar catch {eval {$x(}} puts "TEST 17 PASSED" # REGTEST 18 # 12 Apr 2011 - crashes on unset for loop var catch { for {set i 0} {$i < 5} {incr i} {unset i} } puts "TEST 18 PASSED" # REGTEST 19 # 25 May 2011 - crashes with double colon catch { expr {5 ne ::} } puts "TEST 19 PASSED" # REGTEST 20 # 26 May 2011 - infinite recursion proc a {} { global ::blah; set ::blah test } a puts "TEST 20 PASSED" # REGTEST 21 # 26 May 2011 - infinite loop with null byte in subst subst "abc\0def" puts "TEST 21 PASSED" # REGTEST 22 # 21 June 2011 - crashes on lappend to to value with script rep set x rand eval $x lappend x b puts "TEST 22 PASSED" # REGTEST 23 # 27 July 2011 - unfreed objects on exit catch { set x abc subst $x regexp $x $x } # Actually, the test passes if no objects leaked on exit puts "TEST 23 PASSED" # REGTEST 24 # 13 Nov 2011 - invalid cached global var proc a {} { foreach i {1 2} { incr z [set ::t] unset ::t } } set t 6 catch a puts "TEST 24 PASSED" # REGTEST 25 # 14 Nov 2011 - link global var to proc var proc a {} { set x 3 upvar 0 x ::globx } set globx 0 catch { a } incr globx puts "TEST 25 PASSED" # REGTEST 26 # 2 Dec 2011 - infinite eval recursion catch { set x 0 set y {incr x; eval $y} eval $y } msg puts "TEST 26 PASSED" # REGTEST 27 # 2 Dec 2011 - infinite alias recursion catch { proc p {} {} alias p p p } msg puts "TEST 27 PASSED" # REGTEST 28 # 16 Dec 2011 - ref count problem with finalizers catch { ref x x [list dummy] collect } puts "TEST 28 PASSED" # REGTEST 29 # Reference counting problem at exit set x [lindex {} 0] info source $x eval $x puts "TEST 29 PASSED" # REGTEST 30 # non-UTF8 string tolower string tolower "/mod/video/h\303\203\302\244xan_ witchcraft through the ages_20131101_0110.t" puts "TEST 30 PASSED" # REGTEST 31 # infinite lsort -unique with error catch {lsort -unique -real {foo 42.0}} puts "TEST 31 PASSED" # REGTEST 32 # return -code eval should only used by tailcall, but this incorrect usage # should not crash the interpreter proc a {} { tailcall b } proc b {} { return -code eval c } proc c {} {} catch -eval a puts "TEST 32 PASSED" # REGTEST 33 # unset array variable which doesn't exist array unset blahblah abc puts "TEST 33 PASSED" # REGTEST 34 # onexception and writable conflict set f [open [info nameofexecutable]] $f onexception {incr x} $f writable {incr y} $f close puts "TEST 34 PASSED" # TAKE THE FOLLOWING puts AS LAST LINE puts "--- ALL TESTS PASSED ---" openocd-0.9.0/jimtcl/tests/0000755000175000017500000000000012526202231012567 500000000000000openocd-0.9.0/jimtcl/tests/stacktrace.test0000644000175000017500000001570312516456445015563 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim; needs cmd package package require errors # Make this a proc so that the line numbers don't have to change proc main {} { set id1 0 foreach type {badcmd badvar badproc error interpbadvar interpbadcmd package source badpackage returncode} { set id2 0 incr id1 foreach method {call uplevel eval evalstr} { incr id2 set exp "" if {[info exists ::expected(err-$id1.$id2)]} { set exp $::expected(err-$id1.$id2) } test err-$id1.$id2 "Stacktrace on error type $type, method $method" { set rc [catch {error_caller $type $method} msg] #puts "\n-----------------\n$type, $method\n[errorInfo $msg]\n\n" if {$::SHOW_EXPECTED} { puts stderr "\terr-$id1.$id2 {[list $rc $msg [info stacktrace]]}" } list $rc $msg [info stacktrace] } $exp } } proc unknown {args} { error "from unknown" } test err-10.1 "Stacktrace on error from unknown (badcmd, call)" { set rc [catch {error_caller badcmd call} msg] #puts stderr "err-10.1\n[errorInfo $msg]\n" #puts stderr "\terr-10.1 {[list $rc $msg [info stacktrace]]}" list $rc $msg [info stacktrace] } {1 {from unknown} {{} stacktrace.test 26 {} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 30}} rename unknown "" set a {one} set b [list 1 \ 2 \ 3] set c {two} set d "list 1 2 3" set e {three} set f "list 1 \ 2 \ 3" set g {four} test source-1.1 "Basic line numbers" { info source $a } {stacktrace.test 39} test source-1.2 "Line numbers after command with escaped newlines" { info source $c } {stacktrace.test 43} test source-1.3 "Line numbers after string with newlines" { info source $e } {stacktrace.test 47} test source-1.4 "Line numbers after string with escaped newlines" { info source $g } {stacktrace.test 51} } set expected { err-1.1 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-1.2 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-1.3 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-1.4 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-2.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-2.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-2.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-2.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-3.1 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-3.2 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-3.3 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-3.4 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-4.1 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-4.2 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-4.3 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-4.4 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-5.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-5.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-5.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-5.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-6.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-6.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-6.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-6.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-7.1 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-7.2 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-7.3 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-7.4 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-8.1 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-8.2 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-8.3 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-8.4 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-9.1 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 44 error_caller stacktrace.test 17}} err-9.2 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-9.3 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-9.4 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 53 error_caller stacktrace.test 17}} err-10.1 {1 failure {{} errors.tcl 44 error_caller stacktrace.test 17}} err-10.2 {1 failure {{} errors.tcl 47 error_caller stacktrace.test 17}} err-10.3 {1 failure {{} errors.tcl 50 error_caller stacktrace.test 17}} err-10.4 {1 failure {{} errors.tcl 53 error_caller stacktrace.test 17}} } # Set this to output expected results to stderr # in a form which can be pasted into 'expected' below set SHOW_EXPECTED 0 main testreport openocd-0.9.0/jimtcl/tests/testing.tcl0000644000175000017500000000025412516456445014712 00000000000000# Find and load the Jim tcltest wrapper if {[catch {info version}]} { # Tcl source [file dirname [info script]]/../tcltest.tcl } else { # Jim package require tcltest } openocd-0.9.0/jimtcl/tests/parse.test0000644000175000017500000001326012516456445014545 00000000000000source [file dirname [info script]]/testing.tcl test parse-1.1 "Quoted closing bracket" { set x [string length "]"] } {1} test parse-1.2 "Quoted opening bracket" { set x [string length "\["] } {1} test parse-1.3 "Quoted open brace" { set x [string length "\{"] } {1} test parse-1.4 "Quoted open brace via var" { set lb \{ set x [string length "$lb"] } {1} test parse-1.5 "Braced bracket" { set x [string length {]}] } {1} test parse-1.6 "Dict sugar" -body { unset -nocomplain a array set a {a 1 b 2 c 3} set x $a( } -returnCodes error -match glob -result "*" test parse-1.8 "Dict sugar" { unset -nocomplain a array set a {a 1 b 2 c 3} set x $a([set y b]) } 2 test parse-1.9 "Backslash newline" { set x 123;\ set y 456 list $x $y } {123 456} test parse-1.10 "Backslash newline in quotes" { set x "abc\ def" } "abc def" test parse-1.11 "Backslash newline in quotes after var" { set y 1 set x "abc$y\ def" } "abc1 def" test parse-1.12 "Backslash newline in quotes after var" { set y 1 set x "abc$y\ def" } "abc1 def" test parse-1.13 "Newline in quotes" { set y 1 set x "abc def" } "abc\ndef" test parse-1.14 "Newline in quotes after var" { set y 1 set x "abc$y def" } "abc1\ndef" test parse-1.15 "Space in quotes" { set y 1 set x "abc def" } "abc def" test parse-1.16 "Space in quotes after var" { set y 1 set x "abc${y} def" } "abc1 def" test parse-1.17 "Command and var in quotes" { set y 1 set x "[set z 2][set y]" } 21 test parse-1.18 "Command and var in bare context" { set y 1 set x [set z 2][set y] } 21 test parse-1.19 "Lone dollar sign in quotes" { set y 1 set x "6$[set y]" } 6\$1 test parse-1.20 "Command and var in bare context" { set y 1 set x 6$[set y] } 6\$1 test parse-1.21 "Comment" { set y 1 # A comment one a line set x [set y] ;# comment after semicolon } 1 test parse-1.22 "# char" { set y 1 append y # set x "[set y]#" } {1##} test parse-1.23 "newline in command" { set y 1 set z 2 set x [incr y incr z] list $x $y $z } {3 2 3} test parse-1.24 "semicolon in command" { set x [list a; list b c; list d e f] } {d e f} # Note that Tcl complains about the missing brace here # while Jim ignores it test parse-1.25 "missing brace in var" jim { unset -nocomplain a set a 3 set brace \{ set x [subst \$${brace}a] } 3 test parse-1.26 "newline in braced var" { set "a\nb" var1 set x ${a b} } var1 test parse-1.27 "backslash escape in dict sugar" { unset -nocomplain a set a(b\x55d) 5 set x $a(b\x55d) } 5 test parse-1.28 "nested dict sugar" { unset -nocomplain a b set a(V) 5 set b(5) five set x $b($a(V)) } five set dq {"} set script "set x ${dq}hello" test parse-1.29 "missing quote" -constraints jim -body { eval $script } -returnCodes error -match glob -result {missing quote} test parse-1.30 "missing quote" { info complete $script } 0 test parse-1.31 "backslash newline in bare context" { list abc\ 123 } {abc 123} test parse-1.32 "comment as last line of script" { set script {set x 3; # this is a comment} eval $script } 3 test parse-1.33 "upper case hex escapes" { list \x4A \x4F \x3C } {J O <} test parse-1.34 "octal escapes" { list \112 \117 \074 } {J O <} test parse-1.35 "invalid hex escape" { list \xZZ } xZZ test parse-1.36 "unicode escape" jim { list \u00b5 } \xc2\xb5 test parse-1.37 "invalid unicode escape after unicode" jim { list \ub5x } \xc2\xb5x test parse-1.38 "invalid unicode escape" { list \ux } ux test parse-1.39 "octal escape followed by invalid" { list \76x } >x test parse-1.40 "list containing quoted trailing backslash" jim { set x "abc \"def\\" lindex $x 1 } def\\ test parse-1.41 "list containing quoted newline" { set x {abc "def ghi"} lindex $x 1 } def\nghi test parse-1.42 "list containing missing quote" jim { set x {abc "def} lindex $x 1 } def test parse-1.43 "list containing trailing backslash" { set x "abc def\\" lindex $x 1 } def\\ test parse-1.44 "list creation" { list "a{ }d" } {{a{ }d}} test parse-1.45 "spaces before expr function args" { expr {round (3.2)} } 3 test parse-1.46 "expr function missing paren" { catch {expr {round 3.2}} } 1 test parse-1.47 "backslash newline in quotes" { # spaces set x "abc\ def" } "abc def" test parse-1.48 "backslash newline in quotes" { # tabs set x "abc\ def" } "abc def" test parse-1.49 "backslash newline in quotes" { # tabs plus newline set x "abc\ def" } "abc \ndef" test parse-1.50 "backslash newline in quotes" { # tabs plus newline set x "abc\ def" } "abc def" test parse-1.51 "special chars in dict sugar" { unset -nocomplain a set a(x$) 5 array names a } {{x$}} test parse-1.52 "special chars in dict sugar" { set x $a(x$) } 5 test parse-1.53 "special chars in dict sugar" { unset -nocomplain a set a(x\[) 5 array names a } {{x[}} test parse-1.54 "special chars in dict sugar" { set x $a(x\[) } 5 test parse-1.55 "special chars in dict sugar" { unset -nocomplain a set a(x\() 5 array names a } {x(} test parse-1.56 "special chars in dict sugar" { set x $a(x\() } 5 test parse-1.57 "special chars in dict sugar" { unset -nocomplain a set a(x() 5 array names a } {x(} test parse-1.58 "special chars in dict sugar" { set x $a(x() } 5 test parse-1.59 "special chars in dict sugar" { unset -nocomplain a set a(x") 5 lindex [array names a] 0 } {x"} test parse-1.60 "special chars in dict sugar" { set x $a(x") } 5 test parse-1.61 "quote in command" { set x [list \\" x] lindex $x end } x test parse-1.62 "quoted orphan dollar sign" { set x "x$" } {x$} test parse-1.63 "unquoted dollar sign" { set x x$ } {x$} test parse-1.64 "backslash in comment" { set x 0 # comment \ incr x incr x } 1 test parse-1.65 "double backslash in comment" { set x 0 # comment \\ incr x incr x } 2 testreport openocd-0.9.0/jimtcl/tests/Makefile0000644000175000017500000000027512516456444014173 00000000000000jimsh ?= ../jimsh test: @rc=0; for i in *.test; do LD_LIBRARY_PATH=..:$(LD_LIBRARY_PATH) $(jimsh) $$i || rc=$?; done; exit $$rc clean: rm -f gorp.file2 gorp.file sleepx test1 exec.tmp1 openocd-0.9.0/jimtcl/tests/expr-base.test0000644000175000017500000000110312315602575015304 00000000000000source [file dirname [info script]]/testing.tcl # Test number detection set good_testcases { 0 0 1 1 8 8 00 0 07 7 08 8 0x5 5 0x0 0 0x00 0 -0x5 -5 0b111 7 -0b111 -7 -0B101 -5 0o7 7 } set i 0 foreach {str exp} $good_testcases { test expr-base-1.[incr i] "expr conversion" [list expr [list $str]] $exp } set bad_testcases { {0x + 1} x 0xx5 0x-5 {0x 5} {0o8 + 1} } set i 0 foreach str $bad_testcases { test expr-base-2.[incr i] "expr conversion failure" -returnCodes error -body [list expr $str] -match glob -result "*" } testreport openocd-0.9.0/jimtcl/tests/lrange.test0000644000175000017500000000550312315602575014676 00000000000000# Commands covered: lrange # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl test lrange-1.1 {range of list elements} { lrange {a b c d} 1 2 } {b c} test lrange-1.2 {range of list elements} { lrange {a {bcd e {f g {}}} l14 l15 d} 1 1 } {{bcd e {f g {}}}} test lrange-1.3 {range of list elements} { lrange {a {bcd e {f g {}}} l14 l15 d} 3 end } {l15 d} test lrange-1.4 {range of list elements} { lrange {a {bcd e {f g {}}} l14 l15 d} 4 10000 } {d} test lrange-1.5 {range of list elements} { lrange {a {bcd e {f g {}}} l14 l15 d} 4 3 } {} test lrange-1.6 {range of list elements} { lrange {a {bcd e {f g {}}} l14 l15 d} 10 11 } {} test lrange-1.7 {range of list elements} { lrange {a b c d e} -1 2 } {a b c} test lrange-1.8 {range of list elements} { lrange {a b c d e} -2 -1 } {} test lrange-1.9 {range of list elements} { lrange {a b c d e} -2 end } {a b c d e} test lrange-1.10 {range of list elements} { lrange "a b\{c d" 1 2 } "b\\{c d" test lrange-1.11 {range of list elements} { lrange "a b c d" end end } d test lrange-1.12 {range of list elements} { lrange "a b c d" end 100000 } d test lrange-1.13 {range of list elements} { lrange "a b c d" end 3 } d test lrange-1.14 {range of list elements} { lrange "a b c d" end 2 } {} test lrange-1.15 {range of list elements} { concat \"[lrange {a b \{\ } 0 2]" } {"a b \{\ "} test lrange-1.16 {list element quoting} { lrange {[append a .b]} 0 end } {{[append} a .b\]} test lrange-2.1 {error conditions} { list [catch {lrange a b} msg] $msg } {1 {wrong # args: should be "lrange list first last"}} test lrange-2.2 {error conditions} { list [catch {lrange a b 6 7} msg] $msg } {1 {wrong # args: should be "lrange list first last"}} test lrange-2.3 {error conditions} { list [catch {lrange a b 6} msg] $msg } {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}} test lrange-2.4 {error conditions} { list [catch {lrange a 0 enigma} msg] $msg } {1 {bad index "enigma": must be integer?[+-]integer? or end?[+-]integer?}} test lrange-2.5 {error conditions} tcl { list [catch {lrange "a \{b c" 3 4} msg] $msg } {1 {unmatched open brace in list}} test lrange-2.6 {error conditions} tcl { list [catch {lrange "a b c \{ d e" 1 4} msg] $msg } {1 {unmatched open brace in list}} # cleanup ::tcltest::cleanupTests return openocd-0.9.0/jimtcl/tests/utftcl.test0000644000175000017500000001647012315602575014734 00000000000000# This file contains a collection of tests for tclUtf.c # Sourcing this file into Tcl runs the tests and generates output for # errors. No output means no errors were found. # # Copyright (c) 1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: utf.test,v 1.14 2007/05/02 01:37:28 kennykb Exp $ source [file dirname [info script]]/testing.tcl needs constraint utf8 catch {unset x} test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} { set x \x01 } [bytestring "\x01"] test utf-1.2 {Tcl_UniCharToUtf: 2 byte sequences} { set x "\u80" } [bytestring "\xc2\x80"] test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} { set x "\ue0" } [bytestring "\xc3\xa0"] test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} { set x "\u4e4e" } [bytestring "\xe4\xb9\x8e"] test utf-1.5 {Tcl_UniCharToUtf: negative Tcl_UniChar} { string length [format %c -1] } 1 test utf-2.1 {Tcl_UtfToUniChar: low ascii} { string length "abc" } {3} test utf-2.2 {Tcl_UtfToUniChar: naked trail bytes} { string length [bytestring "\x82\x83\x84"] } {3} test utf-2.3 {Tcl_UtfToUniChar: lead (2-byte) followed by non-trail} { string length [bytestring "\xC2"] } {1} test utf-2.4 {Tcl_UtfToUniChar: lead (2-byte) followed by trail} { string length [bytestring "\xC2\xa2"] } {1} test utf-2.5 {Tcl_UtfToUniChar: lead (3-byte) followed by non-trail} { string length [bytestring "\xE2"] } {1} test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} { string length [bytestring "\xE2\xA2"] } {2} test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} { string length [bytestring "\xE4\xb9\x8e"] } {1} # Note that Tcl may or may not support utf-8 sequences >= 4 bytes test utf-2.9 {Tcl_UtfToUniChar: 4-byte UTF sequence} { string length [bytestring "\xF4\xA2\xA2\xA2"] } {1} test utf-3.1 {Tcl_UtfCharComplete} { } {} proc testnumutfchars {a {n ""}} { string length $a } test utf-4.1 {Tcl_NumUtfChars: zero length} { testnumutfchars "" } {0} test utf-4.2 {Tcl_NumUtfChars: length 1} { testnumutfchars [bytestring "\xC2\xA2"] } {1} test utf-4.3 {Tcl_NumUtfChars: long string} { testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] } {7} test utf-4.4 {Tcl_NumUtfChars: #u0000} { testnumutfchars [bytestring "\xC0\x80"] } {1} test utf-4.5 {Tcl_NumUtfChars: zero length, calc len} { testnumutfchars "" 1 } {0} test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} { testnumutfchars [bytestring "\xC2\xA2"] 1 } {1} test utf-4.7 {Tcl_NumUtfChars: long string, calc len} { testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 1 } {7} test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} { testnumutfchars [bytestring "\xC0\x80"] 1 } {1} test utf-5.1 {Tcl_UtfFindFirsts} { } {} test utf-6.1 {Tcl_UtfNext} { } {} test utf-7.1 {Tcl_UtfPrev} { } {} test utf-8.1 {Tcl_UniCharAtIndex: index = 0} { string index abcd 0 } {a} test utf-8.2 {Tcl_UniCharAtIndex: index = 0} { string index \u4e4e\u25a 0 } "\u4e4e" test utf-8.3 {Tcl_UniCharAtIndex: index > 0} { string index abcd 2 } {c} test utf-8.4 {Tcl_UniCharAtIndex: index > 0} { string index \u4e4e\u25a\uff\u543 2 } "\uff" test utf-9.1 {Tcl_UtfAtIndex: index = 0} { string range abcd 0 2 } {abc} test utf-9.2 {Tcl_UtfAtIndex: index > 0} { string range \u4e4e\u25a\xff\u543klmnop 1 5 } "\u25a\xff\u543kl" test utf-10.1 {Tcl_UtfBackslash: dst == NULL} { set x \n } { } test utf-10.2 {Tcl_UtfBackslash: \u subst} { set x \ua2 } [bytestring "\xc2\xa2"] test utf-10.3 {Tcl_UtfBackslash: longer \u subst} { set x \u4e21 } [bytestring "\xe4\xb8\xa1"] test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} { set x \u4e2k } "[bytestring \xd3\xa2]k" test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} { set x \u4e216 } "[bytestring \xe4\xb8\xa1]6" proc bsCheck {char num} { global errNum test utf-10.$errNum {backslash substitution} { scan $char %c value set value } $num incr errNum } set errNum 6 bsCheck \b 8 bsCheck \e 101 bsCheck \f 12 bsCheck \n 10 bsCheck \r 13 bsCheck \t 9 bsCheck \v 11 bsCheck \{ 123 bsCheck \} 125 bsCheck \[ 91 bsCheck \] 93 bsCheck \$ 36 bsCheck \ 32 bsCheck \; 59 bsCheck \\ 92 bsCheck \Ca 67 bsCheck \Ma 77 bsCheck \CMa 67 # prior to 8.3, this returned 8, as \8 as accepted as an # octal value - but it isn't! [Bug: 3975] bsCheck \8a 56 bsCheck \14 12 bsCheck \141 97 bsCheck b\0 98 bsCheck \x 120 bsCheck \ua 10 bsCheck \uA 10 bsCheck \u41 65 bsCheck \u 117 bsCheck \uk 117 bsCheck \u41 65 bsCheck \ua 10 bsCheck \uA 10 bsCheck \340 224 bsCheck \ua1 161 bsCheck \u4e21 20001 test utf-11.1 {Tcl_UtfToUpper} { string toupper {} } {} test utf-11.2 {Tcl_UtfToUpper} { string toupper abc } ABC test utf-11.3 {Tcl_UtfToUpper} { string toupper \u00e3ab } \u00c3AB test utf-11.4 {Tcl_UtfToUpper} { string toupper \u01e3ab } \u01e2AB test utf-12.1 {Tcl_UtfToLower} { string tolower {} } {} test utf-12.2 {Tcl_UtfToLower} { string tolower ABC } abc test utf-12.3 {Tcl_UtfToLower} { string tolower \u00c3AB } \u00e3ab test utf-12.4 {Tcl_UtfToLower} { string tolower \u01e2AB } \u01e3ab test utf-14.1 {Tcl_UtfNcasecmp} { string compare -nocase a b } -1 test utf-14.2 {Tcl_UtfNcasecmp} { string compare -nocase b a } 1 test utf-14.3 {Tcl_UtfNcasecmp} { string compare -nocase B a } 1 test utf-14.4 {Tcl_UtfNcasecmp} { string compare -nocase aBcB abca } 1 test utf-15.1 {Tcl_UniCharToUpper, negative delta} { string toupper aA } AA test utf-15.2 {Tcl_UniCharToUpper, positive delta} { string toupper \u0178\u00ff } \u0178\u0178 test utf-15.3 {Tcl_UniCharToUpper, no delta} { string toupper ! } ! test utf-16.1 {Tcl_UniCharToLower, negative delta} { string tolower aA } aa test utf-16.2 {Tcl_UniCharToLower, positive delta} { string tolower \u0178\u00ff } \u00ff\u00ff test utf-17.1 {Tcl_UniCharToLower, no delta} { string tolower ! } ! #test utf-21.1 {TclUniCharIsAlnum} { # # this returns 1 with Unicode 3 compliance # string is alnum \u1040\u021f #} {1} #test utf-21.2 {unicode alnum char in regc_locale.c} { # # this returns 1 with Unicode 3 compliance # list [regexp {^[[:alnum:]]+$} \u1040\u021f] [regexp {^\w+$} \u1040\u021f] #} {1 1} #test utf-22.1 {TclUniCharIsWordChar} { # string wordend "xyz123_bar fg" 0 #} 10 #test utf-22.2 {TclUniCharIsWordChar} { # string wordend "x\u5080z123_bar\u203c fg" 0 #} 10 #test utf-23.1 {TclUniCharIsAlpha} { # # this returns 1 with Unicode 3 compliance # string is alpha \u021f #} {1} #test utf-23.2 {unicode alpha char in regc_locale.c} { # # this returns 1 with Unicode 3 compliance # regexp {^[[:alpha:]]+$} \u021f #} {1} # #test utf-24.1 {TclUniCharIsDigit} { # # this returns 1 with Unicode 3 compliance # string is digit \u1040 #} {1} #test utf-24.2 {unicode digit char in regc_locale.c} { # # this returns 1 with Unicode 3 compliance # list [regexp {^[[:digit:]]+$} \u1040] [regexp {^\d+$} \u1040] #} {1 1} # #test utf-24.3 {TclUniCharIsSpace} { # # this returns 1 with Unicode 3 compliance # string is space \u1680 #} {1} #test utf-24.4 {unicode space char in regc_locale.c} { # # this returns 1 with Unicode 3 compliance # list [regexp {^[[:space:]]+$} \u1680] [regexp {^\s+$} \u1680] #} {1 1} testreport openocd-0.9.0/jimtcl/tests/exists.test0000644000175000017500000000223112315602575014740 00000000000000source [file dirname [info script]]/testing.tcl needs cmd exists testConstraint lambda [expr {[info commands lambda] ne {}}] test exists-1.1 "Exists var" { set a 1 exists a } 1 test exists-1.1 "Exists var" { unset -nocomplain b exists b } 0 test exists-1.1 "Exists -var" { exists -var a } 1 test exists-1.1 "Exists -var" { exists -var b } 0 test exists-1.1 "Exists in proc" { proc a {name} { exists $name } a ::a } 1 test exists-1.1 "Exists in proc" { a ::b } 0 test exists-1.1 "Exists in proc" { a name } 1 test exists-1.1 "Exists in proc" { a none } 0 test exists-1.1 "Exists -proc" { exists -proc a } 1 test exists-1.1 "Exists -proc" { exists -proc bogus } 0 test exists-1.1 "Exists -proc" { exists -proc info } 0 test exists-1.1 "Exists -command" { exists -command a } 1 test exists-1.1 "Exists -command" { exists -command info } 1 test exists-1.1 "Exists -command" { exists -command bogus } 0 test exists-1.1 "Exists local lambda after exit" lambda { proc a {} { local lambda {} {dummy} } exists -proc [a] } 0 test exists-1.1 "Exists local lambda" lambda { proc a {} { exists -proc [local lambda {} {dummy}] } a } 1 testreport openocd-0.9.0/jimtcl/tests/break.tcl0000644000175000017500000000000612315602575014306 00000000000000break openocd-0.9.0/jimtcl/tests/regexp2.test0000644000175000017500000006127612315602575015013 00000000000000# Commands covered: regexp, regsub # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1998 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id$ source [file dirname [info script]]/testing.tcl needs cmd regexp testConstraint regexp_are [regexp {\d} 1] needs constraint regexp_are # Procedure to evaluate a script within a proc, to test compilation # functionality proc evalInProc { script } { proc testProc {} $script set status [catch { testProc } result] rename testProc {} return $result #return [list $status $result] } catch {unset foo} test regexpComp-1.1 {basic regexp operation} { evalInProc { regexp ab*c abbbc } } 1 test regexpComp-1.2 {basic regexp operation} { evalInProc { regexp ab*c ac } } 1 test regexpComp-1.3 {basic regexp operation} { evalInProc { regexp ab*c ab } } 0 test regexpComp-1.4 {basic regexp operation} { evalInProc { regexp -- -gorp abc-gorpxxx } } 1 test regexpComp-1.5 {basic regexp operation} { evalInProc { regexp {^([^ ]*)[ ]*([^ ]*)} "" a } } 1 test regexpComp-1.6 {basic regexp operation} { list [catch {regexp {} abc} msg] $msg } {0 1} test regexpComp-1.7 {regexp utf compliance} { # if not UTF-8 aware, result is "0 1" evalInProc { set foo "\u4e4eb q" regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar list [string compare $foo $bar] [regexp 4 $bar] } } {0 0} test regexpComp-2.1 {getting substrings back from regexp} { evalInProc { set foo {} list [regexp ab*c abbbbc foo] $foo } } {1 abbbbc} test regexpComp-2.2 {getting substrings back from regexp} { evalInProc { set foo {} set f2 {} list [regexp a(b*)c abbbbc foo f2] $foo $f2 } } {1 abbbbc bbbb} test regexpComp-2.3 {getting substrings back from regexp} { evalInProc { set foo {} set f2 {} list [regexp a(b*)(c) abbbbc foo f2] $foo $f2 } } {1 abbbbc bbbb} test regexpComp-2.4 {getting substrings back from regexp} { evalInProc { set foo {} set f2 {} set f3 {} list [regexp a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3 } } {1 abbbbc bbbb c} test regexpComp-2.5 {getting substrings back from regexp} { evalInProc { set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {}; set f6 {}; set f7 {}; set f8 {}; set f9 {}; set fa {}; set fb {}; list [regexp (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*)(a*)(b*) \ 12223345556789999aabbb \ foo f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb] $foo $f1 $f2 $f3 $f4 $f5 \ $f6 $f7 $f8 $f9 $fa $fb } } {1 12223345556789999aabbb 1 222 33 4 555 6 7 8 9999 aa bbb} test regexpComp-2.6 {getting substrings back from regexp} { evalInProc { set foo 2; set f2 2; set f3 2; set f4 2 list [regexp (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4 } } {1 a a {} {}} test regexpComp-2.7 {getting substrings back from regexp} { evalInProc { set foo 1; set f2 1; set f3 1; set f4 1 list [regexp (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4 } } {1 ac a {} c} test regexpComp-2.8 {getting substrings back from regexp} { evalInProc { set match {} list [regexp {^a*b} aaaab match] $match } } {1 aaaab} test regexpComp-3.1 {-indices option to regexp} { evalInProc { set foo {} list [regexp -indices ab*c abbbbc foo] $foo } } {1 {0 5}} test regexpComp-3.2 {-indices option to regexp} { evalInProc { set foo {} set f2 {} list [regexp -indices a(b*)c abbbbc foo f2] $foo $f2 } } {1 {0 5} {1 4}} test regexpComp-3.3 {-indices option to regexp} { evalInProc { set foo {} set f2 {} list [regexp -indices a(b*)(c) abbbbc foo f2] $foo $f2 } } {1 {0 5} {1 4}} test regexpComp-3.4 {-indices option to regexp} { evalInProc { set foo {} set f2 {} set f3 {} list [regexp -indices a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3 } } {1 {0 5} {1 4} {5 5}} test regexpComp-3.5 {-indices option to regexp} { evalInProc { set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {}; set f6 {}; set f7 {}; set f8 {}; set f9 {} list [regexp -indices (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*) \ 12223345556789999 \ foo f1 f2 f3 f4 f5 f6 f7 f8 f9] $foo $f1 $f2 $f3 $f4 $f5 \ $f6 $f7 $f8 $f9 } } {1 {0 16} {0 0} {1 3} {4 5} {6 6} {7 9} {10 10} {11 11} {12 12} {13 16}} test regexpComp-3.6 {getting substrings back from regexp} { evalInProc { set foo 2; set f2 2; set f3 2; set f4 2 list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4 } } {1 {1 1} {1 1} {-1 -1} {-1 -1}} test regexpComp-3.7 {getting substrings back from regexp} { evalInProc { set foo 1; set f2 1; set f3 1; set f4 1 list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4 } } {1 {1 2} {1 1} {-1 -1} {2 2}} test regexpComp-4.1 {-nocase option to regexp} { evalInProc { regexp -nocase foo abcFOo } } 1 test regexpComp-4.2 {-nocase option to regexp} { evalInProc { set f1 22 set f2 33 set f3 44 list [regexp -nocase {a(b*)([xy]*)z} aBbbxYXxxZ22 f1 f2 f3] $f1 $f2 $f3 } } {1 aBbbxYXxxZ Bbb xYXxx} test regexpComp-4.3 {-nocase option to regexp} { evalInProc { regexp -nocase FOo abcFOo } } 1 set ::x abcdefghijklmnopqrstuvwxyz1234567890 set ::x $x$x$x$x$x$x$x$x$x$x$x$x test regexpComp-4.4 {case conversion in regexp} { evalInProc { list [regexp -nocase $::x $::x foo] $foo } } "1 $x" catch {unset ::x} test regexpComp-5.1 {exercise cache of compiled expressions} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*a bbba } } 1 test regexpComp-5.2 {exercise cache of compiled expressions} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*b xxxb } } 1 test regexpComp-5.3 {exercise cache of compiled expressions} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*c yyyc } } 1 test regexpComp-5.4 {exercise cache of compiled expressions} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*d 1d } } 1 test regexpComp-5.5 {exercise cache of compiled expressions} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*e xe } } 1 test regexpComp-6.4 {regexp errors} { evalInProc { list [catch {regexp a( b} msg] $msg } } {1 {couldn't compile regular expression pattern: parentheses () not balanced}} test regexpComp-6.5 {regexp errors} { evalInProc { list [catch {regexp a( b} msg] $msg } } {1 {couldn't compile regular expression pattern: parentheses () not balanced}} test regexpComp-6.6 {regexp errors} { evalInProc { list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg } } {0 1} test regexpComp-6.7 {regexp errors} { evalInProc { list [catch {regexp (x)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) xyzzy} msg] $msg } } {0 0} test regexpComp-6.8 {regexp errors} { evalInProc { catch {unset f1} set f1 44 catch {regexp abc abc f1(f2)} msg } } {1} test regexpComp-6.9 {regexp errors, -start bad int check} { evalInProc { list [catch {regexp -start bogus {^$} {}} msg] $msg } } {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}} test regexpComp-7.1 {basic regsub operation} { evalInProc { list [regsub aa+ xaxaaaxaa 111&222 foo] $foo } } {1 xax111aaa222xaa} test regexpComp-7.2 {basic regsub operation} { evalInProc { list [regsub aa+ aaaxaa &111 foo] $foo } } {1 aaa111xaa} test regexpComp-7.3 {basic regsub operation} { evalInProc { list [regsub aa+ xaxaaa 111& foo] $foo } } {1 xax111aaa} test regexpComp-7.4 {basic regsub operation} { evalInProc { list [regsub aa+ aaa 11&2&333 foo] $foo } } {1 11aaa2aaa333} test regexpComp-7.5 {basic regsub operation} { evalInProc { list [regsub aa+ xaxaaaxaa &2&333 foo] $foo } } {1 xaxaaa2aaa333xaa} test regexpComp-7.6 {basic regsub operation} { evalInProc { list [regsub aa+ xaxaaaxaa 1&22& foo] $foo } } {1 xax1aaa22aaaxaa} test regexpComp-7.7 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {1\122\1} foo] $foo } } {1 xax1aa22aaxaa} test regexpComp-7.8 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {1\\\122\1} foo] $foo } } "1 {xax1\\aa22aaxaa}" test regexpComp-7.9 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {1\\122\1} foo] $foo } } "1 {xax1\\122aaxaa}" test regexpComp-7.10 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {1\\&\1} foo] $foo } } "1 {xax1\\aaaaaxaa}" test regexpComp-7.11 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {1\&\1} foo] $foo } } {1 xax1&aaxaa} test regexpComp-7.12 {basic regsub operation} { evalInProc { list [regsub a(a+) xaxaaaxaa {\1\1\1\1&&} foo] $foo } } {1 xaxaaaaaaaaaaaaaaxaa} test regexpComp-7.13 {basic regsub operation} { evalInProc { set foo xxx list [regsub abc xyz 111 foo] $foo } } {0 xyz} test regexpComp-7.14 {basic regsub operation} { evalInProc { set foo xxx list [regsub ^ xyz "111 " foo] $foo } } {1 {111 xyz}} test regexpComp-7.15 {basic regsub operation} { evalInProc { set foo xxx list [regsub -- -foo abc-foodef "111 " foo] $foo } } {1 {abc111 def}} test regexpComp-7.16 {basic regsub operation} { evalInProc { set foo xxx list [regsub x "" y foo] $foo } } {0 {}} test regexpComp-7.17 {regsub utf compliance} { evalInProc { # if not UTF-8 aware, result is "0 1" set foo "xyz555ijka\u4e4ebpqr" regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar list [string compare $foo $bar] [regexp 4 $bar] } } {0 0} test regexpComp-7.18 {regsub utf8 in char range} utf8 { regsub {[\u4e4ex]b} xyza\u4e4ebijka\u4e4ebpqr 555 } xyza555ijka\u4e4ebpqr test regexpComp-7.19 {regsub utf8 in complemented char range} utf8 { regsub -all {[^x\u4e4e]b} xyza\u4e4ebizbjxbka\u4e4fbpqr 555 } xyza\u4e4ebi555jxbka555pqr test regexpComp-8.1 {case conversion in regsub} { evalInProc { list [regsub -nocase a(a+) xaAAaAAay & foo] $foo } } {1 xaAAaAAay} test regexpComp-8.2 {case conversion in regsub} { evalInProc { list [regsub -nocase a(a+) xaAAaAAay & foo] $foo } } {1 xaAAaAAay} test regexpComp-8.3 {case conversion in regsub} { evalInProc { set foo 123 list [regsub a(a+) xaAAaAAay & foo] $foo } } {0 xaAAaAAay} test regexpComp-8.4 {case conversion in regsub} { evalInProc { set foo 123 list [regsub -nocase a CaDE b foo] $foo } } {1 CbDE} test regexpComp-8.5 {case conversion in regsub} { evalInProc { set foo 123 list [regsub -nocase XYZ CxYzD b foo] $foo } } {1 CbD} test regexpComp-8.6 {case conversion in regsub} { evalInProc { set x abcdefghijklmnopqrstuvwxyz1234567890 set x $x$x$x$x$x$x$x$x$x$x$x$x set foo 123 list [regsub -nocase $x $x b foo] $foo } } {1 b} test regexpComp-9.1 {-all option to regsub} { evalInProc { set foo 86 list [regsub -all x+ axxxbxxcxdx |&| foo] $foo } } {4 a|xxx|b|xx|c|x|d|x|} test regexpComp-9.2 {-all option to regsub} { evalInProc { set foo 86 list [regsub -nocase -all x+ aXxXbxxcXdx |&| foo] $foo } } {4 a|XxX|b|xx|c|X|d|x|} test regexpComp-9.3 {-all option to regsub} { evalInProc { set foo 86 list [regsub x+ axxxbxxcxdx |&| foo] $foo } } {1 a|xxx|bxxcxdx} test regexpComp-9.4 {-all option to regsub} { evalInProc { set foo 86 list [regsub -all bc axxxbxxcxdx |&| foo] $foo } } {0 axxxbxxcxdx} test regexpComp-9.5 {-all option to regsub} { evalInProc { set foo xxx list [regsub -all node "node node more" yy foo] $foo } } {2 {yy yy more}} test regexpComp-9.6 {-all option to regsub} { evalInProc { set foo xxx list [regsub -all ^ xxx 123 foo] $foo } } {1 123xxx} #test regexpComp-10.1 {expanded syntax in regsub} { # evalInProc { # set foo xxx # list [regsub -expanded ". \#comment\n . \#comment2" abc def foo] $foo # } #} {1 defc} test regexpComp-10.2 {newline sensitivity in regsub} { evalInProc { set foo xxx list [regsub -line {^a.*b$} "dabc\naxyb\n" 123 foo] $foo } } "1 {dabc\n123\n}" test regexpComp-10.3 {newline sensitivity in regsub} { evalInProc { set foo xxx list [regsub -line {^a.*b$} "dabc\naxyb\nxb" 123 foo] $foo } } "1 {dabc\n123\nxb}" #test regexpComp-10.4 {partial newline sensitivity in regsub} { # evalInProc { # set foo xxx # list [regsub -lineanchor {^a.*b$} "da\naxyb\nxb" 123 foo] $foo # } #} "1 {da\n123}" #test regexpComp-10.5 {inverse partial newline sensitivity in regsub} { # evalInProc { # set foo xxx # list [regsub -linestop {a.*b} "da\nbaxyb\nxb" 123 foo] $foo # } #} "1 {da\nb123\nxb}" #test regexpComp-11.1 {regsub errors} { # evalInProc { # list [catch {regsub a b} msg] $msg # } #} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}} #test regexpComp-11.2 {regsub errors} { # evalInProc { # list [catch {regsub -nocase a b} msg] $msg # } #} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}} #test regexpComp-11.3 {regsub errors} { # evalInProc { # list [catch {regsub -nocase -all a b} msg] $msg # } #} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}} #test regexpComp-11.4 {regsub errors} { # evalInProc { # list [catch {regsub a b c d e f} msg] $msg # } #} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}} #test regexpComp-11.5 {regsub errors} { # evalInProc { # list [catch {regsub -gorp a b c} msg] $msg # } #} {1 {bad switch "-gorp": must be -all, -nocase, -expanded, -line, -linestop, -lineanchor, -start, or --}} #test regexpComp-11.6 {regsub errors} { # evalInProc { # list [catch {regsub -nocase a( b c d} msg] $msg # } #} {1 {couldn't compile regular expression pattern: parentheses () not balanced}} test regexpComp-11.7 {regsub errors} { evalInProc { catch {unset f1} set f1 44 catch {regsub -nocase aaa aaa xxx f1(f2)} msg } } {1} test regexpComp-11.8 {regsub errors, -start bad int check} { evalInProc { list [catch {regsub -start bogus pattern string rep var} msg] $msg } } {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}} # This test crashes on the Mac unless you increase the Stack Space to about 1 # Meg. This is probably bigger than most users want... # 8.2.3 regexp reduced stack space requirements, but this should be # tested again test regexpComp-12.1 {Tcl_RegExpExec: large number of subexpressions} { evalInProc { list [regexp (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) abcdefghijklmnopqrstuvwxyz all a b c d e f g h i j k l m n o p q r s t u v w x y z] $all $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z } } {1 abcdefghijklmnopqrstuvwxyz a b c d e f g h i j k l m n o p q r s t u v w x y z} test regexpComp-13.1 {regsub of a very large string} { # This test is designed to stress the memory subsystem in order # to catch Bug #933. It only fails if the Tcl memory allocator # is in use. set line {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE} set filedata [string repeat $line 200] for {set i 1} {$i<10} {incr i} { regsub -all "BEGIN_TABLE " $filedata "" newfiledata } set x done } {done} test regexpComp-14.1 {CompileRegexp: regexp cache} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f set x . append x *a regexp $x bbba } } 1 test regexpComp-14.2 {CompileRegexp: regexp cache, different flags} { evalInProc { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f set x . append x *a regexp -nocase $x bbba } } 1 test regexpComp-15.1 {regexp -start} { catch {unset x} list [regexp -start -10 {\d} 1abc2de3 x] $x } {1 1} test regexpComp-15.2 {regexp -start} { catch {unset x} list [regexp -start 2 {\d} 1abc2de3 x] $x } {1 2} test regexpComp-15.3 {regexp -start} { catch {unset x} list [regexp -start 4 {\d} 1abc2de3 x] $x } {1 2} test regexpComp-15.4 {regexp -start} { catch {unset x} list [regexp -start 5 {\d} 1abc2de3 x] $x } {1 3} test regexpComp-15.5 {regexp -start, over end of string} { catch {unset x} list [regexp -start [string length 1abc2de3] {\d} 1abc2de3 x] [info exists x] } {0 0} test regexpComp-15.6 {regexp -start, loss of ^$ behavior} { list [regexp -start 2 {^$} {}] } {0} test regexpComp-16.1 {regsub -start} { catch {unset x} list [regsub -all -start 2 {\d} a1b2c3d4e5 {/&} x] $x } {4 a1b/2c/3d/4e/5} test regexpComp-16.2 {regsub -start} { catch {unset x} list [regsub -all -start -25 {z} hello {/&} x] $x } {0 hello} test regexpComp-16.3 {regsub -start} { catch {unset x} list [regsub -all -start 3 {z} hello {/&} x] $x } {0 hello} #test regexpComp-16.4 {regsub -start, \A behavior} { # set out {} # lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x # lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x #} {5 /a/b/c/d/e 3 ab/c/d/e} test regexpComp-17.1 {regexp -inline} { regexp -inline b ababa } {b} test regexpComp-17.2 {regexp -inline} { regexp -inline (b) ababa } {b b} test regexpComp-17.3 {regexp -inline -indices} { regexp -inline -indices (b) ababa } {{1 1} {1 1}} test regexpComp-17.4 {regexp -inline} { regexp -inline {\w(\d+)\w} " hello 23 there456def " } {e456d 456} test regexpComp-17.5 {regexp -inline no matches} { regexp -inline {\w(\d+)\w} "" } {} test regexpComp-17.6 {regexp -inline no matches} { regexp -inline hello goodbye } {} test regexpComp-17.7 {regexp -inline, no matchvars allowed} { list [catch {regexp -inline b abc match} msg] $msg } {1 {regexp match variables not allowed when using -inline}} test regexpComp-18.1 {regexp -all} { regexp -all b bbbbb } {5} test regexpComp-18.2 {regexp -all} { regexp -all b abababbabaaaaaaaaaab } {6} test regexpComp-18.3 {regexp -all -inline} { regexp -all -inline b abababbabaaaaaaaaaab } {b b b b b b} test regexpComp-18.4 {regexp -all -inline} { regexp -all -inline {\w(\w)} abcdefg } {ab b cd d ef f} test regexpComp-18.5 {regexp -all -inline} { regexp -all -inline {\w(\w)$} abcdefg } {fg g} test regexpComp-18.6 {regexp -all -inline} { regexp -all -inline {\d+} 10:20:30:40 } {10 20 30 40} test regexpComp-18.7 {regexp -all -inline} { list [catch {regexp -all -inline b abc match} msg] $msg } {1 {regexp match variables not allowed when using -inline}} test regexpComp-18.8 {regexp -all} { # This should not cause an infinite loop regexp -all -inline {a*} a } {a} test regexpComp-18.9 {regexp -all} { # Yes, the expected result is {a {}}. Here's why: # Start at index 0; a* matches the "a" there then stops. # Go to index 1; a* matches the lambda (or {}) there then stops. Recall # that a* matches zero or more "a"'s; thus it matches the string "b", as # there are zero or more "a"'s there. # Go to index 2; this is past the end of the string, so stop. regexp -all -inline {a*} ab } {a {}} test regexpComp-18.10 {regexp -all} { # Yes, the expected result is {a {} a}. Here's why: # Start at index 0; a* matches the "a" there then stops. # Go to index 1; a* matches the lambda (or {}) there then stops. Recall # that a* matches zero or more "a"'s; thus it matches the string "b", as # there are zero or more "a"'s there. # Go to index 2; a* matches the "a" there then stops. # Go to index 3; this is past the end of the string, so stop. regexp -all -inline {a*} aba } {a {} a} test regexpComp-18.11 {regexp -all} { evalInProc { regexp -all -inline {^a} aaaa } } {a} test regexpComp-18.12 {regexp -all -inline -indices} { evalInProc { regexp -all -inline -indices a(b(c)d|e(f)g)h abcdhaefgh } } {{0 4} {1 3} {2 2} {-1 -1} {5 9} {6 8} {-1 -1} {7 7}} test regexpComp-19.1 {regsub null replacement} { evalInProc { regsub -all {@} {@hel@lo@} "\0a\0" result list $result [string length $result] } } "\0a\0hel\0a\0lo\0a\0 14" test regexpComp-20.1 {regsub shared object shimmering} { evalInProc { # Bug #461322 set a abcdefghijklmnopqurstuvwxyz set b $a set c abcdefghijklmnopqurstuvwxyz0123456789 regsub $a $c $b d list $d [string length $d] [string bytelength $d] } } [list abcdefghijklmnopqurstuvwxyz0123456789 37 37] #test regexpComp-20.2 {regsub shared object shimmering with -about} { # evalInProc { # eval regexp -about abc # } #} {0 {}} test regexpComp-21.1 {regexp command compiling tests} { evalInProc { regexp foo bar } } 0 test regexpComp-21.2 {regexp command compiling tests} { evalInProc { regexp {^foo$} dogfood } } 0 test regexpComp-21.3 {regexp command compiling tests} { evalInProc { set a foo regexp {^foo$} $a } } 1 test regexpComp-21.4 {regexp command compiling tests} { evalInProc { regexp foo dogfood } } 1 test regexpComp-21.5 {regexp command compiling tests} { evalInProc { regexp -nocase FOO dogfod } } 0 test regexpComp-21.6 {regexp command compiling tests} { evalInProc { regexp -n foo dogfoOd } } 1 test regexpComp-21.7 {regexp command compiling tests} { evalInProc { regexp -no -- FoO dogfood } } 1 test regexpComp-21.8 {regexp command compiling tests} { evalInProc { regexp -- foo dogfod } } 0 test regexpComp-21.9 {regexp command compiling tests} { evalInProc { list [catch {regexp -- -nocase foo dogfod} msg] $msg } } {0 0} test regexpComp-21.10 {regexp command compiling tests} { evalInProc { list [regsub -all "" foo bar str] $str } } {3 barfbarobaro} # This useless expression fails. Jim returns "bar" #test regexpComp-21.11 {regexp command compiling tests} { # evalInProc { # list [regsub -all "" "" bar str] $str # } #} {0 {}} # We can forgive the underlying regexp engine for not supporting this. # Why not use this instead? "((^X)*|\$)" #test regexpComp-22.0.1 {Bug 1810038} { # evalInProc { # regexp ($|^X)* {} # } #} 1 set i 0 foreach {str exp result} { foo ^foo 1 foobar ^foobar$ 1 foobar bar$ 1 foobar ^$ 0 "" ^$ 1 anything $ 1 anything ^.*$ 1 anything ^.*a$ 0 anything ^.*a.*$ 1 anything ^.*.*$ 1 anything ^.*..*$ 1 anything ^.*b$ 0 anything ^a.*$ 1 } { test regexpComp-22.[incr i] {regexp command compiling tests} \ [subst {evalInProc {set a "$str"; regexp {$exp} \$a}}] $result } set i 0 foreach {str exp result} { foo ^foo 1 foobar ^foobar$ 1 foobar bar$ 1 foobar ^$ 0 "" ^$ 1 anything $ 1 anything ^.*$ 1 anything ^.*a$ 0 anything ^.*a.*$ 1 anything ^.*.*$ 1 anything ^.*..*$ 1 anything ^.*b$ 0 anything ^a.*$ 1 } { test regexpComp-23.[incr i] {regexp command compiling tests INST_REGEXP} \ [list regexp $exp $str] $result } test regexpComp-24.1 {regexp command compiling tests} { evalInProc { set re foo regexp -nocase $re bar } } 0 test regexpComp-24.2 {regexp command compiling tests} { evalInProc { set re {^foo$} regexp $re dogfood } } 0 test regexpComp-24.3 {regexp command compiling tests} { evalInProc { set a foo set re {^foo$} regexp $re $a } } 1 test regexpComp-24.4 {regexp command compiling tests} { evalInProc { set re foo regexp $re dogfood } } 1 test regexpComp-24.5 {regexp command compiling tests} { evalInProc { set re FOO regexp -nocase $re dogfod } } 0 test regexpComp-24.6 {regexp command compiling tests} { evalInProc { set re foo regexp -n $re dogfoOd } } 1 test regexpComp-24.7 {regexp command compiling tests} { evalInProc { set re FoO regexp -no -- $re dogfood } } 1 test regexpComp-24.8 {regexp command compiling tests} { evalInProc { set re foo regexp -- $re dogfod } } 0 test regexpComp-24.9 {regexp command compiling tests} { evalInProc { set re "(" list [catch {regexp -- $re dogfod} msg] $msg } } {1 {couldn't compile regular expression pattern: parentheses () not balanced}} test regexpComp-24.10 {regexp command compiling tests} { # Bug 1902436 - last * escaped evalInProc { set text {this is *bold* !} set re {\*bold\*} regexp -- $re $text } } 1 test regexpComp-24.11 {regexp command compiling tests} { # Bug 1902436 - last * escaped evalInProc { set text {this is *bold* !} set re {\*bold\*.*!} regexp -- $re $text } } 1 test regexp-25.1 {Repeat on escaped char} { regexp {\x41\x42*} bc } 0 test regexp-25.2 {Single braced count} { regexp "a{4}" baaaad } 1 testreport openocd-0.9.0/jimtcl/tests/return-break.tcl0000644000175000017500000000003212315602575015622 00000000000000return -code break result openocd-0.9.0/jimtcl/tests/expr-new.test0000644000175000017500000007231012315602575015173 00000000000000# Commands covered: expr # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1996-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: expr.test,v 1.9 2000/04/10 17:18:59 ericm Exp $ source [file dirname [info script]]/testing.tcl # procedures used below proc put_hello_char {c} { global a append a [format %c $c] return $c } proc hello_world {} { global a set a "" set L1 [set l0 [set h_1 [set q 0]]] for {put_hello_char [expr [put_hello_char [expr [set h 7]*10+2]]+29]} {$l0?[put_hello_char $l0] :!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])] ?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3? [incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]] :[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2 ?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]} expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]} } set a } proc 12days {a b c} { global xxx expr {1<$a?[expr {$a<3?[12days -79 -13 [string range $c [12days -87 \ [expr 1-$b] [string range $c [12days -86 0 [string range $c 1 end]] \ end]] end]]:1};expr {$a<$b?[12days [expr $a+1] $b $c]:3};expr {[12days \ -94 [expr $a-27] $c]&&$a==2?$b<13?[12days 2 [expr $b+1] "%s %d %d\n"]:9 :16}]:$a<0?$a<-72?[12days $b $a "@n'+,#'/*\{\}w+/w#cdnr/+,\{\}r/*de\}+,/*\{*+,/w\{%+,/w#q#n+,/#\{l+,/n\{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,\}\{w+K w'K:'+\}e#';dq#'l q#'+d'K#!/+k#;q#'r\}eKK#\}w'r\}eKK\{nl\]'/#;#q#n')\{)#\}w')\{)\{nl\]'/+#n';d\}rw' i;# )\{nl\]!/n\{n#'; r\{#w'r nc\{nl\]'/#\{l,+'K \{rw' iK\{;\[\{nl\]'/w#q#n'wk nw' iwk\{KK\{nl\]!/w\{%'l##w#' i; :\{nl\]'/*\{q#'ld;r'\}\{nlwb!/*de\}'c ;;\{nl'-\{\}rw\]'/+,\}##'*\}#nc,',#nw\]'/+kd'+e\}+;#'rdq#w! nr'/ ') \}+\}\{rl#'\{n' ')# \}'+\}##(!!/"] :$a<-50?[string compare [format %c $b] [string index $c 0]]==0?[append \ xxx [string index $c 31];scan [string index $c 31] %c x;set x] :[12days -65 $b [string range $c 1 end]]:[12days [expr ([string compare \ [string index $c 0] "/"]==0)+$a] $b [string range $c 1 end]]:0<$a ?[12days 2 2 "%s"]:[string compare [string index $c 0] "/"]==0|| [12days 0 [12days -61 [scan [string index $c 0] %c x; set x] \ "!ek;dc i@bK'(q)-\[w\]*%n+r3#l,\{\}:\nuwloca-O;m .vpbks,fxntdCeghiry"] \ [string range $c 1 end]]} } proc do_twelve_days {} { global xxx set xxx "" 12days 1 1 1 string length $xxx } # start of tests catch {unset a b i x} test expr-1.1 {TclCompileExprCmd: no expression} { list [catch {expr } msg] } {1} test expr-1.2 {TclCompileExprCmd: one expression word} { expr -25 } -25 test expr-1.3 {TclCompileExprCmd: two expression words} { expr -8.2 -6 } -14.2 test expr-1.4 {TclCompileExprCmd: five expression words} { expr 20 - 5 +10 -7 } 18 test expr-1.5 {TclCompileExprCmd: quoted expression word} { expr "0005" } 5 test expr-1.6 {TclCompileExprCmd: quoted expression word} { catch {expr "0005"zxy} msg } {1} test expr-1.7 {TclCompileExprCmd: expression word in braces} { expr {-0005} } -5 # XXX: I believe that this ought to return a string, thus -0x1234 #test expr-1.8 {TclCompileExprCmd: expression word in braces} { # expr {{-0x1234}} #} -4660 test expr-1.9 {TclCompileExprCmd: expression word in braces} { catch {expr {-0005}foo} msg } {1} test expr-1.10 {TclCompileExprCmd: other expression word in braces} { expr 4*[llength "6 2"] } 8 test expr-1.11 {TclCompileExprCmd: expression word terminated by ;} { expr 4*[llength "6 2"]; } 8 test expr-1.12 {TclCompileExprCmd: inlined expr (in "catch") inside other catch} { set a xxx catch { # Might not be a number set a [expr 10*$a] } } 1 test expr-1.13 {TclCompileExprCmd: second level of substitutions in expr not in braces with single var reference} { set a xxx set x 27; set bool {$x}; if $bool {set a foo} set a } foo test expr-1.14 {TclCompileExprCmd: second level of substitutions in expr with comparison as top-level operator} { set a xxx set x 2; set b {$x}; set a [expr $b == 2] set a } 1 test expr-2.1 {TclCompileExpr: are builtin functions registered?} { expr double(5*[llength "6 2"]) } 10.0 test expr-2.2 {TclCompileExpr: error in expr} { catch {expr 2//3} msg } {1} test expr-2.3 {TclCompileExpr: junk after legal expr} { catch {expr 7*[llength "a b"]foo} msg } {1} test expr-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} { expr {0001} } 1 test expr-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1 test expr-3.2 {CompileCondExpr: error in lor expr} { catch {expr x||3} msg } {1} test expr-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44 test expr-3.4 {CompileCondExpr: error compiling true arm} { catch {expr 3>2?2//3:66} msg } {1} test expr-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66 test expr-3.6 {CompileCondExpr: error compiling false arm} { catch {expr 2>3?44:2//3} msg } {1} if {0} { test expr-3.7 {CompileCondExpr: long arms & nested cond exprs} { puts "Note: doing test expr-3.7 which can take several minutes to run" hello_world } {Hello world} catch {unset xxx} test expr-3.8 {CompileCondExpr: long arms & nested cond exprs} { puts "Note: doing test expr-3.8 which can take several minutes to run" do_twelve_days } 2358 catch {unset xxx} } test expr-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1 test expr-4.2 {CompileLorExpr: error in land expr} { catch {expr x&&3} msg } {1} test expr-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1 test expr-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1 test expr-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1 test expr-4.6 {CompileLorExpr: error compiling lor arm} { catch {expr 2//3||4.0} msg } {1} test expr-4.7 {CompileLorExpr: error compiling lor arm} { catch {expr 1.3||2//3} msg } {1} test expr-4.8 {CompileLorExpr: error compiling lor arms} { list [catch {expr {"a"||"b"}} msg] } {1} test expr-4.9 {CompileLorExpr: long lor arm} { set a "abcdefghijkl" set i 7 expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} } 1 test expr-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23 test expr-5.2 {CompileLandExpr: error in bitor expr} { catch {expr x|3} msg } {1} test expr-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0 test expr-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0 test expr-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1 test expr-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1 test expr-5.7 {CompileLandExpr: error compiling land arm} { catch {expr 2//3&&4.0} msg } {1} test expr-5.8 {CompileLandExpr: error compiling land arm} { catch {expr 1.3&&2//3} msg } {1} test expr-5.9 {CompileLandExpr: error compiling land arm} { list [catch {expr {"a"&&"b"}} msg] } {1} test expr-5.10 {CompileLandExpr: long land arms} { set a "abcdefghijkl" set i 7 expr {[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]} } 1 test expr-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3 test expr-6.2 {CompileBitXorExpr: error in bitand expr} { catch {expr x|3} msg } {1} test expr-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20 test expr-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19 test expr-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7 test expr-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8 test expr-6.7 {CompileBitXorExpr: error compiling bitxor arm} { catch {expr 2//3|6} msg } {1} test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} { catch {expr 2^x} msg } {1} test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} { list [catch {expr {24.0^3}} msg] } {1} test expr-6.10 {CompileBitXorExpr: runtime error in bitxor arm} { list [catch {expr {"a"^"b"}} msg] } {1} test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0 test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1 test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1 test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0 test expr-7.5 {CompileBitAndExpr: error in equality expr} { catch {expr x==3} msg } {1} test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3 test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82 test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2 test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7 test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} { catch {expr 2//3&6} msg } {1} test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} { catch {expr 2&x} msg } {1} test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} { list [catch {expr {24.0&3}} msg] } {1} test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} { list [catch {expr {"a"&"b"}} msg] } {1} test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1 test expr-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1 test expr-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1 test expr-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0 test expr-8.5 {CompileEqualityExpr: error in relational expr} { catch {expr x>3} msg } {1} test expr-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0 test expr-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1 test expr-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1 test expr-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1 test expr-8.10 {CompileEqualityExpr: error compiling equality arm} { catch {expr 2//3==6} msg } {1} test expr-8.11 {CompileEqualityExpr: error compiling equality arm} { catch {expr 2!=x} msg } {1} test expr-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12 test expr-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63 test expr-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1 test expr-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8 # The following test is different for 32-bit versus 64-bit # architectures because LONG_MIN is different if {0x80000000 > 0} { test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN (64bit)} jim { expr {1<<63} } -9223372036854775808 } else { test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN (32bit)} jim { expr {1<<31} } -2147483648 } test expr-9.6 {CompileRelationalExpr: error in shift expr} { catch {expr x>>3} msg } {1} test expr-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1 test expr-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1 test expr-9.9 {CompileRelationalExpr: error compiling relational arm} { catch {expr 2//3>6} msg } {1} test expr-9.10 {CompileRelationalExpr: error compiling relational arm} { catch {expr 2>0x3} 31 test expr-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936 test expr-10.8 {CompileShiftExpr: error compiling shift arm} { catch {expr 2//3>>6} msg } {1} test expr-10.9 {CompileShiftExpr: error compiling shift arm} { catch {expr 2<>43}} msg] } {1} test expr-10.11 {CompileShiftExpr: runtime error} { list [catch {expr {"a"<<"b"}} msg] } {1} test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8 test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1 test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1 test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 19 test expr-11.5 {CompileAddExpr: error in multiply expr} { catch {expr x*3} msg } {1} test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258 test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239 test expr-11.8 {CompileAddExpr: error compiling add arm} { catch {expr 2//3+6} msg } {1} test expr-11.9 {CompileAddExpr: error compiling add arm} { catch {expr 2-x} msg } {1} test expr-11.10 {CompileAddExpr: runtime error} { list [catch {expr {24.0+"xx"}} msg] } {1} test expr-11.11 {CompileAddExpr: runtime error} { list [catch {expr {"a"-"b"}} msg] } {1} test expr-11.12 {CompileAddExpr: runtime error} { list [catch {expr {3/0}} msg] } {1} test expr-11.13 {CompileAddExpr: divide by zero} { expr {2.3/0.0} } {Inf} test expr-11.14 {CompileAddExpr: divide by zero} { expr {-2.3/0.0} } {-Inf} test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5 test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5 test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0 test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936 test expr-12.5 {CompileMultiplyExpr: error in unary expr} { catch {expr ~x} msg } {1} test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765 test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2 test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} { catch {expr 2*3%%6} msg } {1} test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} { catch {expr 2*x} msg } {1} test expr-12.10 {CompileMultiplyExpr: runtime error} { list [catch {expr {24.0*"xx"}} msg] } {1} test expr-12.11 {CompileMultiplyExpr: runtime error} { list [catch {expr {"a"/"b"}} msg] } {1} test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255 test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 123 test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36 test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0 test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0 test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1 test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0 test expr-13.8 {CompileUnaryExpr: error compiling unary expr} { catch {expr ~x} msg } {1} test expr-13.9 {CompileUnaryExpr: error compiling unary expr} { catch {expr !1.x} msg } {1} test expr-13.10 {CompileUnaryExpr: runtime error} { list [catch {expr {~"xx"}} msg] } {1} test expr-13.11 {CompileUnaryExpr: runtime error} { list [catch {expr ~4.0} msg] } {1} test expr-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291 test expr-13.13 {CompileUnaryExpr: just primary expr} { set a 27 expr $a } 27 test expr-13.14 {CompileUnaryExpr: just primary expr} { expr double(27) } 27.0 test expr-13.15 {CompileUnaryExpr: just primary expr} {expr "123"} 123 test expr-13.16 {CompileUnaryExpr: error in primary expr} { catch {expr [set]} msg } {1} test expr-14.1 {CompilePrimaryExpr: literal primary} {expr 1} 1 test expr-14.2 {CompilePrimaryExpr: literal primary} {expr 123} 123 test expr-14.3 {CompilePrimaryExpr: literal primary} {expr 0xff} 255 test expr-14.4 {CompilePrimaryExpr: literal primary} {expr 00010} 10 test expr-14.5 {CompilePrimaryExpr: literal primary} {expr 62.0} 62.0 test expr-14.6 {CompilePrimaryExpr: literal primary} { expr 3.1400000 } 3.14 test expr-14.7 {CompilePrimaryExpr: literal primary} {expr {{abcde}<{abcdef}}} 1 test expr-14.8 {CompilePrimaryExpr: literal primary} {expr {{abc\ def} < {abcdef}}} 1 test expr-14.9 {CompilePrimaryExpr: literal primary} {expr {{abc\tde} > {abc\tdef}}} 0 test expr-14.10 {CompilePrimaryExpr: literal primary} {expr {{123}}} 123 test expr-14.11 {CompilePrimaryExpr: var reference primary} { set i 789 list [expr {$i}] [expr $i] } {789 789} test expr-14.12 {CompilePrimaryExpr: var reference primary} { set i {789} ;# test expr's aggressive conversion to numeric semantics list [expr {$i}] [expr $i] } {789 789} test expr-14.13 {CompilePrimaryExpr: var reference primary} { catch {unset a} set a(foo) foo set a(bar) bar set a(123) 123 set result "" lappend result [expr $a(123)] [expr {$a(bar)<$a(foo)}] catch {unset a} set result } {123 1} test expr-14.14 {CompilePrimaryExpr: var reference primary} { set i 123 ;# test "$var.0" floating point conversion hack list [expr $i] [expr $i.0] [expr $i.0/12.0] } {123 123.0 10.25} test expr-14.15 {CompilePrimaryExpr: var reference primary} { set i 123 catch {expr $i.2} msg set msg } 123.2 test expr-14.16 {CompilePrimaryExpr: error compiling var reference primary} { catch {expr {$a(foo}} msg } {1} test expr-14.18 {CompilePrimaryExpr: quoted string primary} { expr "21" } 21 test expr-14.19 {CompilePrimaryExpr: quoted string primary} { set i 123 set x 456 expr "$i+$x" } 579 test expr-14.20 {CompilePrimaryExpr: quoted string primary} { set i 3 set x 6 expr 2+"$i.$x" } 5.6 test expr-14.21 {CompilePrimaryExpr: error in quoted string primary} { catch {expr "[set]"} msg } {1} test expr-14.22 {CompilePrimaryExpr: subcommand primary} { expr {[set i 123; set i]} } 123 test expr-14.23 {CompilePrimaryExpr: error in subcommand primary} { catch {expr {[set]}} msg } {1} test expr-14.24 {CompilePrimaryExpr: error in subcommand primary} { catch {expr {[set blah}} msg } {1} test expr-14.28 {CompilePrimaryExpr: subexpression primary} { expr 2+(3*4) } 14 test expr-14.29 {CompilePrimaryExpr: error in subexpression primary} { catch {expr 2+(3*[set])} msg } {1} test expr-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} { catch {expr 2+(3*(4+5)} msg } {1} test expr-14.31 {CompilePrimaryExpr: just var ref in subexpression primary} { set i "5+10" list "[expr $i] == 15" "[expr ($i)] == 15" "[eval expr ($i)] == 15" } {{15 == 15} {15 == 15} {15 == 15}} test expr-14.32 {CompilePrimaryExpr: unexpected token} { catch {expr @} msg } {1} test expr-15.2 {CompileMathFuncCall: unknown math function} { catch {expr whazzathuh(1)} msg } {1} test expr-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} { catch {unset a} set a(VALUE) ff15 set i 123 if {[expr 0x$a(VALUE)] & 16} { set i {} } set i } {} test expr-16.2 {GetToken: check for string literal in braces} { expr {{1}} } {1} # Check "expr" and computed command names. test expr-17.1 {expr and computed command names} { set i 0 set z expr $z 1+2 } 3 # Check correct conversion of operands to numbers: If the string looks like # an integer, convert to integer. Otherwise, if the string looks like a # double, convert to double. test expr-18.1 {expr and conversion of operands to numbers} { set x [lindex 11 0] catch {expr int($x)} expr {$x} } 11 test expr-18.2 {whitespace strings should not be == 0 (buggy strtod)} { expr {" "} } { } # Check "expr" and interpreter result object resetting before appending # an error msg during evaluation of exprs not in {}s test expr-19.1 {expr and interpreter result object resetting} { proc p {} { set t 10.0 set x 2.0 set dx 0.2 set f {$dx-$x/10} set g {-$x/5} set center 1.0 set x [expr $x-$center] set dx [expr $dx+$g] set x [expr $x+$f+$center] set x [expr $x+$f+$center] set y [expr round($x)] } p } 3 catch {unset a} # Test for incorrect "double evaluation" semantics #XXX: Jim doesn't care about missing braces #test expr-20.1 {wrong brace matching} { # catch {unset l} # catch {unset r} # catch {unset q} # catch {unset cmd} # catch {unset a} # set l "\{"; set r "\}"; set q "\"" # set cmd "expr $l$q|$q == $q$r$q$r" # catch $cmd a #} {1} test expr-20.3 {broken substitution of integer digits} { # fails with 8.0.x, but not 8.1b2 list [set a 000; expr 0x1$a] [set a 1; expr ${a}000] } {4096 1000} test expr-20.4 {proper double evaluation compilation, error case} { catch {unset a}; # make sure $a doesn't exist list [catch {expr 1?{$a}:0} msg] } {1} test expr-20.5 {proper double evaluation compilation, working case} { set a yellow expr 1?{$a}:0 } yellow test expr-20.6 {handling of compile error in trial compile} { list [catch {expr + {[incr]}} msg] } {1} test expr-20.7 {handling of compile error in runtime case} { list [catch {expr + {[error foo]}} msg] } {1} # cleanup if {[info exists a]} { unset a } testreport openocd-0.9.0/jimtcl/tests/expr.test0000644000175000017500000000457412315602575014413 00000000000000source [file dirname [info script]]/testing.tcl test expr-1.1 "Compare strings lt" { expr {"V000500" < "V000405"} } {0} test expr-1.2 "Compare strings with embedded nulls" { set s1 [format abc%cdef 0] set s2 [format abc%cghi 0] expr {$s1 < $s2} } {1} test expr-1.3 "Hex values" { set mask1 [expr 0x4050 & 0x0CCC] } {64} test expr-1.4 "Ternary operator - true" { expr {1 ? 2 : 3} } {2} test expr-1.5 "Ternary operator - false" { expr {0 ? 2 : 3} } {3} test expr-1.6 "Ternary operator - double check" { expr {1.0 ? 2 : 3} } {2} test expr-1.7 "Ternary operator - string result" { expr {1 ? "two" : 3} } {two} test expr-1.8 "Ternary operator - don't eval false path" { set a 100 set b 200 set c [expr {20 ? [incr a] : [incr b]}] list $a $b $c } {101 200 101} test expr-1.9 "Unary minus" { set a 1 expr {-$a} } {-1} test expr-1.10 "Subtraction" { set a 1 set b 10 expr {$b-$a} } {9} test expr-1.11 "Short circuit evaluation" { set a 100 set c [expr {0 || [incr a]}] list $a $c } {101 1} test expr-1.12 "Short circuit evaluation" { set a 100 set c [expr {1 || [incr a]}] list $a $c } {100 1} test expr-1.13 "Short circuit evaluation" { set a 100 set c [expr {1 || [incr a] && [incr a]}] list $a $c } {100 1} test expr-1.14 "Rotate left" jim { expr {1 <<< 5} } {32} test expr-1.15 "Rotate left" jim { expr {1 <<< 65} } {2} test expr-1.16 "Rotate right" jim { expr {1 >>> 48} } {65536} test expr-1.17 "Rotate left" jim { expr {1 >>> 63} } {2} # This crashes older jim test expr-2.1 "bogus unarymin" { catch {expr {unarymin 1}} return 1 } {1} test expr-2.2 "Ternary operator - missing colon" { list [catch {expr {1 ? 2 3}} msg] } {1} test expr-2.3 "Ternary operator - missing third term" { list [catch {expr {1 ? 2}} msg] } {1} test expr-2.4 "Ternary operator - missing question" { list [catch {expr {1 : 2}} msg] } {1} test expr-3.1 "in, ni operators" { set l {a b c d} set c C list [expr {"a" in $l}] [expr {$c in $l}] [expr {"b" ni $l}] [expr {$c ni $l}] } {1 0 0 1} test expr-3.2 "if: in, ni operators" { set l {a b c d} set a a set c C set result {} if {$a in $l} { lappend result 1 } if {$c in $l} { lappend result 2 } if {$a ni $l} { lappend result 3 } if {$c ni $l} { lappend result 4 } if {"d" in $l} { lappend result 5 } } {1 4 5} # Don't want a to become 2.0 test expr-4.1 "Shimmering" { set a 2 expr {$a < 3.0} set a } {2} testreport openocd-0.9.0/jimtcl/tests/applyns.test0000644000175000017500000000627512315602575015123 00000000000000# Commands covered: apply # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2005-2006 Miguel Sofer # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl needs cmd apply needs cmd namespace # Tests for runtime errors in the lambda expression # Note: Jim doesn't have the concept of non-existent namespaces test apply-3.1 {non-existing namespace} -constraints tcl -body { apply [list x {set x 1} ::NONEXIST::FOR::SURE] x } -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found} test apply-3.2 {non-existing namespace} -constraints tcl -body { namespace eval ::NONEXIST::FOR::SURE {} set lambda [list x {set x 1} ::NONEXIST::FOR::SURE] apply $lambda x namespace delete ::NONEXIST apply $lambda x } -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found} test apply-3.3 {non-existing namespace} -constraints tcl -body { apply [list x {set x 1} NONEXIST::FOR::SURE] x } -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found} test apply-3.4 {non-existing namespace} -constraints tcl -body { namespace eval ::NONEXIST::FOR::SURE {} set lambda [list x {set x 1} NONEXIST::FOR::SURE] apply $lambda x namespace delete ::NONEXIST apply $lambda x } -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found} # Tests for correct namespace scope namespace eval ::testApply { proc testApply args {return testApply} } test apply-7.1 {namespace access} { set ::testApply::x 0 set body {set x 1; set x} list [apply [list args $body ::testApply]] $::testApply::x } {1 0} test apply-7.2 {namespace access} { set ::testApply::x 0 set body {variable x; set x} list [apply [list args $body ::testApply]] $::testApply::x } {0 0} test apply-7.3 {namespace access} { set ::testApply::x 0 set body {variable x; set x 1} list [apply [list args $body ::testApply]] $::testApply::x } {1 1} test apply-7.4 {namespace access} { set ::testApply::x 0 set body {testApply} apply [list args $body ::testApply] } testApply test apply-7.5 {namespace access} { set ::testApply::x 0 set body {set x 1; set x} list [apply [list args $body testApply]] $::testApply::x } {1 0} test apply-7.6 {namespace access} { set ::testApply::x 0 set body {variable x; set x} list [apply [list args $body testApply]] $::testApply::x } {0 0} test apply-7.7 {namespace access} { set ::testApply::x 0 set body {variable x; set x 1} list [apply [list args $body testApply]] $::testApply::x } {1 1} test apply-7.8 {namespace access} { set ::testApply::x 0 set body {testApply} apply [list args $body testApply] } testApply namespace delete testApply testreport # Local Variables: # mode: tcl # fill-column: 78 # End: openocd-0.9.0/jimtcl/tests/exitpackage.tcl0000644000175000017500000000004212315602575015507 00000000000000# This package just exits exit 1 openocd-0.9.0/jimtcl/tests/try.test0000644000175000017500000000304412315602575014242 00000000000000source [file dirname [info script]]/testing.tcl needs cmd try tclcompat test try-1.1 "Simple case" { try { set x 0 } finally { incr x } } 0 test try-1.2 "Error in body" { list [catch { try { set x 0 error message } finally { incr x } } msg] $msg $x } {1 message 1} test try-1.3 "Error in finally" { list [catch { try { set x 0 } finally { incr x error finally } } msg] $msg $x } {1 finally 1} test try-1.4 "Error in both" { list [catch { try { set x 0 error message } finally { incr x error finally } } msg] $msg $x } {1 finally 1} test try-1.5 "break in body" { list [catch { try { set x 0 break } finally { incr x } } msg] $msg $x } {3 {} 1} test try-1.6 "break in finally" { list [catch { try { set x 0 } finally { incr x break } } msg] $msg $x } {3 {} 1} test try-1.7 "return value from try, not finally" { list [catch { try { set x 0 } finally { incr x } } msg] $msg $x } {0 0 1} test try-1.8 "return from within try" { proc a {} { try { return 1 } # notreached return 2 } a } {1} test try-1.9 "return -code from within try" { proc a {} { try { return -code break text } # notreached return 2 } list [catch a msg] $msg } {3 text} proc c {} { try { error here } on error {msg opts} { # jim can do simply: if {[catch {incr opts(-level)}]} { # Must be Tcl dict incr opts -level } return {*}$opts $msg } } test try-3.1 "rethrow error in try/on handler" { list [catch c msg] $msg } {1 here} testreport openocd-0.9.0/jimtcl/tests/perf.test0000644000175000017500000000655412315602575014371 00000000000000source [file dirname [info script]]/testing.tcl needs constraint manual set iterations 10000 set version [info patchlevel] proc bench {name cmd} { if {[catch { set t [time $cmd 2] set ms [format %.0f [expr {[lindex $t 0] / 1000}]] }]} { set ms ? } puts "$::version: $name ${ms}ms" } proc set_dict_sugar {} { for {set i 0} {$i < $::iterations} {incr i} { set a(b) $i } } # Note that this case does not benefit from the dict sugar # speedup since a($b) needs to be interpolated and reparsed every time proc set_var_dict_sugar {} { set b b for {set i 0} {$i < $::iterations} {incr i} { set a($b) $i } } proc set_var_dict {} { set b b for {set i 0} {$i < $::iterations} {incr i} { dict set a $b $i } } proc read_file {file} { set f [open $file] while {[gets $f buf] >= 0} { } close $f } proc read_file_split {file} { set f [open $file] while {[gets $f buf] >= 0} { split $buf \t } close $f } proc read_file_split_assign_foreach {file} { set f [open $file] while {[gets $f buf] >= 0} { foreach {info(chan) info(datetime) info(duration) info(title) subtitle_genre info(desc) info(rating) dummy} [split $buf \t] {break} } close $f } proc read_file_split_assign_foreach_dict {file} { set f [open $file] while {[gets $f buf] >= 0} { foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break} dict set info chan $chan dict set info duration $duration dict set info title $title dict set info subtitle_genre $subtitle_genre dict set info desc $desc dict set info rating $rating } close $f } proc read_file_split_assign_foreach_dictsugar {file} { set f [open $file] while {[gets $f buf] >= 0} { foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break} set info(chan) $chan set info(duration) $duration set info(title) $title set info(subtitle_genre) $subtitle_genre set info(desc) $desc set info(rating) $rating } close $f } proc read_file_split_assign_foreach_simple {file} { set f [open $file] while {[gets $f buf] >= 0} { foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break} } close $f } proc read_file_split_assign_lindex {file} { set f [open $file] while {[gets $f buf] >= 0} { set split [split $buf \t] set info(chan) [lindex $split 0] set info(datetime) [lindex $split 1] set info(duration) [lindex $split 2] set info(title) [lindex $split 3] set info(subtitle_genre) [lindex $split 4] set info(desc) [lindex $split 5] set info(rating) [lindex $split 6] } close $f } # Create a really big file set f [open test.in w] for {set i 0} {$i < $::iterations} {incr i} { puts $f "a\tb\tc\te\tf\tg\th\ti\tj\tk" } close $f bench "set dictsugar" {set_dict_sugar} bench "set var dictsugar" {set_var_dict_sugar} bench "set var dict" {set_var_dict} # Read once before testing perf read_file test.in bench "read file" {read_file test.in} bench "read file split" {read_file_split test.in} bench "foreach: simple" {read_file_split_assign_foreach_simple test.in} bench "foreach: direct dictsugar" {read_file_split_assign_foreach test.in} bench "foreach: dict cmd" {read_file_split_assign_foreach_dict test.in} bench "foreach: assign to dictsugar" {read_file_split_assign_foreach_dictsugar test.in} bench "foreach: assign to dictsugar via lindex" {read_file_split_assign_lindex test.in} file delete test.in # testreport openocd-0.9.0/jimtcl/tests/for.test0000644000175000017500000000336012315602575014213 00000000000000# Commands covered: for, continue, break # # This file contains the original set of tests for Tcl's for command. # Since the for command is now compiled, a new set of tests covering # the new implementation is in the file "for.test". Sourcing this file # into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: for-old.test,v 1.5 2000/04/10 17:18:59 ericm Exp $ source [file dirname [info script]]/testing.tcl # Check "for" and its use of continue and break. catch {unset a i} test for-old-1.1 {for tests} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { set a [concat $a $i] } set a } {1 2 3 4 5} test for-old-1.2 {for tests} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 continue set a [concat $a $i] } set a } {1 2 3 5} test for-old-1.3 {for tests} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 break set a [concat $a $i] } set a } {1 2 3} test for-old-1.4 {for tests} {catch {for 1 2 3} msg} 1 test for-old-1.5 {for tests} { catch {for 1 2 3} msg } {1} test for-old-1.6 {for tests} {catch {for 1 2 3 4 5} msg} 1 test for-old-1.7 {for tests} { catch {for 1 2 3 4 5} msg } {1} test for-old-1.8 {for tests} { set a {xyz} for {set i 1} {$i<6} {set i [expr $i+1]} {} set a } xyz test for-old-1.9 {for tests} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]; if $i==4 break} { set a [concat $a $i] } set a } {1 2 3} testreport openocd-0.9.0/jimtcl/tests/while.test0000644000175000017500000000567712315602575014552 00000000000000# Commands covered: while # # This file contains the original set of tests for Tcl's while command. # Since the while command is now compiled, a new set of tests covering # the new implementation is in the file "while.test". Sourcing this file # into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: while-old.test,v 1.6 2000/04/10 17:19:06 ericm Exp $ source [file dirname [info script]]/testing.tcl test while-old-1.1 {basic while loops} { set count 0 while {$count < 10} {set count [expr $count+1]} set count } 10 test while-old-1.2 {basic while loops} { set value xxx while {2 > 3} {set value yyy} set value } xxx test while-old-1.3 {basic while loops} { set value 1 while {1} { incr value; if {$value > 5} { break; } } set value } 6 test while-old-1.4 {basic while loops, multiline test expr} { set value 1 while {($tcl_platform(platform) != "foobar1") && \ ($tcl_platform(platform) != "foobar2")} { incr value break } set value } {2} test while-old-1.5 {basic while loops, test expr in quotes} { set value 1 while "0 < 3" {set value 2; break} set value } {2} test while-old-2.1 {continue in while loop} { set list {1 2 3 4 5} set index 0 set result {} while {$index < 5} { if {$index == 2} {set index [expr $index+1]; continue} set result [concat $result [lindex $list $index]] set index [expr $index+1] } set result } {1 2 4 5} test while-old-3.1 {break in while loop} { set list {1 2 3 4 5} set index 0 set result {} while {$index < 5} { if {$index == 3} break set result [concat $result [lindex $list $index]] set index [expr $index+1] } set result } {1 2 3} test while-old-4.1 {errors in while loops} { set err [catch {while} msg] list $err } {1} test while-old-4.2 {errors in while loops} { set err [catch {while 1} msg] list $err } {1} test while-old-4.3 {errors in while loops} { set err [catch {while 1 2 3} msg] list $err } {1} test while-old-4.4 {errors in while loops} { set err [catch {while {"a"+"b"} {error "loop aborted"}} msg] list $err } {1} test while-old-4.5 {errors in while loops} { catch {unset x} set x 1 set err [catch {while {$x} {set x foo}} msg] list $err } {1} test while-old-4.6 {errors in while loops} { set err [catch {while {1} {error "loop aborted"}} msg] list $err $msg } {1 {loop aborted}} test while-old-5.1 {while return result} { while {0} {set a 400} } {} test while-old-5.2 {while return result} { set x 1 while {$x} {set x 0} } {} # cleanup testreport openocd-0.9.0/jimtcl/tests/pid.test0000644000175000017500000000350012516456445014203 00000000000000# Commands covered: pid # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1995 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: pid.test,v 1.6 2000/04/10 17:19:03 ericm Exp $ source [file dirname [info script]]/testing.tcl needs cmd pid posix needs cmd exec catch {package require regexp} testConstraint regexp [expr {[info commands regexp] ne {}}] testConstraint socket [expr {[info commands socket] ne {}}] testConstraint getpid [expr {[catch pid] == 0}] # This is a proxy for tcl || tclcompat testConstraint pidchan [expr {[info commands fconfigure] ne {}}] file delete test1 test pid-1.1 {pid command} {regexp getpid} { regexp {(^[0-9]+$)|(^0x[0-9a-fA-F]+$)} [pid] } 1 test pid-1.2 {pid command} {regexp socket pidchan} { set f [open {| echo foo | cat >test1} w] set pids [pid $f] close $f catch {removeFile test1} list [llength $pids] [regexp {^[0-9]+$} [lindex $pids 0]] \ [regexp {^[0-9]+$} [lindex $pids 1]] \ [expr {[lindex $pids 0] == [lindex $pids 1]}] } {2 1 1 0} test pid-1.3 {pid command} {socket pidchan} { set f [open test1 w] set pids [pid $f] close $f set pids } {} test pid-1.4 {pid command} pidchan { list [catch {pid a b} msg] $msg } {1 {wrong # args: should be "pid ?channelId?"}} test pid-1.5 {pid command} pidchan { list [catch {pid gorp} msg] $msg } {1 {can not find channel named "gorp"}} # cleanup file delete test1 testreport openocd-0.9.0/jimtcl/tests/filejoin.test0000644000175000017500000000311112315602575015216 00000000000000source [file dirname [info script]]/testing.tcl needs cmd file test join-1.1 "One name" { file join abc } {abc} test join-1.2 "One name with trailing slash" { file join abc/ } {abc} test join-1.3 "One name with leading slash" { file join /abc } {/abc} test join-1.4 "One name with leading and trailing slash" { file join /abc/ } {/abc} test join-1.5 "Two names" { file join abc def } {abc/def} test join-1.6 "Two names with dir trailing slash" { file join abc/ def } {abc/def} test join-1.7 "Two names with dir leading slash" { file join /abc def } {/abc/def} test join-1.8 "Two names with dir leading and trailing slash" { file join /abc/ def } {/abc/def} test join-1.9 "Two names with file trailing slash" { file join abc def/ } {abc/def} test join-1.10 "Two names with file leading slash" { file join abc /def } {/def} test join-1.11 "Two names with file leading and trailing slash" { file join abc /def/ } {/def} test join-1.12 "Two names with double slashes" { file join abc/ /def } {/def} test join-1.13 "Join to root" { file join / abc } {/abc} test join-1.14 "Join to root" { set dir [file join / .] # Either / or /. is OK here expr {$dir in {/ /.}} } 1 test join-1.15 "Join to root" { file join / / } {/} test join-1.16 "Join to root" { file join /abc / } {/} test join-2.1 "Dir is empty string" { file join "" def } {def} test join-2.2 "File is empty string" { file join abc "" } {abc} test join-2.3 "Path too long" jim { set components [string repeat {abcdefghi } 500] list [catch [concat file join $components] msg] $msg } {1 {Path too long}} testreport openocd-0.9.0/jimtcl/tests/stringmatch.test0000644000175000017500000001405012315602575015746 00000000000000# This file is a Tcl script to test the code in the file tclUtil.c. # This file is organized in the standard fashion for Tcl tests. # # Copyright (c) 1995-1998 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: util.test,v 1.7.2.1 2001/07/16 23:14:13 hobbs Exp $ source [file dirname [info script]]/testing.tcl test stringmatch-5.1 {Tcl_StringMatch} { string match ab*c abc } 1 test stringmatch-5.2 {Tcl_StringMatch} { string match ab**c abc } 1 test stringmatch-5.3 {Tcl_StringMatch} { string match ab* abcdef } 1 test stringmatch-5.4 {Tcl_StringMatch} { string match *c abc } 1 test stringmatch-5.5 {Tcl_StringMatch} { string match *3*6*9 0123456789 } 1 test stringmatch-5.6 {Tcl_StringMatch} { string match *3*6*9 01234567890 } 0 test stringmatch-5.7 {Tcl_StringMatch: UTF-8} { string match *u \u4e4fu } 1 test stringmatch-5.8 {Tcl_StringMatch} { string match a?c abc } 1 test stringmatch-5.9 {Tcl_StringMatch: UTF-8} utf8 { # skip one character in string string match a?c a\u4e4fc } 1 test stringmatch-5.10 {Tcl_StringMatch} { string match a??c abc } 0 test stringmatch-5.11 {Tcl_StringMatch} { string match ?1??4???8? 0123456789 } 1 test stringmatch-5.12 {Tcl_StringMatch} { string match {[abc]bc} abc } 1 test stringmatch-5.13 {Tcl_StringMatch: UTF-8} utf8 { # string += Tcl_UtfToUniChar(string, &ch); string match "\[\u4e4fxy\]bc" "\u4e4fbc" } 1 test stringmatch-5.14 {Tcl_StringMatch} { # if ((*pattern == ']') || (*pattern == '\0')) # badly formed pattern string match {[]} {[]} } 0 test stringmatch-5.15 {Tcl_StringMatch} { # if ((*pattern == ']') || (*pattern == '\0')) # badly formed pattern string match {[} {[} } 0 test stringmatch-5.16 {Tcl_StringMatch} { string match {a[abc]c} abc } 1 test stringmatch-5.17 {Tcl_StringMatch: UTF-8} utf8 { # pattern += Tcl_UtfToUniChar(pattern, &endChar); # get 1 UTF-8 character string match "a\[a\u4e4fc]c" "a\u4e4fc" } 1 test stringmatch-5.18 {Tcl_StringMatch: UTF-8} { # pattern += Tcl_UtfToUniChar(pattern, &endChar); # proper advance: wrong answer would match on UTF trail byte of \u4e4f string match {a[a\u4e4fc]c} a\u008fc } 0 test stringmatch-5.19 {Tcl_StringMatch: UTF-8} { # pattern += Tcl_UtfToUniChar(pattern, &endChar); # proper advance. string match {a[a\u4e4fc]c} "acc" } 1 test stringmatch-5.20 {Tcl_StringMatch} { string match {a[xyz]c} abc } 0 test stringmatch-5.21 {Tcl_StringMatch} { string match {12[2-7]45} 12345 } 1 test stringmatch-5.22 {Tcl_StringMatch: UTF-8 range} { string match "\[\u4e00-\u4e4f]" "0" } 0 test stringmatch-5.23 {Tcl_StringMatch: UTF-8 range} utf8 { string match "\[\u4e00-\u4e4f]" "\u4e33" } 1 test stringmatch-5.24 {Tcl_StringMatch: UTF-8 range} utf8 { string match "\[\u4e00-\u4e4f]" "\uff08" } 0 test stringmatch-5.25 {Tcl_StringMatch} { string match {12[ab2-4cd]45} 12345 } 1 test stringmatch-5.26 {Tcl_StringMatch} { string match {12[ab2-4cd]45} 12b45 } 1 test stringmatch-5.27 {Tcl_StringMatch} { string match {12[ab2-4cd]45} 12d45 } 1 test stringmatch-5.28 {Tcl_StringMatch} { string match {12[ab2-4cd]45} 12145 } 0 test stringmatch-5.29 {Tcl_StringMatch} { string match {12[ab2-4cd]45} 12545 } 0 test stringmatch-5.30 {Tcl_StringMatch: forwards range} { string match {[k-w]} "z" } 0 test stringmatch-5.31 {Tcl_StringMatch: forwards range} { string match {[k-w]} "w" } 1 test stringmatch-5.32 {Tcl_StringMatch: forwards range} { string match {[k-w]} "r" } 1 test stringmatch-5.33 {Tcl_StringMatch: forwards range} { string match {[k-w]} "k" } 1 test stringmatch-5.34 {Tcl_StringMatch: forwards range} { string match {[k-w]} "a" } 0 test stringmatch-5.35 {Tcl_StringMatch: reverse range} { string match {[w-k]} "z" } 0 test stringmatch-5.36 {Tcl_StringMatch: reverse range} { string match {[w-k]} "w" } 1 test stringmatch-5.37 {Tcl_StringMatch: reverse range} { string match {[w-k]} "r" } 1 test stringmatch-5.38 {Tcl_StringMatch: reverse range} { string match {[w-k]} "k" } 1 test stringmatch-5.39 {Tcl_StringMatch: reverse range} { string match {[w-k]} "a" } 0 test stringmatch-5.40 {Tcl_StringMatch: skip correct number of ']'} { string match {[A-]x} Ax } 0 test stringmatch-5.41 {Tcl_StringMatch: skip correct number of ']'} { string match {[A-]]x} Ax } 1 test stringmatch-5.42 {Tcl_StringMatch: skip correct number of ']'} { string match {[A-]]x} \ue1x } 0 test stringmatch-5.43 {Tcl_StringMatch: skip correct number of ']'} utf8 { string match \[A-]\ue1]x \ue1x } 1 test stringmatch-5.44 {Tcl_StringMatch: skip correct number of ']'} { string match {[A-]h]x} hx } 1 test stringmatch-5.45 {Tcl_StringMatch} { # if (*pattern == '\0') # badly formed pattern, still treats as a set string match {[a} a } 1 test stringmatch-5.46 {Tcl_StringMatch} { string match {a\*b} a*b } 1 test stringmatch-5.47 {Tcl_StringMatch} { string match {a\*b} ab } 0 test stringmatch-5.48 {Tcl_StringMatch} { string match {a\*\?\[\]\\\x} "a*?\[\]\\x" } 1 test stringmatch-5.49 {Tcl_StringMatch} { string match ** "" } 1 test stringmatch-5.50 {Tcl_StringMatch} { string match *. "" } 0 test stringmatch-5.51 {Tcl_StringMatch} { string match "" "" } 1 # 'string match' doesn't support ^, which is different # from 'scan' test stringmatch-6.1 {bracket in charset} { string match {a[]b]c} {a]c} } 0 test stringmatch-6.2 {bracket in charset} { string match {a[]b]c} {abc} } 0 test stringmatch-6.3 {charset with ^} { string match {a[^]b]c} {axc} } 0 test stringmatch-6.4 {charset with ^} { string match {a[^]b]c} {a]c} } 0 test stringmatch-6.5 {charset with ^} { string match {a[^bc]d} {axd} } 0 test stringmatch-6.6 {charset with ^} { string match {a[\]]c} {a]c} } 0 test stringmatch=7.1 {short string with ?} { string match {ab?} ab } 0 test stringmatch=7.1 {multiple * to end} { string match {ab**} ab } 1 testreport openocd-0.9.0/jimtcl/tests/expand.test0000644000175000017500000000072112315602575014702 00000000000000source [file dirname [info script]]/testing.tcl test expand-1.1 "Basic tests" { set a {1 2 3} set b {4 5 6} lappend a {*}$b } {1 2 3 4 5 6} test expand-1.2 "Basic tests" jim { set a {1 2 3} set b {4 5 6} lappend a {expand}$b } {1 2 3 4 5 6} test expand-1.3 "Basic tests" { set a {1 2 3} set b {4 5 6} lappend a *$b } {1 2 3 {*4 5 6}} test expand-1.4 "Basic tests" { set a {1 2 3} set b {4 5 6} lappend a expand$b } {1 2 3 {expand4 5 6}} testreport openocd-0.9.0/jimtcl/tests/regmin.test0000644000175000017500000000241112315602575014702 00000000000000source [file dirname [info script]]/testing.tcl needs cmd regexp testConstraint regexp_are [regexp {\d} 1] needs constraint regexp_are test regexpmin-1.1 {Minimal +} { regexp -inline {x(a|b|c)+?c} xabcabc } {xabc b} test regexpmin-1.2 {Maximal +} { regexp -inline {x(a|b|c)+c} xabcabc } {xabcabc b} test regexpmin-1.3 {Minimal *} { regexp -inline {x(a|b)*?} xababcabc } {x {}} test regexpmin-1.4 {Maximal *} { regexp -inline {x(a|b)*} xababcabc } {xabab b} test regexpmin-1.5 {Maximal ?} { regexp -inline {x(a|b)?} xababcabc } {xa a} test regexpmin-1.6 {Minimal ?} { regexp -inline {x(a|b)??} xababcabc } {x {}} test regexpmin-1.7 {Maximal html} { regexp -inline {<(.+)>} } { foo>} } { foo} test regexpmin-2.1 {utf8 repeat} utf8 { regexp -inline {a\u00df+} a\udf\udf\udf\udf\ub5z } "a\udf\udf\udf\udf" test regexpmin-2.2 {utf8 min repeat} utf8 { regexp -inline {a\u00df+?} a\udf\udf\udf\udf\ub5z } "a\udf" test regexpmin-3.1 {non-capturing paren} { regexp -inline {x(?:a|b)?} xababcabc } {xa} test regexpmin-3.2 {non-capturing paren} { regexp -inline {x(?:a|b)?.*(b|c)} xababcabc } {xababcabc c} testreport openocd-0.9.0/jimtcl/tests/filedir.test0000644000175000017500000000242612315602575015045 00000000000000source [file dirname [info script]]/testing.tcl needs cmd file needs cmd exec catch { exec rm -rf tmp exec mkdir tmp exec touch tmp/file exec mkdir tmp/dir } test mkdir-1.1 "Simple dir" { file mkdir tmp/abc file isdir tmp/abc } {1} test mkdir-1.2 "Create missing parents" { file mkdir tmp/def/ghi/jkl file isdir tmp/def/ghi/jkl } {1} test mkdir-1.3 "Existing dir" { file mkdir tmp/dir file isdir tmp/dir } {1} test mkdir-1.4 "Child of existing dir" { file mkdir tmp/dir/child file isdir tmp/dir/child } {1} test mkdir-1.5 "Create dir over existing file" { list [catch {file mkdir tmp/file} msg] [file isdir tmp/file] } {1 0} test mkdir-1.6 "Create dir below existing file" { list [catch {file mkdir tmp/file/dir} msg] [file isdir tmp/file/dir] } {1 0} test mkdir-1.8 "Multiple dirs" { file mkdir tmp/1 tmp/2 tmp/3 list [file isdir tmp/1] [file isdir tmp/2] [file isdir tmp/3] } {1 1 1} test mkdir-1.7 "Stop on failure" { catch {file mkdir tmp/4 tmp/file tmp/5} list [file isdir tmp/4] [file isdir tmp/5] } {1 0} test rmdir-2.0 "Remove existing dir" { file delete tmp/1 file isdir tmp/1 } {0} test rmdir-2.1 "Remove missing dir" { file delete tmp/1 } {} test rmdir-2.2 "Remove non-empty dir" { catch {file delete tmp/def} } {1} catch { exec rm -rf tmp } testreport openocd-0.9.0/jimtcl/tests/format.test0000644000175000017500000004421512516456444014726 00000000000000# Commands covered: format # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1994 The Regents of the University of California. # Copyright (c) 1994-1998 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: format.test,v 1.8 2000/04/10 17:18:59 ericm Exp $ source [file dirname [info script]]/testing.tcl needs cmd format # The following code is needed because some versions of SCO Unix have # a round-off error in sprintf which would cause some of the tests to # fail. Someday I hope this code shouldn't be necessary (code added # 9/9/91). set roundOffBug 0 if {"[format %7.1e 68.514]" == "6.8e+01"} { puts stdout "Note: this system has a sprintf round-off bug, some tests skipped\n" set roundOffBug 1 } test format-1.1 {integer formatting} { format "%*d %d %d %d" 6 34 16923 -12 -1 } { 34 16923 -12 -1} test format-1.2 {integer formatting} { format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12 } { 6 34 16923 -12 -1 0xe 0XC} # %u output depends on word length, so this test is not portable. test format-1.3 {integer formatting} { format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0 } { 6 34 16923 18446744073709551604 -1 0} test format-1.4 {integer formatting} { format "%-4d %-4i %-4d %-4ld" 6 34 16923 -12 -1 } {6 34 16923 -12 } test format-1.5 {integer formatting} { format "%04d %04d %04d %04i" 6 34 16923 -12 -1 } {0006 0034 16923 -012} test format-1.6 {integer formatting} { format "%00*d" 6 34 } {000034} # Printing negative numbers in hex or octal format depends on word # length, so these tests are not portable. test format-1.7 {integer formatting} { format "%4x %4x %4x %4x" 6 34 16923 -12 -1 } { 6 22 421b fffffffffffffff4} test format-1.8 {integer formatting} { format "%#x %#X %#X %#x" 6 34 16923 -12 -1 } {0x6 0X22 0X421B 0xfffffffffffffff4} test format-1.9 {integer formatting} { format "%#20x %#20x %#20x %#20x" 6 34 16923 -12 -1 } { 0x6 0x22 0x421b 0xfffffffffffffff4} test format-1.10 {integer formatting} { format "%-#20x %-#20x %-#20x %-#20x" 6 34 16923 -12 -1 } {0x6 0x22 0x421b 0xfffffffffffffff4 } test format-1.11 {integer formatting} { format "%-#20o %#-20o %#-20o %#-20o" 6 34 16923 -12 -1 } {06 042 041033 01777777777777777777764} test format-1.12 {no sign extend large 32 bit values} { format %x 0xa0000000 } {a0000000} test format-2.1 {string formatting} { format "%s %s %c %s" abcd {This is a very long test string.} 120 x } {abcd This is a very long test string. x x} test format-2.2 {string formatting} { format "%20s %20s %20c %20s" abcd {This is a very long test string.} 120 x } { abcd This is a very long test string. x x} test format-2.3 {string formatting} { format "%.10s %.10s %c %.10s" abcd {This is a very long test string.} 120 x } {abcd This is a x x} test format-2.4 {string formatting} { format "%s %s %% %c %s" abcd {This is a very long test string.} 120 x } {abcd This is a very long test string. % x x} test format-2.5 {string formatting, embedded nulls} { format "%10s" abc\0def } " abc\0def" test format-2.6 {string formatting, international chars} utf8 { format "%10s" abc\ufeffdef } " abc\ufeffdef" test format-2.6 {string formatting, international chars} utf8 { format "%.5s" abc\ufeffdef } "abc\ufeffd" test format-2.7 {string formatting, international chars} { format "foo\ufeffbar%s" baz } "foo\ufeffbarbaz" test format-2.8 {string formatting, width} { format "a%5sa" f } "a fa" test format-2.8 {string formatting, width} { format "a%-5sa" f } "af a" test format-2.8 {string formatting, width} { format "a%2sa" foo } "afooa" test format-2.8 {string formatting, width} { format "a%0sa" foo } "afooa" test format-2.8 {string formatting, precision} { format "a%.2sa" foobarbaz } "afoa" test format-2.8 {string formatting, precision} { format "a%.sa" foobarbaz } "aa" test format-2.8 {string formatting, precision} { list [catch {format "a%.-2sa" foobarbaz} msg] $msg } {1 {bad field specifier "-"}} test format-2.8 {string formatting, width and precision} { format "a%5.2sa" foobarbaz } "a foa" test format-2.8 {string formatting, width and precision} { format "a%5.7sa" foobarbaz } "afoobarba" test format-3.1 {Tcl_FormatObjCmd: character formatting} utf8 { format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 65 65 65 65 65 65 3 65 -4 65 } "|A|A|A|A|A | A| A|A |" test format-3.2 {Tcl_FormatObjCmd: international character formatting} utf8 { format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xa2 0x4e4e 0x25a 0xc3 0xff08 0 3 0x6575 -4 0x4e4f } "|\ua2|\u4e4e|\u25a|\uc3|\uff08 | \0| \u6575|\u4e4f |" test format-4.1 {e and f formats} -body { format "%e %e %e %e" 34.2e12 68.514 -.125 -16000. .000053 } -match regexp -result {3.420000e\+0?13 6.851400e\+0?01 -1.250000e-0?01 -1.600000e\+0?04} test format-4.2 {e and f formats} -body { format "%20e %20e %20e %20e" 34.2e12 68.514 -.125 -16000. .000053 } -match regexp -result {( 3.420000e\+13 6.851400e\+01 -1.250000e-01 -1.600000e\+04| 3.420000e\+013 6.851400e\+001 -1.250000e-001 -1.600000e\+004)} test format-4.3 {e and f formats} -body { format "%.1e %.1e %.1e %.1e" 34.2e12 68.514 -.126 -16000. .000053 } -match regexp -result {3.4e\+0?13 6.9e\+0?01 -1.3e-0?01 -1.6e\+0?04} test format-4.4 {e and f formats} -body { format "%020e %020e %020e %020e" 34.2e12 68.514 -.126 -16000. .000053 } -match regexp -result {(000000003.420000e\+13 000000006.851400e\+01 -00000001.260000e-01 -00000001.600000e\+04|00000003.420000e\+013 00000006.851400e\+001 -0000001.260000e-001 -0000001.600000e\+004)} test format-4.5 {e and f formats} -body { format "%7.1e %7.1e %7.1e %7.1e" 34.2e12 68.514 -.126 -16000. .000053 } -match regexp -result {3.4e\+0?13 6.9e\+0?01 -1.3e-0?01 -1.6e\+0?04} test format-4.6 {e and f formats} { format "%f %f %f %f" 34.2e12 68.514 -.125 -16000. .000053 } {34200000000000.000000 68.514000 -0.125000 -16000.000000} test format-4.7 {e and f formats} { format "%.4f %.4f %.4f %.4f %.4f" 34.2e12 68.514 -.125 -16000. .000053 } {34200000000000.0000 68.5140 -0.1250 -16000.0000 0.0001} test format-4.8 {e and f formats} -body { format "%.4e %.5e %.6e" -9.99996 -9.99996 9.99996 } -match regexp -result {\-1.0000e\+0?01 -9.99996e\+0?00 9.999960e\+0?00} test format-4.9 {e and f formats} { format "%.4f %.5f %.6f" -9.99996 -9.99996 9.99996 } {-10.0000 -9.99996 9.999960} test format-4.10 {e and f formats} { format "%20f %-20f %020f" -9.99996 -9.99996 9.99996 } { -9.999960 -9.999960 0000000000009.999960} test format-4.11 {e and f formats} { format "%-020f %020f" -9.99996 -9.99996 9.99996 } {-9.999960 -000000000009.999960} test format-4.12 {e and f formats} -body { format "%.0e %#.0e" -9.99996 -9.99996 9.99996 } -match regexp -result {\-1e\+0?01 -1.e\+0?01} test format-4.13 {e and f formats} { format "%.0f %#.0f" -9.99996 -9.99996 9.99996 } {-10 -10.} test format-4.14 {e and f formats} { format "%.4f %.5f %.6f" -9.99996 -9.99996 9.99996 } {-10.0000 -9.99996 9.999960} test format-4.15 {e and f formats} { format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001 } { 1 1 1 1} test format-4.16 {e and f formats} { format "%3.1f %3.1f %3.1f %3.1f" 0.0 0.1 0.01 0.001 } {0.0 0.1 0.0 0.0} test format-5.1 {g-format} -body { format "%.3g" 12341.0 } -match regexp -result {1.23e\+0?04} test format-5.2 {g-format} -body { format "%.3G" 1234.12345 } -match regexp -result {1.23E\+0?03} test format-5.3 {g-format} { format "%.3g" 123.412345 } {123} test format-5.4 {g-format} { format "%.3g" 12.3412345 } {12.3} test format-5.5 {g-format} { format "%.3g" 1.23412345 } {1.23} test format-5.6 {g-format} { format "%.3g" 1.23412345 } {1.23} test format-5.7 {g-format} { format "%.3g" .123412345 } {0.123} test format-5.8 {g-format} { format "%.3g" .012341 } {0.0123} test format-5.9 {g-format} { format "%.3g" .0012341 } {0.00123} test format-5.10 {g-format} { format "%.3g" .00012341 } {0.000123} test format-5.11 {g-format} -body { format "%.3g" .00001234 } -match regexp -result {1.23e-0?05} test format-5.12 {g-format} -body { format "%.4g" 9999.6 } -match regexp -result {1e\+0?04} test format-5.13 {g-format} { format "%.4g" 999.96 } {1000} test format-5.14 {g-format} { format "%.3g" 1.0 } {1} test format-5.15 {g-format} { format "%.3g" .1 } {0.1} test format-5.16 {g-format} { format "%.3g" .01 } {0.01} test format-5.17 {g-format} { format "%.3g" .001 } {0.001} test format-5.18 {g-format} -body { format "%.3g" .00001 } -match regexp -result {1e-0?05} test format-5.19 {g-format} -body { format "%#.3g" 1234.0 } -match regexp -result {1.23e\+0?03} test format-5.20 {g-format} -body { format "%#.3G" 9999.5 } -match regexp -result {1.00E\+0?04} test format-6.1 {floating-point zeroes} -body { format "%e %f %g" 0.0 0.0 0.0 0.0 } -match regexp -result {0.000000e\+0?00 0.000000 0} test format-6.2 {floating-point zeroes} -body { format "%.4e %.4f %.4g" 0.0 0.0 0.0 0.0 } -match regexp -result {0.0000e\+0?00 0.0000 0} test format-6.3 {floating-point zeroes} -body { format "%#.4e %#.4f %#.4g" 0.0 0.0 0.0 0.0 } -match regexp -result {0.0000e\+0?00 0.0000 0.000} test format-6.4 {floating-point zeroes} -body { format "%.0e %.0f %.0g" 0.0 0.0 0.0 0.0 } -match regexp -result {0e\+0?00 0 0} test format-6.5 {floating-point zeroes} -body { format "%#.0e %#.0f %#.0g" 0.0 0.0 0.0 0.0 } -match regexp -result {0.e\+0?00 0. 0.} test format-6.6 {floating-point zeroes} { format "%3.0f %3.0f %3.0f %3.0f" 0.0 0.0 0.0 0.0 } { 0 0 0 0} test format-6.7 {floating-point zeroes} { format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001 } { 1 1 1 1} test format-6.8 {floating-point zeroes} { format "%3.1f %3.1f %3.1f %3.1f" 0.0 0.1 0.01 0.001 } {0.0 0.1 0.0 0.0} test format-7.1 {various syntax features} { format "%*.*f" 12 3 12.345678901 } { 12.346} test format-7.2 {various syntax features} { format "%0*.*f" 12 3 12.345678901 } {00000012.346} test format-7.3 {various syntax features} { format "\*\t\\n" } {* \n} test format-8.1 {error conditions} { catch format } 1 test format-8.2 {error conditions} jim { catch format msg set msg } {wrong # args: should be "format formatString ?arg arg ...?"} test format-8.3 {error conditions} { catch {format %*d} } 1 test format-8.4 {error conditions} { catch {format %*d} msg set msg } {not enough arguments for all format specifiers} test format-8.5 {error conditions} { catch {format %*.*f 12} } 1 test format-8.6 {error conditions} { catch {format %*.*f 12} msg set msg } {not enough arguments for all format specifiers} test format-8.7 {error conditions} { catch {format %*.*f 12 3} } 1 test format-8.8 {error conditions} { catch {format %*.*f 12 3} msg set msg } {not enough arguments for all format specifiers} test format-8.9 {error conditions} { list [catch {format %*d x 3} msg] $msg } {1 {expected integer but got "x"}} test format-8.10 {error conditions} { list [catch {format %*.*f 2 xyz 3} msg] $msg } {1 {expected integer but got "xyz"}} test format-8.11 {error conditions} { catch {format %d 2a} } 1 test format-8.12 {error conditions} { catch {format %d 2a} msg set msg } {expected integer but got "2a"} test format-8.13 {error conditions} { catch {format %c 2x} } 1 test format-8.14 {error conditions} { catch {format %c 2x} msg set msg } {expected integer but got "2x"} test format-8.15 {error conditions} { catch {format %f 2.1z} } 1 test format-8.16 {error conditions} jim { catch {format %f 2.1z} msg set msg } {expected floating-point number but got "2.1z"} test format-8.17 {error conditions} { catch {format ab%} } 1 test format-8.18 {error conditions} { catch {format ab% 12} msg set msg } {format string ended in middle of field specifier} test format-8.19 {error conditions} { catch {format %q x} } 1 test format-8.20 {error conditions} { catch {format %q x} msg set msg } {bad field specifier "q"} test format-8.21 {error conditions} { catch {format %d} } 1 test format-8.22 {error conditions} { catch {format %d} msg set msg } {not enough arguments for all format specifiers} test format-8.23 {error conditions} { catch {format "%d %d" 24 xyz} msg set msg } {expected integer but got "xyz"} test format-9.1 {long result} { set a {1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} format {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG %s %s} $a $a } {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} test format-10.1 {"h" format specifier} { format %hd 0xffff } -1 test format-10.2 {"h" format specifier} { format %hx 0x10fff } fff test format-10.3 {"h" format specifier} { format %hd 0x10000 } 0 test format-11.1 {XPG3 %$n specifiers} { format {%2$d %1$d} 4 5 } {5 4} test format-11.2 {XPG3 %$n specifiers} { format {%2$d %1$d %1$d %3$d} 4 5 6 } {5 4 4 6} test format-11.3 {XPG3 %$n specifiers} { list [catch {format {%2$d %3$d} 4 5} msg] $msg } {1 {"%n$" argument index out of range}} test format-11.4 {XPG3 %$n specifiers} { list [catch {format {%2$d %0$d} 4 5 6} msg] $msg } {1 {"%n$" argument index out of range}} test format-11.5 {XPG3 %$n specifiers} { list [catch {format {%d %1$d} 4 5 6} msg] $msg } {1 {cannot mix "%" and "%n$" conversion specifiers}} test format-11.6 {XPG3 %$n specifiers} { list [catch {format {%2$d %d} 4 5 6} msg] $msg } {1 {cannot mix "%" and "%n$" conversion specifiers}} test format-11.7 {XPG3 %$n specifiers} { list [catch {format {%2$d %3d} 4 5 6} msg] $msg } {1 {cannot mix "%" and "%n$" conversion specifiers}} test format-11.8 {XPG3 %$n specifiers} { format {%2$*d %3$d} 1 10 4 } { 4 4} test format-11.9 {XPG3 %$n specifiers} { format {%2$.*s %4$d} 1 5 abcdefghijklmnop 44 } {abcde 44} test format-11.10 {XPG3 %$n specifiers} { list [catch {format {%2$*d} 4} msg] $msg } {1 {"%n$" argument index out of range}} test format-11.11 {XPG3 %$n specifiers} { list [catch {format {%2$*d} 4 5} msg] $msg } {1 {"%n$" argument index out of range}} test format-11.12 {XPG3 %$n specifiers} { list [catch {format {%2$*d} 4 5 6} msg] $msg } {0 { 6}} test format-12.1 {negative width specifiers} { format "%*d" -47 25 } {25 } test format-13.1 {tcl_precision fuzzy comparison} { catch {unset a} catch {unset b} catch {unset c} catch {unset d} set a 0.0000000000001 set b 0.00000000000001 set c 0.00000000000000001 set d [expr $a + $b + $c] format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d } {0.0000000000 0.000000000000 0.000000000000110 0.00000000000011001} test format-13.2 {tcl_precision fuzzy comparison} { catch {unset a} catch {unset b} catch {unset c} catch {unset d} set a 0.000000000001 set b 0.000000000000005 set c 0.0000000000000008 set d [expr $a + $b + $c] format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d } {0.0000000000 0.000000000001 0.000000000001006 0.00000000000100580} test format-13.3 {tcl_precision fuzzy comparison} { catch {unset a} catch {unset b} catch {unset c} set a 0.00000000000099 set b 0.000000000000011 set c [expr $a + $b] format {%0.10f %0.12f %0.15f %0.17f} $c $c $c $c } {0.0000000000 0.000000000001 0.000000000001001 0.00000000000100100} test format-13.4 {tcl_precision fuzzy comparison} { catch {unset a} catch {unset b} catch {unset c} set a 0.444444444444 set b 0.33333333333333 set c [expr $a + $b] format {%0.10f %0.12f %0.15f %0.16f} $c $c $c $c } {0.7777777778 0.777777777777 0.777777777777330 0.7777777777773300} test format-13.5 {tcl_precision fuzzy comparison} { catch {unset a} catch {unset b} catch {unset c} set a 0.444444444444 set b 0.99999999999999 set c [expr $a + $b] format {%0.10f %0.12f %0.15f} $c $c $c } {1.4444444444 1.444444444444 1.444444444443990} test format-14.1 {testing MAX_FLOAT_SIZE for 0 and 1} { format {%s} "" } {} test format-14.2 {testing MAX_FLOAT_SIZE for 0 and 1} { format {%s} "a" } {a} test format-15.1 {testing %0..s 0 padding for chars/strings} { format %05s a } {0000a} test format-15.2 {testing %0..s 0 padding for chars/strings} { format "% 5s" a } { a} test format-15.3 {testing %0..s 0 padding for chars/strings} { format %5s a } { a} test format-15.4 {testing %0..s 0 padding for chars/strings} { format %05c 61 } {0000=} set a "0123456789" set b "" for {set i 0} {$i < 290} {incr i} { append b $a } for {set i 290} {$i < 400} {incr i} { test format-15.[expr $i -290] {testing MAX_FLOAT_SIZE} { format {%s} $b } $b append b "x" } test format-16.1 {format %b} { format %b 0 } {0} test format-16.2 {format %b} { format %b 1 } {1} test format-16.3 {format %b} { format %b 0xf } {1111} test format-16.4 {format %b} { format %b 1234567 } {100101101011010000111} # cleanup catch {unset a} catch {unset b} catch {unset c} catch {unset d} testreport openocd-0.9.0/jimtcl/tests/tailcall.test0000644000175000017500000000403212516456445015215 00000000000000# vim:se syntax=tcl: source [file dirname [info script]]/testing.tcl needs cmd tailcall needs cmd try tclcompat test tailcall-1.1 {Basic tailcall} { # Demo -- a tail-recursive factorial function proc fac {x {val 1}} { if {$x <= 2} { expr {$x * $val} } else { tailcall fac [expr {$x -1}] [expr {$x * $val}] } } fac 10 } {3628800} test tailcall-1.2 {Tailcall in try} { set x 0 proc a {} { upvar x x; incr x } proc b {} { upvar x x; incr x 4; try { tailcall a } finally { incr x 8 }} b set x } {13} test tailcall-1.3 {Tailcall does return} { set x 0 proc a {} { upvar x x; incr x } proc b {} { upvar x x; incr x 4; tailcall a; incr x 8} b set x } {5} test tailcall-1.5 {interaction of uplevel and tailcall} { proc a {cmd} { tailcall $cmd } proc b {} { lappend result [uplevel 1 a c] lappend result [uplevel 1 a c] } proc c {} { return c } a b } {c c} test tailcall-1.6 {tailcall pass through return} { proc a {script} { # return from $script should pass through back to the caller tailcall foreach i {1 2 3} $script } proc b {} { a {return ok} # Should not get here return bad } b } {ok} test tailcall-1.7 {tailcall with namespaces} jim { proc a::b {} { proc c {} { return 1 } set d [local lambda {} { c }] # $d should resolve in namespace 'a', not "" tailcall $d } a::b } 1 test tailcall-1.8 {tailcall with local} jim { proc a {} { tailcall [local proc b {} { return c }] } a } {c} test tailcall-1.9 {tailcall with large number of invocations} { proc a {n} { if {$n == 0} { return 1 } incr n -1 tailcall a $n } a 1000 } 1 test tailcall-1.10 {tailcall through uplevel} { proc a {} { tailcall b } proc b {} { uplevel 1 c } proc c {} { tailcall d } proc d {} { return [info level] } a } 1 test tailcall-1.11 {chained tailcall} { proc a {} { b } proc b {} { tailcall tailcall c } proc c {} { return [info level] } a } 1 test tailcall-1.12 {uplevel tailcall} { proc a {} { b } proc b {} { uplevel 1 tailcall c } proc c {} { return [info level] } a } 1 testreport openocd-0.9.0/jimtcl/tests/scan.test0000644000175000017500000005563112315602575014361 00000000000000# Commands covered: scan # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1994 The Regents of the University of California. # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: scan.test,v 1.10.2.2 2002/02/07 01:54:04 hobbs Exp $ source [file dirname [info script]]/testing.tcl needs cmd scan test scan-1.1 {BuildCharSet, CharInSet} { list [scan foo {%[^o]} x] $x } {1 f} test scan-1.2 {BuildCharSet, CharInSet} { list [scan \]foo {%[]f]} x] $x } {1 \]f} test scan-1.3 {BuildCharSet, CharInSet} { list [scan abc-def {%[a-c]} x] $x } {1 abc} test scan-1.4 {BuildCharSet, CharInSet} { list [scan abc-def {%[a-c]} x] $x } {1 abc} test scan-1.5 {BuildCharSet, CharInSet} { list [scan -abc-def {%[-ac]} x] $x } {1 -a} test scan-1.6 {BuildCharSet, CharInSet} { list [scan -abc-def {%[ac-]} x] $x } {1 -a} test scan-1.7 {BuildCharSet, CharInSet} { list [scan abc-def {%[c-a]} x] $x } {1 abc} test scan-1.8 {BuildCharSet, CharInSet} { list [scan def-abc {%[^c-a]} x] $x } {1 def-} test scan-1.9 {BuildCharSet, CharInSet no match} { catch {unset x} list [scan {= f} {= %[TF]} x] [info exists x] } {0 0} test scan-2.1 {ReleaseCharSet} { list [scan abcde {%[abc]} x] $x } {1 abc} test scan-2.2 {ReleaseCharSet} { list [scan abcde {%[a-c]} x] $x } {1 abc} test scan-3.1 {ValidateFormat} { list [catch {scan {} {%d%1$d} x} msg] $msg } {1 {cannot mix "%" and "%n$" conversion specifiers}} test scan-3.2 {ValidateFormat} { list [catch {scan {} {%d%1$d} x} msg] $msg } {1 {cannot mix "%" and "%n$" conversion specifiers}} test scan-3.3 {ValidateFormat} { list [catch {scan {} {%2$d%d} x} msg] $msg } {1 {"%n$" argument index out of range}} test scan-3.4 {ValidateFormat} { # degenerate case, before changed from 8.2 to 8.3 list [catch {scan {} %d} msg] $msg } {0 {}} test scan-3.5 {ValidateFormat} { list [catch {scan {} {%10c} a} msg] $msg } {1 {field width may not be specified in %c conversion}} test scan-3.6 {ValidateFormat} jim { list [catch {scan {} {%*1$d} a} msg] $msg } {1 {bad scan conversion character}} test scan-3.7 {ValidateFormat} { list [catch {scan {} {%1$d%1$d} a} msg] $msg } {1 {variable is assigned by multiple "%n$" conversion specifiers}} test scan-3.8 {ValidateFormat} { list [catch {scan {} a x} msg] $msg } {1 {variable is not assigned by any conversion specifiers}} test scan-3.9 {ValidateFormat} { list [catch {scan {} {%2$s} x y} msg] $msg } {1 {variable is not assigned by any conversion specifiers}} test scan-3.10 {ValidateFormat} { list [catch {scan {} {%[a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-3.11 {ValidateFormat} { list [catch {scan {} {%[^a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-3.12 {ValidateFormat} { list [catch {scan {} {%[]a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-3.13 {ValidateFormat} { list [catch {scan {} {%[^]a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-4.1 {Tcl_ScanObjCmd, argument checks} jim { list [catch {scan} msg] $msg } {1 {wrong # args: should be "scan string format ?varName varName ...?"}} test scan-4.2 {Tcl_ScanObjCmd, argument checks} jim { list [catch {scan string} msg] $msg } {1 {wrong # args: should be "scan string format ?varName varName ...?"}} test scan-4.3 {Tcl_ScanObjCmd, argument checks} { # degenerate case, before changed from 8.2 to 8.3 list [catch {scan string format} msg] $msg } {0 {}} test scan-4.4 {Tcl_ScanObjCmd, whitespace} { list [scan { abc def } {%s%s} x y] $x $y } {2 abc def} test scan-4.5 {Tcl_ScanObjCmd, whitespace} { list [scan { abc def } { %s %s } x y] $x $y } {2 abc def} test scan-4.6 {Tcl_ScanObjCmd, whitespace} { list [scan { abc def } { %s %s } x y] $x $y } {2 abc def} test scan-4.7 {Tcl_ScanObjCmd, literals} { # degenerate case, before changed from 8.2 to 8.3 scan { abc def } { abc def } } {} test scan-4.8 {Tcl_ScanObjCmd, literals} { set x {} list [scan { abcg} { abc def %1s} x] $x } {0 {}} test scan-4.9 {Tcl_ScanObjCmd, literals} { list [scan { abc%defghi} { abc %% def%n } x] $x } {1 10} test scan-4.10 {Tcl_ScanObjCmd, assignment suppression} { list [scan { abc def } { %*c%s def } x] $x } {1 bc} test scan-4.11 {Tcl_ScanObjCmd, XPG3-style} { list [scan { abc def } {%2$s %1$s} x y] $x $y } {2 def abc} test scan-4.12 {Tcl_ScanObjCmd, width specifiers} { list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e } {5 abc 123 456.0 789 012} test scan-4.13 {Tcl_ScanObjCmd, width specifiers} { list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e } {5 abc 123 456.0 789 012} test scan-4.14 {Tcl_ScanObjCmd, underflow} { set x {} list [scan {a} {a%d} x] $x } {-1 {}} test scan-4.15 {Tcl_ScanObjCmd, underflow} { set x {} list [scan {} {a%d} x] $x } {-1 {}} test scan-4.16 {Tcl_ScanObjCmd, underflow} { set x {} list [scan {ab} {a%d} x] $x } {0 {}} test scan-4.17 {Tcl_ScanObjCmd, underflow} { set x {} list [scan {a } {a%d} x] $x } {-1 {}} test scan-4.18 {Tcl_ScanObjCmd, skipping whitespace} { list [scan { b} {%c%s} x y] $x $y } {2 32 b} test scan-4.19 {Tcl_ScanObjCmd, skipping whitespace} { list [scan { b} {%[^b]%s} x y] $x $y } {2 { } b} test scan-4.20 {Tcl_ScanObjCmd, string scanning} { list [scan {abc def} {%s} x] $x } {1 abc} test scan-4.21 {Tcl_ScanObjCmd, string scanning} { list [scan {abc def} {%0s} x] $x } {1 abc} test scan-4.22 {Tcl_ScanObjCmd, string scanning} { list [scan {abc def} {%2s} x] $x } {1 ab} test scan-4.23 {Tcl_ScanObjCmd, string scanning} { list [scan {abc def} {%*s%n} x] $x } {1 3} test scan-4.24 {Tcl_ScanObjCmd, charset scanning} { list [scan {abcdef} {%[a-c]} x] $x } {1 abc} test scan-4.25 {Tcl_ScanObjCmd, charset scanning} { list [scan {abcdef} {%0[a-c]} x] $x } {1 abc} test scan-4.26 {Tcl_ScanObjCmd, charset scanning} { list [scan {abcdef} {%2[a-c]} x] $x } {1 ab} test scan-4.27 {Tcl_ScanObjCmd, charset scanning} { list [scan {abcdef} {%*[a-c]%n} x] $x } {1 3} test scan-4.28 {Tcl_ScanObjCmd, character scanning} { list [scan {abcdef} {%c} x] $x } {1 97} test scan-4.29 {Tcl_ScanObjCmd, character scanning} { list [scan {abcdef} {%*c%n} x] $x } {1 1} test scan-4.30 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {1234567890a} {%3d} x] $x } {1 123} test scan-4.31 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {1234567890a} {%d} x] $x } {1 1234567890} test scan-4.32 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {01234567890a} {%d} x] $x } {1 1234567890} test scan-4.33 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {+01234} {%d} x] $x } {1 1234} test scan-4.34 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {-01234} {%d} x] $x } {1 -1234} test scan-4.35 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {a01234} {%d} x] $x } {0 {}} test scan-4.36 {Tcl_ScanObjCmd, base-10 integer scanning} { set x {} list [scan {0x10} {%d} x] $x } {1 0} test scan-4.37 {Tcl_ScanObjCmd, base-8 integer scanning} { set x {} list [scan {012345678} {%o} x] $x } {1 342391} test scan-4.38 {Tcl_ScanObjCmd, base-8 integer scanning} { set x {} list [scan {+1238 -1239 123a} {%o%*s%o%*s%o} x y z] $x $y $z } {3 83 -83 83} test scan-4.39 {Tcl_ScanObjCmd, base-16 integer scanning} { set x {} list [scan {+1238 -123a 0123} {%x%x%x} x y z] $x $y $z } {3 4664 -4666 291} test scan-4.40 {Tcl_ScanObjCmd, base-16 integer scanning} { # The behavior changed in 8.4a4/8.3.4cvs (6 Feb) to correctly # return '1' for 0x1 scanned via %x, to comply with 8.0 and C scanf. # Bug #495213 set x {} list [scan {aBcDeF AbCdEf 0x1} {%x%x%x} x y z] $x $y $z } {3 11259375 11259375 1} test scan-4.40.1 {Tcl_ScanObjCmd, base-16 integer scanning} { set x {} list [scan {0xF 0x00A0B 0X0XF} {%x %x %x} x y z] $x $y $z } {3 15 2571 0} test scan-4.40.2 {Tcl_ScanObjCmd, base-16 integer scanning} { catch {unset x} list [scan {xF} {%x} x] [info exists x] } {0 0} test scan-4.41 {Tcl_ScanObjCmd, base-unknown integer scanning} { set x {} list [scan {10 010 0x10} {%i%i%i} x y z] $x $y $z } {3 10 10 16} test scan-4.42 {Tcl_ScanObjCmd, base-unknown integer scanning} { set x {} list [scan {10 010 0X10} {%i%i%i} x y z] $x $y $z } {3 10 10 16} test scan-4.43 {Tcl_ScanObjCmd, integer scanning, odd cases} { set x {} list [scan {+ } {%i} x] $x } {0 {}} #test scan-4.44 {Tcl_ScanObjCmd, integer scanning, odd cases} { # set x {} # list [scan {+} {%i} x] $x #} {-1 {}} test scan-4.45 {Tcl_ScanObjCmd, integer scanning, odd cases} { set x {} list [scan {0x} {%i%s} x y] $x $y } {2 0 x} test scan-4.46 {Tcl_ScanObjCmd, integer scanning, odd cases} { set x {} list [scan {0X} {%i%s} x y] $x $y } {2 0 X} test scan-4.47 {Tcl_ScanObjCmd, integer scanning, suppressed} { set x {} list [scan {123def} {%*i%s} x] $x } {1 def} test scan-4.48 {Tcl_ScanObjCmd, float scanning} { list [scan {1 2 3} {%e %f %g} x y z] $x $y $z } {3 1.0 2.0 3.0} test scan-4.49 {Tcl_ScanObjCmd, float scanning} { list [scan {.1 0.2 3.} {%e %f %g} x y z] $x $y $z } {3 0.1 0.2 3.0} test scan-4.50 {Tcl_ScanObjCmd, float scanning} { list [scan {1234567890a} %f x] $x } {1 1234567890.0} test scan-4.51 {Tcl_ScanObjCmd, float scanning} { list [scan {+123+45} %f x] $x } {1 123.0} test scan-4.52 {Tcl_ScanObjCmd, float scanning} { list [scan {-123+45} %f x] $x } {1 -123.0} test scan-4.53 {Tcl_ScanObjCmd, float scanning} { list [scan {1.0e1} %f x] $x } {1 10.0} test scan-4.54 {Tcl_ScanObjCmd, float scanning} { list [scan {1.0e-1} %f x] $x } {1 0.1} #test scan-4.55 {Tcl_ScanObjCmd, odd cases} { # set x {} # list [scan {+} %f x] $x #} {-1 {}} test scan-4.56 {Tcl_ScanObjCmd, odd cases} { set x {} list [scan {1.0e} %f%s x y] $x $y } {2 1.0 e} test scan-4.57 {Tcl_ScanObjCmd, odd cases} { set x {} list [scan {1.0e+} %f%s x y] $x $y } {2 1.0 e+} test scan-4.58 {Tcl_ScanObjCmd, odd cases} { set x {} set y {} list [scan {e1} %f%s x y] $x $y } {0 {} {}} test scan-4.59 {Tcl_ScanObjCmd, float scanning} { list [scan {1.0e-1x} %*f%n x] $x } {1 6} test scan-4.60 {Tcl_ScanObjCmd, set errors} { set x {} set y {} set z 1 set result [list [catch {scan {abc def ghi} {%s%s%s} x z(z) y} msg] \ $x $y] set result } {1 abc ghi} test scan-4.61 {Tcl_ScanObjCmd, set errors} { set x {} set y 1 set z 1 set result [list [catch {scan {abc def ghi} {%s%s%s} x y(y) z(z)} msg] \ $x] set result } {1 abc} # procedure that returns the range of integers # On Tcl with bignum, these won't produce a result! proc int_range {} { for { set MIN_INT 1 } { $MIN_INT > 0 } {} { set MIN_INT [expr { $MIN_INT << 1 }] } set MAX_INT [expr { ~ $MIN_INT }] return [list $MIN_INT $MAX_INT] } test scan-4.62 {scanning of large and negative octal integers} jim { foreach { MIN_INT MAX_INT } [int_range] {} set scanstring [format {%o %o %o} -1 $MIN_INT $MAX_INT] list [scan $scanstring {%o %o %o} a b c] \ [expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }] } {3 1 1 1} test scan-4.63 {scanning of large and negative hex integers} jim { foreach { MIN_INT MAX_INT } [int_range] {} set scanstring [format {%x %x %x} -1 $MIN_INT $MAX_INT] list [scan $scanstring {%x %x %x} a b c] \ [expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }] } {3 1 1 1} # clean up from last two tests catch { rename int_range {} } test scan-5.1 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "-20 1476 \n33 0" "%d %d %d %d" a b c d] $a $b $c $d } {4 -20 1476 33 0} test scan-5.2 {integer scanning} { set a {}; set b {}; set c {} list [scan "-45 16 7890 +10" "%2d %*d %10d %d" a b c] $a $b $c } {3 -4 16 7890} test scan-5.3 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "-45 16 +10 987" "%ld %d %ld %d" a b c d] $a $b $c $d } {4 -45 16 10 987} test scan-5.4 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "14 1ab 62 10" "%d %x %lo %x" a b c d] $a $b $c $d } {4 14 427 50 16} test scan-5.5 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "12345670 1234567890ab cdefg" "%o %o %x %lx" a b c d] \ $a $b $c $d } {4 2739128 342391 561323 52719} test scan-5.6 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "ab123-24642" "%2x %3x %3o %2o" a b c d] $a $b $c $d } {4 171 291 -20 52} test scan-5.7 {integer scanning} { set a {}; set b {} list [scan "1234567 234 567 " "%*3x %x %*o %4o" a b] $a $b } {2 17767 375} test scan-5.8 {integer scanning} { set a {}; set b {} list [scan "a 1234" "%d %d" a b] $a $b } {0 {} {}} test scan-5.9 {integer scanning} { set a {}; set b {}; set c {}; set d {}; list [scan "12345678" "%2d %2d %2ld %2d" a b c d] $a $b $c $d } {4 12 34 56 78} test scan-5.10 {integer scanning} { set a {}; set b {}; set c {}; set d {} list [scan "1 2 " "%hd %d %d %d" a b c d] $a $b $c $d } {2 1 2 {} {}} # # The behavior for scaning intergers larger than MAX_INT is # not defined by the ANSI spec. Some implementations wrap the # input (-16) some return MAX_INT. # test scan-5.11 {integer scanning} { set a {}; set b {}; list [scan "4294967280 4294967280" "%u %d" a b] $a \ [expr {$b == -16 || $b == 0x7fffffff || $b == $a}] } {2 4294967280 1} test scan-6.1 {floating-point scanning} { set a {}; set b {}; set c {}; set d {} list [scan "2.1 -3.0e8 .99962 a" "%f%g%e%f" a b c d] $a $b $c $d } {3 2.1 -300000000.0 0.99962 {}} test scan-6.2 {floating-point scanning} { set a {}; set b {}; set c {}; set d {} list [scan "-1.2345 +8.2 9" "%3e %3lf %f %f" a b c d] $a $b $c $d } {4 -1.0 234.0 5.0 8.2} test scan-6.3 {floating-point scanning} { set a {}; set b {}; set c {} list [scan "1e00004 332E-4 3e+4" "%Lf %*2e %f %f" a b c] $a $c } {3 10000.0 30000.0} # # Some libc implementations consider 3.e- bad input. The ANSI # spec states that digits must follow the - sign. # test scan-6.4 {floating-point scanning} { set a {}; set b {}; set c {} list [scan "1. 47.6 2.e2 3.e-" "%f %*f %f %f" a b c] $a $b $c } {3 1.0 200.0 3.0} test scan-6.5 {floating-point scanning} { set a {}; set b {}; set c {}; set d {} list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d } {4 4.6 99999.7 87.643 118.0} test scan-6.6 {floating-point scanning} jim { set a {}; set b {}; set c {}; set d {} list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d } {4 1.2345 0.697 124.0 5e-05} test scan-6.7 {floating-point scanning} { set a {}; set b {}; set c {}; set d {} list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d } {1 4.6 {} {} {}} test scan-6.8 {floating-point scanning} { set a {}; set b {}; set c {}; set d {} list [scan "4.6 5.2" "%f %f %f %f" a b c d] $a $b $c $d } {2 4.6 5.2 {} {}} test scan-7.1 {string and character scanning} { set a {}; set b {}; set c {}; set d {} list [scan "abc defghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d } {4 abc def ghijk dum} test scan-7.2 {string and character scanning} { set a {}; set b {}; set c {}; set d {} list [scan "a bcdef" "%c%c%1s %s" a b c d] $a $b $c $d } {4 97 32 b cdef} test scan-7.3 {string and character scanning} { set a {}; set b {}; set c {} list [scan "123456 test " "%*c%*s %s %s %s" a b c] $a $b $c } {1 test {} {}} test scan-7.4 {string and character scanning} { set a {}; set b {}; set c {}; set d list [scan "ababcd01234 f 123450" {%4[abcd] %4[abcd] %[^abcdef] %[^0]} a b c d] $a $b $c $d } {4 abab cd {01234 } {f 12345}} test scan-7.5 {string and character scanning} { set a {}; set b {}; set c {} list [scan "aaaaaabc aaabcdefg + + XYZQR" {%*4[a] %s %*4[a]%s%*4[ +]%c} a b c] $a $b $c } {3 aabc bcdefg 43} test scan-7.6 {string and character scanning, unicode} utf8 { set a {}; set b {}; set c {}; set d {} list [scan "abc d\u00c7fghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d } "4 abc d\u00c7f ghijk dum" test scan-7.7 {string and character scanning, unicode} utf8 { set a {}; set b {} list [scan "ab\u00c7cdef" "ab%c%c" a b] $a $b } "2 199 99" test scan-7.8 {string and character scanning, unicode} utf8 { set a {}; set b {} list [scan "ab\ufeffdef" "%\[ab\ufeff\]" a] $a } "1 ab\ufeff" test scan-8.1 {error conditions} { catch {scan a} } 1 test scan-8.2 {error conditions} jim { catch {scan a} msg set msg } {wrong # args: should be "scan string format ?varName varName ...?"} test scan-8.3 {error conditions} jim { list [catch {scan a %D x} msg] $msg } {1 {bad scan conversion character}} test scan-8.4 {error conditions} jim { list [catch {scan a %O x} msg] $msg } {1 {bad scan conversion character}} test scan-8.5 {error conditions} jim { list [catch {scan a %X x} msg] $msg } {1 {bad scan conversion character}} test scan-8.6 {error conditions} jim { list [catch {scan a %F x} msg] $msg } {1 {bad scan conversion character}} test scan-8.7 {error conditions} jim { list [catch {scan a %E x} msg] $msg } {1 {bad scan conversion character}} test scan-8.8 {error conditions} { list [catch {scan a "%d %d" a} msg] $msg } {1 {different numbers of variable names and field specifiers}} test scan-8.9 {error conditions} { list [catch {scan a "%d %d" a b c} msg] $msg } {1 {variable is not assigned by any conversion specifiers}} test scan-8.10 {error conditions} { set a {}; set b {}; set c {}; set d {} list [expr {[scan " a" " a %d %d %d %d" a b c d] <= 0}] $a $b $c $d } {1 {} {} {} {}} test scan-8.11 {error conditions} { set a {}; set b {}; set c {}; set d {} list [scan "1 2" "%d %d %d %d" a b c d] $a $b $c $d } {2 1 2 {} {}} test scan-8.12 {error conditions} { set a 44 list [catch {scan 44 %d a(0)} msg] } {1} test scan-8.13 {error conditions} { set a 44 list [catch {scan 44 %c a(0)} msg] } {1} test scan-8.14 {error conditions} { set a 44 list [catch {scan 44 %s a(0)} msg] } {1} test scan-8.15 {error conditions} { set a 44 list [catch {scan 44 %f a(0)} msg] } {1} catch {unset a} test scan-8.17 {error conditions} { list [catch {scan 44 %2c a} msg] $msg } {1 {field width may not be specified in %c conversion}} test scan-8.18 {error conditions} { list [catch {scan abc {%[} x} msg] $msg } {1 {unmatched [ in format string}} test scan-8.19 {error conditions} { list [catch {scan abc {%[^a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-8.20 {error conditions} { list [catch {scan abc {%[^]a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-8.21 {error conditions} { list [catch {scan abc {%[]a} x} msg] $msg } {1 {unmatched [ in format string}} test scan-9.1 {lots of arguments} { scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 } 20 test scan-9.2 {lots of arguments} { scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 set a20 } 200 test scan-10.1 {miscellaneous tests} { set a {} list [scan ab16c ab%dc a] $a } {1 16} test scan-10.2 {miscellaneous tests} { set a {} list [scan ax16c ab%dc a] $a } {0 {}} test scan-10.3 {miscellaneous tests} { set a {} list [catch {scan ab%c114 ab%%c%d a} msg] $msg $a } {0 1 114} test scan-10.4 {miscellaneous tests} { set a {} list [catch {scan ab%c14 ab%%c%d a} msg] $msg $a } {0 1 14} test scan-10.5 {miscellaneous tests} { catch {unset arr} set arr(2) {} list [catch {scan ab%c14 ab%%c%d arr(2)} msg] $msg $arr(2) } {0 1 14} test scan-11.1 {alignment in results array (TCL_ALIGN)} { scan "123 13.6" "%s %f" a b set b } 13.6 test scan-11.2 {alignment in results array (TCL_ALIGN)} { scan "1234567 13.6" "%s %f" a b set b } 13.6 test scan-11.3 {alignment in results array (TCL_ALIGN)} { scan "12345678901 13.6" "%s %f" a b set b } 13.6 test scan-11.4 {alignment in results array (TCL_ALIGN)} { scan "123456789012345 13.6" "%s %f" a b set b } 13.6 test scan-11.5 {alignment in results array (TCL_ALIGN)} { scan "1234567890123456789 13.6" "%s %f" a b set b } 13.6 test scan-12.1 {Tcl_ScanObjCmd, inline case} { scan a %c } 97 test scan-12.2 {Tcl_ScanObjCmd, inline case} { scan abc %c%c%c%c } {97 98 99 {}} test scan-12.3 {Tcl_ScanObjCmd, inline case} { scan abc %s%c } {abc {}} test scan-12.4 {Tcl_ScanObjCmd, inline case, underflow} { scan abc abc%c } {} test scan-12.5 {Tcl_ScanObjCmd, inline case} { scan abc bogus%c%c%c } {{} {} {}} test scan-12.6 {Tcl_ScanObjCmd, inline case} { # degenerate case, behavior changed from 8.2 to 8.3 list [catch {scan foo foobar} msg] $msg } {0 {}} test scan-12.7 {Tcl_ScanObjCmd, inline case lots of arguments} { scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140\ 150 160 170 180 190 200" \ "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" } {10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 {}} test scan-13.1 {Tcl_ScanObjCmd, inline XPG case} { scan a {%1$c} } 97 test scan-13.2 {Tcl_ScanObjCmd, inline XPG case} { scan abc {%1$c%2$c%3$c%4$c} } {97 98 99 {}} test scan-13.3 {Tcl_ScanObjCmd, inline XPG case} { list [catch {scan abc {%1$c%1$c}} msg] $msg } {1 {variable is assigned by multiple "%n$" conversion specifiers}} test scan-13.4 {Tcl_ScanObjCmd, inline XPG case} { scan abc {%2$s%1$c} } {{} abc} test scan-13.5 {Tcl_ScanObjCmd, inline XPG case, underflow} { scan abc {abc%5$c} } {} test scan-13.6 {Tcl_ScanObjCmd, inline XPG case} { catch {scan abc {bogus%1$c%5$c%10$c}} msg list [llength $msg] $msg } {10 {{} {} {} {} {} {} {} {} {} {}}} test scan-13.7 {Tcl_ScanObjCmd, inline XPG case lots of arguments} { scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" {%20$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d %10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d} } {190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 {} 10} test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} { set msg [scan "10 20 30" {%100$d %5$d %200$d}] list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199] } {200 10 20 30} test scan-14.1 {scan with null chars} { scan a\0c %c%c%c } {97 0 99} test scan-14.2 {scan with null chars} { scan \0\0c %c%c%c } {0 0 99} test scan-14.3 {scan with null chars} { scan ab12x\0 %cb%dx%c } {97 12 0} testreport openocd-0.9.0/jimtcl/tests/exec.test0000644000175000017500000003206112516456444014356 00000000000000# Commands covered: exec # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1994 The Regents of the University of California. # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: exec.test,v 1.8.2.1 2001/10/17 19:29:25 das Exp $ source [file dirname [info script]]/testing.tcl needs cmd exec needs cmd flush needs cmd after eventloop # Sleep which supports fractions of a second if {[info commands sleep] eq {}} { proc sleep {n} { after [expr {int($n * 1000)}] } } set f [open sleepx w] puts $f "#![info nameofexecutable]" puts $f { set seconds [lindex $argv 0] after [expr {int($seconds * 1000)}] } close $f #catch {exec chmod +x sleepx} set sleepx [list [info nameofexecutable] sleepx] # Basic operations. test exec-1.1 {basic exec operation} { exec echo a b c } "a b c" test exec-1.2 {pipelining} { exec echo a b c d | cat | cat } "a b c d" test exec-1.3 {pipelining} { set a [exec echo a b c d | cat | wc] list [scan $a "%d %d %d" b c d] $b $c } {3 1 4} set arg {12345678901234567890123456789012345678901234567890} set arg "$arg$arg$arg$arg$arg$arg" test exec-1.4 {long command lines} { exec echo $arg } $arg set arg {} # I/O redirection: input from Tcl command. test exec-2.1 {redirecting input from immediate source} { exec cat << "Sample text" } {Sample text} test exec-2.2 {redirecting input from immediate source} { exec << "Sample text" cat | cat } {Sample text} test exec-2.3 {redirecting input from immediate source} { exec cat << "Sample text" | cat } {Sample text} test exec-2.4 {redirecting input from immediate source} { exec cat | cat << "Sample text" } {Sample text} test exec-2.5 {redirecting input from immediate source} { exec cat "< external conversion did not # occur before writing out the temp file. exec cat << "\uE9\uE0\uFC\uF1" } "\uE9\uE0\uFC\uF1" test exec-2.7 {redirecting input from immediate source with nulls} { exec cat << "Sample\0text" } "Sample\0text" # I/O redirection: output to file. file delete gorp.file test exec-3.1 {redirecting output to file} { exec echo "Some simple words" > gorp.file exec cat gorp.file } "Some simple words" test exec-3.2 {redirecting output to file} { exec echo "More simple words" | >gorp.file cat | cat exec cat gorp.file } "More simple words" test exec-3.3 {redirecting output to file} { exec > gorp.file echo "Different simple words" | cat | cat exec cat gorp.file } "Different simple words" test exec-3.4 {redirecting output to file} { exec echo "Some simple words" >gorp.file exec cat gorp.file } "Some simple words" test exec-3.5 {redirecting output to file} { exec echo "First line" >gorp.file exec echo "Second line" >> gorp.file exec cat gorp.file } "First line\nSecond line" test exec-3.6 {redirecting output to file} { exec echo "First line" >gorp.file exec echo "Second line" >>gorp.file exec cat gorp.file } "First line\nSecond line" test exec-3.7 {redirecting output to file} { set f [open gorp.file w] puts $f "Line 1" flush $f exec echo "More text" >@ $f exec echo >@$f "Even more" puts $f "Line 3" close $f exec cat gorp.file } "Line 1\nMore text\nEven more\nLine 3" # I/O redirection: output and stderr to file. file delete gorp.file test exec-4.1 {redirecting output and stderr to file} { exec echo "test output" >& gorp.file exec cat gorp.file } "test output" test exec-4.2 {redirecting output and stderr to file} { list [exec sh -c "echo foo bar 1>&2" >&gorp.file] \ [exec cat gorp.file] } {{} {foo bar}} test exec-4.3 {redirecting output and stderr to file} { exec echo "first line" > gorp.file list [exec sh -c "echo foo bar 1>&2" >>&gorp.file] \ [exec cat gorp.file] } "{} {first line\nfoo bar}" test exec-4.4 {redirecting output and stderr to file} { set f [open gorp.file w] puts $f "Line 1" flush $f exec echo "More text" >&@ $f exec echo >&@$f "Even more" puts $f "Line 3" close $f exec cat gorp.file } "Line 1\nMore text\nEven more\nLine 3" test exec-4.5 {redirecting output and stderr to file} { set f [open gorp.file w] puts $f "Line 1" flush $f exec >&@ $f sh -c "echo foo bar 1>&2" exec >&@$f sh -c "echo xyzzy 1>&2" puts $f "Line 3" close $f exec cat gorp.file } "Line 1\nfoo bar\nxyzzy\nLine 3" # I/O redirection: input from file. exec echo "Just a few thoughts" > gorp.file test exec-5.1 {redirecting input from file} { exec cat < gorp.file } {Just a few thoughts} test exec-5.2 {redirecting input from file} { exec cat | cat < gorp.file } {Just a few thoughts} test exec-5.3 {redirecting input from file} { exec cat < gorp.file | cat } {Just a few thoughts} test exec-5.4 {redirecting input from file} { exec < gorp.file cat | cat } {Just a few thoughts} test exec-5.5 {redirecting input from file} { exec cat &2" |& cat } "foo bar" test exec-6.3 {redirecting stderr through a pipeline} { exec sh -c "echo foo bar 1>&2" \ |& cat |& cat } "foo bar" # I/O redirection: combinations. file delete gorp.file2 test exec-7.1 {multiple I/O redirections} { exec << "command input" > gorp.file2 cat < gorp.file exec cat gorp.file2 } {Just a few thoughts} test exec-7.2 {multiple I/O redirections} { exec < gorp.file << "command input" cat } {command input} # Long input to command and output from command. set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n" set a [concat $a $a $a $a] set a [concat $a $a $a $a] set a [concat $a $a $a $a] set a [concat $a $a $a $a] test exec-8.1 {long input and output} { exec cat << $a } $a # More than 20 arguments to exec. test exec-8.1 {long input and output} { exec echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23} # Commands that return errors. test exec-9.1 {commands returning errors} { catch {exec gorp456} } {1} test exec-9.2 {commands returning errors} { catch {exec echo foo | foo123} msg } {1} test exec-9.3 {commands returning errors} { list [catch {exec {*}$sleepx 0.1 | false | {*}$sleepx 0.1} msg] } {1} test exec-9.4 {commands returning errors} jim { list [catch {exec false | echo "foo bar"} msg] $msg } {1 {foo bar}} test exec-9.5 {commands returning errors} { list [catch {exec gorp456 | echo a b c} msg] } {1} test exec-9.6 {commands returning errors} jim { list [catch {exec sh -c "echo error msg 1>&2"} msg] $msg } {0 {error msg}} test exec-9.7 {commands returning errors} jim { # Note: Use sleep here to ensure the order list [catch {exec sh -c "echo error msg 1 1>&2" \ | sh -c "sleep 0.1; echo error msg 2 1>&2"} msg] $msg } {0 {error msg 1 error msg 2}} # Errors in executing the Tcl command, as opposed to errors in the # processes that are invoked. test exec-10.1 {errors in exec invocation} { list [catch {exec} msg] } {1} test exec-10.2 {errors in exec invocation} { list [catch {exec | cat} msg] $msg } {1 {illegal use of | or |& in command}} test exec-10.3 {errors in exec invocation} { list [catch {exec cat |} msg] $msg } {1 {illegal use of | or |& in command}} test exec-10.4 {errors in exec invocation} { list [catch {exec cat | | cat} msg] $msg } {1 {illegal use of | or |& in command}} test exec-10.5 {errors in exec invocation} { list [catch {exec cat | |& cat} msg] $msg } {1 {illegal use of | or |& in command}} test exec-10.6 {errors in exec invocation} { list [catch {exec cat |&} msg] $msg } {1 {illegal use of | or |& in command}} test exec-10.7 {errors in exec invocation} { list [catch {exec cat <} msg] $msg } {1 {can't specify "<" as last word in command}} test exec-10.8 {errors in exec invocation} { list [catch {exec cat >} msg] $msg } {1 {can't specify ">" as last word in command}} test exec-10.9 {errors in exec invocation} { list [catch {exec cat <<} msg] $msg } {1 {can't specify "<<" as last word in command}} test exec-10.10 {errors in exec invocation} { list [catch {exec cat >>} msg] $msg } {1 {can't specify ">>" as last word in command}} test exec-10.11 {errors in exec invocation} { list [catch {exec cat >&} msg] $msg } {1 {can't specify ">&" as last word in command}} test exec-10.12 {errors in exec invocation} { list [catch {exec cat >>&} msg] $msg } {1 {can't specify ">>&" as last word in command}} test exec-10.13 {errors in exec invocation} { list [catch {exec cat >@} msg] $msg } {1 {can't specify ">@" as last word in command}} test exec-10.14 {errors in exec invocation} { list [catch {exec cat <@} msg] $msg } {1 {can't specify "<@" as last word in command}} test exec-10.15 {errors in exec invocation} { list [catch {exec cat < a/b/c} msg] [string tolower $msg] } {1 {couldn't read file "a/b/c": no such file or directory}} test exec-10.16 {errors in exec invocation} { list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg] } {1 {couldn't write file "a/b/c": no such file or directory}} test exec-10.17 {errors in exec invocation} { list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg] } {1 {couldn't write file "a/b/c": no such file or directory}} set f [open gorp.file w] test exec-10.18 {errors in exec invocation} { list [catch {exec cat <@ $f} msg] } 1 close $f # Commands in background. test exec-11.1 {commands in background} { set x [lindex [time {exec {*}$sleepx 0.2 &}] 0] expr $x<1000000 } 1 test exec-11.2 {commands in background} { list [catch {exec echo a &b} msg] $msg } {0 {a &b}} test exec-11.3 {commands in background} { llength [exec {*}$sleepx 0.1 &] } 1 test exec-11.4 {commands in background} { llength [exec {*}$sleepx 0.1 | {*}$sleepx 0.1 | {*}$sleepx 0.1 &] } 3 # Make sure that background commands are properly reaped when # they eventually die. exec {*}$sleepx 0.3 test exec-12.1 {reaping background processes} -body { for {set i 0} {$i < 20} {incr i} { exec echo foo > exec.tmp1 & } exec {*}$sleepx 0.1 catch {exec ps | fgrep "echo foo" | fgrep -v fgrep | wc} msg lindex $msg 0 } -cleanup { file delete exec.tmp1 } -result 0 # Redirecting standard error separately from standard output test exec-15.1 {standard error redirection} { exec echo "First line" > gorp.file list [exec sh -c "echo foo bar 1>&2" 2> gorp.file] \ [exec cat gorp.file] } {{} {foo bar}} test exec-15.2 {standard error redirection} { list [exec sh -c "echo foo bar 1>&2" \ | echo biz baz >gorp.file 2> gorp.file2] \ [exec cat gorp.file] \ [exec cat gorp.file2] } {{} {biz baz} {foo bar}} test exec-15.3 {standard error redirection} { list [exec sh -c "echo foo bar 1>&2" \ | echo biz baz 2>gorp.file > gorp.file2] \ [exec cat gorp.file] \ [exec cat gorp.file2] } {{} {foo bar} {biz baz}} test exec-15.4 {standard error redirection} { set f [open gorp.file w] puts $f "Line 1" flush $f exec sh -c "echo foo bar 1>&2" 2>@ $f puts $f "Line 3" close $f exec cat gorp.file } {Line 1 foo bar Line 3} test exec-15.5 {standard error redirection} { exec echo "First line" > gorp.file exec sh -c "echo foo bar 1>&2" 2>> gorp.file exec cat gorp.file } {First line foo bar} test exec-15.6 {standard error redirection} { exec sh -c "echo foo bar 1>&2" > gorp.file2 2> gorp.file \ >& gorp.file 2> gorp.file2 | echo biz baz list [exec cat gorp.file] [exec cat gorp.file2] } {{biz baz} {foo bar}} test exec-15.7 {combine standard output/standard error} -body { exec sh -c "echo foo bar 1>&2" > gorp.file 2>@1 exec cat gorp.file } -cleanup { file delete gorp.file gorp.file2 } -result {foo bar} test exec-16.1 {flush output before exec} -body { set f [open gorp.file w] puts $f "First line" exec echo "Second line" >@ $f puts $f "Third line" close $f exec cat gorp.file } -cleanup { file delete gorp.file } -result {First line Second line Third line} file delete sleepx testreport openocd-0.9.0/jimtcl/tests/namespace.test0000644000175000017500000004022512516456445015370 00000000000000source [file dirname [info script]]/testing.tcl needs cmd namespace test namespace-1.1 {usage for "namespace" command} -body { namespace } -returnCodes error -match glob -result {wrong # args: should be *} test namespace-1.2 {global namespace's name is "::" or {}} { list [namespace current] [namespace eval {} {namespace current}] [namespace eval :: {namespace current}] } {:: :: ::} test namespace-1.3 {usage for "namespace eval"} -body { namespace eval } -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"} test namespace-1.5 {access a new namespace} { namespace eval ns1 { namespace current } } {::ns1} test namespace-1.7 {usage for "namespace eval"} -body { namespace eval ns1 } -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"} test namespace-1.8 {command "namespace eval" concatenates args} { namespace eval ns1 namespace current } {::ns1} test namespace-1.9 {simple namespace elements} { namespace eval ns1 { variable v1 1 proc p1 {a} {variable v1; list $a $v1} p1 3 } } {3 1} test namespace-1.10 {commands in a namespace} { namespace eval ns1 { info commands [namespace current]::* } } {::ns1::p1} test namespace-1.11 {variables in a namespace} { namespace eval ns1 { info vars [namespace current]::* } } {::ns1::v1} test namespace-1.12 {global vars are separate from locals vars} { set v1 2 list [ns1::p1 123] [set ns1::v1] [set ::v1] } {{123 1} 1 2} test namespace-1.13 {add to an existing namespace} { namespace eval ns1 { variable v2 22 proc p2 {script} {variable v2; eval $script} p2 {return $v2} } } 22 test namespace-1.14 {commands in a namespace} { lsort [namespace eval ns1 {info commands [namespace current]::*}] } {::ns1::p1 ::ns1::p2} test namespace-1.15 {variables in a namespace} { lsort [namespace eval ns1 {info vars [namespace current]::*}] } {::ns1::v1 ::ns1::v2} # Tcl produces fully scoped names here test namespace-1.16 {variables in a namespace} jim { lsort [info vars ns1::*] } {ns1::v1 ns1::v2} test namespace-1.17 {commands in a namespace are hidden} -body { v2 {return 3} } -returnCodes error -result {invalid command name "v2"} test namespace-1.18 {using namespace qualifiers} { ns1::p2 {return 44} } 44 test namespace-1.19 {using absolute namespace qualifiers} { ::ns1::p2 {return 55} } 55 test namespace-1.20 {variables in a namespace are hidden} -body { set v2 } -returnCodes error -result {can't read "v2": no such variable} test namespace-1.21 {using namespace qualifiers} { list $ns1::v1 $ns1::v2 } {1 22} test namespace-1.22 {using absolute namespace qualifiers} { list $::ns1::v1 $::ns1::v2 } {1 22} test namespace-1.23 {variables can be accessed within a namespace} { ns1::p2 { variable v1 variable v2 list $v1 $v2 } } {1 22} test namespace-1.24 {setting global variables} { ns1::p2 { variable v1 set v1 new } namespace eval ns1 { variable v1 variable v2 list $v1 $v2 } } {new 22} test namespace-1.25 {qualified variables don't need a global declaration} { namespace eval ns2 { variable x 456 } set cmd {set ::ns2::x} ns1::p2 "$cmd some-value" set ::ns2::x } {some-value} test namespace-1.26 {namespace qualifiers are okay after $'s} { namespace eval ns1 { variable x; variable y; set x 12; set y 34 } set cmd {list $::ns1::x $::ns1::y} list [ns1::p2 $cmd] [eval $cmd] } {{12 34} {12 34}} test namespace-1.27 {can create commands with null names} { proc ns1:: {args} {return $args} ns1:: x } {x} test namespace-1.28 {namespace variable with array element syntax} -body { namespace eval ns1 { variable x(3) y } } -returnCodes error -result {can't define "x(3)": name refers to an element in an array} unset -nocomplain ns1::x ns1::y # ----------------------------------------------------------------------- # TEST: using "info" in namespace contexts # ----------------------------------------------------------------------- test namespace-2.1 {querying: info commands} { lsort [ns1::p2 {info commands [namespace current]::*}] } {::ns1:: ::ns1::p1 ::ns1::p2} test namespace-2.2 {querying: info procs} { lsort [ns1::p2 {info procs}] } {{} p1 p2} # Tcl produces fully scoped names here test namespace-2.3 {querying: info vars} jim { lsort [info vars ns1::*] } {ns1::v1 ns1::v2} test namespace-2.4 {querying: info vars} { lsort [ns1::p2 {info vars [namespace current]::*}] } {::ns1::v1 ::ns1::v2} test namespace-2.5 {querying: info locals} { lsort [ns1::p2 {info locals}] } {script} test namespace-2.6 {querying: info exists} { ns1::p2 {info exists v1} } {0} test namespace-2.7 {querying: info exists} { ns1::p2 {info exists v2} } {1} test namespace-2.8 {querying: info args} { info args ns1::p2 } {script} test namespace-2.9 {querying: info body} { string trim [info body ns1::p1] } {variable v1; list $a $v1} # ----------------------------------------------------------------------- # TEST: namespace qualifiers, namespace tail # ----------------------------------------------------------------------- test namespace-3.1 {usage for "namespace qualifiers"} { list [catch "namespace qualifiers" msg] $msg } {1 {wrong # args: should be "namespace qualifiers string"}} test namespace-3.2 {querying: namespace qualifiers} { list [namespace qualifiers ""] \ [namespace qualifiers ::] \ [namespace qualifiers x] \ [namespace qualifiers ::x] \ [namespace qualifiers foo::x] \ [namespace qualifiers ::foo::bar::xyz] } {{} {} {} {} foo ::foo::bar} test namespace-3.3 {usage for "namespace tail"} { list [catch "namespace tail" msg] $msg } {1 {wrong # args: should be "namespace tail string"}} test namespace-3.4 {querying: namespace tail} { list [namespace tail ""] \ [namespace tail ::] \ [namespace tail x] \ [namespace tail ::x] \ [namespace tail foo::x] \ [namespace tail ::foo::bar::xyz] } {{} {} x x x xyz} # ----------------------------------------------------------------------- # TEST: namespace hierarchy # ----------------------------------------------------------------------- test namespace-5.1 {define nested namespaces} { set test_ns_var_global "var in ::" proc test_ns_cmd_global {} {return "cmd in ::"} namespace eval nsh1 { set test_ns_var_hier1 "particular to hier1" proc test_ns_cmd_hier1 {} {return "particular to hier1"} proc test_ns_show {} {return "[namespace current]: 1"} namespace eval nsh2 { set test_ns_var_hier2 "particular to hier2" proc test_ns_cmd_hier2 {} {return "particular to hier2"} proc test_ns_show {} {return "[namespace current]: 2"} namespace eval nsh3a {} namespace eval nsh3b {} } namespace eval nsh2a {} namespace eval nsh2b {} } } {} test namespace-5.2 {namespaces can be nested} { list [namespace eval nsh1 {namespace current}] \ [namespace eval nsh1 { namespace eval nsh2 {namespace current} }] } {::nsh1 ::nsh1::nsh2} test namespace-5.3 {namespace qualifiers work in namespace command} { list [namespace eval ::nsh1 {namespace current}] \ [namespace eval nsh1::nsh2 {namespace current}] \ [namespace eval ::nsh1::nsh2 {namespace current}] } {::nsh1 ::nsh1::nsh2 ::nsh1::nsh2} test namespace-5.4 {nested namespaces can access global namespace} { list [namespace eval nsh1 {set ::test_ns_var_global}] \ [namespace eval nsh1 {test_ns_cmd_global}] \ [namespace eval nsh1::nsh2 {set ::test_ns_var_global}] \ [namespace eval nsh1::nsh2 {test_ns_cmd_global}] } {{var in ::} {cmd in ::} {var in ::} {cmd in ::}} test namespace-5.6 {commands in different namespaces don't conflict} { list [nsh1::test_ns_show] \ [nsh1::nsh2::test_ns_show] } {{::nsh1: 1} {::nsh1::nsh2: 2}} test namespace-5.7 {nested namespaces don't see variables in parent} { set cmd { namespace eval nsh1::nsh2 {set test_ns_var_hier1} } list [catch $cmd msg] $msg } {1 {can't read "test_ns_var_hier1": no such variable}} test namespace-5.8 {nested namespaces don't see commands in parent} { set cmd { namespace eval nsh1::nsh2 {test_ns_cmd_hier1} } list [catch $cmd msg] $msg } {1 {invalid command name "test_ns_cmd_hier1"}} test namespace-5.18 {usage for "namespace parent"} { list [catch {namespace parent x y} msg] $msg } {1 {wrong # args: should be "namespace parent ?name?"}} test namespace-5.20 {querying namespace parent} { list [namespace eval :: {namespace parent}] \ [namespace eval nsh1 {namespace parent}] \ [namespace eval nsh1::nsh2 {namespace parent}] \ [namespace eval nsh1::nsh2::nsh3a {namespace parent}] \ } {{} :: ::nsh1 ::nsh1::nsh2} test namespace-5.21 {querying namespace parent for explicit namespace} { list [namespace parent ::] \ [namespace parent nsh1] \ [namespace parent nsh1::nsh2] \ [namespace parent nsh1::nsh2::nsh3a] } {{} :: ::nsh1 ::nsh1::nsh2} # ----------------------------------------------------------------------- # TEST: name resolution and caching # ----------------------------------------------------------------------- test namespace-6.1 {relative ns names only looked up in current ns} { namespace eval tns1 {} namespace eval tns2 {} namespace eval tns2::test_ns_cache3 {} set trigger { namespace eval tns2 {namespace current} } set trigger2 { namespace eval tns2::test_ns_cache3 {namespace current} } list [namespace eval tns1 $trigger] \ [namespace eval tns1 $trigger2] } {::tns1::tns2 ::tns1::tns2::test_ns_cache3} test namespace-6.2 {relative ns names only looked up in current ns} { namespace eval tns1::tns2 {} list [namespace eval tns1 $trigger] \ [namespace eval tns1 $trigger2] } {::tns1::tns2 ::tns1::tns2::test_ns_cache3} test namespace-6.3 {relative ns names only looked up in current ns} { namespace eval tns1::tns2::test_ns_cache3 {} list [namespace eval tns1 $trigger] \ [namespace eval tns1 $trigger2] } {::tns1::tns2 ::tns1::tns2::test_ns_cache3} test namespace-6.4 {relative ns names only looked up in current ns} { namespace delete tns1::tns2 list [namespace eval tns1 $trigger] \ [namespace eval tns1 $trigger2] } {::tns1::tns2 ::tns1::tns2::test_ns_cache3} test namespace-6.5 {define test commands} { proc testcmd {} { return "global version" } namespace eval tns1 { proc trigger {} { testcmd } } tns1::trigger } {global version} test namespace-6.6 {one-level check for command shadowing} { proc tns1::testcmd {} { return "cache1 version" } tns1::trigger } {cache1 version} test namespace-6.7 {renaming commands changes command epoch} { namespace eval tns1 { rename testcmd testcmd_new } tns1::trigger } {global version} test namespace-6.8 {renaming back handles shadowing} { namespace eval tns1 { rename testcmd_new testcmd } tns1::trigger } {cache1 version} test namespace-6.9 {deleting commands changes command epoch} { namespace eval tns1 { rename testcmd "" } tns1::trigger } {global version} test namespace-6.10 {define test namespaces} { namespace eval tns2 { proc testcmd {} { return "global cache2 version" } } namespace eval tns1 { proc trigger {} { tns2::testcmd } } namespace eval tns1::tns2 { proc trigger {} { testcmd } } list [tns1::trigger] [tns1::tns2::trigger] } {{global cache2 version} {global version}} test namespace-6.11 {commands affect all parent namespaces} { proc tns1::tns2::testcmd {} { return "cache2 version" } list [tns1::trigger] [tns1::tns2::trigger] } {{cache2 version} {cache2 version}} # ----------------------------------------------------------------------- # TEST: uplevel/upvar across namespace boundaries # ----------------------------------------------------------------------- # Note that Tcl behaves a little differently for uplevel and upvar test namespace-7.1 {uplevel in namespace eval} jim { set x 66 namespace eval uns1 { variable y 55 set x 33 uplevel 1 set x } } {66} test namespace-7.2 {upvar in ns proc} jim { proc uns1::getvar {v} { variable y upvar $v var list $var $y } uns1::getvar x } {66 55} # ----------------------------------------------------------------------- # TEST: scoped values # ----------------------------------------------------------------------- test namespace-10.1 {define namespace for scope test} { namespace eval ins1 { variable x "x-value" proc show {args} { return "show: $args" } proc do {args} { return [eval $args] } list [set x] [show test] } } {x-value {show: test}} test namespace-10.2 {command "namespace code" requires one argument} { list [catch {namespace code} msg] $msg } {1 {wrong # args: should be "namespace code arg"}} test namespace-10.3 {command "namespace code" requires one argument} { list [catch {namespace code first "second arg" third} msg] $msg } {1 {wrong # args: should be "namespace code arg"}} test namespace-10.4 {command "namespace code" gets current namesp context} { namespace eval ins1 { namespace code {"1 2 3" "4 5" 6} } } {::namespace inscope ::ins1 {"1 2 3" "4 5" 6}} test namespace-10.5 {with one arg, first "scope" sticks} { set sval [namespace eval ins1 {namespace code {one two}}] namespace code $sval } {::namespace inscope ::ins1 {one two}} test namespace-10.6 {with many args, each "scope" adds new args} { set sval [namespace eval ins1 {namespace code {one two}}] namespace code "$sval three" } {::namespace inscope ::ins1 {one two} three} test namespace-10.7 {scoped commands work with eval} { set cref [namespace eval ins1 {namespace code show}] list [eval $cref "a" "b c" "d e f"] } {{show: a b c d e f}} test namespace-10.8 {scoped commands execute in namespace context} { set cref [namespace eval ins1 { namespace code {variable x; set x "some new value"} }] list [set ins1::x] [eval $cref] [set ins1::x] } {x-value {some new value} {some new value}} test namespace-11.1 {command caching} { proc cmd1 {} { return global } set result {} namespace eval ns1 { proc cmd1 {} { return ns1 } proc cmd2 {} { uplevel 1 cmd1 } lappend ::result [cmd2] } lappend result [ns1::cmd2] } {ns1 global} test namespace-12.1 {namespace import} { namespace eval test_ns_scope1 { proc a {} { return a } namespace export a } namespace eval test_ns_scope2 { namespace import ::test_ns_scope1::a a } } {a} test namespace-12.2 {namespace import recursive} -body { namespace eval test_ns_scope1 { namespace import [namespace current]::* } } -returnCodes error -match glob -result {import pattern "*" tries to import from namespace "*" into itself} test namespace-12.3 {namespace import loop} -setup { namespace eval one { namespace export cmd proc cmd {} {} } namespace eval two namespace export cmd namespace eval two \ [list namespace import [namespace current]::one::cmd] namespace eval three namespace export cmd namespace eval three \ [list namespace import [namespace current]::two::cmd] } -body { namespace eval two [list namespace import -force \ [namespace current]::three::cmd] namespace origin two::cmd } -cleanup { namespace delete one two three } -returnCodes error -match glob -result {import pattern * would create a loop*} foreach cmd [info commands test_ns_*] { rename $cmd "" } catch {rename cmd {}} catch {rename cmd1 {}} catch {rename cmd2 {}} catch {rename ncmd {}} catch {rename ncmd1 {}} catch {rename ncmd2 {}} catch {unset cref} catch {unset trigger} catch {unset trigger2} catch {unset sval} catch {unset msg} catch {unset x} catch {unset test_ns_var_global} catch {unset cmd} catch {eval namespace delete [namespace children :: test_ns_*]} # cleanup ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: openocd-0.9.0/jimtcl/tests/dummy.tcl0000644000175000017500000000011612315602575014357 00000000000000# generates an error proc dummyproc {} { error "from dummyproc" } dummyproc openocd-0.9.0/jimtcl/tests/string.test0000644000175000017500000006547312516456445014756 00000000000000# Commands covered: string # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: string.test,v 1.23.2.1 2001/04/03 22:54:38 hobbs Exp $ source [file dirname [info script]]/testing.tcl # Some tests require the testobj command test string-1.1 {error conditions} { list [catch {string gorp a b} msg] } {1} test string-1.2 {error conditions} { list [catch {string} msg] } {1} test string-2.1 {string compare, too few args} { list [catch {string compare a} msg] } {1} test string-2.2 {string compare, bad args} { list [catch {string compare a b c} msg] } {1} test string-2.3 {string compare, bad args} { list [catch {string compare -length -nocase str1 str2} msg] } {1} test string-2.4 {string compare, too many args} { list [catch {string compare -length 10 -nocase str1 str2 str3} msg] } {1} test string-2.5 {string compare with length unspecified} { list [catch {string compare -length 10 10} msg] } {1} test string-2.6 {string compare} { string compare abcde abdef } -1 test string-2.7 {string compare, shortest method name} { string co abcde ABCDE } 1 test string-2.8 {string compare} { string compare abcde abcde } 0 test string-2.9 {string compare with length} { string compare -length 2 abcde abxyz } 0 test string-2.10 {string compare with special index} { list [catch {string compare -length end-3 abcde abxyz} msg] } {1} test string-2.12 {string compare, high bit} { # This test will fail if the underlying comparaison # is using signed chars instead of unsigned chars. # (like SunOS's default memcmp thus the compat/memcmp.c) string compare "\x80" "@" # Nb this tests works also in utf8 space because \x80 is # translated into a 2 or more bytelength but whose first byte has # the high bit set. } 1 test string-2.13 {string compare -nocase} { string compare -nocase abcde abdef } -1 test string-2.14 {string compare -nocase} { string co -nocase abcde ABCDE } 0 test string-2.15 {string compare -nocase} { string compare -nocase abcde abcde } 0 test string-2.16 {string compare -nocase with length} { string compare -length 2 -nocase abcde Abxyz } 0 test string-2.17 {string compare -nocase with length} { string compare -nocase -length 3 abcde Abxyz } -1 test string-2.18 {string compare -nocase with length <= 0} { string compare -nocase -length -1 abcde AbCdEf } -1 test string-2.19 {string compare -nocase with excessive length} { string compare -nocase -length 50 AbCdEf abcde } 1 test string-2.20 {string compare -len unicode} { # These are strings that are 6 BYTELENGTH long, but the length # shouldn't make a different because there are actually 3 CHARS long string compare -len 5 \334\334\334 \334\334\374 } -1 test string-2.21 {string compare -nocase with special index} { list [catch {string compare -nocase -length end-3 Abcde abxyz} msg] } {1} test string-2.22 {string compare, null strings} { string compare "" "" } 0 test string-2.23 {string compare, null strings} { string compare "" foo } -1 test string-2.24 {string compare, null strings} { string compare foo "" } 1 test string-2.25 {string compare -nocase, null strings} { string compare -nocase "" "" } 0 test string-2.26 {string compare -nocase, null strings} { string compare -nocase "" foo } -1 test string-2.27 {string compare -nocase, null strings} { string compare -nocase foo "" } 1 test string-2.28 {string equal with length, unequal strings} { string compare -length 2 abc abde } 0 test string-2.29 {string equal with length, unequal strings} { string compare -length 2 ab abde } 0 # only need a few tests on equal, since it uses the same code as # string compare, but just modifies the return output test string-3.1 {string equal} { string equal abcde abdef } 0 test string-3.2 {string equal} { string eq abcde ABCDE } 0 test string-3.3 {string equal} { string equal abcde abcde } 1 test string-3.4 {string equal -nocase} utf8 { string equal -nocase \u00dc\u00dc\u00dc\u00dc\u00fc\u00fc\u00fc\u00fc \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc } 1 test string-3.5 {string equal -nocase} { string equal -nocase abcde abdef } 0 test string-3.6 {string equal -nocase} { string eq -nocase abcde ABCDE } 1 test string-3.7 {string equal -nocase} { string equal -nocase abcde abcde } 1 test string-3.8 {string equal with length, unequal strings} { string equal -length 2 abc abde } 1 test string-4.1 {string first, too few args} { list [catch {string first a} msg] } {1} test string-4.2 {string first, bad args} { list [catch {string first a b c} msg] } {1} test string-4.3 {string first, too many args} { list [catch {string first a b 5 d} msg] } {1} test string-4.4 {string first} { string first bq abcdefgbcefgbqrs } 12 test string-4.5 {string first} { string fir bcd abcdefgbcefgbqrs } 1 test string-4.6 {string first} { string f b abcdefgbcefgbqrs } 1 test string-4.7 {string first} { string first xxx x123xx345xxx789xxx012 } 9 test string-4.8 {string first} { string first "" x123xx345xxx789xxx012 } -1 test string-4.14 {string first, start index} { string first a abcabc end-4 } 3 test string-4.15 {string first, empty needle} { string first "" b } -1 test string-4.16 {string first, empty haystack} { string first a "" } -1 test string-4.17 {string first, needle bigger than haystack} { string first aaa b } -1 test string-4.18 {string first, negative index} { string first a aaa -4 } 0 test string-4.19 {string first, not found} { string first a bcd } -1 test string-5.1 {string index} { list [catch {string index} msg] } {1} test string-5.2 {string index} { list [catch {string index a b c} msg] } {1} test string-5.3 {string index} { string index abcde 0 } a test string-5.4 {string index} { string in abcde 4 } e test string-5.5 {string index} { string index abcde 5 } {} test string-5.6 {string index} { list [catch {string index abcde -10} msg] } {0} test string-5.7 {string index} { list [catch {string index a xyz} msg] } {1} test string-5.8 {string index} { string index abc end } c test string-5.9 {string index} { string index abc end-1 } b test string-5.17 {string index, bad integer} tcl { list [catch {string index "abc" 08} msg] } {1} test string-5.18 {string index, bad integer} tcl { list [catch {string index "abc" end-00289} msg] } {1} test string-6.1 {string is, too few args} jim { list [catch {string is} msg] $msg } {1 {wrong # args: should be "string is class ?-strict? str"}} test string-6.2 {string is, too few args} jim { list [catch {string is alpha} msg] $msg } {1 {wrong # args: should be "string is class ?-strict? str"}} test string-6.3 {string is, bad args} jim { list [catch {string is alpha -failin str} msg] $msg } {1 {wrong # args: should be "string is class ?-strict? str"}} test string-6.4 {string is, too many args} jim { list [catch {string is alpha -failin var -strict str more} msg] $msg } {1 {wrong # args: should be "string is class ?-strict? str"}} test string-6.5 {string is, class check} jim { list [catch {string is bogus str} msg] $msg } {1 {bad class "bogus": must be alnum, alpha, ascii, control, digit, double, graph, integer, lower, print, punct, space, upper, or xdigit}} test string-6.6 {string is, ambiguous class} jim { list [catch {string is al str} msg] $msg } {1 {ambiguous class "al": must be alnum, alpha, ascii, control, digit, double, graph, integer, lower, print, punct, space, upper, or xdigit}} test string-6.10 {string is, ok on empty} { string is alpha {} } 1 test string-6.11 {string is, -strict check against empty} { string is alpha -strict {} } 0 test string-6.12 {string is alnum, true} { string is alnum abc123 } 1 test string-6.15 {string is alpha, true} { string is alpha abc } 1 test string-6.16 {string is ascii, true} { string is ascii abc123 } 1 test string-6.17 {string is ascii, false} { string is ascii 0123Ü567 } 0 test string-6.24 {string is digit, true} { string is digit 0123456789 } 1 test string-6.25 {string is digit, false} { list [string is digit 0123Ü567] } {0} test string-6.26 {string is digit, false} { list [string is digit +123567] } {0} test string-6.27 {string is double, true} { string is double 1 } 1 test string-6.28 {string is double, true} { string is double [expr double(1)] } 1 test string-6.29 {string is double, true} { string is double 1.0 } 1 test string-6.30 {string is double, true} { string is double [string compare a a] } 1 test string-6.31 {string is double, true} { string is double " +1.0e-1 " } 1 test string-6.32 {string is double, true} { string is double "\n1.0\v" } 1 test string-6.33 {string is double, false} { list [string is double 1abc] } {0} test string-6.34 {string is double, false} { list [string is double abc] } {0} test string-6.35 {string is double, false} { list [string is double " 1.0e4e4 "] } {0} test string-6.36 {string is double, false} { list [string is double "\n"] } {0} test string-6.38 {string is double, false on underflow} jim { list [string is double 123e-9999] } {0} test string-6.39 {string is double, false} { # This test is non-portable because IRIX thinks # that .e1 is a valid double - this is really a bug # on IRIX as .e1 should NOT be a valid double list [string is double .e1] } {0} test string-6.48 {string is integer, true} { string is integer +1234567890 } 1 test string-6.49 {string is integer, true on type} { string is integer [expr int(50.0)] } 1 test string-6.50 {string is integer, true} { string is integer [list -10] } 1 test string-6.51 {string is integer, true as hex} { string is integer 0xabcdef } 1 test string-6.52 {string is integer, true as octal} { string is integer 012345 } 1 test string-6.53 {string is integer, true with whitespace} { string is integer " \n1234\v" } 1 test string-6.54 {string is integer, false} { list [string is integer 123abc] } 0 test string-6.56 {string is integer, false} { list [string is integer [expr double(1)]] } 0 test string-6.57 {string is integer, false} { list [string is integer " "] } 0 test string-6.58 {string is integer, false on bad octal} jim { list [string is integer 036963] } 1 test string-6.59 {string is integer, false on bad octal} tcl { list [string is integer 036963] } 0 test string-6.60 {string is integer, false on bad hex} { list [string is integer 0X345XYZ] } 0 test string-6.61 {string is lower, true} { string is lower abc } 1 test string-6.62 {string is lower, false} { list [string is lower aBc] } 0 test string-6.63 {string is lower, false} { list [string is lower abc1] } 0 test string-6.64 {string is lower, unicode false} { list [string is lower abÜUE] } 0 test string-6.65 {string is space, true} { string is space " \t\n\v\f" } 1 test string-6.66 {string is space, false} { list [string is space " \t\n\v1\f"] } 0 test string-6.75 {string is upper, true} { string is upper ABC } 1 test string-6.77 {string is upper, false} { list [string is upper AbC] } 0 test string-6.78 {string is upper, false} { list [string is upper AB2C] } 0 test string-6.84 {string is control} { ## Control chars are in the ranges ## 00..1F && 7F..9F list [string is control \x00\x01\x10\x1F\x7F\x80\x9F\x60] } 0 test string-6.85 {string is control} tcl { string is control \u0100 } 0 test string-6.86 {string is graph} { ## graph is any print char, except space list [string is gra "0123abc!@#\$ "] } 0 test string-6.87 {string is print} { ## basically any printable char list [string is print "0123abc!@#\$ \010"] } 0 test string-6.88 {string is punct} { ## any graph char that isn't alnum list [string is punct "_!@#\000beq0"] } 0 test string-6.89 {string is xdigit} { list [string is xdigit 0123456789\u0061bcdefABCDEFg] } 0 test string-7.1 {string last, too few args} { list [catch {string last a} msg] } {1} test string-7.2 {string last, bad args} { list [catch {string last a b c} msg] } {1} test string-7.3 {string last, too many args} { list [catch {string last a b c d} msg] } {1} test string-7.4 {string last} { string la xxx xxxx123xx345x678 } 1 test string-7.5 {string last} { string last xx xxxx123xx345x678 } 7 test string-7.6 {string last} { string las x xxxx123xx345x678 } 12 test string-7.13 {string last, start index} { ## Constrain to last 'a' should work string last ba badbad end-1 } 3 test string-7.14 {string last, start index} { ## Constrain to last 'b' should skip last 'ba' string last ba badbad end-2 } 0 test string-7.15 {string last, start index} { string last \u00dca \u00dcad\u00dcad 0 } -1 test string-7.16 {string last, start index} utf8 { string last \u00dca \u00dcad\u00dcad end-1 } 3 test string-7.17 {string last, too few args} { string last abc def } -1 test string-9.1 {string length} { list [catch {string length} msg] } {1} test string-9.2 {string length} { list [catch {string length a b} msg] } {1} test string-9.3 {string length} { string length "a little string" } 15 test string-9.4 {string length} { string le "" } 0 test string-10.1 {string map, too few args} { list [catch {string map} msg] } {1} test string-10.2 {string map, bad args} { list [catch {string map {a b} abba oops} msg] } {1} test string-10.3 {string map, too many args} { list [catch {string map -nocase {a b} str1 str2} msg] } {1} test string-10.4 {string map} { string map {a b} abba } {bbbb} test string-10.5 {string map} { string map {a b} a } {b} test string-10.6 {string map -nocase} { string map -nocase {a b} Abba } {bbbb} test string-10.7 {string map} { string map {abc 321 ab * a A} aabcabaababcab } {A321*A*321*} test string-10.8 {string map -nocase} { string map -nocase {aBc 321 Ab * a A} aabcabaababcab } {A321*A*321*} test string-10.9 {string map -nocase} { string map -no {abc 321 Ab * a A} aAbCaBaAbAbcAb } {A321*A*321*} test string-10.10 {string map} { list [catch {string map {a b c} abba} msg] } {1} test string-10.11 {string map, nulls} { string map {\x00 NULL blah \x00nix} {qwerty} } {qwerty} test string-10.12 {string map, unicode} { string map [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU" } aueue\u00dc\0EU test string-10.13 {string map, -nocase unicode} { string map -nocase [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU" } aue\u00dc\u00dc\0EU test string-10.14 {string map, -nocase null arguments} { string map -nocase {{} abc} foo } foo test string-10.15 {string map, one pair case} { string map -nocase {abc 32} aAbCaBaAbAbcAb } {a32aBaAb32Ab} test string-10.16 {string map, one pair case} { string map -nocase {ab 4321} aAbCaBaAbAbcAb } {a4321C4321a43214321c4321} test string-10.17 {string map, one pair case} { string map {Ab 4321} aAbCaBaAbAbcAb } {a4321CaBa43214321c4321} test string-11.1 {string match, too few args} { list [catch {string match a} msg] } {1} test string-11.2 {string match, too many args} { list [catch {string match a b c d} msg] } {1} test string-11.3 {string match} { string match abc abc } 1 test string-11.4 {string match} { string mat abc abd } 0 test string-11.5 {string match} { string match ab*c abc } 1 test string-11.6 {string match} { string match ab**c abc } 1 test string-11.7 {string match} { string match ab* abcdef } 1 test string-11.8 {string match} { string match *c abc } 1 test string-11.9 {string match} { string match *3*6*9 0123456789 } 1 test string-11.10 {string match} { string match *3*6*9 01234567890 } 0 test string-11.11 {string match} { string match a?c abc } 1 test string-11.12 {string match} { string match a??c abc } 0 test string-11.13 {string match} { string match ?1??4???8? 0123456789 } 1 test string-11.14 {string match} { string match {[abc]bc} abc } 1 test string-11.15 {string match} { string match {a[abc]c} abc } 1 test string-11.16 {string match} { string match {a[xyz]c} abc } 0 test string-11.17 {string match} { string match {12[2-7]45} 12345 } 1 test string-11.18 {string match} { string match {12[ab2-4cd]45} 12345 } 1 test string-11.19 {string match} { string match {12[ab2-4cd]45} 12b45 } 1 test string-11.20 {string match} { string match {12[ab2-4cd]45} 12d45 } 1 test string-11.21 {string match} { string match {12[ab2-4cd]45} 12145 } 0 test string-11.22 {string match} { string match {12[ab2-4cd]45} 12545 } 0 test string-11.23 {string match} { string match {a\*b} a*b } 1 test string-11.24 {string match} { string match {a\*b} ab } 0 test string-11.25 {string match} { string match {a\*\?\[\]\\\x} "a*?\[\]\\x" } 1 test string-11.26 {string match} { string match ** "" } 1 test string-11.27 {string match} { string match *. "" } 0 test string-11.28 {string match} { string match "" "" } 1 test string-11.29 {string match} { string match \[a a } 1 test string-11.30 {string match, bad args} { list [catch {string match - b c} msg] } {1} test string-11.31 {string match case} { string match a A } 0 test string-11.32 {string match nocase} { string match -nocase a A } 1 test string-11.34 {string match nocase} { string match -nocase a*f ABCDEf } 1 test string-11.35 {string match case, false hope} { # This is true because '_' lies between the A-Z and a-z ranges string match {[A-z]} _ } 1 test string-11.36 {string match nocase range} { # This is false because although '_' lies between the A-Z and a-z ranges, # we lower case the end points before checking the ranges. string match -nocase {[A-z]} _ } 0 test string-11.37 {string match nocase} { string match -nocase {[A-fh-Z]} g } 0 test string-11.38 {string match case, reverse range} { string match {[A-fh-Z]} g } 1 test string-11.39 {string match, *\ case} { string match {*\abc} abc } 1 test string-11.40 {string match, *special case} { string match {*[ab]} abc } 0 test string-11.41 {string match, *special case} { string match {*[ab]*} abc } 1 # I don't see why this shouldn't match. Ignored for jim test string-11.42 {string match, *special case} tcl { string match "*\\" "\\" } 0 test string-11.43 {string match, *special case} { string match "*\\\\" "\\" } 1 test string-11.44 {string match, *special case} { string match "*???" "12345" } 1 test string-11.45 {string match, *special case} { string match "*???" "12" } 0 test string-11.46 {string match, *special case} { string match "*\\*" "abc*" } 1 test string-11.47 {string match, *special case} { string match "*\\*" "*" } 1 test string-11.48 {string match, *special case} { string match "*\\*" "*abc" } 0 test string-11.49 {string match, *special case} { string match "?\\*" "a*" } 1 # I don't see why this shouldn't match. Ignored for jim test string-11.50 {string match, *special case} tcl { string match "\\" "\\" } 0 test string-12.1 {string range} { list [catch {string range} msg] } {1} test string-12.2 {string range} { list [catch {string range a 1} msg] } {1} test string-12.3 {string range} { list [catch {string range a 1 2 3} msg] } {1} test string-12.4 {string range} { string range abcdefghijklmnop 2 14 } {cdefghijklmno} test string-12.5 {string range, last > length} { string range abcdefghijklmnop 7 1000 } {hijklmnop} test string-12.6 {string range} { string range abcdefghijklmnop 10 end } {klmnop} test string-12.7 {string range, last < first} { string range abcdefghijklmnop 10 9 } {} test string-12.8 {string range, first < 0} { string range abcdefghijklmnop -3 2 } {abc} test string-12.9 {string range} { string range abcdefghijklmnop -3 -2 } {} test string-12.10 {string range} { string range abcdefghijklmnop 1000 1010 } {} test string-12.11 {string range} { string range abcdefghijklmnop -100 end } {abcdefghijklmnop} test string-12.12 {string range} { list [catch {string range abc abc 1} msg] } {1} test string-12.13 {string range} { list [catch {string range abc 1 eof} msg] } {1} test string-12.14 {string range} { string range abcdefghijklmnop end-1 end } {op} test string-12.15 {string range} { string range abcdefghijklmnop end 1000 } {p} test string-12.16 {string range} { string range abcdefghijklmnop end end-1 } {} test string-13.1 {string repeat} { list [catch {string repeat} msg] } {1} test string-13.2 {string repeat} { list [catch {string repeat abc 10 oops} msg] } {1} test string-13.3 {string repeat} { string repeat {} 100 } {} test string-13.4 {string repeat} { string repeat { } 5 } { } test string-13.5 {string repeat} { string repeat abc 3 } {abcabcabc} test string-13.6 {string repeat} { string repeat abc -1 } {} test string-13.7 {string repeat} { list [catch {string repeat abc end} msg] } {1} test string-13.8 {string repeat} { string repeat {} -1000 } {} test string-13.9 {string repeat} { string repeat {} 0 } {} test string-13.10 {string repeat} { string repeat def 0 } {} test string-13.11 {string repeat} { string repeat def 1 } def test string-13.12 {string repeat} { string repeat ab\u7266cd 3 } ab\u7266cdab\u7266cdab\u7266cd test string-13.13 {string repeat} { string repeat \x00 3 } \x00\x00\x00 test string-14.1 {string replace} { list [catch {string replace} msg] $msg } {1 {wrong # args: should be "string replace string first last ?string?"}} test string-14.2 {string replace} { list [catch {string replace a 1} msg] $msg } {1 {wrong # args: should be "string replace string first last ?string?"}} test string-14.3 {string replace} { list [catch {string replace a 1 2 3 4} msg] $msg } {1 {wrong # args: should be "string replace string first last ?string?"}} test string-14.4 {string replace} { } {} test string-14.5 {string replace} { string replace abcdefghijklmnop 2 14 } {abp} test string-14.6 {string replace} { string replace abcdefghijklmnop 7 1000 } {abcdefg} test string-14.7 {string replace} { string replace abcdefghijklmnop 10 end } {abcdefghij} test string-14.8 {string replace} { string replace abcdefghijklmnop 10 9 } {abcdefghijklmnop} test string-14.9 {string replace} { string replace abcdefghijklmnop -3 2 } {defghijklmnop} test string-14.10 {string replace} { string replace abcdefghijklmnop -3 -2 } {abcdefghijklmnop} test string-14.11 {string replace} { string replace abcdefghijklmnop 1000 1010 } {abcdefghijklmnop} test string-14.12 {string replace} { string replace abcdefghijklmnop -100 end } {} test string-14.13 {string replace} { list [catch {string replace abc abc 1} msg] $msg } {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}} test string-14.14 {string replace} { list [catch {string replace abc 1 eof} msg] $msg } {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}} test string-14.15 {string replace} { string replace abcdefghijklmnop end-10 end-2 NEW } {abcdeNEWop} test string-14.16 {string replace} { string replace abcdefghijklmnop 0 end foo } {foo} test string-14.17 {string replace} { string replace abcdefghijklmnop end end-1 } {abcdefghijklmnop} test string-15.1 {string tolower too few args} { list [catch {string tolower} msg] } {1} test string-15.2 {string tolower bad args} { list [catch {string tolower a b} msg] } {1} test string-15.3 {string tolower too many args} { list [catch {string tolower ABC 1 end oops} msg] } {1} test string-15.4 {string tolower} { string tolower ABCDeF } {abcdef} test string-15.5 {string tolower} { string tolower "ABC XyZ" } {abc xyz} test string-15.6 {string tolower} { string tolower {123#$&*()} } {123#$&*()} test string-16.1 {string toupper} { list [catch {string toupper} msg] } {1} test string-16.2 {string toupper} { list [catch {string toupper a b} msg] } {1} test string-16.4 {string toupper} { string toupper abCDEf } {ABCDEF} test string-16.5 {string toupper} { string toupper "abc xYz" } {ABC XYZ} test string-16.6 {string toupper} { string toupper {123#$&*()} } {123#$&*()} test string-17.1 {string totitle} -body { string totitle } -returnCodes error -match glob -result {wrong # args: should be "string totitle string*} test string-17.3 {string totitle} { string totitle abCDEf } {Abcdef} test string-17.4 {string totitle} { string totitle "abc xYz" } {Abc xyz} test string-17.5 {string totitle} { string totitle {123#$&*()} } {123#$&*()} test string-18.1 {string trim} { list [catch {string trim} msg] } {1} test string-18.2 {string trim} { list [catch {string trim a b c} msg] } {1} test string-18.3 {string trim} { string trim " XYZ " } {XYZ} test string-18.4 {string trim} { string trim "\t\nXYZ\t\n\r\n" } {XYZ} test string-18.5 {string trim} { string trim " A XYZ A " } {A XYZ A} test string-18.6 {string trim} { string trim "XXYYZZABC XXYYZZ" ZYX } {ABC } test string-18.7 {string trim} { string trim " \t\r " } {} test string-18.8 {string trim} { string trim {abcdefg} {} } {abcdefg} test string-18.9 {string trim} { string trim {} } {} test string-18.10 {string trim} { string trim ABC DEF } {ABC} test string-18.11 {string trim, unicode} { string trim "\xe7\xe8 AB\xe7C \xe8\xe7" \xe7\xe8 } " AB\xe7C " test string-19.1 {string trimleft} { list [catch {string trimleft} msg] } {1} test string-19.2 {string trimleft} { string trimleft " XYZ " } {XYZ } test string-20.1 {string trimright errors} { list [catch {string trimright} msg] } {1} test string-20.2 {string trimright errors} { list [catch {string trimg a} msg] } {1} test string-20.3 {string trimright} { string trimright " XYZ " } { XYZ} test string-20.4 {string trimright} { string trimright " " } {} test string-20.5 {string trimright} { string trimright "" } {} # Test for 8-bit clean and utf-8 trim chars test string-21.1 {string trim embedded nulls} { string trim " abc\x00def " } "abc\x00def" test string-21.2 {string trimleft embedded nulls} { string trimleft " abc\x00def " } "abc\x00def " test string-21.3 {string trimright embedded nulls} { string trimright " abc\x00def " } " abc\x00def" test string-21.4 {string trim utf-8} { string trim "\u00b5\u00b6abc\x00def\u00b5\u00b5" "\u00b5\u00b6" } "abc\x00def" test string-22.1 {string replace} { string replace //test.net/path/path2?query=url?otherquery 21 end } {//test.net/path/path2} test string-23.1 {string cat} { string cat } {} test string-23.2 {string cat} { string cat abc } {abc} test string-23.3 {string cat} { string cat abc def } {abcdef} test string-23.4 {string cat} { set abc 123 string cat $abc (def) } {123(def)} testreport openocd-0.9.0/jimtcl/tests/signal.test0000644000175000017500000000345212516456445014712 00000000000000source [file dirname [info script]]/testing.tcl needs cmd signal needs cmd pid testConstraint try [expr {[info commands try] ne ""}] test signal-1.1 "catch/throw" { signal handle TERM set x 1 set rc [catch -signal { signal throw -TERM incr x } result] signal default TERM list [info returncode $rc] $result $x } {signal SIGTERM 1} test signal-1.2 "catch/kill" { signal handle TERM set x 1 set rc [catch -signal { kill -TERM [pid] incr x } result] signal default TERM list [info returncode $rc] $result $x } {signal SIGTERM 1} test signal-1.3 "catch/alarm" { signal handle ALRM set x 1 set rc [catch -signal { alarm .2 sleep 1 incr x } result] signal default ALRM list [info returncode $rc] $result $x } {signal SIGALRM 1} test signal-1.4 "multiple signals before catch" { signal handle ALRM INT kill -INT [pid] alarm .2 sleep 1 set x 1 set rc [catch -signal { # Doesn't not execute because signals already active incr x } result] signal default ALRM INT list [info returncode $rc] [lsort $result] $x } {signal {SIGALRM SIGINT} 1} test signal-1.5 "ignored signals" { signal handle INT signal ignore HUP set x 1 catch -signal { # Send an ignored signal kill -HUP [pid] incr x # Now a caught signal kill -INT [pid] incr x } result signal default INT TERM list [lsort $result] $x } {SIGINT 2} test signal-1.6 "check ignored signals" { list [signal check SIGINT] [signal check] } {{} SIGHUP} test signal-1.7 "clearing ignored signals" { signal check -clear signal check } {} test signal-1.8 "try/signal" try { signal handle ALRM try -signal { alarm 0.4 foreach i [range 10] { sleep 0.1 } set msg "" } on signal {msg} { # Just set msg here } finally { alarm 0 } signal default ALRM list [expr {$i in {3 4 5}}] $msg } {1 SIGALRM} testreport openocd-0.9.0/jimtcl/tests/lsort.test0000644000175000017500000002066412516456444014603 00000000000000# This file contains a collection of tests for the procedures in the # file tclCmdIL.c. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: lsort.test,v 1.12.2.2 2001/10/08 15:50:24 dkf Exp $ source [file dirname [info script]]/testing.tcl test lsort-1.1 {Tcl_LsortObjCmd procedure} jim { list [catch {lsort} msg] $msg } {1 {wrong # args: should be "lsort ?options? list"}} test lsort-1.2 {Tcl_LsortObjCmd procedure} jim { list [catch {lsort -foo {1 3 2 5}} msg] $msg } {1 {bad option "-foo": must be -ascii, -command, -decreasing, -increasing, -index, -integer, -nocase, -real, or -unique}} test lsort-1.3 {Tcl_LsortObjCmd procedure, default options} { lsort {d e c b a \{ d35 d300} } {a b c d d300 d35 e \{} test lsort-1.4 {Tcl_LsortObjCmd procedure, -ascii option} { lsort -integer -ascii {d e c b a d35 d300} } {a b c d d300 d35 e} test lsort-1.5 {Tcl_LsortObjCmd procedure, -command option} { list [catch {lsort -command {1 3 2 5}} msg] $msg } {1 {"-command" option must be followed by comparison command}} test lsort-1.6 {Tcl_LsortObjCmd procedure, -command option} { proc cmp {a b} { set rc [expr {[string match x* $b] - [string match x* $a]}] if {$rc == 0} { set rc [string compare $a $b] } return $rc } lsort -command cmp {x1 abc x2 def x3 x4} } {x1 x2 x3 x4 abc def} test lsort-1.7 {Tcl_LsortObjCmd procedure, -decreasing option} { lsort -decreasing {d e c b a d35 d300} } {e d35 d300 d c b a} test lsort-1.8 {Tcl_LsortObjCmd procedure, -real option} { lsort -real {24.2 6e3 150e-1} } {150e-1 24.2 6e3} test lsort-1.10 {Tcl_LsortObjCmd procedure, -increasing option} { lsort -decreasing -increasing {d e c b a d35 d300} } {a b c d d300 d35 e} test lsort-1.11 {Tcl_LsortObjCmd procedure, -index option} { list [catch {lsort -index {1 3 2 5}} msg] $msg } {1 {"-index" option must be followed by list index}} test lsort-1.12 {Tcl_LsortObjCmd procedure, -index option} { list [catch {lsort -index foo {1 3 2 5}} msg] $msg } {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}} test lsort-1.13 {Tcl_LsortObjCmd procedure, -index option} { lsort -index end -integer {{2 25} {10 20 50 100} {3 16 42} 1} } {1 {2 25} {3 16 42} {10 20 50 100}} test lsort-1.14 {Tcl_LsortObjCmd procedure, -index option} { lsort -index 1 -integer {{1 25 100} {3 16 42} {10 20 50}} } {{3 16 42} {10 20 50} {1 25 100}} test lsort-1.15 {Tcl_LsortObjCmd procedure, -integer option} { lsort -integer {24 6 300 18} } {6 18 24 300} test lsort-1.16 {Tcl_LsortObjCmd procedure, -integer option} { list [catch {lsort -integer {1 3 2.4}} msg] $msg } {1 {expected integer but got "2.4"}} test lsort-1.19 {Tcl_LsortObjCmd procedure, empty list} { lsort {} } {} test lsort-1.24 {Tcl_LsortObjCmd procedure, order of -index and -command} { catch {rename 1 ""} proc testcmp {a b} {return [string compare $a $b]} set l [list [list a b] [list c d]] set result [list [catch {lsort -command testcmp -index 1 $l} msg] $msg] rename testcmp "" set result } [list 0 [list [list a b] [list c d]]] test lsort-1.25 {Tcl_LsortObjCmd procedure, order of -index and -command} { catch {rename 1 ""} proc testcmp {a b} {return [string compare $a $b]} set l [list [list a b] [list c d]] set result [list [catch {lsort -index 1 -command testcmp $l} msg] $msg] rename testcmp "" set result } [list 0 [list [list a b] [list c d]]] # Note that the required order only exists in the end-1'th element; # indexing using the end element or any fixed offset from the start # will not work... test lsort-1.26 {Tcl_LsortObjCmd procedure, offset indexing from end} { lsort -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}} } {{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}} # Can't think of any good tests for the MergeSort and MergeLists # procedures, except a bunch of random lists to sort. test lsort-2.1 {MergeSort and MergeLists procedures} { set result {} set r 1435753299 proc rand {} { global r set r [expr {(16807 * $r) % (0x7fffffff)}] } for {set i 0} {$i < 150} {incr i} { set x {} for {set j 0} {$j < $i} {incr j} { lappend x [expr {[rand] & 0xfff}] } set y [lsort -integer $x] set old -1 foreach el $y { if {$el < $old} { append result "list {$x} sorted to {$y}, element $el out of order\n" break } set old $el } } set result } {} test lsort-3.1 {SortCompare procedure, skip comparisons after error} { set x 0 proc cmp {a b} { global x incr x error "error #$x" } list [catch {lsort -integer -command cmp {48 6 28 190 16 2 3 6 1}} msg] \ $msg $x } {1 {error #1} 1} test lsort-3.2 {lsort -real, returning indices} { lsort -decreasing -real {1.2 34.5 34.5 5.6} } {34.5 34.5 5.6 1.2} test lsort-3.3 {SortCompare procedure, -index option} jim { list [catch {lsort -integer -index 2 {{20 10} {15 30 40}}} msg] $msg } {1 {list index out of range}} test lsort-3.5 {SortCompare procedure, -index option} jim { list [catch {lsort -integer -index 2 {{20 10 13} {15}}} msg] $msg } {1 {list index out of range}} test lsort-3.6 {SortCompare procedure, -index option} { lsort -integer -index 2 {{1 15 30} {2 5 25} {3 25 20}} } {{3 25 20} {2 5 25} {1 15 30}} test lsort-3.7 {SortCompare procedure, -ascii option} { lsort -ascii {d e c b a d35 d300 100 20} } {100 20 a b c d d300 d35 e} test lsort-3.9 {SortCompare procedure, -integer option} { list [catch {lsort -integer {x 3}} msg] $msg } {1 {expected integer but got "x"}} test lsort-3.10 {SortCompare procedure, -integer option} { list [catch {lsort -integer {3 q}} msg] $msg } {1 {expected integer but got "q"}} test lsort-3.11 {SortCompare procedure, -integer option} { lsort -integer {35 21 0x20 30 023 100 8} } {8 21 023 30 0x20 35 100} test lsort-3.15 {SortCompare procedure, -command option} { proc cmp {a b} { error "comparison error" } list [catch {lsort -command cmp {48 6}} msg] $msg } {1 {comparison error}} test lsort-3.16 {SortCompare procedure, -command option, long command} { proc cmp {dummy a b} { string compare $a $b } lsort -command {cmp {this argument is very very long in order to make the dstring overflow its statically allocated space}} {{this first element is also long in order to help expand the dstring} {the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring}} } {{the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring} {this first element is also long in order to help expand the dstring}} test lsort-3.17 {SortCompare procedure, -command option, non-integer result} jim { proc cmp {a b} { return foow } list [catch {lsort -command cmp {48 6}} msg] $msg } {1 {expected integer but got "foow"}} test lsort-3.18 {SortCompare procedure, -command option} { proc cmp {a b} { expr {$b - $a} } lsort -command cmp {48 6 18 22 21 35 36} } {48 36 35 22 21 18 6} test lsort-3.19 {SortCompare procedure, -decreasing option} { lsort -decreasing -integer {35 21 0x20 30 023 100 8} } {100 35 0x20 30 023 21 8} test lsort-3.20 {SortCompare procedure, -real option} -body { lsort -real {6...4 3} } -returnCodes error -result {expected floating-point number but got "6...4"} test lsort-3.21 {lsort, unique sort} { lsort -integer -unique {3 1 2 3 1 4 3} } {1 2 3 4} test lsort-3.22 {lsort, unique sort with index} { # lsort -unique should return the last unique item # Note that lsort is not guarunteed to be a stable sort, so # allow for different lsort -int -unique {0 5 05 00 004 4} } {00 4 05} test lsort-4.26 {DefaultCompare procedure, signed characters} utf8 { set l [lsort [list "abc\u80" "abc"]] set viewlist {} foreach s $l { set viewelem "" set len [string length $s] for {set i 0} {$i < $len} {incr i} { set c [string index $s $i] scan $c %c d if {$d > 0 && $d < 128} { append viewelem $c } else { append viewelem "\\[format %03o [expr {$d & 0xff}]]" } } lappend viewlist $viewelem } set viewlist } [list "abc" "abc\\200"] test lsort-5.1 "Sort case insensitive" { lsort -nocase {ba aB aa ce} } {aa aB ba ce} testreport openocd-0.9.0/jimtcl/tests/tree.test0000644000175000017500000000454112315602575014366 00000000000000source [file dirname [info script]]/testing.tcl needs cmd tree needs cmd ref proc dputs {msg} { #puts $msg } test tree-1.1 "Create tree" { set pt [tree] return 1 } {1} test tree-1.2 "Root node depth" { $pt depth root } {0} test tree-1.3 "Access invalid node" { list [catch { $pt depth bogus } msg] $msg } {1 {key "bogus" not known in dictionary}} test tree-1.4 "Set key/value" { $pt set root key value $pt set root type root $pt set root name rootnode $pt set root values {} $pt get root key } {value} test tree-1.5 "Add child node" { set n [$pt insert root] $pt set $n childkey childvalue $pt set $n type level1type $pt set $n name childnode1 $pt set $n values {label testlabel} $pt get $n childkey } {childvalue} test tree-1.6 "Add child, child node" { set nn [$pt insert $n] $pt set $nn childkey2 childvalue2 $pt set $nn type level2type $pt set $nn name childnode2 $pt set $nn values {label testlabel storage none} $pt get $nn childkey2 } {childvalue2} test tree-1.7 "Key exists true" { $pt keyexists $nn childkey2 } {1} test tree-1.7 "Key exists false" { $pt keyexists $n boguskey } {0} test tree-1.8 "lappend" { $pt lappend $n newkey first $pt lappend $n newkey second $pt lappend $n newkey third $pt lappend $n newkey last } {first second third last} test tree-2.0 "Add more nodes" { set c [$pt insert root] $pt set $c name root.c2 set c [$pt insert root] $pt set $c name root.c3 set c [$pt insert $n] $pt set $c name n.c4 set c [$pt insert $n] $pt set $c name n.c5 set c [$pt insert $c] $pt set $c name n.c5.c6 return 1 } {1} test tree-2.1 "walk dfs" { set result {} dputs "" $pt walk root dfs {action n} { set indent [string repeat " " [$pt depth $n]] if {$action == "enter"} { lappend result [$pt get $n name] dputs "$indent[$pt get $n name]" } } dputs "" set result } {rootnode childnode1 childnode2 n.c4 n.c5 n.c5.c6 root.c2 root.c3} test tree-2.2 "walk dfs exit" { set result {} $pt walk root dfs {action n} { if {$action == "exit"} { lappend result [$pt get $n name] } } set result } {childnode2 n.c4 n.c5.c6 n.c5 childnode1 root.c2 root.c3 rootnode} test tree-2.3 "walk bfs" { set result {} $pt walk root bfs {action n} { if {$action == "enter"} { lappend result [$pt get $n name] } } set result } {rootnode childnode1 root.c2 root.c3 childnode2 n.c4 n.c5 n.c5.c6} $pt destroy testreport openocd-0.9.0/jimtcl/tests/filecopy.test0000644000175000017500000000414412516456444015245 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim needs cmd file needs cmd exec needs cmd parray tclcompat cd $testdir file mkdir tempdir test filecopy-1.1 "Simple case" { file copy testio.in tempfile } {} test filecopy-1.2 "Target exists" { list [catch {file copy testio.in tempfile} msg] $msg } {1 {error copying "testio.in" to "tempfile": file already exists}} test filecopy-1.3 "Source doesn't exist" { list [catch {file copy missing tempfile} msg] $msg } {1 {missing: No such file or directory}} test filecopy-1.4 "Can't write to target" { list [catch {file copy testio.in tempdir} msg] $msg } {1 {error copying "testio.in" to "tempdir": file already exists}} test filecopy-1.5 "Source doesn't exist and can't write to target" { list [catch {file copy missing tempdir} msg] $msg } {1 {missing: No such file or directory}} test filecopy-1.6 "Wrong args" { list [catch {file copy onearg} msg] $msg } {1 {wrong # args: should be "file copy ?-force? source dest"}} test filecopy-1.7 "Wrong args" { list [catch {file copy too many args here} msg] $msg } {1 {wrong # args: should be "file copy ?-force? source dest"}} test filecopy-1.8 "Wrong args" { list [catch {file copy -blah testio.in tempfile} msg] $msg } {1 {bad option "-blah": should be -force}} file delete tempfile test filecopy-2.1 "Simple case (-force)" { file copy -force testio.in tempfile } {} test filecopy-2.2 "Target exists (-force)" { file copy -force testio.in tempfile } {} test filecopy-2.3 "Source doesn't exist (-force)" { list [catch {file copy -force missing tempfile} msg] $msg } {1 {missing: No such file or directory}} test filecopy-2.4 "Can't write to target (-force)" -body { file copy -force testio.in tempdir } -returnCodes error -match glob -result {tempdir: *} test filecopy-2.5 "Source doesn't exist and can't write to target (-force)" { list [catch {file copy -force missing tempdir} msg] $msg } {1 {missing: No such file or directory}} test filecopy-2.6 "Source and target identical (-force)" { file copy -force tempfile tempfile file size tempfile } 16 file delete tempfile exec rm -rf tempdir testreport openocd-0.9.0/jimtcl/tests/linsert.test0000644000175000017500000000675112315602575015114 00000000000000# Commands covered: linsert # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl catch {unset lis} catch {rename p ""} test linsert-1.1 {linsert command} { linsert {1 2 3 4 5} 0 a } {a 1 2 3 4 5} test linsert-1.2 {linsert command} { linsert {1 2 3 4 5} 1 a } {1 a 2 3 4 5} test linsert-1.3 {linsert command} { linsert {1 2 3 4 5} 2 a } {1 2 a 3 4 5} test linsert-1.4 {linsert command} { linsert {1 2 3 4 5} 3 a } {1 2 3 a 4 5} test linsert-1.5 {linsert command} { linsert {1 2 3 4 5} 4 a } {1 2 3 4 a 5} test linsert-1.6 {linsert command} { linsert {1 2 3 4 5} 5 a } {1 2 3 4 5 a} test linsert-1.7 {linsert command} { linsert {1 2 3 4 5} 2 one two \{three \$four } {1 2 one two \{three {$four} 3 4 5} test linsert-1.8 {linsert command} { linsert {\{one \$two \{three \ four \ five} 2 a b c } {\{one {$two} a b c \{three { four} { five}} test linsert-1.9 {linsert command} { linsert {{1 2} {3 4} {5 6} {7 8}} 2 {x y} {a b} } {{1 2} {3 4} {x y} {a b} {5 6} {7 8}} test linsert-1.10 {linsert command} { linsert {} 2 a b c } {a b c} test linsert-1.11 {linsert command} { linsert {} 2 {} } {{}} test linsert-1.12 {linsert command} { linsert {a b "c c" d e} 3 1 } {a b {c c} 1 d e} test linsert-1.13 {linsert command} { linsert { a b c d} 0 1 2 } {1 2 a b c d} test linsert-1.14 {linsert command} { linsert {a b c {d e f}} 4 1 2 } {a b c {d e f} 1 2} test linsert-1.15 {linsert command} { linsert {a b c \{\ abc} 4 q r } {a b c \{\ q r abc} test linsert-1.16 {linsert command} { linsert {a b c \{ abc} 4 q r } {a b c \{ q r abc} test linsert-1.17 {linsert command} { linsert {a b c} end q r } {a b c q r} test linsert-1.18 {linsert command} { linsert {a} end q r } {a q r} test linsert-1.19 {linsert command} { linsert {} end q r } {q r} test linsert-1.20 {linsert command, use of end-int index} { linsert {a b c d} end-2 e f } {a b e f c d} test linsert-2.1 {linsert errors} { list [catch linsert msg] $msg } {1 {wrong # args: should be "linsert list index ?element ...?"}} test linsert-2.2 {linsert errors} { list [catch {linsert a b} msg] $msg } {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}} test linsert-2.3 {linsert errors} { list [catch {linsert a 12x 2} msg] $msg } {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}} test linsert-2.4 {linsert errors} tcl { list [catch {linsert \{ 12 2} msg] $msg } {1 {unmatched open brace in list}} test linsert-2.5 {syntax (TIP 323)} { linsert {a b c} 0 } [list a b c] test linsert-2.6 {syntax (TIP 323)} { linsert "a\nb\nc" 0 } [list a b c] test linsert-3.1 {linsert won't modify shared argument objects} { proc p {} { linsert "a b c" 1 "x y" return "a b c" } p } "a b c" test linsert-3.2 {linsert won't modify shared argument objects} { catch {unset lis} set lis [format "a \"%s\" c" "b"] linsert $lis 0 [string length $lis] } "7 a b c" # cleanup catch {unset lis} catch {rename p ""} ::tcltest::cleanupTests return openocd-0.9.0/jimtcl/tests/exec2.test0000644000175000017500000000223012315602575014426 00000000000000# These tests are design especially for the vfork() implementation # of exec where sh -c must be used and thus we must take extra care # in quoting arguments to exec. source [file dirname [info script]]/testing.tcl needs cmd exec set d \" set s ' set b \\ array set saveenv [array get env] test exec2-1.1 "Quoting - Result" { exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b} } "\"double\ quoted\"\ 'single quoted'\ \\backslash\ quoted\\" test exec2-1.2 "Quoting - Word Grouping" { string trim [exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b} | wc -w] } {6} test exec2-2.1 "Add to exec environment" { set env(TESTENV) "the value" exec printenv | sed -n -e /^TESTENV=/p } {TESTENV=the value} test exec2-2.2 "Remove from exec environment" { set env(TESTENV2) "new value" unset env(TESTENV) exec printenv | sed -n -e /^TESTENV=/p } {} test exec2-2.3 "Remove all exec environment" { array unset env * exec printenv | sed -n -e /^TESTENV2=/p } {} test exec2-2.4 "Remove all env var" { unset -nocomplain env exec printenv | sed -n -e /^TESTENV2=/p } {} array set env [array get saveenv] testreport openocd-0.9.0/jimtcl/tests/loop.test0000644000175000017500000000465312315602575014404 00000000000000source [file dirname [info script]]/testing.tcl # Check "loop" and its use of continue and break. needs cmd loop catch {unset a i} test loop-1.1 {loop tests} { set a {} loop i 1 6 { set a [concat $a $i] } set a } {1 2 3 4 5} test loop-1.2 {loop tests} { set a {} loop i 1 6 { if $i==4 continue set a [concat $a $i] } set a } {1 2 3 5} test loop-1.3 {loop tests} { set a {} loop i 1 6 { if $i==4 break set a [concat $a $i] } set a } {1 2 3} test loop-1.5 {loop errors} { catch {loop 1 2 3} msg } {1} test loop-1.6 {loop errors} { catch {loop 1 2 3 4 5} msg } {1} test loop-1.7 {loop tests} { set a {xyz} loop i 1 6 { } set a } xyz test loop-1.8 {error in loop} { set rc [catch { set a {} loop i 1 6 { lappend a $i if {$i == 3} { error "stop" } } }] list $a $rc } {{1 2 3} 1} test loop-1.9 {loop incr} { set a {} loop i 0 6 2 { lappend a $i } set a } {0 2 4} test loop-1.10 {no exec infinite loop} { set a {} loop i 0 6 -1 { lappend a $i break } set a } {} test loop-2.1 {loop shimmering tests} { loop i 1 6 { } set i } 6 test loop-2.2 {loop shimmering tests} { # Setting the variable inside the loop doesn't # affect the loop or the final variable value loop i 1 6 { set i blah } set i } 6 test loop-2.3 {loop shimmering tests} { set a {} loop i 1 6 { lappend a $i set i blah lappend a $i } set a } {1 blah 2 blah 3 blah 4 blah 5 blah} test loop-2.4 {loop shimmering tests} { set i xyz loop i 1 6 { } set i } 6 test loop-2.5 {loop shimmering tests} { # Ensure that the string rep of $i is updated set i {1 3} loop i(1) 1 6 { } set i } {1 6} test loop-2.6 {modify loop var} { unset -nocomplain i catch { loop i(1) 1 6 { # this makes it impossible to set the loop var set i blah } } } 1 test loop-2.7 {unset loop var} { unset -nocomplain i loop i 1 6 { # var will simply get recreated on each loop unset i } set i } 6 test loop-2.8 {modify loop var} { unset -nocomplain i set a {} loop i 1 6 { lappend a $i incr i } set a } {1 2 3 4 5} testreport break testreport openocd-0.9.0/jimtcl/tests/expr-old.test0000644000175000017500000007774112315602575015175 00000000000000# Commands covered: expr # # This file contains the original set of tests for Tcl's expr command. # Since the expr command is now compiled, a new set of tests covering # the new implementation are in the files "parseExpr.test and # "compExpr.test". Sourcing this file into Tcl runs the tests and generates # output for errors. No output means no errors were found. # # Copyright (c) 1991-1994 The Regents of the University of California. # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: expr-old.test,v 1.8.2.1 2002/04/18 13:10:27 msofer Exp $ source [file dirname [info script]]/testing.tcl # First, test all of the integer operators individually. test expr-old-1.1 {integer operators} {expr -4} -4 test expr-old-1.2 {integer operators} {expr -(1+4)} -5 test expr-old-1.3 {integer operators} {expr ~3} -4 test expr-old-1.4 {integer operators} {expr !2} 0 test expr-old-1.5 {integer operators} {expr !0} 1 test expr-old-1.6 {integer operators} {expr 4*6} 24 test expr-old-1.7 {integer operators} {expr 36/12} 3 test expr-old-1.8 {integer operators} {expr 27/4} 6 test expr-old-1.9 {integer operators} {expr 27%4} 3 test expr-old-1.10 {integer operators} {expr 2+2} 4 test expr-old-1.11 {integer operators} {expr 2-6} -4 test expr-old-1.12 {integer operators} {expr 1<<3} 8 test expr-old-1.13 {integer operators} {expr 0xff>>2} 63 test expr-old-1.14 {integer operators} {expr -1>>2} -1 test expr-old-1.15 {integer operators} {expr 3>2} 1 test expr-old-1.16 {integer operators} {expr 2>2} 0 test expr-old-1.17 {integer operators} {expr 1>2} 0 test expr-old-1.18 {integer operators} {expr 3<2} 0 test expr-old-1.19 {integer operators} {expr 2<2} 0 test expr-old-1.20 {integer operators} {expr 1<2} 1 test expr-old-1.21 {integer operators} {expr 3>=2} 1 test expr-old-1.22 {integer operators} {expr 2>=2} 1 test expr-old-1.23 {integer operators} {expr 1>=2} 0 test expr-old-1.24 {integer operators} {expr 3<=2} 0 test expr-old-1.25 {integer operators} {expr 2<=2} 1 test expr-old-1.26 {integer operators} {expr 1<=2} 1 test expr-old-1.27 {integer operators} {expr 3==2} 0 test expr-old-1.28 {integer operators} {expr 2==2} 1 test expr-old-1.29 {integer operators} {expr 3!=2} 1 test expr-old-1.30 {integer operators} {expr 2!=2} 0 test expr-old-1.31 {integer operators} {expr 7&0x13} 3 test expr-old-1.32 {integer operators} {expr 7^0x13} 20 test expr-old-1.33 {integer operators} {expr 7|0x13} 23 test expr-old-1.34 {integer operators} {expr 0&&1} 0 test expr-old-1.35 {integer operators} {expr 0&&0} 0 test expr-old-1.36 {integer operators} {expr 1&&3} 1 test expr-old-1.37 {integer operators} {expr 0||1} 1 test expr-old-1.38 {integer operators} {expr 3||0} 1 test expr-old-1.39 {integer operators} {expr 0||0} 0 test expr-old-1.40 {integer operators} {expr 3>2?44:66} 44 test expr-old-1.41 {integer operators} {expr 2>3?44:66} 66 test expr-old-1.42 {integer operators} {expr 36/5} 7 test expr-old-1.43 {integer operators} {expr 36%5} 1 test expr-old-1.44 {integer operators} {expr -36/5} -8 test expr-old-1.45 {integer operators} {expr -36%5} 4 test expr-old-1.46 {integer operators} {expr 36/-5} -8 test expr-old-1.47 {integer operators} {expr 36%-5} -4 test expr-old-1.48 {integer operators} {expr -36/-5} 7 test expr-old-1.49 {integer operators} {expr -36%-5} -1 test expr-old-1.50 {integer operators} {expr +36} 36 test expr-old-1.51 {integer operators} {expr +--++36} 36 test expr-old-1.52 {integer operators} {expr +36%+5} 1 test expr-old-1.53 {integer operators} { catch {unset x} set x 1 list [expr {1 && $x}] [expr {$x && 1}] \ [expr {0 || $x}] [expr {$x || 0}] } {1 1 1 1} # Check the floating-point operators individually, along with # automatic conversion to integers where needed. test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2 test expr-old-2.2 {floating-point operators} jim {expr -(1.1+4.2)} -5.3 test expr-old-2.3 {floating-point operators} {expr +5.7} 5.7 test expr-old-2.4 {floating-point operators} {expr +--+-62.0} -62.0 test expr-old-2.5 {floating-point operators} {expr !2.1} 0 test expr-old-2.6 {floating-point operators} {expr !0.0} 1 test expr-old-2.7 {floating-point operators} {expr 4.2*6.3} 26.46 test expr-old-2.8 {floating-point operators} {expr 36.0/12.0} 3.0 test expr-old-2.9 {floating-point operators} {expr 27/4.0} 6.75 test expr-old-2.10 {floating-point operators} {expr 2.3+2.1} 4.4 test expr-old-2.11 {floating-point operators} {expr 2.3-6.5} -4.2 test expr-old-2.12 {floating-point operators} {expr 3.1>2.1} 1 test expr-old-2.13 {floating-point operators} {expr {2.1 > 2.1}} 0 test expr-old-2.14 {floating-point operators} {expr 1.23>2.34e+1} 0 test expr-old-2.15 {floating-point operators} {expr 3.45<2.34} 0 test expr-old-2.16 {floating-point operators} {expr 0.002e3<--200e-2} 0 test expr-old-2.17 {floating-point operators} {expr 1.1<2.1} 1 test expr-old-2.18 {floating-point operators} {expr 3.1>=2.2} 1 test expr-old-2.19 {floating-point operators} {expr 2.345>=2.345} 1 test expr-old-2.20 {floating-point operators} {expr 1.1>=2.2} 0 test expr-old-2.21 {floating-point operators} {expr 3.0<=2.0} 0 test expr-old-2.22 {floating-point operators} {expr 2.2<=2.2} 1 test expr-old-2.23 {floating-point operators} {expr 2.2<=2.2001} 1 test expr-old-2.24 {floating-point operators} {expr 3.2==2.2} 0 test expr-old-2.25 {floating-point operators} {expr 2.2==2.2} 1 test expr-old-2.26 {floating-point operators} {expr 3.2!=2.2} 1 test expr-old-2.27 {floating-point operators} {expr 2.2!=2.2} 0 test expr-old-2.28 {floating-point operators} {expr 0.0&&0.0} 0 test expr-old-2.29 {floating-point operators} {expr 0.0&&1.3} 0 test expr-old-2.30 {floating-point operators} {expr 1.3&&0.0} 0 test expr-old-2.31 {floating-point operators} {expr 1.3&&3.3} 1 test expr-old-2.32 {floating-point operators} {expr 0.0||0.0} 0 test expr-old-2.33 {floating-point operators} {expr 0.0||1.3} 1 test expr-old-2.34 {floating-point operators} {expr 1.3||0.0} 1 test expr-old-2.35 {floating-point operators} {expr 3.3||0.0} 1 test expr-old-2.36 {floating-point operators} {expr 3.3>2.3?44.3:66.3} 44.3 test expr-old-2.37 {floating-point operators} {expr 2.3>3.3?44.3:66.3} 66.3 test expr-old-2.38 {floating-point operators} { list [catch {expr 028.1 + 09.2} msg] $msg } {0 37.3} # Operators that aren't legal on floating-point numbers test expr-old-3.1 {illegal floating-point operations} { list [catch {expr ~4.0} msg] } {1} test expr-old-3.2 {illegal floating-point operations} { list [catch {expr 27%4.0} msg] } {1} test expr-old-3.3 {illegal floating-point operations} { list [catch {expr 27.0%4} msg] } {1} test expr-old-3.4 {illegal floating-point operations} { list [catch {expr 1.0<<3} msg] } {1} test expr-old-3.5 {illegal floating-point operations} { list [catch {expr 3<<1.0} msg] } {1} test expr-old-3.6 {illegal floating-point operations} { list [catch {expr 24.0>>3} msg] } {1} test expr-old-3.7 {illegal floating-point operations} { list [catch {expr 24>>3.0} msg] } {1} test expr-old-3.8 {illegal floating-point operations} { list [catch {expr 24&3.0} msg] } {1} test expr-old-3.9 {illegal floating-point operations} { list [catch {expr 24.0|3} msg] } {1} test expr-old-3.10 {illegal floating-point operations} { list [catch {expr 24.0^3} msg] } {1} # Check the string operators individually. test expr-old-4.1 {string operators} {expr {"abc" > "def"}} 0 test expr-old-4.2 {string operators} {expr {"def" > "def"}} 0 test expr-old-4.3 {string operators} {expr {"g" > "def"}} 1 test expr-old-4.4 {string operators} {expr {"abc" < "abd"}} 1 test expr-old-4.5 {string operators} {expr {"abd" < "abd"}} 0 test expr-old-4.6 {string operators} {expr {"abe" < "abd"}} 0 test expr-old-4.7 {string operators} {expr {"abc" >= "def"}} 0 test expr-old-4.8 {string operators} {expr {"def" >= "def"}} 1 test expr-old-4.9 {string operators} {expr {"g" >= "def"}} 1 test expr-old-4.10 {string operators} {expr {"abc" <= "abd"}} 1 test expr-old-4.11 {string operators} {expr {"abd" <= "abd"}} 1 test expr-old-4.12 {string operators} {expr {"abe" <= "abd"}} 0 test expr-old-4.13 {string operators} {expr {"abc" == "abd"}} 0 test expr-old-4.14 {string operators} {expr {"abd" == "abd"}} 1 test expr-old-4.15 {string operators} {expr {"abc" != "abd"}} 1 test expr-old-4.16 {string operators} {expr {"abd" != "abd"}} 0 test expr-old-4.17 {string operators} {expr {"0y" < "0x12"}} 0 test expr-old-4.18 {string operators} {expr {"." < " "}} 0 # The following tests are non-portable because on some systems "+" # and "-" can be parsed as numbers. test expr-old-4.19 {string operators} {expr {"0" == "+"}} 0 test expr-old-4.20 {string operators} {expr {"0" == "-"}} 0 test expr-old-4.21 {string operators} {expr {1?"foo":"bar"}} foo test expr-old-4.22 {string operators} {expr {0?"foo":"bar"}} bar # Operators that aren't legal on string operands. test expr-old-5.1 {illegal string operations} { list [catch {expr {-"a"}} msg] } {1} test expr-old-5.2 {illegal string operations} { list [catch {expr {+"a"}} msg] } {1} test expr-old-5.3 {illegal string operations} { list [catch {expr {~"a"}} msg] } {1} test expr-old-5.4 {illegal string operations} { list [catch {expr {!"a"}} msg] } {1} test expr-old-5.5 {illegal string operations} { list [catch {expr {"a"*"b"}} msg] } {1} test expr-old-5.6 {illegal string operations} { list [catch {expr {"a"/"b"}} msg] } {1} test expr-old-5.7 {illegal string operations} { list [catch {expr {"a"%"b"}} msg] } {1} test expr-old-5.8 {illegal string operations} { list [catch {expr {"a"+"b"}} msg] } {1} test expr-old-5.9 {illegal string operations} { list [catch {expr {"a"-"b"}} msg] } {1} test expr-old-5.10 {illegal string operations} { list [catch {expr {"a"<<"b"}} msg] } {1} test expr-old-5.11 {illegal string operations} { list [catch {expr {"a">>"b"}} msg] } {1} test expr-old-5.12 {illegal string operations} { list [catch {expr {"a"&"b"}} msg] } {1} test expr-old-5.13 {illegal string operations} { list [catch {expr {"a"^"b"}} msg] } {1} test expr-old-5.14 {illegal string operations} { list [catch {expr {"a"|"b"}} msg] } {1} test expr-old-5.15 {illegal string operations} { list [catch {expr {"a"&&"b"}} msg] } {1} test expr-old-5.16 {illegal string operations} { list [catch {expr {"a"||"b"}} msg] } {1} test expr-old-5.17 {illegal string operations} { list [catch {expr {"a"?4:2}} msg] } {1} # Check precedence pairwise. test expr-old-6.1 {precedence checks} {expr -~3} 4 test expr-old-6.2 {precedence checks} {expr -!3} 0 test expr-old-6.3 {precedence checks} {expr -~0} 1 test expr-old-7.1 {precedence checks} {expr 2*4/6} 1 test expr-old-7.2 {precedence checks} {expr 24/6*3} 12 test expr-old-7.3 {precedence checks} {expr 24/6/2} 2 test expr-old-8.1 {precedence checks} {expr -2+4} 2 test expr-old-8.2 {precedence checks} {expr -2-4} -6 test expr-old-8.3 {precedence checks} {expr +2-4} -2 test expr-old-9.1 {precedence checks} {expr 2*3+4} 10 test expr-old-9.2 {precedence checks} {expr 8/2+4} 8 test expr-old-9.3 {precedence checks} {expr 8%3+4} 6 test expr-old-9.4 {precedence checks} {expr 2*3-1} 5 test expr-old-9.5 {precedence checks} {expr 8/2-1} 3 test expr-old-9.6 {precedence checks} {expr 8%3-1} 1 test expr-old-10.1 {precedence checks} {expr 6-3-2} 1 test expr-old-11.1 {precedence checks} {expr 7+1>>2} 2 test expr-old-11.2 {precedence checks} {expr 7+1<<2} 32 test expr-old-11.3 {precedence checks} {expr 7>>3-2} 3 test expr-old-11.4 {precedence checks} {expr 7<<3-2} 14 test expr-old-12.1 {precedence checks} {expr 6>>1>4} 0 test expr-old-12.2 {precedence checks} {expr 6>>1<2} 0 test expr-old-12.3 {precedence checks} {expr 6>>1>=3} 1 test expr-old-12.4 {precedence checks} {expr 6>>1<=2} 0 test expr-old-12.5 {precedence checks} {expr 6<<1>5} 1 test expr-old-12.6 {precedence checks} {expr 6<<1<5} 0 test expr-old-12.7 {precedence checks} {expr 5<=6<<1} 1 test expr-old-12.8 {precedence checks} {expr 5>=6<<1} 0 test expr-old-13.1 {precedence checks} {expr 2<3<4} 1 test expr-old-13.2 {precedence checks} {expr 0<4>2} 0 test expr-old-13.3 {precedence checks} {expr 4>2<1} 0 test expr-old-13.4 {precedence checks} {expr 4>3>2} 0 test expr-old-13.5 {precedence checks} {expr 4>3>=2} 0 test expr-old-13.6 {precedence checks} {expr 4>=3>2} 0 test expr-old-13.7 {precedence checks} {expr 4>=3>=2} 0 test expr-old-13.8 {precedence checks} {expr 0<=4>=2} 0 test expr-old-13.9 {precedence checks} {expr 4>=2<=0} 0 test expr-old-13.10 {precedence checks} {expr 2<=3<=4} 1 test expr-old-14.1 {precedence checks} {expr 1==4>3} 1 test expr-old-14.2 {precedence checks} {expr 0!=4>3} 1 test expr-old-14.3 {precedence checks} {expr 1==3<4} 1 test expr-old-14.4 {precedence checks} {expr 0!=3<4} 1 test expr-old-14.5 {precedence checks} {expr 1==4>=3} 1 test expr-old-14.6 {precedence checks} {expr 0!=4>=3} 1 test expr-old-14.7 {precedence checks} {expr 1==3<=4} 1 test expr-old-14.8 {precedence checks} {expr 0!=3<=4} 1 test expr-old-15.1 {precedence checks} {expr 1==3==3} 0 test expr-old-15.2 {precedence checks} {expr 3==3!=2} 1 test expr-old-15.3 {precedence checks} {expr 2!=3==3} 0 test expr-old-15.4 {precedence checks} {expr 2!=1!=1} 0 test expr-old-16.1 {precedence checks} {expr 2&3==2} 0 test expr-old-16.2 {precedence checks} {expr 1&3!=3} 0 test expr-old-17.1 {precedence checks} {expr 7&3^0x10} 19 test expr-old-17.2 {precedence checks} {expr 7^0x10&3} 7 test expr-old-18.1 {precedence checks} {expr 7^0x10|3} 23 test expr-old-18.2 {precedence checks} {expr 7|0x10^3} 23 test expr-old-19.1 {precedence checks} {expr 7|3&&1} 1 test expr-old-19.2 {precedence checks} {expr 1&&3|7} 1 test expr-old-19.3 {precedence checks} {expr 0&&1||1} 1 test expr-old-19.4 {precedence checks} {expr 1||1&&0} 1 test expr-old-20.1 {precedence checks} {expr 1||0?3:4} 3 test expr-old-20.2 {precedence checks} {expr 1?0:4||1} 0 test expr-old-20.3 {precedence checks} {expr 1?2:0?3:4} 2 test expr-old-20.4 {precedence checks} {expr 0?2:0?3:4} 4 test expr-old-20.5 {precedence checks} {expr 1?2?3:4:0} 3 test expr-old-20.6 {precedence checks} {expr 0?2?3:4:0} 0 test expr-old-20.7 {precedence checks} {expr 0?1?1?2:3:0?4:5:1?0?6:7:0?8:9} 7 # Parentheses. test expr-old-21.1 {parenthesization} {expr (2+4)*6} 36 test expr-old-21.2 {parenthesization} {expr (1?0:4)||1} 1 test expr-old-21.3 {parenthesization} {expr +(3-4)} -1 # Embedded commands and variable names. set a 16 test expr-old-22.1 {embedded variables} {expr {2*$a}} 32 test expr-old-22.2 {embedded variables} { set x -5 set y 10 expr {$x + $y} } {5} test expr-old-22.3 {embedded variables} { set x " -5" set y " +10" expr {$x + $y} } {5} test expr-old-22.4 {embedded commands and variables} {expr {[set a] - 14}} 2 test expr-old-22.5 {embedded commands and variables} { list [catch {expr {12 - [bad_command_name]}} msg] $msg } {1 {invalid command name "bad_command_name"}} # Double-quotes and things inside them. test expr-old-23.1 {double quotes} {expr {"abc"}} abc test expr-old-23.2 {double quotes} { set a 189 expr {"$a.bc"} } 189.bc test expr-old-23.3 {double quotes} { set b2 xyx expr {"$b2$b2$b2.[set b2].[set b2]"} } xyxxyxxyx.xyx.xyx test expr-old-23.4 {double quotes} {expr {"11\}\}22"}} 11}}22 test expr-old-23.5 {double quotes} {expr {"\*bc"}} {*bc} test expr-old-23.6 {double quotes} { catch {unset bogus__} list [catch {expr {"$bogus__"}} msg] $msg } {1 {can't read "bogus__": no such variable}} test expr-old-23.7 {double quotes} { list [catch {expr {"a[error Testing]bc"}} msg] $msg } {1 Testing} test expr-old-23.8 {double quotes} { list [catch {expr {"12398712938788234-1298379" != ""}} msg] $msg } {0 1} # Numbers in various bases. test expr-old-24.1 {numbers in different bases} {expr 0x20} 32 test expr-old-24.2 {numbers in different bases} {expr 015} 15 # Conversions between various data types. test expr-old-25.1 {type conversions} {expr 2+2.5} 4.5 test expr-old-25.2 {type conversions} {expr 2.5+2} 4.5 test expr-old-25.3 {type conversions} {expr 2-2.5} -0.5 test expr-old-25.4 {type conversions} {expr 2/2.5} 0.8 test expr-old-25.5 {type conversions} {expr 2>2.5} 0 test expr-old-25.6 {type conversions} {expr 2.5>2} 1 test expr-old-25.7 {type conversions} {expr 2<2.5} 1 test expr-old-25.8 {type conversions} {expr 2>=2.5} 0 test expr-old-25.9 {type conversions} {expr 2<=2.5} 1 test expr-old-25.10 {type conversions} {expr 2==2.5} 0 test expr-old-25.11 {type conversions} {expr 2!=2.5} 1 test expr-old-25.12 {type conversions} {expr 2>"ab"} 0 test expr-old-25.13 {type conversions} {expr {2>" "}} 1 test expr-old-25.14 {type conversions} {expr {"24.1a" > 24.1}} 1 test expr-old-25.15 {type conversions} {expr {24.1 > "24.1a"}} 0 test expr-old-25.16 {type conversions} {expr 2+2.5} 4.5 test expr-old-25.17 {type conversions} {expr 2+2.5} 4.5 test expr-old-25.18 {type conversions} {expr 2.0e2} 200.0 test expr-old-25.19 {type conversions} {expr 2.0e30} 2e+30 test expr-old-25.20 {type conversions} {expr 10.0} 10.0 # Various error conditions. test expr-old-26.1 {error conditions} { list [catch {expr 2+"a"} msg] } {1} test expr-old-26.2 {error conditions} { list [catch {expr 2+4*} msg] } {1} test expr-old-26.3 {error conditions} { list [catch {expr 2+4*(} msg] } {1} catch {unset _non_existent_} test expr-old-26.4 {error conditions} { list [catch {expr 2+$_non_existent_} msg] } {1} set a xx test expr-old-26.5 {error conditions} { list [catch {expr {2+$a}} msg] } {1} test expr-old-26.6 {error conditions} { list [catch {expr {2+[set a]}} msg] } {1} test expr-old-26.7 {error conditions} { list [catch {expr {2+(4}} msg] } {1} test expr-old-26.8 {error conditions} { list [catch {expr 2/0} msg] } {1} test expr-old-26.9 {error conditions} { list [catch {expr 2%0} msg] } {1} test expr-old-26.10 {error conditions} { expr 2.0/0.0 } {Inf} test expr-old-26.11 {error conditions} { list [catch {expr 2#} msg] } {1} test expr-old-26.12 {error conditions} { list [catch {expr a.b} msg] } {1} test expr-old-26.13 {error conditions} { list [catch {expr {"a"/"b"}} msg] } {1} test expr-old-26.14 {error conditions} { list [catch {expr 2:3} msg] } {1} test expr-old-26.15 {error conditions} { list [catch {expr a@b} msg] } {1} test expr-old-26.16 {error conditions} { list [catch {expr a[b} msg] } {1} test expr-old-26.17 {error conditions} { list [catch {expr a`b} msg] } {1} test expr-old-26.18 {error conditions} { list [catch {expr \"a\"\{b} msg] } {1} test expr-old-26.19 {error conditions} { list [catch {expr a} msg] } {1} test expr-old-26.20 {error conditions} { list [catch expr msg] } {1} # Cancelled evaluation. test expr-old-27.1 {cancelled evaluation} { set a 1 expr {0&&[set a 2]} set a } 1 test expr-old-27.2 {cancelled evaluation} { set a 1 expr {1||[set a 2]} set a } 1 test expr-old-27.3 {cancelled evaluation} { set a 1 expr {0?[set a 2]:1} set a } 1 test expr-old-27.4 {cancelled evaluation} { set a 1 expr {1?2:[set a 2]} set a } 1 catch {unset x} test expr-old-27.5 {cancelled evaluation} { list [catch {expr {[info exists x] && $x}} msg] $msg } {0 0} test expr-old-27.6 {cancelled evaluation} { list [catch {expr {0 && [concat $x]}} msg] $msg } {0 0} test expr-old-27.7 {cancelled evaluation} { set one 1 list [catch {expr {1 || 1/$one}} msg] $msg } {0 1} test expr-old-27.8 {cancelled evaluation} { list [catch {expr {1 || -"string"}} msg] $msg } {0 1} test expr-old-27.9 {cancelled evaluation} { list [catch {expr {1 || ("string" * ("x" && "y"))}} msg] $msg } {0 1} test expr-old-27.10 {cancelled evaluation} { set x -1.3 list [catch {expr {($x > 0) ? round($x) : 0}} msg] $msg } {0 0} test expr-old-27.11 {cancelled evaluation} { list [catch {expr {0 && foo}} msg] } {1} test expr-old-27.12 {cancelled evaluation} { list [catch {expr {0 ? 1 : foo}} msg] } {1} # Operands enclosed in braces #test expr-old-29.1 {braces} {expr {{abc}}} abc #test expr-old-29.2 {braces} {expr {{00010}}} 8 #test expr-old-29.3 {braces} {expr {{3.1200000}}} 3.12 #test expr-old-29.4 {braces} {expr {{a{b}{1 {2 3}}c}}} "a{b}{1 {2 3}}c" #test expr-old-29.5 {braces} { # list [catch {expr "\{abc"} msg] $msg #} {1 {missing close-brace}} # Very long values test expr-old-30.1 {long values} { set a "0000 1111 2222 3333 4444" set a "$a | $a | $a | $a | $a" set a "$a || $a || $a || $a || $a" expr {$a} } {0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444} test expr-old-30.2 {long values} { set a "000000000000000000000000000000" set a "$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a${a}5" expr $a } 5 # Expressions spanning multiple arguments test expr-old-31.1 {multiple arguments to expr command} { expr 4 + ( 6 *12) -3 } 73 test expr-old-31.2 {multiple arguments to expr command} { list [catch {expr 2 + (3 + 4} msg] } {1} test expr-old-31.3 {multiple arguments to expr command} { list [catch {expr 2 + 3 +} msg] } {1} test expr-old-31.4 {multiple arguments to expr command} { list [catch {expr 2 + 3 )} msg] } {1} # Math functions if {0} { test expr-old-32.1 {math functions in expressions} { format %.6g [expr acos(0.5)] } {1.0472} test expr-old-32.2 {math functions in expressions} { format %.6g [expr asin(0.5)] } {0.523599} test expr-old-32.3 {math functions in expressions} { format %.6g [expr atan(1.0)] } {0.785398} test expr-old-32.4 {math functions in expressions} { format %.6g [expr atan2(2.0, 2.0)] } {0.785398} test expr-old-32.5 {math functions in expressions} { format %.6g [expr ceil(1.999)] } {2} test expr-old-32.6 {math functions in expressions} { format %.6g [expr cos(.1)] } {0.995004} test expr-old-32.7 {math functions in expressions} { format %.6g [expr cosh(.1)] } {1.005} test expr-old-32.8 {math functions in expressions} { format %.6g [expr exp(1.0)] } {2.71828} test expr-old-32.9 {math functions in expressions} { format %.6g [expr floor(2.000)] } {2} test expr-old-32.10 {math functions in expressions} { format %.6g [expr floor(2.001)] } {2} test expr-old-32.11 {math functions in expressions} { format %.6g [expr fmod(7.3, 3.2)] } {0.9} test expr-old-32.12 {math functions in expressions} { format %.6g [expr hypot(3.0, 4.0)] } {5} test expr-old-32.13 {math functions in expressions} { format %.6g [expr log(2.8)] } {1.02962} test expr-old-32.14 {math functions in expressions} { format %.6g [expr log10(2.8)] } {0.447158} test expr-old-32.15 {math functions in expressions} { format %.6g [expr pow(2.1, 3.1)] } {9.97424} test expr-old-32.16 {math functions in expressions} { format %.6g [expr sin(.1)] } {0.0998334} test expr-old-32.17 {math functions in expressions} { format %.6g [expr sinh(.1)] } {0.100167} test expr-old-32.18 {math functions in expressions} { format %.6g [expr sqrt(2.0)] } {1.41421} test expr-old-32.19 {math functions in expressions} { format %.6g [expr tan(0.8)] } {1.02964} test expr-old-32.20 {math functions in expressions} { format %.6g [expr tanh(0.8)] } {0.664037} } test expr-old-32.21 {math functions in expressions} { format %.6g [expr abs(-1.8)] } {1.8} test expr-old-32.22 {math functions in expressions} { expr abs(10.0) } {10.0} test expr-old-32.23 {math functions in expressions} { format %.6g [expr abs(-4)] } {4} test expr-old-32.24 {math functions in expressions} { format %.6g [expr abs(66)] } {66} # The following test is different for 32-bit versus 64-bit architectures. #test expr-old-32.25 {math functions in expressions} { # list [catch {expr abs(0x8000000000000000)} msg] $msg #} {1 {integer value too large to represent}} test expr-old-32.26 {math functions in expressions} { expr double(1) } {1.0} test expr-old-32.27 {math functions in expressions} { expr double(1.1) } {1.1} test expr-old-32.28 {math functions in expressions} { expr int(1) } {1} test expr-old-32.29 {math functions in expressions} { expr int(1.4) } {1} test expr-old-32.30 {math functions in expressions} { expr int(1.6) } {1} test expr-old-32.31 {math functions in expressions} { expr int(-1.4) } {-1} test expr-old-32.32 {math functions in expressions} { expr int(-1.6) } {-1} #test expr-old-32.33 {math functions in expressions} { # list [catch {expr int(1e60)} msg] $msg #} {1 {integer value too large to represent}} #test expr-old-32.34 {math functions in expressions} { # list [catch {expr int(-1e60)} msg] $msg #} {1 {integer value too large to represent}} test expr-old-32.35 {math functions in expressions} { expr round(1.49) } {1} test expr-old-32.36 {math functions in expressions} { expr round(1.51) } {2} test expr-old-32.37 {math functions in expressions} { expr round(-1.49) } {-1} test expr-old-32.38 {math functions in expressions} { expr round(-1.51) } {-2} #test expr-old-32.39 {math functions in expressions} { # list [catch {expr round(1e60)} msg] $msg #} {1 {integer value too large to represent}} #test expr-old-32.40 {math functions in expressions} { # list [catch {expr round(-1e60)} msg] $msg #} {1 {integer value too large to represent}} if {0} { test expr-old-32.41 {math functions in expressions} { list [catch {expr pow(1.0 + 3.0 - 2, .8 * 5)} msg] $msg } {0 16.0} test expr-old-32.42 {math functions in expressions} { list [catch {expr hypot(5*.8,3)} msg] $msg } {0 5.0} test expr-old-32.45 {math functions in expressions} { expr (0 <= rand()) && (rand() < 1) } {1} test expr-old-32.46 {math functions in expressions} { list [catch {expr rand(24)} msg] $msg } {1 {too many arguments for math function}} test expr-old-32.47 {math functions in expressions} { list [catch {expr srand()} msg] $msg } {1 {too few arguments for math function}} test expr-old-32.48 {math functions in expressions} { list [catch {expr srand(3.79)} msg] $msg } {1 {can't use floating-point value as argument to srand}} test expr-old-32.49 {math functions in expressions} { list [catch {expr srand("")} msg] $msg } {1 {argument to math function didn't have numeric value}} test expr-old-32.50 {math functions in expressions} { set result [expr round(srand(12345) * 1000)] for {set i 0} {$i < 10} {incr i} { lappend result [expr round(rand() * 1000)] } set result } {97 834 948 36 12 51 766 585 914 784 333} test expr-old-32.51 {math functions in expressions} { list [catch {expr {srand([lindex "6ty" 0])}} msg] $msg } {1 {argument to math function didn't have numeric value}} test expr-old-33.1 {conversions and fancy args to math functions} { expr hypot ( 3 , 4 ) } 5.0 test expr-old-33.2 {conversions and fancy args to math functions} { expr hypot ( (2.0+1.0) , 4 ) } 5.0 test expr-old-33.3 {conversions and fancy args to math functions} { expr hypot ( 3 , (3.0 + 1.0) ) } 5.0 test expr-old-33.4 {conversions and fancy args to math functions} { format %.6g [expr cos(acos(0.1))] } 0.1 test expr-old-34.1 {errors in math functions} { list [catch {expr func_2(1.0)} msg] $msg } {1 {unknown math function "func_2"}} test expr-old-34.2 {errors in math functions} { list [catch {expr func|(1.0)} msg] $msg } {1 {syntax error in expression "func|(1.0)"}} test expr-old-34.3 {errors in math functions} { list [catch {expr {hypot("a b", 2.0)}} msg] $msg } {1 {argument to math function didn't have numeric value}} test expr-old-34.4 {errors in math functions} { list [catch {expr hypot(1.0 2.0)} msg] $msg } {1 {syntax error in expression "hypot(1.0 2.0)"}} test expr-old-34.5 {errors in math functions} { list [catch {expr hypot(1.0, 2.0} msg] $msg } {1 {syntax error in expression "hypot(1.0, 2.0"}} test expr-old-34.6 {errors in math functions} { list [catch {expr hypot(1.0 ,} msg] $msg } {1 {syntax error in expression "hypot(1.0 ,"}} test expr-old-34.7 {errors in math functions} { list [catch {expr hypot(1.0)} msg] $msg } {1 {too few arguments for math function}} test expr-old-34.8 {errors in math functions} { list [catch {expr hypot(1.0, 2.0, 3.0)} msg] $msg } {1 {too many arguments for math function}} test expr-old-34.9 {errors in math functions} { list [catch {expr acos(-2.0)} msg] $msg $errorCode } {1 {domain error: argument not in valid range} {ARITH DOMAIN {domain error: argument not in valid range}}} test expr-old-34.10 {errors in math functions} { list [catch {expr pow(-3, 1000001)} msg] $msg $errorCode } {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}} test expr-old-34.11 {errors in math functions} { list [catch {expr pow(3, 1000001)} msg] $msg $errorCode } {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}} test expr-old-34.12 {errors in math functions} { list [catch {expr -14.0*exp(100000)} msg] $msg $errorCode } {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}} test expr-old-34.13 {errors in math functions} { list [catch {expr int(1.0e30)} msg] $msg $errorCode } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}} test expr-old-34.14 {errors in math functions} { list [catch {expr int(-1.0e30)} msg] $msg $errorCode } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}} test expr-old-34.15 {errors in math functions} { list [catch {expr round(1.0e30)} msg] $msg $errorCode } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}} test expr-old-34.16 {errors in math functions} { list [catch {expr round(-1.0e30)} msg] $msg $errorCode } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}} test expr-old-36.1 {ExprLooksLikeInt procedure} { list [catch {expr 0289} msg] $msg } {1 {"0289" is an invalid octal number}} test expr-old-36.2 {ExprLooksLikeInt procedure} { set x 0289 list [catch {expr {$x+1}} msg] $msg } {1 {can't use invalid octal number as operand of "+"}} test expr-old-36.3 {ExprLooksLikeInt procedure} { list [catch {expr 0289.1} msg] $msg } {0 289.1} test expr-old-36.4 {ExprLooksLikeInt procedure} { set x 0289.1 list [catch {expr {$x+1}} msg] $msg } {0 290.1} test expr-old-36.5 {ExprLooksLikeInt procedure} { set x { +22} list [catch {expr {$x+1}} msg] $msg } {0 23} test expr-old-36.6 {ExprLooksLikeInt procedure} { set x { -22} list [catch {expr {$x+1}} msg] $msg } {0 -21} test expr-old-36.7 {ExprLooksLikeInt procedure} { list [catch {expr nan} msg] $msg } {1 {domain error: argument not in valid range}} test expr-old-36.8 {ExprLooksLikeInt procedure} { list [catch {expr 78e1} msg] $msg } {0 780.0} test expr-old-36.9 {ExprLooksLikeInt procedure} { list [catch {expr 24E1} msg] $msg } {0 240.0} test expr-old-36.10 {ExprLooksLikeInt procedure} { list [catch {expr 78e} msg] $msg } {1 {syntax error in expression "78e"}} } # test for [Bug #542588] # XXX: Can't rely on overflow checking #test expr-old-36.11 {ExprLooksLikeInt procedure} { # # define a "too large integer"; this one works also for 64bit arith # set x 665802003400000000000000 # list [catch {expr {$x+1}} msg] $msg #} {1 {can't use integer value too large to represent as operand of "+"}} # Special test for Pentium arithmetic bug of 1994: if {(4195835.0 - (4195835.0/3145727.0)*3145727.0) == 256.0} { puts "Warning: this machine contains a defective Pentium processor" puts "that performs arithmetic incorrectly. I recommend that you" puts "call Intel customer service immediately at 1-800-628-8686" puts "to request a replacement processor." puts [expr {(4195835.0 - (4195835.0/3145727.0)*3145727.0)}] } if {0.0 == 256.0} { puts error } testreport openocd-0.9.0/jimtcl/tests/error.test0000644000175000017500000000216412315602575014557 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim; needs cmd package proc a {} { error "error thrown from a" } proc b {} { set rc [catch {a} msg] if {$rc} { error $msg [info stacktrace] } } test error-1.1 "Rethrow caught error" { set rc [catch {b} msg] #puts stderr "error-1.1\n[errorInfo $msg]\n" list $rc $msg [info stacktrace] } {1 {error thrown from a} {{} error.test 4 a error.test 8 b error.test 15}} proc c {} { a } proc d {} { c } proc e {} { d } test error-1.2 "Modify stacktrace" { set rc [catch {e} msg] set st [info stacktrace] # Now elide one entry from the stacktrace #puts [errorInfo $msg] set newst {} foreach {p f l} $st { if {$p ne "d"} { lappend newst $p $f $l } } # Now rethrow with the new stack set rc [catch {error $msg $newst} msg] #puts [errorInfo $msg] info stacktrace } {{} error.test 4 a error.test 22 c error.test 26 e error.test 34} # Package should be able to invoke exit, which should exit if not caught test error-2.1 "Exit from package" { list [catch -exit {package require exitpackage} msg] $msg } {6 {Can't load package exitpackage}} testreport openocd-0.9.0/jimtcl/tests/alias.test0000644000175000017500000001064212315602575014517 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim needs cmd array needs cmd ref test alias-1.1 "One word alias" { set x 2 alias newincr incr newincr x } {3} test alias-1.4 "Two word alias" { alias infoexists info exists infoexists x } {1} test alias-1.5 "Replace alias" { alias newincr infoexists newincr x } {1} test alias-1.6 "Delete alias" { rename newincr "" catch {newincr x} } {1} test alias-1.7 "Replace alias with proc" { proc infoexists {n} { return yes } infoexists any } {yes} test alias-1.8 "Replace proc with alias" { alias infoexists info exists infoexists any } {0} test alias-1.9 "error message from alias" -body { alias newstring string newstring match } -returnCodes error -result {wrong # args: should be "string match ?-nocase? pattern string"} test alias-1.10 "info alias" { alias x info exists info alias x } {info exists} test alias-1.10 "info alias on non-alias" -body { info alias format } -returnCodes error -result {command "format" is not an alias} test curry-1.1 "One word curry" { set x 2 set one [curry incr] $one x } {3} test curry-1.4 "Two word curry" { set two [curry info exists] list [$two x] [$two y] } {1 0} test curry-1.5 "Delete curry" { unset one two collect } {2} test local-1.2 "local curry in proc" { proc a {} { local set p [curry info exists] set x 1 list $p [$p x] [$p y] } lassign [a] p exists_x exists_y list [info procs $p] $exists_x $exists_y } {{} 1 0} test local-1.2 "set local curry in proc" { proc a {} { set p [local curry info exists] set x 1 list $p [$p x] [$p y] } lassign [a] p exists_x exists_y list [info procs $p] $exists_x $exists_y } {{} 1 0} test local-1.3 "local alias in proc" { proc a {} { local alias p info exists set x 1 list [p x] [p y] } lassign [a] exists_x exists_y list [info commands p] $exists_x $exists_y } {{} 1 0} test local-1.5 "local proc in proc" { set ::x 1 proc a {} { local proc b {} { incr ::x } b set ::x } a list [info procs b] $::x } {{} 2} test local-1.6 "local lambda in lsort" { proc a {} { lsort -command [local lambda {a b} {string compare $a $b}] {d a f g} } a } {a d f g} test local-1.7 "check no reference procs" { info procs " 0} { set minIndex [expr [llength $list] - 1] set min [lindex $list $last] set i [expr $minIndex-1] while {$i >= 0} { if {[string compare [lindex $list $i] $min] < 0} { set minIndex $i set min [lindex $list $i] } set i [expr $i-1] } set result [concat $result [list $min]] if {$minIndex == 0} { set list [lrange $list 1 end] } else { set list [concat [lrange $list 0 [expr $minIndex-1]] \ [lrange $list [expr $minIndex+1] end]] } set last [expr $last-1] } return [concat $result $list] } test list-3.1 {SetListFromAny and lrange/concat results} { slowsort {fred julie alex carol bill annie} } {alex annie bill carol fred julie} testreport openocd-0.9.0/jimtcl/tests/proc.test0000644000175000017500000002327712315602575014401 00000000000000# Commands covered: proc, return, global # # This file, proc-old.test, includes the original set of tests for Tcl's # proc, return, and global commands. There is now a new file proc.test # that contains tests for the tclProc.c source file. # # Sourcing this file into Tcl runs the tests and generates output for # errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: proc-old.test,v 1.6 2000/04/10 17:19:03 ericm Exp $ source [file dirname [info script]]/testing.tcl needs constraint jim needs cmd array catch {rename t1 ""} catch {rename foo ""} proc tproc {} {return a; return b} test proc-old-1.1 {simple procedure call and return} {tproc} a proc tproc x { set x [expr $x+1] return $x } test proc-old-1.2 {simple procedure call and return} {tproc 2} 3 test proc-old-1.3 {simple procedure call and return} { proc tproc {} {return foo} } {tproc} test proc-old-1.4 {simple procedure call and return} { proc tproc {} {return} tproc } {} proc tproc1 {a} {incr a; return $a} proc tproc2 {a b} {incr a; return $a} test proc-old-1.5 {simple procedure call and return (2 procs with same body but different parameters)} { list [tproc1 123] [tproc2 456 789] } {124 457} test proc-old-1.6 {simple procedure call and return (shared proc body string)} { set x {} proc tproc {} {} ;# body is shared with x list [tproc] [append x foo] } {{} foo} test proc-old-2.1 {local and global variables} { proc tproc x { set x [expr $x+1] return $x } set x 42 list [tproc 6] $x } {7 42} test proc-old-2.2 {local and global variables} { proc tproc x { set y [expr $x+1] return $y } set y 18 list [tproc 6] $y } {7 18} test proc-old-2.3 {local and global variables} { proc tproc x { global y set y [expr $x+1] return $y } set y 189 list [tproc 6] $y } {7 7} test proc-old-2.4 {local and global variables} { proc tproc x { global y return [expr $x+$y] } set y 189 list [tproc 6] $y } {195 189} catch {unset _undefined_} test proc-old-2.5 {local and global variables} { proc tproc x { global _undefined_ return $_undefined_ } list [catch {tproc xxx} msg] $msg } {1 {can't read "_undefined_": no such variable}} test proc-old-2.6 {local and global variables} { set a 114 set b 115 global a b list $a $b } {114 115} proc do {cmd} {eval $cmd} test proc-old-3.1 {local and global arrays} { catch {unset a} set a(0) 22 list [catch {do {global a; set a(0)}} msg] $msg } {0 22} test proc-old-3.2 {local and global arrays} { catch {unset a} set a(x) 22 list [catch {do {global a; set a(x) newValue}} msg] $msg $a(x) } {0 newValue newValue} test proc-old-3.3 {local and global arrays} { catch {unset a} set a(x) 22 set a(y) 33 list [catch {do {global a; unset a(y)}; array names a} msg] $msg } {0 x} test proc-old-3.4 {local and global arrays} { catch {unset a} set a(x) 22 set a(y) 33 list [catch {do {global a; unset a; info exists a}} msg] $msg \ [info exists a] } {0 0 0} test proc-old-3.5 {local and global arrays} { catch {unset a} set a(x) 22 set a(y) 33 list [catch {do {global a; unset a(y); array names a}} msg] $msg } {0 x} catch {unset a} test proc-old-3.6 {local and global arrays} { catch {unset a} set a(x) 22 set a(y) 33 do {global a; do {global a; unset a}; set a(z) 22} list [catch {array names a} msg] $msg } {0 z} test proc-old-3.1 {arguments and defaults} { proc tproc {x y z} { return [list $x $y $z] } tproc 11 12 13 } {11 12 13} test proc-old-3.2 {arguments and defaults} { proc tproc {x y z} { return [list $x $y $z] } list [catch {tproc 11 12} msg] } {1} test proc-old-3.3 {arguments and defaults} { proc tproc {x y z} { return [list $x $y $z] } list [catch {tproc 11 12 13 14} msg] } {1} test proc-old-3.4 {arguments and defaults} { proc tproc {x {y y-default} {z z-default}} { return [list $x $y $z] } tproc 11 12 13 } {11 12 13} test proc-old-3.5 {arguments and defaults} { proc tproc {x {y y-default} {z z-default}} { return [list $x $y $z] } tproc 11 12 } {11 12 z-default} test proc-old-3.6 {arguments and defaults} { proc tproc {x {y y-default} {z z-default}} { return [list $x $y $z] } tproc 11 } {11 y-default z-default} test proc-old-3.7 {arguments and defaults} { proc tproc {x {y y-default} {z z-default}} { return [list $x $y $z] } list [catch {tproc} msg] } {1} # Note: This requires new TIP #288 support test proc-old-3.8 {arguments and defaults} { list [catch { proc tproc {x {y y-default} z} { return [list $x $y $z] } tproc 2 3 } msg] $msg } {0 {2 y-default 3}} test proc-old-3.9 {arguments and defaults} { proc tproc {x {y y-default} args} { return [list $x $y $args] } tproc 2 3 4 5 } {2 3 {4 5}} test proc-old-3.10 {arguments and defaults} { proc tproc {x {y y-default} args} { return [list $x $y $args] } tproc 2 3 } {2 3 {}} test proc-old-3.11 {arguments and defaults} { proc tproc {x {y y-default} args} { return [list $x $y $args] } tproc 2 } {2 y-default {}} test proc-old-3.12 {arguments and defaults} { proc tproc {x {y y-default} args} { return [list $x $y $args] } list [catch {tproc} msg] } {1} test proc-old-4.1 {variable numbers of arguments} { proc tproc args {return $args} tproc } {} test proc-old-4.2 {variable numbers of arguments} { proc tproc args {return $args} tproc 1 2 3 4 5 6 7 8 } {1 2 3 4 5 6 7 8} test proc-old-4.3 {variable numbers of arguments} { proc tproc args {return $args} tproc 1 {2 3} {4 {5 6} {{{7}}}} 8 } {1 {2 3} {4 {5 6} {{{7}}}} 8} test proc-old-4.4 {variable numbers of arguments} { proc tproc {x y args} {return $args} tproc 1 2 3 4 5 6 7 } {3 4 5 6 7} test proc-old-4.5 {variable numbers of arguments} { proc tproc {x y args} {return $args} tproc 1 2 } {} test proc-old-4.6 {variable numbers of arguments} { proc tproc {x missing args} {return $args} list [catch {tproc 1} msg] } {1} test proc-old-5.1 {error conditions} { list [catch {proc} msg] } {1} test proc-old-5.2 {error conditions} { list [catch {proc tproc b} msg] } {1} test proc-old-5.3 {error conditions} { list [catch {proc tproc b c d e} msg] } {1} test proc-old-5.6 {error conditions} { list [catch {proc tproc {{} y} {return foo}} msg] $msg } {1 {argument with no name}} test proc-old-5.7 {error conditions} { list [catch {proc tproc {{x 1 2} y} {return foo}} msg] $msg } {1 {too many fields in argument specifier "x 1 2"}} test proc-old-5.8 {error conditions} { catch {return} } 2 test proc-old-5.9 {error conditions} { list [catch {global} msg] $msg } {1 {wrong # args: should be "global varName ?varName ...?"}} proc tproc {} { set a 22 global a } test proc-old-5.10 {error conditions} { list [catch {tproc} msg] $msg } {1 {variable "a" already exists}} test proc-old-5.11 {error conditions} { catch {rename tproc {}} catch { proc tproc {x {} z} {return foo} } list [catch {tproc 1} msg] $msg } {1 {invalid command name "tproc"}} test proc-old-5.12 {error conditions} { proc tproc {} { set a 22 error "error in procedure" return } list [catch tproc msg] $msg } {1 {error in procedure}} # The tests below will really only be useful when run under Purify or # some other system that can detect accesses to freed memory... test proc-old-6.1 {procedure that redefines itself} { proc tproc {} { proc tproc {} { return 44 } return 45 } tproc } 45 test proc-old-6.2 {procedure that deletes itself} { proc tproc {} { rename tproc {} return 45 } tproc } 45 proc tproc code { return -code $code abc } test proc-old-7.1 {return with special completion code} { list [catch {tproc ok} msg] $msg } {0 abc} test proc-old-7.2 {return with special completion code} { list [catch {tproc error} msg] $msg } {1 abc} test proc-old-7.3 {return with special completion code} { list [catch {tproc return} msg] $msg } {2 abc} test proc-old-7.4 {return with special completion code} { list [catch {tproc break} msg] $msg } {3 abc} test proc-old-7.5 {return with special completion code} { list [catch {tproc continue} msg] $msg } {4 abc} test proc-old-7.6 {return with special completion code} { list [catch {tproc -14} msg] $msg } {-14 abc} test proc-old-7.7 {return with special completion code} { list [catch {tproc gorp} msg] } {1} test proc-old-7.8 {return with special completion code} { list [catch {tproc 10b} msg] } {1} test proc-old-7.9 {return with special completion code} { proc tproc2 {} { tproc return } list [catch tproc2 msg] $msg } {0 abc} test proc-old-7.10 {return with special completion code} { proc tproc2 {} { return -code error } list [catch tproc2 msg] $msg } {1 {}} test proc-old-8.1 {unset and undefined local arrays} { proc t1 {} { foreach v {xxx, yyy} { catch {unset $v} } set yyy(foo) bar } t1 } bar test proc-old-9.1 {empty command name} { catch {rename {} ""} proc t1 {args} { return } set v [t1] catch {$v} } 1 test proc-old-10.1 {ByteCode epoch change during recursive proc execution} { proc t1 x { set y 20 rename expr expr.old rename expr.old expr if $x then {t1 0} ;# recursive call after foo's code is invalidated return 20 } t1 1 } 20 # cleanup catch {rename t1 ""} catch {rename foo ""} testreport openocd-0.9.0/jimtcl/tests/timer.test0000644000175000017500000002565412315602575014557 00000000000000# This file contains a collection of tests for the procedures in the # file tclTimer.c, which includes the "after" Tcl command. Sourcing # this file into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1997 by Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: timer.test,v 1.7.2.1 2001/10/13 01:14:19 hobbs Exp $ source [file dirname [info script]]/testing.tcl needs cmd after eventloop test timer-1.1 {Tcl_CreateTimerHandler procedure} { foreach i [after info] { after cancel $i } set x "" foreach i {20 40 200 10 30} { after $i lappend x $i } after 50 update set x } {10 20 30 40} test timer-2.1 {Tcl_DeleteTimerHandler procedure} { foreach i [after info] { after cancel $i } set x "" foreach i {20 40 60 10 30} { after $i lappend x $i } after cancel lappend x 60 after cancel lappend x 10 after 50 update set x } {20 30 40} # No tests for Tcl_ServiceTimer or ResetTimer, since it is already tested # above. test timer-3.1 {TimerHandlerEventProc procedure: event masks} { set x start after 20 { set x fired } update idletasks set result $x after 40 update lappend result $x } {start fired} test timer-3.2 {TimerHandlerEventProc procedure: multiple timers} { foreach i [after info] { after cancel $i } foreach i {40 120 200} { after $i lappend x $i } after 50 set result "" set x "" update lappend result $x after 80 update lappend result $x after 80 update lappend result $x } {40 {40 120} {40 120 200}} test timer-3.3 {TimerHandlerEventProc procedure: reentrant timer deletion} { foreach i [after info] { after cancel $i } set x {} after 20 lappend x 20 set i [after 60 lappend x 60] after 40 after cancel $i after 80 update set x } 20 test timer-3.4 {TimerHandlerEventProc procedure: all expired timers fire} { foreach i [after info] { after cancel $i } set x {} after 20 lappend x a after 40 lappend x b after 60 lappend x c after 70 vwait x set x } {a b c} test timer-3.5 {TimerHandlerEventProc procedure: reentrantly added timers don't fire} { foreach i [after info] { after cancel $i } set x {} after 20 {lappend x a; after 0 lappend x b} after 20 vwait x set x } a test timer-3.6 {TimerHandlerEventProc procedure: reentrantly added timers don't fire} { foreach i [after info] { after cancel $i } set x {} after 20 {lappend x a; after 20 lappend x b; after 20} after 20 vwait x set result $x vwait x lappend result $x } {a {a b}} # No tests for Tcl_DoWhenIdle: it's already tested by other tests # below. test timer-4.1 {Tcl_CancelIdleCall procedure} { foreach i [after info] { after cancel $i } set x before set y before set z before after idle set x after1 after idle set y after2 after idle set z after3 after cancel set y after2 update idletasks concat $x $y $z } {after1 before after3} test timer-4.2 {Tcl_CancelIdleCall procedure} { foreach i [after info] { after cancel $i } set x before set y before set z before after idle set x after1 after idle set y after2 after idle set z after3 after cancel set x after1 update idletasks concat $x $y $z } {before after2 after3} test timer-5.1 {Tcl_ServiceIdle, self-rescheduling handlers} { foreach i [after info] { after cancel $i } set x 1 set y 23 after idle {incr x; after idle {incr x; after idle {incr x}}} after idle {incr y} vwait x set result "$x $y" update idletasks lappend result $x } {2 24 4} test timer-6.1 {Tcl_AfterCmd procedure, basics} { list [catch {after} msg] $msg } {1 {wrong # args: should be "after option ?arg ...?"}} test timer-6.2 {Tcl_AfterCmd procedure, basics} jim { list [catch {after 2x} msg] $msg } {1 {bad argument "2x": must be cancel, idle, or info}} test timer-6.3 {Tcl_AfterCmd procedure, basics} jim { list [catch {after gorp} msg] $msg } {1 {bad argument "gorp": must be cancel, idle, or info}} test timer-6.4 {Tcl_AfterCmd procedure, ms argument} { set x before after 80 {set x after} after 40 update set y $x after 80 update list $y $x } {before after} test timer-6.5 {Tcl_AfterCmd procedure, ms argument} { set x before after 60 {set x after} after 40 update set y $x after 40 update list $y $x } {before after} test timer-6.6 {Tcl_AfterCmd procedure, cancel option} { list [catch {after cancel} msg] $msg } {1 {wrong # args: should be "after cancel id|command"}} test timer-6.7 {Tcl_AfterCmd procedure, cancel option} { after cancel after#1 } {} test timer-6.8 {Tcl_AfterCmd procedure, cancel option} { after cancel {foo bar} } {} test timer-6.9 {Tcl_AfterCmd procedure, cancel option} { foreach i [after info] { after cancel $i } set x before set y [after 20 set x after] after cancel $y after 40 update set x } {before} test timer-6.10 {Tcl_AfterCmd procedure, cancel option} { foreach i [after info] { after cancel $i } set x before after 20 set x after after cancel set x after after 40 update set x } {before} test timer-6.11 {Tcl_AfterCmd procedure, cancel option} { foreach i [after info] { after cancel $i } set x before after 20 set x after set id [after 60 set x after] after cancel $id after 40 update set y $x set x cleared after 40 update list $y $x } {after cleared} test timer-6.12 {Tcl_AfterCmd procedure, cancel option} { foreach i [after info] { after cancel $i } set x first after idle lappend x second after idle lappend x third set i [after idle lappend x fourth] after cancel {lappend x second} after cancel $i update idletasks set x } {first third} test timer-6.13 {Tcl_AfterCmd procedure, cancel option, multiple arguments for command} { foreach i [after info] { after cancel $i } set x first after idle lappend x second after idle lappend x third set i [after idle lappend x fourth] after cancel lappend x second after cancel $i update idletasks set x } {first third} test timer-6.14 {Tcl_AfterCmd procedure, cancel option, cancel during handler, used to dump core} { foreach i [after info] { after cancel $i } set id [ after 20 { set x done after cancel $id } ] vwait x } {} test timer-6.16 {Tcl_AfterCmd procedure, idle option} { list [catch {after idle} msg] $msg } {1 {wrong # args: should be "after idle script ?script ...?"}} test timer-6.17 {Tcl_AfterCmd procedure, idle option} { set x before after idle {set x after} set y $x update idletasks list $y $x } {before after} test timer-6.18 {Tcl_AfterCmd procedure, idle option} { set x before after idle set x after set y $x update idletasks list $y $x } {before after} test timer-6.23 {Tcl_AfterCmd procedure, no option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after 1 "set x ab\0cd" after 10 update string length $x } {5} test timer-6.24 {Tcl_AfterCmd procedure, no option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after 1 set x ab\0cd after 10 update string length $x } {5} test timer-6.25 {Tcl_AfterCmd procedure, cancel option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after 1 set x ab\0cd after cancel "set x ab\0ef" set x [llength [after info]] foreach i [after info] { after cancel $i } set x } {1} test timer-6.26 {Tcl_AfterCmd procedure, cancel option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after 1 set x ab\0cd after cancel set x ab\0ef set y [llength [after info]] foreach i [after info] { after cancel $i } set y } {1} test timer-6.27 {Tcl_AfterCmd procedure, idle option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after idle "set x ab\0cd" update string length $x } {5} test timer-6.28 {Tcl_AfterCmd procedure, idle option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" after idle set x ab\0cd update string length $x } {5} test timer-6.29 {Tcl_AfterCmd procedure, info option, script with NULL} { foreach i [after info] { after cancel $i } set x "hello world" set id junk set id [after 10 set x ab\0cd] update set y [string length [lindex [lindex [after info $id] 0] 2]] foreach i [after info] { after cancel $i } set y } {5} set event [after idle foo bar] scan $event after#%d id test timer-7.1 {GetAfterEvent procedure} { list [catch {after info xfter#$id} msg] $msg } "1 {event \"xfter#$id\" doesn't exist}" test timer-7.2 {GetAfterEvent procedure} { list [catch {after info afterx$id} msg] $msg } "1 {event \"afterx$id\" doesn't exist}" test timer-7.3 {GetAfterEvent procedure} { list [catch {after info after#ab} msg] $msg } {1 {event "after#ab" doesn't exist}} test timer-7.4 {GetAfterEvent procedure} { list [catch {after info after#} msg] $msg } {1 {event "after#" doesn't exist}} test timer-7.5 {GetAfterEvent procedure} { list [catch {after info after#${id}x} msg] $msg } "1 {event \"after#${id}x\" doesn't exist}" test timer-7.6 {GetAfterEvent procedure} { list [catch {after info afterx[expr $id+1]} msg] $msg } "1 {event \"afterx[expr $id+1]\" doesn't exist}" after cancel $event test timer-8.1 {AfterProc procedure} { set x before proc foo {} { set x untouched after 20 {set x after} after 200 update return $x } list [foo] $x } {untouched after} test timer-8.2 {AfterProc procedure} { catch {rename bgerror {}} proc bgerror msg { set ::x $msg } set x empty after 20 {error "After error"} after 200 set y $x update catch {rename bgerror {}} list $y $x } {empty {After error}} test timer-8.4 {AfterProc procedure, deleting handler from itself} { foreach i [after info] { after cancel $i } proc foo {} { global x set x {} foreach i [after info] { lappend x [after info $i] } after cancel foo } after 1000 {error "I shouldn't ever have executed"} after idle foo update idletasks set x } {{{error "I shouldn't ever have executed"} timer}} foreach i [after info] { after cancel $i } testreport openocd-0.9.0/jimtcl/tests/array.test0000644000175000017500000000327012516456444014550 00000000000000source [file dirname [info script]]/testing.tcl needs cmd array unset -nocomplain a array set a { 1 one 2 two 22 "twenty two" 3 three } test array-1.1 "array exists - true" { array exists a } {1} test array-1.2 "array exists - false" { array exists b } {0} test array-1.3 "array size" { array size a } {4} test array-1.4 "array size - nonexistant" { array size b } {0} test array-1.5 "array get" { set result {} foreach {name value} [array get a] { lappend result $name $value } lsort $result } {1 2 22 3 one three {twenty two} two} test array-1.6 "array get - pattern" { set result {} foreach {name value} [array get a 2*] { lappend result $name $value } lsort $result } {2 22 {twenty two} two} test array-1.7 "array names" { lsort [array names a] } {1 2 22 3} test array-1.8 "array get - pattern" { lsort [array names a 2*] } {2 22} #set b $a array set b [array get a] test array-1.9 "array set - replace" { array set b {22 twenty-two} set b(22) } {twenty-two} test array-1.10 "array unset - pattern" { array unset b 2* lsort [array names b] } {1 3} test array-1.11 "array unset - all" { array unset b list [array size b] [array exists b] } {0 0} test array-1.12 "array set to invalid variable" -body { unset -nocomplain a b set a 1 array set a(1) {b c} } -returnCodes error -result {can't set "a(1)": variable isn't array} test array-1.13 "unset missing array element" -body { unset -nocomplain a set a(1) one unset a(2) } -returnCodes error -result {can't unset "a(2)": no such element in array} test array-1.14 "access array via unset var" -body { unset -nocomplain b expr {$a($b) + 4} } -returnCodes error -result {can't read "b": no such variable} testreport openocd-0.9.0/jimtcl/tests/errors.tcl0000644000175000017500000000174412516456444014555 00000000000000# Package which can generate a variety of errors at known locations proc error_generator {type} { switch $type { badcmd { bogus command called } badvar { set bogus } error { error bogus } interpbadvar { set x "some $bogus text" } interpbadcmd { set x "some $bogus text" } package { package require dummy } source { source dummy.tcl } badpackage { package require bogus } returncode { return -code error failure } badproc { error_badproc } default { puts "Unknown type=$type" } } } # line 40: Some empty lines above so that line numbers don't change proc error_caller {type {method call}} { switch $method { call { error_generator $type } uplevel { uplevel 1 [list error_generator $type] } eval { eval [list error_generator $type] } evalstr { eval error_generator $type } default { puts "Unknown method=$method" } } } proc error_badproc {} { return [list missing bracket here } openocd-0.9.0/jimtcl/tests/lreplace.test0000644000175000017500000001011412315602575015207 00000000000000# Commands covered: lreplace # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl test lreplace-1.1 {lreplace command} { lreplace {1 2 3 4 5} 0 0 a } {a 2 3 4 5} test lreplace-1.2 {lreplace command} { lreplace {1 2 3 4 5} 1 1 a } {1 a 3 4 5} test lreplace-1.3 {lreplace command} { lreplace {1 2 3 4 5} 2 2 a } {1 2 a 4 5} test lreplace-1.4 {lreplace command} { lreplace {1 2 3 4 5} 3 3 a } {1 2 3 a 5} test lreplace-1.5 {lreplace command} { lreplace {1 2 3 4 5} 4 4 a } {1 2 3 4 a} test lreplace-1.6 {lreplace command} { lreplace {1 2 3 4 5} 4 5 a } {1 2 3 4 a} test lreplace-1.7 {lreplace command} { lreplace {1 2 3 4 5} -1 -1 a } {a 1 2 3 4 5} test lreplace-1.8 {lreplace command} { lreplace {1 2 3 4 5} 2 end a b c d } {1 2 a b c d} test lreplace-1.9 {lreplace command} { lreplace {1 2 3 4 5} 0 3 } {5} test lreplace-1.10 {lreplace command} { lreplace {1 2 3 4 5} 0 4 } {} test lreplace-1.11 {lreplace command} { lreplace {1 2 3 4 5} 0 1 } {3 4 5} test lreplace-1.12 {lreplace command} { lreplace {1 2 3 4 5} 2 3 } {1 2 5} test lreplace-1.13 {lreplace command} { lreplace {1 2 3 4 5} 3 end } {1 2 3} test lreplace-1.14 {lreplace command} { lreplace {1 2 3 4 5} -1 4 a b c } {a b c} test lreplace-1.15 {lreplace command} { lreplace {a b "c c" d e f} 3 3 } {a b {c c} e f} test lreplace-1.16 {lreplace command} { lreplace { 1 2 3 4 5} 0 0 a } {a 2 3 4 5} test lreplace-1.17 {lreplace command} { lreplace {1 2 3 4 "5 6"} 4 4 a } {1 2 3 4 a} test lreplace-1.18 {lreplace command} { lreplace {1 2 3 4 {5 6}} 4 4 a } {1 2 3 4 a} test lreplace-1.19 {lreplace command} { lreplace {1 2 3 4} 2 end x y z } {1 2 x y z} test lreplace-1.20 {lreplace command} { lreplace {1 2 3 4} end end a } {1 2 3 a} test lreplace-1.21 {lreplace command} { lreplace {1 2 3 4} end 3 a } {1 2 3 a} test lreplace-1.22 {lreplace command} { lreplace {1 2 3 4} end end } {1 2 3} test lreplace-1.23 {lreplace command} { lreplace {1 2 3 4} 2 -1 xy } {1 2 xy 3 4} test lreplace-1.24 {lreplace command} { lreplace {1 2 3 4} end -1 z } {1 2 3 z 4} test lreplace-1.25 {lreplace command} { concat \"[lreplace {\}\ hello} end end]\" } {"\}\ "} test lreplace-1.26 {lreplace command} { catch {unset foo} set foo {a b} list [set foo [lreplace $foo end end]] \ [set foo [lreplace $foo end end]] \ [set foo [lreplace $foo end end]] } {a {} {}} test lreplace-2.1 {lreplace errors} { list [catch lreplace msg] $msg } {1 {wrong # args: should be "lreplace list first last ?element ...?"}} test lreplace-2.2 {lreplace errors} { list [catch {lreplace a b} msg] $msg } {1 {wrong # args: should be "lreplace list first last ?element ...?"}} test lreplace-2.3 {lreplace errors} { list [catch {lreplace x a 10} msg] $msg } {1 {bad index "a": must be integer?[+-]integer? or end?[+-]integer?}} test lreplace-2.4 {lreplace errors} { list [catch {lreplace x 10 x} msg] $msg } {1 {bad index "x": must be integer?[+-]integer? or end?[+-]integer?}} test lreplace-2.5 {lreplace errors} { list [catch {lreplace x 10 1x} msg] $msg } {1 {bad index "1x": must be integer?[+-]integer? or end?[+-]integer?}} test lreplace-2.6 {lreplace errors} { list [catch {lreplace x 3 2} msg] $msg } {1 {list doesn't contain element 3}} test lreplace-2.7 {lreplace errors} { list [catch {lreplace x 1 1} msg] $msg } {1 {list doesn't contain element 1}} test lreplace-3.1 {lreplace won't modify shared argument objects} { proc p {} { lreplace "a b c" 1 1 "x y" return "a b c" } p } "a b c" # cleanup catch {unset foo} ::tcltest::cleanupTests return openocd-0.9.0/jimtcl/tests/jim.test0000644000175000017500000027265012516456444014223 00000000000000# $Id: test.tcl,v 1.31 2008/11/06 13:31:22 oharboe Exp $ # # These are Tcl tests imported into Jim. Tests that will probably not be passed # in the long term are usually removed (for example all the tests about # unicode things, about errors in list parsing that are always valid in Jim # and so on). # # Sometimes tests are modified to reflect different error messages. source [file dirname [info script]]/testing.tcl needs constraint jim catch {package require regexp} testConstraint regexp [expr {[info commands regexp] ne {}}] testConstraint lambda [expr {[info commands ref] ne {}}] ################################################################################ # SET ################################################################################ test set-1.2 {TclCompileSetCmd: simple variable name} { set i 10 list [set i] $i } {10 10} test set-1.4 {TclCompileSetCmd: simple variable name in quotes} { set i 17 list [set "i"] $i } {17 17} test set-1.7 {TclCompileSetCmd: non-simple (computed) variable name} { set x "i" set i 77 list [set $x] $i } {77 77} test set-1.8 {TclCompileSetCmd: non-simple (computed) variable name} { set x "i" set i 77 list [set [set x] 2] $i } {2 2} test set-1.9 {TclCompileSetCmd: 3rd arg => assignment} { set i "abcdef" list [set i] $i } {abcdef abcdef} test set-1.10 {TclCompileSetCmd: only two args => just getting value} { set i {one two} set i } {one two} test set-1.11 {TclCompileSetCmd: simple global name} { proc p {} { global i set i 54 set i } p } {54} test set-1.12 {TclCompileSetCmd: simple local name} { proc p {bar} { set foo $bar set foo } p 999 } {999} test set-1.14 {TclCompileSetCmd: simple local name, >255 locals} { proc 260locals {} { # create 260 locals (the last ones with index > 255) set a0 0; set a1 0; set a2 0; set a3 0; set a4 0 set a5 0; set a6 0; set a7 0; set a8 0; set a9 0 set b0 0; set b1 0; set b2 0; set b3 0; set b4 0 set b5 0; set b6 0; set b7 0; set b8 0; set b9 0 set c0 0; set c1 0; set c2 0; set c3 0; set c4 0 set c5 0; set c6 0; set c7 0; set c8 0; set c9 0 set d0 0; set d1 0; set d2 0; set d3 0; set d4 0 set d5 0; set d6 0; set d7 0; set d8 0; set d9 0 set e0 0; set e1 0; set e2 0; set e3 0; set e4 0 set e5 0; set e6 0; set e7 0; set e8 0; set e9 0 set f0 0; set f1 0; set f2 0; set f3 0; set f4 0 set f5 0; set f6 0; set f7 0; set f8 0; set f9 0 set g0 0; set g1 0; set g2 0; set g3 0; set g4 0 set g5 0; set g6 0; set g7 0; set g8 0; set g9 0 set h0 0; set h1 0; set h2 0; set h3 0; set h4 0 set h5 0; set h6 0; set h7 0; set h8 0; set h9 0 set i0 0; set i1 0; set i2 0; set i3 0; set i4 0 set i5 0; set i6 0; set i7 0; set i8 0; set i9 0 set j0 0; set j1 0; set j2 0; set j3 0; set j4 0 set j5 0; set j6 0; set j7 0; set j8 0; set j9 0 set k0 0; set k1 0; set k2 0; set k3 0; set k4 0 set k5 0; set k6 0; set k7 0; set k8 0; set k9 0 set l0 0; set l1 0; set l2 0; set l3 0; set l4 0 set l5 0; set l6 0; set l7 0; set l8 0; set l9 0 set m0 0; set m1 0; set m2 0; set m3 0; set m4 0 set m5 0; set m6 0; set m7 0; set m8 0; set m9 0 set n0 0; set n1 0; set n2 0; set n3 0; set n4 0 set n5 0; set n6 0; set n7 0; set n8 0; set n9 0 set o0 0; set o1 0; set o2 0; set o3 0; set o4 0 set o5 0; set o6 0; set o7 0; set o8 0; set o9 0 set p0 0; set p1 0; set p2 0; set p3 0; set p4 0 set p5 0; set p6 0; set p7 0; set p8 0; set p9 0 set q0 0; set q1 0; set q2 0; set q3 0; set q4 0 set q5 0; set q6 0; set q7 0; set q8 0; set q9 0 set r0 0; set r1 0; set r2 0; set r3 0; set r4 0 set r5 0; set r6 0; set r7 0; set r8 0; set r9 0 set s0 0; set s1 0; set s2 0; set s3 0; set s4 0 set s5 0; set s6 0; set s7 0; set s8 0; set s9 0 set t0 0; set t1 0; set t2 0; set t3 0; set t4 0 set t5 0; set t6 0; set t7 0; set t8 0; set t9 0 set u0 0; set u1 0; set u2 0; set u3 0; set u4 0 set u5 0; set u6 0; set u7 0; set u8 0; set u9 0 set v0 0; set v1 0; set v2 0; set v3 0; set v4 0 set v5 0; set v6 0; set v7 0; set v8 0; set v9 0 set w0 0; set w1 0; set w2 0; set w3 0; set w4 0 set w5 0; set w6 0; set w7 0; set w8 0; set w9 0 set x0 0; set x1 0; set x2 0; set x3 0; set x4 0 set x5 0; set x6 0; set x7 0; set x8 0; set x9 0 set y0 0; set y1 0; set y2 0; set y3 0; set y4 0 set y5 0; set y6 0; set y7 0; set y8 0; set y9 0 set z0 0; set z1 0; set z2 0; set z3 0; set z4 0 set z5 0; set z6 0; set z7 0; set z8 0; set z9 1234 } 260locals } {1234} test set-1.17 {TclCompileSetCmd: doing assignment, simple int} { set i 5 set i 123 } 123 test set-1.18 {TclCompileSetCmd: doing assignment, simple int} { set i 5 set i -100 } -100 test set-1.19 {TclCompileSetCmd: doing assignment, simple but not int} { set i 5 set i 0x12MNOP set i } {0x12MNOP} test set-1.20 {TclCompileSetCmd: doing assignment, in quotes} { set i 25 set i "-100" } -100 test set-1.21 {TclCompileSetCmd: doing assignment, in braces} { set i 24 set i {126} } 126 test set-1.22 {TclCompileSetCmd: doing assignment, large int} { set i 5 set i 200000 } 200000 test set-1.23 {TclCompileSetCmd: doing assignment, formatted int != int} { set i 25 set i 000012345 ;# a decimal literal == 5349 decimal list $i [incr i] } {000012345 12346} ################################################################################ # LIST ################################################################################ test list-1.1 {basic tests} {list a b c} {a b c} test list-1.2 {basic tests} {list {a b} c} {{a b} c} test list-1.3 {basic tests} {list \{a b c} {\{a b c} test list-1.4 {basic tests} "list a{}} b{} c}" "a\\{\\}\\} b{} c\\}" test list-1.5 {basic tests} {list a\[ b\] } "{a\[} b\\]" test list-1.6 {basic tests} {list c\ d\t } "{c } {d\t}" test list-1.7 {basic tests} {list e\n f\$ } "{e\n} {f\$}" test list-1.8 {basic tests} {list g\; h\\} {{g;} h\\} test list-1.9 {basic tests} "list a\\\[} b\\\]} " "a\\\[\\\} b\\\]\\\}" test list-1.10 {basic tests} "list c\\\} d\\t} " "c\\} d\\t\\}" test list-1.11 {basic tests} "list e\\n} f\\$} " "e\\n\\} f\\$\\}" test list-1.12 {basic tests} "list g\\;} h\\\\} " "g\\;\\} {h\\}}" test list-1.13 {basic tests} {list a {{}} b} {a {{}} b} test list-1.14 {basic tests} {list a b xy\\} "a b xy\\\\" test list-1.15 {basic tests} "list a b\} e\\" "a b\\} e\\\\" test list-1.16 {basic tests} "list a b\}\\\$ e\\\$\\" "a b\\}\\\$ e\\\$\\\\" test list-1.17 {basic tests} {list a\f \{\f} "{a\f} \\\{\\f" test list-1.18 {basic tests} {list a\r \{\r} "{a\r} \\\{\\r" test list-1.19 {basic tests} {list a\v \{\v} "{a\v} \\\{\\v" test list-1.20 {basic tests} {list \"\}\{} "\\\"\\}\\{" test list-1.21 {basic tests} {list a b c\\\nd} "a b c\\\\\\nd" test list-1.22 {basic tests} {list "{ab}\\"} \\{ab\\}\\\\ test list-1.23 {basic tests} {list \{} "\\{" test list-1.24 {basic tests} {list} {} set num 0 proc lcheck {testid a b c} { global num d set d [list $a $b $c] test ${testid}-0 {what goes in must come out} {lindex $d 0} $a test ${testid}-1 {what goes in must come out} {lindex $d 1} $b test ${testid}-2 {what goes in must come out} {lindex $d 2} $c } lcheck list-2.1 a b c lcheck list-2.2 "a b" c\td e\nf lcheck list-2.3 {{a b}} {} { } lcheck list-2.4 \$ \$ab ab\$ lcheck list-2.5 \; \;ab ab\; lcheck list-2.6 \[ \[ab ab\[ lcheck list-2.7 \\ \\ab ab\\ lcheck list-2.8 {"} {"ab} {ab"} ;#" Stupid emacs highlighting! lcheck list-2.9 {a b} { ab} {ab } lcheck list-2.10 a{ a{b \{ab lcheck list-2.11 a} a}b }ab lcheck list-2.12 a\\} {a \}b} {a \{c} lcheck list-2.13 xyz \\ 1\\\n2 lcheck list-2.14 "{ab}\\" "{ab}xy" abc concat {} ################################################################################ # WHILE ################################################################################ test while-1.9 {TclCompileWhileCmd: simple command body} { set a {} set i 1 while {$i<6} { if $i==4 break set a [concat $a $i] incr i } set a } {1 2 3} test while-1.10 {TclCompileWhileCmd: command body in quotes} { set a {} set i 1 while {$i<6} "append a x; incr i" set a } {xxxxx} test while-1.13 {TclCompileWhileCmd: while command result} { set i 0 set a [while {$i < 5} {incr i}] set a } {} test while-1.14 {TclCompileWhileCmd: while command result} { set i 0 set a [while {$i < 5} {if $i==3 break; incr i}] set a } {} test while-2.1 {continue tests} { set a {} set i 1 while {$i <= 4} { incr i if {$i == 3} continue set a [concat $a $i] } set a } {2 4 5} test while-2.2 {continue tests} { set a {} set i 1 while {$i <= 4} { incr i if {$i != 2} continue set a [concat $a $i] } set a } {2} test while-2.3 {continue tests, nested loops} { set msg {} set i 1 while {$i <= 4} { incr i set a 1 while {$a <= 2} { incr a if {$i>=3 && $a>=3} continue set msg [concat $msg "$i.$a"] } } set msg } {2.2 2.3 3.2 4.2 5.2} test while-4.1 {while and computed command names} { set i 0 set z while $z {$i < 10} { incr i } set i } 10 test while-5.2 {break tests with computed command names} { set a {} set i 1 set z break while {$i <= 4} { if {$i == 3} $z set a [concat $a $i] incr i } set a } {1 2} test while-7.1 {delayed substitution of body} { set i 0 while {[incr i] < 10} " set result $i " proc p {} { set i 0 while {[incr i] < 10} " set result $i " set result } append result [p] } {00} ################################################################################ # LSET ################################################################################ set lset lset test lset-2.1 {lset, not compiled, 3 args, second arg a plain index} { set x {0 1 2} list [eval [list $lset x 0 3]] $x } {{3 1 2} {3 1 2}} test lset-3.1 {lset, not compiled, 3 args, data duplicated} { set x {0 1 2} list [eval [list $lset x 0 $x]] $x } {{{0 1 2} 1 2} {{0 1 2} 1 2}} test lset-3.2 {lset, not compiled, 3 args, data duplicated} { set x {0 1} set y $x list [eval [list $lset x 0 2]] $x $y } {{2 1} {2 1} {0 1}} test lset-3.3 {lset, not compiled, 3 args, data duplicated} { set x {0 1} set y $x list [eval [list $lset x 0 $x]] $x $y } {{{0 1} 1} {{0 1} 1} {0 1}} test lset-3.4 {lset, not compiled, 3 args, data duplicated} { set x {0 1 2} list [eval [list $lset x [list 0] $x]] $x } {{{0 1 2} 1 2} {{0 1 2} 1 2}} test lset-3.5 {lset, not compiled, 3 args, data duplicated} { set x {0 1} set y $x list [eval [list $lset x [list 0] 2]] $x $y } {{2 1} {2 1} {0 1}} test lset-3.6 {lset, not compiled, 3 args, data duplicated} { set x {0 1} set y $x list [eval [list $lset x [list 0] $x]] $x $y } {{{0 1} 1} {{0 1} 1} {0 1}} test lset-4.2 {lset, not compiled, 3 args, bad index} { set a {x y z} list [catch { eval [list $lset a [list 2a2] w] } msg] $msg } {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}} test lset-4.3 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a [list -1] w] } msg] $msg } {1 {list index out of range}} test lset-4.4 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a [list 3] w] } msg] $msg } {1 {list index out of range}} test lset-4.5 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a [list end--1] w] } msg] $msg } {1 {list index out of range}} test lset-4.6 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a [list end-3] w] } msg] $msg } {1 {list index out of range}} test lset-4.8 {lset, not compiled, 3 args, bad index} { set a {x y z} list [catch { eval [list $lset a 2a2 w] } msg] $msg } {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}} test lset-4.9 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a -1 w] } msg] $msg } {1 {list index out of range}} test lset-4.10 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a 3 w] } msg] $msg } {1 {list index out of range}} test lset-4.11 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a end--1 w] } msg] $msg } {1 {list index out of range}} test lset-4.12 {lset, not compiled, 3 args, index out of range} { set a {x y z} list [catch { eval [list $lset a end-3 w] } msg] $msg } {1 {list index out of range}} test lset-6.1 {lset, not compiled, 3 args, 1-d list basics} { set a {x y z} list [eval [list $lset a 0 a]] $a } {{a y z} {a y z}} test lset-6.2 {lset, not compiled, 3 args, 1-d list basics} { set a {x y z} list [eval [list $lset a [list 0] a]] $a } {{a y z} {a y z}} test lset-6.3 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a 2 a]] $a } {{x y a} {x y a}} test lset-6.4 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a [list 2] a]] $a } {{x y a} {x y a}} test lset-6.5 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a end a]] $a } {{x y a} {x y a}} test lset-6.6 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a [list end] a]] $a } {{x y a} {x y a}} test lset-6.7 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a end-0 a]] $a } {{x y a} {x y a}} test lset-6.8 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a [list end-0] a]] $a } {{x y a} {x y a}} test lset-6.9 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a end-2 a]] $a } {{a y z} {a y z}} test lset-6.10 {lset, not compiled, 1-d list basics} { set a {x y z} list [eval [list $lset a [list end-2] a]] $a } {{a y z} {a y z}} test lset-7.1 {lset, not compiled, data sharing} { set a 0 list [eval [list $lset a $a {gag me}]] $a } {{{gag me}} {{gag me}}} test lset-7.2 {lset, not compiled, data sharing} { set a [list 0] list [eval [list $lset a $a {gag me}]] $a } {{{gag me}} {{gag me}}} test lset-7.3 {lset, not compiled, data sharing} { set a {x y} list [eval [list $lset a 0 $a]] $a } {{{x y} y} {{x y} y}} test lset-7.4 {lset, not compiled, data sharing} { set a {x y} list [eval [list $lset a [list 0] $a]] $a } {{{x y} y} {{x y} y}} test lset-7.5 {lset, not compiled, data sharing} { set n 0 set a {x y} list [eval [list $lset a $n $n]] $a $n } {{0 y} {0 y} 0} test lset-7.6 {lset, not compiled, data sharing} { set n [list 0] set a {x y} list [eval [list $lset a $n $n]] $a $n } {{0 y} {0 y} 0} test lset-7.7 {lset, not compiled, data sharing} { set n 0 set a [list $n $n] list [eval [list $lset a $n 1]] $a $n } {{1 0} {1 0} 0} test lset-7.8 {lset, not compiled, data sharing} { set n [list 0] set a [list $n $n] list [eval [list $lset a $n 1]] $a $n } {{1 0} {1 0} 0} test lset-7.9 {lset, not compiled, data sharing} { set a 0 list [eval [list $lset a $a $a]] $a } {0 0} test lset-7.10 {lset, not compiled, data sharing} { set a [list 0] list [eval [list $lset a $a $a]] $a } {0 0} test lset-8.3 {lset, not compiled, bad second index} { set a {{b c} {d e}} list [catch {eval [list $lset a 0 2a2 f]} msg] $msg } {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}} test lset-8.5 {lset, not compiled, second index out of range} { set a {{b c} {d e} {f g}} list [catch {eval [list $lset a 2 -1 h]} msg] $msg } {1 {list index out of range}} test lset-8.7 {lset, not compiled, second index out of range} { set a {{b c} {d e} {f g}} list [catch {eval [list $lset a 2 2 h]} msg] $msg } {1 {list index out of range}} test lset-8.9 {lset, not compiled, second index out of range} { set a {{b c} {d e} {f g}} list [catch {eval [list $lset a 2 end--1 h]} msg] $msg } {1 {list index out of range}} test lset-8.11 {lset, not compiled, second index out of range} { set a {{b c} {d e} {f g}} list [catch {eval [list $lset a 2 end-2 h]} msg] $msg } {1 {list index out of range}} test lset-9.1 {lset, not compiled, entire variable} { set a x list [eval [list $lset a y]] $a } {y y} test lset-10.1 {lset, not compiled, shared data} { set row {p q} set a [list $row $row] list [eval [list $lset a 0 0 x]] $a } {{{x q} {p q}} {{x q} {p q}}} test lset-11.1 {lset, not compiled, 2-d basics} { set a {{b c} {d e}} list [eval [list $lset a 0 0 f]] $a } {{{f c} {d e}} {{f c} {d e}}} test lset-11.3 {lset, not compiled, 2-d basics} { set a {{b c} {d e}} list [eval [list $lset a 0 1 f]] $a } {{{b f} {d e}} {{b f} {d e}}} test lset-11.5 {lset, not compiled, 2-d basics} { set a {{b c} {d e}} list [eval [list $lset a 1 0 f]] $a } {{{b c} {f e}} {{b c} {f e}}} test lset-11.7 {lset, not compiled, 2-d basics} { set a {{b c} {d e}} list [eval [list $lset a 1 1 f]] $a } {{{b c} {d f}} {{b c} {d f}}} test lset-12.0 {lset, not compiled, typical sharing pattern} { set zero 0 set row [list $zero $zero $zero $zero] set ident [list $row $row $row $row] for { set i 0 } { $i < 4 } { incr i } { eval [list $lset ident $i $i 1] } set ident } {{1 0 0 0} {0 1 0 0} {0 0 1 0} {0 0 0 1}} test lset-13.0 {lset, not compiled, shimmering hell} { set a 0 list [eval [list $lset a $a $a $a $a {gag me}]] $a } {{{{{{gag me}}}}} {{{{{gag me}}}}}} test lset-13.1 {lset, not compiled, shimmering hell} { set a [list 0] list [eval [list $lset a $a $a $a $a {gag me}]] $a } {{{{{{gag me}}}}} {{{{{gag me}}}}}} test lset-14.1 {lset, not compiled, list args, is string rep preserved?} { set a { { 1 2 } { 3 4 } } catch { eval [list $lset a {1 5} 5] } list $a [lindex $a 1] } "{ { 1 2 } { 3 4 } } { 3 4 }" catch {unset noRead} catch {unset noWrite} catch {rename failTrace {}} catch {unset ::x} catch {unset ::y} ################################################################################ # IF ################################################################################ test if-1.1 {bad syntax: lacking all} { catch {if} } 1 test if-1.2 {bad syntax: lacking then-clause} { catch {if 1==1} } 1 test if-1.3 {bad syntax: lacking then-clause 2} { catch {if 1==1 then} } 1 test if-1.4 {bad syntax: lacking else-clause after keyword 'else'} { catch {if 1==0 then {list 1} else} } 1 test if-1.5 {bad syntax: lacking expr after 'elseif'} { catch {if 1==0 then {list 1} elseif} } 1 test if-1.6 {bad syntax: lacking then-clause after 'elseif'} { catch {if 1==0 then {list 1} elseif 1==1} } 1 test if-1.7 {bad syntax: lacking else-clause after 'elseif' after keyword 'else'} { catch {if 1==0 then {list 1} elseif 1==0 {list 2} else} } 1 test if-1.8 {bad syntax: extra arg after implicit else-clause} { catch {if 1==0 {list 1} elseif 1==0 then {list 2} {list 3} else} } 1 test if-1.9 {bad syntax: elsif-clause after else-clause} { catch {if 1==0 {list 1} else {list 2} elseif 1==1 {list 3}} } 1 test if-2.1 {taking proper branch} { set a {} if 0 {set a 1} else {set a 2} set a } 2 test if-2.2 {taking proper branch} { set a {} if 1 {set a 1} else {set a 2} set a } 1 test if-2.3 {taking proper branch} { set a {} if 1<2 {set a 1} set a } 1 test if-2.4 {taking proper branch} { set a {} if 1>2 {set a 1} set a } {} test if-2.5 {taking proper branch} { set a {} if 0 {set a 1} else {} set a } {} test if-2.6 {taking proper branch} { set a {} if 0 {set a 1} elseif 1 {set a 2} elseif 1 {set a 3} else {set a 4} set a } 2 test if-2.7 {taking proper branch} { set a {} if 0 {set a 1} elseif 0 {set a 2} elseif 1 {set a 3} else {set a 4} set a } 3 test if-2.8 {taking proper branch} { set a {} if 0 {set a 1} elseif 0 {set a 2} elseif 0 {set a 3} else {set a 4} set a } 4 test if-2.9 {taking proper branch, multiline test expr} { set a {} if {1 != \ 3} {set a 3} else {set a 4} set a } 3 test if-3.1 {optional then-else args} { set a 44 if 0 then {set a 1} elseif 0 then {set a 3} else {set a 2} set a } 2 test if-3.2 {optional then-else args} { set a 44 if 1 then {set a 1} else {set a 2} set a } 1 test if-3.3 {optional then-else args} { set a 44 if 0 {set a 1} else {set a 2} set a } 2 test if-3.4 {optional then-else args} { set a 44 if 1 {set a 1} else {set a 2} set a } 1 test if-3.5 {optional then-else args} { set a 44 if 0 then {set a 1} {set a 2} set a } 2 test if-3.6 {optional then-else args} { set a 44 if 1 then {set a 1} {set a 2} set a } 1 test if-3.7 {optional then-else args} { set a 44 if 0 then {set a 1} else {set a 2} set a } 2 test if-3.8 {optional then-else args} { set a 44 if 0 then {set a 1} elseif 0 {set a 2} elseif 0 {set a 3} {set a 4} set a } 4 test if-4.1 {return value} { if 1 then {set a 22; concat abc} } abc test if-4.2 {return value} { if 0 then {set a 22; concat abc} elseif 1 {concat def} {concat ghi} } def test if-4.3 {return value} { if 0 then {set a 22; concat abc} else {concat def} } def test if-4.4 {return value} { if 0 then {set a 22; concat abc} } {} test if-4.5 {return value} { if 0 then {set a 22; concat abc} elseif 0 {concat def} } {} test if-5.1 {error conditions} { list [catch {if {[error "error in condition"]} foo} msg] $msg } {1 {error in condition}} test if-5.2 {error conditions} { list [catch {if 2 the} msg] $msg } {1 {invalid command name "the"}} test if-5.3 {error conditions} { list [catch {if 2 then {[error "error in then clause"]}} msg] $msg } {1 {error in then clause}} test if-5.4 {error conditions} { list [catch {if 0 then foo elsei} msg] $msg } {1 {invalid command name "elsei"}} test if-5.5 {error conditions} { list [catch {if 0 then foo elseif 0 bar els} msg] $msg } {1 {invalid command name "els"}} test if-5.6 {error conditions} { list [catch {if 0 then foo elseif 0 bar else {[error "error in else clause"]}} msg] $msg } {1 {error in else clause}} ################################################################################ # APPEND ################################################################################ catch {unset x} test append-1.1 {append command} { catch {unset x} list [append x 1 2 abc "long string"] $x } {{12abclong string} {12abclong string}} test append-1.2 {append command} { set x "" list [append x first] [append x second] [append x third] $x } {first firstsecond firstsecondthird firstsecondthird} test append-1.3 {append command} { set x "abcd" append x } abcd test append-2.1 {long appends} { set x "" for {set i 0} {$i < 1000} {set i [expr $i+1]} { append x "foobar " } set y "foobar" set y "$y $y $y $y $y $y $y $y $y $y" set y "$y $y $y $y $y $y $y $y $y $y" set y "$y $y $y $y $y $y $y $y $y $y " expr {$x eq $y} } 1 test append-3.1 {append errors} { list [catch {append} msg] $msg } {1 {wrong # args: should be "append varName ?value ...?"}} test append-3.2 {append errors} { set x 1 list [catch {append x(0) 44} msg] $msg } {1 {can't set "x(0)": variable isn't array}} test append-3.3 {append errors} { catch {unset x} list [catch {append x} msg] $msg } {1 {can't read "x": no such variable}} test append-4.1 {lappend command} { catch {unset x} list [lappend x 1 2 abc "long string"] $x } {{1 2 abc {long string}} {1 2 abc {long string}}} test append-4.2 {lappend command} { set x "" list [lappend x first] [lappend x second] [lappend x third] $x } {first {first second} {first second third} {first second third}} test append-4.3 {lappend command} { proc foo {} { global x set x old unset x lappend x new } set result [foo] rename foo {} set result } {new} test append-4.4 {lappend command} { set x {} lappend x \{\ abc } {\{\ abc} test append-4.5 {lappend command} { set x {} lappend x \{ abc } {\{ abc} test append-4.6 {lappend command} { set x {1 2 3} lappend x } {1 2 3} test append-4.7 {lappend command} { set x "a\{" lappend x abc } "a\\\{ abc" test append-4.8 {lappend command} { set x "\\\{" lappend x abc } "\\{ abc" #test append-4.9 {lappend command} { # set x " \{" # list [catch {lappend x abc} msg] $msg #} {1 {unmatched open brace in list}} #test append-4.10 {lappend command} { # set x " \{" # list [catch {lappend x abc} msg] $msg #} {1 {unmatched open brace in list}} #test append-4.11 {lappend command} { # set x "\{\{\{" # list [catch {lappend x abc} msg] $msg #} {1 {unmatched open brace in list}} #test append-4.12 {lappend command} { # set x "x \{\{\{" # list [catch {lappend x abc} msg] $msg #} {1 {unmatched open brace in list}} test append-4.13 {lappend command} { set x "x\{\{\{" lappend x abc } "x\\\{\\\{\\\{ abc" test append-4.14 {lappend command} { set x " " lappend x abc } "abc" test append-4.15 {lappend command} { set x "\\ " lappend x abc } "{ } abc" test append-4.16 {lappend command} { set x "x " lappend x abc } "x abc" test append-4.17 {lappend command} { catch {unset x} lappend x } {} test append-4.18 {lappend command} { catch {unset x} lappend x {} } {{}} test append-4.19 {lappend command} { catch {unset x} lappend x(0) } {} test append-4.20 {lappend command} { catch {unset x} lappend x(0) abc } {abc} proc check {var size} { set l [llength $var] if {$l != $size} { return "length mismatch: should have been $size, was $l" } for {set i 0} {$i < $size} {set i [expr $i+1]} { set j [lindex $var $i] if {$j ne "item $i"} { return "element $i should have been \"item $i\", was \"$j\"" } } return ok } test append-5.1 {long lappends} { catch {unset x} set x "" for {set i 0} {$i < 300} {set i [expr $i+1]} { lappend x "item $i" } check $x 300 } ok test append-6.1 {lappend errors} { list [catch {lappend} msg] $msg } {1 {wrong # args: should be "lappend varName ?value value ...?"}} test append-6.2 {lappend errors} { set x 1 list [catch {lappend x(0) 44} msg] $msg } {1 {can't set "x(0)": variable isn't array}} ################################################################################ # UPLEVEL ################################################################################ proc a {x y} { newset z [expr $x+$y] return $z } proc newset {name value} { uplevel set $name $value uplevel 1 {uplevel 1 {set xyz 22}} } test uplevel-1.1 {simple operation} { set xyz 0 a 22 33 } 55 test uplevel-1.2 {command is another uplevel command} { set xyz 0 a 22 33 set xyz } 22 proc a1 {} { b1 global a a1 set a $x set a1 $y } proc b1 {} { c1 global b b1 set b $x set b1 $y } proc c1 {} { uplevel 1 set x 111 uplevel #2 set y 222 uplevel 2 set x 333 uplevel #1 set y 444 uplevel 3 set x 555 uplevel #0 set y 666 } a1 test uplevel-2.1 {relative and absolute uplevel} {set a} 333 test uplevel-2.2 {relative and absolute uplevel} {set a1} 444 test uplevel-2.3 {relative and absolute uplevel} {set b} 111 test uplevel-2.4 {relative and absolute uplevel} {set b1} 222 test uplevel-2.5 {relative and absolute uplevel} {set x} 555 test uplevel-2.6 {relative and absolute uplevel} {set y} 666 test uplevel-3.1 {uplevel to same level} { set x 33 uplevel #0 set x 44 set x } 44 test uplevel-3.2 {uplevel to same level} { set x 33 uplevel 0 set x } 33 test uplevel-3.3 {uplevel to same level} { set y xxx proc a1 {} {set y 55; uplevel 0 set y 66; return $y} a1 } 66 test uplevel-3.4 {uplevel to same level} { set y zzz proc a1 {} {set y 55; uplevel #1 set y} a1 } 55 test uplevel-4.1 {error: non-existent level} { list [catch c1 msg] $msg } {1 {bad level "#2"}} test uplevel-4.2 {error: non-existent level} { proc c2 {} {uplevel 3 {set a b}} list [catch c2 msg] $msg } {1 {bad level "3"}} test uplevel-4.3 {error: not enough args} { list [catch uplevel msg] $msg } {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}} test uplevel-4.4 {error: not enough args} { proc upBug {} {uplevel 1} list [catch upBug msg] $msg } {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}} proc a2 {} { uplevel a3 } proc a3 {} { global x y set x [info level] set y [info level 1] } a2 test uplevel-5.1 {info level} {set x} 1 test uplevel-5.2 {info level} {set y} a3 ################################################################################ # UNKNOWN ################################################################################ catch {unset x} catch {rename unknown unknown.old} test unknown-1.1 {non-existent "unknown" command} { list [catch {_non-existent_ foo bar} msg] $msg } {1 {invalid command name "_non-existent_"}} proc unknown {args} { global x set x $args } test unknown-2.1 {calling "unknown" command} { foobar x y z set x } {foobar x y z} test unknown-2.2 {calling "unknown" command with lots of args} { foobar 1 2 3 4 5 6 7 set x } {foobar 1 2 3 4 5 6 7} test unknown-2.3 {calling "unknown" command with lots of args} { foobar 1 2 3 4 5 6 7 8 set x } {foobar 1 2 3 4 5 6 7 8} test unknown-2.4 {calling "unknown" command with lots of args} { foobar 1 2 3 4 5 6 7 8 9 set x } {foobar 1 2 3 4 5 6 7 8 9} test unknown-3.1 {argument quoting in calls to "unknown"} { foobar \{ \} a\{b \; "\\" \$a a\[b \] set x } "foobar \\{ \\} a\\{b {;} \\\\ {\$a} {a\[b} \\]" proc unknown args { error "unknown failed" } test unknown-4.1 {errors in "unknown" procedure} { list [catch {non-existent a b} msg] $msg } {1 {unknown failed}} rename unknown {} ################################################################################ # INCR ################################################################################ catch {unset x} catch {unset i} test incr-1.1 {TclCompileIncrCmd: missing variable name} { list [catch {incr} msg] $msg } {1 {wrong # args: should be "incr varName ?increment?"}} test incr-1.2 {TclCompileIncrCmd: simple variable name} { set i 10 list [incr i] $i } {11 11} #test incr-1.3 {TclCompileIncrCmd: error compiling variable name} { # set i 10 # catch {incr "i"xxx} msg # set msg #} {extra characters after close-quote} test incr-1.4 {TclCompileIncrCmd: simple variable name in quotes} { set i 17 list [incr "i"] $i } {18 18} test incr-1.5 {TclCompileIncrCmd: simple variable name in braces} { catch {unset {a simple var}} set {a simple var} 27 list [incr {a simple var}] ${a simple var} } {28 28} test incr-1.6 {TclCompileIncrCmd: simple array variable name} { catch {unset a} set a(foo) 37 list [incr a(foo)] $a(foo) } {38 38} test incr-1.7 {TclCompileIncrCmd: non-simple (computed) variable name} { set x "i" set i 77 list [incr $x 2] $i } {79 79} test incr-1.8 {TclCompileIncrCmd: non-simple (computed) variable name} { set x "i" set i 77 list [incr [set x] +2] $i } {79 79} test incr-1.9 {TclCompileIncrCmd: increment given} { set i 10 list [incr i +07] $i } {17 17} test incr-1.10 {TclCompileIncrCmd: no increment given} { set i 10 list [incr i] $i } {11 11} test incr-1.11 {TclCompileIncrCmd: simple global name} { proc p {} { global i set i 54 incr i } p } {55} test incr-1.12 {TclCompileIncrCmd: simple local name} { proc p {} { set foo 100 incr foo } p } {101} test incr-1.13 {TclCompileIncrCmd: simple but new (unknown) local name} { proc p {} { incr bar } catch {p} msg set msg } {1} test incr-1.14 {TclCompileIncrCmd: simple local name, >255 locals} { proc 260locals {} { # create 260 locals set a0 0; set a1 0; set a2 0; set a3 0; set a4 0 set a5 0; set a6 0; set a7 0; set a8 0; set a9 0 set b0 0; set b1 0; set b2 0; set b3 0; set b4 0 set b5 0; set b6 0; set b7 0; set b8 0; set b9 0 set c0 0; set c1 0; set c2 0; set c3 0; set c4 0 set c5 0; set c6 0; set c7 0; set c8 0; set c9 0 set d0 0; set d1 0; set d2 0; set d3 0; set d4 0 set d5 0; set d6 0; set d7 0; set d8 0; set d9 0 set e0 0; set e1 0; set e2 0; set e3 0; set e4 0 set e5 0; set e6 0; set e7 0; set e8 0; set e9 0 set f0 0; set f1 0; set f2 0; set f3 0; set f4 0 set f5 0; set f6 0; set f7 0; set f8 0; set f9 0 set g0 0; set g1 0; set g2 0; set g3 0; set g4 0 set g5 0; set g6 0; set g7 0; set g8 0; set g9 0 set h0 0; set h1 0; set h2 0; set h3 0; set h4 0 set h5 0; set h6 0; set h7 0; set h8 0; set h9 0 set i0 0; set i1 0; set i2 0; set i3 0; set i4 0 set i5 0; set i6 0; set i7 0; set i8 0; set i9 0 set j0 0; set j1 0; set j2 0; set j3 0; set j4 0 set j5 0; set j6 0; set j7 0; set j8 0; set j9 0 set k0 0; set k1 0; set k2 0; set k3 0; set k4 0 set k5 0; set k6 0; set k7 0; set k8 0; set k9 0 set l0 0; set l1 0; set l2 0; set l3 0; set l4 0 set l5 0; set l6 0; set l7 0; set l8 0; set l9 0 set m0 0; set m1 0; set m2 0; set m3 0; set m4 0 set m5 0; set m6 0; set m7 0; set m8 0; set m9 0 set n0 0; set n1 0; set n2 0; set n3 0; set n4 0 set n5 0; set n6 0; set n7 0; set n8 0; set n9 0 set o0 0; set o1 0; set o2 0; set o3 0; set o4 0 set o5 0; set o6 0; set o7 0; set o8 0; set o9 0 set p0 0; set p1 0; set p2 0; set p3 0; set p4 0 set p5 0; set p6 0; set p7 0; set p8 0; set p9 0 set q0 0; set q1 0; set q2 0; set q3 0; set q4 0 set q5 0; set q6 0; set q7 0; set q8 0; set q9 0 set r0 0; set r1 0; set r2 0; set r3 0; set r4 0 set r5 0; set r6 0; set r7 0; set r8 0; set r9 0 set s0 0; set s1 0; set s2 0; set s3 0; set s4 0 set s5 0; set s6 0; set s7 0; set s8 0; set s9 0 set t0 0; set t1 0; set t2 0; set t3 0; set t4 0 set t5 0; set t6 0; set t7 0; set t8 0; set t9 0 set u0 0; set u1 0; set u2 0; set u3 0; set u4 0 set u5 0; set u6 0; set u7 0; set u8 0; set u9 0 set v0 0; set v1 0; set v2 0; set v3 0; set v4 0 set v5 0; set v6 0; set v7 0; set v8 0; set v9 0 set w0 0; set w1 0; set w2 0; set w3 0; set w4 0 set w5 0; set w6 0; set w7 0; set w8 0; set w9 0 set x0 0; set x1 0; set x2 0; set x3 0; set x4 0 set x5 0; set x6 0; set x7 0; set x8 0; set x9 0 set y0 0; set y1 0; set y2 0; set y3 0; set y4 0 set y5 0; set y6 0; set y7 0; set y8 0; set y9 0 set z0 0; set z1 0; set z2 0; set z3 0; set z4 0 set z5 0; set z6 0; set z7 0; set z8 0; set z9 0 # now increment the last one (local var index > 255) incr z9 } 260locals } {1} test incr-1.15 {TclCompileIncrCmd: variable is array} { catch {unset a} set a(foo) 27 set x [incr a(foo) 11] catch {unset a} set x } 38 test incr-1.16 {TclCompileIncrCmd: variable is array, elem substitutions} { catch {unset a} set i 5 set a(foo5) 27 set x [incr a(foo$i) 11] catch {unset a} set x } 38 test incr-1.17 {TclCompileIncrCmd: increment given, simple int} { set i 5 incr i 123 } 128 test incr-1.18 {TclCompileIncrCmd: increment given, simple int} { set i 5 incr i -100 } -95 #test incr-1.19 {TclCompileIncrCmd: increment given, but erroneous} { # set i 5 # catch {incr i [set]} msg # set errorInfo #} {wrong # args: should be "set varName ?newValue?" # while compiling #"set" # while compiling #"incr i [set]"} test incr-1.20 {TclCompileIncrCmd: increment given, in quotes} { set i 25 incr i "-100" } -75 test incr-1.21 {TclCompileIncrCmd: increment given, in braces} { set i 24 incr i {126} } 150 test incr-1.22 {TclCompileIncrCmd: increment given, large int} { set i 5 incr i 200000 } 200005 test incr-1.23 {TclCompileIncrCmd: increment given, formatted int != int} { set i 25 incr i 000012345 ;# a decimal literal } 12370 test incr-1.24 {TclCompileIncrCmd: increment given, formatted int != int} { set i 25 catch {incr i 1a} msg set msg } {expected integer but got "1a"} test incr-1.25 {TclCompileIncrCmd: too many arguments} { set i 10 catch {incr i 10 20} msg set msg } {wrong # args: should be "incr varName ?increment?"} test incr-1.29 {TclCompileIncrCmd: runtime error, bad variable value} { set x " - " list [catch {incr x 1} msg] $msg } {1 {expected integer but got " - "}} test incr-1.30 {TclCompileIncrCmd: array var, braced (no subs)} { catch {unset array} set array(\$foo) 4 incr {array($foo)} } 5 # Check "incr" and computed command names. test incr-2.0 {incr and computed command names} { set i 5 set z incr $z i -1 set i } 4 catch {unset x} catch {unset i} test incr-2.1 {incr command (not compiled): missing variable name} { set z incr list [catch {$z} msg] $msg } {1 {wrong # args: should be "incr varName ?increment?"}} test incr-2.2 {incr command (not compiled): simple variable name} { set z incr set i 10 list [$z i] $i } {11 11} test incr-2.4 {incr command (not compiled): simple variable name in quotes} { set z incr set i 17 list [$z "i"] $i } {18 18} test incr-2.5 {incr command (not compiled): simple variable name in braces} { set z incr catch {unset {a simple var}} set {a simple var} 27 list [$z {a simple var}] ${a simple var} } {28 28} test incr-2.6 {incr command (not compiled): simple array variable name} { set z incr catch {unset a} set a(foo) 37 list [$z a(foo)] $a(foo) } {38 38} test incr-2.7 {incr command (not compiled): non-simple (computed) variable name} { set z incr set x "i" set i 77 list [$z $x 2] $i } {79 79} test incr-2.8 {incr command (not compiled): non-simple (computed) variable name} { set z incr set x "i" set i 77 list [$z [set x] +2] $i } {79 79} test incr-2.9 {incr command (not compiled): increment given} { set z incr set i 10 list [$z i +07] $i } {17 17} test incr-2.10 {incr command (not compiled): no increment given} { set z incr set i 10 list [$z i] $i } {11 11} test incr-2.11 {incr command (not compiled): simple global name} { proc p {} { set z incr global i set i 54 $z i } p } {55} test incr-2.12 {incr command (not compiled): simple local name} { proc p {} { set z incr set foo 100 $z foo } p } {101} test incr-2.13 {incr command (not compiled): simple but new (unknown) local name} { proc p {} { set z incr $z bar } catch {p} msg set msg } {1} test incr-2.14 {incr command (not compiled): simple local name, >255 locals} { proc 260locals {} { set z incr # create 260 locals set a0 0; set a1 0; set a2 0; set a3 0; set a4 0 set a5 0; set a6 0; set a7 0; set a8 0; set a9 0 set b0 0; set b1 0; set b2 0; set b3 0; set b4 0 set b5 0; set b6 0; set b7 0; set b8 0; set b9 0 set c0 0; set c1 0; set c2 0; set c3 0; set c4 0 set c5 0; set c6 0; set c7 0; set c8 0; set c9 0 set d0 0; set d1 0; set d2 0; set d3 0; set d4 0 set d5 0; set d6 0; set d7 0; set d8 0; set d9 0 set e0 0; set e1 0; set e2 0; set e3 0; set e4 0 set e5 0; set e6 0; set e7 0; set e8 0; set e9 0 set f0 0; set f1 0; set f2 0; set f3 0; set f4 0 set f5 0; set f6 0; set f7 0; set f8 0; set f9 0 set g0 0; set g1 0; set g2 0; set g3 0; set g4 0 set g5 0; set g6 0; set g7 0; set g8 0; set g9 0 set h0 0; set h1 0; set h2 0; set h3 0; set h4 0 set h5 0; set h6 0; set h7 0; set h8 0; set h9 0 set i0 0; set i1 0; set i2 0; set i3 0; set i4 0 set i5 0; set i6 0; set i7 0; set i8 0; set i9 0 set j0 0; set j1 0; set j2 0; set j3 0; set j4 0 set j5 0; set j6 0; set j7 0; set j8 0; set j9 0 set k0 0; set k1 0; set k2 0; set k3 0; set k4 0 set k5 0; set k6 0; set k7 0; set k8 0; set k9 0 set l0 0; set l1 0; set l2 0; set l3 0; set l4 0 set l5 0; set l6 0; set l7 0; set l8 0; set l9 0 set m0 0; set m1 0; set m2 0; set m3 0; set m4 0 set m5 0; set m6 0; set m7 0; set m8 0; set m9 0 set n0 0; set n1 0; set n2 0; set n3 0; set n4 0 set n5 0; set n6 0; set n7 0; set n8 0; set n9 0 set o0 0; set o1 0; set o2 0; set o3 0; set o4 0 set o5 0; set o6 0; set o7 0; set o8 0; set o9 0 set p0 0; set p1 0; set p2 0; set p3 0; set p4 0 set p5 0; set p6 0; set p7 0; set p8 0; set p9 0 set q0 0; set q1 0; set q2 0; set q3 0; set q4 0 set q5 0; set q6 0; set q7 0; set q8 0; set q9 0 set r0 0; set r1 0; set r2 0; set r3 0; set r4 0 set r5 0; set r6 0; set r7 0; set r8 0; set r9 0 set s0 0; set s1 0; set s2 0; set s3 0; set s4 0 set s5 0; set s6 0; set s7 0; set s8 0; set s9 0 set t0 0; set t1 0; set t2 0; set t3 0; set t4 0 set t5 0; set t6 0; set t7 0; set t8 0; set t9 0 set u0 0; set u1 0; set u2 0; set u3 0; set u4 0 set u5 0; set u6 0; set u7 0; set u8 0; set u9 0 set v0 0; set v1 0; set v2 0; set v3 0; set v4 0 set v5 0; set v6 0; set v7 0; set v8 0; set v9 0 set w0 0; set w1 0; set w2 0; set w3 0; set w4 0 set w5 0; set w6 0; set w7 0; set w8 0; set w9 0 set x0 0; set x1 0; set x2 0; set x3 0; set x4 0 set x5 0; set x6 0; set x7 0; set x8 0; set x9 0 set y0 0; set y1 0; set y2 0; set y3 0; set y4 0 set y5 0; set y6 0; set y7 0; set y8 0; set y9 0 set z0 0; set z1 0; set z2 0; set z3 0; set z4 0 set z5 0; set z6 0; set z7 0; set z8 0; set z9 0 # now increment the last one (local var index > 255) $z z9 } 260locals } {1} test incr-2.15 {incr command (not compiled): variable is array} { set z incr catch {unset a} set a(foo) 27 set x [$z a(foo) 11] catch {unset a} set x } 38 test incr-2.16 {incr command (not compiled): variable is array, elem substitutions} { set z incr catch {unset a} set i 5 set a(foo5) 27 set x [$z a(foo$i) 11] catch {unset a} set x } 38 test incr-2.17 {incr command (not compiled): increment given, simple int} { set z incr set i 5 $z i 123 } 128 test incr-2.18 {incr command (not compiled): increment given, simple int} { set z incr set i 5 $z i -100 } -95 test incr-2.20 {incr command (not compiled): increment given, in quotes} { set z incr set i 25 $z i "-100" } -75 test incr-2.21 {incr command (not compiled): increment given, in braces} { set z incr set i 24 $z i {126} } 150 test incr-2.22 {incr command (not compiled): increment given, large int} { set z incr set i 5 $z i 200000 } 200005 test incr-2.23 {incr command (not compiled): increment given, formatted int != int} { set z incr set i 25 $z i 000012345 ;# an octal literal } 12370 test incr-2.24 {incr command (not compiled): increment given, formatted int != int} { set z incr set i 25 catch {$z i 1a} msg set msg } {expected integer but got "1a"} test incr-2.25 {incr command (not compiled): too many arguments} { set z incr set i 10 catch {$z i 10 20} msg set msg } {wrong # args: should be "incr varName ?increment?"} test incr-2.29 {incr command (not compiled): runtime error, bad variable value} { set z incr set x " - " list [catch {$z x 1} msg] $msg } {1 {expected integer but got " - "}} ################################################################################ # LLENGTH ################################################################################ test llength-1.1 {length of list} { llength {a b c d} } 4 test llength-1.2 {length of list} { llength {a b c {a b {c d}} d} } 5 test llength-1.3 {length of list} { llength {} } 0 test llength-2.1 {error conditions} { list [catch {llength} msg] $msg } {1 {wrong # args: should be "llength list"}} test llength-2.2 {error conditions} { list [catch {llength 123 2} msg] $msg } {1 {wrong # args: should be "llength list"}} ################################################################################ # LINDEX ################################################################################ set lindex lindex set minus - # Tests of Tcl_LindexObjCmd, NOT COMPILED test lindex-1.1 {wrong # args} { list [catch {eval $lindex} result] $result } "1 {wrong # args: should be \"lindex list ?index ...?\"}" # Indices that are lists or convertible to lists #test lindex-2.1 {empty index list} { # set x {} # list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] #} {{a b c} {a b c}} test lindex-2.2 {singleton index list} { set x { 1 } list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {b b} test lindex-2.4 {malformed index list} { set x \{ list [catch { eval [list $lindex {a b c} $x] } result] $result } {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?} # Indices that are integers or convertible to integers test lindex-3.1 {integer -1} { set x ${minus}1 list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {{} {}} test lindex-3.2 {integer 0} { set x [string range 00 0 0] list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {a a} test lindex-3.3 {integer 2} { set x [string range 22 0 0] list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {c c} test lindex-3.4 {integer 3} { set x [string range 33 0 0] list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {{} {}} test lindex-3.7 {indexes don't shimmer wide ints} { set x [expr {(1<<31) - 2}] list $x [lindex {1 2 3} $x] [incr x] [incr x] } {2147483646 {} 2147483647 2147483648} # Indices relative to end test lindex-4.1 {index = end} { set x end list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {c c} test lindex-4.2 {index = end--1} { set x end--1 list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {{} {}} test lindex-4.3 {index = end-0} { set x end-0 list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {c c} test lindex-4.4 {index = end-2} { set x end-2 list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {a a} test lindex-4.5 {index = end-3} { set x end-3 list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] } {{} {}} test lindex-4.8 {bad integer, not octal} { set x end-0a2 list [catch { eval [list $lindex {a b c} $x] } result] $result } {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}} #test lindex-4.9 {incomplete end} { # set x en # list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]] #} {c c} test lindex-4.10 {incomplete end-} { set x end- list [catch { eval [list $lindex {a b c} $x] } result] $result } {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}} test lindex-5.1 {bad second index} { list [catch { eval [list $lindex {a b c} 0 0a2] } result] $result } {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}} test lindex-5.2 {good second index} { eval [list $lindex {{a b c} {d e f} {g h i}} 1 2] } f test lindex-5.3 {three indices} { eval [list $lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1] } f test lindex-7.1 {quoted elements} { eval [list $lindex {a "b c" d} 1] } {b c} test lindex-7.2 {quoted elements} { eval [list $lindex {"{}" b c} 0] } {{}} test lindex-7.3 {quoted elements} { eval [list $lindex {ab "c d \" x" y} 1] } {c d " x} test lindex-7.4 {quoted elements} { lindex {a b {c d "e} {f g"}} 2 } {c d "e} test lindex-8.1 {data reuse} { set x 0 eval [list $lindex $x $x] } {0} test lindex-8.2 {data reuse} { set a 0 eval [list $lindex $a $a $a] } 0 test lindex-8.3 {data reuse} { set a 1 eval [list $lindex $a $a $a] } {} #---------------------------------------------------------------------- test lindex-10.2 {singleton index list} { set x { 1 } catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {b b} test lindex-10.4 {malformed index list} { set x \{ list [catch { lindex {a b c} $x } result] $result } {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?} # Indices that are integers or convertible to integers test lindex-11.1 {integer -1} { set x ${minus}1 catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {{} {}} test lindex-11.2 {integer 0} { set x [string range 00 0 0] catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {a a} test lindex-11.3 {integer 2} { set x [string range 22 0 0] catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {c c} test lindex-11.4 {integer 3} { set x [string range 33 0 0] catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {{} {}} # Indices relative to end test lindex-12.1 {index = end} { set x end catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {c c} test lindex-12.2 {index = end--1} { set x end--1 catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {{} {}} test lindex-12.3 {index = end-0} { set x end-0 catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {c c} test lindex-12.4 {index = end-2} { set x end-2 catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {a a} test lindex-12.5 {index = end-3} { set x end-3 catch { list [lindex {a b c} $x] [lindex {a b c} $x] } result set result } {{} {}} test lindex-12.8 {bad integer, not octal} { set x end-0a2 list [catch { lindex {a b c} $x } result] $result } {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}} test lindex-12.10 {incomplete end-} { set x end- list [catch { lindex {a b c} $x } result] $result } {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}} test lindex-13.1 {bad second index} { list [catch { lindex {a b c} 0 0a2 } result] $result } {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}} test lindex-13.2 {good second index} { catch { lindex {{a b c} {d e f} {g h i}} 1 2 } result set result } f test lindex-13.3 {three indices} { catch { lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1 } result set result } f test lindex-15.1 {quoted elements} { catch { lindex {a "b c" d} 1 } result set result } {b c} test lindex-15.2 {quoted elements} { catch { lindex {"{}" b c} 0 } result set result } {{}} test lindex-15.3 {quoted elements} { catch { lindex {ab "c d \" x" y} 1 } result set result } {c d " x} test lindex-15.4 {quoted elements} { catch { lindex {a b {c d "e} {f g"}} 2 } result set result } {c d "e} test lindex-16.1 {data reuse} { set x 0 catch { lindex $x $x } result set result } {0} test lindex-16.2 {data reuse} { set a 0 catch { lindex $a $a $a } result set result } 0 test lindex-16.3 {data reuse} { set a 1 catch { lindex $a $a $a } result set result } {} test lindex-17.1 {no index} { lindex {a b c} } {a b c} catch { unset lindex} catch { unset minus } ################################################################################ # LINDEX ################################################################################ catch {unset a} catch {unset x} # Basic "foreach" operation. test foreach-1.1 {basic foreach tests} { set a {} foreach i {a b c d} { set a [concat $a $i] } set a } {a b c d} test foreach-1.2 {basic foreach tests} { set a {} foreach i {a b {{c d} e} {123 {{x}}}} { set a [concat $a $i] } set a } {a b {c d} e 123 {{x}}} test foreach-1.3 {basic foreach tests} {catch {foreach} msg} 1 test foreach-1.4 {basic foreach tests} {catch {foreach i} msg} 1 test foreach-1.5 {basic foreach tests} {catch {foreach i j} msg} 1 test foreach-1.6 {basic foreach tests} {catch {foreach i j k l} msg} 1 test foreach-1.7 {basic foreach tests} { set a {} foreach i {} { set a [concat $a $i] } set a } {} catch {unset a} test foreach-2.1 {foreach errors} { list [catch {foreach {} {} {}} msg] $msg } {1 {foreach varlist is empty}} catch {unset a} test foreach-3.1 {parallel foreach tests} { set x {} foreach {a b} {1 2 3 4} { append x $b $a } set x } {2143} test foreach-3.2 {parallel foreach tests} { set x {} foreach {a b} {1 2 3 4 5} { append x $b $a } set x } {21435} test foreach-3.3 {parallel foreach tests} { set x {} foreach a {1 2 3} b {4 5 6} { append x $b $a } set x } {415263} test foreach-3.4 {parallel foreach tests} { set x {} foreach a {1 2 3} b {4 5 6 7 8} { append x $b $a } set x } {41526378} test foreach-3.5 {parallel foreach tests} { set x {} foreach {a b} {a b A B aa bb} c {c C cc CC} { append x $a $b $c } set x } {abcABCaabbccCC} test foreach-3.6 {parallel foreach tests} { set x {} foreach a {1 2 3} b {1 2 3} c {1 2 3} d {1 2 3} e {1 2 3} { append x $a $b $c $d $e } set x } {111112222233333} test foreach-3.7 {parallel foreach tests} { set x {} foreach a {} b {1 2 3} c {1 2} d {1 2 3 4} e {{1 2}} { append x $a $b $c $d $e } set x } {1111 2222334} test foreach-4.1 {foreach only sets vars if repeating loop} { proc foo {} { set rgb {65535 0 0} foreach {r g b} [set rgb] {} return "r=$r, g=$g, b=$b" } foo } {r=65535, g=0, b=0} test foreach-5.1 {foreach supports dict syntactic sugar} { proc foo {} { set x {} foreach {a(3)} {1 2 3 4} {lappend x [set {a(3)}]} list $a $x } foo } {{3 4} {1 2 3 4}} test foreach-6.1 {noncompiled foreach and shared variable or value list objects that are converted to another type} { catch {unset x} foreach {12.0} {a b c} { set x 12.0 set x [expr $x + 1] } set x } 13.0 # Check "continue". test foreach-7.1 {continue tests} {catch continue} 4 test foreach-7.2 {continue tests} { set a {} foreach i {a b c d} { if {[string compare $i "b"] == 0} continue set a [concat $a $i] } set a } {a c d} test foreach-7.3 {continue tests} { set a {} foreach i {a b c d} { if {[string compare $i "b"] != 0} continue set a [concat $a $i] } set a } {b} test foreach-7.4 {continue tests} {catch {continue foo} msg} 1 test foreach-7.5 {continue tests} { catch {continue foo} msg set msg } {wrong # args: should be "continue"} # Check "break". test foreach-8.1 {break tests} {catch break} 3 test foreach-8.2 {break tests} { set a {} foreach i {a b c d} { if {[string compare $i "c"] == 0} break set a [concat $a $i] } set a } {a b} test foreach-8.3 {break tests} {catch {break foo} msg} 1 test foreach-8.4 {break tests} { catch {break foo} msg set msg } {wrong # args: should be "break"} # Test for incorrect "double evaluation" semantics test foreach-9.1 {delayed substitution of body - knownbugs} { proc foo {} { set a 0 foreach a [list 1 2 3] " set x $a " set x } foo } {0} # cleanup catch {unset a} catch {unset x} ################################################################################ # STRING ################################################################################ # string last test string-7.1 {string last, too few args} { list [catch {string last a} msg] $msg } {1 {wrong # args: should be "string last subString string ?index?"}} test string-7.2 {string last, bad args} { list [catch {string last a b c} msg] $msg } {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}} test string-7.3 {string last, too many args} { list [catch {string last a b c d} msg] $msg } {1 {wrong # args: should be "string last subString string ?index?"}} test string-7.5 {string last} { string last xx xxxx123xx345x678 } 7 test string-7.13 {string last, start index} { ## Constrain to last 'a' should work string last ba badbad end-1 } 3 test string-7.14 {string last, start index} { ## Constrain to last 'b' should skip last 'ba' string last ba badbad end-2 } 0 ## string match ## test string-11.1 {string match, too few args} { proc foo {} {string match a} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string match ?-nocase? pattern string"}} test string-11.2 {string match, too many args} { proc foo {} {string match a b c d} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string match ?-nocase? pattern string"}} test string-11.3 {string match} { proc foo {} {string match abc abc} foo } 1 #test string-11.4 {string match} { # proc foo {} {string mat abc abd} # foo #} 0 test string-11.5 {string match} { proc foo {} {string match ab*c abc} foo } 1 test string-11.6 {string match} { proc foo {} {string match ab**c abc} foo } 1 test string-11.7 {string match} { proc foo {} {string match ab* abcdef} foo } 1 test string-11.8 {string match} { proc foo {} {string match *c abc} foo } 1 test string-11.9 {string match} { proc foo {} {string match *3*6*9 0123456789} foo } 1 test string-11.10 {string match} { proc foo {} {string match *3*6*9 01234567890} foo } 0 test string-11.11 {string match} { proc foo {} {string match a?c abc} foo } 1 test string-11.12 {string match} { proc foo {} {string match a??c abc} foo } 0 test string-11.13 {string match} { proc foo {} {string match ?1??4???8? 0123456789} foo } 1 test string-11.14 {string match} { proc foo {} {string match {[abc]bc} abc} foo } 1 test string-11.15 {string match} { proc foo {} {string match {a[abc]c} abc} foo } 1 test string-11.16 {string match} { proc foo {} {string match {a[xyz]c} abc} foo } 0 test string-11.17 {string match} { proc foo {} {string match {12[2-7]45} 12345} foo } 1 test string-11.18 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12345} foo } 1 test string-11.19 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12b45} foo } 1 test string-11.20 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12d45} foo } 1 test string-11.21 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12145} foo } 0 test string-11.22 {string match} { proc foo {} {string match {12[ab2-4cd]45} 12545} foo } 0 test string-11.23 {string match} { proc foo {} {string match {a\*b} a*b} foo } 1 test string-11.24 {string match} { proc foo {} {string match {a\*b} ab} foo } 0 test string-11.25 {string match} { proc foo {} {string match {a\*\?\[\]\\\x} "a*?\[\]\\x"} foo } 1 test string-11.26 {string match} { proc foo {} {string match ** ""} foo } 1 test string-11.27 {string match} { proc foo {} {string match *. ""} foo } 0 test string-11.28 {string match} { proc foo {} {string match "" ""} foo } 1 test string-11.29 {string match} { proc foo {} {string match \[a a} foo } 1 test string-11.31 {string match case} { proc foo {} {string match a A} foo } 0 test string-11.32 {string match nocase} { proc foo {} {string match -n a A} foo } 1 #test string-11.33 {string match nocase} { # proc foo {} {string match -nocase a\334 A\374} # foo #} 1 test string-11.34 {string match nocase} { proc foo {} {string match -nocase a*f ABCDEf} foo } 1 test string-11.35 {string match case, false hope} { # This is true because '_' lies between the A-Z and a-z ranges proc foo {} {string match {[A-z]} _} foo } 1 test string-11.36 {string match nocase range} { # This is false because although '_' lies between the A-Z and a-z ranges, # we lower case the end points before checking the ranges. proc foo {} {string match -nocase {[A-z]} _} foo } 0 test string-11.37 {string match nocase} { proc foo {} {string match -nocase {[A-fh-Z]} g} foo } 0 test string-11.38 {string match case, reverse range} { proc foo {} {string match {[A-fh-Z]} g} foo } 1 test string-11.39 {string match, *\ case} { proc foo {} {string match {*\abc} abc} foo } 1 test string-11.40 {string match, *special case} { proc foo {} {string match {*[ab]} abc} foo } 0 test string-11.41 {string match, *special case} { proc foo {} {string match {*[ab]*} abc} foo } 1 #test string-11.42 {string match, *special case} { # proc foo {} {string match "*\\" "\\"} # foo #} 0 test string-11.43 {string match, *special case} { proc foo {} {string match "*\\\\" "\\"} foo } 1 test string-11.44 {string match, *special case} { proc foo {} {string match "*???" "12345"} foo } 1 test string-11.45 {string match, *special case} { proc foo {} {string match "*???" "12"} foo } 0 test string-11.46 {string match, *special case} { proc foo {} {string match "*\\*" "abc*"} foo } 1 test string-11.47 {string match, *special case} { proc foo {} {string match "*\\*" "*"} foo } 1 test string-11.48 {string match, *special case} { proc foo {} {string match "*\\*" "*abc"} foo } 0 test string-11.49 {string match, *special case} { proc foo {} {string match "?\\*" "a*"} foo } 1 #test string-11.50 {string match, *special case} { # proc foo {} {string match "\\" "\\"} # foo #} 0 ## string length ## test string-9.1 {string length} { proc foo {} {string length} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string length string"}} test string-9.2 {string length} { proc foo {} {string length a b} list [catch {foo} msg] $msg } {1 {wrong # args: should be "string length string"}} test string-9.3 {string length} { proc foo {} {string length "a little string"} foo } 15 # string map test string-10.4 {string map} { string map {a b} abba } {bbbb} test string-10.5 {string map} { string map {a b} a } {b} test string-10.6 {string map -nocase} { string map -nocase {a b} Abba } {bbbb} test string-10.7 {string map} { string map {abc 321 ab * a A} aabcabaababcab } {A321*A*321*} test string-10.8 {string map -nocase} { string map -nocase {aBc 321 Ab * a A} aabcabaababcab } {A321*A*321*} test string-10.10 {string map} { list [catch {string map {a b c} abba} msg] $msg } {1 {list must contain an even number of elements}} test string-10.11 {string map, nulls} { string map {\x00 NULL blah \x00nix} {qwerty} } {qwerty} test string-10.12 {string map, unicode} { string map [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU" } aueue\u00dc\0EU test string-10.13 {string map, -nocase unicode} { string map -nocase [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU" } aue\u00dc\u00dc\0EU test string-10.14 {string map, -nocase null arguments} { string map -nocase {{} abc} foo } foo test string-10.15 {string map, one pair case} { string map -nocase {abc 32} aAbCaBaAbAbcAb } {a32aBaAb32Ab} test string-10.16 {string map, one pair case} { string map -nocase {ab 4321} aAbCaBaAbAbcAb } {a4321C4321a43214321c4321} test string-10.17 {string map, one pair case} { string map {Ab 4321} aAbCaBaAbAbcAb } {a4321CaBa43214321c4321} test string-10.18 {string map, empty argument} { string map -nocase {{} abc} foo } foo test string-10.19 {string map, empty arguments} { string map -nocase {{} abc f bar {} def} foo } baroo ################################################################################ # SPLIT ################################################################################ test split-1.1 {basic split commands} { split "a\n b\t\r c\n " } {a {} b {} {} c {} {}} test split-1.2 {basic split commands} { split "word 1xyzword 2zword 3" xyz } {{word 1} {} {} {word 2} {word 3}} test split-1.3 {basic split commands} { split "12345" {} } {1 2 3 4 5} test split-1.4 {basic split commands} { split "a\}b\[c\{\]\$" } "a\\}b\\\[c\\{\\\]\\\$" test split-1.5 {basic split commands} { split {} {} } {} test split-1.6 {basic split commands} { split {} } {} test split-1.7 {basic split commands} { split { } } {{} {} {} {}} test split-1.8 {basic split commands} { proc foo {} { set x {} foreach f [split {]\n} {}] { append x $f } return $x } foo } {]\n} test split-1.9 {basic split commands} { proc foo {} { set x ab\000c set y [split $x {}] return $y } foo } "a b \000 c" test split-1.10 {basic split commands} { split "a0ab1b2bbb3\000c4" ab\000c } {{} 0 {} 1 2 {} {} 3 {} 4} test split-1.11 {basic split commands} { split "12,3,45" {,} } {12 3 45} test split-1.12 {basic split commands} { split "\u0001ab\u0001cd\u0001\u0001ef\u0001" \1 } {{} ab cd {} ef {}} test split-1.13 {basic split commands} { split "12,34,56," {,} } {12 34 56 {}} test split-1.14 {basic split commands} { split ",12,,,34,56," {,} } {{} 12 {} {} 34 56 {}} test split-2.1 {split errors} { list [catch split msg] $msg } {1 {wrong # args: should be "split string ?splitChars?"}} test split-2.2 {split errors} { list [catch {split a b c} msg] $msg } {1 {wrong # args: should be "split string ?splitChars?"}} # cleanup catch {rename foo {}} ################################################################################ # JOIN ################################################################################ test join-1.1 {basic join commands} { join {a b c} xyz } axyzbxyzc test join-1.2 {basic join commands} { join {a b c} {} } abc test join-1.3 {basic join commands} { join {} xyz } {} test join-1.4 {basic join commands} { join {12 34 56} } {12 34 56} test join-2.1 {join errors} { list [catch join msg] $msg } {1 {wrong # args: should be "join list ?joinString?"}} test join-2.2 {join errors} { list [catch {join a b c} msg] $msg } {1 {wrong # args: should be "join list ?joinString?"}} #test join-2.3 {join errors} { # list [catch {join "a \{ c" 111} msg] $msg #} {1 {unmatched open brace in list}} test join-3.1 {joinString is binary ok} { string length [join {a b c} a\0b] } 9 test join-3.2 {join is binary ok} { string length [join "a\0b a\0b a\0b"] } 11 ################################################################################ # SWITCH ################################################################################ test switch-1.1 {simple patterns} { switch a a {expr 1} b {expr 2} c {expr 3} default {expr 4} } 1 test switch-1.2 {simple patterns} { switch b a {expr 1} b {expr 2} c {expr 3} default {expr 4} } 2 test switch-1.3 {simple patterns} { switch x a {expr 1} b {expr 2} c {expr 3} default {expr 4} } 4 test switch-1.4 {simple patterns} { switch x a {expr 1} b {expr 2} c {expr 3} } {} test switch-1.5 {simple pattern matches many times} { switch b a {expr 1} b {expr 2} b {expr 3} b {expr 4} } 2 test switch-1.6 {simple patterns} { switch default a {expr 1} default {expr 2} c {expr 3} default {expr 4} } 2 test switch-1.7 {simple patterns} { switch x a {expr 1} default {expr 2} c {expr 3} default {expr 4} } 4 test switch-2.1 {single-argument form for pattern/command pairs} { switch b { a {expr 1} b {expr 2} default {expr 6} } } {2} test switch-2.2 {single-argument form for pattern/command pairs} { list [catch {switch z {a 2 b}}] } 1 test switch-3.1 {-exact vs. -glob vs. -regexp} { switch -exact aaaab { ^a*b$ {concat regexp} *b {concat glob} aaaab {concat exact} default {concat none} } } exact test switch-3.2 {-exact vs. -glob vs. -regexp (no [regexp] cmd)} regexp { rename regexp regexp.none set rc [catch { switch -regexp aaaab { ^a*b$ {concat regexp} *b {concat glob} aaaab {concat exact} default {concat none} } }] rename regexp.none regexp set rc } 1 test switch-3.3 {-exact vs. -glob vs. -regexp (with [regexp] cmd)} regexp { switch -regexp aaaab { ^a*b$ {concat regexp} *b {concat glob} aaaab {concat exact} default {concat none} } } regexp test switch-3.4 {-exact vs. -glob vs. -regexp} { switch -glob aaaab { ^a*b$ {concat regexp} *b {concat glob} aaaab {concat exact} default {concat none} } } glob test switch-3.5 {-exact vs. -glob vs. -regexp} { switch aaaab {^a*b$} {concat regexp} *b {concat glob} \ aaaab {concat exact} default {concat none} } exact test switch-3.6 {-exact vs. -glob vs. -regexp} { switch -- -glob { ^g.*b$ {concat regexp} -* {concat glob} -glob {concat exact} default {concat none} } } exact test switch-3.7 {-exact vs. -glob vs. -regexp} { list [catch {switch -foo a b c} msg] $msg } {1 {bad option "-foo": must be -exact, -glob, -regexp, -command procname or --}} test switch-4.1 {error in executed command} { list [catch {switch a a {error "Just a test"} default {expr 1}} msg] \ $msg } {1 {Just a test}} test switch-4.2 {error: not enough args} { catch {switch} } 1 test switch-4.3 {error: pattern with no body} { catch {switch a b} } 1 test switch-4.4 {error: pattern with no body} { catch {switch a b {expr 1} c} } 1 test switch-4.5 {error in default command} { list [catch {switch foo a {error switch1} b {error switch 3} \ default {error switch2}} msg] $msg } {1 switch2} test switch-5.1 {errors in -regexp matching} regexp { catch {switch -regexp aaaab { *b {concat glob} aaaab {concat exact} default {concat none} }} msg } 1 test switch-6.1 {backslashes in patterns} { switch -exact {\a\$\.\[} { \a\$\.\[ {concat first} \a\\$\.\\[ {concat second} \\a\\$\\.\\[ {concat third} {\a\\$\.\\[} {concat fourth} {\\a\\$\\.\\[} {concat fifth} default {concat none} } } third test switch-6.2 {backslashes in patterns} { switch -exact {\a\$\.\[} { \a\$\.\[ {concat first} {\a\$\.\[} {concat second} {{\a\$\.\[}} {concat third} default {concat none} } } second test switch-7.1 {"-" bodies} { switch a { a - b - c {concat 1} default {concat 2} } } 1 test switch-7.2 {"-" bodies} { list [catch { switch a { a - b - c - } } msg] $msg } {1 {no body specified for pattern "c"}} # Following original Tcl test makes no sense, I feel! Please review ... #~ test switch-7.3 {"-" bodies} { #~ list [catch { #~ switch a { #~ a - #~ b -foo #~ c - #~ } #~ } msg] $msg #~ } {1 {no body specified for pattern "c"}} test switch-7.3 {"-" bodies} { list [catch { switch a { a - b -foo c - } } msg] $msg } {1 {invalid command name "-foo"}} test switch-8.1 {empty body} { set msg {} switch {2} { 1 {set msg 1} 2 {} default {set msg 2} } } {} test switch-9.1 {empty pattern/body list} { catch {switch x} } 1 test switch-9.2 {empty pattern/body list} { catch {switch -- x} } 1 test switch-9.3 {empty pattern/body list} { catch {switch x {}} } 1 test switch-9.4 {empty pattern/body list} { catch {switch -- x {}} } 1 test switch-9.5 {unpaired pattern} { catch {switch x a {} b} } 1 test switch-9.6 {unpaired pattern} { catch {switch x {a {} b}} } 1 test switch-9.7 {unpaired pattern} { catch {switch x a {} # comment b} } 1 test switch-9.8 {unpaired pattern} { catch {switch x {a {} # comment b}} } 1 test switch-9.9 {unpaired pattern} { catch {switch x a {} x {} # comment b} } 1 test switch-9.10 {unpaired pattern} { catch {switch x {a {} x {} # comment b}} } 1 test switch-10.1 {no callback given to -command} { catch {switch -command a { a {expr 1} b {expr 2} }} } 1 test switch-10.2 {callback expect wrong # args for -command} lambda { catch {switch -command [lambda {p1} {expr 1}] a { a {expr 1} b {expr 2} }} } 1 test switch-10.3 {callback to -command returns ever 0: no match} lambda { switch -command [lambda {p1 p2} {expr 0}] a a {expr 1} b {expr 2} } {} test switch-10.4 {callback to -command returns 3 at first match} lambda { switch -command [lambda {p1 p2} {expr 3}] a a {expr 1} b {expr 2} } 1 test switch-10.5 {[error] in callback to -command} lambda { list [catch { switch -command [lambda {p1 p2} {error "foo"}] a a {expr 1} b {expr 2} } msg] $msg } {1 foo} test switch-10.6 {[continue] in callback to -command} lambda { list [catch { switch -command [lambda {p1 p2} {continue}] a a {expr 1} b {expr 2} } msg] $msg } {4 {}} test switch-10.7 {callback matches first if pat < str} lambda { switch -command [lambda {pat str} {expr {$pat < $str}}] 3 \ 5 {expr 1} 3 {expr 2} } {} test switch-10.8 {callback matches first if pat < str} lambda { switch -command [lambda {pat str} {expr {$pat < $str}}] 7 \ 5 {expr 1} 3 {expr 2} } 1 test switch-10.9 {callback matches first if pat < str} lambda { switch -command [lambda {pat str} {expr {$pat < $str}}] 4 \ 5 {expr 1} 3 {expr 2} } 2 ################################################################################ # FOR ################################################################################ # Basic "for" operation. test for-1.1 {TclCompileForCmd: missing initial command} { list [catch {for} msg] $msg } {1 {wrong # args: should be "for start test next body"}} test for-1.2 {TclCompileForCmd: error in initial command} { list [catch {for {set}} msg] $msg } {1 {wrong # args: should be "for start test next body"}} catch {unset i} test for-1.3 {TclCompileForCmd: missing test expression} { catch {for {set i 0}} msg set msg } {wrong # args: should be "for start test next body"} test for-1.5 {TclCompileForCmd: test expression is enclosed in quotes} { set i 0 for {} "$i > 5" {incr i} {} } {} test for-1.6 {TclCompileForCmd: missing "next" command} { catch {for {set i 0} {$i < 5}} msg set msg } {wrong # args: should be "for start test next body"} test for-1.7 {TclCompileForCmd: missing command body} { catch {for {set i 0} {$i < 5} {incr i}} msg set msg } {wrong # args: should be "for start test next body"} catch {unset a} test for-1.9 {TclCompileForCmd: simple command body} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 break set a [concat $a $i] } set a } {1 2 3} test for-1.10 {TclCompileForCmd: command body in quotes} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} "append a x" set a } {xxxxx} test for-1.11 {TclCompileForCmd: computed command body} { catch {unset x1} catch {unset bb} catch {unset x2} set x1 {append a x1; } set bb {break} set x2 {; append a x2} set a {} for {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2 set a } {x1} test for-1.13 {TclCompileForCmd: long command body} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 break if $i>5 continue set tcl_platform(machine) i686 if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } set a [concat $a $i] } set a } {1 2 3} test for-1.14 {TclCompileForCmd: for command result} { set a [for {set i 0} {$i < 5} {incr i} {}] set a } {} test for-1.15 {TclCompileForCmd: for command result} { set a [for {set i 0} {$i < 5} {incr i} {if $i==3 break}] set a } {} # Check "for" and "continue". test for-2.1 {TclCompileContinueCmd: arguments after "continue"} { catch {continue foo} msg set msg } {wrong # args: should be "continue"} test for-2.2 {TclCompileContinueCmd: continue result} { catch continue } 4 test for-2.3 {continue tests} { set a {} for {set i 1} {$i <= 4} {set i [expr $i+1]} { if {$i == 2} continue set a [concat $a $i] } set a } {1 3 4} test for-2.4 {continue tests} { set a {} for {set i 1} {$i <= 4} {set i [expr $i+1]} { if {$i != 2} continue set a [concat $a $i] } set a } {2} test for-2.5 {continue tests, nested loops} { set msg {} for {set i 1} {$i <= 4} {incr i} { for {set a 1} {$a <= 2} {incr a} { if {$i>=2 && $a>=2} continue set msg [concat $msg "$i.$a"] } } set msg } {1.1 1.2 2.1 3.1 4.1} test for-2.6 {continue tests, long command body} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==2 continue if $i==4 break if $i>5 continue if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } set a [concat $a $i] } set a } {1 3} # Check "for" and "break". test for-3.1 {TclCompileBreakCmd: arguments after "break"} { catch {break foo} msg set msg } {wrong # args: should be "break"} test for-3.2 {TclCompileBreakCmd: break result} { catch break } 3 test for-3.3 {break tests} { set a {} for {set i 1} {$i <= 4} {incr i} { if {$i == 3} break set a [concat $a $i] } set a } {1 2} test for-3.4 {break tests, nested loops} { set msg {} for {set i 1} {$i <= 4} {incr i} { for {set a 1} {$a <= 2} {incr a} { if {$i>=2 && $a>=2} break set msg [concat $msg "$i.$a"] } } set msg } {1.1 1.2 2.1 3.1 4.1} test for-3.5 {break tests, long command body} { set a {} for {set i 1} {$i<6} {set i [expr $i+1]} { if $i==2 continue if $i==5 break if $i>5 continue if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i == 4} break if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } set a [concat $a $i] } set a } {1 3} test for-4.1 {break must reset the interp result} { catch { set z GLOBTESTDIR/dir2/file2.c if [string match GLOBTESTDIR/dir2/* $z] { break } } j set j } {} # Test for incorrect "double evaluation" semantics test for-5.1 {possible delayed substitution of increment command} { # Increment should be 5, and lappend should always append $a catch {unset a} catch {unset i} set a 5 set i {} for {set a 1} {$a < 12} "incr a $a" {lappend i $a} set i } {1 6 11} test for-5.2 {possible delayed substitution of increment command} { # Increment should be 5, and lappend should always append $a catch {rename p ""} proc p {} { set a 5 set i {} for {set a 1} {$a < 12} "incr a $a" {lappend i $a} set i } p } {1 6 11} test for-5.3 {possible delayed substitution of body command} { # Increment should be $a, and lappend should always append 5 set a 5 set i {} for {set a 1} {$a < 12} {incr a $a} "lappend i $a" set i } {5 5 5 5} test for-5.4 {possible delayed substitution of body command} { # Increment should be $a, and lappend should always append 5 catch {rename p ""} proc p {} { set a 5 set i {} for {set a 1} {$a < 12} {incr a $a} "lappend i $a" set i } p } {5 5 5 5} # In the following tests we need to bypass the bytecode compiler by # substituting the command from a variable. This ensures that command # procedure is invoked directly. test for-6.1 {Tcl_ForObjCmd: number of args} { set z for catch {$z} msg set msg } {wrong # args: should be "for start test next body"} test for-6.2 {Tcl_ForObjCmd: number of args} { set z for catch {$z {set i 0}} msg set msg } {wrong # args: should be "for start test next body"} test for-6.3 {Tcl_ForObjCmd: number of args} { set z for catch {$z {set i 0} {$i < 5}} msg set msg } {wrong # args: should be "for start test next body"} test for-6.4 {Tcl_ForObjCmd: number of args} { set z for catch {$z {set i 0} {$i < 5} {incr i}} msg set msg } {wrong # args: should be "for start test next body"} test for-6.5 {Tcl_ForObjCmd: number of args} { set z for catch {$z {set i 0} {$i < 5} {incr i} {body} extra} msg set msg } {wrong # args: should be "for start test next body"} test for-6.6 {Tcl_ForObjCmd: error in initial command} { set z for list [catch {$z {set} {$i < 5} {incr i} {body}} msg] $msg } {1 {wrong # args: should be "set varName ?newValue?"}} test for-6.8 {Tcl_ForObjCmd: test expression is enclosed in quotes} { set z for set i 0 $z {set i 6} "$i > 5" {incr i} {set y $i} set i } 6 test for-6.10 {Tcl_ForObjCmd: simple command body} { set z for set a {} $z {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 break set a [concat $a $i] } set a } {1 2 3} test for-6.11 {Tcl_ForObjCmd: command body in quotes} { set z for set a {} $z {set i 1} {$i<6} {set i [expr $i+1]} "append a x" set a } {xxxxx} test for-6.12 {Tcl_ForObjCmd: computed command body} { set z for catch {unset x1} catch {unset bb} catch {unset x2} set x1 {append a x1; } set bb {break} set x2 {; append a x2} set a {} $z {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2 set a } {x1} test for-6.14 {Tcl_ForObjCmd: long command body} { set z for set a {} $z {set i 1} {$i<6} {set i [expr $i+1]} { if $i==4 break if $i>5 continue if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } if {$i>6 && $tcl_platform(machine) eq "xxx"} { catch {set a $a} msg catch {incr i 5} msg catch {incr i -5} msg } set a [concat $a $i] } set a } {1 2 3} test for-6.15 {Tcl_ForObjCmd: for command result} { set z for set a [$z {set i 0} {$i < 5} {incr i} {}] set a } {} test for-6.16 {Tcl_ForObjCmd: for command result} { set z for set a [$z {set i 0} {$i < 5} {incr i} {if $i==3 break}] set a } {} ################################################################################ # INFO ################################################################################ test info-1.1 {info body option} { proc t1 {} {body of t1} info body t1 } {body of t1} test info-1.2 {info body option} { list [catch {info body set} msg] $msg } {1 {command "set" is not a procedure}} test info-1.3 {info body option} { list [catch {info args set 1} msg] $msg } {1 {wrong # args: should be "info args procname"}} test info-1.5 {info body option, returning bytecompiled bodies} { catch {unset args} proc foo {args} { foreach v $args { upvar $v var return "variable $v existence: [info exists var]" } } foo a list [catch [info body foo] msg] $msg } {1 {can't read "args": no such variable}} test info-1.6 {info body option, returning list bodies} { proc foo args [list subst bar] list [string length [info body foo]] \ [foo; string length [info body foo]] } {9 9} test info-2.1 {info commands option} { proc t1 {} {} proc t2 {} {} set x " [info commands] " list [string match {* t1 *} $x] [string match {* t2 *} $x] \ [string match {* set *} $x] [string match {* list *} $x] } {1 1 1 1} test info-2.2 {info commands option} { proc t1 {} {} rename t1 {} set x [info commands] string match {* t1 *} $x } 0 test info-2.3 {info commands option} { proc _test1_ {} {} proc _test2_ {} {} info commands _test1_ } _test1_ test info-2.4 {info commands option} { proc _test1_ {} {} proc _test2_ {} {} lsort [info commands _test*] } {_test1_ _test2_} catch {rename _test1_ {}} catch {rename _test2_ {}} test info-2.5 {info commands option} { list [catch {info commands a b} msg] $msg } {1 {wrong # args: should be "info commands ?pattern?"}} test info-3.1 {info exists option} { set value foo info exists value } 1 catch {unset _nonexistent_} test info-3.2 {info exists option} { info exists _nonexistent_ } 0 test info-3.3 {info exists option} { proc t1 {x} {return [info exists x]} t1 2 } 1 test info-3.4 {info exists option} { proc t1 {x} { global _nonexistent_ return [info exists _nonexistent_] } t1 2 } 0 test info-3.5 {info exists option} { proc t1 {x} { set y 47 return [info exists y] } t1 2 } 1 test info-3.6 {info exists option} { proc t1 {x} {return [info exists value]} t1 2 } 0 test info-3.7 {info exists option} { catch {unset x} set x(2) 44 list [info exists x] [info exists x(1)] [info exists x(2)] } {1 0 1} catch {unset x} test info-3.8 {info exists option} { list [catch {info exists} msg] $msg } {1 {wrong # args: should be "info exists varName"}} test info-3.9 {info exists option} { list [catch {info exists 1 2} msg] $msg } {1 {wrong # args: should be "info exists varName"}} test info-4.1 {info globals option} { set x 1 set y 2 set value 23 set a " [info globals] " list [string match {* x *} $a] [string match {* y *} $a] \ [string match {* value *} $a] [string match {* _foobar_ *} $a] } {1 1 1 0} test info-4.2 {info globals option} { set _xxx1 1 set _xxx2 2 lsort [info globals _xxx*] } {_xxx1 _xxx2} test info-4.3 {info globals option} { list [catch {info globals 1 2} msg] $msg } {1 {wrong # args: should be "info globals ?pattern?"}} test info-5.1 {info level option} { info level } 0 test info-5.2 {info level option} { proc t1 {a b} { set x [info level] set y [info level 1] list $x $y } t1 146 testString } {1 {t1 146 testString}} test info-5.3 {info level option} { proc t1 {a b} { t2 [expr $a*2] $b } proc t2 {x y} { list [info level] [info level 1] [info level 2] [info level -1] \ [info level 0] } t1 146 {a {b c} {{{c}}}} } {2 {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}} {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}}} test info-5.4 {info level option} { proc t1 {} { set x [info level] set y [info level 1] list $x $y } t1 } {1 t1} test info-5.5 {info level option} { list [catch {info level 1 2} msg] $msg } {1 {wrong # args: should be "info level ?levelNum?"}} test info-5.6 {info level option} { list [catch {info level 123a} msg] $msg } {1 {bad level "123a"}} test info-5.7 {info level option} { list [catch {info level 0} msg] $msg } {1 {bad level "0"}} test info-5.8 {info level option} { proc t1 {} {info level -1} list [catch {t1} msg] $msg } {1 {bad level "-1"}} test info-5.9 {info level option} { proc t1 {x} {info level $x} list [catch {t1 -3} msg] $msg } {1 {bad level "-3"}} test info-6.1 {info locals option} { set a 22 proc t1 {x y} { set b 13 set c testing global a global aa set aa 23 return [info locals] } lsort [t1 23 24] } {b c x y} test info-6.2 {info locals option} { proc t1 {x y} { set xx1 2 set xx2 3 set y 4 return [info locals x*] } lsort [t1 2 3] } {x xx1 xx2} test info-6.3 {info locals option} { list [catch {info locals 1 2} msg] $msg } {1 {wrong # args: should be "info locals ?pattern?"}} test info-6.4 {info locals option} { info locals } {} test info-6.5 {info locals option} { proc t1 {} {return [info locals]} t1 } {} test info-6.6 {info locals vs unset compiled locals} { proc t1 {lst} { foreach $lst $lst {} unset lst return [info locals] } lsort [t1 {a b c c d e f}] } {a b c d e f} test info-6.7 {info locals with temporary variables} { proc t1 {} { foreach a {b c} {} info locals } t1 } {a} test info-7.1 {info vars option} { set a 1 set b 2 proc t1 {x y} { global a b set c 33 return [info vars] } lsort [t1 18 19] } {a b c x y} test info-7.2 {info vars option} { set xxx1 1 set xxx2 2 proc t1 {xxa y} { global xxx1 xxx2 set c 33 return [info vars x*] } lsort [t1 18 19] } {xxa xxx1 xxx2} test info-7.3 {info vars option} { lsort [info vars] } [lsort [info globals]] test info-7.4 {info vars option} { list [catch {info vars a b} msg] $msg } {1 {wrong # args: should be "info vars ?pattern?"}} test info-7.5 {info vars with temporary variables} { proc t1 {} { foreach a {b c} {} info vars } t1 } {a} ################################################################################ # RANGE ################################################################################ test range-1.1 {basic range tests} { range 0 10 } {0 1 2 3 4 5 6 7 8 9} test range-1.2 {basic range tests} { range 10 0 -1 } {10 9 8 7 6 5 4 3 2 1} test range-1.3 {basic range tests} { range 1 10 11 } {1} test range-1.4 {basic range tests} { range 1 10 11 } {1} test range-1.5 {basic range tests} { range 10 10 } {} test range-1.6 {basic range tests} { range 10 10 2 } {} test range-1.7 {basic range test} { range 5 } {0 1 2 3 4} test range-1.8 {basic range test} { range -10 -20 -2 } {-10 -12 -14 -16 -18} test range-1.9 {basic range test} { range -20 -10 3 } {-20 -17 -14 -11} test range-2.0 {foreach range test} { set k 0 foreach {x y} [range 100] { incr k [expr {$x*$y}] } set k } {164150} test range-2.1 {foreach range test without obj reuse} { set k 0 set trash {} foreach {x y} [range 100] { incr k [expr {$x*$y}] lappend trash $x $y } set trash {} set k } {164150} test range-2.2 {range element shimmering test} { set k {} foreach x [range 0 10] { append k [llength $x] } set k } {1111111111} test range-3.0 {llength range test} { llength [range 5000] } {5000} test range-3.1 {llength range test} { llength [range 5000 5000] } {0} test range-4.0 {lindex range test} { lindex [range 1000] 500 } {500} test range-4.1 {lindex range test} { lindex [range 1000] end-2 } {997} test range-5.0 {lindex llength range test} { set k 0 set trash {} set r [range 100] for {set i 0} {$i < [llength $r]} {incr i 2} { incr k [expr {[lindex $r $i]*[lindex $r [expr {$i+1}]]}] } set trash {} set k } {164150} ################################################################################ # SCOPE ################################################################################ if 0 { test scope-1.0 {Non existing var} { catch {unset x} scope x { set x 10 set y [+ $x 1] } list [info exists x] $y } {0 11} test scope-1.1 {Existing var restore} { set x 100 scope x { for {set x 0} {$x < 10} {incr x} {} } set x } {100} test scope-1.2 {Mix of 1.0 and 1.1 tests} { catch {unset x} set y 10 scope {x y} { set y 100 set x 200 } list [info exists x] $y } {0 10} test scope-1.3 {Array element} { set x "a 1 b 2" scope x(a) { set x(a) Hello! } set x(a) } {1} test scope-1.4 {Non existing array element} { catch {unset x} scope x(a) { set x(a) Hello! } info exists x(a) } {0} test scope-1.5 {Info exists} { set x foo scope x { info exists x } } {0} catch {unset x} catch {unset y} } ################################################################################ # RAND ################################################################################ test rand-1.0 {Only one output is valid} { list [rand 100 100] [rand 101 101] } {100 101} test rand-1.1 {invalid arguments} { catch {rand 100 50} err set err } {Invalid arguments (max < min)} test rand-1.2 {Check limits} { set sum 0 for {set i 0} {$i < 100} {incr i} { incr sum [expr {([rand $i] >= 0)+([rand $i] < 100)}] } set sum } {200} catch {unset sum; unset err; unset i} ################################################################################ # JIM REGRESSION TESTS ################################################################################ test regression-1.0 {Rename against procedures with static vars} { proc foobar {x} {{y 10}} { incr y $x } foobar 30 foobar 20 rename foobar barfoo list [barfoo 1] [barfoo 2] [barfoo 3] } {61 63 66} catch {rename barfoo {}} test regression-1.1 {lrange bug with negative indexes of type int} { lrange {a b c} 0 [- 0 1] } {} test regression-1.2 {open/close from non-global namespace} { proc a::b {} { set f [open $::argv0] $f close return $f } set f [a::b] rename a::b "" expr {$f in [info channels]} } {0} testreport openocd-0.9.0/jimtcl/tests/uplevel.test0000644000175000017500000000573012315602575015104 00000000000000# Commands covered: uplevel # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: uplevel.test,v 1.6 2000/04/10 17:19:05 ericm Exp $ source [file dirname [info script]]/testing.tcl proc a {x y} { newset z [expr $x+$y] return $z } proc newset {name value} { uplevel set $name $value uplevel 1 {uplevel 1 {set xyz 22}} } proc b {x y} { uplevel #0 set $x $y } test uplevel-1.1 {simple operation} { set xyz 0 a 22 33 } 55 test uplevel-1.2 {command is another uplevel command} { set xyz 0 a 22 33 set xyz } 22 proc a1 {} { b1 global a a1 set a $x set a1 $y } proc b1 {} { c1 global b b1 set b $x set b1 $y } proc c1 {} { uplevel 1 set x 111 uplevel #2 set y 222 uplevel 2 set x 333 uplevel #1 set y 444 uplevel 3 set x 555 uplevel #0 set y 666 } a1 test uplevel-2.1 {relative and absolute uplevel} {set a} 333 test uplevel-2.2 {relative and absolute uplevel} {set a1} 444 test uplevel-2.3 {relative and absolute uplevel} {set b} 111 test uplevel-2.4 {relative and absolute uplevel} {set b1} 222 test uplevel-2.5 {relative and absolute uplevel} {set x} 555 test uplevel-2.6 {relative and absolute uplevel} {set y} 666 test uplevel-3.1 {uplevel to same level} { set x 33 uplevel #0 set x 44 set x } 44 test uplevel-3.2 {uplevel to same level} { set x 33 uplevel 0 set x } 33 test uplevel-3.3 {uplevel to same level} { set y xxx proc a1 {} {set y 55; uplevel 0 set y 66; return $y} a1 } 66 test uplevel-3.4 {uplevel to same level} { set y zzz proc a1 {} {set y 55; uplevel #1 set y} a1 } 55 test uplevel-4.1 {error check: non-existent level} { list [catch c1 msg] $msg } {1 {bad level "#2"}} test uplevel-4.2 {error check: non-existent level} { proc c2 {} {uplevel 3 {set a b}} list [catch c2 msg] $msg } {1 {bad level "3"}} test uplevel-4.3 {error check: not enough args} { list [catch uplevel msg] $msg } {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}} test uplevel-4.4 {error check: not enough args} { proc upBug {} {uplevel 1} list [catch upBug msg] $msg } {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}} proc a2 {} { uplevel a3 } proc a3 {} { global x y set x [info level] set y [info level 1] } a2 test uplevel-5.1 {info level} {set x} 1 test uplevel-5.2 {info level} {set y} a3 test uplevel-6.1 {uplevel #0} { b g1 g1val set ::g1 } g1val test uplevel-6.2 {uplevel #bad} { catch {uplevel #bad set x 1} } 1 testreport openocd-0.9.0/jimtcl/tests/lsearch.test0000644000175000017500000001165412315602575015053 00000000000000# Commands covered: lsearch # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: lsearch.test,v 1.5 2000/04/10 17:19:01 ericm Exp $ source [file dirname [info script]]/testing.tcl catch {package require regexp} testConstraint regexp [expr {[info commands regexp] ne {}}] set x {abcd bbcd 123 234 345} test lsearch-1.1 {lsearch command} { lsearch $x 123 } 2 test lsearch-1.2 {lsearch command} { lsearch $x 3456 } -1 test lsearch-1.3 {lsearch command} { lsearch -glob $x *5 } 4 test lsearch-1.4 {lsearch command} { lsearch -glob $x *bc* } 0 test lsearch-2.1 {search modes} { lsearch -exact {xyz bbcc *bc*} *bc* } 2 test lsearch-2.2 {search modes} { lsearch -exact {b.x ^bc xy bcx} ^bc } 1 test lsearch-2.3 {search modes} { lsearch -exact {foo bar cat} ba } -1 test lsearch-2.4 {search modes} { lsearch -exact {foo bar cat} bart } -1 test lsearch-2.5 {search modes} { lsearch -exact {foo bar cat} bar } 1 test lsearch-2.6 {search modes} regexp { list [catch {lsearch -regexp {xyz bbcc *bc*} *bc*} msg] } {1} test lsearch-2.7 {search modes} regexp { lsearch -regexp {b.x ^bc xy bcx} ^bc } 3 test lsearch-2.8 {search modes} { lsearch -glob {xyz bbcc *bc*} *bc* } 1 test lsearch-2.9 {search modes} { lsearch -glob {b.x ^bc xy bcx} ^bc } 1 test lsearch-2.10 {search modes} { list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg] } {1} test lsearch-2.7 {search modes, -nocase} regexp { lsearch -nocase -regexp {b.x ^bc xy bcx} ^BC } 3 test lsearch-2.8 {search modes, -nocase} { lsearch -nocase -exact {b.x ^bc xy bcx} ^BC } 1 test lsearch-2.9 {search modes, -nocase} { lsearch -nocase -glob {b.x ^bc xy bcx} B* } 0 test lsearch-3.1 {lsearch errors} { list [catch lsearch msg] } {1} test lsearch-3.2 {lsearch errors} { list [catch {lsearch a} msg] } {1} test lsearch-3.3 {lsearch errors} { list [catch {lsearch a b c} msg] } {1} test lsearch-3.4 {lsearch errors} { list [catch {lsearch a b c d} msg] } {1} test lsearch-4.1 {binary data} { lsearch -exact [list foo one\000two bar] bar } 2 test lsearch-4.2 {binary data} { set x one append x \x00 append x two lsearch -exact [list foo one\000two bar] $x } 1 test lsearch-5.1 {lsearch -all} { lsearch -glob -all {a1 a2 b1 b2 a3 b3} a* } {0 1 4} test lsearch-5.2 {lsearch -all no match} { lsearch -glob -all {a1 a2 b1 b2 a3 b3} B* } {} test lsearch-5.3 {lsearch -all -nocase} { lsearch -glob -all -nocase {a1 a2 b1 b2 a3 b3} B* } {2 3 5} test lsearch-5.4 {lsearch -all -inline} { lsearch -glob -all -inline -nocase {a1 a2 b1 b2 a3 b3} A* } {a1 a2 a3} test lsearch-5.5 {lsearch -inline} { lsearch -glob -inline {a1 a2 b1 b2 a3 b3} b* } {b1} test lsearch-5.6 {lsearch -not -all} { lsearch -not -glob -all {a1 a2 b1 b2 a3 b3} a* } {2 3 5} test lsearch-5.7 {lsearch -not -all no match} { lsearch -not -glob -all {a1 a2 b1 b2 a3 b3} B* } {0 1 2 3 4 5} test lsearch-5.8 {lsearch -not -all -nocase} { lsearch -not -glob -all -nocase {a1 a2 b1 b2 a3 b3} B* } {0 1 4} test lsearch-5.9 {lsearch -not -all -inline} { lsearch -not -glob -all -inline -nocase {a1 a2 b1 b2 a3 b3} A* } {b1 b2 b3} test lsearch-5.10 {lsearch -not -inline} { lsearch -not -glob -inline {a1 a2 b1 b2 a3 b3} b* } {a1} test lsearch-5.11 {lsearch -inline, no match} { lsearch -glob -inline {a1 a2 b1 b2 a3 b3} C* } {} test lsearch-6.1 {lsearch -bool, found} jim { lsearch -bool {a1 a2 b1 b2 a3 b3} b1 } {1} test lsearch-6.2 {lsearch -bool, not found} jim { lsearch -bool {a1 a2 b1 b2 a3 b3} c1 } {0} test lsearch-6.3 {lsearch -not -bool, found} jim { lsearch -not -bool {a1 a2 b1 b2 a3 b3} b1 } {0} test lsearch-6.4 {lsearch -not -bool, not found} jim { lsearch -not -bool {a1 a2 b1 b2 a3 b3} c1 } {1} test lsearch-6.5 {lsearch -bool -all} jim { lsearch -bool -glob -all {a1 a2 b1 b2 a3 b3} a* } {1 1 0 0 1 0} test lsearch-6.6 {lsearch -bool -all no match} jim { lsearch -bool -glob -all {a1 a2 b1 b2 a3 b3} B* } {0 0 0 0 0 0} test lsearch-6.7 {lsearch -bool -all -nocase} jim { lsearch -bool -glob -all -nocase {a1 a2 b1 b2 a3 b3} B* } {0 0 1 1 0 1} test lsearch-6.8 {lsearch -not -bool -all} jim { lsearch -not -bool -glob -all {a1 a2 b1 b2 a3 b3} a* } {0 0 1 1 0 1} test lsearch-6.9 {lsearch -not -bool -all no match} jim { lsearch -not -bool -glob -all {a1 a2 b1 b2 a3 b3} B* } {1 1 1 1 1 1} test lsearch-6.10 {lsearch -not -bool -all -nocase} jim { lsearch -not -bool -glob -all -nocase {a1 a2 b1 b2 a3 b3} B* } {1 1 0 0 1 0} testreport openocd-0.9.0/jimtcl/tests/glob.test0000644000175000017500000000605712516456444014363 00000000000000# Test the glob command source [file dirname [info script]]/testing.tcl needs constraint jim needs cmd glob # Fake the bare minimum that glob.tcl needs: # [readdir], [file isdir] and [file exists] local proc file {cmd args} { if {$cmd in {isdir exists}} { lassign [fslookup [lindex $args 0]] type contents if {$cmd eq "isdir" && $type eq "dir"} { return 1 } elseif {$type ne "none"} { return 1 } return 0 } tailcall upcall file $cmd {*}$args } local proc readdir {{-nocomplain {}} dir} { lassign [fslookup $dir] type contents if {$type ne "dir"} { if {${-nocomplain} eq ""} { return {} } return -code error "No such file or directory" } dict keys $contents } local proc fslookup {path} { set type dir set dict $::FAKEFS foreach p [split $path /] { if {$p in {. {}}} { continue } if {![dict exists $dict $p] || $type ne "dir"} { return none } lassign [dict get $dict $p] type dict } list $type $dict } # Creates the representation of a filesystem in a dictionary - for testing local proc makefakefs {fs} { set fakefs {} foreach {type name contents} $fs { switch -glob -- $type { f* { set fakefs($name) [list file $contents] } d* { set fakefs($name) [list dir [makefakefs $contents]] } default { error "Unknown fs type: $type" } } } return $fakefs } # Create a fake filesystem for testing the glob command set ::FAKEFS [makefakefs { file abc {This is the contents of abc} dir def { file ghi {This file is inside def} dir jkl } dir tmp { file "open{brace" {} file "close}brace" {} file "open\[bracket" {} file "close\]bracket" {} } }] test glob-1.1 {Simple} { lsort [glob *] } {abc def tmp} test glob-1.2 {Simple} { lsort [glob a*] } {abc} test glob-1.3 {Simple} -returnCodes error -body { lsort [glob x*] } -result {no files matched glob pattern "x*"} test glob-1.4 {Simple} -returnCodes error -body { lsort [glob] } -result {wrong # args: should be "glob ?options? pattern ?pattern ...?"} test glob-1.5 {Simple} -returnCodes ok -body { lsort [glob -nocomplain x*] } -result {} test glob-2.1 {Braces} -returnCodes ok -body { lsort [glob "{a,d}*"] } -result {abc def} test glob-2.2 {Files containing braces and brackets} -returnCodes ok -body { lsort [glob tmp/*] } -result {tmp/close\]bracket tmp/close\}brace {tmp/open[bracket} tmp/open\{brace} test glob-2.3 {Glob match files open bracket} -returnCodes ok -body { lsort [glob {tmp/*\[*}] } -result [list tmp/open\[bracket] test glob-2.4 {Glob match files close bracket} -returnCodes ok -body { lsort [glob {tmp/*\]*}] } -result [list tmp/close\]bracket] test glob-2.5 {Glob match files containing braced brackets} -returnCodes ok -body { lsort [glob {tmp/*{\[,]}*}] } -result [list tmp/close\]bracket tmp/open\[bracket] test glob-3.1 {Directory option} -returnCodes ok -body { lsort [glob -dir tmp -tails *] } -result [list close\]bracket close\}brace open\[bracket open\{brace] test glob-3.2 {Directory option} -returnCodes ok -body { lsort [glob -dir tmp -tails *close*] } -result [list close\]bracket close\}brace] testreport openocd-0.9.0/jimtcl/tests/dict.test0000644000175000017500000001263712516456444014364 00000000000000source [file dirname [info script]]/testing.tcl test dict-1.1 "Basic dict" { set d [dict create] dict set d fruit apple dict set d car holden #puts "d=$d" #puts "d(fruit)=$d(fruit)" dict get $d car } {holden} catch {unset d} test dict-2.1 "Dict via reference" references { set d [dict create] dict set d fruit apple dict set d car holden # now create a dictionary reference set dref [ref $d dict] dict get [getref $dref] car } {holden} test dict-2.2 "Modify dict via reference" references { # Get the value out of the refernence set d [getref $dref] # Modify it dict set d car toyota # And put the new value back setref $dref $d # Finally check it dict get [getref $dref] car } {toyota} test dict-2.3 "Modify dict via reference - one line" references { # Get the value out of the refernence set d [getref $dref] setref $dref [dict set d car toyota] # Finally check it dict get [getref $dref] car } {toyota} # Sort a dictionary in key order - return a list proc dictsort {dict} { set result {} foreach k [lsort [dict keys $dict]] { lappend result $k [dict get $dict $k] } return $result } set a [dict create a 1 b 2] set b [dict create b 3 c 4] test dict-3.1 {Merge} { dict merge } {} test dict-3.2 {Merge} { dictsort [dict merge $a] } {a 1 b 2} test dict-3.3 {Merge} { dictsort [dict merge $b] } {b 3 c 4} test dict-3.4 {Merge} { dictsort [dict merge $a $b] } {a 1 b 3 c 4} test dict-3.5 {Merge} { dictsort [dict merge $b $a] } {a 1 b 2 c 4} test dict-3.6 {Merge} { dictsort [dict merge $b $a {a 5}] } {a 5 b 2 c 4} test dict-3.7 {Merge} { dictsort [dict merge {a 5} $b $a] } {a 1 b 2 c 4} test dict-3.8 {Merge} { catch {dict merge 1 $b $a} } 1 test dict-3.9 {Merge} { catch {dict merge $b 1 $a} } 1 test dict-3.10 {Merge} { catch {dict merge $b $a 1} } 1 test dict-3.11 {Merge} { catch {dict merge 1} } 1 test dict-4.1 {Dict size} { dict size {a b} } 1 test dict-4.2 {Dict size} { dict size {a b c d} } 2 test dict-5.1 {Dict with} { proc a {} { set x [dict create a b c d] dict with x { set a B unset c } set x } dictsort [a] } {a B} test dict-5.2 {Dict with} { proc a {} { set x [dict create a b c d] dict with x { set a B unset c } set x } dictsort [a] } {a B} test dict-22.1 {dict with command} { list [catch {dict with} msg] $msg } {1 {wrong # args: should be "dict with dictVar ?key ...? script"}} test dict-22.2 {dict with command} { list [catch {dict with v} msg] $msg } {1 {wrong # args: should be "dict with dictVar ?key ...? script"}} test dict-22.3 {dict with command} { unset -nocomplain v list [catch {dict with v {error "in body"}} msg] $msg } {1 {can't read "v": no such variable}} test dict-22.4 {dict with command} { set a {b c d e} unset -nocomplain b d set result [list [info exist b] [info exist d]] dict with a { lappend result [info exist b] [info exist d] $b $d } set result } {0 0 1 1 c e} test dict-22.5 {dict with command} { set a {b c d e} dict with a { lassign "$b $d" d b } dictsort $a } {b e d c} test dict-22.6 {dict with command} { set a {b c d e} dict with a { unset b # This *won't* go into the dict... set f g } set a } {d e} test dict-22.7 {dict with command} { set a {b c d e} dict with a { dict unset a b } dictsort $a } {b c d e} test dict-22.8 {dict with command} { set a [dict create b c] dict with a { set b $a } set a } {b {b c}} test dict-22.9 {dict with command} { set a {b {c d}} dict with a b { set c $c$c } set a } {b {c dd}} test dict-22.10 {dict with command: result handling tricky case} { set a {b {c d}} foreach i {0 1} { if {$i} break dict with a b { set a {} # We're checking to see if we lose this break break } } list $i $a } {0 {}} test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} { set foo {t {t {t {inner 1}}}} dict with foo { dict with t { dict with t { dict with t { incr inner } } } } string range [append foo OK] end-1 end } OK test dict-23.1 {dict unset missing last level} { set a {b c d e} dict unset a xyz dict size $a } 2 test dict-23.2 {dict unset command} -returnCodes error -body { set dictVar a dict unset dictVar a } -cleanup { unset dictVar } -result {missing value to go with key} test dict-23.3 {dict unset command} -setup { unset -nocomplain dictVar } -body { list [info exists dictVar] [dict unset dictVar a] [info exists dictVar] } -cleanup { unset dictVar } -result {0 {} 1} test dict-23.4 {dict unset command: write failure} -setup { unset -nocomplain dictVar } -body { set dictVar 1 dict unset dictVar a } -returnCodes error -cleanup { unset dictVar } -result {missing value to go with key} test dict-24.1 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3} test dict-24.2 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6 test dict-24.3 {dict/list shimmering with embedded nulls} { # Must be a string containing embedded nulls that would be double quoted in string form set binary_value 1\000\\ set dictVar [dict create value $binary_value] lassign $dictVar k v string length $v } {3} test dict-24.4 {dict/list shimmering with lappend and foreach} { set a [list 1 2 3 4] foreach b $a { # convert to dict dict size $a # append to list lappend a x y } llength $a } 12 testreport openocd-0.9.0/jimtcl/tests/proc-new.test0000644000175000017500000000523512315602575015162 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim needs cmd array proc aproc {} { list } proc bproc {b} { list b $b } proc cproc {b c} { list b $b c $c } proc dproc {b c {d dd}} { list b $b c $c d $d } proc eproc {b c {d dd} e} { list b $b c $c d $d e $e } proc fproc {b c {d dd} args} { list b $b c $c d $d args $args } proc gproc {b c {d dd} args e} { list b $b c $c d $d args $args e $e } proc hproc {{a aa} args} { list a $a args $args } proc iproc {{a aa} b {c cc}} { list a $a b $b c $c } proc jproc {args {a aa} b {c cc} d} { list a $a b $b c $c d $d args $args } set n 1 foreach {proc params result} { aproc {} {} bproc B {b B} cproc {B C} {b B c C} dproc {B C} {b B c C d dd} dproc {B C D} {b B c C d D} eproc {B C D E} {b B c C d D e E} eproc {B C E} {b B c C d dd e E} fproc {B C} {b B c C d dd args {}} fproc {B C D} {b B c C d D args {}} fproc {B C D E} {b B c C d D args E} fproc {B C D E F} {b B c C d D args {E F}} gproc {B C E} {b B c C d dd args {} e E} gproc {B C D E} {b B c C d D args {} e E} gproc {B C D X E} {b B c C d D args X e E} gproc {B C D X Y Z E} {b B c C d D args {X Y Z} e E} hproc {} {a aa args {}} hproc {A} {a A args {}} hproc {A X Y Z} {a A args {X Y Z}} iproc {B} {a aa b B c cc} iproc {A B} {a A b B c cc} iproc {A B C} {a A b B c C} jproc {B D} {a aa b B c cc d D args {}} jproc {A B D} {a A b B c cc d D args {}} jproc {A B C D} {a A b B c C d D args {}} jproc {E F A B C D} {a A b B c C d D args {E F}} } { test proc-1.$n "Proc args combos" [list $proc {*}$params] $result incr n } proc onearg_search {{nocase ""} value list} { lsearch {*}$nocase $list $value } proc multiarg_search {args value list} { lsearch {*}$args $list $value } test proc-2.1 "Real test of optional switches" { onearg_search c {A a B b C c D d} } 5 test proc-2.2 "Real test of optional switches" { onearg_search -nocase c {A a B b C c D d} } 4 test proc-2.3 "Real test of optional switches" { multiarg_search -glob c* {A a B b C c D d} } 5 test proc-2.4 "Real test of optional switches" { multiarg_search -nocase -glob c* {A a B b C c D d} } 4 test proc-3.1 "Rename optional args" { proc a {b {args vars}} { } catch {a} msg set msg } {wrong # args: should be "a b ?vars ...?"} test proc-3.2 "Rename optional args" { proc a {b {args vars} c} { } catch {a} msg set msg } {wrong # args: should be "a b ?vars ...? c"} test proc-3.2 "Rename optional args" { proc a {b {args vars}} { return $vars } a B C D } {C D} test proc-3.3 "dict sugar arg" { proc a {b(c)} { return $b} a 4 } {c 4} test proc-3.4 "invalid upref in rightargs" { proc a {{x 2} &b} { return $b} unset -nocomplain B catch {a B} } 1 testreport openocd-0.9.0/jimtcl/tests/regexp.test0000644000175000017500000005513612315602575014727 00000000000000# Commands covered: regexp, regsub # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1998 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: regexp.test,v 1.30.2.1 2008/08/21 23:19:06 hobbs Exp $ source [file dirname [info script]]/testing.tcl needs cmd regexp catch {unset foo} test regexp-1.1 {basic regexp operation} { regexp ab*c abbbc } 1 test regexp-1.2 {basic regexp operation} { regexp ab*c ac } 1 test regexp-1.3 {basic regexp operation} { regexp ab*c ab } 0 test regexp-1.4 {basic regexp operation} { regexp -- -gorp abc-gorpxxx } 1 test regexp-1.5 {basic regexp operation} { regexp {^([^ ]*)[ ]*([^ ]*)} "" a } 1 #test regexp-1.6 {basic regexp operation} { # list [catch {regexp {} abc} msg] $msg #} {0 1} #test regexp-1.7 {regexp utf compliance} { # # if not UTF-8 aware, result is "0 1" # set foo "\u4e4eb q" # regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar # list [string compare $foo $bar] [regexp 4 $bar] #} {0 0} test regexp-2.1 {getting substrings back from regexp} { set foo {} list [regexp ab*c abbbbc foo] $foo } {1 abbbbc} test regexp-2.2 {getting substrings back from regexp} { set foo {} set f2 {} list [regexp a(b*)c abbbbc foo f2] $foo $f2 } {1 abbbbc bbbb} test regexp-2.3 {getting substrings back from regexp} { set foo {} set f2 {} list [regexp a(b*)(c) abbbbc foo f2] $foo $f2 } {1 abbbbc bbbb} test regexp-2.4 {getting substrings back from regexp} { set foo {} set f2 {} set f3 {} list [regexp a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3 } {1 abbbbc bbbb c} test regexp-2.5 {getting substrings back from regexp} { set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {}; set f6 {}; set f7 {}; set f8 {}; set f9 {}; set fa {}; set fb {}; list [regexp (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*)(a*)(b*) \ 12223345556789999aabbb \ foo f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb] $foo $f1 $f2 $f3 $f4 $f5 \ $f6 $f7 $f8 $f9 $fa $fb } {1 12223345556789999aabbb 1 222 33 4 555 6 7 8 9999 aa bbb} test regexp-2.6 {getting substrings back from regexp} { set foo 2; set f2 2; set f3 2; set f4 2 list [regexp (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4 } {1 a a {} {}} test regexp-2.7 {getting substrings back from regexp} { set foo 1; set f2 1; set f3 1; set f4 1 list [regexp (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4 } {1 ac a {} c} test regexp-2.8 {getting substrings back from regexp} { set match {} list [regexp {^a*b} aaaab match] $match } {1 aaaab} test regexp-2.9 {getting substrings back from regexp} { set foo {} set f2 {} list [regexp f\352te(b*)c f\352tebbbbc foo f2] $foo $f2 } [list 1 f\352tebbbbc bbbb] test regexp-2.10 {getting substrings back from regexp} { set foo {} set f2 {} list [regexp f\352te(b*)c eff\352tebbbbc foo f2] $foo $f2 } [list 1 f\352tebbbbc bbbb] test regexp-3.1 {-indices option to regexp} { set foo {} list [regexp -indices ab*c abbbbc foo] $foo } {1 {0 5}} test regexp-3.2 {-indices option to regexp} { set foo {} set f2 {} list [regexp -indices a(b*)c abbbbc foo f2] $foo $f2 } {1 {0 5} {1 4}} test regexp-3.3 {-indices option to regexp} { set foo {} set f2 {} list [regexp -indices a(b*)(c) abbbbc foo f2] $foo $f2 } {1 {0 5} {1 4}} test regexp-3.4 {-indices option to regexp} { set foo {} set f2 {} set f3 {} list [regexp -indices a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3 } {1 {0 5} {1 4} {5 5}} test regexp-3.5 {-indices option to regexp} { set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {}; set f6 {}; set f7 {}; set f8 {}; set f9 {} list [regexp -indices (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*) \ 12223345556789999 \ foo f1 f2 f3 f4 f5 f6 f7 f8 f9] $foo $f1 $f2 $f3 $f4 $f5 \ $f6 $f7 $f8 $f9 } {1 {0 16} {0 0} {1 3} {4 5} {6 6} {7 9} {10 10} {11 11} {12 12} {13 16}} test regexp-3.6 {getting substrings back from regexp} { set foo 2; set f2 2; set f3 2; set f4 2 list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4 } {1 {1 1} {1 1} {-1 -1} {-1 -1}} test regexp-3.7 {getting substrings back from regexp} { set foo 1; set f2 1; set f3 1; set f4 1 list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4 } {1 {1 2} {1 1} {-1 -1} {2 2}} test regexp-4.1 {-nocase option to regexp} { regexp -nocase foo abcFOo } 1 test regexp-4.2 {-nocase option to regexp} { set f1 22 set f2 33 set f3 44 list [regexp -nocase {a(b*)([xy]*)z} aBbbxYXxxZ22 f1 f2 f3] $f1 $f2 $f3 } {1 aBbbxYXxxZ Bbb xYXxx} test regexp-4.3 {-nocase option to regexp} { regexp -nocase FOo abcFOo } 1 set x abcdefghijklmnopqrstuvwxyz1234567890 set x $x$x$x$x$x$x$x$x$x$x$x$x test regexp-4.4 {case conversion in regexp} { list [regexp -nocase $x $x foo] $foo } "1 $x" catch {unset x} test regexp-5.1 {exercise cache of compiled expressions} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*a bbba } 1 test regexp-5.2 {exercise cache of compiled expressions} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*b xxxb } 1 test regexp-5.3 {exercise cache of compiled expressions} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*c yyyc } 1 test regexp-5.4 {exercise cache of compiled expressions} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*d 1d } 1 test regexp-5.5 {exercise cache of compiled expressions} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f regexp .*e xe } 1 test regexp-6.1 {regexp errors} jim { list [catch {regexp a} msg] $msg } {1 {wrong # args: should be "regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"}} test regexp-6.2 {regexp errors} jim { list [catch {regexp -nocase a} msg] $msg } {1 {wrong # args: should be "regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"}} test regexp-6.3 {regexp errors} jim { list [catch {regexp -gorp a} msg] $msg } {1 {bad switch "-gorp": must be --, -all, -indices, -inline, -line, -nocase, or -start}} test regexp-6.4 {regexp errors} { catch {regexp a( b} msg } 1 #test regexp-6.5 {regexp errors} { # list [catch {regexp a) b} msg] [string match *parentheses* $msg] #} {1 1} test regexp-6.6 {regexp errors} { list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg } {0 1} test regexp-6.7 {regexp errors} { list [catch {regexp (x)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) xyzzy} msg] $msg } {0 0} test regexp-6.8 {regexp errors} jim { catch {unset f1} set f1 44 list [catch {regexp abc abc f1(f2)} msg] $msg } {1 {can't set "f1(f2)": variable isn't array}} test regexp-6.9 {regexp errors, -start bad int check} { list [catch {regexp -start bogus {^$} {}} msg] $msg } {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}} test regexp-7.1 {basic regsub operation} { list [regsub aa+ xaxaaaxaa 111&222 foo] $foo } {1 xax111aaa222xaa} test regexp-7.2 {basic regsub operation} { list [regsub aa+ aaaxaa &111 foo] $foo } {1 aaa111xaa} test regexp-7.3 {basic regsub operation} { list [regsub aa+ xaxaaa 111& foo] $foo } {1 xax111aaa} test regexp-7.4 {basic regsub operation} { list [regsub aa+ aaa 11&2&333 foo] $foo } {1 11aaa2aaa333} test regexp-7.5 {basic regsub operation} { list [regsub aa+ xaxaaaxaa &2&333 foo] $foo } {1 xaxaaa2aaa333xaa} test regexp-7.6 {basic regsub operation} { list [regsub aa+ xaxaaaxaa 1&22& foo] $foo } {1 xax1aaa22aaaxaa} test regexp-7.7 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {1\122\1} foo] $foo } {1 xax1aa22aaxaa} test regexp-7.8 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {1\\\122\1} foo] $foo } "1 {xax1\\aa22aaxaa}" test regexp-7.9 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {1\\122\1} foo] $foo } "1 {xax1\\122aaxaa}" test regexp-7.10 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {1\\&\1} foo] $foo } "1 {xax1\\aaaaaxaa}" test regexp-7.11 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {1\&\1} foo] $foo } {1 xax1&aaxaa} test regexp-7.12 {basic regsub operation} { list [regsub a(a+) xaxaaaxaa {\1\1\1\1&&} foo] $foo } {1 xaxaaaaaaaaaaaaaaxaa} test regexp-7.13 {basic regsub operation} { set foo xxx list [regsub abc xyz 111 foo] $foo } {0 xyz} test regexp-7.14 {basic regsub operation} { set foo xxx list [regsub ^ xyz "111 " foo] $foo } {1 {111 xyz}} test regexp-7.15 {basic regsub operation} { set foo xxx list [regsub -- -foo abc-foodef "111 " foo] $foo } {1 {abc111 def}} test regexp-7.16 {basic regsub operation} { set foo xxx list [regsub x "" y foo] $foo } {0 {}} #test regexp-7.17 {regsub utf compliance} { # # if not UTF-8 aware, result is "0 1" # set foo "xyz555ijka\u4e4ebpqr" # regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar # list [string compare $foo $bar] [regexp 4 $bar] #} {0 0} test regexp-8.1 {case conversion in regsub} { list [regsub -nocase a(a+) xaAAaAAay & foo] $foo } {1 xaAAaAAay} test regexp-8.2 {case conversion in regsub} { list [regsub -nocase a(a+) xaAAaAAay & foo] $foo } {1 xaAAaAAay} test regexp-8.3 {case conversion in regsub} { set foo 123 list [regsub a(a+) xaAAaAAay & foo] $foo } {0 xaAAaAAay} test regexp-8.4 {case conversion in regsub} { set foo 123 list [regsub -nocase a CaDE b foo] $foo } {1 CbDE} test regexp-8.5 {case conversion in regsub} { set foo 123 list [regsub -nocase XYZ CxYzD b foo] $foo } {1 CbD} test regexp-8.6 {case conversion in regsub} { set x abcdefghijklmnopqrstuvwxyz1234567890 set x $x$x$x$x$x$x$x$x$x$x$x$x set foo 123 list [regsub -nocase $x $x b foo] $foo } {1 b} test regexp-9.1 {-all option to regsub} { set foo 86 list [regsub -all x+ axxxbxxcxdx |&| foo] $foo } {4 a|xxx|b|xx|c|x|d|x|} test regexp-9.2 {-all option to regsub} { set foo 86 list [regsub -nocase -all x+ aXxXbxxcXdx |&| foo] $foo } {4 a|XxX|b|xx|c|X|d|x|} test regexp-9.3 {-all option to regsub} { set foo 86 list [regsub x+ axxxbxxcxdx |&| foo] $foo } {1 a|xxx|bxxcxdx} test regexp-9.4 {-all option to regsub} { set foo 86 list [regsub -all bc axxxbxxcxdx |&| foo] $foo } {0 axxxbxxcxdx} test regexp-9.5 {-all option to regsub} { set foo xxx list [regsub -all node "node node more" yy foo] $foo } {2 {yy yy more}} test regexp-9.6 {-all option to regsub} { set foo xxx list [regsub -all ^ xxx 123 foo] $foo } {1 123xxx} test regexp-10.2 {newline sensitivity in regsub} { set foo xxx list [regsub -line {^a.*b$} "dabc\naxyb\n" 123 foo] $foo } "1 {dabc\n123\n}" test regexp-10.3 {newline sensitivity in regsub} { set foo xxx list [regsub -line {^a.*b$} "dabc\naxyb\nxb" 123 foo] $foo } "1 {dabc\n123\nxb}" #test regexp-10.4 {partial newline sensitivity in regsub} { # set foo xxx # list [regsub -lineanchor {^a.*b$} "da\naxyb\nxb" 123 foo] $foo #} "1 {da\n123}" #test regexp-10.5 {inverse partial newline sensitivity in regsub} { # set foo xxx # list [regsub -linestop {a.*b} "da\nbaxyb\nxb" 123 foo] $foo #} "1 {da\nb123\nxb}" test regexp-11.1 {regsub errors} jim { list [catch {regsub a b} msg] $msg } {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}} test regexp-11.2 {regsub errors} jim { list [catch {regsub -nocase a b} msg] $msg } {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}} test regexp-11.3 {regsub errors} jim { list [catch {regsub -nocase -all a b} msg] $msg } {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}} test regexp-11.4 {regsub errors} jim { list [catch {regsub a b c d e f} msg] $msg } {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}} test regexp-11.5 {regsub errors} jim { list [catch {regsub -gorp a b c} msg] $msg } {1 {bad switch "-gorp": must be --, -all, -line, -nocase, or -start}} test regexp-11.6 {regsub errors} { catch {regsub -nocase a( b c d} msg } 1 test regexp-11.7 {regsub errors} jim { catch {unset f1} set f1 44 list [catch {regsub -nocase aaa aaa xxx f1(f2)} msg] $msg } {1 {can't set "f1(f2)": variable isn't array}} test regexp-11.8 {regsub errors, -start bad int check} { list [catch {regsub -start bogus pattern string rep var} msg] $msg } {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}} test regexp-11.9 {regsub without final variable name returns value} { regsub b abaca X } {aXaca} test regexp-11.10 {regsub without final variable name returns value} { regsub -all a abaca X } {XbXcX} test regexp-11.11 {regsub without final variable name returns value} { regsub b(\[^d\]*)d abcdeabcfde {,&,\1,} } {a,bcd,c,eabcfde} test regexp-11.12 {regsub without final variable name returns value} { regsub -all b(\[^d\]*)d abcdeabcfde {,&,\1,} } {a,bcd,c,ea,bcfd,cf,e} # This test crashes on the Mac unless you increase the Stack Space to about 1 # Meg. This is probably bigger than most users want... # 8.2.3 regexp reduced stack space requirements, but this should be # tested again test regexp-12.1 {Tcl_RegExpExec: large number of subexpressions} { list [regexp (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) abcdefghijklmnopqrstuvwxyz all a b c d e f g h i j k l m n o p q r s t u v w x y z] $all $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z } {1 abcdefghijklmnopqrstuvwxyz a b c d e f g h i j k l m n o p q r s t u v w x y z} test regexp-13.1 {regsub of a very large string} { # This test is designed to stress the memory subsystem in order # to catch Bug #933. It only fails if the Tcl memory allocator # is in use. set line {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE} set filedata [string repeat $line 200] for {set i 1} {$i<10} {incr i} { regsub -all "BEGIN_TABLE " $filedata "" newfiledata } set x done } {done} test regexp-14.1 {CompileRegexp: regexp cache} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f set x . append x *a regexp $x bbba } 1 test regexp-14.2 {CompileRegexp: regexp cache, different flags} { regexp .*a b regexp .*b c regexp .*c d regexp .*d e regexp .*e f set x . append x *a regexp -nocase $x bbba } 1 #test regexp-15.1 {regexp -start} { # catch {unset x} # list [regexp -start -10 {\d} 1abc2de3 x] $x #} {1 1} #test regexp-15.2 {regexp -start} { # catch {unset x} # list [regexp -start 2 {\d} 1abc2de3 x] $x #} {1 2} #test regexp-15.3 {regexp -start} { # catch {unset x} # list [regexp -start 4 {\d} 1abc2de3 x] $x #} {1 2} #test regexp-15.4 {regexp -start} { # catch {unset x} # list [regexp -start 5 {\d} 1abc2de3 x] $x #} {1 3} test regexp-15.5 {regexp -start, over end of string} { catch {unset x} list [regexp -start [string length 1abc2de3] {\d} 1abc2de3 x] [info exists x] } {0 0} test regexp-15.6 {regexp -start, loss of ^$ behavior} { list [regexp -start 2 {^$} {}] } {0} test regexp-15.7 {regexp -start, double option} { regexp -start 2 -start 0 a abc } 1 test regexp-15.8 {regexp -start, double option} { regexp -start 0 -start 2 a abc } 0 #test regexp-15.9 {regexp -start, end relative index} { # catch {unset x} # list [regexp -start end {\d} 1abc2de3 x] [info exists x] #} {0 0} #test regexp-15.10 {regexp -start, end relative index} { # catch {unset x} # list [regexp -start end-1 {\d} 1abc2de3 x] [info exists x] $x #} {1 1 3} # #test regexp-16.1 {regsub -start} { # catch {unset x} # list [regsub -all -start 2 {\d} a1b2c3d4e5 {/&} x] $x #} {4 a1b/2c/3d/4e/5} test regexp-16.2 {regsub -start} { catch {unset x} list [regsub -all -start -25 {z} hello {/&} x] $x } {0 hello} test regexp-16.3 {regsub -start} { catch {unset x} list [regsub -all -start 3 {z} hello {/&} x] $x } {0 hello} #test regexp-16.4 {regsub -start, \A behavior} { # set out {} # lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x # lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x #} {5 /a/b/c/d/e 3 ab/c/d/e} test regexp-16.5 {regsub -start, double option} { list [regsub -start 2 -start 0 a abc c x] $x } {1 cbc} test regexp-16.6 {regsub -start, double option} { list [regsub -start 0 -start 2 a abc c x] $x } {0 abc} test regexp-16.7 {regexp -start, end relative index} { list [regsub -start end a aaa b x] $x } {0 aaa} test regexp-16.8 {regexp -start, end relative index} { list [regsub -start end-1 a aaa b x] $x } {1 aab} test regexp-17.1 {regexp -inline} { regexp -inline b ababa } {b} test regexp-17.2 {regexp -inline} { regexp -inline (b) ababa } {b b} test regexp-17.3 {regexp -inline -indices} { regexp -inline -indices (b) ababa } {{1 1} {1 1}} #test regexp-17.4 {regexp -inline} { # regexp -inline {\w(\d+)\w} " hello 23 there456def " #} {e456d 456} #test regexp-17.5 {regexp -inline no matches} { # regexp -inline {\w(\d+)\w} "" #} {} test regexp-17.6 {regexp -inline no matches} { regexp -inline hello goodbye } {} test regexp-17.7 {regexp -inline, no matchvars allowed} { list [catch {regexp -inline b abc match} msg] $msg } {1 {regexp match variables not allowed when using -inline}} test regexp-18.1 {regexp -all} { regexp -all b bbbbb } {5} test regexp-18.2 {regexp -all} { regexp -all b abababbabaaaaaaaaaab } {6} test regexp-18.3 {regexp -all -inline} { regexp -all -inline b abababbabaaaaaaaaaab } {b b b b b b} #test regexp-18.4 {regexp -all -inline} { # regexp -all -inline {\w(\w)} abcdefg #} {ab b cd d ef f} #test regexp-18.5 {regexp -all -inline} { # regexp -all -inline {\w(\w)$} abcdefg #} {fg g} #test regexp-18.6 {regexp -all -inline} { # regexp -all -inline {\d+} 10:20:30:40 #} {10 20 30 40} test regexp-18.7 {regexp -all -inline} { list [catch {regexp -all -inline b abc match} msg] $msg } {1 {regexp match variables not allowed when using -inline}} test regexp-18.8 {regexp -all} { # This should not cause an infinite loop regexp -all -inline {a*} a } {a} test regexp-18.9 {regexp -all} { # Yes, the expected result is {a {}}. Here's why: # Start at index 0; a* matches the "a" there then stops. # Go to index 1; a* matches the lambda (or {}) there then stops. Recall # that a* matches zero or more "a"'s; thus it matches the string "b", as # there are zero or more "a"'s there. # Go to index 2; this is past the end of the string, so stop. regexp -all -inline {a*} ab } {a {}} test regexp-18.10 {regexp -all} { # Yes, the expected result is {a {} a}. Here's why: # Start at index 0; a* matches the "a" there then stops. # Go to index 1; a* matches the lambda (or {}) there then stops. Recall # that a* matches zero or more "a"'s; thus it matches the string "b", as # there are zero or more "a"'s there. # Go to index 2; a* matches the "a" there then stops. # Go to index 3; this is past the end of the string, so stop. regexp -all -inline {a*} aba } {a {} a} test regexp-18.11 {regexp -all} { regexp -all -inline {^a} aaaa } {a} test regexp-18.12 {regexp -all -inline -indices} { regexp -all -inline -indices a(b(c)d|e(f)g)h abcdhaefgh } {{0 4} {1 3} {2 2} {-1 -1} {5 9} {6 8} {-1 -1} {7 7}} test regexp-19.1 {regsub null replacement} { regsub -all {@} {@hel@lo@} "\0a\0" result list $result [string length $result] } "\0a\0hel\0a\0lo\0a\0 14" #test regexp-20.1 {regsub shared object shimmering} { # # Bug #461322 # set a abcdefghijklmnopqurstuvwxyz # set b $a # set c abcdefghijklmnopqurstuvwxyz0123456789 # regsub $a $c $b d # list $d [string length $d] [string bytelength $d] #} [list abcdefghijklmnopqurstuvwxyz0123456789 37 37] #test regexp-20.2 {regsub shared object shimmering with -about} { # eval regexp -about abc #} {0 {}} test regexp-21.1 {regsub works with empty string} { regsub -- ^ {} foo } {foo} test regexp-21.2 {regsub works with empty string} { regsub -- \$ {} foo } {foo} test regexp-21.3 {regsub works with empty string offset} { regsub -start 0 -- ^ {} foo } {foo} test regexp-21.4 {regsub works with empty string offset} { regsub -start 0 -- \$ {} foo } {foo} test regexp-21.5 {regsub works with empty string offset} { regsub -start 3 -- \$ {123} foo } {123foo} test regexp-21.6 {regexp works with empty string} { regexp -- ^ {} } {1} test regexp-21.7 {regexp works with empty string} { regexp -start 0 -- ^ {} } {1} test regexp-21.8 {regexp works with empty string offset} { regexp -start 3 -- ^ {123} } {0} test regexp-21.9 {regexp works with empty string offset} { regexp -start 3 -- \$ {123} } {1} #test regexp-21.10 {multiple matches handle newlines} { # regsub -all -lineanchor -- {^#[^\n]*\n} "#one\n#two\n#three\n" foo\n #} "foo\nfoo\nfoo\n" test regexp-21.11 {multiple matches handle newlines} { regsub -all -line -- ^ "a\nb\nc" \# } "\#a\n\#b\n\#c" test regexp-21.12 {multiple matches handle newlines} { regsub -all -line -- ^ "\n\n" \# } "\#\n\#\n\#" test regexp-21.13 {multiple matches handle newlines} { regexp -all -inline -indices -line -- ^ "a\nb\nc" } {{0 -1} {2 1} {4 3}} test regexp-21.14 {Literal newline in pattern} { regexp -all -inline "\n(\[ \t\]+)" "\n\t\t# This is a test" } "{\n\t\t} {\t\t}" test regexp-22.1 {effect of caching} jim { set filedata {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE} # Note: use 2 REs because often libc will cache a single regcomp() result # t1 should be faster because the compiled re can be cached. set re1 "END_TABLE" set re2 "BEGIN_TABLE" set t1 [time { regexp -inline -all $re1 $filedata regexp -inline -all $re2 $filedata } 10000] # t2 should be slower since the re's need to be recompiled every time set t2 [time { set re1 END append re1 _TABLE regexp -inline -all $re1 $filedata set re2 BEGIN append re2 _TABLE regexp -inline -all $re2 $filedata } 10000] set t1 [lindex $t1 0] set t2 [lindex $t2 0] # If these two times are within 20% of each other, caching isn't working expr {$t2 * 1.0 / $t1 < 1.2 && $t1 * 1.0 / $t2 < 1.2} } {0} testreport openocd-0.9.0/jimtcl/tests/procref.test0000644000175000017500000000157612315602575015074 00000000000000# Tests auto-upref with the "&name" syntax source [file dirname [info script]]/testing.tcl needs constraint jim proc a1 {&b c} { append b b append c c } proc a2 {&b {dummy 3} &c} { append b b append c c } proc a3 {&b(c)} { append b(c) b_c } # This is treated as a normal var "&b" proc a4 {{&b x}} { append &b B } set B 1 set C 1 test procref-1.1 {Basic test} { a1 B $C set B } {1b} test procref-1.2 {Basic test} { a1 B $C set B } {1bb} test procref-1.3 {Unset var} -body { a1 unsetB $C } -returnCodes error -result {can't read "unsetB": no such variable} test procref-1.4 {Left and right args are refs} { a2 B C list $B $C } {1bbb 1c} test procref-1.5 {Invalid arg} -body { a3 B } -returnCodes error -result {bad variable name "b(c)": upvar won't create a scalar variable that looks like an array element} test procref-1.6 {Default arg as ref} { a4 } xB testreport openocd-0.9.0/jimtcl/tests/utf8.test0000644000175000017500000000643612315602575014322 00000000000000source [file dirname [info script]]/testing.tcl needs constraint utf8 test utf8-1.1 "Pattern matching - ?" { string match "abc?def" "abc\u00b5def" } 1 test utf8-1.2 "Pattern matching - ?" { string match "abc?def" "abc\u2704def" } 1 test utf8-1.3 "Pattern utf-8 literal" { string match "ab\u00b5\u2704?" "ab\u00b5\u2704x" } 1 test utf8-1.4 "Pattern utf-8 char sets" { string match "a\[b\u00b5\]\u2704?" "a\u00b5\u2704x" } 1 test utf8-1.5 "Pattern utf-8 char sets" { string match "a\[b\u00b5\]\u2704?" "a\u00b6\u2704x" } 0 test utf8-1.6 "Pattern utf-8 char sets" { string match "a\[b\u00b5\]\u2704?" "ab\u2704x" } 1 test utf8-1.7 "Pattern utf-8 char sets" { string match "a\[b\u00b5\]?" "a\u2704x" } 0 test utf8-1.8 "Pattern utf-8 char sets" { string match "a\[\u00b5-\u00c3\]" "a\ubd" } 1 test utf8-1.9 "Pattern utf-8 char sets" { string match "a\[\u00b5-\u00c3\]" "a\uc4" } 0 test utf8-2.1 "Pattern utf-8 nocase" { string match -nocase "a\u1edc\u1ef4*" "A\u1edd\u1ef5XX" } 1 test utf8-2.2 "Pattern utf-8 case difference" { string match "a\u1edc\u1ef4*" "A\u1edd\u1ef5XX" } 0 test utf8-3.1 "lsearch -glob" { lsearch -glob {1 d a\u00b5xyb c} a\ub5*b } 2 test utf8-3.2 "switch -glob" { switch -glob -- a\ub5xyb a\ub5*b { set x 1 } default { set x 0 } set x } 1 set x "\ub5test" test utf8-3.3 "info procs" { proc $x {} { info procs \[\ub5X]???? } $x } $x test utf8-3.3 "info commands" { info commands \[\ub5X]???? } $x test utf8-3.4 "proc name with invalid utf-8" { catch { proc ab\xc2 {} {} } msg } 0 test utf8-3.5 "rename to invalid name" { catch { rename ab\xc2 ab\xc3 } msg } 0 catch {rename ab\xc3 ""} test utf8-4.1 "split with utf-8" { split "zy\u2702xw" x } "zy\u2702 w" test utf8-4.2 "split with utf-8" { split "zy\u2702xw" \u2702 } "zy xw" test utf8-4.2 "split with utf-8" { split "zy\u2702xw" {} } "z y \u2702 x w" test utf8-5.1 "string first with utf-8" { string first w "zy\u2702xw" } 4 test utf8-5.2 "string first with utf-8" { string first \u2702 "\ub5zy\u2702xw" } 3 test utf8-5.3 "string first with utf-8" { string first \u2704 "\ub5zy\u2702xw" } -1 test utf8-5.4 "string first with utf-8" { string first \u2702 "\ub5zy\u2702xw\u2702BB" } 3 test utf8-6.1 "string last with utf-8" { string last w "zy\u2702xw" } 4 test utf8-6.2 "string last with utf-8" { string last \u2702 "\ub5zy\u2702xw" } 3 test utf8-6.3 "string last with utf-8" { string last \u2704 "\ub5zy\u2702xw" } -1 test utf8-6.4 "string last with utf-8" { string last \u2702 "\ub5zy\u2702xw\u2702BB" } 6 test utf8-7.1 "string reverse" { string reverse \ub5Test\u2702 } \u2702tseT\ub5 test utf8-7.2 {append counts correctly} { set x \u2702XYZ append x \u2702XYZ list [string length $x] [string bytelength $x] } {8 12} test utf8-7.3 {Upper, lower for titlecase utf-8} { list [string toupper \u01c5] [string tolower \u01c5] } "\u01c4 \u01c6" test utf8-7.4 {Case folding may change encoded length} { list [string bytelength \u0131] [string bytelength [string toupper \u0131]] } {2 1} test utf8-8.1 {Chars outside the BMP} jim { string length \u{12000}\u{13000} } 2 test utf8-8.2 {Chars outside the BMP} jim { string match "ab\[\u{12000}c\]d" ab\u{12000}d } 1 test utf8-8.3 {Chars outside the BMP} jim { string last d "ab\u{101fff}cd" } 4 test utf8-8.4 {Longer sequences} { string length \u12000 } 2 testreport openocd-0.9.0/jimtcl/tests/subst.test0000644000175000017500000001160012315602575014561 00000000000000# Commands covered: subst # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1994 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-2000 Ajuba Solutions. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: subst.test,v 1.6.2.1 2001/04/03 22:54:38 hobbs Exp $ source [file dirname [info script]]/testing.tcl test subst-1.0 {basics} { subst {\$x} } "\$x" test subst-1.1 {basics} { list [catch {subst} msg] } {1} test subst-1.2 {basics} { list [catch {subst a b c} msg] } {1} test subst-2.1 {simple strings} { subst {} } {} test subst-2.2 {simple strings} { subst a } a test subst-2.3 {simple strings} { subst abcdefg } abcdefg test subst-3.1 {backslash substitutions} { subst {\x\$x\[foo bar]\\} } "x\$x\[foo bar]\\" test subst-4.1 {variable substitutions} { set a 44 subst {$a} } {44} test subst-4.2 {variable substitutions} { set a 44 subst {x$a.y{$a}.z} } {x44.y{44}.z} test subst-4.3 {variable substitutions} { catch {unset a} set a(13) 82 set i 13 subst {x.$a($i)} } {x.82} catch {unset a} set long {This is a very long string, intentionally made so long that it will overflow the static character size for dstrings, so that additional memory will have to be allocated by subst. That way, if the subst procedure forgets to free up memory while returning an error, there will be memory that isn't freed (this will be detected when the tests are run under a checking memory allocator such as Purify).} test subst-4.4 {variable substitutions} { list [catch {subst {$long $a}} msg] $msg } {1 {can't read "a": no such variable}} test subst-5.1 {command substitutions} { subst {[concat {}]} } {} test subst-5.2 {command substitutions} { subst {[concat A test string]} } {A test string} test subst-5.3 {command substitutions} { subst {x.[concat foo].y.[concat bar].z} } {x.foo.y.bar.z} test subst-5.4 {command substitutions} { list [catch {subst {$long [set long] [bogus_command]}} msg] $msg } {1 {invalid command name "bogus_command"}} test subst-6.1 {clear the result after command substitution} { catch {unset a} list [catch {subst {[concat foo] $a}} msg] $msg } {1 {can't read "a": no such variable}} test subst-7.1 {switches} { list [catch {subst foo bar} msg] } {1} test subst-7.2 {switches} { list [catch {subst -no bar} msg] } {1} test subst-7.3 {switches} { list [catch {subst -bogus bar} msg] } {1} test subst-7.4 {switches} { set x 123 subst -nobackslashes {abc $x [expr 1+2] \\\x41} } {abc 123 3 \\\x41} test subst-7.5 {switches} { set x 123 subst -nocommands {abc $x [expr 1+2] \\\x41} } {abc 123 [expr 1+2] \A} test subst-7.6 {switches} { set x 123 subst -novariables {abc $x [expr 1+2] \\\x41} } {abc $x 3 \A} test subst-7.7 {switches} { set x 123 subst -nov -nob -noc {abc $x [expr 1+2] \\\x41} } {abc $x [expr 1+2] \\\x41} test subst-8.1 {return in a subst} { subst {foo [return {x}; bogus code] bar} } {foo x bar} test subst-8.2 {return in a subst} { subst {foo [return x ; bogus code] bar} } {foo x bar} test subst-8.3 {return in a subst} { subst {foo [if 1 { return {x}; bogus code }] bar} } {foo x bar} test subst-8.4 {return in a subst} { subst {[eval {return hi}] there} } {hi there} test subst-8.5 {return in a subst} { subst {foo [return {]}; bogus code] bar} } {foo ] bar} test subst-9.1 {error in a subst} { list [catch {subst {[error foo; bogus code]bar}} msg] $msg } {1 foo} test subst-9.2 {error in a subst} { list [catch {subst {[if 1 { error foo; bogus code}]bar}} msg] $msg } {1 foo} test subst-10.1 {break in a subst} { subst {foo [break; bogus code] bar} } {foo } test subst-10.2 {break in a subst} { subst {foo [break; return x; bogus code] bar} } {foo } test subst-10.3 {break in a subst} { subst {foo [if 1 { break; bogus code}] bar} } {foo } test subst-10.4 {break in a subst, parse error} { subst {foo [break ; set a {}{} ; stuff] bar} } {foo } test subst-10.5 {break in a subst, parse error} { subst {foo [break ;set bar baz ;set a {}{} ; stuff] bar} } {foo } test subst-11.1 {continue in a subst} { subst {foo [continue; bogus code] bar} } {foo bar} test subst-11.2 {continue in a subst} { subst {foo [continue; return x; bogus code] bar} } {foo bar} test subst-11.3 {continue in a subst} { subst {foo [if 1 { continue; bogus code}] bar} } {foo bar} test subst-12.1 {lone $} { subst {$} } {$} test subst-12.2 {lone $} { set a 1 subst -novar {${a}} } {${a}} test subst-12.3 {variable inside [] with -noc} { set a 1 subst -noc {x[join $a]y} } {x[join 1]y} # cleanup testreport openocd-0.9.0/jimtcl/tests/concat.test0000644000175000017500000000405212315602575014673 00000000000000source [file dirname [info script]]/testing.tcl test concat-1.1 {simple concatenation} { concat a b c d e f g } {a b c d e f g} test concat-1.2 {merging lists together} { concat a {b c d} {e f g h} } {a b c d e f g h} test concat-1.3 {merge lists, retain sub-lists} { concat a {b {c d}} {{e f}} g h } {a b {c d} {e f} g h} test concat-1.4 {special characters} { concat a\{ {b \{c d} \{d } "a{ b \\{c d {d" test concat-2.1 {error check: one empty argument} { concat {} } {} test concat-3.1 {error check: no arguments} { list [catch concat msg] $msg } {0 {}} test concat-4.1 {pruning off extra white space} { concat {} {a b c} } {a b c} test concat-4.2 {pruning off extra white space} { concat x y " a b c \n\t " " " " def " } {x y a b c def} test concat-4.3 {pruning off extra white space sets length correctly} { llength [concat { {{a}} }] } 1 test concat-5.1 {Tcl_ScanCountedElement procedure - don't leave unmatched braces} { # This test checks for a very tricky feature. Any list element # generated with Tcl_ScanCountedElement and Tcl_ConvertElement must # have the property that it can be enclosing in curly braces to make # an embedded sub-list. If this property doesn't hold, then # Tcl_DStringStartSublist doesn't work. set x {} lappend x " \\\{ \\" concat $x [llength "{$x}"] } {\ \\\{\ \\ 1} test concat-6.1 {Tcl_ConcatObj - backslash-space at end of argument} { concat a {b\ } c } {a b\ c} test concat-6.2 {Tcl_ConcatObj - backslash-space at end of argument} { concat a {b\ } c } {a b\ c} test concat-6.3 {Tcl_ConcatObj - backslash-space at end of argument} { concat a {b\\ } c } {a b\\ c} test concat-6.4 {Tcl_ConcatObj - backslash-space at end of argument} { concat a {b } c } {a b c} test concat-6.5 {Tcl_ConcatObj - backslash-space at end of argument} { concat a { } c } {a c} test concat-6.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} { # Check for Bug #227512. If this violates C isspace, then it returns \xc3. concat \xe0 } \xe0 testreport openocd-0.9.0/jimtcl/tests/infoframe.test0000644000175000017500000000105712315602575015374 00000000000000source [file dirname [info script]]/testing.tcl needs constraint jim proc a {n} { if {$n eq "trace"} { stacktrace } else { info frame $n } } proc b {n} { a $n } proc c {n} { b $n } # --- Don't change line numbers above test info-frame-1.1 "Current proc" { c 0 } {a infoframe.test 12} test info-frame-1.2 "Caller" { c -1 } {b infoframe.test 16} test info-frame-1.3 "Caller of Caller" { c -2 } {c infoframe.test 30} test stacktrace-1.1 "Full stack trace" { c trace } {a infoframe.test 12 b infoframe.test 16 c infoframe.test 34} testreport openocd-0.9.0/jimtcl/tests/upvar.test0000644000175000017500000002031012516456445014562 00000000000000# Commands covered: upvar # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: upvar.test,v 1.7 2000/04/10 17:19:05 ericm Exp $ source [file dirname [info script]]/testing.tcl needs cmd array test upvar-1.1 {reading variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2} proc p2 {} {upvar a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a} p1 foo bar } {foo bar 22 33 abc} test upvar-1.2 {reading variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2} proc p2 {} {p3} proc p3 {} {upvar 2 a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a} p1 foo bar } {foo bar 22 33 abc} test upvar-1.3 {reading variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2} proc p2 {} {p3} proc p3 {} { upvar #1 a x1 b x2 c x3 d x4 set a abc list $x1 $x2 $x3 $x4 $a } p1 foo bar } {foo bar 22 33 abc} test upvar-1.4 {reading variables with upvar} { set x1 44 set x2 55 proc p1 {} {p2} proc p2 {} { upvar 2 x1 x1 x2 a upvar #0 x1 b set c $b incr b 3 list $x1 $a $b } p1 } {47 55 47} test upvar-1.5 {reading array elements with upvar} { proc p1 {} {set a(0) zeroth; set a(1) first; p2} proc p2 {} {upvar a(0) x; set x} p1 } {zeroth} test upvar-2.1 {writing variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2; list $a $b $c $d} proc p2 {} { upvar a x1 b x2 c x3 d x4 set x1 14 set x4 88 } p1 foo bar } {14 bar 22 88} test upvar-2.2 {writing variables with upvar} { set x1 44 set x2 55 proc p1 {x1 x2} { upvar #0 x1 a upvar x2 b set a $x1 set b $x2 } p1 newbits morebits list $x1 $x2 } {newbits morebits} test upvar-2.3 {writing variables with upvar} { catch {unset x1} catch {unset x2} proc p1 {x1 x2} { upvar #0 x1 a upvar x2 b set a $x1 set b $x2 } p1 newbits morebits list [catch {set x1} msg] $msg [catch {set x2} msg] $msg } {0 newbits 0 morebits} test upvar-2.4 {writing array elements with upvar} { proc p1 {} {set a(0) zeroth; set a(1) first; list [p2] $a(0)} proc p2 {} {upvar a(0) x; set x xyzzy} p1 } {xyzzy xyzzy} test upvar-3.1 {unsetting variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2; lsort [info vars]} proc p2 {} { upvar 1 a x1 d x2 unset x1 x2 } p1 foo bar } {b c} test upvar-3.2 {unsetting variables with upvar} { proc p1 {a b} {set c 22; set d 33; p2; lsort [info vars]} proc p2 {} { upvar 1 a x1 d x2 unset x1 x2 set x2 28 } p1 foo bar } {b c d} test upvar-3.3 {unsetting variables with upvar} { set x1 44 set x2 55 proc p1 {} {p2} proc p2 {} { upvar 2 x1 a upvar #0 x2 b unset a b } p1 list [info exists x1] [info exists x2] } {0 0} test upvar-3.4 {unsetting variables with upvar} { set x1 44 set x2 55 proc p1 {} { upvar x1 a x2 b unset a b set b 118 } p1 list [info exists x1] [catch {set x2} msg] $msg } {0 0 118} test upvar-3.5 {unsetting array elements with upvar} { proc p1 {} { set a(0) zeroth set a(1) first set a(2) second p2 lsort [array names a] } proc p2 {} {upvar a(0) x; unset x} p1 } {1 2} test upvar-3.6 {unsetting then resetting array elements with upvar} { proc p1 {} { set a(0) zeroth set a(1) first set a(2) second p2 list [lsort [array names a]] [catch {set a(0)} msg] $msg } proc p2 {} {upvar a(0) x; unset x; set x 12345} p1 } {{0 1 2} 0 12345} test upvar-4.1 {nested upvars} { set x1 88 proc p1 {a b} {set c 22; set d 33; p2} proc p2 {} {global x1; upvar c x2; p3} proc p3 {} { upvar x1 a x2 b list $a $b } p1 14 15 } {88 22} test upvar-4.2 {nested upvars} { set x1 88 proc p1 {a b} {set c 22; set d 33; p2; list $a $b $c $d} proc p2 {} {global x1; upvar c x2; p3} proc p3 {} { upvar x1 a x2 b set a foo set b bar } list [p1 14 15] $x1 } {{14 15 bar 33} foo} proc tproc {args} {global x; set x [list $args [uplevel info vars]]} test upvar-6.1 {retargeting an upvar} { proc p1 {} { set a(0) zeroth set a(1) first set a(2) second p2 } proc p2 {} { upvar a x set result {} foreach i [array names x] { upvar a($i) x lappend result $x } lsort $result } p1 } {first second zeroth} test upvar-6.2 {retargeting an upvar} { set x 44 set y abcde proc p1 {} { global x set result $x upvar y x lappend result $x } p1 } {44 abcde} test upvar-6.3 {retargeting an upvar} { set x 44 set y abcde proc p1 {} { upvar y x lappend result $x global x lappend result $x } p1 } {abcde 44} test upvar-7.1 {upvar to same level} { set x 44 set y 55 catch {unset uv} upvar #0 x uv set uv abc upvar 0 y uv set uv xyzzy list $x $y } {abc xyzzy} test upvar-7.2 {upvar to same level} { set x 1234 set y 4567 proc p1 {x y} { upvar 0 x uv set uv $y return "$x $y" } p1 44 89 } {89 89} test upvar-7.3 {upvar to same level} { set x 1234 set y 4567 proc p1 {x y} { upvar #1 x uv set uv $y return "$x $y" } p1 xyz abc } {abc abc} test upvar-7.4 {upvar to same level: tricky problems when deleting variable table} { proc tt {} {upvar #1 toto loc; return $loc} list [catch tt msg] $msg } {1 {can't read "loc": no such variable}} test upvar-7.5 {potential memory leak when deleting variable table} { proc leak {} { array set foo {1 2 3 4} upvar 0 foo(1) bar } leak } {} test upvar-8.1 {errors in upvar command} { catch upvar msg } 1 test upvar-8.2 {errors in upvar command} { catch {upvar 1} } 1 test upvar-8.3 {errors in upvar command} { proc p1 {} {upvar a b c} catch p1 } 1 test upvar-8.4 {errors in upvar command} { proc p1 {} {upvar 0 b b} list [catch p1 msg] $msg } {1 {can't upvar from variable to itself}} test upvar-8.5 {errors in upvar command} { proc p1 {} {upvar 0 a b; upvar 0 b a} list [catch p1 msg] $msg } {1 {can't upvar from variable to itself}} test upvar-8.6 {errors in upvar command} { proc p1 {} {set a 33; upvar b a} list [catch p1 msg] $msg } {1 {variable "a" already exists}} # Jim allows dicts within dicts. Tcl can't do this. test upvar-8.8 {create nested array with upvar} jim { proc p1 {} {upvar x(a) b; set b(2) 44} catch {unset x} p1 set x } {a {2 44}} test upvar-8.10 {upvar will create element alias for new array element} { catch {unset upvarArray} array set upvarArray {} catch {upvar 0 upvarArray(elem) upvarArrayElemAlias} } {0} test upvar-8.11 {error upvar array element} { proc a {} { upvar a b(1) } list [catch {a} msg] $msg } {1 {bad variable name "b(1)": upvar won't create a scalar variable that looks like an array element}} test upvar-9.1 {global redefine} { proc p1 {} { global x; global x } p1 } {} test upvar-9.2 {upvar redefine} { set a 1 set b 2 proc p1 {} { upvar a x; upvar b x; return $x } p1 } 2 test upvar-9.3 {upvar redefine static} jim { proc p1 {} {{a 3}} { upvar b a; return $b } list [catch p1 msg] $msg } {1 {variable "a" already exists}} test upvar-9.4 {upvar links to static} jim { proc p1 {} {} { upvar a x; incr x; return $x } proc p2 {} {{a 3}} { list [p1] $a } p2 } {4 4} test upvar-9.5 {upvar via global namespace} { set x 2 unset -nocomplain y # Links ::y to ::x proc p1 {} { upvar x ::y; incr ::y -1 } p1 list $x $y } {1 1} test upvar-9.6 {upvar via global namespace} { set x 2 unset -nocomplain x # Links ::x to ::x proc p1 {} { upvar x ::x; incr ::x } list [catch p1 msg] $msg } {1 {can't upvar from variable to itself}} test upvar-9.7 {upvar to higher level} { proc p1 {} { upvar 0 x ::globx } list [catch p1 msg] $msg } {1 {bad variable name "::globx": upvar won't create namespace variable that refers to procedure variable}} catch {unset a} testreport openocd-0.9.0/jimtcl/tests/regcount.test0000644000175000017500000000514512315602575015256 00000000000000source [file dirname [info script]]/testing.tcl needs cmd regexp testConstraint regexp_are [expr {[regexp {\d} 1]}] needs constraint regexp_are # Test regexp counted repetitions set n 0 foreach {pat str exp} { a+ bac a a{1,} bac a a* bac {{}} a{0,} bac {{}} aa+ bac {} a{2,} bac {} a{2,} bacaad aa a{3,} bacaad {} {a{2,}$} bacaad {} {a{2,}$} bacaa aa {a{2,}$} ba {} {a{2,}$} aa aa {a{0,0}b$} b b {a{1,1}b$} b {} {a{1,1}b$} cab ab {a{2,2}b$} cab {} {a{2,2}b$} cabaabx {} {a{2,2}b$} cacaab aab ca{2,4}b cacaab caab ca{2,3}b cacaab caab ca{2,3}b cacaaab caaab c(a|b){2,3}d xcbad {cbad a} c(a|b){2,3}d xcabbd {cabbd b} c(a|b){2,3}d xcbaaad {} a{4} baaaad aaaa a{2,5} baaaad aaaa a{1,3} baaaad aaa a{1,2} baaaad aa a{3,4} baaaad aaaa a{5,6} baaaad {} a{4}? baaaad aaaa a{2,5}? baaaad aa a{1,3}? baaaad a a{1,2}? baaaad a a{3,4}? baaaad aaa a{5,6}? baaaad {} {\d{1,3}} 239 239 (aa|bb)?c xabbaac {aac aa} (a|y)+ bac {a a} (a|y){1,} bac {a a} (a|y)* bac {{} {}} (a|y){0,} bac {{} {}} (a|y)a+ bac {} (a|y){2,} bac {} (a|y){2,} bacaad {aa a} (a|y){3,} bacaad {} {(a|y){2,}$} bacaad {} {(a|y){2,}$} bacaa {aa a} {(a|y){2,}$} ba {} {(a|y){2,}$} aa {aa a} {(a|y){0,0}b$} b {b {}} {(a|y){1,1}b$} b {} {(a|y){1,1}b$} cab {ab a} {(a|y){2,2}b$} cab {} {(a|y){2,2}b$} cabaabx {} {(a|y){2,2}b$} cacaab {aab a} c(a|y){2,4}b cacaab {caab a} c(a|y){2,3}b cacaab {caab a} c(a|y){2,3}b cacaaab {caaab a} c((a|y)|b){2,3}d xcbad {cbad a a} ####c((a|y)|b){2,3}d xcabbd {cabbd b {}} c((a|y)|b){2,3}d xcbaaad {} (a|y){4} baaaad {aaaa a} (a|y){2,5} baaaad {aaaa a} (a|y){1,3} baaaad {aaa a} (a|y){1,2} baaaad {aa a} (a|y){3,4} baaaad {aaaa a} (a|y){5,6} baaaad {} (a|y){4}? baaaad {aaaa a} (a|y){2,5}? baaaad {aa a} (a|y){1,3}? baaaad {a a} (a|y){1,2}? baaaad {a a} (a|y){3,4}? baaaad {aaa a} (a|y){5,6}? baaaad {} {[[:alpha:]]+} _bcd56_ef bcd {[[:alnum:]]+} _bcd56_ef bcd56 {[[:space:]]+} "_bc \t\r\n\f\v_" "{ \t\r\n\f\v}" {[\x41-\x43]+} "_ABCD_" ABC {\m.+\M} "#A test#" "{A test}" {\m.+?\M} "#A test#" "A" {\m\M} "a" "" {ab*c} xnbbmbbbc {} {.^xxx} yyy {} {\mb} " abc " "" ####((a*)*b)*b aaaaaaaaaaaaaaaaaaaaaaaaab {b {} {}} ####(a*)* aab {aa {}} {^([^:=]*)(:)?(=)?$} version {version version {} {}} } { if {[string match #* $pat]} { continue } #puts \t[list $pat $str [regexp -inline -- $pat $str]] test regcount-1.[incr n] "Test: regexp $pat $str" [list regexp -inline -- $pat $str] $exp } test regcount-2.1 "regexp counts cleared" { set re "((a|b){1,2}(c{2,3}))" regexp -inline $re xabcccce regexp -inline $re xabcccce } {abccc abccc b ccc} testreport openocd-0.9.0/jimtcl/tests/event.test0000644000175000017500000001417112516456444014555 00000000000000# This file contains a collection of tests for the procedures in the file # tclEvent.c, which includes the "update", and "vwait" Tcl # commands. Sourcing this file into Tcl runs the tests and generates # output for errors. No output means no errors were found. # # Copyright (c) 1995-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl needs cmd after eventloop testConstraint socket [expr {[info commands socket] ne ""}] testConstraint exec [expr {[info commands exec] ne ""}] testConstraint signal [expr {[info commands signal] ne ""}] catch {[socket -ipv6 stream ::1:5000]} ipv6res testConstraint ipv6 [expr {$ipv6res ne "ipv6 not supported"}] test event-5.1 {Tcl_BackgroundError, HandleBgErrors procedures} jim { catch {rename bgerror {}} proc bgerror msg { lappend ::x $msg } after idle {error "a simple error"} after idle {open non_existent} after idle {set errorInfo foobar; set errorCode xyzzy} set x {} update idletasks rename bgerror {} set x } {{a simple error} {non_existent: No such file or directory}} test event-7.1 {bgerror / regular} { set errRes {} proc bgerror {err} { global errRes; set errRes $err; } after 0 {error err1} vwait errRes; set errRes; } err1 test event-7.2 {bgerror / accumulation} { set errRes {} proc bgerror {err} { global errRes; lappend errRes $err; } after 0 {error err1} after 0 {error err2} after 0 {error err3} update set errRes; } {err1 err2 err3} test event-7.3 {bgerror / accumulation / break} { set errRes {} proc bgerror {err} { global errRes; lappend errRes $err; return -code break "skip!"; } after 0 {error err1} after 0 {error err2} after 0 {error err3} update set errRes; } err1 # end of bgerror tests catch {rename bgerror {}} test event-10.1 {Tcl_Exit procedure} exec { set cmd [list exec [info nameofexecutable] "<= 0} { incr lines } close $f list $lines } {2} set g1 1 set g2 2 array set g3 {4 5 6 7} proc test_unset {} { test unset-1.1 "Simple var" { set g4 4 list [catch {unset g4; info exists g4} msg] $msg } {0 0} test unset-1.2 "Simple var" { list [catch {unset g4; info exists g4} msg] $msg } {1 {can't unset "g4": no such variable}} test unset-1.3 "Simple var" { list [catch {unset g2; info exists g2} msg] $msg } {1 {can't unset "g2": no such variable}} test unset-1.4 "Global via global" { global g1 list [catch {unset g1; info exists g1} msg] $msg } {0 0} test unset-1.5 "Global error" { list [catch {unset ::g2; info exists ::g2} msg] $msg } {0 0} test unset-1.6 "Global array" { list [catch {unset ::g3; info exists ::g3} msg] $msg } {0 0} test unset-1.7 "Simple var -nocomplain" { list [catch {unset -nocomplain g2; info exists g2} msg] $msg } {0 0} test unset-1.8 "Simple var --" { list [catch {unset -- g2; info exists g2} msg] $msg } {1 {can't unset "g2": no such variable}} test unset-1.9 "Simple var -nocomplain --" { set g2 1 list [catch {unset -nocomplain -- g2; info exists g2} msg] $msg } {0 0} test unset-1.10 "Var named -nocomplain with --" { set -nocomplain 1 list [catch {unset -- -nocomplain; info exists -nocomplain} msg] $msg } {0 0} test unset-1.11 "Unset no args" { list [catch {unset} msg] $msg } {0 {}} } test_unset test lrepeat-1.1 "Basic tests" { lrepeat 1 a } {a} test lrepeat-1.2 "Basic tests" { lrepeat 1 a b } {a b} test lrepeat-1.3 "Basic tests" { lrepeat 2 a b } {a b a b} test lrepeat-1.4 "Basic tests" { lrepeat 2 a } {a a} test lrepeat-1.5 "Errors" { catch {lrepeat} } {1} test lrepeat-1.6 "Errors" { lrepeat 1 } {} test lrepeat-1.7 "Errors" { lrepeat 0 a b } {} test lrepeat-1.8 "Errors" { catch {lrepeat -10 a} } {1} test lindex-1.1 "Integer" { lindex {a b c} 0 } a test lindex-1.2 "Integer" { lindex {a b c} 2 } c test lindex-1.3 "Integer" { lindex {a b c} -1 } {} test lindex-1.4 "Integer" { lindex {a b c} 4 } {} test lindex-1.5 "end" { lindex {a b c} end } c test lindex-1.6 "end" { lindex {a b c} end-1 } b test lindex-1.7 "end" { lindex {a b c} end-4 } {} test lindex-1.8 "end + " { lindex {a b c} end+1 } {} test lindex-1.9 "end + " { lindex {a b c} end+-1 } b test lindex-1.10 "end - errors" { catch {lindex {a b c} end-} } 1 test lindex-1.11 "end - errors" { catch {lindex {a b c} end-blah} } 1 test lindex-1.12 "int+int, int-int" { lindex {a b c} 0+4 } {} test lindex-1.13 "int+int, int-int" { lindex {a b c} 3-1 } c test lindex-1.14 "int+int, int-int" { lindex {a b c} 1--1 } c test lindex-1.15 "int+int, int-int" { set l {a b c} lindex $l [lsearch $l b]-1 } a test lindex-1.16 "int+int, int-int" { lindex {a b c} 0+1 } b test lindex-1.17 "int+int - errors" { catch {lindex {a b c} 5-blah} } 1 test lindex-1.18 "int+int - errors" { catch {lindex {a b c} blah-2} } 1 test lindex-1.19 "int+int - errors" { catch {lindex {a b c} 5+blah} } 1 test lindex-1.20 "unary plus" { lindex {a b c} +2 } c test incr-1.1 "incr unset" { unset -nocomplain a incr a set a } 1 test incr-1.2 "incr, incr unset" { incr a } 2 test incr-1.3 "incr unset array element" { unset -nocomplain a incr a(2) set a(2) } 1 test incr-1.4 "incr array element - shimmering" { set b "$a(2)-test" incr a(2) } 2 test catch-1.1 "catch ok" { list [catch {set abc 2} result] $result } {0 2} test catch-1.2 "catch error" { list [catch {error 3} result] $result } {1 3} test catch-1.3 "catch break" { list [catch {break} result] $result } {3 {}} test catch-1.4 "catch -nobreak" { set result {} foreach x {a b c} { lappend result $x # This acts just like break since it won't be caught by catch catch -nobreak {break} tmp } set result } {a} test catch-1.5 "catch -no3" { set result {} foreach x {a b c} { lappend result $x # Same as above, but specify as an integer catch -no3 {break} tmp } set result } {a} test catch-1.6 "catch break" { set result {} foreach x {a b c} { lappend result $x # This does nothing since the break is caught catch {break} tmp } set result } {a b c} test catch-1.7 "catch exit" { # Normally exit would not be caught dict get [info returncodes] [catch -exit {exit 5} result] } {exit} test catch-1.8 "catch error has -errorinfo" { set rc [catch {set undefined} msg opts] list $rc [info exists opts(-errorinfo)] } {1 1} test catch-1.9 "catch no error has no -errorinfo" { set rc [catch {set x 1} msg opts] list $rc [info exists opts(-errorinfo)] } {0 0} test return-1.1 "return can rethrow an error" { proc a {} { error "from a" } proc b {} { catch {a} msg opts; return {*}$opts $msg } set rc [catch {b} msg opts] list $rc $msg [llength $opts(-errorinfo)] } {1 {from a} 6} test return-1.2 "error can rethrow an error" { proc a {} { error "from a" } proc b {} { catch {a} msg; error $msg [info stacktrace] } set rc [catch {b} msg opts] list $rc $msg [llength $opts(-errorinfo)] } {1 {from a} 9} test return-1.3 "return can rethrow no error" { proc a {} { return "from a" } proc b {} { catch {a} msg opts; return {*}$opts $msg } set rc [catch {b} msg opts] #list $rc $msg [llength $opts(-errorinfo)] list $rc $msg [info exists opts(-errorinfo)] } {0 {from a} 0} test stringreverse-1.1 "Containing nulls" { string reverse abc\0def } "fed\0cba" test split-1.1 "Split with leading null" { split "\0abc\0def\0" \0 } {{} abc def {}} test parsevar-1.1 "Variables should include double colons" { set ::a::b 2 set x $::a::b unset ::a::b set x } 2 test sharing-1.1 "Problems with ref sharing in arrays: lappend" { set a {a 1 c 2} set b $a lappend b(c) 3 set a(c) } 2 test sharing-1.2 "Problems with ref sharing in arrays: append" { set a {a 1 c 2} set b $a append b(c) 3 set a(c) } 2 test sharing-1.3 "Problems with ref sharing in arrays: incr" { set a {a 1 c 2} set b $a incr b(c) set a(c) } 2 test sharing-1.4 "Problems with ref sharing in arrays: lset" { set a {a 1 c {2 3}} set b $a lset b(c) 1 x set a(c) } {2 3} test jimexpr-1.1 "integer ** operator" { expr {2 ** 3} } 8 test jimexpr-1.2 "integer ** operator" { expr {0 ** 3} } 0 test jimexpr-1.3 "integer ** operator" { expr {2 ** 0} } 1 test jimexpr-1.4 "integer ** operator" { expr {-2 ** 1} } -2 test jimexpr-1.5 "integer ** operator" { expr {3 ** -2} } 0 test jimexpr-1.6 "+ command" { + 1 } 1 test jimexpr-1.7 "+ command" { + 2 3.5 } 5.5 test jimexpr-1.8 "+ command" { + 2 3 4 -6 } 3 test jimexpr-1.9 "* command" { * 4 } 4 test jimexpr-1.10 "* command" { * 4 2 } 8 test jimexpr-1.11 "* command" { * 4 2 -0.5 } -4.0 test jimexpr-1.12 "/ command" { / 2 } 0.5 test jimexpr-1.12 "/ command" { / 0.5 } 2.0 test jimexpr-1.13 "/ command" { / 12 3 } 4 test jimexpr-1.14 "/ command" { / 12 3 2.0 } 2.0 test jimexpr-1.15 "- command" { - 6 } -6 test jimexpr-1.15 "- command" { - 6.5 } -6.5 test jimexpr-1.16 "- command" { - 6 3 } 3 test jimexpr-1.17 "- command" { - 6 3 1.5 } 1.5 test jimexpr-1.17 "- command" { - 6.5 3 } 3.5 test jimexpr-2.1 "errors in math commands" { list [catch /] [catch {/ x}] [catch -] [catch {- blah blah}] [catch {- 2.0 blah}] [catch {+ x y}] [catch {* x}] } {1 1 1 1 1 1 1} test jimexpr-2.2 "not var optimisation" { set x [expr 1] set y [expr 0] set z [expr 2.0] list [expr {!$x}] [expr {!$y}] [expr {!$z}] } {0 1 0} test jimexpr-2.3 "expr access unset var" { unset -nocomplain a catch {expr {3 * $a}} } 1 test jimexpr-2.4 "expr double as bool" { set x 2 if {1.0} { set x 3 } } 3 # May be supported if support compiled in test jimexpr-2.5 "double ** operator" { catch {expr {2.0 ** 3}} result expr {$result in {unsupported 8.0}} } 1 # This one is for test coverage of an unusual case test jimobj-1.1 "duplicate obj with no dupIntRepProc" { proc "x x" {} { return 2 } set a "x x" # force it to be a command object set b [$a] # A second reference set c $a # Now force it to be duplicated lset a 1 x # force the duplicate object it to be a command object again set b [$a] # And get the string rep set x "y $a" } "y x x" test jimobj-1.2 "cooerced double to int" { set x 3 # cooerce to a double expr {4.5 + $x} # Now get the int rep incr x } 4 test jimobj-1.3 "cooerced double to double" { set x 3 # cooerce to a double expr {4.5 + $x} # Now use as a double expr {1.5 + $x} } 4.5 test jimobj-1.4 "incr dict sugar" { unset -nocomplain a set a(3) 3 incr a(3) list $a(3) $a } {4 {3 4}} test jim-badvar-1.1 "invalid variable name" { set x b\0c catch {set $x 5} } 1 test jim-badvar-1.2 "incr invalid variable name" { set x b\0c catch {incr $x} } 1 test lset-1.1 "lset with bad var" { catch {lset badvar 1 x} } 1 test dict-1.1 "dict to string" { set a [dict create abc \\ def \"] set x x$a # The order of keys in the dictionary is random if {$x eq "xabc \\\\ def {\"}" || $x eq "xdef {\"} abc \\\\"} { return ok } else { return "failed: \"$x\"" } } ok test channels-1.1 {info channels} { lsort [info channels] } {stderr stdin stdout} test lmap-1.1 {lmap} { lmap p {1 2 3} {incr p} } {2 3 4} test exprerr-1.1 {Error message with bad expr} { catch {expr {5 ||}} msg set msg } {Expression has bad operands to ||} test eval-list-1.1 {Lost string rep with list} { set x {set y 1; incr y} # Convert to list rep internally lindex $x 4 # But make sure we don't lost the original string rep list [catch $x] $y } {0 2} test info-statics-1.1 {info statics commands} { set x 1 proc a {} {x {y 2}} {} lsort [info statics a] } {1 2 x y} testreport openocd-0.9.0/jimtcl/tests/lsortcmd.test0000644000175000017500000000126112315602575015252 00000000000000source [file dirname [info script]]/testing.tcl set list {b d a c z} proc sorter {a v1 v2} { set ::arg $a return [string compare $v1 $v2] } proc test_lsort_cmd {test cmd list exp} { lsort -command $cmd $list if {$::arg != $exp} { error "$test: Failed" } } test lsortcmd-1.1 "Sort with one arg" { lsort -command "sorter arg1" $list set arg } {arg1} test lsortcmd-1.2 "Sort with one arg containg spaces" { lsort -command {sorter "arg with space"} $list set arg } {arg with space} test lsortcmd-1.3 "Sort with arg as list containg spaces" { lsort -command [list sorter [list arg with list "last with spaces"]] $list set arg } {arg with list {last with spaces}} testreport openocd-0.9.0/jimtcl/tests/prefix.test0000644000175000017500000001146612315602575014730 00000000000000# Commands covered: tcl::prefix # # This file contains a collection of tests for one or more of the Tcl # built-in commands. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. source [file dirname [info script]]/testing.tcl needs cmd tcl::prefix prefix testConstraint namespace [expr {[info commands namespace] ne ""}] test string-26.1 {tcl::prefix, too few args} -body { tcl::prefix match a } -returnCodes 1 -match glob -result {wrong # args: should be "tcl::prefix match ?options*? table string"} test string-26.2 {tcl::prefix, bad args} -body { tcl::prefix match a b c } -returnCodes 1 -result {bad option "a": must be -error, -exact, or -message} test string-26.2.1 {tcl::prefix, empty table} -body { tcl::prefix match {} foo } -returnCodes 1 -result {bad option "foo": no valid options} test string-26.3.1 {tcl::prefix, bad args} -body { tcl::prefix match -error "x" -exact str1 str2 } -returnCodes 1 -match glob -result * test string-26.3.2 {tcl::prefix, bad args} -body { tcl::prefix match -error str1 str2 } -returnCodes 1 -result {missing error options} test string-26.4 {tcl::prefix, bad args} -body { tcl::prefix match -message str1 str2 } -returnCodes 1 -result {missing message} test string-26.5 {tcl::prefix} { tcl::prefix match {apa bepa cepa depa} cepa } cepa test string-26.6 {tcl::prefix} { tcl::prefix match {apa bepa cepa depa} be } bepa test string-26.7 {tcl::prefix} -body { tcl::prefix match -exact {apa bepa cepa depa} be } -returnCodes 1 -result {bad option "be": must be apa, bepa, cepa, or depa} test string-26.8 {tcl::prefix} -body { tcl::prefix match -message switch {apa bear bepa depa} be } -returnCodes 1 -result {ambiguous switch "be": must be apa, bear, bepa, or depa} test string-26.9 {tcl::prefix} -body { tcl::prefix match -error {} {apa bepa bear depa} be } -returnCodes 0 -result {} test string-26.10 {tcl::prefix} -body { tcl::prefix match -error {-level 1} {apa bear bepa depa} be } -returnCodes 2 -result {ambiguous option "be": must be apa, bear, bepa, or depa} test string-27.1 {tcl::prefix all, too few args} -body { tcl::prefix all a } -returnCodes 1 -result {wrong # args: should be "tcl::prefix all table string"} test string-27.2 {tcl::prefix all, bad args} -body { tcl::prefix all a b c } -returnCodes 1 -result {wrong # args: should be "tcl::prefix all table string"} test string-27.4 {tcl::prefix all} { tcl::prefix all {apa bepa cepa depa} c } cepa test string-27.5 {tcl::prefix all} { tcl::prefix all {apa bepa cepa depa} cepa } cepa test string-27.6 {tcl::prefix all} { tcl::prefix all {apa bepa cepa depa} cepax } {} test string-27.7 {tcl::prefix all} { tcl::prefix all {apa aska appa} a } {apa aska appa} test string-27.8 {tcl::prefix all} { tcl::prefix all {apa aska appa} ap } {apa appa} test string-27.9 {tcl::prefix all} { tcl::prefix all {apa aska appa} p } {} test string-27.10 {tcl::prefix all} { tcl::prefix all {apa aska appa} {} } {apa aska appa} test string-28.1 {tcl::prefix longest, too few args} -body { tcl::prefix longest a } -returnCodes 1 -result {wrong # args: should be "tcl::prefix longest table string"} test string-28.2 {tcl::prefix longest, bad args} -body { tcl::prefix longest a b c } -returnCodes 1 -result {wrong # args: should be "tcl::prefix longest table string"} test string-28.4 {tcl::prefix longest} { tcl::prefix longest {apa bepa cepa depa} c } cepa test string-28.5 {tcl::prefix longest} { tcl::prefix longest {apa bepa cepa depa} cepa } cepa test string-28.6 {tcl::prefix longest} { tcl::prefix longest {apa bepa cepa depa} cepax } {} test string-28.7 {tcl::prefix longest} { tcl::prefix longest {apa aska appa} a } a test string-28.8 {tcl::prefix longest} { tcl::prefix longest {apa aska appa} ap } ap test string-28.9 {tcl::prefix longest} { tcl::prefix longest {apa bska appa} a } ap test string-28.10 {tcl::prefix longest} { tcl::prefix longest {apa bska appa} {} } {} test string-28.11 {tcl::prefix longest} { tcl::prefix longest {{} bska appa} {} } {} test string-28.12 {tcl::prefix longest} { tcl::prefix longest {apa {} appa} {} } {} test string-28.13 {tcl::prefix longest} { # Test UTF8 handling tcl::prefix longest {ax\x90 bep ax\x91} a } ax test string-29.1 {tcl::prefix from another namespace} namespace { namespace eval abc { tcl::prefix longest {apa bepa cepa depa} cepa } } cepa testreport openocd-0.9.0/jimtcl/tests/return.test0000644000175000017500000000200712315602575014741 00000000000000source [file dirname [info script]]/testing.tcl # return -code test return-1.1 {return -code} { set script "return -code 4 result" list [catch {eval $script} msg] $msg } {2 result} test return-1.2 {source file with break} { list [catch {source break.tcl} msg] $msg } {3 {}} test return-1.3 {source file with break} { list [catch {source return-break.tcl} msg] $msg } {3 result} proc a {level code msg} { return -level $level -code $code $msg } proc b {level code msg} { a $level $code $msg } test return-2.1 {return -level 0} { list [catch {a 0 20 text} msg] $msg } {20 text} test return-2.2 {return -level 1} { list [catch {a 1 20 text} msg] $msg } {20 text} test return-2.3 {return -level 2} { list [catch {a 2 20 text} msg] $msg } {2 text} test return-2.4 {return -level 0} { list [catch {b 0 20 text} msg] $msg } {20 text} test return-2.5 {return -level 1} { list [catch {b 1 20 text} msg] $msg } {20 text} test return-2.6 {return -level 2} { list [catch {b 2 20 text} msg] $msg } {20 text} testreport openocd-0.9.0/jimtcl/tools/0000755000175000017500000000000012526202232012566 500000000000000openocd-0.9.0/jimtcl/tools/benchtable.tcl0000644000175000017500000000205612315602575015316 00000000000000#!/usr/bin/env tclsh # # Tabulate the output of Jim's bench.tcl -batch # # Copyright (C) 2005 Pat Thoyts # proc main {filename} { set versions {} array set bench {} set f [open $filename r] while {[gets $f data] >= 0} { lappend versions [lindex $data 0] set results [lindex $data 1] foreach {title time} $results { lappend bench($title) $time } } close $f puts "Jim benchmarks - time in milliseconds" puts -nonewline [string repeat " " 21] foreach v $versions { puts -nonewline [format "% 6s " $v] } puts "" foreach test [lsort [array names bench]] { puts -nonewline "[format {% 20s} $test] " foreach v $bench($test) { if {$v eq "F"} { puts -nonewline " F " } else { puts -nonewline [format "% 6d " $v] } } puts "" } } if {!$tcl_interactive} { set r [catch {eval [linsert $argv 0 main]} res] puts $res exit $r } openocd-0.9.0/jimtcl/binary.tcl0000644000175000017500000001421512516456444013360 00000000000000# Implements the 'binary scan' and 'binary format' commands. # # (c) 2010 Steve Bennett # # See LICENCE in this directory for licensing. package require pack package require regexp proc binary {cmd args} { tailcall "binary $cmd" {*}$args } proc "binary format" {formatString args} { set bitoffset 0 set result {} # This RE is too unreliable... foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] { switch -exact -- $t { a - A { set value [binary::nextarg args] set sn [string bytelength $value] if {$n ne "*"} { if {$n eq ""} { set n 1 } if {$n > $sn} { # Need to pad the string with spaces or nulls append value [string repeat [dict get {A " " a \x00} $t] $($n - $sn)] } } else { set n $sn } if {$n} { set bitoffset [pack result $value -str $(8 * $n) $bitoffset] } } x { if {$n eq "*"} { return -code error {cannot use "*" in format string with "x"} } if {$n eq ""} { set n 1 } loop i 0 $n { set bitoffset [pack result 0 -intbe 8 $bitoffset] } } @ { if {$n eq ""} { return -code error {missing count for "@" field specifier} } if {$n eq "*"} { set bitoffset $(8 * [string bytelength $result]) } else { # May need to pad it out set max [string bytelength $result] append result [string repeat \x00 $($n - $max)] set bitoffset $(8 * $n) } } X { if {$n eq "*"} { set bitoffset 0 } elseif {$n eq ""} { incr bitoffset -8 } else { incr bitoffset $($n * -8) } if {$bitoffset < 0} { set bitoffset 0 } } default { if {![info exists ::binary::scalarinfo($t)]} { return -code error "bad field specifier \"$t\"" } # A scalar (integer or float) type lassign $::binary::scalarinfo($t) type convtype size prefix set value [binary::nextarg args] if {$type in {bin hex}} { set value [split $value {}] } set vn [llength $value] if {$n eq "*"} { set n $vn } elseif {$n eq ""} { set n 1 set value [list $value] } elseif {$vn < $n} { if {$type in {bin hex}} { # Need to pad the list with zeros lappend value {*}[lrepeat $($n - $vn) 0] } else { return -code error "number of elements in list does not match count" } } elseif {$vn > $n} { # Need to truncate the list set value [lrange $value 0 $n-1] } set convtype -$::binary::convtype($convtype) foreach v $value { set bitoffset [pack result $prefix$v $convtype $size $bitoffset] } # Now pad out with zeros to the end of the current byte if {$bitoffset % 8} { set bitoffset [pack result 0 $convtype $(8 - $bitoffset % 8) $bitoffset] } } } } return $result } proc "binary scan" {value formatString {args varName}} { # Pops the next arg from the front of the list and returns it. # Throws an error if no more args set bitoffset 0 set count 0 # This RE is too unreliable... foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] { set rembytes $([string bytelength $value] - $bitoffset / 8) switch -exact -- $t { a - A { if {$n eq "*"} { set n $rembytes } elseif {$n eq ""} { set n 1 } if {$n > $rembytes} { break } set var [binary::nextarg varName] set result [unpack $value -str $bitoffset $($n * 8)] incr bitoffset $([string bytelength $result] * 8) if {$t eq "A"} { set result [string trimright $result] } } x { # Skip bytes if {$n eq "*"} { set n $rembytes } elseif {$n eq ""} { set n 1 } if {$n > $rembytes} { set n $rembytes } incr bitoffset $($n * 8) continue } X { # Back up bytes if {$n eq "*"} { set bitoffset 0 continue } if {$n eq ""} { set n 1 } if {$n * 8 > $bitoffset} { set bitoffset 0 continue } incr bitoffset -$($n * 8) continue } @ { if {$n eq ""} { return -code error {missing count for "@" field specifier} } if {$n eq "*" || $n > $rembytes + $bitoffset / 8} { incr bitoffset $($rembytes * 8) } elseif {$n < 0} { set bitoffset 0 } else { set bitoffset $($n * 8) } continue } default { if {![info exists ::binary::scalarinfo($t)]} { return -code error "bad field specifier \"$t\"" } # A scalar (integer or float) type lassign $::binary::scalarinfo($t) type convtype size prefix set var [binary::nextarg varName] if {$n eq "*"} { set n $($rembytes * 8 / $size) } else { if {$n eq ""} { set n 1 } } if {$n * $size > $rembytes * 8} { break } if {$type in {hex bin}} { set u u } set convtype -$u$::binary::convtype($convtype) set result {} loop i 0 $n { set v [unpack $value $convtype $bitoffset $size] if {$type in {bin hex}} { append result [lindex {0 1 2 3 4 5 6 7 8 9 a b c d e f} $v] } else { lappend result $v } incr bitoffset $size } # Now skip to the end of the current byte if {$bitoffset % 8} { incr bitoffset $(8 - ($bitoffset % 8)) } } } uplevel 1 [list set $var $result] incr count } return $count } # Pops the next arg from the front of the list and returns it. # Throws an error if no more args proc binary::nextarg {&arglist} { if {[llength $arglist] == 0} { return -level 2 -code error "not enough arguments for all format specifiers" } set arglist [lassign $arglist arg] return $arg } set binary::scalarinfo { c {int be 8} s {int le 16} t {int host 16} S {int be 16} i {int le 32} I {int be 32} n {int host 32} w {int le 64} W {int be 64} m {int host 64} h {hex le 4 0x} H {hex be 4 0x} b {bin le 1} B {bin be 1} r {float fle 32} R {float fbe 32} f {float fhost 32} q {float fle 64} Q {float fbe 64} d {float fhost 64} } set binary::convtype { be intbe le intle fbe floatbe fle floatle } if {$::tcl_platform(byteOrder) eq "bigEndian"} { array set binary::convtype {host intbe fhost floatbe} } else { array set binary::convtype {host intle fhost floatle} } openocd-0.9.0/jimtcl/README0000644000175000017500000002505412315602574012245 00000000000000The Jim Interpreter A small-footprint implementation of the Tcl programming language. -------------------------------------------------------------------------------- WHAT IS JIM? -------------------------------------------------------------------------------- Jim is a small footprint implementation of the Tcl programming language written from scratch. Currently Jim Tcl is very feature complete with an extensive test suite (see the tests directory). There are some Tcl commands and features which are not implemented (and likely never will be), including namespaces, traces and Tk. However Jim Tcl offers a number of both Tcl8.5 and Tcl8.6 features ({*}, dict, lassign, tailcall and optional UTF-8 support) and some unique features. These unique features include [lambda] with garbage collection, a general GC/references system, arrays as syntax sugar for [dict]tionaries, object-based I/O and more. Other common features of the Tcl programming language are present, like the "everything is a string" behaviour, implemented internally as dual ported objects to ensure that the execution time does not reflect the semantic of the language :) -------------------------------------------------------------------------------- WHEN JIM CAN BE USEFUL? -------------------------------------------------------------------------------- 1) If you are writing an application, and want to make it scriptable, with Jim you have a way to do it that does not require to link your application with a big system. You can include the Jim source directly in your project and use the Jim API to write the glue code that makes your application scriptable in Jim, with the following advantages: - Jim is not the next "little language", but it's a Tcl implementation. You can reuse your knowledge if you already Tcl skills, or enjoy the availability of documentation, books, web resources, ... (for example check my online Tcl book at http://www.invece.org/tclwise) - Jim is simple, 14k lines of core code. If you want to adapt it you can hack the source code to meet the needs of your application. It makes you able to have scripting for default, and avoid external dependences. Having scripting support *inside*, and in a way that a given version of your program always gets shipped a given version of Jim, you can write part of your application in Jim itself. Like it happens for Emacs/Elisp, or Gimp/Scheme, both this applications have the interpreter inside. - Jim is Tcl, and Tcl looks like a configuration file if you want. So if you use Jim you have also a flexible syntax for your config file. This is a valid Tcl script: set MyFeature on ifssl { set SslPort 45000 use compression } It looks like a configuration file, but if you implement the [ifssl] and [use] commands, it's a valid Tcl script. - Tcl scales with the user. Not all know it, but Tcl is so powerful that you can reprogram the language in itself. Jim support this features of the Tcl programming language. You can write new control structures, use the flexible data types it offers (Lists are a central data structure, with Dictionaries that are also lists). Still Tcl is simpler for the casual programmer, especially if compared to other languages offering small footprint implementations (like Scheme and FORTH). - Because of the Tcl semantic (pass by value, everything is a command since there are no reserved words), there is a nice API to glue your application with Jim. See under the Jim Tcl manual for more detail. - Jim is supported. If you need commercial software, contact the original author at 'antirez@gmail.com' or the current maintainer at 'steveb@workware.net.au'. 2) The other "field" where Jim can be useful is obviously embedded systems. 3) We are working to make Jim as feature-complete as possible, thanks to dynamically loaded extensions it may stay as little as it is today but able to do interesting things for you. So it's not excluded that in the future Jim will be an option as general purpose language. But don't mind, for this there is already the mainstream Tcl implementation ;). -------------------------------------------------------------------------------- HOW BIG IS IT? -------------------------------------------------------------------------------- Jim with the default extensions configured and compiled with -Os is about 130k. Without any extensions, it is about 85k. -------------------------------------------------------------------------------- HOW FAST IS IT? -------------------------------------------------------------------------------- Jim is in most code faster than Tcl7.6p2 (latest 7.x version), and slower than Tcl 8.4.x. You can expect pretty decent performance for such a little interpreter. If you want a more precise measure, there is 'bench.tcl' inside this distribution that will run both under Jim and Tcl, so just execute it with both the interpreters and see what you get :) -------------------------------------------------------------------------------- HOW TO COMPILE -------------------------------------------------------------------------------- Jim was tested under Linux, FreeBSD, MacosX, eCos, QNX, Windows XP (mingw, MVC). To compile jim itself try: ./configure make -------------------------------------------------------------------------------- EXTENSIONS -------------------------------------------------------------------------------- Many optional extensions are included. Some are C extensions and others are pure Tcl. Form more information, try: ./configure --help -------------------------------------------------------------------------------- HOW TO EMBED JIM INTO APPLICATIONS -------------------------------------------------------------------------------- See the "examples.api" directory -------------------------------------------------------------------------------- HOW TO WRITE EXTENSIONS FOR JIM -------------------------------------------------------------------------------- See the extensions shipped with Jim, jim-readline.c, jim-clock.c, glob.tcl and oo.tcl -------------------------------------------------------------------------------- COPYRIGHT and LICENSE -------------------------------------------------------------------------------- Unless explicitly stated, all files within Jim repository are released under following license: /* Jim - A small embeddable Tcl interpreter * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze * Copyright 2005 patthoyts - Pat Thoyts * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein * Copyright 2008 Steve Bennett * Copyright 2009 Nico Coesel * Copyright 2009 Zachary T Welch zw@superlucidity.net * Copyright 2009 David Brownell * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. */ -------------------------------------------------------------------------------- HISTORY -------------------------------------------------------------------------------- "first Jim goal: to vent my need to hack on Tcl." And actually this is exactly why I started Jim, in the first days of Jenuary 2005. After a month of hacking Jim was able to run simple scripts, now, after two months it started to be clear to me that it was not just the next toy to throw away but something that may evolve into a real interpreter. In the same time Pat Thoyts and Clemens Hintze started to contribute code, so that the development of new core commands was faster, and also more people hacking on the same code had as result fixes in the API, C macros, and so on. Currently we are at the point that the core interpreter is almost finished and it is entering the Beta stage. There is to add some other core command, to do a code review to ensure quality of all the parts and to write documentation. We already started to work on extensions like OOP, event loop, I/O, networking, regexp. Some extensions are already ready for prime time, like the Sqlite extension and the ANSI I/O. ------------------------------------------------------------------------------ Thanks to... ------------------------------------------------------------------------------ - First of all, thanks to every guy that are listed in the AUTHORS file, that directly helped with code and ideas. Also check the ChangeLog file for additional credits about patches or bug reports. - Elisa Manara that helped me to select this ill conceived name for an interpreter. - Many people on the Tclers Chat that helped me to explore issues about the use and the implementation of the Tcl programming language. - David Welton for the tech info sharing and our chats about programming languages design and the ability of software to "scale down". - Martin S. Weber for the great help with Solaris issues, debugging of problems with [load] on this arch, 64bit tests. - The authors of "valgrind", for this wonderful tool, that helped me a lot to fix bugs in minutes instead of hours. ---- Enjoy! Salvatore Sanfilippo 10 Mar 2005 openocd-0.9.0/jimtcl/nshelper.tcl0000644000175000017500000000673012516456444013717 00000000000000# Implements script-based implementations of various namespace # subcommands # # (c) 2011 Steve Bennett # proc {namespace delete} {args} { foreach name $args { if {$name ni {:: ""}} { set name [uplevel 1 [list ::namespace canon $name]] foreach i [info commands ${name}::*] { rename $i "" } uplevel #0 [list unset {*}[info globals ${name}::*]] } } } proc {namespace origin} {name} { set nscanon [uplevel 1 [list ::namespace canon $name]] if {[exists -alias $nscanon]} { tailcall {namespace origin} [info alias $nscanon] } if {[exists -command $nscanon]} { return ::$nscanon } if {[exists -command $name]} { return ::$name } return -code error "invalid command name \"$name\"" } proc {namespace which} {{type -command} name} { set nsname ::[uplevel 1 [list ::namespace canon $name]] if {$type eq "-variable"} { return $nsname } if {$type eq "-command"} { if {[exists -command $nsname]} { return $nsname } elseif {[exists -command ::$name]} { return ::$name } return "" } return -code error {wrong # args: should be "namespace which ?-command? ?-variable? name"} } proc {namespace code} {arg} { if {[string first "::namespace inscope " $arg] == 0} { # Already scoped return $arg } list ::namespace inscope [uplevel 1 ::namespace current] $arg } proc {namespace inscope} {name arg args} { tailcall namespace eval $name $arg $args } proc {namespace import} {args} { set current [uplevel 1 ::namespace canon] foreach pattern $args { foreach cmd [info commands [namespace canon $current $pattern]] { if {[namespace qualifiers $cmd] eq $current} { return -code error "import pattern \"$pattern\" tries to import from namespace \"$current\" into itself" } # What if this alias would create a loop? # follow the target alias chain to see if we are creating a loop set newcmd ${current}::[namespace tail $cmd] set alias $cmd while {[exists -alias $alias]} { set alias [info alias $alias] if {$alias eq $newcmd} { return -code error "import pattern \"$pattern\" would create a loop" } } alias $newcmd $cmd } } } # namespace-aware info commands: procs, channels, globals, locals, vars proc {namespace info} {cmd {pattern *}} { set current [uplevel 1 ::namespace canon] # Now we may need to strip $pattern if {[string first :: $pattern] == 0} { set global 1 set prefix :: } else { set global 0 set clen [string length $current] incr clen 2 } set fqp [namespace canon $current $pattern] switch -glob -- $cmd { co* - p* { if {$global} { set result [info $cmd $fqp] } else { # Add commands in the current namespace set r {} foreach c [info $cmd $fqp] { dict set r [string range $c $clen end] 1 } if {[string match co* $cmd]} { # Now in the global namespace foreach c [info -nons commands $pattern] { dict set r $c 1 } } set result [dict keys $r] } } ch* { set result [info channels $pattern] } v* { #puts "uplevel #0 info gvars $fqp" set result [uplevel #0 info -nons vars $fqp] } g* { set result [info globals $fqp] } l* { set result [uplevel 1 info -nons locals $pattern] } } if {$global} { set result [lmap p $result { string cat $prefix $p }] } return $result } proc {namespace upvar} {ns args} { set nscanon ::[uplevel 1 [list ::namespace canon $ns]] set script [list upvar 0] foreach {other local} $args { lappend script ${nscanon}::$other $local } tailcall {*}$script } openocd-0.9.0/jimtcl/jim-readdir.c0000644000175000017500000001020712516456444013720 00000000000000/* * Tcl readdir command. * * (c) 2008 Steve Bennett * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. * * Based on original work by: *----------------------------------------------------------------------------- * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies. Karl Lehenbauer and * Mark Diekhans make no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. *----------------------------------------------------------------------------- */ #include #include #include #include #include #ifdef HAVE_DIRENT_H #include #endif /* *----------------------------------------------------------------------------- * * Jim_ReaddirCmd -- * Implements the rename TCL command: * readdir ?-nocomplain? dirPath * * Results: * Standard TCL result. *----------------------------------------------------------------------------- */ int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *dirPath; DIR *dirPtr; struct dirent *entryPtr; int nocomplain = 0; if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) { nocomplain = 1; } if (argc != 2 && !nocomplain) { Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath"); return JIM_ERR; } dirPath = Jim_String(argv[1 + nocomplain]); dirPtr = opendir(dirPath); if (dirPtr == NULL) { if (nocomplain) { return JIM_OK; } Jim_SetResultString(interp, strerror(errno), -1); return JIM_ERR; } else { Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); while ((entryPtr = readdir(dirPtr)) != NULL) { if (entryPtr->d_name[0] == '.') { if (entryPtr->d_name[1] == '\0') { continue; } if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) continue; } Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); } closedir(dirPtr); Jim_SetResult(interp, listObj); return JIM_OK; } } int Jim_readdirInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) return JIM_ERR; Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL); return JIM_OK; } openocd-0.9.0/jimtcl/parse-unidata.tcl0000644000175000017500000000221312315602574014616 00000000000000#!/usr/bin/env tclsh # Generate UTF-8 case mapping tables # # (c) 2010 Steve Bennett # # See LICENCE for licence details. #/ # Parse the unicode data from: http://unicode.org/Public/UNIDATA/UnicodeData.txt # to generate case mapping tables set map(lower) {} set map(upper) {} set map(title) {} set f [open [lindex $argv 0]] while {[gets $f buf] >= 0} { set title "" set lower "" set upper "" foreach {code name class x x x x x x x x x upper lower title} [split $buf ";"] break set codex [string tolower 0x$code] if {$codex <= 0x7f} { continue } if {$codex > 0xffff} { break } if {![string match L* $class]} { continue } if {$upper ne ""} { lappend map(upper) $codex [string tolower 0x$upper] } if {$lower ne ""} { lappend map(lower) $codex [string tolower 0x$lower] } if {$title ne "" && $title ne $upper} { if {$title eq $code} { set title 0 } lappend map(title) $codex [string tolower 0x$title] } } close $f foreach type {upper lower title} { puts "static const struct casemap unicode_case_mapping_$type\[\] = \{" foreach {code alt} $map($type) { puts "\t{ $code, $alt }," } puts "\};\n" } openocd-0.9.0/jimtcl/configure0000755000175000017500000000016612315602574013271 00000000000000#!/bin/sh dir="`dirname "$0"`/autosetup" WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" openocd-0.9.0/jimtcl/README.sqlite0000644000175000017500000001332212315602574013540 00000000000000Jim Sqlite extension documentation. Copyright 2005 Salvatore Sanfilippo Overview ~~~~~~~~ The Sqlite extension makes possible to work with sqlite (http://www.sqlite.org) databases from Jim. SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine. This means it is perfect for embedded systems, and for stand-alone applications that need the power of SQL without to use an external server like Mysql. Basic usage ~~~~~~~~~~~ The Sqlite extension exports an Object Based interface for databases. In order to open a database use: set f [sqlite3.open dbname] The [sqlite3.open] command returns a db handle, that is a command name that can be used to perform operations on the database. A real example: . set db [sqlite3.open test.db] sqlite.handle0 . $db query "SELECT * from tbl1" {one hello! two 10} {one goodbye two 20} In the second line the handle is used as a command name, followed by the 'method' or 'subcommand' ("query" in the example), and the arguments. The query method ~~~~~~~~~~~~~~~~ The query method has the following signature: $db query SqlQuery ?args? The sql query may contain occurrences of "%s" that are substituted in the actual query with the following arguments, quoted in order to make sure that the query is correct even if this arguments contain "'" characters. So for example it is possible to write: . $db query "SELECT * from tbl1 WHERE one='%s'" hello! {one hello! two 10} Instead of hello! it is possible to use a string with embedded "'": . $db query "SELECT * from tbl1 WHERE one='%s'" a'b (no matches - the empty list is returned) This does not work instead using the Tcl variable expansion in the string: . $db query "SELECT * from tbl1 WHERE one='$foo'" Runtime error, file "?", line 1: near "b": syntax error In order to obtain an actual '%' character in the query, there is just to use two, like in "foo %% bar". This is the same as the [format] argument. Specification of query results ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In one of the above examples, the following query was used: . $db query "SELECT * from tbl1" {one hello! two 10} {one goodbye two 20} As you can see the result of a query is a list of lists. Every element of the list represents a row, as a list of key/value pairs, so actually every row is a Jim dictionary. The following example and generated output show how to take advantage of this representation: . set res [$db query "SELECT * from tbl1"] {one hello! two 10} {one goodbye two 20} . foreach row $res {puts "One: $row(one), Two: $row(two)"} One: hello!, Two: 10 One: goodbye, Two: 20 To access every row sequentially is very simple, and field of a row can be accessed using the $row(field) syntax. The close method ~~~~~~~~~~~~~~~~ In order to close the db, use the 'close' method that will have as side effect to close the db and to remove the command associated with the db. Just use: $db close Handling NULL values ~~~~~~~~~~~~~~~~~~~~ In the SQL language there is a special value NULL that is not the empty string, so how to represent it in a typeless language like Tcl? For default this extension will use the empty string, but it is possible to specify a different string for the NULL value. In the above example there were two rows in the 'tbl1' table. Now we can add using the "sqlite" command line client another one with a NULL value: sqlite> INSERT INTO tbl1 VALUES(NULL,30); sqlite> .exit That's what the sqlite extension will return for default: . $db query "SELECT * from tbl1" {one hello! two 10} {one goodbye two 20} {one {} two 30} As you can see in the last row, the NULL is represented as {}, that's the empty string. Using the -null option of the 'query' command we can change this default, and tell the sqlite extension to represent the NULL value as a different string: . $db query -null <> "SELECT * from tbl1" {one hello! two 10} {one goodbye two 20} {one <> two 30} This way if the emtpy string has some semantical value for your dataset you can change it. Finding the ID of the last inserted row ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is as simple as: . $db lastid 10 Number of rows changed by the most recent query ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is also very simple, there is just to use the 'changes' method without arugments. . $db changes 5 Note that if you drop an entire table the number of changes will be reported as zero, because of details of the sqlite implementation. That's all, Enjoy! Salvatore Sanfilippo p.s. this extension is just the work of some hour thanks to the cool clean C API that sqlite exports. Thanks to the author of sqlite for this great work. In memory databases ~~~~~~~~~~~~~~~~~~~ SQLite is able to create in-memory databases instead to use files. This is of course faster and does not need the ability to write to the filesystem. Of course this databases are only useful for temp data. In-memory DBs are used just like regular databases, just the name used to open the database is :memory:. That's an example that does not use the filesystem at all to create and work with the db. package require sqlite3 set db [sqlite3.open :memory:] $db query {CREATE TABLE plays (id, author, title)} $db query {INSERT INTO plays (id, author, title) VALUES (1, 'Goethe', 'Faust');} $db query {INSERT INTO plays (id, author, title) VALUES (2, 'Shakespeare', 'Hamlet');} $db query {INSERT INTO plays (id, author, title) VALUES (3, 'Sophocles', 'Oedipus Rex');} set res [$db query "SELECT * FROM plays"] $db close foreach r $res {puts $r(author)} Of course once the Jim process is destroyed the database will no longer exists. openocd-0.9.0/jimtcl/make-index0000755000175000017500000000306012315602574013326 00000000000000#!/usr/bin/env tclsh # vim:se syn=tcl: set filename [lindex $argv 0] set f [open $filename] # Read the file looking for command definitions set lines {} set commands {} array set cdict {} set c 0 while {[gets $f buf] >= 0} { if {[string match "~~*" $buf]} { if {[string match "*: *" $prev]} { incr c set target cmd_$c set lines [linsert $lines end-1 "\[\[$target\]\]"] set prevlist [split $prev ":, "] } else { set target _[string map {:: _} $prev] set prevlist [list $prev] } foreach cmd $prevlist { set cmd [string trim $cmd] if {[regexp {^[a-z.:]+$} $cmd]} { lappend commands [list $cmd $target] set cdict($cmd) $target } } } lappend lines $buf set prev $buf } close $f # Build the command index in the list: $index lappend index {[frame="none",grid="none"]} lappend index {|=========================} set i 0 set row {} foreach command [lsort $commands] { lassign $command cmd target append row "|<<$target,*`$cmd`*>> " incr i if {$i % 8 == 0} { lappend index $row set row {} } } while {$i % 8 != 0} { incr i append row "| " } lappend index $row lappend index {|=========================} # Map all `cmd` to <<$target,`cmd`>> set mapping {} foreach c [array names cdict] { lappend mapping `$c` <<$cdict($c),*`$c`*>> lappend mapping "`$c " "<<$cdict($c),*`$c`*>> `" } # And the command index lappend mapping @INSERTINDEX@ [join $index \n] # Output the result foreach line $lines { if {[string first ` $line] >= 0 || [string first @ $line] >= 0} { puts [string map $mapping $line] } else { puts $line } } openocd-0.9.0/jimtcl/jim-config.h.in0000644000175000017500000000006712315602574014162 00000000000000/* Public autoconf settings */ @DEFINE_HAVE_LONG_LONG@ openocd-0.9.0/jimtcl/auto.def0000644000175000017500000002772212516456443013026 00000000000000# vim:se syn=tcl: # define JIM_VERSION 76 # Note: modules which support options *must* be included before 'options' use cc cc-shared cc-db cc-lib use local options { utf8 => "include support for utf8-encoded strings" lineedit=1 => "disable line editing" references=1 => "disable support for references" math => "include support for math functions" ipv6 => "include ipv6 support in the aio extension" maintainer => {enable the [debug] command and JimPanic} full => "Enable some optional features: ipv6, math, utf8, binary, oo, tree" with-jim-shared shared => "build a shared library instead of a static library" jim-regexp=1 => "prefer POSIX regex if over the the built-in (Tcl-compatible) regex" docs=1 => "don't build or install the documentation" random-hash => "randomise hash tables. more secure but hash table results are not predicable" with-jim-ext: {with-ext:"ext1 ext2 ..."} => { Specify additional jim extensions to include. These are enabled by default: aio - ANSI I/O, including open and socket eventloop - after, vwait, update array - Tcl-compatible array command clock - Tcl-compatible clock command exec - Tcl-compatible exec command file - Tcl-compatible file command glob - Tcl-compatible glob command history - Tcl access to interactive history readdir - Required for glob package - Package management with the package command load - Load binary extensions at runtime with load or package posix - Posix APIs including os.fork, os.wait, pid regexp - Tcl-compatible regexp, regsub commands signal - Signal handling stdlib - Built-in commands including lassign, lambda, alias syslog - System logging with syslog tclcompat - Tcl compatible read, gets, puts, parray, case, ... namespace - Tcl compatible namespace support These are disabled by default: oo - Jim OO extension tree - OO tree structure, similar to tcllib ::struct::tree binary - Tcl-compatible 'binary' command readline - Interface to libreadline rlprompt - Tcl wrapper around the readline extension mk - Interface to Metakit tclprefix - Support for the tcl::prefix command sqlite3 - Interface to sqlite3 win32 - Interface to win32 } with-out-jim-ext: {without-ext:"default|ext1 ext2 ..."} => { Specify jim extensions to exclude. If 'default' is given, the default extensions will not be added. } with-jim-extmod: {with-mod:"ext1 ext2 ..."} => { Specify jim extensions to build as separate modules (either C or Tcl). Note that not all extensions can be built as loadable modules. } # To help out openocd with automake install-jim=1 } # Save the user-specified LIBS # We add detected libs to LDLIBS explicitly set LIBS [get-define LIBS] cc-check-types "long long" define CCOPTS "" define CXXOPTS "" if {[cctest -cflags -fno-unwind-tables]} { define-append CCOPTS -fno-unwind-tables } if {[cctest -cflags -fno-asynchronous-unwind-tables]} { define-append CCOPTS -fno-asynchronous-unwind-tables } cc-check-includes sys/time.h sys/socket.h netinet/in.h arpa/inet.h netdb.h cc-check-includes sys/un.h dlfcn.h unistd.h dirent.h crt_externs.h define LDLIBS "" # Haiku needs -lnetwork, Solaris needs -lnsl if {[cc-check-function-in-lib inet_ntop {nsl network}]} { # This does nothing if no libs are needed cc-with [list -libs [get-define lib_inet_ntop]] define-append LDLIBS [get-define lib_inet_ntop] } # Solaris needs -lsocket, Windows needs -lwsock32 if {[cc-check-function-in-lib socket socket]} { define-append LDLIBS [get-define lib_socket] } cc-check-functions ualarm lstat fork vfork system select execvpe cc-check-functions backtrace geteuid mkstemp realpath strptime isatty cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes cc-check-functions shutdown socketpair isinf isnan link symlink if {[cc-check-functions sysinfo]} { cc-with {-includes sys/sysinfo.h} { cc-check-members "struct sysinfo.uptime" } } cc-check-lfs cc-check-functions fseeko ftello define TCL_LIBRARY [get-define prefix]/lib/jim lassign [split [get-define host] -] host_cpu host_vendor host_os # Scrub revision from the host_os regsub -all {[0-9.]} $host_os {} host_os switch -glob -- $host_os { mingw* { # We provide our own implementation of dlopen for mingw32 define-feature dlopen-compat define-feature winconsole define TCL_PLATFORM_OS $host_os define TCL_PLATFORM_PLATFORM windows define TCL_PLATFORM_PATH_SEPARATOR {;} } default { # Note that cygwin is considered a unix platform define TCL_PLATFORM_OS $host_os define TCL_PLATFORM_PLATFORM unix define TCL_PLATFORM_PATH_SEPARATOR : } } # Find some tools cc-check-tools ar ranlib strip define tclsh [info nameofexecutable] if {![cc-check-functions _NSGetEnviron]} { msg-checking "Checking environ declared in unistd.h..." if {[cctest -cflags -D_GNU_SOURCE -includes unistd.h -code {char **ep = environ;}]} { define NO_ENVIRON_EXTERN msg-result "yes" } else { msg-result "no" } } # Windows has a mkdir with no permission arg cc-check-includes sys/types.h sys/stat.h msg-checking "Checking for mkdir with one arg..." if {[cctest -includes {sys/types.h sys/stat.h} -code {mkdir("/dummy");}]} { define HAVE_MKDIR_ONE_ARG msg-result yes } else { msg-result no } set extra_objs {} set jimregexp 0 if {[opt-bool utf8 full]} { msg-result "Enabling UTF-8" define JIM_UTF8 incr jimregexp } else { define JIM_UTF8 0 } if {[opt-bool maintainer]} { msg-result "Enabling maintainer settings" define JIM_MAINTAINER } if {[opt-bool math full]} { msg-result "Enabling math functions" define JIM_MATH_FUNCTIONS cc-check-function-in-lib sin m define-append LDLIBS [get-define lib_sin] } if {[opt-bool ipv6 full]} { msg-result "Enabling IPv6" define JIM_IPV6 } if {[opt-bool lineedit full]} { if {([cc-check-includes termios.h] && [have-feature isatty]) || [have-feature winconsole]} { msg-result "Enabling line editing" define USE_LINENOISE lappend extra_objs linenoise.o } } if {[opt-bool references]} { msg-result "Enabling references" define JIM_REFERENCES } if {[opt-bool shared with-jim-shared]} { msg-result "Building shared library" } else { msg-result "Building static library" define JIM_STATICLIB } define LIBSOEXT [format [get-define SH_SOEXTVER] [format %.2f [expr {[get-define JIM_VERSION] / 100.0}]]] define JIM_INSTALL [opt-bool install-jim] define JIM_DOCS [opt-bool docs] define JIM_RANDOMISE_HASH [opt-bool random-hash] # Attributes of the extensions # tcl=Pure Tcl extension # static=Can't be built as a module # optional=Not selected by default # cpp=Is a C++ extension global extdb dict set extdb attrs { aio { static } array {} binary { tcl } clock {} eventloop { static } exec { static } file {} glob { tcl } history {} load { static } mk { cpp optional } namespace { static } nshelper { tcl optional } oo { tcl } pack {} package { static } posix {} readdir {} readline { optional } regexp {} rlprompt { tcl optional } sdl { optional } signal { static } sqlite3 { optional } stdlib { tcl static } syslog {} tclcompat { tcl static } tclprefix {} tree { tcl } win32 { optional } } # Additional information about certain extensions # dep=list of extensions which are required for this extension # check=[expr] expression to evaluate to determine if the extension can be used # libdep=list of 'define' symbols for dependent libraries dict set extdb info { binary { dep pack } exec { check {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]} } glob { dep readdir } load { check {[have-feature dlopen-compat] || [cc-check-function-in-lib dlopen dl]} libdep lib_dlopen } mk { check {[check-metakit]} libdep lib_mk } namespace { dep nshelper } posix { check {[have-feature waitpid]} } readdir { check {[have-feature opendir]} } readline { check {[cc-check-function-in-lib readline readline]} libdep lib_readline} rlprompt { dep readline } tree { dep oo } sdl { check {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]} libdep {lib_SDL_SetVideoMode lib_rectangleRGBA} } signal { check {[have-feature sigaction] && [have-feature vfork]} } sqlite3 { check {[cc-check-function-in-lib sqlite3_prepare_v2 sqlite3]} libdep lib_sqlite3_prepare_v2 } syslog { check {[have-feature syslog]} } tree { dep oo } win32 { check {[have-feature windows]} } } # autosetup cc-check-function-in-library can't handle C++ libraries proc check-metakit {} { set found 0 msg-checking "Checking for Metakit..." cc-with {-lang c++} { if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} { msg-result ok define lib_mk -lmk4 incr found } else { msg-result "not found" } } return $found } # Set up the withinfo array based on what the user selected global withinfo set withinfo(without) [join [opt-val {without-ext with-out-jim-ext}]] set withinfo(ext) [join [opt-val {with-ext with-jim-ext}]] set withinfo(mod) [join [opt-val {with-mod with-jim-extmod}]] set withinfo(nodefault) 0 if {$withinfo(without) eq "default"} { set withinfo(without) {} set withinfo(nodefault) 1 } # Now go check everything - see autosetup/local.tcl array set extinfo [check-extensions] # Now special checks if {[have-feature windows]} { lappend extra_objs jim-win32compat.o if {[llength $extinfo(module-c)] && [get-define JIM_STATICLIB]} { user-error "cygwin/mingw require --shared for dynamic modules" } } if {[ext-get-status regexp] in {y m}} { if {![have-feature regcomp]} { # No regcomp means we need to use the built-in version incr jimregexp } } if {$jimregexp || [opt-bool jim-regexp]} { msg-result "Using built-in regexp" define JIM_REGEXP # If the built-in regexp overrides the system regcomp, etc. # jim must be built shared so that the correct symbols are found if {[ext-get-status regexp] eq "m" && [get-define JIM_STATICLIB] && [have-feature regcomp]} { user-error "Must use --shared with regexp module and built-in regexp" } } if {[ext-get-status load] eq "n"} { # If we don't have load, no need to support shared objects define SH_LINKFLAGS "" } msg-result "Jim static extensions: [lsort [concat $extinfo(static-tcl) $extinfo(static-c)]]" if {[llength $extinfo(module-tcl)]} { msg-result "Jim Tcl extensions: [lsort $extinfo(module-tcl)]" } if {[llength $extinfo(module-c)]} { msg-result "Jim dynamic extensions: [lsort $extinfo(module-c)]" } define STATIC_EXTS [concat $extinfo(static-c) $extinfo(static-tcl)] define C_EXT_OBJS [prefix jim- [suffix .o $extinfo(static-c)]] define TCL_EXT_OBJS [suffix .o $extinfo(static-tcl)] define C_EXT_SHOBJS [suffix .so $extinfo(module-c)] define TCL_EXTS [suffix .tcl $extinfo(module-tcl)] define EXTRA_OBJS $extra_objs # Restore the user-specified LIBS define LIBS $LIBS make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -bare JIM_VERSION -none * make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_* _FILE_OFFSET*} make-template Makefile.in make-template build-jim-ext.in catch {exec chmod +x build-jim-ext} openocd-0.9.0/jimtcl/Tcl_shipped.html0000644000175000017500000125266712516456443014533 00000000000000 Jim Tcl(n)

SYNOPSIS

cc <source> -ljim

or

jimsh [<scriptfile>]
jimsh -e '<immediate-script>'
jimsh --version

INTRODUCTION

Jim Tcl is a small footprint reimplementation of the Tcl scripting language. The core language engine is compatible with Tcl 8.5+, while implementing a significant subset of the Tcl 8.6 command set, plus additional features available only in Jim Tcl.

Some notable differences with Tcl 8.5/8.6 are:

  1. Object-based I/O (aio), but with a Tcl-compatibility layer

  2. I/O: Support for sockets and pipes including udp, unix domain sockets and IPv6

  3. Integers are 64bit

  4. Support for references (ref/getref/setref) and garbage collection

  5. Builtin dictionary type (dict) with some limitations compared to Tcl 8.6

  6. env command to access environment variables

  7. Operating system features: os.fork, os.wait, os.uptime, signal, alarm, sleep

  8. Much better error reporting. info stacktrace as a replacement for $errorInfo, $errorCode

  9. Support for "static" variables in procedures

  10. Threads and coroutines are not supported

  11. Command and variable traces are not supported

  12. Built-in command line editing

  13. Expression shorthand syntax: $(…)

  14. Modular build allows many features to be omitted or built as dynamic, loadable modules

  15. Highly suitable for use in an embedded environment

  16. Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets

RECENT CHANGES

Changes between 0.75 and 0.76

  1. Add support for file link

  2. glob now supports the --tails option

  3. Add support for string cat

  4. Allow info source to add source info

Changes between 0.74 and 0.75

  1. binary, pack and unpack now support floating point

  2. file copy -force handles source and target as the same file

  3. format now supports %b for binary conversion

  4. lsort now supports -unique and -real

  5. Add support for half-close with aio close ?r|w?

  6. Add socket pair for a bidirectional pipe

  7. Add --random-hash to randomise hash tables for greater security

  8. dict now supports for, values, incr, append, lappend, update, info and replace

  9. file stat no longer requires the variable name

Changes between 0.73 and 0.74

  1. Numbers with leading zeros are treated as decimal, not octal

  2. Add aio isatty

  3. Add LFS (64 bit) support for aio seek, aio tell, aio copyto, file copy

  4. string compare and string equal now support -length

  5. glob now supports -directory

Changes between 0.72 and 0.73

  1. Built-in regexp now support non-capturing parentheses: (?:…)

  2. Add string replace

  3. Add string totitle

  4. Add info statics

  5. Add build-jim-ext for easy separate building of loadable modules (extensions)

  6. local now works with any command, not just procs

  7. Add info alias to access the target of an alias

  8. UTF-8 encoding past the basic multilingual plane (BMP) is supported

  9. Add tcl::prefix

  10. Add history

  11. Most extensions are now enabled by default

  12. Add support for namespaces and the namespace command

  13. Add apply

Changes between 0.71 and 0.72

  1. procs now allow args and optional parameters in any position

  2. Add Tcl-compatible expr functions, rand(), srand() and pow()

  3. Add support for the -force option to file delete

  4. Better diagnostics when source fails to load a script with a missing quote or bracket

  5. New tcl_platform(pathSeparator)

  6. Add support settings the modification time with file mtime

  7. exec is now fully supported on win32 (mingw32)

  8. file join, pwd, glob etc. now work for mingw32

  9. Line editing is now supported for the win32 console (mingw32)

  10. Add aio listen command

Changes between 0.70 and 0.71

  1. Allow args to be renamed in procs

  2. Add $(…) shorthand syntax for expressions

  3. Add automatic reference variables in procs with &var syntax

  4. Support jimsh --version

  5. Additional variables in tcl_platform()

  6. local procs now push existing commands and upcall can call them

  7. Add loop command (TclX compatible)

  8. Add aio buffering command

  9. info complete can now return the missing character

  10. binary format and binary scan are now (optionally) supported

  11. Add string byterange

  12. Built-in regexp now support non-greedy repetition (*?, +?, ??)

TCL INTRODUCTION

Tcl stands for tool command language and is pronounced tickle. It is actually two things: a language and a library.

First, Tcl is a simple textual language, intended primarily for issuing commands to interactive programs such as text editors, debuggers, illustrators, and shells. It has a simple syntax and is also programmable, so Tcl users can write command procedures to provide more powerful commands than those in the built-in set.

Second, Tcl is a library package that can be embedded in application programs. The Tcl library consists of a parser for the Tcl language, routines to implement the Tcl built-in commands, and procedures that allow each application to extend Tcl with additional commands specific to that application. The application program generates Tcl commands and passes them to the Tcl parser for execution. Commands may be generated by reading characters from an input source, or by associating command strings with elements of the application’s user interface, such as menu entries, buttons, or keystrokes.

When the Tcl library receives commands it parses them into component fields and executes built-in commands directly. For commands implemented by the application, Tcl calls back to the application to execute the commands. In many cases commands will invoke recursive invocations of the Tcl interpreter by passing in additional strings to execute (procedures, looping commands, and conditional commands all work in this way).

An application program gains three advantages by using Tcl for its command language. First, Tcl provides a standard syntax: once users know Tcl, they will be able to issue commands easily to any Tcl-based application. Second, Tcl provides programmability. All a Tcl application needs to do is to implement a few application-specific low-level commands. Tcl provides many utility commands plus a general programming interface for building up complex command procedures. By using Tcl, applications need not re-implement these features.

Third, Tcl can be used as a common language for communicating between applications. Inter-application communication is not built into the Tcl core described here, but various add-on libraries, such as the Tk toolkit, allow applications to issue commands to each other. This makes it possible for applications to work together in much more powerful ways than was previously possible.

Fourth, Jim Tcl includes a command processor, jimsh, which can be used to run standalone Tcl scripts, or to run Tcl commands interactively.

This manual page focuses primarily on the Tcl language. It describes the language syntax and the built-in commands that will be available in any application based on Tcl. The individual library procedures are described in more detail in separate manual pages, one per procedure.

JIMSH COMMAND INTERPRETER

A simple, but powerful command processor, jimsh, is part of Jim Tcl. It may be invoked in interactive mode as:

jimsh

or to process the Tcl script in a file with:

jimsh filename

It may also be invoked to execute an immediate script with:

jimsh -e "script"

Interactive Mode

Interactive mode reads Tcl commands from standard input, evaluates those commands and prints the results.

$ jimsh
Welcome to Jim version 0.73, Copyright (c) 2005-8 Salvatore Sanfilippo
. info version
0.73
. lsort [info commands p*]
package parray pid popen proc puts pwd
. foreach i {a b c} {
{> puts $i
{> }
a
b
c
. bad
invalid command name "bad"
[error] . exit
$

If jimsh is configured with line editing (it is by default) and a VT-100-compatible terminal is detected, Emacs-style line editing commands are available, including: arrow keys, ^W to erase a word, ^U to erase the line, ^R for reverse incremental search in history. Additionally, the h command may be used to display the command history.

Command line history is automatically saved and loaded from ~/.jim_history

In interactive mode, jimsh automatically runs the script ~/.jimrc at startup if it exists.

INTERPRETERS

The central data structure in Tcl is an interpreter (C type Jim_Interp). An interpreter consists of a set of command bindings, a set of variable values, and a few other miscellaneous pieces of state. Each Tcl command is interpreted in the context of a particular interpreter.

Some Tcl-based applications will maintain multiple interpreters simultaneously, each associated with a different widget or portion of the application. Interpreters are relatively lightweight structures. They can be created and deleted quickly, so application programmers should feel free to use multiple interpreters if that simplifies the application.

DATA TYPES

Tcl supports only one type of data: strings. All commands, all arguments to commands, all command results, and all variable values are strings.

Where commands require numeric arguments or return numeric results, the arguments and results are passed as strings. Many commands expect their string arguments to have certain formats, but this interpretation is up to the individual commands. For example, arguments often contain Tcl command strings, which may get executed as part of the commands. The easiest way to understand the Tcl interpreter is to remember that everything is just an operation on a string. In many cases Tcl constructs will look similar to more structured constructs from other languages. However, the Tcl constructs are not structured at all; they are just strings of characters, and this gives them a different behaviour than the structures they may look like.

Although the exact interpretation of a Tcl string depends on who is doing the interpretation, there are three common forms that strings take: commands, expressions, and lists. The major sections below discuss these three forms in more detail.

BASIC COMMAND SYNTAX

The Tcl language has syntactic similarities to both the Unix shells and Lisp. However, the interpretation of commands is different in Tcl than in either of those other two systems. A Tcl command string consists of one or more commands separated by newline characters or semi-colons. Each command consists of a collection of fields separated by white space (spaces or tabs). The first field must be the name of a command, and the additional fields, if any, are arguments that will be passed to that command. For example, the command:

set a 22

has three fields: the first, set, is the name of a Tcl command, and the last two, a and 22, will be passed as arguments to the set command. The command name may refer either to a built-in Tcl command, an application-specific command bound in with the library procedure Jim_CreateCommand, or a command procedure defined with the proc built-in command.

Arguments are passed literally as text strings. Individual commands may interpret those strings in any fashion they wish. The set command, for example, will treat its first argument as the name of a variable and its second argument as a string value to assign to that variable. For other commands arguments may be interpreted as integers, lists, file names, or Tcl commands.

Command names should normally be typed completely (e.g. no abbreviations). However, if the Tcl interpreter cannot locate a command it invokes a special command named unknown which attempts to find or create the command.

For example, at many sites unknown will search through library directories for the desired command and create it as a Tcl procedure if it is found. The unknown command often provides automatic completion of abbreviated commands, but usually only for commands that were typed interactively.

It’s probably a bad idea to use abbreviations in command scripts and other forms that will be re-used over time: changes to the command set may cause abbreviations to become ambiguous, resulting in scripts that no longer work.

COMMENTS

If the first non-blank character in a command is #, then everything from the # up through the next newline character is treated as a comment and ignored. When comments are embedded inside nested commands (e.g. fields enclosed in braces) they must have properly-matched braces (this is necessary because when Tcl parses the top-level command it doesn’t yet know that the nested field will be used as a command so it cannot process the nested comment character as a comment).

GROUPING ARGUMENTS WITH DOUBLE-QUOTES

Normally each argument field ends at the next white space, but double-quotes may be used to create arguments with embedded space.

If an argument field begins with a double-quote, then the argument isn’t terminated by white space (including newlines) or a semi-colon (see below for information on semi-colons); instead it ends at the next double-quote character. The double-quotes are not included in the resulting argument. For example, the command

set a "This is a single argument"

will pass two arguments to set: a and This is a single argument.

Within double-quotes, command substitutions, variable substitutions, and backslash substitutions still occur, as described below. If the first character of a command field is not a quote, then quotes receive no special interpretation in the parsing of that field.

GROUPING ARGUMENTS WITH BRACES

Curly braces may also be used for grouping arguments. They are similar to quotes except for two differences. First, they nest; this makes them easier to use for complicated arguments like nested Tcl command strings. Second, the substitutions described below for commands, variables, and backslashes do not occur in arguments enclosed in braces, so braces can be used to prevent substitutions where they are undesirable.

If an argument field begins with a left brace, then the argument ends at the matching right brace. Tcl will strip off the outermost layer of braces and pass the information between the braces to the command without any further modification. For example, in the command

set a {xyz a {b c d}}

the set command will receive two arguments: a and xyz a {b c d}.

When braces or quotes are in effect, the matching brace or quote need not be on the same line as the starting quote or brace; in this case the newline will be included in the argument field along with any other characters up to the matching brace or quote. For example, the eval command takes one argument, which is a command string; eval invokes the Tcl interpreter to execute the command string. The command

eval {
  set a 22
  set b 33
}

will assign the value 22 to a and 33 to b.

If the first character of a command field is not a left brace, then neither left nor right braces in the field will be treated specially (except as part of variable substitution; see below).

COMMAND SUBSTITUTION WITH BRACKETS

If an open bracket occurs in a field of a command, then command substitution occurs (except for fields enclosed in braces). All of the text up to the matching close bracket is treated as a Tcl command and executed immediately. Then the result of that command is substituted for the bracketed text. For example, consider the command

set a [set b]

When the set command has only a single argument, it is the name of a variable and set returns the contents of that variable. In this case, if variable b has the value foo, then the command above is equivalent to the command

set a foo

Brackets can be used in more complex ways. For example, if the variable b has the value foo and the variable c has the value gorp, then the command

set a xyz[set b].[set c]

is equivalent to the command

set a xyzfoo.gorp

A bracketed command may contain multiple commands separated by newlines or semi-colons in the usual fashion. In this case the value of the last command is used for substitution. For example, the command

set a x[set b 22
expr $b+2]x

is equivalent to the command

set a x24x

If a field is enclosed in braces then the brackets and the characters between them are not interpreted specially; they are passed through to the argument verbatim.

VARIABLE SUBSTITUTION WITH $

The dollar sign ($) may be used as a special shorthand form for substituting variable values. If $ appears in an argument that isn’t enclosed in braces then variable substitution will occur. The characters after the $, up to the first character that isn’t a number, letter, or underscore, are taken as a variable name and the string value of that variable is substituted for the name.

For example, if variable foo has the value test, then the command

set a $foo.c

is equivalent to the command

set a test.c

There are two special forms for variable substitution. If the next character after the name of the variable is an open parenthesis, then the variable is assumed to be an array name, and all of the characters between the open parenthesis and the next close parenthesis are taken as an index into the array. Command substitutions and variable substitutions are performed on the information between the parentheses before it is used as an index.

For example, if the variable x is an array with one element named first and value 87 and another element named 14 and value more, then the command

set a xyz$x(first)zyx

is equivalent to the command

set a xyz87zyx

If the variable index has the value 14, then the command

set a xyz$x($index)zyx

is equivalent to the command

set a xyzmorezyx

For more information on arrays, see VARIABLES AND ARRAYS below.

The second special form for variables occurs when the dollar sign is followed by an open curly brace. In this case the variable name consists of all the characters up to the next curly brace.

Array references are not possible in this form: the name between braces is assumed to refer to a scalar variable. For example, if variable foo has the value test, then the command

set a abc${foo}bar

is equivalent to the command

set a abctestbar

Variable substitution does not occur in arguments that are enclosed in braces: the dollar sign and variable name are passed through to the argument verbatim.

The dollar sign abbreviation is simply a shorthand form. $a is completely equivalent to [set a]; it is provided as a convenience to reduce typing.

SEPARATING COMMANDS WITH SEMI-COLONS

Normally, each command occupies one line (the command is terminated by a newline character). However, semi-colon (;) is treated as a command separator character; multiple commands may be placed on one line by separating them with a semi-colon. Semi-colons are not treated as command separators if they appear within curly braces or double-quotes.

BACKSLASH SUBSTITUTION

Backslashes may be used to insert non-printing characters into command fields and also to insert special characters like braces and brackets into fields without them being interpreted specially as described above.

The backslash sequences understood by the Tcl interpreter are listed below. In each case, the backslash sequence is replaced by the given character:

\b

Backspace (0x8)

\f

Form feed (0xc)

\n

Newline (0xa)

\r

Carriage-return (0xd).

\t

Tab (0x9).

\v

Vertical tab (0xb).

\{

Left brace ({).

\}

Right brace (}).

\[

Open bracket ([).

\]

Close bracket (]).

\$

Dollar sign ($).

\<space>

Space ( ): doesn’t terminate argument.

\;

Semi-colon: doesn’t terminate command.

\"

Double-quote.

\<newline>

Nothing: this joins two lines together into a single line. This backslash feature is unique in that it will be applied even when the sequence occurs within braces.

\\

Backslash (\).

\ddd

The digits ddd (one, two, or three of them) give the octal value of the character. Note that Jim supports null characters in strings.

\unnnn
\u{nnn}
\Unnnnnnnn

The UTF-8 encoding of the unicode codepoint represented by the hex digits, nnnn, is inserted. The u form allows for one to four hex digits. The U form allows for one to eight hex digits. The u{nnn} form allows for one to eight hex digits, but makes it easier to insert characters UTF-8 characters which are followed by a hex digit.

For example, in the command

set a \{x\[\ yz\141

the second argument to set will be {x[ yza.

If a backslash is followed by something other than one of the options described above, then the backslash is transmitted to the argument field without any special processing, and the Tcl scanner continues normal processing with the next character. For example, in the command

set \*a \\\{foo

The first argument to set will be \*a and the second argument will be \{foo.

If an argument is enclosed in braces, then backslash sequences inside the argument are parsed but no substitution occurs (except for backslash-newline): the backslash sequence is passed through to the argument as is, without making any special interpretation of the characters in the backslash sequence. In particular, backslashed braces are not counted in locating the matching right brace that terminates the argument. For example, in the command

set a {\{abc}

the second argument to set will be \{abc.

This backslash mechanism is not sufficient to generate absolutely any argument structure; it only covers the most common cases. To produce particularly complicated arguments it is probably easiest to use the format command along with command substitution.

STRING AND LIST INDEX SPECIFICATIONS

Many string and list commands take one or more index parameters which specify a position in the string relative to the start or end of the string/list.

The index may be one of the following forms:

integer

A simple integer, where 0 refers to the first element of the string or list.

integer+integer or
integer-integer

The sum or difference of the two integers. e.g. 2+3 refers to the 5th element. This is useful when used with (e.g.) $i+1 rather than the more verbose [expr {$i+1}]

end

The last element of the string or list.

end-integer

The nth-from-last element of the string or list.

COMMAND SUMMARY

  1. A command is just a string.

  2. Within a string commands are separated by newlines or semi-colons (unless the newline or semi-colon is within braces or brackets or is backslashed).

  3. A command consists of fields. The first field is the name of the command. The other fields are strings that are passed to that command as arguments.

  4. Fields are normally separated by white space.

  5. Double-quotes allow white space and semi-colons to appear within a single argument. Command substitution, variable substitution, and backslash substitution still occur inside quotes.

  6. Braces defer interpretation of special characters. If a field begins with a left brace, then it consists of everything between the left brace and the matching right brace. The braces themselves are not included in the argument. No further processing is done on the information between the braces except that backslash-newline sequences are eliminated.

  7. If a field doesn’t begin with a brace then backslash, variable, and command substitution are done on the field. Only a single level of processing is done: the results of one substitution are not scanned again for further substitutions or any other special treatment. Substitution can occur on any field of a command, including the command name as well as the arguments.

  8. If the first non-blank character of a command is a #, everything from the # up through the next newline is treated as a comment and ignored.

EXPRESSIONS

The second major interpretation applied to strings in Tcl is as expressions. Several commands, such as expr, for, and if, treat one or more of their arguments as expressions and call the Tcl expression processors (Jim_ExprLong, Jim_ExprBoolean, etc.) to evaluate them.

The operators permitted in Tcl expressions are a subset of the operators permitted in C expressions, and they have the same meaning and precedence as the corresponding C operators. Expressions almost always yield numeric results (integer or floating-point values). For example, the expression

8.2 + 6

evaluates to 14.2.

Tcl expressions differ from C expressions in the way that operands are specified, and in that Tcl expressions support non-numeric operands and string comparisons.

A Tcl expression consists of a combination of operands, operators, and parentheses.

White space may be used between the operands and operators and parentheses; it is ignored by the expression processor. Where possible, operands are interpreted as integer values.

Integer values may be specified in decimal (the normal case) or in hexadecimal (if the first two characters of the operand are 0x). Note that Jim Tcl does not treat numbers with leading zeros as octal.

If an operand does not have one of the integer formats given above, then it is treated as a floating-point number if that is possible. Floating-point numbers may be specified in any of the ways accepted by an ANSI-compliant C compiler (except that the f, F, l, and L suffixes will not be permitted in most installations). For example, all of the following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.

If no numeric interpretation is possible, then an operand is left as a string (and only a limited set of operators may be applied to it).

  1. Operands may be specified in any of the following ways:

  2. As a numeric value, either integer or floating-point.

  3. As a Tcl variable, using standard $ notation. The variable’s value will be used as the operand.

  4. As a string enclosed in double-quotes. The expression parser will perform backslash, variable, and command substitutions on the information between the quotes, and use the resulting value as the operand

  5. As a string enclosed in braces. The characters between the open brace and matching close brace will be used as the operand without any substitutions.

  6. As a Tcl command enclosed in brackets. The command will be executed and its result will be used as the operand.

Where substitutions occur above (e.g. inside quoted strings), they are performed by the expression processor. However, an additional layer of substitution may already have been performed by the command parser before the expression processor was called.

As discussed below, it is usually best to enclose expressions in braces to prevent the command parser from performing substitutions on the contents.

For some examples of simple expressions, suppose the variable a has the value 3 and the variable b has the value 6. Then the expression on the left side of each of the lines below will evaluate to the value on the right side of the line:

$a + 3.1                6.1
2 + "$a.$b"             5.6
4*[llength "6 2"]       8
{word one} < "word $a"  0

The valid operators are listed below, grouped in decreasing order of precedence:

int() double() round() abs(), rand(), srand()

Unary functions (except rand() which takes no arguments)

  • int() converts the numeric argument to an integer by truncating down.

  • double() converts the numeric argument to floating point.

  • round() converts the numeric argument to the closest integer value.

  • abs() takes the absolute value of the numeric argument.

  • rand() takes the absolute value of the numeric argument.

  • rand() returns a pseudo-random floating-point value in the range (0,1).

  • srand() takes an integer argument to (re)seed the random number generator. Returns the first random number from that seed.

sin() cos() tan() asin() acos() atan() sinh() cosh() tanh() ceil() floor() exp() log() log10() sqrt()

Unary math functions. If Jim is compiled with math support, these functions are available.

- + ~ !

Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operands may be applied to string operands, and bit-wise NOT may be applied only to integers.

** pow(x,y)

Power. e.g. xy. If Jim is compiled with math support, supports doubles and integers. Otherwise supports integers only. (Note that the math-function form has the same highest precedence)

* / %

Multiply, divide, remainder. None of these operands may be applied to string operands, and remainder may be applied only to integers.

+ -

Add and subtract. Valid for any numeric operands.

<< >> <<< >>>

Left and right shift, left and right rotate. Valid for integer operands only.

< > <= >=

Boolean less, greater, less than or equal, and greater than or equal. Each operator produces 1 if the condition is true, 0 otherwise. These operators may be applied to strings as well as numeric operands, in which case string comparison is used.

== !=

Boolean equal and not equal. Each operator produces a zero/one result. Valid for all operand types. Note that values will be converted to integers if possible, then floating point types, and finally strings will be compared. It is recommended that eq and ne should be used for string comparison.

eq ne

String equal and not equal. Uses the string value directly without attempting to convert to a number first.

in ni

String in list and not in list. For in, result is 1 if the left operand (as a string) is contained in the right operand (as a list), or 0 otherwise. The result for {$a ni $list} is equivalent to {!($a in $list)}.

&

Bit-wise AND. Valid for integer operands only.

|

Bit-wise OR. Valid for integer operands only.

^

Bit-wise exclusive OR. Valid for integer operands only.

&&

Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise. Valid for numeric operands only (integers or floating-point).

||

Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. Valid for numeric operands only (integers or floating-point).

x ? y : z

If-then-else, as in C. If x evaluates to non-zero, then the result is the value of y. Otherwise the result is the value of z. The x operand must have a numeric value, while y and z can be of any type.

See the C manual for more details on the results produced by each operator. All of the binary operators group left-to-right within the same precedence level. For example, the expression

4*2 < 7

evaluates to 0.

The &&, ||, and ?: operators have lazy evaluation, just as in C, which means that operands are not evaluated if they are not needed to determine the outcome. For example, in

$v ? [a] : [b]

only one of [a] or [b] will actually be evaluated, depending on the value of $v.

All internal computations involving integers are done with the C type long long if available, or long otherwise, and all internal computations involving floating-point are done with the C type double.

When converting a string to floating-point, exponent overflow is detected and results in a Tcl error. For conversion to integer from string, detection of overflow depends on the behaviour of some routines in the local C library, so it should be regarded as unreliable. In any case, overflow and underflow are generally not detected reliably for intermediate results.

Conversion among internal representations for integer, floating-point, and string operands is done automatically as needed. For arithmetic computations, integers are used until some floating-point number is introduced, after which floating-point is used. For example,

5 / 4

yields the result 1, while

5 / 4.0
5 / ( [string length "abcd"] + 0.0 )

both yield the result 1.25.

String values may be used as operands of the comparison operators, although the expression evaluator tries to do comparisons as integer or floating-point when it can. If one of the operands of a comparison is a string and the other has a numeric value, the numeric operand is converted back to a string using the C sprintf format specifier %d for integers and %g for floating-point values. For example, the expressions

"0x03" > "2"
"0y" < "0x12"

both evaluate to 1. The first comparison is done using integer comparison, and the second is done using string comparison after the second operand is converted to the string 18.

In general it is safest to enclose an expression in braces when entering it in a command: otherwise, if the expression contains any white space then the Tcl interpreter will split it among several arguments. For example, the command

expr $a + $b

results in three arguments being passed to expr: $a, +, and $b. In addition, if the expression isn’t in braces then the Tcl interpreter will perform variable and command substitution immediately (it will happen in the command parser rather than in the expression parser). In many cases the expression is being passed to a command that will evaluate the expression later (or even many times if, for example, the expression is to be used to decide when to exit a loop). Usually the desired goal is to re-do the variable or command substitutions each time the expression is evaluated, rather than once and for all at the beginning. For example, the command

for {set i 1} $i<=10 {incr i} {...}        ** WRONG **

is probably intended to iterate over all values of i from 1 to 10. After each iteration of the body of the loop, for will pass its second argument to the expression evaluator to see whether or not to continue processing. Unfortunately, in this case the value of i in the second argument will be substituted once and for all when the for command is parsed. If i was 0 before the for command was invoked then the second argument of for will be 0<=10 which will always evaluate to 1, even though i eventually becomes greater than 10. In the above case the loop will never terminate. Instead, the expression should be placed in braces:

for {set i 1} {$i<=10} {incr i} {...}      ** RIGHT **

This causes the substitution of i to be delayed; it will be re-done each time the expression is evaluated, which is the desired result.

LISTS

The third major way that strings are interpreted in Tcl is as lists. A list is just a string with a list-like structure consisting of fields separated by white space. For example, the string

Al Sue Anne John

is a list with four elements or fields. Lists have the same basic structure as command strings, except that a newline character in a list is treated as a field separator just like space or tab. Conventions for braces and quotes and backslashes are the same for lists as for commands. For example, the string

a b\ c {d e {f g h}}

is a list with three elements: a, b c, and d e {f g h}.

Whenever an element is extracted from a list, the same rules about braces and quotes and backslashes are applied as for commands. Thus in the example above when the third element is extracted from the list, the result is

d e {f g h}

(when the field was extracted, all that happened was to strip off the outermost layer of braces). Command substitution and variable substitution are never made on a list (at least, not by the list-processing commands; the list can always be passed to the Tcl interpreter for evaluation).

The Tcl commands concat, foreach, lappend, lindex, linsert, list, llength, lrange, lreplace, lsearch, and lsort allow you to build lists, extract elements from them, search them, and perform other list-related functions.

Advanced list commands include lrepeat, lreverse, lmap, lassign, lset.

LIST EXPANSION

A new addition to Tcl 8.5 is the ability to expand a list into separate arguments. Support for this feature is also available in Jim.

Consider the following attempt to exec a list:

set cmd {ls -l}
exec $cmd

This will attempt to exec the a command named "ls -l", which will clearly not work. Typically eval and concat are required to solve this problem, however it can be solved much more easily with {*}.

exec {*}$cmd

This will expand the following argument into individual elements and then evaluate the resulting command.

Note that the official Tcl syntax is {*}, however {expand} is retained for backward compatibility with experimental versions of this feature.

REGULAR EXPRESSIONS

Tcl provides two commands that support string matching using regular expressions, regexp and regsub, as well as switch -regexp and lsearch -regexp.

Regular expressions may be implemented one of two ways. Either using the system’s C library POSIX regular expression support, or using the built-in regular expression engine. The differences between these are described below.

NOTE Tcl 7.x and 8.x use perl-style Advanced Regular Expressions (ARE).

POSIX Regular Expressions

If the system supports POSIX regular expressions, and UTF-8 support is not enabled, this support will be used by default. The type of regular expressions supported are Extended Regular Expressions (ERE) rather than Basic Regular Expressions (BRE). See REG_EXTENDED in the documentation.

Using the system-supported POSIX regular expressions will typically make for the smallest code size, but some features such as UTF-8 and \w, \d, \s are not supported, and null characters in strings are not supported.

See regex(3) and regex(7) for full details.

Jim built-in Regular Expressions

The Jim built-in regular expression engine may be selected with ./configure --with-jim-regexp or it will be selected automatically if UTF-8 support is enabled.

This engine supports UTF-8 as well as some ARE features. The differences with both Tcl 7.x/8.x and POSIX are highlighted below.

  1. UTF-8 strings and patterns are both supported

  2. Supported character classes: [:alnum:], [:digit:] and [:space:]

  3. Supported shorthand character classes: \w = [:alnum:], \d = [:digit:], \s = [:space:]

  4. Character classes apply to ASCII characters only

  5. Supported constraint escapes: \m = \< = start of word, \M = \> = end of word

  6. Backslash escapes may be used within regular expressions, such as \n = newline, \uNNNN = unicode

  7. Support for the ? non-greedy quantifier. e.g. *?

  8. Support for non-capuring parentheses (?:…)

  9. Jim Tcl considers that both patterns and strings end at a null character (\x00)

COMMAND RESULTS

Each command produces two results: a code and a string. The code indicates whether the command completed successfully or not, and the string gives additional information. The valid codes are defined in jim.h, and are:

JIM_OK(0)

This is the normal return code, and indicates that the command completed successfully. The string gives the command’s return value.

JIM_ERR(1)

Indicates that an error occurred; the string gives a message describing the error.

JIM_RETURN(2)

Indicates that the return command has been invoked, and that the current procedure (or top-level command or source command) should return immediately. The string gives the return value for the procedure or command.

JIM_BREAK(3)

Indicates that the break command has been invoked, so the innermost loop should abort immediately. The string should always be empty.

JIM_CONTINUE(4)

Indicates that the continue command has been invoked, so the innermost loop should go on to the next iteration. The string should always be empty.

JIM_SIGNAL(5)

Indicates that a signal was caught while executing a commands. The string contains the name of the signal caught. See the signal and catch commands.

JIM_EXIT(6)

Indicates that the command called the exit command. The string contains the exit code.

Tcl programmers do not normally need to think about return codes, since JIM_OK is almost always returned. If anything else is returned by a command, then the Tcl interpreter immediately stops processing commands and returns to its caller. If there are several nested invocations of the Tcl interpreter in progress, then each nested command will usually return the error to its caller, until eventually the error is reported to the top-level application code. The application will then display the error message for the user.

In a few cases, some commands will handle certain error conditions themselves and not return them upwards. For example, the for command checks for the JIM_BREAK code; if it occurs, then for stops executing the body of the loop and returns JIM_OK to its caller. The for command also handles JIM_CONTINUE codes and the procedure interpreter handles JIM_RETURN codes. The catch command allows Tcl programs to catch errors and handle them without aborting command interpretation any further.

The info returncodes command may be used to programmatically map between return codes and names.

PROCEDURES

Tcl allows you to extend the command interface by defining procedures. A Tcl procedure can be invoked just like any other Tcl command (it has a name and it receives one or more arguments). The only difference is that its body isn’t a piece of C code linked into the program; it is a string containing one or more other Tcl commands.

The proc command is used to create a new Tcl command procedure:

proc name arglist ?statics? body

The new command is named name, and it replaces any existing command there may have been by that name. Whenever the new command is invoked, the contents of body will be executed by the Tcl interpreter.

arglist specifies the formal arguments to the procedure. It consists of a list, possibly empty, of the following argument specifiers:

name

Required Argument - A simple argument name.

name default

Optional Argument - A two-element list consisting of the argument name, followed by the default value, which will be used if the corresponding argument is not supplied.

&name

Reference Argument - The caller is expected to pass the name of an existing variable. An implicit upvar 1 'origname' 'name' is done to make the variable available in the proc scope.

args

Variable Argument - The special name args, which is assigned all remaining arguments (including none) as a list. The variable argument may only be specified once. Note that the syntax args newname may be used to retain the special behaviour of args with a different local name. In this case, the variable is named newname rather than args.

When the command is invoked, a local variable will be created for each of the formal arguments to the procedure; its value will be the value of corresponding argument in the invoking command or the argument’s default value.

Arguments with default values need not be specified in a procedure invocation. However, there must be enough actual arguments for all required arguments, and there must not be any extra actual arguments (unless the Variable Argument is specified).

Actual arguments are assigned to formal arguments as in left-to-right order with the following precedence.

  1. Required Arguments (including Reference Arguments)

  2. Optional Arguments

  3. Variable Argument

The following example illustrates precedence. Assume a procedure declaration:

proc p {{a A} args b {c C} d} {...}

This procedure requires at least two arguments, but can accept an unlimited number. The following table shows how various numbers of arguments are assigned. Values marked as - are assigned the default value.

Number of arguments a args b c d

2

-

-

1

-

2

3

1

-

2

-

3

4

1

-

2

3

4

5

1

2

3

4

5

6

1

2,3

4

5

6

When body is being executed, variable names normally refer to local variables, which are created automatically when referenced and deleted when the procedure returns. One local variable is automatically created for each of the procedure’s arguments. Global variables can be accessed by invoking the global command or via the :: prefix.

New in Jim

In addition to procedure arguments, Jim procedures may declare static variables. These variables scoped to the procedure and initialised at procedure definition. Either from the static variable definition, or from the enclosing scope.

Consider the following example:

jim> set a 1
jim> proc a {} {a {b 2}} {
    set c 1
    puts "$a $b $c"
    incr a
    incr b
    incr c
}
jim> a
1 2 1
jim> a
2 3 1

The static variable a has no initialiser, so it is initialised from the enclosing scope with the value 1. (Note that it is an error if there is no variable with the same name in the enclosing scope). However b has an initialiser, so it is initialised to 2.

Unlike a local variable, the value of a static variable is retained across invocations of the procedure.

See the proc command for information on how to define procedures and what happens when they are invoked. See also NAMESPACES.

VARIABLES - SCALARS AND ARRAYS

Tcl allows the definition of variables and the use of their values either through $-style variable substitution, the set command, or a few other mechanisms.

Variables need not be declared: a new variable will automatically be created each time a new variable name is used.

Tcl supports two types of variables: scalars and arrays. A scalar variable has a single value, whereas an array variable can have any number of elements, each with a name (called its index) and a value.

Array indexes may be arbitrary strings; they need not be numeric. Parentheses are used refer to array elements in Tcl commands. For example, the command

set x(first) 44

will modify the element of x whose index is first so that its new value is 44.

Two-dimensional arrays can be simulated in Tcl by using indexes that contain multiple concatenated values. For example, the commands

set a(2,3) 1
set a(3,6) 2

set the elements of a whose indexes are 2,3 and 3,6.

In general, array elements may be used anywhere in Tcl that scalar variables may be used.

If an array is defined with a particular name, then there may not be a scalar variable with the same name.

Similarly, if there is a scalar variable with a particular name then it is not possible to make array references to the variable.

To convert a scalar variable to an array or vice versa, remove the existing variable with the unset command.

The array command provides several features for dealing with arrays, such as querying the names of all the elements of the array and converting between an array and a list.

Variables may be either global or local. If a variable name is used when a procedure isn’t being executed, then it automatically refers to a global variable. Variable names used within a procedure normally refer to local variables associated with that invocation of the procedure. Local variables are deleted whenever a procedure exits. Either global command may be used to request that a name refer to a global variable for the duration of the current procedure (this is somewhat analogous to extern in C), or the variable may be explicitly scoped with the :: prefix. For example

set a 1
set b 2
proc p {} {
    set c 3
    global a
    puts "$a $::b $c"
}
p

will output:

1 2 3

ARRAYS AS LISTS IN JIM

Unlike Tcl, Jim can automatically convert between a list (with an even number of elements) and an array value. This is similar to the way Tcl can convert between a string and a list.

For example:

set a {1 one 2 two}
puts $a(2)

will output:

two

Thus array set is equivalent to set when the variable does not exist or is empty.

The reverse is also true where an array will be converted into a list.

set a(1) one; set a(2) two
puts $a

will output:

1 one 2 two

DICTIONARY VALUES

Tcl 8.5 introduced the dict command, and Jim Tcl has added a version of this command. Dictionaries provide efficient access to key-value pairs, just like arrays, but dictionaries are pure values. This means that you can pass them to a procedure just as a list or a string. Tcl dictionaries are therefore much more like Tcl lists, except that they represent a mapping from keys to values, rather than an ordered sequence.

You can nest dictionaries, so that the value for a particular key consists of another dictionary. That way you can elegantly build complicated data structures, such as hierarchical databases. You can also combine dictionaries with other Tcl data structures. For instance, you can build a list of dictionaries that themselves contain lists.

Dictionaries are values that contain an efficient, order-preserving mapping from arbitrary keys to arbitrary values. Each key in the dictionary maps to a single value. They have a textual format that is exactly that of any list with an even number of elements, with each mapping in the dictionary being represented as two items in the list. When a command takes a dictionary and produces a new dictionary based on it (either returning it or writing it back into the variable that the starting dictionary was read from) the new dictionary will have the same order of keys, modulo any deleted keys and with new keys added on to the end. When a string is interpreted as a dictionary and it would otherwise have duplicate keys, only the last value for a particular key is used; the others are ignored, meaning that, "apple banana" and "apple carrot apple banana" are equivalent dictionaries (with different string representations).

Note that in Jim, arrays are implemented as dictionaries. Thus automatic conversion between lists and dictionaries applies as it does for arrays.

jim> dict set a 1 one
1 one
jim> dict set a 2 two
1 one 2 two
jim> puts $a
1 one 2 two
jim> puts $a(2)
two
jim> dict set a 3 T three
1 one 2 two 3 {T three}

See the dict command for more details.

NAMESPACES

Tcl added namespaces as a mechanism avoiding name clashes, especially in applications including a number of 3rd party components. While there is less need for namespaces in Jim Tcl (which does not strive to support large applications), it is convenient to provide a subset of the support for namespaces to easy porting code from Tcl.

Jim Tcl currently supports "light-weight" namespaces which should be adequate for most purposes. This feature is currently experimental. See README.namespaces for more information and the documentation of the namespace command.

GARBAGE COLLECTION, REFERENCES, LAMBDA

Unlike Tcl, Jim has some sophisticated support for functional programming. These are described briefly below.

More information may be found at http://wiki.tcl.tk/13847

References

A reference can be thought of as holding a value with one level of indirection, where the value may be garbage collected when unreferenced. Consider the following example:

jim> set r [ref "One String" test]
<reference.<test___>.00000000000000000000>
jim> getref $r
One String

The operation ref creates a references to the value specified by the first argument. (The second argument is a "type" used for documentation purposes).

The operation getref is the dereferencing operation which retrieves the value stored in the reference.

jim> setref $r "New String"
New String
jim> getref $r
New String

The operation setref replaces the value stored by the reference. If the old value is no longer accessible by any reference, it will eventually be automatically be garbage collected.

Garbage Collection

Normally, all values in Tcl are passed by value. As such values are copied and released automatically as necessary.

With the introduction of references, it is possible to create values whose lifetime transcend their scope. To support this, case, the Jim system will periodically identify and discard objects which are no longer accessible by any reference.

The collect command may be used to force garbage collection. Consider a reference created with a finalizer:

jim> proc f {ref value} { puts "Finaliser called for $ref,$value" }
jim> set r [ref "One String" test f]
<reference.<test___>.00000000000
jim> collect
0
jim> set r ""
jim> collect
Finaliser called for <reference.<test___>.00000000000,One String
1

Note that once the reference, r, was modified so that it no longer contained a reference to the value, the garbage collector discarded the value (after calling the finalizer).

The finalizer for a reference may be examined or changed with the finalize command

jim> finalize $r
f
jim> finalize $r newf
newf

Lambda

Jim provides a garbage collected lambda function. This is a procedure which is able to create an anonymous procedure. Consider:

jim> set f [lambda {a} {{x 0}} { incr x $a }]
jim> $f 1
1
jim> $f 2
3
jim> set f ""

This create an anonymous procedure (with the name stored in f), with a static variable which is incremented by the supplied value and the result returned.

Once the procedure name is no longer accessible, it will automatically be deleted when the garbage collector runs.

The procedure may also be delete immediately by renaming it "". e.g.

jim> rename $f ""

UTF-8 AND UNICODE

If Jim is built with UTF-8 support enabled (configure --enable-utf), then most string-related commands become UTF-8 aware. These include, but are not limited to, string match, split, glob, scan and format.

UTF-8 encoding has many advantages, but one of the complications is that characters can take a variable number of bytes. Thus the addition of string bytelength which returns the number of bytes in a string, while string length returns the number of characters.

If UTF-8 support is not enabled, all commands treat bytes as characters and string bytelength returns the same value as string length.

Note that even if UTF-8 support is not enabled, the \uNNNN and related syntax is still available to embed UTF-8 sequences.

Jim Tcl supports all currently defined unicode codepoints. That is 21 bits, up to +U+1FFFFF.

String Matching

Commands such as string match, lsearch -glob, array names and others use string pattern matching rules. These commands support UTF-8. For example:

string match a\[\ua0-\ubf\]b "a\u00a3b"

format and scan

format %c allows a unicode codepoint to be be encoded. For example, the following will return a string with two bytes and one character. The same as \ub5

format %c 0xb5

format respects widths as character widths, not byte widths. For example, the following will return a string with three characters, not three bytes.

format %.3s \ub5\ub6\ub7\ub8

Similarly, scan … %c allows a UTF-8 to be decoded to a unicode codepoint. The following will set a to 181 (0xb5) and b to 65 (0x41).

scan \u00b5A %c%c a b

scan %s will also accept a character class, including unicode ranges.

String Classes

string is has not been extended to classify UTF-8 characters. Therefore, the following will return 0, even though the string may be considered to be alphabetic.

string is alpha \ub5Test

This does not affect the string classes ascii, control, digit, double, integer or xdigit.

Case Mapping and Conversion

Jim provides a simplified unicode case mapping. This means that case conversion and comparison will not increase or decrease the number of characters in a string. (Although it may change the number of bytes).

string toupper will convert any lowercase letters to their uppercase equivalent. Any character which is not a letter or has no uppercase equivalent is left unchanged. Similarly for string tolower and string totitle.

Commands which perform case insensitive matches, such as string compare -nocase and lsearch -nocase fold both strings to uppercase before comparison.

Invalid UTF-8 Sequences

Some UTF-8 character sequences are invalid, such as those beginning with 0xff, those which represent character sequences longer than 3 bytes (greater than U+FFFF), and those which end prematurely, such as a lone 0xc2.

In these situations, the offending bytes are treated as single characters. For example, the following returns 2.

string bytelength \xff\xff

Regular Expressions

If UTF-8 support is enabled, the built-in regular expression engine will be selected which supports UTF-8 strings and patterns.

See REGULAR EXPRESSIONS

BUILT-IN COMMANDS

The Tcl library provides the following built-in commands, which will be available in any application using Tcl. In addition to these built-in commands, there may be additional commands defined by each application, plus commands defined as Tcl procedures.

In the command syntax descriptions below, words in boldface are literals that you type verbatim to Tcl.

Words in italics are meta-symbols; they serve as names for any of a range of values that you can type.

Optional arguments or groups of arguments are indicated by enclosing them in ?question-marks?.

Ellipses (...) indicate that any number of additional arguments or groups of arguments may appear, in the same format as the preceding argument(s).

alarm

alarm seconds

Delivers the SIGALRM signal to the process after the given number of seconds. If the platform supports ualarm(3) then the argument may be a floating point value. Otherwise it must be an integer.

Note that unless a signal handler for SIGALRM has been installed (see signal), the process will exit on this signal.

alias

alias name args...

Creates a single word alias (command) for one or more words. For example, the following creates an alias for the command info exists.

alias e info exists
if {[e var]} {
  ...
}

alias returns name, allowing it to be used with local.

See also proc, curry, lambda, local, info alias, exists -alias

append

append varName value ?value value …?

Append all of the value arguments to the current value of variable varName. If varName doesn’t exist, it is given a value equal to the concatenation of all the value arguments.

This command provides an efficient way to build up long variables incrementally. For example, "append a $b" is much more efficient than "set a $a$b" if $a is long.

apply

apply lambdaExpr ?arg1 arg2 ...?

The command apply provides for anonymous procedure calls, similar to lambda, but without command name being created, even temporarily.

The function lambdaExpr is a two element list {args body} or a three element list {args body namespace}. The first element args specifies the formal arguments, in the same form as the proc and lambda commands.

array

array option arrayName ?arg...?

This command performs one of several operations on the variable given by arrayName.

Note that in general, if the named array does not exist, the array command behaves as though the array exists but is empty.

The option argument determines what action is carried out by the command. The legal options (which may be abbreviated) are:

array exists arrayName

Returns 1 if arrayName is an array variable, 0 if there is no variable by that name. This command is essentially identical to info exists

array get arrayName ?pattern?

Returns a list containing pairs of elements. The first element in each pair is the name of an element in arrayName and the second element of each pair is the value of the array element. The order of the pairs is undefined. If pattern is not specified, then all of the elements of the array are included in the result. If pattern is specified, then only those elements whose names match pattern (using the matching rules of string match) are included. If arrayName isn’t the name of an array variable, or if the array contains no elements, then an empty list is returned.

array names arrayName ?pattern?

Returns a list containing the names of all of the elements in the array that match pattern. If pattern is omitted then the command returns all of the element names in the array. If pattern is specified, then only those elements whose names match pattern (using the matching rules of string match) are included. If there are no (matching) elements in the array, or if arrayName isn’t the name of an array variable, then an empty string is returned.

array set arrayName list

Sets the values of one or more elements in arrayName. list must have a form like that returned by array get, consisting of an even number of elements. Each odd-numbered element in list is treated as an element name within arrayName, and the following element in list is used as a new value for that array element. If the variable arrayName does not already exist and list is empty, arrayName is created with an empty array value.

array size arrayName

Returns the number of elements in the array. If arrayName isn’t the name of an array then 0 is returned.

array unset arrayName ?pattern?

Unsets all of the elements in the array that match pattern (using the matching rules of string match). If arrayName isn’t the name of an array variable or there are no matching elements in the array, no error will be raised. If pattern is omitted and arrayName is an array variable, then the command unsets the entire array. The command always returns an empty string.

break

break

This command may be invoked only inside the body of a loop command such as for or foreach or while. It returns a JIM_BREAK code to signal the innermost containing loop command to return immediately.

case

case string ?in? patList body ?patList body …?

case string ?in? {patList body ?patList body …?}

Note that the switch command should generally be preferred unless compatibility with Tcl 6.x is desired.

Match string against each of the patList arguments in order. If one matches, then evaluate the following body argument by passing it recursively to the Tcl interpreter, and return the result of that evaluation. Each patList argument consists of a single pattern or list of patterns. Each pattern may contain any of the wild-cards described under string match.

If a patList argument is default, the corresponding body will be evaluated if no patList matches string. If no patList argument matches string and no default is given, then the case command returns an empty string.

Two syntaxes are provided.

The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands.

The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands.

The second form makes it easy to construct multi-line case commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line.

Since the patList arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behaviour of the second form different than the first form in some cases.

Below are some examples of case commands:

case abc in {a b} {format 1} default {format 2} a* {format 3}

will return 3,

case a in {
    {a b} {format 1}
    default {format 2}
    a* {format 3}
}

will return 1, and

case xyz {
    {a b}
        {format 1}
    default
        {format 2}
    a*
        {format 3}
}

will return 2.

catch

catch ?-?no?code ...? ?--? command ?resultVarName? ?optionsVarName?

The catch command may be used to prevent errors from aborting command interpretation. catch evaluates command, and returns a JIM_OK code, regardless of any errors that might occur while executing command (with the possible exception of JIM_SIGNAL - see below).

The return value from catch is a decimal string giving the code returned by the Tcl interpreter after executing command. This will be 0 (JIM_OK) if there were no errors in command; otherwise it will have a non-zero value corresponding to one of the exceptional return codes (see jim.h for the definitions of code values, or the info returncodes command).

If the resultVarName argument is given, then it gives the name of a variable; catch will set the value of the variable to the string returned from command (either a result or an error message).

If the optionsVarName argument is given, then it gives the name of a variable; catch will set the value of the variable to a dictionary. For any return code other than JIM_RETURN, the value for the key -code will be set to the return code. For JIM_RETURN it will be set to the code given in return -code. Additionally, for the return code JIM_ERR, the value of the key -errorinfo will contain the current stack trace (the same result as info stacktrace), the value of the key -errorcode will contain the same value as the global variable $::errorCode, and the value of the key -level will be the current return level (see return -level). This can be useful to rethrow an error:

if {[catch {...} msg opts]} {
    ...maybe do something with the error...
    incr opts(-level)
    return {*}$opts $msg
}

Normally catch will not catch any of the codes JIM_EXIT, JIM_EVAL or JIM_SIGNAL. The set of codes which will be caught may be modified by specifying the one more codes before command.

e.g. To catch JIM_EXIT but not JIM_BREAK or JIM_CONTINUE

catch -exit -nobreak -nocontinue -- { ... }

The use of -- is optional. It signifies that no more return code options follow.

Note that if a signal marked as signal handle is caught with catch -signal, the return value (stored in resultVarName) is name of the signal caught.

cd

cd dirName

Change the current working directory to dirName.

Returns an empty string.

This command can potentially be disruptive to an application, so it may be removed in some applications.

clock

clock seconds

Returns the current time as seconds since the epoch.

clock format seconds ?-format format?

Format the given time (seconds since the epoch) according to the given format. See strftime(3) for supported formats. If no format is supplied, "%c" is used.

clock scan str -format format

Scan the given time string using the given format string. See strptime(3) for supported formats.

close

close fileId

fileId close

Closes the file given by fileId. fileId must be the return value from a previous invocation of the open command; after this command, it should not be used anymore.

collect

collect

Normally reference garbage collection is automatically performed periodically. However it may be run immediately with the collect command.

See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

concat

concat arg ?arg ...?

This command treats each argument as a list and concatenates them into a single list. It permits any number of arguments. For example, the command

concat a b {c d e} {f {g h}}

will return

a b c d e f {g h}

as its result.

continue

continue

This command may be invoked only inside the body of a loop command such as for or foreach or while. It returns a JIM_CONTINUE code to signal the innermost containing loop command to skip the remainder of the loop’s body but continue with the next iteration of the loop.

curry

alias args...

Similar to alias except it creates an anonymous procedure (lambda) instead of a named procedure.

the following creates a local, unnamed alias for the command info exists.

set e [local curry info exists]
if {[$e var]} {
  ...
}

curry returns the name of the procedure.

See also proc, alias, lambda, local.

dict

dict option ?arg...?

Performs one of several operations on dictionary values.

The option argument determines what action is carried out by the command. The legal options are:

dict create ?key value ...?

Create and return a new dictionary value that contains each of the key/value mappings listed as arguments (keys and values alternating, with each key being followed by its associated value.)

dict exists dictionary key ?key ...?

Returns a boolean value indicating whether the given key (or path of keys through a set of nested dictionaries) exists in the given dictionary value. This returns a true value exactly when dict get on that path will succeed.

dict get dictionary ?key ...?

Given a dictionary value (first argument) and a key (second argument), this will retrieve the value for that key. Where several keys are supplied, the behaviour of the command shall be as if the result of "dict get $dictVal $key" was passed as the first argument to dict get with the remaining arguments as second (and possibly subsequent) arguments. This facilitates lookups in nested dictionaries. If no keys are provided, dict would return a list containing pairs of elements in a man- ner similar to array get. That is, the first element of each pair would be the key and the second element would be the value for that key. It is an error to attempt to retrieve a value for a key that is not present in the dictionary.

dict keys dictionary ?pattern?

Returns a list of the keys in the dictionary. If pattern is specified, then only those keys whose names match pattern (using the matching rules of string match) are included.

dict merge ?dictionary ...?

Return a dictionary that contains the contents of each of the dictionary arguments. Where two (or more) dictionaries contain a mapping for the same key, the resulting dictionary maps that key to the value according to the last dictionary on the command line containing a mapping for that key.

dict set dictionaryName key ?key ...? value

This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. When multiple keys are present, this operation creates or updates a chain of nested dictionaries.

dict size dictionary

Return the number of key/value mappings in the given dictionary value.

dict unset dictionaryName key ?key ...? value

This operation (the companion to dict set) takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified, but the last key on the key-path need not exist. All other components on the path must exist.

dict with dictionaryName key ?key ...? script

Execute the Tcl script in script with the value for each key in dictionaryName mapped to a variable with the same name. Where one or more keys are given, these indicate a chain of nested dictionaries, with the innermost dictionary being the one opened out for the execution of body. Making dictionaryName unreadable will make the updates to the dictionary be discarded, and this also happens if the contents of dictionaryName are adjusted so that the chain of dictionaries no longer exists. The result of dict with is (unless some kind of error occurs) the result of the evaluation of body.

The variables are mapped in the scope enclosing the dict with; it is recommended that this command only be used in a local scope (procedure). Because of this, the variables set by dict with will continue to exist after the command finishes (unless explicitly unset). Note that changes to the contents of dictionaryName only happen when script terminates.

dict for, values, incr, append, lappend, update, info, replace to be documented…

env

env ?name? ?default?

If name is supplied, returns the value of name from the initial environment (see getenv(3)). An error is returned if name does not exist in the environment, unless default is supplied - in which case that value is returned instead.

If no arguments are supplied, returns a list of all environment variables and their values as {name value ...}

See also the global variable ::env

eof

eof fileId

fileId eof

Returns 1 if an end-of-file condition has occurred on fileId, 0 otherwise.

fileId must have been the return value from a previous call to open, or it may be stdin, stdout, or stderr to refer to one of the standard I/O channels.

error

error message ?stacktrace?

Returns a JIM_ERR code, which causes command interpretation to be unwound. message is a string that is returned to the application to indicate what went wrong.

If the stacktrace argument is provided and is non-empty, it is used to initialize the stacktrace.

This feature is most useful in conjunction with the catch command: if a caught error cannot be handled successfully, stacktrace can be used to return a stack trace reflecting the original point of occurrence of the error:

catch {...} errMsg
...
error $errMsg [info stacktrace]

See also errorInfo, info stacktrace, catch and return

errorInfo

errorInfo error ?stacktrace?

Returns a human-readable representation of the given error message and stack trace. Typical usage is:

if {[catch {...} error]} {
    puts stderr [errorInfo $error [info stacktrace]]
    exit 1
}

See also error.

eval

eval arg ?arg...?

eval takes one or more arguments, which together comprise a Tcl command (or collection of Tcl commands separated by newlines in the usual way). eval concatenates all its arguments in the same fashion as the concat command, passes the concatenated string to the Tcl interpreter recursively, and returns the result of that evaluation (or any error generated by it).

exec

exec arg ?arg...?

This command treats its arguments as the specification of one or more UNIX commands to execute as subprocesses. The commands take the form of a standard shell pipeline; | arguments separate commands in the pipeline and cause standard output of the preceding command to be piped into standard input of the next command (or |& for both standard output and standard error).

Under normal conditions the result of the exec command consists of the standard output produced by the last command in the pipeline.

If any of the commands in the pipeline exit abnormally or are killed or suspended, then exec will return an error and the error message will include the pipeline’s output followed by error messages describing the abnormal terminations.

If any of the commands writes to its standard error file, then exec will return an error, and the error message will include the pipeline’s output, followed by messages about abnormal terminations (if any), followed by the standard error output.

If the last character of the result or error message is a newline then that character is deleted from the result or error message for consistency with normal Tcl return values.

An arg may have one of the following special forms:

>filename

The standard output of the last command in the pipeline is redirected to the file. In this situation exec will normally return an empty string.

>>filename

As above, but append to the file.

>@fileId

The standard output of the last command in the pipeline is redirected to the given (writable) file descriptor (e.g. stdout, stderr, or the result of open). In this situation exec will normally return an empty string.

2>filename

The standard error of the last command in the pipeline is redirected to the file.

2>>filename

As above, but append to the file.

2>@fileId

The standard error of the last command in the pipeline is redirected to the given (writable) file descriptor.

2>@1

The standard error of the last command in the pipeline is redirected to the same file descriptor as the standard output.

>&filename

Both the standard output and standard error of the last command in the pipeline is redirected to the file.

>>&filename

As above, but append to the file.

<filename

The standard input of the first command in the pipeline is taken from the file.

<<string

The standard input of the first command is taken as the given immediate value.

<@fileId

The standard input of the first command in the pipeline is taken from the given (readable) file descriptor.

If there is no redirection of standard input, standard error or standard output, these are connected to the corresponding input or output of the application.

If the last arg is & then the command will be executed in background. In this case the standard output from the last command in the pipeline will go to the application’s standard output unless redirected in the command, and error output from all the commands in the pipeline will go to the application’s standard error file. The return value of exec in this case is a list of process ids (pids) in the pipeline.

Each arg becomes one word for a command, except for |, <, <<, >, and & arguments, and the arguments that follow <, <<, and >.

The first word in each command is taken as the command name; the directories in the PATH environment variable are searched for an executable by the given name.

No glob expansion or other shell-like substitutions are performed on the arguments to commands.

If the command fails, the global $::errorCode (and the -errorcode option in catch) will be set to a list, as follows:

CHILDKILLED pid sigName msg

This format is used when a child process has been killed because of a signal. The pid element will be the process’s identifier (in decimal). The sigName element will be the symbolic name of the signal that caused the process to terminate; it will be one of the names from the include file signal.h, such as SIGPIPE. The msg element will be a short human-readable message describing the signal, such as "write on pipe with no readers" for SIGPIPE.

CHILDSUSP pid sigName msg

This format is used when a child process has been suspended because of a signal. The pid element will be the process’s identifier, in decimal. The sigName element will be the symbolic name of the signal that caused the process to suspend; this will be one of the names from the include file signal.h, such as SIGTTIN. The msg element will be a short human-readable message describing the signal, such as "background tty read" for SIGTTIN.

CHILDSTATUS pid code

This format is used when a child process has exited with a non-zero exit status. The pid element will be the process’s identifier (in decimal) and the code element will be the exit code returned by the process (also in decimal).

The environment for the executed command is set from $::env (unless this variable is unset, in which case the original environment is used).

exists

exists ?-var|-proc|-command|-alias? name

Checks the existence of the given variable, procedure, command or alias respectively and returns 1 if it exists or 0 if not. This command provides a more simplified/convenient version of info exists, info procs and info commands.

If the type is omitted, a type of -var is used. The type may be abbreviated.

exit

exit ?returnCode?

Terminate the process, returning returnCode to the parent as the exit status.

If returnCode isn’t specified then it defaults to 0.

Note that exit can be caught with catch.

expr

expr arg

Calls the expression processor to evaluate arg, and returns the result as a string. See the section EXPRESSIONS above.

Note that Jim supports a shorthand syntax for expr as $(...) The following two are identical.

set x [expr {3 * 2 + 1}]
set x $(3 * 2 + 1)

file

file option name ?arg...?

Operate on a file or a file name. name is the name of a file.

option indicates what to do with the file name. Any unique abbreviation for option is acceptable. The valid options are:

file atime name

Return a decimal string giving the time at which file name was last accessed. The time is measured in the standard UNIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file doesn’t exist or its access time cannot be queried then an error is generated.

file copy ?-force? source target

Copies file source to file target. The source file must exist. The target file must not exist, unless -force is specified.

file delete ?-force? ?--? name...

Deletes file or directory name. If the file or directory doesn’t exist, nothing happens. If it can’t be deleted, an error is generated. Non-empty directories will not be deleted unless the -force options is given. In this case no errors will be generated, even if the file/directory can’t be deleted. Use -- if there is any possibility of the first name being -force.

file dirname name

Return all of the characters in name up to but not including the last slash character. If there are no slashes in name then return . (a single dot). If the last slash in name is its first character, then return /.

file executable name

Return 1 if file name is executable by the current user, 0 otherwise.

file exists name

Return 1 if file name exists and the current user has search privileges for the directories leading to it, 0 otherwise.

file extension name

Return all of the characters in name after and including the last dot in name. If there is no dot in name then return the empty string.

file isdirectory name

Return 1 if file name is a directory, 0 otherwise.

file isfile name

Return 1 if file name is a regular file, 0 otherwise.

file join arg...

Joins multiple path components. Note that if any components is an absolute path, the preceding components are ignored. Thus "file join /tmp /root" returns "/root".

file link ?-hard|-symbolic? newname target

Creates a hard link (default) or symbolic link from newname to target. Note that the sense of this command is the opposite of file rename and file copy and also of ln, but this is compatible with Tcl. An error is returned if target doesn’t exist or newname already exists.

file lstat name varName

Same as stat option (see below) except uses the lstat kernel call instead of stat. This means that if name refers to a symbolic link the information returned in varName is for the link rather than the file it refers to. On systems that don’t support symbolic links this option behaves exactly the same as the stat option.

file mkdir dir1 ?dir2...?

Creates each directory specified. For each pathname dir specified, this command will create all non-existing parent directories as well as dir itself. If an existing directory is specified, then no action is taken and no error is returned. Trying to overwrite an existing file with a directory will result in an error. Arguments are processed in the order specified, halting at the first error, if any.

file mtime name ?time?

Return a decimal string giving the time at which file name was last modified. The time is measured in the standard UNIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file doesn’t exist or its modified time cannot be queried then an error is generated. If time is given, sets the modification time of the file to the given value.

file normalize name

Return the normalized path of name. See realpath(3).

file owned name

Return 1 if file name is owned by the current user, 0 otherwise.

file readable name

Return 1 if file name is readable by the current user, 0 otherwise.

file readlink name

Returns the value of the symbolic link given by name (i.e. the name of the file it points to). If name isn’t a symbolic link or its value cannot be read, then an error is returned. On systems that don’t support symbolic links this option is undefined.

file rename ?-force? oldname newname

Renames the file from the old name to the new name. If newname already exists, an error is returned unless -force is specified.

file rootname name

Return all of the characters in name up to but not including the last . character in the name. If name doesn’t contain a dot, then return name.

file size name

Return a decimal string giving the size of file name in bytes. If the file doesn’t exist or its size cannot be queried then an error is generated.

file stat name ?varName?

Invoke the stat kernel call on name, and return the result as a dictionary with the following keys: atime, ctime, dev, gid, ino, mode, mtime, nlink, size, type, uid. Each element except type is a decimal string with the value of the corresponding field from the stat return structure; see the manual entry for stat for details on the meanings of the values. The type element gives the type of the file in the same form returned by the command file type. If varName is specified, it is taken to be the name of an array variable and the values are also stored into the array.

file tail name

Return all of the characters in name after the last slash. If name contains no slashes then return name.

file tempfile ?template?

Creates and returns the name of a unique temporary file. If template is omitted, a default template will be used to place the file in /tmp. See mkstemp(3) for the format of the template and security concerns.

file type name

Returns a string giving the type of file name, which will be one of file, directory, characterSpecial, blockSpecial, fifo, link, or socket.

file writable name

Return 1 if file name is writable by the current user, 0 otherwise.

The file commands that return 0/1 results are often used in conditional or looping commands, for example:

if {![file exists foo]} {
    error {bad file name}
} else {
    ...
}

finalize

finalize reference ?command?

If command is omitted, returns the finalizer command for the given reference.

Otherwise, sets a new finalizer command for the given reference. command may be the empty string to remove the current finalizer.

The reference must be a valid reference create with the ref command.

See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

flush

flush fileId

fileId flush

Flushes any output that has been buffered for fileId. fileId must have been the return value from a previous call to open, or it may be stdout or stderr to access one of the standard I/O streams; it must refer to a file that was opened for writing. This command returns an empty string.

for

for start test next body

for is a looping command, similar in structure to the C for statement. The start, next, and body arguments must be Tcl command strings, and test is an expression string.

The for command first invokes the Tcl interpreter to execute start. Then it repeatedly evaluates test as an expression; if the result is non-zero it invokes the Tcl interpreter on body, then invokes the Tcl interpreter on next, then repeats the loop. The command terminates when test evaluates to 0.

If a continue command is invoked within body then any remaining commands in the current execution of body are skipped; processing continues by invoking the Tcl interpreter on next, then evaluating test, and so on.

If a break command is invoked within body or next, then the for command will return immediately.

The operation of break and continue are similar to the corresponding statements in C.

for returns an empty string.

foreach

foreach varName list body

foreach varList list ?varList2 list2 ...? body

In this command, varName is the name of a variable, list is a list of values to assign to varName, and body is a collection of Tcl commands.

For each field in list (in order from left to right), foreach assigns the contents of the field to varName (as if the lindex command had been used to extract the field), then calls the Tcl interpreter to execute body.

If instead of being a simple name, varList is used, multiple assignments are made each time through the loop, one for each element of varList.

For example, if there are two elements in varList and six elements in the list, the loop will be executed three times.

If the length of the list doesn’t evenly divide by the number of elements in varList, the value of the remaining variables in the last iteration of the loop are undefined.

The break and continue statements may be invoked inside body, with the same effect as in the for command.

foreach returns an empty string.

format

format formatString ?arg ...?

This command generates a formatted string in the same way as the C sprintf procedure (it uses sprintf in its implementation). formatString indicates how to format the result, using % fields as in sprintf, and the additional arguments, if any, provide values to be substituted into the result.

All of the sprintf options are valid; see the sprintf man page for details. Each arg must match the expected type from the % field in formatString; the format command converts each argument to the correct type (floating, integer, etc.) before passing it to sprintf for formatting.

The only unusual conversion is for %c; in this case the argument must be a decimal string, which will then be converted to the corresponding ASCII (or UTF-8) character value.

In addition, Jim Tcl provides basic support for conversion to binary with %b.

format does backslash substitution on its formatString argument, so backslash sequences in formatString will be handled correctly even if the argument is in braces.

The return value from format is the formatted string.

getref

getref reference

Returns the string associated with reference. The reference must be a valid reference create with the ref command.

See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

gets

gets fileId ?varName?

fileId gets ?varName?

Reads the next line from the file given by fileId and discards the terminating newline character.

If varName is specified, then the line is placed in the variable by that name and the return value is a count of the number of characters read (not including the newline).

If the end of the file is reached before reading any characters then -1 is returned and varName is set to an empty string.

If varName is not specified then the return value will be the line (minus the newline character) or an empty string if the end of the file is reached before reading any characters.

An empty string will also be returned if a line contains no characters except the newline, so eof may have to be used to determine what really happened.

If the last character in the file is not a newline character, then gets behaves as if there were an additional newline character at the end of the file.

fileId must be stdin or the return value from a previous call to open; it must refer to a file that was opened for reading.

glob

glob ?-nocomplain? ?-directory dir? ?-tails? ?--? pattern ?pattern ...?

This command performs filename globbing, using csh rules. The returned value from glob is the list of expanded filenames.

If -nocomplain is specified as the first argument then an empty list may be returned; otherwise an error is returned if the expanded list is empty. The -nocomplain argument must be provided exactly: an abbreviation will not be accepted.

If -directory is given, the dir is understood to contain a directory name to search in. This allows globbing inside directories whose names may contain glob-sensitive characters. The returned names include the directory name unless -tails is specified.

If -tails is specified, along with -directory, the returned names are relative to the given directory.

global

global varName ?varName ...?

This command is ignored unless a Tcl procedure is being interpreted. If so, then it declares each given varName to be a global variable rather than a local one. For the duration of the current procedure (and only while executing in the current procedure), any reference to varName will be bound to a global variable instead of a local one.

An alternative to using global is to use the :: prefix to explicitly name a variable in the global scope.

if

if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?

The if command evaluates expr1 as an expression (in the same way that expr evaluates its argument). The value of the expression must be numeric; if it is non-zero then body1 is executed by passing it to the Tcl interpreter.

Otherwise expr2 is evaluated as an expression and if it is non-zero then body2 is executed, and so on.

If none of the expressions evaluates to non-zero then bodyN is executed.

The then and else arguments are optional "noise words" to make the command easier to read.

There may be any number of elseif clauses, including zero. bodyN may also be omitted as long as else is omitted too.

The return value from the command is the result of the body script that was executed, or an empty string if none of the expressions was non-zero and there was no bodyN.

incr

incr varName ?increment?

Increment the value stored in the variable whose name is varName. The value of the variable must be integral.

If increment is supplied then its value (which must be an integer) is added to the value of variable varName; otherwise 1 is added to varName.

The new value is stored as a decimal string in variable varName and also returned as result.

If the variable does not exist, the variable is implicitly created and set to 0 first.

info

info option ?arg...?

Provide information about various internals to the Tcl interpreter. The legal option's (which may be abbreviated) are:

info args procname

Returns a list containing the names of the arguments to procedure procname, in order. procname must be the name of a Tcl command procedure.

info alias command

command must be an alias created with alias. In which case the target command and arguments, as passed to alias are returned. See exists -alias

info body procname

Returns the body of procedure procname. procname must be the name of a Tcl command procedure.

info channels

Returns a list of all open file handles from open or socket

info commands ?pattern?

If pattern isn’t specified, returns a list of names of all the Tcl commands, including both the built-in commands written in C and the command procedures defined using the proc command. If pattern is specified, only those names matching pattern are returned. Matching is determined using the same rules as for string match.

info complete command ?missing?

Returns 1 if command is a complete Tcl command in the sense of having no unclosed quotes, braces, brackets or array element names, If the command doesn’t appear to be complete then 0 is returned. This command is typically used in line-oriented input environments to allow users to type in commands that span multiple lines; if the command isn’t complete, the script can delay evaluating it until additional lines have been typed to complete the command. If varName is specified, the missing character is stored in the variable with that name.

info exists varName

Returns 1 if the variable named varName exists in the current context (either as a global or local variable), returns 0 otherwise.

info frame ?number?

If number is not specified, this command returns a number which is the same result as info level - the current stack frame level. If number is specified, then the result is a list consisting of the procedure, filename and line number for the procedure call at level number on the stack. If number is positive then it selects a particular stack level (1 refers to the top-most active procedure, 2 to the procedure it called, and so on); otherwise it gives a level relative to the current level (0 refers to the current procedure, -1 to its caller, and so on). The level has an identical meaning to info level.

info globals ?pattern?

If pattern isn’t specified, returns a list of all the names of currently-defined global variables. If pattern is specified, only those names matching pattern are returned. Matching is determined using the same rules as for string match.

info hostname

An alias for os.gethostname for compatibility with Tcl 6.x

info level ?number?

If number is not specified, this command returns a number giving the stack level of the invoking procedure, or 0 if the command is invoked at top-level. If number is specified, then the result is a list consisting of the name and arguments for the procedure call at level number on the stack. If number is positive then it selects a particular stack level (1 refers to the top-most active procedure, 2 to the procedure it called, and so on); otherwise it gives a level relative to the current level (0 refers to the current procedure, -1 to its caller, and so on). See the uplevel command for more information on what stack levels mean.

info locals ?pattern?

If pattern isn’t specified, returns a list of all the names of currently-defined local variables, including arguments to the current procedure, if any. Variables defined with the global and upvar commands will not be returned. If pattern is specified, only those names matching pattern are returned. Matching is determined using the same rules as for string match.

info nameofexecutable

Returns the name of the binary file from which the application was invoked. A full path will be returned, unless the path can’t be determined, in which case the empty string will be returned.

info procs ?pattern?

If pattern isn’t specified, returns a list of all the names of Tcl command procedures. If pattern is specified, only those names matching pattern are returned. Matching is determined using the same rules as for string match.

info references

Returns a list of all references which have not yet been garbage collected.

info returncodes ?code?

Returns a list representing the mapping of standard return codes to names. e.g. {0 ok 1 error 2 return ...}. If a code is given, instead returns the name for the given code.

info script

If a Tcl script file is currently being evaluated (i.e. there is a call to Jim_EvalFile active or there is an active invocation of the source command), then this command returns the name of the innermost file being processed. Otherwise the command returns an empty string.

info source script ?filename line?

With a single argument, returns the original source location of the given script as a list of {filename linenumber}. If the source location can’t be determined, the list {{} 0} is returned. If filename and line are given, returns a copy of script with the associate source information. This can be useful to produce useful messages from eval, etc. if the original source information may be lost.

info stacktrace

After an error is caught with catch, returns the stack trace as a list of {procedure filename line ...}.

info statics procname

Returns a dictionary of the static variables of procedure procname. procname must be the name of a Tcl command procedure. An empty dictionary is returned if the procedure has no static variables.

info version

Returns the version number for this version of Jim in the form x.yy.

info vars ?pattern?

If pattern isn’t specified, returns a list of all the names of currently-visible variables, including both locals and currently-visible globals. If pattern is specified, only those names matching pattern are returned. Matching is determined using the same rules as for string match.

join

join list ?joinString?

The list argument must be a valid Tcl list. This command returns the string formed by joining all of the elements of list together with joinString separating each adjacent pair of elements.

The joinString argument defaults to a space character.

kill

kill ?SIG|-0? pid

Sends the given signal to the process identified by pid.

The signal may be specified by name or number in one of the following forms:

  • TERM

  • SIGTERM

  • -TERM

  • 15

  • -15

The signal name may be in either upper or lower case.

The special signal name -0 simply checks that a signal could be sent.

If no signal is specified, SIGTERM is used.

An error is raised if the signal could not be delivered.

lambda

lambda args ?statics? body

The lambda command is identical to proc, except rather than creating a named procedure, it creates an anonymous procedure and returns the name of the procedure.

See proc and GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

lappend

lappend varName value ?value value ...?

Treat the variable given by varName as a list and append each of the value arguments to that list as a separate element, with spaces between elements.

If varName doesn’t exist, it is created as a list with elements given by the value arguments. lappend is similar to append except that each value is appended as a list element rather than raw text.

This command provides a relatively efficient way to build up large lists. For example,

lappend a $b

is much more efficient than

set a [concat $a [list $b]]

when $a is long.

lassign

lassign list varName ?varName ...?

This command treats the value list as a list and assigns successive elements from that list to the variables given by the varName arguments in order. If there are more variable names than list elements, the remaining variables are set to the empty string. If there are more list ele- ments than variables, a list of unassigned elements is returned.

jim> lassign {1 2 3} a b; puts a=$a,b=$b
3
a=1,b=2

local

local cmd ?arg...?

First, local evaluates cmd with the given arguments. The return value must be the name of an existing command, which is marked as having local scope. This means that when the current procedure exits, the specified command is deleted. This can be useful with lambda, local procedures or to automatically close a filehandle.

In addition, if a command already exists with the same name, the existing command will be kept rather than deleted, and may be called via upcall. The previous command will be restored when the current procedure exits. See upcall for more details.

In this example, a local procedure is created. Note that the procedure continues to have global scope while it is active.

proc outer {} {
  # proc ... returns "inner" which is marked local
  local proc inner {} {
    # will be deleted when 'outer' exits
  }
  inner
  ...
}

In this example, the lambda is deleted at the end of the procedure rather than waiting until garbage collection.

proc outer {} {
  set x [lambda inner {args} {
    # will be deleted when 'outer' exits
  }]
  # Use 'function' here which simply returns $x
  local function $x
  $x ...
  ...
}

loop

loop var first limit ?incr? body

Similar to for except simpler and possibly more efficient. With a positive increment, equivalent to:

for {set var $first} {$var < $limit} {incr var $incr} $body

If incr is not specified, 1 is used. Note that setting the loop variable inside the loop does not affect the loop count.

lindex

lindex list ?index …?

Treats list as a Tcl list and returns element index from it (0 refers to the first element of the list). See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for index.

In extracting the element, lindex observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur.

If no index values are given, simply returns list

If index is negative or greater than or equal to the number of elements in list, then an empty string is returned.

If additional index arguments are supplied, then each argument is used in turn to select an element from the previous indexing operation, allowing the script to select elements from sublists.

linsert

linsert list index element ?element element ...?

This command produces a new list from list by inserting all of the element arguments just before the element index of list. Each element argument will become a separate element of the new list. If index is less than or equal to zero, then the new elements are inserted at the beginning of the list. If index is greater than or equal to the number of elements in the list, then the new elements are appended to the list.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for index.

list

list arg ?arg ...?

This command returns a list comprised of all the arguments, arg. Braces and backslashes get added as necessary, so that the lindex command may be used on the result to re-extract the original arguments, and also so that eval may be used to execute the resulting list, with arg1 comprising the command’s name and the other args comprising its arguments. list produces slightly different results than concat: concat removes one level of grouping before forming the list, while list works directly from the original arguments. For example, the command

list a b {c d e} {f {g h}}

will return

a b {c d e} {f {g h}}

while concat with the same arguments will return

a b c d e f {g h}

llength

llength list

Treats list as a list and returns a decimal string giving the number of elements in it.

lset

lset varName ?index ..? newValue

Sets an element in a list.

The lset command accepts a parameter, varName, which it interprets as the name of a variable containing a Tcl list. It also accepts zero or more indices into the list. Finally, it accepts a new value for an element of varName. If no indices are presented, the command takes the form:

lset varName newValue

In this case, newValue replaces the old value of the variable varName.

When presented with a single index, the lset command treats the content of the varName variable as a Tcl list. It addresses the index’th element in it (0 refers to the first element of the list). When interpreting the list, lset observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. The command constructs a new list in which the designated element is replaced with newValue. This new list is stored in the variable varName, and is also the return value from the lset command.

If index is negative or greater than or equal to the number of elements in $varName, then an error occurs.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for index.

If additional index arguments are supplied, then each argument is used in turn to address an element within a sublist designated by the previous indexing operation, allowing the script to alter elements in sublists. The command,

lset a 1 2 newValue

replaces element 2 of sublist 1 with newValue.

The integer appearing in each index argument must be greater than or equal to zero. The integer appearing in each index argument must be strictly less than the length of the corresponding list. In other words, the lset command cannot change the size of a list. If an index is outside the permitted range, an error is reported.

lmap

lmap varName list body

lmap varList list ?varList2 list2 ...? body

lmap is a "collecting" foreach which returns a list of its results.

For example:

jim> lmap i {1 2 3 4 5} {expr $i*$i}
1 4 9 16 25
jim> lmap a {1 2 3} b {A B C} {list $a $b}
{1 A} {2 B} {3 C}

If the body invokes continue, no value is added for this iteration. If the body invokes break, the loop ends and no more values are added.

load

load filename

Loads the dynamic extension, filename. Generally the filename should have the extension .so. The initialisation function for the module must be based on the name of the file. For example loading hwaccess.so will invoke the initialisation function, Jim_hwaccessInit. Normally the load command should not be used directly. Instead it is invoked automatically by package require.

lrange

lrange list first last

list must be a valid Tcl list. This command will return a new list consisting of elements first through last, inclusive.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for first and last.

If last is greater than or equal to the number of elements in the list, then it is treated as if it were end.

If first is greater than last then an empty string is returned.

Note: "lrange list first first" does not always produce the same result as "lindex list first" (although it often does for simple fields that aren’t enclosed in braces); it does, however, produce exactly the same results as "list [lindex list first]"

lreplace

lreplace list first last ?element element ...?

Returns a new list formed by replacing one or more elements of list with the element arguments.

first gives the index in list of the first element to be replaced.

If first is less than zero then it refers to the first element of list; the element indicated by first must exist in the list.

last gives the index in list of the last element to be replaced; it must be greater than or equal to first.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for first and last.

The element arguments specify zero or more new arguments to be added to the list in place of those that were deleted.

Each element argument will become a separate element of the list.

If no element arguments are specified, then the elements between first and last are simply deleted.

lrepeat

lrepeat number element1 ?element2 ...?

Build a list by repeating elements number times (which must be a positive integer).

jim> lrepeat 3 a b
a b a b a b

lreverse

lreverse list

Returns the list in reverse order.

jim> lreverse {1 2 3}
3 2 1

lsearch

lsearch ?options? list pattern

This command searches the elements list to see if one of them matches pattern. If so, the command returns the index of the first matching element (unless the options -all, -inline or -bool are specified.) If not, the command returns -1. The option arguments indicates how the elements of the list are to be matched against pattern and must have one of the values below:

Note that this command is different from Tcl in that default match type is -exact rather than -glob.

-exact

pattern is a literal string that is compared for exact equality against each list element. This is the default.

-glob

pattern is a glob-style pattern which is matched against each list element using the same rules as the string match command.

-regexp

pattern is treated as a regular expression and matched against each list element using the rules described by regexp.

-command cmdname

cmdname is a command which is used to match the pattern against each element of the list. It is invoked as cmdname ?-nocase? pattern listvalue and should return 1 for a match, or 0 for no match.

-all

Changes the result to be the list of all matching indices (or all matching values if -inline is specified as well). If indices are returned, the indices will be in numeric order. If values are returned, the order of the values will be the order of those values within the input list.

-inline

The matching value is returned instead of its index (or an empty string if no value matches). If -all is also specified, then the result of the command is the list of all values that matched. The -inline and -bool options are mutually exclusive.

-bool

Changes the result to 1 if a match was found, or 0 otherwise. If -all is also specified, the result will be a list of 0 and 1 for each element of the list depending upon whether the corresponding element matches. The -inline and -bool options are mutually exclusive.

-not

This negates the sense of the match, returning the index (or value if -inline is specified) of the first non-matching value in the list. If -bool is also specified, the 0 will be returned if a match is found, or 1 otherwise. If -all is also specified, non-matches will be returned rather than matches.

-nocase

Causes comparisons to be handled in a case-insensitive manner.

lsort

lsort ?-index listindex? ?-nocase!-integer|-real|-command cmdname? ?-unique? ?-decreasing|-increasing? list

Sort the elements of list, returning a new list in sorted order. By default, ASCII (or UTF-8) sorting is used, with the result in increasing order.

If -nocase is specified, comparisons are case-insenstive.

If -integer is specified, numeric sorting is used.

If -real is specified, floating point number sorting is used.

If -command cmdname is specified, cmdname is treated as a command name. For each comparison, cmdname $value1 $value2 is called which should compare the values and return an integer less than, equal to, or greater than zero if the $value1 is to be considered less than, equal to, or greater than $value2, respectively.

If -decreasing is specified, the resulting list is in the opposite order to what it would be otherwise. -increasing is the default.

If -unique is specified, then only the last set of duplicate elements found in the list will be retained. Note that duplicates are determined relative to the comparison used in the sort. Thus if -index 0 is used, {1 a} and {1 b} would be considered duplicates and only the second element, {1 b}, would be retained.

If -index listindex is specified, each element of the list is treated as a list and the given index is extracted from the list for comparison. The list index may be any valid list index, such as 1, end or end-2.

open

open fileName ?access?

open |command-pipeline ?access?

Opens a file and returns an identifier that may be used in future invocations of commands like read, puts, and close. fileName gives the name of the file to open.

The access argument indicates the way in which the file is to be accessed. It may have any of the following values:

r

Open the file for reading only; the file must already exist.

r+

Open the file for both reading and writing; the file must already exist.

w

Open the file for writing only. Truncate it if it exists. If it doesn’t exist, create a new file.

w+

Open the file for reading and writing. Truncate it if it exists. If it doesn’t exist, create a new file.

a

Open the file for writing only. The file must already exist, and the file is positioned so that new data is appended to the file.

a+

Open the file for reading and writing. If the file doesn’t exist, create a new empty file. Set the initial access position to the end of the file.

access defaults to r.

If a file is opened for both reading and writing, then seek must be invoked between a read and a write, or vice versa.

If the first character of fileName is "|" then the remaining characters of fileName are treated as a list of arguments that describe a command pipeline to invoke, in the same style as the arguments for exec. In this case, the channel identifier returned by open may be used to write to the command’s input pipe or read from its output pipe, depending on the value of access. If write-only access is used (e.g. access is w), then standard output for the pipeline is directed to the current standard output unless overridden by the command. If read-only access is used (e.g. access is r), standard input for the pipeline is taken from the current standard input unless overridden by the command.

The pid command may be used to return the process ids of the commands forming the command pipeline.

See also socket, pid, exec

package

package provide name ?version?

Indicates that the current script provides the package named name. If no version is specified, 1.0 is used.

Any script which provides a package may include this statement as the first statement, although it is not required.

package require name ?version?*

Searches for the package with the given name by examining each path in $::auto_path and trying to load $path/$name.so as a dynamic extension, or $path/$name.tcl as a script package.

The first such file which is found is considered to provide the the package. (The version number is ignored).

If $name.so exists, it is loaded with the load command, otherwise if $name.tcl exists it is loaded with the source command.

If load or source fails, package require will fail immediately. No further attempt will be made to locate the file.

pid

pid

pid fileId

The first form returns the process identifier of the current process.

The second form accepts a handle returned by open and returns a list of the process ids forming the pipeline in the same form as exec ... &. If fileId represents a regular file handle rather than a command pipeline, the empty string is returned instead.

See also open, exec

proc

proc name args ?statics? body

The proc command creates a new Tcl command procedure, name. When the new command is invoked, the contents of body will be executed. Tcl interpreter. args specifies the formal arguments to the procedure. If specified, static, declares static variables which are bound to the procedure.

See PROCEDURES for detailed information about Tcl procedures.

The proc command returns name (which is useful with local).

When a procedure is invoked, the procedure’s return value is the value specified in a return command. If the procedure doesn’t execute an explicit return, then its return value is the value of the last command executed in the procedure’s body.

If an error occurs while executing the procedure body, then the procedure-as-a-whole will return that same error.

puts

puts ?-nonewline? ?fileId? string

fileId puts ?-nonewline? string

Writes the characters given by string to the file given by fileId. fileId must have been the return value from a previous call to open, or it may be stdout or stderr to refer to one of the standard I/O channels; it must refer to a file that was opened for writing.

In the first form, if no fileId is specified then it defaults to stdout. puts normally outputs a newline character after string, but this feature may be suppressed by specifying the -nonewline switch.

Output to files is buffered internally by Tcl; the flush command may be used to force buffered characters to be output.

pwd

pwd

Returns the path name of the current working directory.

rand

rand ?min? ?max?

Returns a random integer between min (defaults to 0) and max (defaults to the maximum integer).

If only one argument is given, it is interpreted as max.

range

range ?start? end ?step?

Returns a list of integers starting at start (defaults to 0) and ranging up to but not including end in steps of step defaults to 1).

jim> range 5
0 1 2 3 4
jim> range 2 5
2 3 4
jim> range 2 10 4
2 6
jim> range 7 4 -2
7 5

read

read ?-nonewline? fileId

fileId read ?-nonewline?

read fileId numBytes

fileId read numBytes

In the first form, all of the remaining bytes are read from the file given by fileId; they are returned as the result of the command. If the -nonewline switch is specified then the last character of the file is discarded if it is a newline.

In the second form, the extra argument specifies how many bytes to read; exactly this many bytes will be read and returned, unless there are fewer than numBytes bytes left in the file; in this case, all the remaining bytes are returned.

fileId must be stdin or the return value from a previous call to open; it must refer to a file that was opened for reading.

regexp

regexp ?-nocase? ?-line? ?-indices? ?-start offset? ?-all? ?-inline? ?--? exp string ?matchVar? ?subMatchVar subMatchVar ...?

Determines whether the regular expression exp matches part or all of string and returns 1 if it does, 0 if it doesn’t.

See REGULAR EXPRESSIONS above for complete information on the syntax of exp and how it is matched against string.

If additional arguments are specified after string then they are treated as the names of variables to use to return information about which part(s) of string matched exp. matchVar will be set to the range of string that matched all of exp. The first subMatchVar will contain the characters in string that matched the leftmost parenthesized subexpression within exp, the next subMatchVar will contain the characters that matched the next parenthesized subexpression to the right in exp, and so on.

Normally, matchVar and the each subMatchVar are set to hold the matching characters from string, however see -indices and -inline below.

If there are more values for subMatchVar than parenthesized subexpressions within exp, or if a particular subexpression in exp doesn’t match the string (e.g. because it was in a portion of the expression that wasn’t matched), then the corresponding subMatchVar will be set to "-1 -1" if -indices has been specified or to an empty string otherwise.

The following switches modify the behaviour of regexp

-nocase

Causes upper-case and lower-case characters to be treated as identical during the matching process.

-line

Use newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning in either REs or strings. With this flag, [ bracket expressions and . never match newline, a anchor matches the null string after any newline in the string in addition to its normal function, and the $ anchor matches the null string before any newline in the string in addition to its normal function.

-indices

Changes what is stored in the subMatchVars. Instead of storing the matching characters from string, each variable will contain a list of two decimal strings giving the indices in string of the first and last characters in the matching range of characters.

-start offset

Specifies a character index offset into the string at which to start matching the regular expression. If -indices is specified, the indices will be indexed starting from the absolute beginning of the input string. offset will be constrained to the bounds of the input string.

-all

Causes the regular expression to be matched as many times as possible in the string, returning the total number of matches found. If this is specified with match variables, they will contain information for the last match only.

-inline

Causes the command to return, as a list, the data that would otherwise be placed in match variables. When using -inline, match variables may not be specified. If used with -all, the list will be concatenated at each iteration, such that a flat list is always returned. For each match iteration, the command will append the overall match data, plus one element for each subexpression in the regular expression.

--

Marks the end of switches. The argument following this one will be treated as exp even if it starts with a -.

regsub

regsub ?-nocase? ?-all? ?-line? ?-start offset? ?--? exp string subSpec ?varName?

This command matches the regular expression exp against string using the rules described in REGULAR EXPRESSIONS above.

If varName is specified, the commands stores string to varName with the substitutions detailed below, and returns the number of substitutions made (normally 1 unless -all is specified). This is 0 if there were no matches.

If varName is not specified, the substituted string will be returned instead.

When copying string, the portion of string that matched exp is replaced with subSpec. If subSpec contains a & or \0, then it is replaced in the substitution with the portion of string that matched exp.

If subSpec contains a \n, where n is a digit between 1 and 9, then it is replaced in the substitution with the portion of string that matched the n'-th parenthesized subexpression of exp. Additional backslashes may be used in subSpec to prevent special interpretation of & or \0 or \n or backslash.

The use of backslashes in subSpec tends to interact badly with the Tcl parser’s use of backslashes, so it’s generally safest to enclose subSpec in braces if it includes backslashes.

The following switches modify the behaviour of regsub

-nocase

Upper-case characters in string are converted to lower-case before matching against exp; however, substitutions specified by subSpec use the original unconverted form of string.

-all

All ranges in string that match exp are found and substitution is performed for each of these ranges, rather than only the first. The & and \n sequences are handled for each substitution using the information from the corresponding match.

-line

Use newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning in either REs or strings. With this flag, [ bracket expressions and . never match newline, a anchor matches the null string after any newline in the string in addition to its normal function, and the $ anchor matches the null string before any newline in the string in addition to its normal function.

-start offset

Specifies a character index offset into the string at which to start matching the regular expression. offset will be constrained to the bounds of the input string.

--

Marks the end of switches. The argument following this one will be treated as exp even if it starts with a -.

ref

ref string tag ?finalizer?

Create a new reference containing string of type tag. If finalizer is specified, it is a command which will be invoked when the a garbage collection cycle runs and this reference is no longer accessible.

The finalizer is invoked as:

finalizer reference string

See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

rename

rename oldName newName

Rename the command that used to be called oldName so that it is now called newName. If newName is an empty string (e.g. {}) then oldName is deleted. The rename command returns an empty string as result.

return

return ?-code code? ?-errorinfo stacktrace? ?-errorcode errorcode? ?-level n? ?value?

Return immediately from the current procedure (or top-level command or source command), with value as the return value. If value is not specified, an empty string will be returned as result.

If -code is specified (as either a number or ok, error, break, continue, signal, return or exit), this code will be used instead of JIM_OK. This is generally useful when implementing flow of control commands.

If -level is specified and greater than 1, it has the effect of delaying the new return code from -code. This is useful when rethrowing an error from catch. See the implementation of try/catch in tclcompat.tcl for an example of how this is done.

Note: The following options are only used when -code is JIM_ERR.

If -errorinfo is specified (as returned from info stacktrace) it is used to initialize the stacktrace.

If -errorcode is specified, it is used to set the global variable $::errorCode.

scan

scan string format varName1 ?varName2 ...?

This command parses fields from an input string in the same fashion as the C sscanf procedure. string gives the input to be parsed and format indicates how to parse it, using % fields as in sscanf. All of the sscanf options are valid; see the sscanf man page for details. Each varName gives the name of a variable; when a field is scanned from string, the result is converted back into a string and assigned to the corresponding varName. The only unusual conversion is for %c. For %c conversions a single character value is converted to a decimal string, which is then assigned to the corresponding varName; no field width may be specified for this conversion.

seek

seek fileId offset ?origin?

fileId seek offset ?origin?

Change the current access position for fileId. The offset and origin arguments specify the position at which the next read or write will occur for fileId. offset must be a number (which may be negative) and origin must be one of the following:

start

The new access position will be offset bytes from the start of the file.

current

The new access position will be offset bytes from the current access position; a negative offset moves the access position backwards in the file.

end

The new access position will be offset bytes from the end of the file. A negative offset places the access position before the end-of-file, and a positive offset places the access position after the end-of-file.

The origin argument defaults to start.

fileId must have been the return value from a previous call to open, or it may be stdin, stdout, or stderr to refer to one of the standard I/O channels.

This command returns an empty string.

set

set varName ?value?

Returns the value of variable varName.

If value is specified, then set the value of varName to value, creating a new variable if one doesn’t already exist, and return its value.

If varName contains an open parenthesis and ends with a close parenthesis, then it refers to an array element: the characters before the open parenthesis are the name of the array, and the characters between the parentheses are the index within the array. Otherwise varName refers to a scalar variable.

If no procedure is active, then varName refers to a global variable.

If a procedure is active, then varName refers to a parameter or local variable of the procedure, unless the global command has been invoked to declare varName to be global.

The :: prefix may also be used to explicitly reference a variable in the global scope.

setref

setref reference string

Store a new string in reference, replacing the existing string. The reference must be a valid reference create with the ref command.

See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.

signal

Command for signal handling.

See kill for the different forms which may be used to specify signals.

Commands which return a list of signal names do so using the canonical form: "SIGINT SIGTERM".

signal handle ?signals ...?

If no signals are given, returns a list of all signals which are currently being handled. If signals are specified, these are added to the list of signals currently being handled.

signal ignore ?signals ...?

If no signals are given, returns a lists all signals which are currently being ignored. If signals are specified, these are added to the list of signals currently being ignored. These signals are still delivered, but are not considered by catch -signal or try -signal. Use signal check to determine which signals have occurred but been ignored.

signal default ?signals ...?

If no signals are given, returns a lists all signals which are currently have the default behaviour. If signals are specified, these are added to the list of signals which have the default behaviour.

signal check ?-clear? ?signals ...?

Returns a list of signals which have been delivered to the process but are ignored. If signals are specified, only that set of signals will be checked, otherwise all signals will be checked. If -clear is specified, any signals returned are removed and will not be returned by subsequent calls to signal check unless delivered again.

signal throw ?signal?

Raises the given signal, which defaults to SIGINT if not specified. The behaviour is identical to:

kill signal [pid]

Note that signal handle and signal ignore represent two forms of signal handling. signal handle is used in conjunction with catch -signal or try -signal to immediately abort execution when the signal is delivered. Alternatively, signal ignore is used in conjunction with signal check to handle signal synchronously. Consider the two examples below.

Prevent a processing from taking too long

signal handle SIGALRM
alarm 20
try -signal {
    .. possibly long running process ..
    alarm 0
} on signal {sig} {
    puts stderr "Process took too long"
}

Handle SIGHUP to reconfigure:

signal ignore SIGHUP
while {1} {
    ... handle configuration/reconfiguration ...
    while {[signal check -clear SIGHUP] eq ""} {
        ... do processing ..
    }
    # Received SIGHUP, so reconfigure
}

sleep

sleep seconds

Pauses for the given number of seconds, which may be a floating point value less than one to sleep for less than a second, or an integer to sleep for one or more seconds.

source

source fileName

Read file fileName and pass the contents to the Tcl interpreter as a sequence of commands to execute in the normal fashion. The return value of source is the return value of the last command executed from the file. If an error occurs in executing the contents of the file, then the source command will return that error.

If a return command is invoked from within the file, the remainder of the file will be skipped and the source command will return normally with the result from the return command.

split

split string ?splitChars?

Returns a list created by splitting string at each character that is in the splitChars argument.

Each element of the result list will consist of the characters from string between instances of the characters in splitChars.

Empty list elements will be generated if string contains adjacent characters in splitChars, or if the first or last character of string is in splitChars.

If splitChars is an empty string then each character of string becomes a separate element of the result list.

splitChars defaults to the standard white-space characters. For example,

split "comp.unix.misc" .

returns "comp unix misc" and

split "Hello world" {}

returns "H e l l o { } w o r l d".

stackdump

stackdump stacktrace

Creates a human readable representation of a stack trace.

stacktrace

stacktrace

Returns a live stack trace as a list of proc file line proc file line .... Iteratively uses info frame to create the stack trace. This stack trace is in the same form as produced by catch and info stacktrace

See also stackdump.

string

string option arg ?arg ...?

Perform one of several string operations, depending on option. The legal options (which may be abbreviated) are:

string bytelength string

Returns the length of the string in bytes. This will return the same value as string length if UTF-8 support is not enabled, or if the string is composed entirely of ASCII characters. See UTF-8 AND UNICODE.

string byterange string first last

Like string range except works on bytes rather than characters. These commands are identical if UTF-8 support is not enabled.

string cat ?string1 string2 ...?

Concatenates the given strings into a single string.

string compare ?-nocase? ?-length len? string1 string2

Perform a character-by-character comparison of strings string1 and string2 in the same way as the C strcmp procedure. Return -1, 0, or 1, depending on whether string1 is lexicographically less than, equal to, or greater than string2. If -length is specified, then only the first len characters are used in the comparison. If len is negative, it is ignored. Performs a case-insensitive comparison if -nocase is specified.

string equal ?-nocase? ?-length len? string1 string2

Returns 1 if the strings are equal, or 0 otherwise. If -length is specified, then only the first len characters are used in the comparison. If len is negative, it is ignored. Performs a case-insensitive comparison if -nocase is specified.

string first string1 string2 ?firstIndex?

Search string2 for a sequence of characters that exactly match the characters in string1. If found, return the index of the first character in the first such match within string2. If not found, return -1. If firstIndex is specified, matching will start from firstIndex of string1.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for firstIndex.

string index string charIndex

Returns the charIndexth character of the 'string argument. A charIndex of 0 corresponds to the first character of the string. If charIndex is less than 0 or greater than or equal to the length of the string then an empty string is returned.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for charIndex.

string is class ?-strict? string

Returns 1 if string is a valid member of the specified character class, otherwise returns 0. If -strict is specified, then an empty string returns 0, otherwise an empty string will return 1 on any class. The following character classes are recognized (the class name can be abbreviated):

alnum

Any alphabet or digit character.

alpha

Any alphabet character.

ascii

Any character with a value less than 128 (those that are in the 7-bit ascii range).

control

Any control character.

digit

Any digit character.

double

Any of the valid forms for a double in Tcl, with optional surrounding whitespace. In case of under/overflow in the value, 0 is returned.

graph

Any printing character, except space.

integer

Any of the valid string formats for an integer value in Tcl, with optional surrounding whitespace.

lower

Any lower case alphabet character.

print

Any printing character, including space.

punct

Any punctuation character.

space

Any space character.

upper

Any upper case alphabet character.

xdigit

Any hexadecimal digit character ([0-9A-Fa-f]).

Note that string classification does not respect UTF-8. See UTF-8 AND UNICODE

string last string1 string2 ?lastIndex?

Search string2 for a sequence of characters that exactly match the characters in string1. If found, return the index of the first character in the last such match within string2. If there is no match, then return -1. If lastIndex is specified, only characters up to lastIndex of string2 will be considered in the match.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for lastIndex.

string length string

Returns a decimal string giving the number of characters in string. If UTF-8 support is enabled, this may be different than the number of bytes. See UTF-8 AND UNICODE

string map ?-nocase? mapping string

Replaces substrings in string based on the key-value pairs in mapping, which is a list of key value key value ... as in the form returned by array get. Each instance of a key in the string will be replaced with its corresponding value. If -nocase is specified, then matching is done without regard to case differences. Both key and value may be multiple characters. Replacement is done in an ordered manner, so the key appearing first in the list will be checked first, and so on. string is only iterated over once, so earlier key replacements will have no affect for later key matches. For example,

string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc

will return the string 01321221.

Note that if an earlier key is a prefix of a later one, it will completely mask the later one. So if the previous example is reordered like this,

string map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc

it will return the string 02c322c222c.

string match ?-nocase? pattern string

See if pattern matches string; return 1 if it does, 0 if it doesn’t. Matching is done in a fashion similar to that used by the C-shell. For the two strings to match, their contents must be identical except that the following special sequences may appear in pattern:

*

Matches any sequence of characters in string, including a null string.

?

Matches any single character in string.

[chars]

Matches any character in the set given by chars. If a sequence of the form x-y appears in chars, then any character between x and y, inclusive, will match.

\x

Matches the single character x. This provides a way of avoiding the special interpretation of the characters \*?[] in pattern.

Performs a case-insensitive comparison if -nocase is specified.

string range string first last

Returns a range of consecutive characters from string, starting with the character whose index is first and ending with the character whose index is last. An index of 0 refers to the first character of the string.

See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for first and last.

If first is less than zero then it is treated as if it were zero, and if last is greater than or equal to the length of the string then it is treated as if it were end. If first is greater than last then an empty string is returned.

string repeat string count

Returns a new string consisting of string repeated count times.

string replace string first last ?newstring?

Removes a range of consecutive characters from string, starting with the character whose index is first and ending with the character whose index is last. If newstring is specified, then it is placed in the removed character range. If first is less than zero then it is treated as if it were zero, and if last is greater than or equal to the length of the string then it is treated as if it were end. If first is greater than last or the length of the initial string, or last is less than 0, then the initial string is returned untouched.

string reverse string

Returns a string that is the same length as string but with its characters in the reverse order.

string tolower string

Returns a value equal to string except that all upper case letters have been converted to lower case.

string totitle string

Returns a value equal to string except that the first character is converted to title case (or upper case if there is no UTF-8 titlecase variant) and all remaining characters have been converted to lower case.

string toupper string

Returns a value equal to string except that all lower case letters have been converted to upper case.

string trim string ?chars?

Returns a value equal to string except that any leading or trailing characters from the set given by chars are removed. If chars is not specified then white space is removed (spaces, tabs, newlines, and carriage returns).

string trimleft string ?chars?

Returns a value equal to string except that any leading characters from the set given by chars are removed. If chars is not specified then white space is removed (spaces, tabs, newlines, and carriage returns).

string trimright string ?chars?

Returns a value equal to string except that any trailing characters from the set given by chars are removed. If chars is not specified then white space is removed (spaces, tabs, newlines, and carriage returns). Null characters are always removed.

subst

subst ?-nobackslashes? ?-nocommands? ?-novariables? string

This command performs variable substitutions, command substitutions, and backslash substitutions on its string argument and returns the fully-substituted result. The substitutions are performed in exactly the same way as for Tcl commands. As a result, the string argument is actually substituted twice, once by the Tcl parser in the usual fashion for Tcl commands, and again by the subst command.

If any of the -nobackslashes, -nocommands, or -novariables are specified, then the corresponding substitutions are not performed. For example, if -nocommands is specified, no command substitution is performed: open and close brackets are treated as ordinary characters with no special interpretation.

Note: when it performs its substitutions, subst does not give any special treatment to double quotes or curly braces. For example, the following script returns xyz {44}, not xyz {$a}.

set a 44
subst {xyz {$a}}

switch

switch ?options? string pattern body ?pattern body ...?

switch ?options? string {pattern body ?pattern body ...?}

The switch command matches its string argument against each of the pattern arguments in order. As soon as it finds a pattern that matches string it evaluates the following body and returns the result of that evaluation. If the last pattern argument is default then it matches anything. If no pattern argument matches string and no default is given, then the switch command returns an empty string. If the initial arguments to switch start with - then they are treated as options. The following options are currently supported:

-exact

Use exact matching when comparing string to a pattern. This is the default.

-glob

When matching string to the patterns, use glob-style matching (i.e. the same as implemented by the string match command).

-regexp

When matching string to the patterns, use regular expression matching (i.e. the same as implemented by the regexp command).

-command commandname

When matching string to the patterns, use the given command, which must be a single word. The command is invoked as commandname pattern string, or commandname -nocase pattern string and must return 1 if matched, or 0 if not.

--

Marks the end of options. The argument following this one will be treated as string even if it starts with a -.

Two syntaxes are provided for the pattern and body arguments. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line switch commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the pattern arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behaviour of the second form different than the first form in some cases.

If a body is specified as - it means that the body for the next pattern should also be used as the body for this pattern (if the next pattern also has a body of - then the body after that is used, and so on). This feature makes it possible to share a single body among several patterns.

Below are some examples of switch commands:

switch abc a - b {format 1} abc {format 2} default {format 3}

will return 2,

switch -regexp aaab {
       ^a.*b$ -
       b {format 1}
       a* {format 2}
       default {format 3}
}

will return 1, and

switch xyz {
       a -
       b {format 1}
       a* {format 2}
       default {format 3}
}

will return 3.

tailcall

tailcall cmd ?arg...?

The tailcall command provides an optimised way of invoking a command whilst replacing the current call frame. This is similar to exec in Bourne Shell.

The following are identical except the first immediately replaces the current call frame.

tailcall a b c
return [uplevel 1 [list a b c]]

tailcall is useful as a dispatch mechanism:

proc a {cmd args} {
  tailcall sub_$cmd {*}$args
}
proc sub_cmd1 ...
proc sub_cmd2 ...

tell

tell fileId

fileId tell

Returns a decimal string giving the current access position in fileId.

fileId must have been the return value from a previous call to open, or it may be stdin, stdout, or stderr to refer to one of the standard I/O channels.

throw

throw code ?msg?

This command throws an exception (return) code along with an optional message. This command is mostly for convenient usage with try.

The command throw break is equivalent to break. The command throw 20 message can be caught with an on 20 ... clause to try.

time

time command ?count?

This command will call the Tcl interpreter count times to execute command (or once if count isn’t specified). It will then return a string of the form

503 microseconds per iteration

which indicates the average amount of time required per iteration, in microseconds.

Time is measured in elapsed time, not CPU time.

try

try ?catchopts? tryscript ?on returncodes {?resultvar? ?optsvar?} handlerscript ...? ?finally finalscript?

The try command is provided as a convenience for exception handling.

This interpeter first evaluates tryscript under the effect of the catch options catchopts (e.g. -signal -noexit --, see catch).

It then evaluates the script for the first matching on handler (there many be zero or more) based on the return code from the try section. For example a normal JIM_ERR error will be matched by an on error handler.

Finally, any finalscript is evaluated.

The result of this command is the result of tryscript, except in the case where an exception occurs in a matching on handler script or the finally script, in which case the result is this new exception.

The specified returncodes is a list of return codes either as names (ok, error, break, etc.) or as integers.

If resultvar and optsvar are specified, they are set as for catch before evaluating the matching handler.

For example:

set f [open input]
try -signal {
    process $f
} on {continue break} {} {
    error "Unexpected break/continue"
} on error {msg opts} {
    puts "Dealing with error"
    return {*}$opts $msg
} on signal sig {
    puts "Got signal: $sig"
} finally {
    $f close
}

If break, continue or error are raised, they are dealt with by the matching handler.

In any case, the file will be closed via the finally clause.

See also throw, catch, return, error.

unknown

unknown cmdName ?arg arg …?

This command doesn’t actually exist as part of Tcl, but Tcl will invoke it if it does exist.

If the Tcl interpreter encounters a command name for which there is not a defined command, then Tcl checks for the existence of a command named unknown.

If there is no such command, then the interpreter returns an error.

If the unknown command exists, then it is invoked with arguments consisting of the fully-substituted name and arguments for the original non-existent command.

The unknown command typically does things like searching through library directories for a command procedure with the name cmdName, or expanding abbreviated command names to full-length, or automatically executing unknown commands as UNIX sub-processes.

In some cases (such as expanding abbreviations) unknown will change the original command slightly and then (re-)execute it. The result of the unknown command is used as the result for the original non-existent command.

unset

unset ?-nocomplain? ?--? ?name name …?

Remove variables. Each name is a variable name, specified in any of the ways acceptable to the set command.

If a name refers to an element of an array, then that element is removed without affecting the rest of the array.

If a name consists of an array name with no parenthesized index, then the entire array is deleted.

The unset command returns an empty string as result.

An error occurs if any of the variables doesn’t exist, unless -nocomplain is specified. The -- argument may be specified to stop option processing in case the variable name may be -nocomplain.

upcall

upcall command ?args …?

May be used from within a proc defined as local proc in order to call the previous, hidden version of the same command.

If there is no previous definition of the command, an error is returned.

uplevel

uplevel ?level? command ?command …?

All of the command arguments are concatenated as if they had been passed to concat; the result is then evaluated in the variable context indicated by level. uplevel returns the result of that evaluation. If level is an integer, then it gives a distance (up the procedure calling stack) to move before executing the command. If level consists of # followed by a number then the number gives an absolute level number. If level is omitted then it defaults to 1. level cannot be defaulted if the first command argument starts with a digit or #.

For example, suppose that procedure a was invoked from top-level, and that it called b, and that b called c. Suppose that c invokes the uplevel command. If level is 1 or #2 or omitted, then the command will be executed in the variable context of b. If level is 2 or #1 then the command will be executed in the variable context of a.

If level is 3 or #0 then the command will be executed at top-level (only global variables will be visible). The uplevel command causes the invoking procedure to disappear from the procedure calling stack while the command is being executed. In the above example, suppose c invokes the command

uplevel 1 {set x 43; d}

where d is another Tcl procedure. The set command will modify the variable x in b’s context, and 'd will execute at level 3, as if called from b. If it in turn executes the command

uplevel {set x 42}

then the set command will modify the same variable x in b’s context: the procedure 'c does not appear to be on the call stack when d is executing. The command info level may be used to obtain the level of the current procedure.

uplevel makes it possible to implement new control constructs as Tcl procedures (for example, uplevel could be used to implement the while construct as a Tcl procedure).

upvar

upvar ?level? otherVar myVar ?otherVar myVar …?

This command arranges for one or more local variables in the current procedure to refer to variables in an enclosing procedure call or to global variables.

level may have any of the forms permitted for the uplevel command, and may be omitted if the first letter of the first otherVar isn’t # or a digit (it defaults to 1).

For each otherVar argument, upvar makes the variable by that name in the procedure frame given by level (or at global level, if level is #0) accessible in the current procedure by the name given in the corresponding myVar argument.

The variable named by otherVar need not exist at the time of the call; it will be created the first time myVar is referenced, just like an ordinary variable.

upvar may only be invoked from within procedures.

upvar returns an empty string.

The upvar command simplifies the implementation of call-by-name procedure calling and also makes it easier to build new control constructs as Tcl procedures. For example, consider the following procedure:

proc add2 name {
    upvar $name x
    set x [expr $x+2]
}

add2 is invoked with an argument giving the name of a variable, and it adds two to the value of that variable. Although add2 could have been implemented using uplevel instead of upvar, upvar makes it simpler for add2 to access the variable in the caller’s procedure frame.

while

while test body

The while command evaluates test as an expression (in the same way that expr evaluates its argument). The value of the expression must be numeric; if it is non-zero then body is executed by passing it to the Tcl interpreter.

Once body has been executed then test is evaluated again, and the process repeats until eventually test evaluates to a zero numeric value. continue commands may be executed inside body to terminate the current iteration of the loop, and break commands may be executed inside body to cause immediate termination of the while command.

The while command always returns an empty string.

OPTIONAL-EXTENSIONS

The following extensions may or may not be available depending upon what options were selected when Jim Tcl was built.

posix: os.fork, os.wait, os.gethostname, os.getids, os.uptime

os.fork

Invokes fork(2) and returns the result.

os.wait -nohang pid

Invokes waitpid(2), with WNOHANG if -nohang is specified. Returns a list of 3 elements.

{0 none 0} if -nohang is specified, and the process is still alive.
{-1 error <error-description>} if the process does not exist or has already been waited for.
{<pid> exit <exit-status>} if the process exited normally.
{<pid> signal <signal-number>} if the process terminated on a signal.
{<pid> other 0} otherwise (core dump, stopped, continued, etc.)
os.gethostname

Invokes gethostname(3) and returns the result.

os.getids

Returns the various user/group ids for the current process.

jim> os.getids
uid 1000 euid 1000 gid 100 egid 100
os.uptime

Returns the number of seconds since system boot. See description of uptime in sysinfo(2).

ANSI I/O (aio) and EVENTLOOP API

Jim provides an alternative object-based API for I/O.

See open and socket for commands which return an I/O handle.

aio

$handle accept ?addrvar?

Server socket only: Accept a connection and return stream. If addrvar is specified, the address of the connected client is stored in the named variable in the form addr:port. See socket for details.

$handle buffering none|line|full

Sets the buffering mode of the stream.

$handle close ?r(ead)|w(rite)?

Closes the stream. The two-argument form is a "half-close" on a socket. See the shutdown(2) man page.

$handle copyto tofd ?size?

Copy bytes to the file descriptor tofd. If size is specified, at most that many bytes will be copied. Otherwise copying continues until the end of the input file. Returns the number of bytes actually copied.

$handle eof

Returns 1 if stream is at eof

$handle filename

Returns the original filename associated with the handle. Handles returned by socket give the socket type instead of a filename.

$handle flush

Flush the stream

$handle gets ?var?

Read one line and return it or store it in the var

$handle isatty

Returns 1 if the stream is a tty device.

$handle ndelay ?0|1?

Set O_NDELAY (if arg). Returns current/new setting. Note that in general ANSI I/O interacts badly with non-blocking I/O. Use with care.

$handle puts ?-nonewline? str

Write the string, with newline unless -nonewline

$handle read ?-nonewline? ?len?

Read and return bytes from the stream. To eof if no len.

$handle recvfrom maxlen ?addrvar?

Receives a message from the handle via recvfrom(2) and returns it. At most maxlen bytes are read. If addrvar is specified, the sending address of the message is stored in the named variable in the form addr:port. See socket for details.

$handle seek offset ?start|current|end?

Seeks in the stream (default current)

$handle sendto str ?addr:?port

Sends the string, str, to the given address via the socket using sendto(2). This is intended for udp/dgram sockets and may give an error or behave in unintended ways for other handle types. Returns the number of bytes written.

$handle tell

Returns the current seek position

fconfigure

fconfigure handle ?-blocking 0|1? ?-buffering noneline|full? ?-translation mode?

For compatibility with Tcl, a limited form of the fconfigure command is supported.

eventloop: after, vwait, update

The following commands allow a script to be invoked when the given condition occurs. If no script is given, returns the current script. If the given script is the empty, the handler is removed.

$handle readable ?readable-script?

Sets or returns the script for when the socket is readable.

$handle writable ?writable-script?

Sets or returns the script for when the socket is writable.

$handle onexception ?exception-script?

Sets or returns the script for when when oob data received.

For compatibility with Tcl, these may be prefixed with fileevent. e.g.

fileevent $handle readable ...

Time-based execution is also available via the eventloop API.

after ms

Sleeps for the given number of milliseconds. No events are processed during this time.

after ms|idle script ?script ...?'

The scripts are concatenated and executed after the given number of milliseconds have elapsed. If idle is specified, the script will run the next time the event loop is processed with vwait or update. The script is only run once and then removed. Returns an event id.

after cancel id|command

Cancels an after event with the given event id or matching command (script). Returns the number of milliseconds remaining until the event would have fired. Returns the empty string if no matching event is found.

after info ?id?

If id is not given, returns a list of current after events. If id is given, returns a list containing the associated script and either timer or idle to indicated the type of the event. An error occurs if id does not match an event.

vwait variable

A call to vwait is enters the eventloop. vwait processes events until the named (global) variable changes or all event handlers are removed. The variable need not exist beforehand. If there are no event handlers defined, vwait returns immediately.

update ?idletasks?

A call to update enters the eventloop to process expired events, but no new events. If idletasks is specified, only expired time events are handled, not file events. Returns once handlers have been run for all expired events.

Scripts are executed at the global scope. If an error occurs during a handler script, an attempt is made to call (the user-defined command) bgerror with the details of the error. If the bgerror command does not exist, the error message details are printed to stderr instead.

If a file event handler script generates an error, the handler is automatically removed to prevent infinite errors. (A time event handler is always removed after execution).

bgerror msg

Called when an event handler script generates an error. Note that the normal command resolution rules are used for bgerror. First the name is resolved in the current namespace, then in the global scope.

socket

Various socket types may be created.

socket unix path

A unix domain socket client.

socket unix.server path

A unix domain socket server.

socket ?-ipv6? stream addr:port

A TCP socket client. (See the forms for addr below)

socket ?-ipv6? stream.server ?addr:?port

A TCP socket server (addr defaults to 0.0.0.0 for IPv4 or [::] for IPv6).

socket ?-ipv6? dgram ?addr:port?

A UDP socket client. If the address is not specified, the client socket will be unbound and sendto must be used to indicated the destination.

socket ?-ipv6? dgram.server addr:port

A UDP socket server.

socket pipe

A pipe. Note that unlike all other socket types, this command returns a list of two channels: {read write}

socket pair

A socketpair (see socketpair(2)). Like socket pipe, this command returns a list of two channels: {s1 s2}. These channels are both readable and writable.

This command creates a socket connected (client) or bound (server) to the given address.

The returned value is channel and may generally be used with the various file I/O commands (gets, puts, read, etc.), either as object-based syntax or Tcl-compatible syntax.

set f [socket stream www.google.com:80]
aio.sockstream1
$f puts -nonewline "GET / HTTP/1.0\r\n\r\n"
$f gets
HTTP/1.0 302 Found
$f close

Server sockets, however support only accept, which is most useful in conjunction with the EVENTLOOP API.

set f [socket stream.server 80]
$f readable {
    set client [$f accept]
    $client gets $buf
    ...
    $client puts -nonewline "HTTP/1.1 404 Not found\r\n"
    $client close
}
vwait done

The address, addr, can be given in one of the following forms:

  1. For IPv4 socket types, an IPv4 address such as 192.168.1.1

  2. For IPv6 socket types, an IPv6 address such as [fe80::1234] or [::]

  3. A hostname

Note that on many systems, listening on an IPv6 address such as [::] will also accept requests via IPv4.

Where a hostname is specified, the first returned address is used which matches the socket type is used.

The special type pipe isn’t really a socket.

lassign [socket pipe] r w
# Must close $w after exec
exec ps >@$w &
$w close
$r readable ...

syslog

syslog ?options? ?priority? message

This command sends message to system syslog facility with given priority. Valid priorities are:

emerg, alert, crit, err, error, warning, notice, info, debug

If a message is specified, but no priority is specified, then a priority of info is used.

By default, facility user is used and the value of global tcl variable argv0 is used as ident string. However, any of the following options may be specified before priority to control these parameters:

-facility value

Use specified facility instead of user. The following values for facility are recognized:

authpriv, cron, daemon, kernel, lpr, mail, news, syslog, user,
uucp, local0-local7
-ident string

Use given string instead of argv0 variable for ident string.

-options integer

Set syslog options such as LOG_CONS, LOG_NDELAY. You should use numeric values of those from your system syslog.h file, because I haven’t got time to implement yet another hash table.

pack: pack, unpack

The optional pack extension provides commands to encode and decode binary strings.

pack varName value -intle|-intbe|-floatle|-floatbe|-str bitwidth ?bitoffset?

Packs the binary representation of value into the variable varName. The value is packed according to the given type (integer/floating point/string, big-endian/little-endian), width and bit offset. The variable is created if necessary (like append). Ihe variable is expanded if necessary.

unpack binvalue -intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str bitpos bitwidth

Unpacks bits from binvalue at bit position bitpos and with bitwidth. Interprets the value according to the type (integer/floating point/string, big-endian/little-endian and signed/unsigned) and returns it. For integer types, bitwidth may be up to the size of a Jim Tcl integer (typically 64 bits). For floating point types, bitwidth may be 32 bits (for single precision numbers) or 64 bits (for double precision). For the string type, both the width and the offset must be on a byte boundary (multiple of 8). Attempting to access outside the length of the value will return 0 for integer types, 0.0 for floating point types or the empty string for the string type.

binary

The optional, pure-Tcl binary extension provides the Tcl-compatible binary scan and binary format commands based on the low-level pack and unpack commands.

Note that binary format with f/r/R specifiers (single-precision float) uses the value of Infinity in case of overflow.

oo: class, super

The optional, pure-Tcl oo extension provides object-oriented (OO) support for Jim Tcl.

See the online documentation (http://jim.tcl.tk/index.html/doc/www/www/documentation/oo/) for more details.

class classname ?baseclasses? classvars

Create a new class, classname, with the given dictionary (classvars) as class variables. These are the initial variables which all newly created objects of this class are initialised with. If a list of baseclasses is given, methods and instance variables are inherited.

super method ?args ...?

From within a method, invokes the given method on the base class. Note that this will only call the last baseclass given.

tree

The optional, pure-Tcl tree extension implements an OO, general purpose tree structure similar to that provided by tcllib ::struct::tree (http://tcllib.sourceforge.net/doc/struct_tree.html)

A tree is a collection of nodes, where each node (except the root node) has a single parent and zero or more child nodes (ordered), as well as zero or more attribute/value pairs.

tree

Creates and returns a new tree object with a single node named "root". All operations on the tree are invoked through this object.

$tree destroy

Destroy the tree and all it’s nodes. (Note that the the tree will also be automatically garbage collected once it goes out of scope).

$tree set nodename key value

Set the value for the given attribute key.

$tree lappend nodename key value ...

Append to the (list) value(s) for the given attribute key, or set if not yet set.

$tree keyexists nodename key

Returns 1 if the given attribute key exists.

$tree get nodename key

Returns the value associated with the given attribute key.

$tree getall nodename

Returns the entire attribute dictionary associated with the given key.

$tree depth nodename

Returns the depth of the given node. The depth of "root" is 0.

$tree parent nodename

Returns the node name of the parent node, or "" for the root node.

$tree numchildren nodename

Returns the number of child nodes.

$tree children nodename

Returns a list of the child nodes.

$tree next nodename

Returns the next sibling node, or "" if none.

$tree insert nodename ?index?

Add a new child node to the given node. The index is a list index such as 3 or end-2. The default index is end. Returns the name of the newly added node.

$tree walk nodename dfs|bfs {actionvar nodevar} script

Walks the tree starting from the given node, either breadth first (bfs) depth first (dfs). The value "enter" or "exit" is stored in variable actionvar. The name of each node is stored in nodevar. The script is evaluated twice for each node, on entry and exit.

$tree dump

Dumps the tree contents to stdout

tcl::prefix

The optional tclprefix extension provides the Tcl8.6-compatible tcl::prefix command (http://www.tcl.tk/man/tcl8.6/TclCmd/prefix.htm) for matching strings against a table of possible values (typically commands or options).

tcl::prefix all table string

Returns a list of all elements in table that begin with the prefix string.

tcl::prefix longest table string

Returns the longest common prefix of all elements in table that begin with the prefix string.

tcl::prefix match ?options? table string

If string equals one element in table or is a prefix to exactly one element, the matched element is returned. If not, the result depends on the -error option.

  • -exact Accept only exact matches.

  • -message string Use string in the error message at a mismatch. Default is "option".

  • -error options The options are used when no match is found. If options is empty, no error is generated and an empty string is returned. Otherwise the options are used as return options when generating the error message. The default corresponds to setting -level 0.

history

The optional history extension provides script access to the command line editing and history support available in jimsh. See examples/jtclsh.tcl for an example. Note: if line editing support is not available, history getline acts like gets and the remaining subcommands do nothing.

history load filename

Load history from a (text) file. If the file does not exist or is not readable, it is ignored.

history getline prompt ?varname?

Displays the given prompt and allows a line to be entered. Similarly to gets, if varname is given, it receives the line and the length of the line is returned, or -1 on EOF. If varname is not given, the line is returned directly.

history add line

Adds the given line to the history buffer.

history save filename

Saves the current history buffer to the given file.

history show

Displays the current history buffer to standard output.

namespace

Provides namespace-related functions. See also: http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm

namespace code script

Captures the current namespace context for later execution of the script script. It returns a new script in which script has been wrapped in a namespace inscope command.

namespace current

Returns the fully-qualified name for the current namespace.

namespace delete ?namespace …?

Deletes all commands and variables with the given namespace prefixes.

namespace eval namespace arg ?arg…?

Activates a namespace called namespace and evaluates some code in that context.

namespace origin command

Returns the fully-qualified name of the original command to which the imported command command refers.

namespace parent ?namespace?

Returns the fully-qualified name of the parent namespace for namespace namespace, if given, otherwise for the current namespace.

namespace qualifiers string

Returns any leading namespace qualifiers for string

namespace tail string

Returns the simple name at the end of a qualified string.

namespace upvar namespace ?arg…?

This command arranges for zero or more local variables in the current procedure to refer to variables in namespace

namespace which ?-command|-variable? name

Looks up name as either a command (the default) or variable and returns its fully-qualified name.

BUILT-IN VARIABLES

The following global variables are created automatically by the Tcl library.

env

This variable is set by Jim as an array whose elements are the environment variables for the process. Reading an element will return the value of the corresponding environment variable. This array is initialised at startup from the env command. It may be modified and will affect the environment passed to commands invoked with exec.

platform_tcl

This variable is set by Jim as an array containing information about the platform on which Jim was built. Currently this includes os and platform.

auto_path

This variable contains a list of paths to search for packages. It defaults to a location based on where jim is installed (e.g. /usr/local/lib/jim), but may be changed by jimsh or the embedding application. Note that jimsh will consider the environment variable $JIMLIB to be a list of colon-separated list of paths to add to auto_path.

errorCode

This variable holds the value of the -errorcode return option set by the most recent error that occurred in this interpreter. This list value represents additional information about the error in a form that is easy to process with programs. The first element of the list identifies a general class of errors, and determines the format of the rest of the list. The following formats for -errorcode return options are used by the Tcl core; individual applications may define additional formats. Currently only exec sets this variable. Otherwise it will be NONE.

The following global variables are set by jimsh.

tcl_interactive

This variable is set to 1 if jimsh is started in interactive mode or 0 otherwise.

tcl_platform

This variable is set by Jim as an array containing information about the platform upon which Jim was built. The following is an example of the contents of this array.

tcl_platform(byteOrder)     = littleEndian
tcl_platform(os)            = Darwin
tcl_platform(platform)      = unix
tcl_platform(pointerSize)   = 8
tcl_platform(threaded)      = 0
tcl_platform(wordSize)      = 8
tcl_platform(pathSeparator) = :
argv0

If jimsh is invoked to run a script, this variable contains the name of the script.

argv

If jimsh is invoked to run a script, this variable contains a list of any arguments supplied to the script.

argc

If jimsh is invoked to run a script, this variable contains the number of arguments supplied to the script.

jim::argv0

The value of argv[0] when jimsh was invoked.

CHANGES IN PREVIOUS RELEASES

In v0.70

  1. platform_tcl() settings are now automatically determined

  2. Add aio $handle filename

  3. Add info channels

  4. The bio extension is gone. Now aio supports copyto.

  5. Add exists command

  6. Add the pure-Tcl oo extension

  7. The exec command now only uses vfork(), not fork()

  8. Unit test framework is less verbose and more Tcl-compatible

  9. Optional UTF-8 support

  10. Optional built-in regexp engine for better Tcl compatibility and UTF-8 support

  11. Command line editing in interactive mode, e.g. jimsh

In v0.63

  1. source now checks that a script is complete (.i.e. not missing a brace)

  2. info complete now uses the real parser and so is 100% accurate

  3. Better access to live stack frames with info frame, stacktrace and stackdump

  4. tailcall no longer loses stack trace information

  5. Add alias and curry

  6. lambda, alias and curry are implemented via tailcall for efficiency

  7. local allows procedures to be deleted automatically at the end of the current procedure

  8. udp sockets are now supported for both clients and servers.

  9. vfork-based exec is now working correctly

  10. Add file tempfile

  11. Add socket pipe

  12. Enhance try … on … finally to be more Tcl 8.6 compatible

  13. It is now possible to return from within try

  14. IPv6 support is now included

  15. Add string is

  16. Event handlers works better if an error occurs. eof handler has been removed.

  17. exec now sets $::errorCode, and catch sets opts(-errorcode) for exit status

  18. Command pipelines via open "|…" are now supported

  19. pid can now return pids of a command pipeline

  20. Add info references

  21. Add support for after 'ms, 'after idle, after info, update

  22. exec now sets environment based on $::env

  23. Add dict keys

  24. Add support for lsort -index

In v0.62

  1. Add support to exec for >&, >>&, |&, 2>@1

  2. Fix exec error messages when special token (e.g. >) is the last token

  3. Fix subst handling of backslash escapes.

  4. Allow abbreviated options for subst

  5. Add support for return, break, continue in subst

  6. Many expr bug fixes

  7. Add support for functions in expr (e.g. int(), abs()), and also in, ni list operations

  8. The variable name argument to regsub is now optional

  9. Add support for unset -nocomplain

  10. Add support for list commands: lassign, lrepeat

  11. Fully-functional lsearch is now implemented

  12. Add info nameofexecutable and info returncodes

  13. Allow catch to determine what return codes are caught

  14. Allow incr to increment an unset variable by first setting to 0

  15. Allow args and optional arguments to the left or required arguments in proc

  16. Add file copy

  17. Add try … finally command

LICENCE

Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
Copyright 2008 oharboe - Oyvind Harboe - oyvind.harboe@zylin.com
Copyright 2008 Andrew Lunn <andrew@lunn.ch>
Copyright 2008 Duane Ellis <openocd@duaneellis.com>
Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
Copyright 2009 Steve Bennett <steveb@workware.net.au>
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.
THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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
JIM TCL PROJECT 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.
The views and conclusions contained in the software and documentation
are those of the authors and should not be interpreted as representing
official policies, either expressed or implied, of the Jim Tcl Project.

openocd-0.9.0/jimtcl/UnicodeData.txt0000644000175000017500000456473712315602574014332 000000000000000000;;Cc;0;BN;;;;;N;NULL;;;; 0001;;Cc;0;BN;;;;;N;START OF HEADING;;;; 0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; 0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; 0004;;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; 0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; 0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;;Cc;0;BN;;;;;N;BELL;;;; 0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; 0009;;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; 000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; 000B;;Cc;0;S;;;;;N;LINE TABULATION;;;; 000C;;Cc;0;WS;;;;;N;FORM FEED (FF);;;; 000D;;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; 000E;;Cc;0;BN;;;;;N;SHIFT OUT;;;; 000F;;Cc;0;BN;;;;;N;SHIFT IN;;;; 0010;;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; 0011;;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; 0012;;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; 0013;;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; 0014;;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; 0015;;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; 0016;;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; 0017;;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; 0018;;Cc;0;BN;;;;;N;CANCEL;;;; 0019;;Cc;0;BN;;;;;N;END OF MEDIUM;;;; 001A;;Cc;0;BN;;;;;N;SUBSTITUTE;;;; 001B;;Cc;0;BN;;;;;N;ESCAPE;;;; 001C;;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; 001D;;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; 001E;;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; 001F;;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; 0020;SPACE;Zs;0;WS;;;;;N;;;;; 0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; 0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; 0026;AMPERSAND;Po;0;ON;;;;;N;;;;; 0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; 0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; 0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; 002A;ASTERISK;Po;0;ON;;;;;N;;;;; 002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;; 002C;COMMA;Po;0;CS;;;;;N;;;;; 002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;; 002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; 002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;; 0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; 0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; 0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; 0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; 0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; 0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; 0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; 0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; 0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; 0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; 003A;COLON;Po;0;CS;;;;;N;;;;; 003B;SEMICOLON;Po;0;ON;;;;;N;;;;; 003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; 0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; 0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; 0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; 0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; 0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; 0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; 0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; 0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; 0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; 0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; 004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; 004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; 004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; 004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; 004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; 004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; 0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; 0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; 0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; 0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; 0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; 0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; 0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; 0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; 0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; 0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; 005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; 005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; 005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; 005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; 005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; 005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; 0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; 0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A 006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B 006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C 006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D 006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E 006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F 0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A 007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; 007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; 007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; 007E;TILDE;Sm;0;ON;;;;;N;;;;; 007F;;Cc;0;BN;;;;;N;DELETE;;;; 0080;;Cc;0;BN;;;;;N;;;;; 0081;;Cc;0;BN;;;;;N;;;;; 0082;;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; 0083;;Cc;0;BN;;;;;N;NO BREAK HERE;;;; 0084;;Cc;0;BN;;;;;N;;;;; 0085;;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; 0086;;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; 0087;;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; 0088;;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; 0089;;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; 008A;;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; 008B;;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; 008C;;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; 008D;;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; 008E;;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; 008F;;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; 0090;;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; 0091;;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; 0092;;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; 0093;;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; 0094;;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; 0095;;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; 0096;;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; 0097;;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; 0098;;Cc;0;BN;;;;;N;START OF STRING;;;; 0099;;Cc;0;BN;;;;;N;;;;; 009A;;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; 009B;;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; 009C;;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; 009D;;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; 009E;;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; 009F;;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; 00A0;NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;NON-BREAKING SPACE;;;; 00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; 00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; 00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; 00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; 00A7;SECTION SIGN;So;0;ON;;;;;N;;;;; 00A8;DIAERESIS;Sk;0;ON; 0020 0308;;;;N;SPACING DIAERESIS;;;; 00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; 00AA;FEMININE ORDINAL INDICATOR;Ll;0;L; 0061;;;;N;;;;; 00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;; 00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; 00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;; 00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; 00AF;MACRON;Sk;0;ON; 0020 0304;;;;N;SPACING MACRON;;;; 00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; 00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; 00B2;SUPERSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;; 00B3;SUPERSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;; 00B4;ACUTE ACCENT;Sk;0;ON; 0020 0301;;;;N;SPACING ACUTE;;;; 00B5;MICRO SIGN;Ll;0;L; 03BC;;;;N;;;039C;;039C 00B6;PILCROW SIGN;So;0;ON;;;;;N;PARAGRAPH SIGN;;;; 00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; 00B8;CEDILLA;Sk;0;ON; 0020 0327;;;;N;SPACING CEDILLA;;;; 00B9;SUPERSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; 00BA;MASCULINE ORDINAL INDICATOR;Ll;0;L; 006F;;;;N;;;;; 00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; 00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; 00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; 00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; 00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; 00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; 00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; 00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; 00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; 00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; 00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6; 00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; 00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; 00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; 00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; 00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; 00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; 00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; 00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; 00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; 00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0; 00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; 00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; 00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; 00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; 00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; 00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; 00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; 00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; 00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; 00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; 00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; 00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; 00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE; 00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;; 00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6 00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA 00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB 00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC 00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD 00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE 00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF 00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0 00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA 00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB 00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC 00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD 00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE 00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; 0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; 0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; 0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; 0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; 0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; 010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A 010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; 010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C 010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; 010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E 0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; 0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; 0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; 0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; 0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; 0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; 011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A 011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; 011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C 011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; 011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E 0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; 0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; 0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; 0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; 0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; 0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; 012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A 012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; 012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C 012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; 012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E 0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L; 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; 0133;LATIN SMALL LIGATURE IJ;Ll;0;L; 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; 0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; 0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;; 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; 013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; 013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B 013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; 013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L; 004C 00B7;;;;N;;;;0140; 0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L; 006C 00B7;;;;N;;;013F;;013F 0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; 0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; 0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; 0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L; 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; 014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B; 014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A 014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; 014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C 014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; 014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E 0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; 0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; 0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; 0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; 0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; 0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; 015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A 015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; 015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C 015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F; 015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E 0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; 0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163; 0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162 0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; 0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; 0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; 0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; 016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A 016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; 016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C 016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; 016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E 0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; 0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; 0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; 0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; 0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; 0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; 017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; 017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B 017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; 017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D 017F;LATIN SMALL LETTER LONG S;Ll;0;L; 0073;;;;N;;;0053;;0053 0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243 0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; 0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; 0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; 0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; 0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; 0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256; 018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; 018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; 018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B 018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; 018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; 018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; 0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; 0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; 0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; 0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; 0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6 0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; 0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; 0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; 0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D 019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;; 019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; 019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; 019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275; 01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; 01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3; 01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2 01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; 01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280; 01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; 01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; 01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; 01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; 01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; 01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC 01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; 01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; 01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF 01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; 01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; 01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; 01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; 01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; 01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; 01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; 01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; 01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; 01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC 01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; 01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; 01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; 01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; 01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; 01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L; 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L; 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5 01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L; 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 01C7;LATIN CAPITAL LETTER LJ;Lu;0;L; 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L; 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8 01C9;LATIN SMALL LETTER LJ;Ll;0;L; 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 01CA;LATIN CAPITAL LETTER NJ;Lu;0;L; 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB 01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L; 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB 01CC;LATIN SMALL LETTER NJ;Ll;0;L; 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB 01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; 01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD 01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; 01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF 01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; 01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; 01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; 01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; 01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; 01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; 01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB 01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E 01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; 01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE 01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; 01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3; 01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2 01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; 01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; 01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; 01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; 01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA 01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; 01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC 01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; 01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE 01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; 01F1;LATIN CAPITAL LETTER DZ;Lu;0;L; 0044 005A;;;;N;;;;01F3;01F2 01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L; 0044 007A;;;;N;;;01F1;01F3;01F2 01F3;LATIN SMALL LETTER DZ;Ll;0;L; 0064 007A;;;;N;;;01F1;;01F2 01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; 01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; 01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; 01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; 01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; 01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA 01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD; 01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC 01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; 01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE 0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; 0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; 0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; 0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; 0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; 0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; 020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A 020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; 020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C 020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; 020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E 0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; 0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; 0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; 0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; 0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219; 0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218 021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B; 021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A 021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; 021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C 021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; 021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E 0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; 0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;; 0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; 0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; 0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; 0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; 0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; 022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A 022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; 022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C 022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; 022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E 0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; 0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; 0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;; 0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;; 0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;; 0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;; 0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;; 0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;; 023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65; 023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C; 023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B 023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A; 023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66; 023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E 0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F 0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242; 0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241 0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180; 0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289; 0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C; 0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247; 0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246 0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249; 0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248 024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B; 024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A 024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D; 024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C 024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F; 024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E 0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F 0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D 0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70 0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; 0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A 0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; 0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F 025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; 025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;;; 025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; 025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; 025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; 0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;;; 0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; 0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; 0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;;; 0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;;; 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;; 026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;;; 026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; 026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; 026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C 0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; 0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E 0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D 0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; 0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; 0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F 0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; 0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; 0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; 0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; 027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; 027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64 027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; 027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; 0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6 0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; 0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;; 0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; 0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; 0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; 0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;;; 0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE 0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244 028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245 028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; 028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; 028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; 0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; 0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; 0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; 0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; 0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; 0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; 0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; 0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; 029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; 029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; 029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; 029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;; 029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;;; 029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; 02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; 02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; 02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; 02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; 02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; 02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; 02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; 02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; 02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; 02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; 02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; 02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; 02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;; 02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;; 02B0;MODIFIER LETTER SMALL H;Lm;0;L; 0068;;;;N;;;;; 02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L; 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; 02B2;MODIFIER LETTER SMALL J;Lm;0;L; 006A;;;;N;;;;; 02B3;MODIFIER LETTER SMALL R;Lm;0;L; 0072;;;;N;;;;; 02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L; 0279;;;;N;;;;; 02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L; 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; 02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L; 0281;;;;N;;;;; 02B7;MODIFIER LETTER SMALL W;Lm;0;L; 0077;;;;N;;;;; 02B8;MODIFIER LETTER SMALL Y;Lm;0;L; 0079;;;;N;;;;; 02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;; 02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;; 02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; 02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; 02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; 02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; 02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; 02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;; 02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;; 02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;; 02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;; 02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;; 02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; 02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; 02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; 02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; 02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; 02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; 02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; 02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; 02D8;BREVE;Sk;0;ON; 0020 0306;;;;N;SPACING BREVE;;;; 02D9;DOT ABOVE;Sk;0;ON; 0020 0307;;;;N;SPACING DOT ABOVE;;;; 02DA;RING ABOVE;Sk;0;ON; 0020 030A;;;;N;SPACING RING ABOVE;;;; 02DB;OGONEK;Sk;0;ON; 0020 0328;;;;N;SPACING OGONEK;;;; 02DC;SMALL TILDE;Sk;0;ON; 0020 0303;;;;N;SPACING TILDE;;;; 02DD;DOUBLE ACUTE ACCENT;Sk;0;ON; 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; 02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; 02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; 02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L; 0263;;;;N;;;;; 02E1;MODIFIER LETTER SMALL L;Lm;0;L; 006C;;;;N;;;;; 02E2;MODIFIER LETTER SMALL S;Lm;0;L; 0073;;;;N;;;;; 02E3;MODIFIER LETTER SMALL X;Lm;0;L; 0078;;;;N;;;;; 02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L; 0295;;;;N;;;;; 02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; 02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;; 02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; 02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; 02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;; 02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;; 02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;; 02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;; 02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;; 02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;; 02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;; 02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;; 02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;; 0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; 0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;; 0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; 0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; 0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; 0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; 0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;; 0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; 0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;; 0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; 030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; 030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; 030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; 030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; 030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; 030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; 0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; 0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; 0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; 0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;; 0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;; 0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; 0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; 0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; 0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; 0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; 031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; 031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; 031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; 031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; 031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; 031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; 0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; 0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; 0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; 0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; 0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; 0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; 0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; 0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; 0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; 0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; 032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; 032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; 032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; 032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; 032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; 032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; 0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; 0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; 0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; 0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; 0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; 0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; 0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; 0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; 0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; 0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; 033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; 033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; 033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; 033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; 033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; 033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; 0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;; 0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;; 0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; 0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; 0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; 0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; 0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; 034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; 034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; 034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; 034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; 0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;; 0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;; 0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; 0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;; 035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;; 035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;; 035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;; 035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;; 0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; 0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; 0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; 0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; 0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; 0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; 0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; 0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; 0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; 0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; 036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; 036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; 036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; 036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; 036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; 036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; 0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371; 0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370 0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373; 0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372 0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;; 0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;; 0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377; 0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376 037A;GREEK YPOGEGRAMMENI;Lm;0;L; 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; 037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD 037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE 037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF 037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;; 0384;GREEK TONOS;Sk;0;ON; 0020 0301;;;;N;GREEK SPACING TONOS;;;; 0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; 0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; 0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; 0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; 0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; 038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; 038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; 038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; 038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; 0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; 0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; 0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; 0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; 0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; 0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; 0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; 0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; 0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; 039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; 039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; 039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; 039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; 039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; 039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; 03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; 03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; 03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; 03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; 03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; 03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; 03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; 03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; 03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; 03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; 03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; 03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A 03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; 03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A 03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B 03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C 03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D 03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E 03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F 03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA 03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB 03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C 03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E 03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F 03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7; 03D0;GREEK BETA SYMBOL;Ll;0;L; 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 03D1;GREEK THETA SYMBOL;Ll;0;L; 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L; 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; 03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; 03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; 03D5;GREEK PHI SYMBOL;Ll;0;L; 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 03D6;GREEK PI SYMBOL;Ll;0;L; 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF 03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9; 03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8 03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; 03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA 03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; 03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC 03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; 03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE 03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; 03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; 03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; 03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; 03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; 03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; 03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA 03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; 03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC 03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; 03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE 03F0;GREEK KAPPA SYMBOL;Ll;0;L; 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A 03F1;GREEK RHO SYMBOL;Ll;0;L; 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L; 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9 03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;;; 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L; 0398;;;;N;;;;03B8; 03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L; 03B5;;;;N;;;0395;;0395 03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; 03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8; 03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7 03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L; 03A3;;;;N;;;;03F2; 03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB; 03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA 03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;; 03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B; 03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C; 03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D; 0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; 0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; 0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452; 0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; 0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; 0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; 0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; 0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457; 0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; 0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; 040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; 040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B; 040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; 040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; 040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E; 040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; 0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; 0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; 0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; 0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; 0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; 0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; 0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; 0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; 0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; 0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; 041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; 041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; 041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; 041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; 041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; 041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; 0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; 0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; 0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; 0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; 0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; 0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; 0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; 0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; 0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; 0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; 042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; 042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; 042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; 042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; 042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; 042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; 0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A 043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B 043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C 043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D 043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E 043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F 0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A 044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B 044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C 044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D 044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E 044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F 0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402 0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407 0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A 045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B 045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C 045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D 045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E 045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F 0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; 0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; 0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; 0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; 0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; 0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; 046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A 046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; 046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C 046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; 046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E 0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; 0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; 0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; 0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; 0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; 0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; 047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A 047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; 047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C 047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; 047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E 0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; 0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; 0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; 0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; 0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; 0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; 0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;; 0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; 0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; 048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A 048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; 048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C 048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; 048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E 0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; 0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; 0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; 0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; 0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; 0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; 049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A 049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; 049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C 049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; 049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E 04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; 04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; 04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; 04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7; 04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6 04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; 04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; 04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA 04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; 04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC 04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; 04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE 04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; 04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; 04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5; 04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4 04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; 04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; 04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; 04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA 04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; 04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC 04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; 04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE 04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF; 04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; 04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; 04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; 04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; 04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; 04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; 04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB 04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; 04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD 04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0 04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; 04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; 04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; 04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; 04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; 04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; 04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA 04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; 04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC 04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; 04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE 04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; 04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; 04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; 04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; 04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; 04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; 04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA 04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; 04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC 04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; 04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE 04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; 04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; 04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; 04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7; 04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6 04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; 04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB; 04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA 04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD; 04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC 04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF; 04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE 0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; 0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; 0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; 0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; 0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; 0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; 050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A 050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; 050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C 050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; 050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E 0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511; 0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510 0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513; 0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512 0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515; 0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514 0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517; 0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516 0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519; 0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518 051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B; 051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A 051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D; 051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C 051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F; 051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E 0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521; 0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520 0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523; 0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; 0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; 0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; 0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; 0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; 0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; 0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; 0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; 0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; 0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; 053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; 053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; 053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; 053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; 053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; 053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; 0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; 0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; 0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; 0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; 0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; 0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; 0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; 0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; 0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; 0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; 054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; 054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; 054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; 054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; 054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; 054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; 0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; 0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; 0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; 0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; 0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; 0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; 0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; 0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; 055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; 055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; 055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; 055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; 055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; 0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A 056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B 056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C 056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D 056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E 056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F 0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A 057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B 057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C 057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D 057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E 057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F 0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L; 0565 0582;;;;N;;;;; 0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; 058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; 0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; 0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; 0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; 0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; 0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; 0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;; 0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; 0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;; 0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; 059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; 059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; 059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; 059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; 059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; 059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; 05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; 05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; 05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;; 05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; 05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; 05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;; 05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; 05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; 05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;; 05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; 05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;; 05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; 05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; 05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; 05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; 05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; 05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; 05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; 05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; 05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; 05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; 05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; 05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; 05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; 05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; 05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; 05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;; 05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; 05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;; 05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;; 05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;; 05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; 05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;; 05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; 05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; 05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;; 05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; 05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;; 05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;; 05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;; 05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; 05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; 05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; 05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; 05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; 05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; 05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; 05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; 05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; 05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; 05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; 05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; 05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; 05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; 05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; 05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; 05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; 05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; 05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; 05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; 05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; 05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; 05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; 05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; 05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; 05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; 05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; 05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; 0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;; 0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;; 0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;; 0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;; 0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;; 0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;; 0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;; 0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;; 060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; 060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;; 060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;; 060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;; 0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;; 0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;; 0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;; 0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;; 0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;; 0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;; 0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;; 0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;; 0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;; 0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;; 061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; 0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; 0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; 0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; 0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; 0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; 0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; 0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; 0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; 0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; 062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; 062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; 062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; 062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; 062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; 062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; 0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; 0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; 0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; 0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; 0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; 0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; 0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; 0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; 0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; 063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; 063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; 0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; 0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; 0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; 0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; 0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; 0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; 0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; 0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; 064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; 064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; 064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; 064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; 064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; 064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; 0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; 0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; 0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; 0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; 0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; 0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;; 0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;; 0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; 0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;; 065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; 065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; 0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; 0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; 0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; 0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; 0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; 0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; 0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; 0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; 0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; 0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; 066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; 066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; 066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; 066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; 066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; 066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; 0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; 0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; 0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; 0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; 0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; 0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL; 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; 0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL; 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; 0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL; 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; 0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL; 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; 0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; 067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; 067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; 067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; 067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; 067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; 067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; 0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; 0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; 0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; 0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; 0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; 0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; 0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; 0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; 0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; 0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; 068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; 068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; 068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; 068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; 0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; 0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; 0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; 0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; 0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; 0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; 0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; 0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; 0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; 069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; 06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; 06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; 06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; 06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; 06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; 06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; 06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; 06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; 06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; 06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; 06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; 06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;; 06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; 06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; 06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; 06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; 06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; 06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; 06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; 06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; 06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; 06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; 06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; 06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; 06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; 06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; 06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; 06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; 06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; 06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; 06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; 06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; 06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; 06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; 06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;; 06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; 06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; 06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; 06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; 06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; 06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; 06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; 06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; 06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; 06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; 06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; 06DE;ARABIC START OF RUB EL HIZB;Me;0;NSM;;;;;N;;;;; 06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; 06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; 06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; 06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; 06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; 06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; 06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; 06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; 06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; 06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; 06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; 06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; 06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; 06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; 06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; 06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; 06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; 06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; 06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; 06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; 06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; 06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; 06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; 06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; 06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; 06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; 06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; 06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; 0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; 0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; 0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; 0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; 070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; 070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; 070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; 070F;SYRIAC ABBREVIATION MARK;Cf;0;BN;;;;;N;;;;; 0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; 0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; 0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; 0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; 0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; 0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; 0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; 0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; 0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; 071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; 071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; 071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; 071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; 071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; 0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; 0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; 0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; 0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; 0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; 0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; 0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; 0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; 0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; 0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; 072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; 072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; 072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; 072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;; 072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;; 072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;; 0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; 0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; 0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; 0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; 0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; 073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; 073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; 073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; 073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; 0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; 0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; 0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; 0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; 0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; 074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; 074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;; 074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;; 074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;; 0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;; 0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; 0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;; 075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;; 075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;; 0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;; 076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;; 076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;; 076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; 0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;; 077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; 0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; 0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; 0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; 0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; 0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; 0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; 0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; 0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; 0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; 078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; 078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; 078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; 078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; 078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; 078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; 0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; 0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; 0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; 0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; 0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; 0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; 0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; 0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; 0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; 0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; 079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; 079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; 079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; 079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; 079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; 079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; 07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; 07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; 07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; 07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; 07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; 07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; 07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; 07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; 07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; 07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; 07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; 07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; 07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; 07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; 07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; 07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; 07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; 07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; 07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; 07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; 07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; 07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; 07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; 07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; 07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; 07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; 07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; 07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; 07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;; 07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;; 07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;; 07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;; 07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;; 07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;; 07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;; 07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;; 07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;; 07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;; 07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;; 07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;; 07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;; 07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;; 07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;; 07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;; 07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;; 07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;; 07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;; 07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;; 07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;; 07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;; 07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;; 07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;; 07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;; 07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;; 07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;; 07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;; 07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;; 07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;; 07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;; 07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;; 07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;; 07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;; 07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;; 07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;; 07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;; 07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;; 07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;; 07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;; 07F8;NKO COMMA;Po;0;ON;;;;;N;;;;; 07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;; 0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;; 0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;; 0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;; 0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;; 0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;; 0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;; 0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;; 0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;; 0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;; 0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;; 080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;; 080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;; 080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;; 080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;; 080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;; 080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;; 0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;; 0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;; 0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;; 0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;; 0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;; 0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;; 0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;; 0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;; 0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;; 0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;; 081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;; 081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;; 081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;; 081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; 081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;; 081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;; 0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;; 0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;; 0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;; 0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;; 0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;; 0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;; 0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;; 0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;; 0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;; 0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;; 082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;; 082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;; 082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;; 0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;; 0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;; 0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;; 0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;; 0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;; 0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;; 0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;; 0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;; 0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;; 0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;; 083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;; 083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;; 083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; 083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; 083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; 0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;; 0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; 0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; 0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; 0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; 0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; 090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; 090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; 090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; 090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; 0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; 0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; 0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; 0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; 0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; 0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; 0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; 0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; 0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; 0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; 091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; 091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; 091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; 091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; 091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; 091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; 0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; 0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; 0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; 0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; 0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; 0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; 0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; 0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; 092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; 092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; 092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; 092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; 092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; 092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; 0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; 0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; 0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; 0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; 0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; 0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; 0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; 0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; 0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; 0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; 093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; 0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; 0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; 0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; 0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; 0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; 0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; 095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; 095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; 095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; 095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; 095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; 095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; 0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; 0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; 0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; 0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; 097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; 097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; 097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;; 097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;; 097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;; 0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; 0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; 0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; 0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; 0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; 098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; 098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; 0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; 0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; 0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; 0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; 0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; 0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; 0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; 0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; 099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; 099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; 099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; 099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; 099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; 099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; 09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; 09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; 09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; 09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; 09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; 09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; 09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; 09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; 09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; 09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; 09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; 09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; 09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; 09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; 09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; 09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; 09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; 09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; 09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; 09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; 09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; 09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; 09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; 09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;; 09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; 09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; 09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; 09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;; 09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;; 09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; 09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;; 09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;; 09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;; 09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;; 09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;; 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; 0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; 0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; 0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; 0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; 0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; 0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; 0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; 0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; 0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; 0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; 0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; 0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; 0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; 0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; 0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; 0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; 0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; 0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; 0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; 0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; 0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; 0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; 0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; 0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; 0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; 0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; 0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; 0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; 0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; 0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; 0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; 0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; 0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; 0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; 0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;; 0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; 0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; 0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; 0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; 0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; 0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; 0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; 0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; 0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; 0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; 0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;; 0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; 0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; 0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; 0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; 0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; 0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; 0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; 0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; 0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; 0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; 0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; 0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; 0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; 0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; 0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; 0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; 0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; 0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; 0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; 0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; 0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; 0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; 0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; 0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; 0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; 0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; 0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; 0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; 0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; 0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; 0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; 0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; 0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; 0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; 0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; 0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; 0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; 0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; 0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; 0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; 0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; 0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; 0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; 0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; 0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; 0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; 0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; 0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; 0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; 0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; 0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; 0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; 0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; 0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; 0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; 0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; 0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; 0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; 0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; 0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; 0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; 0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; 0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; 0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; 0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; 0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; 0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; 0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; 0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; 0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; 0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; 0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; 0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; 0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; 0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; 0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; 0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;; 0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; 0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; 0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; 0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; 0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; 0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; 0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; 0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; 0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; 0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; 0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; 0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; 0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; 0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; 0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; 0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; 0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; 0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; 0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; 0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; 0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; 0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; 0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; 0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; 0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; 0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; 0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; 0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; 0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; 0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; 0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; 0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; 0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; 0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; 0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; 0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; 0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; 0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; 0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; 0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; 0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; 0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; 0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; 0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; 0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;; 0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; 0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; 0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; 0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; 0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; 0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; 0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;; 0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; 0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;; 0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;; 0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;; 0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;; 0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;; 0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;; 0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;; 0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; 0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; 0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; 0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; 0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; 0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; 0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; 0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; 0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; 0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; 0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; 0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; 0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; 0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; 0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; 0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; 0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; 0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; 0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; 0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; 0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; 0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; 0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; 0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; 0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; 0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; 0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; 0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; 0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; 0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; 0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; 0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; 0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; 0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; 0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; 0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; 0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; 0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; 0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; 0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; 0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; 0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; 0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; 0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; 0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; 0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; 0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; 0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; 0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; 0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; 0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; 0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; 0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;; 0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; 0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; 0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; 0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; 0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; 0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; 0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; 0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; 0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; 0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; 0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; 0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; 0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; 0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; 0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; 0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; 0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; 0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; 0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; 0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; 0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; 0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; 0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; 0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; 0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; 0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; 0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; 0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; 0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; 0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; 0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; 0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; 0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; 0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; 0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; 0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; 0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; 0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; 0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; 0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; 0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; 0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; 0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; 0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; 0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; 0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; 0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;; 0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; 0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;; 0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; 0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; 0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; 0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; 0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; 0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;So;0;ON;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;So;0;ON;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; 0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; 0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; 0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; 0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; 0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; 0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; 0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; 0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; 0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; 0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; 0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; 0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; 0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; 0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; 0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; 0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; 0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; 0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; 0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; 0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; 0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; 0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; 0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; 0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; 0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; 0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; 0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; 0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; 0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; 0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; 0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; 0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; 0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; 0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; 0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; 0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; 0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; 0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; 0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; 0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; 0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; 0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; 0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; 0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;; 0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; 0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; 0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; 0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; 0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;; 0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;; 0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;; 0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;; 0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; 0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; 0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; 0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; 0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; 0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; 0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; 0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; 0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; 0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; 0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; 0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; 0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; 0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; 0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; 0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; 0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; 0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; 0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; 0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; 0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; 0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; 0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; 0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; 0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; 0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; 0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; 0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; 0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; 0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; 0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; 0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; 0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; 0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; 0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; 0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; 0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; 0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; 0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; 0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; 0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; 0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; 0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; 0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; 0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; 0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; 0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; 0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; 0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; 0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; 0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; 0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; 0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; 0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; 0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; 0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; 0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; 0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; 0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; 0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; 0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; 0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; 0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; 0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; 0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; 0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; 0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; 0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; 0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; 0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; 0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; 0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; 0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; 0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; 0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; 0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; 0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; 0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; 0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; 0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; 0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; 0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; 0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; 0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; 0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;; 0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; 0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; 0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; 0E33;THAI CHARACTER SARA AM;Lo;0;L; 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; 0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; 0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; 0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; 0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;; 0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; 0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; 0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; 0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; 0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; 0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; 0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; 0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;; 0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;; 0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;; 0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;; 0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;; 0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; 0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; 0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; 0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; 0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; 0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;; 0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; 0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; 0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; 0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; 0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; 0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; 0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; 0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; 0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; 0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; 0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; 0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; 0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; 0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; 0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; 0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; 0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; 0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; 0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; 0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; 0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; 0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; 0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; 0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; 0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; 0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; 0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; 0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; 0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; 0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; 0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; 0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; 0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; 0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; 0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; 0EB3;LAO VOWEL SIGN AM;Lo;0;L; 0ECD 0EB2;;;;N;;;;; 0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; 0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; 0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; 0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; 0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; 0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; 0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; 0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; 0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; 0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; 0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; 0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; 0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; 0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; 0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; 0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; 0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; 0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0EDC;LAO HO NO;Lo;0;L; 0EAB 0E99;;;;N;;;;; 0EDD;LAO HO MO;Lo;0;L; 0EAB 0EA1;;;;N;;;;; 0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; 0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;; 0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;; 0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;; 0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;; 0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;; 0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;; 0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;; 0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;; 0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;; 0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;; 0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L; 0F0B;;;;N;;;;; 0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;; 0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;; 0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;; 0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;; 0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;; 0F14;TIBETAN MARK GTER TSHEG;So;0;L;;;;;N;TIBETAN COMMA;;;; 0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;; 0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;; 0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;; 0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;; 0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;; 0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;; 0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;; 0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;; 0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;; 0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;; 0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;; 0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; 0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; 0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; 0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; 0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; 0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; 0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; 0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; 0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; 0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; 0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;; 0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;; 0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;; 0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;; 0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;; 0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;; 0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;; 0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;; 0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;; 0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;; 0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;; 0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;; 0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; 0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; 0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; 0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; 0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; 0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; 0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; 0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; 0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; 0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; 0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; 0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; 0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; 0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; 0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; 0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; 0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; 0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; 0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; 0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; 0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; 0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; 0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; 0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; 0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; 0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; 0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; 0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; 0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; 0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; 0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; 0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; 0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;; 0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; 0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; 0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; 0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; 0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; 0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; 0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; 0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;; 0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;; 0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;; 0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; 0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; 0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; 0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; 0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; 0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; 0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM; 0FB2 0F81;;;;N;;;;; 0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; 0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM; 0FB3 0F81;;;;N;;;;; 0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; 0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; 0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; 0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; 0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;; 0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;; 0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; 0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; 0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;; 0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;; 0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; 0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; 0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;; 0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;; 0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;; 0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; 0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; 0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; 0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; 0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; 0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; 0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; 0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; 0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; 0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; 0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; 0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; 0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; 0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; 0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; 0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; 0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; 0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; 0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; 0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; 0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; 0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; 0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; 0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; 0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; 0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; 0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; 0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; 0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; 0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; 0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; 0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; 0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;; 0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; 0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; 0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; 0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; 0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; 0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; 0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; 0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; 0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;; 0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;; 0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;; 0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;; 0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;; 0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; 0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; 0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;; 0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;; 0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;; 0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;; 0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;; 0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;; 0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;; 0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;; 0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;; 0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;; 0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;; 0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;; 0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;; 0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;; 0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;; 0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; 1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; 1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; 1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; 1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; 1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; 1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; 1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; 1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; 1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; 100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; 100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; 100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; 100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; 100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; 100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; 1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; 1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; 1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; 1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; 1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; 1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; 1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; 1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; 1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; 1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; 101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; 101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; 101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; 101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; 101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; 101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; 1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; 1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; 1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;; 1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; 1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; 1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; 1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; 1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; 1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;; 1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; 102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; 102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;; 1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;; 1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; 1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;; 103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; 103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;; 103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; 104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; 104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; 104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; 104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; 104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; 1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; 1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; 1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;; 105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;; 105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;; 105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;; 105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;; 105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;; 1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;; 1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;; 1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;; 1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;; 1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;; 1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;; 1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;; 1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;; 1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;; 106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;; 106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;; 106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;; 106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;; 106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;; 106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;; 1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;; 1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;; 1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;; 1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;; 1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;; 1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;; 1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;; 1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;; 1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;; 1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;; 107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;; 107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;; 107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;; 107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;; 107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;; 107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;; 1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;; 1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;; 1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;; 1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;; 1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;; 1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;; 1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;; 1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;; 108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;; 108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;; 108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;; 108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;; 108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;; 108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;; 1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;; 109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;; 109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;; 109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;; 109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;; 109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;; 10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00; 10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01; 10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02; 10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03; 10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04; 10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05; 10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06; 10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07; 10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08; 10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09; 10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A; 10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B; 10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C; 10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D; 10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E; 10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F; 10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10; 10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11; 10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12; 10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13; 10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14; 10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15; 10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16; 10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17; 10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18; 10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19; 10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A; 10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B; 10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C; 10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D; 10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E; 10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F; 10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20; 10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21; 10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22; 10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23; 10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24; 10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25; 10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;; 10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;; 10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;; 10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;; 10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;; 10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;; 10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;; 10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;; 10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;; 10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;; 10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;; 10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;; 10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;; 10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;; 10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;; 10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;; 10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;; 10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;; 10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;; 10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;; 10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;; 10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;; 10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;; 10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;; 10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;; 10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;; 10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;; 10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;; 10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;; 10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;; 10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;; 10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;; 10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;; 10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;; 10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;; 10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;; 10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;; 10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;; 10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;; 10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;; 10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;; 10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;; 10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;; 10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L; 10DC;;;;N;;;;; 1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;; 1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; 1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;; 1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;; 1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;; 1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; 1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;; 110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; 110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;; 110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; 110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;; 1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; 1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; 111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; 1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; 1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; 1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; 1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; 112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; 112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; 112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; 1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; 1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; 1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; 1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; 113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; 113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; 113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; 113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; 113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; 1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; 1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; 1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; 1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; 1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; 114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; 114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; 114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; 114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; 114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; 1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; 1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; 1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; 1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;; 115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; 1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; 1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; 1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; 1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; 1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; 1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; 1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; 1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; 1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; 1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; 116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; 116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; 116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; 116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; 116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; 116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; 1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; 1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; 1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; 1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; 1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; 1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; 1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; 1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; 1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; 1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; 117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; 117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; 117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; 117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; 117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; 117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; 1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; 1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; 1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; 1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; 1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; 1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; 1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; 1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; 1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; 1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; 118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; 118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; 118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; 118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; 118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; 118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; 1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; 1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; 1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; 1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; 1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; 1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; 1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; 1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; 1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; 1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; 119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; 119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; 119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; 119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; 119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; 119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; 11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; 11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; 11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; 11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;; 11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;; 11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;; 11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;; 11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;; 11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;; 11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;; 11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; 11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; 11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; 11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; 11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;; 11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; 11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;; 11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;; 11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;; 11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;; 11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;; 11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;; 11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; 11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; 11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; 11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; 11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; 11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; 11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; 11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; 11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; 11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; 11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; 11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; 11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; 11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; 11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; 11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; 11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; 11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; 11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;; 11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;; 11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;; 11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;; 11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; 11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; 1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; 1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; 1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; 1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; 1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; 1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; 1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;; 1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; 1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; 120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; 120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; 120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; 120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; 120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; 120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; 1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; 1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; 1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; 1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; 1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; 1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; 1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; 1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; 1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; 1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; 121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; 121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; 121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; 121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; 121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; 121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; 1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; 1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; 1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; 1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; 1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; 1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; 1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; 1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; 1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; 1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; 122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; 122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; 122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; 122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; 122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; 122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; 1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; 1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; 1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; 1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; 1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; 1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; 1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; 1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; 1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; 1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; 123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; 123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; 123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; 123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; 123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; 123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; 1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; 1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; 1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; 1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; 1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; 1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; 1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; 1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;; 1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; 124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; 124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; 124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; 124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; 1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; 1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; 1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; 1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; 1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; 1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; 1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; 1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; 125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; 125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; 125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; 125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; 1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; 1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; 1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; 1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; 1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; 1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; 1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; 1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; 1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; 1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; 126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; 126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; 126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; 126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; 126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; 126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; 1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; 1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; 1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; 1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; 1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; 1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; 1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; 1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; 1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; 1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; 127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; 127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; 127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; 127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; 127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; 127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; 1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; 1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; 1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; 1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; 1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; 1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; 1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; 1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;; 1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; 128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; 128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; 128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; 128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; 1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; 1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; 1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; 1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; 1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; 1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; 1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; 1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; 1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; 1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; 129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; 129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; 129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; 129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; 129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; 129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; 12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; 12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; 12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; 12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; 12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; 12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; 12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; 12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; 12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; 12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; 12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; 12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; 12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; 12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; 12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; 12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;; 12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; 12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; 12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; 12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; 12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; 12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; 12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; 12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; 12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; 12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; 12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; 12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; 12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; 12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; 12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; 12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; 12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; 12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; 12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; 12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; 12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; 12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; 12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; 12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; 12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;; 12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; 12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; 12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; 12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; 12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; 12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; 12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; 12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; 12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; 12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; 12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; 12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; 12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; 12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; 12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; 12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; 12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; 12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; 12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; 12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; 12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; 12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; 12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; 12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; 12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; 12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; 12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; 12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; 12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; 12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; 12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;; 12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; 12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; 12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; 12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; 12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; 12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; 12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; 12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; 12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; 12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; 12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; 12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; 12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; 12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; 12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; 12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; 1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; 1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; 1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; 1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; 1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; 1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; 1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; 1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; 1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; 1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; 130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; 130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; 130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; 130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; 130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; 130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;; 1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; 1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; 1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; 1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; 1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; 1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; 1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; 131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; 131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; 131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; 131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; 131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; 131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;; 1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; 1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; 1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; 1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; 1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; 1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; 1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; 1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; 1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; 1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; 132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; 132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; 132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; 132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; 132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; 132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; 1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; 1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; 1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; 1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; 1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; 1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; 1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; 1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; 1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; 1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; 133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; 133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; 133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; 133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; 133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; 133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; 1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; 1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; 1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; 1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; 1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; 1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; 1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; 1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;; 1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; 1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; 134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; 134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; 134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; 134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; 134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; 134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; 1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; 1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; 1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; 1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; 1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; 1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; 1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; 1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; 1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; 1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; 135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; 135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; 1360;ETHIOPIC SECTION MARK;So;0;L;;;;;N;;;;; 1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; 1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; 1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; 1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; 1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; 1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; 1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; 1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;; 136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;; 136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;; 136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;; 136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;; 136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;; 136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;; 1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;; 1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;; 1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; 1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; 137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;; 1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;; 1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;; 1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;; 1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;; 1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;; 1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;; 1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;; 1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;; 1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;; 138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;; 138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;; 138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;; 138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;; 138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;; 138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;; 1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;; 1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;; 1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;; 1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;; 1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;; 1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;; 1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;; 1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;; 1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;; 1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;; 13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;; 13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;; 13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;; 13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;; 13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;; 13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;; 13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;; 13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;; 13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;; 13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;; 13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;; 13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;; 13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;; 13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;; 13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;; 13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;; 13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;; 13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;; 13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;; 13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;; 13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;; 13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;; 13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;; 13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;; 13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;; 13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;; 13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;; 13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;; 13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;; 13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;; 13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;; 13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;; 13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;; 13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;; 13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;; 13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;; 13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;; 13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;; 13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;; 13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;; 13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;; 13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;; 13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;; 13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;; 13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;; 13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;; 13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;; 13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;; 13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;; 13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;; 13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;; 13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;; 13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;; 13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;; 13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;; 13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;; 13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;; 13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;; 13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;; 13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;; 13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;; 13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;; 13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;; 13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;; 13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;; 13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;; 13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;; 13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;; 13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;; 13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;; 13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;; 13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;; 13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;; 13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;; 13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;; 13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;; 13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;; 13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;; 13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;; 13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;; 13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;; 13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;; 13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;; 13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;; 13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;; 1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;; 1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; 1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; 1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; 1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; 1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; 1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; 1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; 1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; 1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; 140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; 140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; 140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; 140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; 140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; 140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; 1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; 1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; 1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; 1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; 1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; 1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; 1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; 1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; 1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; 1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; 141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; 141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; 141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; 141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; 141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; 1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; 1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; 1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; 1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; 1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; 1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; 1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; 1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; 1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; 1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; 142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; 142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; 142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; 142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; 142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; 142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; 1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; 1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; 1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; 1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; 1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; 1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; 1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; 1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; 1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; 1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; 143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; 143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; 143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; 143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; 143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; 143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; 1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; 1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; 1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; 1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; 1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; 1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; 1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; 1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; 1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; 1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; 144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; 144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; 144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; 144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; 144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; 144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; 1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; 1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; 1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; 1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; 1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; 1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; 1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; 1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; 1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; 1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; 145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; 145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; 145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; 145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; 145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; 145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; 1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; 1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; 1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; 1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; 1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; 1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; 1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; 1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; 1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; 1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; 146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; 146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; 146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; 146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; 146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; 146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; 1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; 1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; 1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; 1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; 1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; 1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; 1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; 1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; 1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; 1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; 147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; 147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; 147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; 147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; 147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; 147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; 1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; 1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; 1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; 1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; 1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; 1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; 1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; 1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; 1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; 1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; 148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; 148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; 148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; 148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; 148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; 148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; 1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; 1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; 1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; 1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; 1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; 1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; 1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; 1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; 1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; 1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; 149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; 149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; 149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; 149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; 149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; 149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; 14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; 14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; 14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; 14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; 14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; 14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; 14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; 14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; 14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; 14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; 14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; 14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; 14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; 14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; 14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; 14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; 14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; 14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; 14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; 14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; 14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; 14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; 14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; 14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; 14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; 14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; 14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; 14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; 14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; 14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; 14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; 14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; 14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; 14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; 14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; 14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; 14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; 14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; 14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; 14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; 14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; 14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; 14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; 14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; 14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; 14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; 14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; 14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; 14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; 14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; 14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; 14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; 14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; 14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; 14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; 14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; 14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; 14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; 14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; 14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; 14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; 14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; 14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; 14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; 14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; 14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; 14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; 14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; 14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; 14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; 14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; 14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; 14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; 14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; 14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; 14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; 14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; 14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; 14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; 14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; 14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; 14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; 14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; 14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; 14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; 14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; 14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; 14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; 14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; 14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; 14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; 14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; 14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; 14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; 14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; 14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; 1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; 1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; 1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; 1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; 1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; 1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; 1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; 1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; 1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; 1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; 150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; 150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; 150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; 150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; 150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; 150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; 1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; 1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; 1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; 1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; 1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; 1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; 1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; 1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; 1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; 1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; 151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; 151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; 151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; 151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; 151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; 151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; 1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; 1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; 1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; 1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; 1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; 1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; 1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; 1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; 1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; 1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; 152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; 152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; 152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; 152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; 152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; 152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; 1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; 1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; 1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; 1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; 1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; 1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; 1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; 1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; 1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; 1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; 153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; 153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; 153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; 153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; 153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; 153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; 1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; 1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; 1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; 1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; 1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; 1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; 1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; 1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; 1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; 1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; 154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; 154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; 154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; 154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; 154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; 154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; 1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; 1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; 1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; 1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; 1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; 1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; 1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; 1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; 1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; 1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; 155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; 155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; 155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; 155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; 155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; 155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; 1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; 1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; 1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; 1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; 1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; 1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; 1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; 1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; 1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; 1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; 156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; 156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; 156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; 156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; 156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; 156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; 1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; 1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; 1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; 1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; 1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; 1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; 1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; 1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; 1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; 1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; 157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; 157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; 157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; 157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; 157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; 157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; 1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; 1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; 1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; 1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; 1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; 1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; 1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; 1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; 1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; 1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; 158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; 158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; 158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; 158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; 158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; 158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; 1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; 1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; 1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; 1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; 1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; 1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; 1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; 1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; 1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; 1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; 159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; 159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; 159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; 159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; 159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; 159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; 15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; 15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; 15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; 15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; 15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; 15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; 15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; 15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; 15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; 15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; 15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; 15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; 15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; 15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; 15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; 15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; 15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; 15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; 15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; 15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; 15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; 15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; 15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; 15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; 15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; 15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; 15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; 15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; 15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; 15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; 15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; 15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; 15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; 15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; 15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; 15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; 15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; 15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; 15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; 15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; 15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; 15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; 15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; 15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; 15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; 15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; 15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; 15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; 15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; 15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; 15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; 15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; 15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; 15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; 15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; 15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; 15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; 15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; 15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; 15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; 15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; 15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; 15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; 15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; 15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; 15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; 15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; 15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; 15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; 15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; 15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; 15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; 15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; 15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; 15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; 15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; 15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; 15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; 15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; 15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; 15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; 15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; 15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; 15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; 15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; 15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; 15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; 15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; 15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; 15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; 15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; 15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; 15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; 15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; 15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; 15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; 1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; 1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; 1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; 1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; 1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; 1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; 1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; 1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; 1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; 1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; 160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; 160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; 160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; 160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; 160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; 160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; 1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; 1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; 1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; 1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; 1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; 1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; 1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; 1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; 1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; 1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; 161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; 161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; 161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; 161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; 161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; 161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; 1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; 1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; 1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; 1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; 1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; 1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; 1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; 1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; 1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; 1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; 162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; 162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; 162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; 162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; 162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; 162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; 1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; 1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; 1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; 1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; 1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; 1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; 1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; 1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; 1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; 1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; 163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; 163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; 163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; 163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; 163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; 163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; 1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; 1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; 1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; 1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; 1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; 1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; 1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; 1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; 1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; 1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; 164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; 164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; 164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; 164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; 164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; 164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; 1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; 1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; 1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; 1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; 1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; 1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; 1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; 1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; 1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; 1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; 165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; 165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; 165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; 165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; 165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; 165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; 1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; 1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; 1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; 1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; 1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; 1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; 1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; 1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; 1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; 1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; 166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; 166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; 166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; 166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;; 166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; 166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; 1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; 1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; 1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; 1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; 1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; 1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; 1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; 1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;; 1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;; 1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;; 167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;; 167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;; 167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;; 167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;; 167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;; 167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;; 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; 1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; 1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; 1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; 1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; 1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; 1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; 1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; 1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; 1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; 168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; 168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; 168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; 168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; 168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; 168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; 1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; 1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; 1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; 1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; 1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; 1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; 1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; 1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; 1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; 1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; 169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; 169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;; 169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;; 16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; 16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; 16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; 16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; 16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; 16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; 16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; 16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; 16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; 16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; 16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; 16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; 16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; 16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; 16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; 16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; 16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; 16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; 16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; 16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; 16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; 16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; 16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; 16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; 16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; 16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; 16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; 16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; 16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; 16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; 16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; 16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; 16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; 16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; 16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; 16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; 16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; 16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; 16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; 16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; 16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; 16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; 16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; 16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; 16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; 16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; 16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; 16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; 16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; 16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; 16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; 16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; 16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; 16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; 16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; 16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; 16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; 16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; 16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; 16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; 16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; 16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; 16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; 16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; 16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; 16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; 16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; 16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; 16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; 16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; 16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; 16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; 16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; 16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; 16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; 16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; 16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;; 16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;; 16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;; 1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; 1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; 1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; 1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; 1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; 1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; 1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; 1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; 1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; 1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; 170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; 170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; 170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; 170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; 170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; 1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; 1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; 1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; 1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; 1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; 1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; 1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; 1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; 1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; 1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; 1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; 1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; 172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; 172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; 172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; 172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; 172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; 172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; 1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; 1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; 1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; 1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; 1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; 1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; 1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; 1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; 1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; 1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; 1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; 1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; 1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; 174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; 174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; 174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; 174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; 174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; 174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; 1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; 1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; 1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; 1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; 1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; 1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; 1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; 1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; 1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; 1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; 1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; 1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; 176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; 176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; 176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; 176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; 176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; 1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; 1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; 1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; 1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; 1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; 1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; 1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; 1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; 1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; 1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; 1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; 178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; 178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; 178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; 178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; 178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; 178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; 1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; 1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; 1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; 1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; 1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; 1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; 1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; 1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; 1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; 1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; 179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; 179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; 179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; 179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; 179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; 179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; 17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; 17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; 17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; 17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; 17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; 17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; 17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; 17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; 17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; 17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; 17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; 17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; 17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; 17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; 17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; 17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; 17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; 17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; 17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; 17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; 17B4;KHMER VOWEL INHERENT AQ;Cf;0;L;;;;;N;;;;; 17B5;KHMER VOWEL INHERENT AA;Cf;0;L;;;;;N;;;;; 17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; 17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; 17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; 17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; 17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; 17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; 17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; 17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; 17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; 17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; 17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; 17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; 17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; 17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; 17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; 17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; 17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; 17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; 17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; 17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; 17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; 17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; 17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; 17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; 17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; 17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; 17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;; 17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;; 17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;; 17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;; 17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;; 17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;; 17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;; 17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;; 17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;; 17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;; 17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;; 1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; 1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; 1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; 1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; 1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; 1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; 1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; 1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; 1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; 1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; 180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; 180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; 180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; 180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; 180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;; 1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; 1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; 1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; 1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; 1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; 1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; 1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; 1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; 1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; 1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; 182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; 182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; 182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; 182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; 182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; 182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; 1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; 1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; 1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; 1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; 1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; 1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; 1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; 1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; 183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; 183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; 183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; 183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; 183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; 183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; 1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; 1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; 1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; 1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; 1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; 1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; 1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; 1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; 1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; 184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; 184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; 184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; 184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; 184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; 184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; 1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; 1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; 1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; 1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; 1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; 1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; 1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; 1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; 1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; 1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; 185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; 185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; 185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; 185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; 185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; 185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; 1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; 1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; 1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; 1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; 1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; 1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; 1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; 1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; 1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; 1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; 186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; 186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; 186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; 186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; 186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; 186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; 1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; 1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; 1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; 1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; 1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; 1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; 1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; 1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; 1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; 1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; 1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; 1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; 1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; 1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;; 1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;; 1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; 1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; 1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; 188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; 188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; 188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; 188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; 188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; 188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; 1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; 1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; 1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; 1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; 1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; 1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; 1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; 1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; 1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; 189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; 189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; 189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; 189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; 189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; 18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; 18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; 18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; 18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; 18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; 18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; 18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; 18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; 18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; 18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;; 18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;; 18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;; 18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;; 18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;; 18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;; 18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;; 18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;; 18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;; 18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;; 18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;; 18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;; 18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;; 18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;; 18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;; 18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;; 18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;; 18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;; 18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;; 18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;; 18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;; 18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;; 18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;; 18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;; 18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;; 18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;; 18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;; 18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;; 18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;; 18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;; 18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;; 18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;; 18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;; 18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;; 18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;; 18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;; 18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;; 18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;; 18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;; 18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;; 18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;; 18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;; 18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;; 18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;; 18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;; 18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;; 18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;; 18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;; 18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;; 18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;; 18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;; 18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;; 18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;; 18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;; 18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;; 18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;; 18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;; 18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;; 18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;; 18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;; 18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;; 18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;; 18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;; 18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;; 18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;; 18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;; 18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;; 18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;; 18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;; 18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;; 18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;; 1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;; 1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;; 1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;; 1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;; 1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;; 1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;; 1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;; 1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;; 1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;; 1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;; 190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;; 190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;; 190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;; 190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;; 190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;; 190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;; 1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;; 1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;; 1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;; 1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;; 1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;; 1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;; 1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;; 1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;; 1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;; 1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;; 191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;; 191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;; 191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;; 1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; 1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;; 1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;; 1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;; 1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;; 1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;; 1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;; 1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;; 1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;; 1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;; 1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;; 193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;; 193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;; 1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;; 1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;; 1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;; 1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;; 1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;; 1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;; 1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;; 1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;; 1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;; 1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;; 1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;; 1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;; 195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;; 195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;; 195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;; 195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;; 195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;; 195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;; 1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;; 1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;; 1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;; 1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;; 1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;; 1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;; 1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;; 1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;; 1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;; 1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;; 196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;; 196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;; 196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;; 196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;; 1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;; 1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;; 1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;; 1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;; 1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;; 1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;; 1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;; 1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;; 1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;; 1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;; 1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;; 1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;; 1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;; 198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;; 198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;; 198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;; 1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;; 1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;; 1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;; 199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;; 199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;; 199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;; 199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;; 199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;; 19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;; 19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;; 19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;; 19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;; 19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;; 19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;; 19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;; 19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;; 19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;; 19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;; 19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;; 19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Mc;0;L;;;;;N;;;;; 19B1;NEW TAI LUE VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 19B2;NEW TAI LUE VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 19B3;NEW TAI LUE VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 19B4;NEW TAI LUE VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 19B5;NEW TAI LUE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 19B6;NEW TAI LUE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 19B7;NEW TAI LUE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 19B8;NEW TAI LUE VOWEL SIGN OA;Mc;0;L;;;;;N;;;;; 19B9;NEW TAI LUE VOWEL SIGN UE;Mc;0;L;;;;;N;;;;; 19BA;NEW TAI LUE VOWEL SIGN AY;Mc;0;L;;;;;N;;;;; 19BB;NEW TAI LUE VOWEL SIGN AAY;Mc;0;L;;;;;N;;;;; 19BC;NEW TAI LUE VOWEL SIGN UY;Mc;0;L;;;;;N;;;;; 19BD;NEW TAI LUE VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; 19BE;NEW TAI LUE VOWEL SIGN OAY;Mc;0;L;;;;;N;;;;; 19BF;NEW TAI LUE VOWEL SIGN UEY;Mc;0;L;;;;;N;;;;; 19C0;NEW TAI LUE VOWEL SIGN IY;Mc;0;L;;;;;N;;;;; 19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;; 19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;; 19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;; 19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;; 19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;; 19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;; 19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;; 19C8;NEW TAI LUE TONE MARK-1;Mc;0;L;;;;;N;;;;; 19C9;NEW TAI LUE TONE MARK-2;Mc;0;L;;;;;N;;;;; 19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 19DA;NEW TAI LUE THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 19DE;NEW TAI LUE SIGN LAE;Po;0;ON;;;;;N;;;;; 19DF;NEW TAI LUE SIGN LAEV;Po;0;ON;;;;;N;;;;; 19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; 19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; 19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; 19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;; 19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;; 19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;; 19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;; 19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;; 19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;; 19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;; 19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;; 19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;; 19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;; 19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;; 19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;; 19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;; 19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;; 19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;; 19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;; 19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;; 19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;; 19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;; 19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;; 19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;; 19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;; 19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;; 19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;; 19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;; 19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;; 19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;; 19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;; 19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;; 1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;; 1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;; 1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;; 1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;; 1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;; 1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;; 1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;; 1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1A1B;BUGINESE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;; 1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;; 1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;; 1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;; 1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;; 1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;; 1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;; 1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;; 1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;; 1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;; 1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;; 1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;; 1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;; 1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;; 1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;; 1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;; 1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;; 1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;; 1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;; 1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;; 1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;; 1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;; 1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;; 1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;; 1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;; 1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;; 1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;; 1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;; 1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;; 1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;; 1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;; 1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;; 1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;; 1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;; 1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;; 1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;; 1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;; 1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;; 1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;; 1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;; 1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;; 1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;; 1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;; 1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;; 1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;; 1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;; 1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;; 1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;; 1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; 1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;; 1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; 1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;; 1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;; 1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;; 1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;; 1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;; 1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;; 1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;; 1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;; 1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;; 1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;; 1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;; 1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;; 1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;; 1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;; 1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;; 1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;; 1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;; 1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;; 1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;; 1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;; 1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;; 1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;; 1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;; 1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;; 1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;; 1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;; 1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; 1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; 1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; 1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;; 1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;; 1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;; 1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;; 1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;; 1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;; 1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;; 1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;; 1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;; 1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;; 1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;; 1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;; 1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;; 1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;; 1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;; 1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;; 1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;; 1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;; 1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;; 1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;; 1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;; 1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;; 1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;; 1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;; 1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;; 1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;; 1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;; 1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;; 1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;; 1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;; 1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;; 1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;; 1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; 1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;; 1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;; 1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;; 1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;; 1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;; 1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; 1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;; 1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;; 1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;; 1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; 1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;; 1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;; 1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;; 1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;; 1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;; 1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;; 1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; 1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; 1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; 1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;; 1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;; 1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;; 1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;; 1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;; 1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;; 1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;; 1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;; 1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;; 1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;; 1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;; 1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;; 1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;; 1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;; 1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;; 1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;; 1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;; 1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;; 1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;; 1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;; 1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;; 1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;; 1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;; 1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;; 1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;; 1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;; 1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;; 1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;; 1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;; 1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; 1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; 1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; 1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; 1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; 1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; 1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;; 1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;; 1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;; 1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;; 1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;; 1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;; 1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;; 1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;; 1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;; 1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;; 1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;; 1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;; 1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;; 1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;; 1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;; 1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;; 1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;; 1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;; 1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;; 1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;; 1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;; 1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;; 1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;; 1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;; 1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;; 1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; 1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; 1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; 1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;; 1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;; 1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;; 1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;; 1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;; 1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;; 1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;; 1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;; 1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;; 1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;; 1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;; 1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;; 1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;; 1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;; 1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;; 1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;; 1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;; 1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;; 1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;; 1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;; 1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;; 1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;; 1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;; 1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;; 1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;; 1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;; 1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;; 1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;; 1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;; 1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;; 1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;; 1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;; 1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;; 1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; 1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; 1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; 1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; 1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;; 1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; 1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;; 1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;; 1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;; 1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;; 1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;; 1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;; 1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;; 1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;; 1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;; 1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;; 1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;; 1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;; 1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;; 1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;; 1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;; 1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;; 1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;; 1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;; 1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;; 1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;; 1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;; 1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;; 1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;; 1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;; 1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;; 1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;; 1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;; 1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;; 1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;; 1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;; 1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;; 1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;; 1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;; 1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;; 1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;; 1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;; 1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;; 1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;; 1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;; 1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;; 1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;; 1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;; 1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;; 1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;; 1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; 1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; 1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; 1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;; 1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;; 1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;; 1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;; 1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;; 1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;; 1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;; 1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;; 1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; 1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;; 1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;; 1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;; 1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;; 1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;; 1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;; 1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; 1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;; 1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;; 1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;; 1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;; 1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;; 1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;; 1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;; 1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;; 1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;; 1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;; 1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;; 1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;; 1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;; 1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;; 1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;; 1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;; 1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;; 1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;; 1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;; 1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;; 1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;; 1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;; 1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;; 1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;; 1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;; 1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;; 1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;; 1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;; 1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;; 1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;; 1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;; 1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;; 1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;; 1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;; 1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;; 1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;; 1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;; 1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;; 1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;; 1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;; 1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;; 1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;; 1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;; 1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L; 0041;;;;N;;;;; 1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L; 00C6;;;;N;;;;; 1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L; 0042;;;;N;;;;; 1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;; 1D30;MODIFIER LETTER CAPITAL D;Lm;0;L; 0044;;;;N;;;;; 1D31;MODIFIER LETTER CAPITAL E;Lm;0;L; 0045;;;;N;;;;; 1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L; 018E;;;;N;;;;; 1D33;MODIFIER LETTER CAPITAL G;Lm;0;L; 0047;;;;N;;;;; 1D34;MODIFIER LETTER CAPITAL H;Lm;0;L; 0048;;;;N;;;;; 1D35;MODIFIER LETTER CAPITAL I;Lm;0;L; 0049;;;;N;;;;; 1D36;MODIFIER LETTER CAPITAL J;Lm;0;L; 004A;;;;N;;;;; 1D37;MODIFIER LETTER CAPITAL K;Lm;0;L; 004B;;;;N;;;;; 1D38;MODIFIER LETTER CAPITAL L;Lm;0;L; 004C;;;;N;;;;; 1D39;MODIFIER LETTER CAPITAL M;Lm;0;L; 004D;;;;N;;;;; 1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L; 004E;;;;N;;;;; 1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;; 1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L; 004F;;;;N;;;;; 1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L; 0222;;;;N;;;;; 1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L; 0050;;;;N;;;;; 1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L; 0052;;;;N;;;;; 1D40;MODIFIER LETTER CAPITAL T;Lm;0;L; 0054;;;;N;;;;; 1D41;MODIFIER LETTER CAPITAL U;Lm;0;L; 0055;;;;N;;;;; 1D42;MODIFIER LETTER CAPITAL W;Lm;0;L; 0057;;;;N;;;;; 1D43;MODIFIER LETTER SMALL A;Lm;0;L; 0061;;;;N;;;;; 1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L; 0250;;;;N;;;;; 1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L; 0251;;;;N;;;;; 1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L; 1D02;;;;N;;;;; 1D47;MODIFIER LETTER SMALL B;Lm;0;L; 0062;;;;N;;;;; 1D48;MODIFIER LETTER SMALL D;Lm;0;L; 0064;;;;N;;;;; 1D49;MODIFIER LETTER SMALL E;Lm;0;L; 0065;;;;N;;;;; 1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L; 0259;;;;N;;;;; 1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L; 025B;;;;N;;;;; 1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L; 025C;;;;N;;;;; 1D4D;MODIFIER LETTER SMALL G;Lm;0;L; 0067;;;;N;;;;; 1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;; 1D4F;MODIFIER LETTER SMALL K;Lm;0;L; 006B;;;;N;;;;; 1D50;MODIFIER LETTER SMALL M;Lm;0;L; 006D;;;;N;;;;; 1D51;MODIFIER LETTER SMALL ENG;Lm;0;L; 014B;;;;N;;;;; 1D52;MODIFIER LETTER SMALL O;Lm;0;L; 006F;;;;N;;;;; 1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L; 0254;;;;N;;;;; 1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L; 1D16;;;;N;;;;; 1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L; 1D17;;;;N;;;;; 1D56;MODIFIER LETTER SMALL P;Lm;0;L; 0070;;;;N;;;;; 1D57;MODIFIER LETTER SMALL T;Lm;0;L; 0074;;;;N;;;;; 1D58;MODIFIER LETTER SMALL U;Lm;0;L; 0075;;;;N;;;;; 1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L; 1D1D;;;;N;;;;; 1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L; 026F;;;;N;;;;; 1D5B;MODIFIER LETTER SMALL V;Lm;0;L; 0076;;;;N;;;;; 1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L; 1D25;;;;N;;;;; 1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L; 03B2;;;;N;;;;; 1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L; 03B3;;;;N;;;;; 1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L; 03B4;;;;N;;;;; 1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L; 03C6;;;;N;;;;; 1D61;MODIFIER LETTER SMALL CHI;Lm;0;L; 03C7;;;;N;;;;; 1D62;LATIN SUBSCRIPT SMALL LETTER I;Ll;0;L; 0069;;;;N;;;;; 1D63;LATIN SUBSCRIPT SMALL LETTER R;Ll;0;L; 0072;;;;N;;;;; 1D64;LATIN SUBSCRIPT SMALL LETTER U;Ll;0;L; 0075;;;;N;;;;; 1D65;LATIN SUBSCRIPT SMALL LETTER V;Ll;0;L; 0076;;;;N;;;;; 1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Ll;0;L; 03B2;;;;N;;;;; 1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Ll;0;L; 03C1;;;;N;;;;; 1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Ll;0;L; 03C6;;;;N;;;;; 1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Ll;0;L; 03C7;;;;N;;;;; 1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;; 1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;; 1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L; 043D;;;;N;;;;; 1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D 1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;; 1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63 1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;; 1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;; 1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L; 0252;;;;N;;;;; 1D9C;MODIFIER LETTER SMALL C;Lm;0;L; 0063;;;;N;;;;; 1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L; 0255;;;;N;;;;; 1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L; 00F0;;;;N;;;;; 1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L; 025C;;;;N;;;;; 1DA0;MODIFIER LETTER SMALL F;Lm;0;L; 0066;;;;N;;;;; 1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L; 025F;;;;N;;;;; 1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L; 0261;;;;N;;;;; 1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L; 0265;;;;N;;;;; 1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L; 0268;;;;N;;;;; 1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L; 0269;;;;N;;;;; 1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L; 026A;;;;N;;;;; 1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L; 1D7B;;;;N;;;;; 1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L; 029D;;;;N;;;;; 1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L; 026D;;;;N;;;;; 1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L; 1D85;;;;N;;;;; 1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L; 029F;;;;N;;;;; 1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L; 0271;;;;N;;;;; 1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L; 0270;;;;N;;;;; 1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L; 0272;;;;N;;;;; 1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L; 0273;;;;N;;;;; 1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L; 0274;;;;N;;;;; 1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L; 0275;;;;N;;;;; 1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L; 0278;;;;N;;;;; 1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L; 0282;;;;N;;;;; 1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L; 0283;;;;N;;;;; 1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L; 01AB;;;;N;;;;; 1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L; 0289;;;;N;;;;; 1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L; 028A;;;;N;;;;; 1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L; 1D1C;;;;N;;;;; 1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L; 028B;;;;N;;;;; 1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L; 028C;;;;N;;;;; 1DBB;MODIFIER LETTER SMALL Z;Lm;0;L; 007A;;;;N;;;;; 1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L; 0290;;;;N;;;;; 1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L; 0291;;;;N;;;;; 1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L; 0292;;;;N;;;;; 1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L; 03B8;;;;N;;;;; 1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;; 1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;; 1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;; 1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;; 1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;; 1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;; 1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;; 1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;; 1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;; 1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;; 1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;; 1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;; 1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;; 1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;; 1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;; 1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;; 1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;; 1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;; 1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;; 1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;; 1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;; 1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;; 1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;; 1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;; 1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; 1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; 1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; 1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; 1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; 1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; 1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; 1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; 1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; 1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A 1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; 1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C 1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; 1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E 1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; 1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; 1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; 1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; 1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; 1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; 1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A 1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; 1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C 1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; 1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E 1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; 1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; 1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; 1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; 1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; 1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; 1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A 1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; 1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C 1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; 1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E 1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; 1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; 1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; 1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; 1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; 1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; 1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A 1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; 1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C 1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; 1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E 1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; 1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; 1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; 1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; 1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; 1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; 1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A 1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; 1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C 1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; 1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E 1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; 1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; 1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; 1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; 1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; 1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; 1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A 1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; 1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C 1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; 1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E 1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; 1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; 1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; 1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; 1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; 1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; 1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A 1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; 1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C 1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; 1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E 1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; 1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; 1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; 1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; 1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; 1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; 1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A 1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; 1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C 1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; 1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E 1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; 1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; 1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; 1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; 1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; 1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; 1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A 1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; 1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C 1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; 1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E 1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; 1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; 1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; 1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; 1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; 1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; 1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; 1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L; 0061 02BE;;;;N;;;;; 1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;; 1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;; 1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF; 1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;; 1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; 1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; 1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; 1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; 1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; 1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; 1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA 1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; 1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC 1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; 1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE 1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; 1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; 1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; 1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; 1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; 1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; 1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA 1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; 1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC 1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; 1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE 1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; 1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; 1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; 1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; 1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; 1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; 1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA 1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC 1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; 1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE 1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; 1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; 1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; 1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; 1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; 1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA 1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; 1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC 1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; 1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE 1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; 1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; 1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; 1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; 1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; 1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; 1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA 1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; 1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC 1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; 1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE 1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; 1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; 1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; 1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; 1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; 1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB; 1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA 1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD; 1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC 1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF; 1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE 1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A 1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B 1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C 1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D 1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E 1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F 1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; 1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; 1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; 1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; 1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; 1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; 1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; 1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; 1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A 1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B 1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C 1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D 1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; 1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; 1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; 1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; 1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; 1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; 1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A 1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B 1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C 1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D 1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E 1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F 1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; 1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; 1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; 1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; 1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; 1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; 1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; 1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; 1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A 1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B 1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C 1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D 1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E 1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F 1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; 1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; 1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; 1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; 1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; 1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; 1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; 1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; 1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A 1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B 1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C 1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D 1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; 1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; 1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; 1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; 1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; 1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; 1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; 1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; 1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B 1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; 1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D 1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; 1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F 1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; 1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; 1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; 1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; 1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A 1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B 1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C 1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D 1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E 1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F 1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; 1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; 1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; 1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; 1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; 1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; 1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; 1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; 1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA 1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB 1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA 1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB 1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA 1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB 1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA 1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB 1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA 1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB 1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A 1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B 1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C 1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D 1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E 1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F 1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; 1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; 1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; 1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; 1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; 1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; 1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; 1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; 1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A 1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B 1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C 1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D 1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E 1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F 1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; 1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; 1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; 1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; 1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; 1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; 1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; 1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; 1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA 1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB 1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC 1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD 1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE 1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF 1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; 1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; 1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; 1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; 1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; 1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; 1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; 1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; 1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; 1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC 1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; 1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; 1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; 1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; 1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; 1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; 1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; 1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; 1FBD;GREEK KORONIS;Sk;0;ON; 0020 0313;;;;N;;;;; 1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 1FBF;GREEK PSILI;Sk;0;ON; 0020 0313;;;;N;;;;; 1FC0;GREEK PERISPOMENI;Sk;0;ON; 0020 0342;;;;N;;;;; 1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; 1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; 1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC 1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; 1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; 1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; 1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; 1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; 1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; 1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; 1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; 1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; 1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; 1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; 1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; 1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; 1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; 1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; 1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; 1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; 1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; 1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; 1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; 1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; 1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; 1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; 1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; 1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; 1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC 1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; 1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; 1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; 1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; 1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; 1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; 1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; 1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; 1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; 1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; 1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; 1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC 1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; 1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; 1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; 1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; 1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; 1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; 1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; 1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; 1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; 1FFE;GREEK DASIA;Sk;0;ON; 0020 0314;;;;N;;;;; 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; 2002;EN SPACE;Zs;0;WS; 0020;;;;N;;;;; 2003;EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2004;THREE-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2005;FOUR-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2006;SIX-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2007;FIGURE SPACE;Zs;0;WS; 0020;;;;N;;;;; 2008;PUNCTUATION SPACE;Zs;0;WS; 0020;;;;N;;;;; 2009;THIN SPACE;Zs;0;WS; 0020;;;;N;;;;; 200A;HAIR SPACE;Zs;0;WS; 0020;;;;N;;;;; 200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;; 200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; 200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; 200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; 200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; 2010;HYPHEN;Pd;0;ON;;;;;N;;;;; 2011;NON-BREAKING HYPHEN;Pd;0;ON; 2010;;;;N;;;;; 2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; 2013;EN DASH;Pd;0;ON;;;;;N;;;;; 2014;EM DASH;Pd;0;ON;;;;;N;;;;; 2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; 2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; 2017;DOUBLE LOW LINE;Po;0;ON; 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; 2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; 2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; 201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; 201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; 201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; 201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; 201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; 201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; 2020;DAGGER;Po;0;ON;;;;;N;;;;; 2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; 2022;BULLET;Po;0;ON;;;;;N;;;;; 2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; 2024;ONE DOT LEADER;Po;0;ON; 002E;;;;N;;;;; 2025;TWO DOT LEADER;Po;0;ON; 002E 002E;;;;N;;;;; 2026;HORIZONTAL ELLIPSIS;Po;0;ON; 002E 002E 002E;;;;N;;;;; 2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; 202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; 202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; 202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; 202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; 202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; 202F;NARROW NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;;;;; 2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 2032;PRIME;Po;0;ET;;;;;N;;;;; 2033;DOUBLE PRIME;Po;0;ET; 2032 2032;;;;N;;;;; 2034;TRIPLE PRIME;Po;0;ET; 2032 2032 2032;;;;N;;;;; 2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; 2036;REVERSED DOUBLE PRIME;Po;0;ON; 2035 2035;;;;N;;;;; 2037;REVERSED TRIPLE PRIME;Po;0;ON; 2035 2035 2035;;;;N;;;;; 2038;CARET;Po;0;ON;;;;;N;;;;; 2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; 203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; 203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; 203C;DOUBLE EXCLAMATION MARK;Po;0;ON; 0021 0021;;;;N;;;;; 203D;INTERROBANG;Po;0;ON;;;;;N;;;;; 203E;OVERLINE;Po;0;ON; 0020 0305;;;;N;SPACING OVERSCORE;;;; 203F;UNDERTIE;Pc;0;ON;;;;;N;;;;; 2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; 2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; 2042;ASTERISM;Po;0;ON;;;;;N;;;;; 2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; 2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;; 2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; 2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; 2047;DOUBLE QUESTION MARK;Po;0;ON; 003F 003F;;;;N;;;;; 2048;QUESTION EXCLAMATION MARK;Po;0;ON; 003F 0021;;;;N;;;;; 2049;EXCLAMATION QUESTION MARK;Po;0;ON; 0021 003F;;;;N;;;;; 204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; 204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; 204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; 204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; 2050;CLOSE UP;Po;0;ON;;;;;N;;;;; 2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; 2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2053;SWUNG DASH;Po;0;ON;;;;;N;;;;; 2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;; 2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;; 2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2057;QUADRUPLE PRIME;Po;0;ON; 2032 2032 2032 2032;;;;N;;;;; 2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;; 205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;; 205D;TRICOLON;Po;0;ON;;;;;N;;;;; 205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;; 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS; 0020;;;;N;;;;; 2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; 2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; 2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; 2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; 2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;; 206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 2070;SUPERSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; 2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L; 0069;;;;N;;;;; 2074;SUPERSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; 2075;SUPERSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; 2076;SUPERSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;; 2077;SUPERSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; 2078;SUPERSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; 2079;SUPERSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;; 207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; 207B;SUPERSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; 207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; 207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; 207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; 2080;SUBSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;; 2081;SUBSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;; 2082;SUBSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;; 2083;SUBSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;; 2084;SUBSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;; 2085;SUBSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;; 2086;SUBSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;; 2087;SUBSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; 2088;SUBSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; 2089;SUBSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;; 208A;SUBSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; 208B;SUBSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; 208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; 208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; 2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L; 0061;;;;N;;;;; 2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L; 0065;;;;N;;;;; 2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L; 006F;;;;N;;;;; 2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L; 0078;;;;N;;;;; 2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L; 0259;;;;N;;;;; 20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; 20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; 20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; 20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; 20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; 20A8;RUPEE SIGN;Sc;0;ET; 0052 0073;;;;N;;;;; 20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; 20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; 20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; 20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; 20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; 20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; 20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; 20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; 20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; 20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;; 20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;; 20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;; 20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;; 20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; 20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; 20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; 20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; 20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; 20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; 20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; 20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; 20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; 20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; 20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; 20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; 20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; 20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; 20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; 20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; 20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; 20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; 20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; 20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; 20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; 20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; 20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; 20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;; 2100;ACCOUNT OF;So;0;ON; 0061 002F 0063;;;;N;;;;; 2101;ADDRESSED TO THE SUBJECT;So;0;ON; 0061 002F 0073;;;;N;;;;; 2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L; 0043;;;;N;DOUBLE-STRUCK C;;;; 2103;DEGREE CELSIUS;So;0;ON; 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; 2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; 2105;CARE OF;So;0;ON; 0063 002F 006F;;;;N;;;;; 2106;CADA UNA;So;0;ON; 0063 002F 0075;;;;N;;;;; 2107;EULER CONSTANT;Lu;0;L; 0190;;;;N;EULERS;;;; 2108;SCRUPLE;So;0;ON;;;;;N;;;;; 2109;DEGREE FAHRENHEIT;So;0;ON; 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; 210A;SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 210B;SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;SCRIPT H;;;; 210C;BLACK-LETTER CAPITAL H;Lu;0;L; 0048;;;;N;BLACK-LETTER H;;;; 210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L; 0048;;;;N;DOUBLE-STRUCK H;;;; 210E;PLANCK CONSTANT;Ll;0;L; 0068;;;;N;;;;; 210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L; 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; 2110;SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;SCRIPT I;;;; 2111;BLACK-LETTER CAPITAL I;Lu;0;L; 0049;;;;N;BLACK-LETTER I;;;; 2112;SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;SCRIPT L;;;; 2113;SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; 2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L; 004E;;;;N;DOUBLE-STRUCK N;;;; 2116;NUMERO SIGN;So;0;ON; 004E 006F;;;;N;NUMERO;;;; 2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; 2118;SCRIPT CAPITAL P;So;0;ON;;;;;N;SCRIPT P;;;; 2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L; 0050;;;;N;DOUBLE-STRUCK P;;;; 211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L; 0051;;;;N;DOUBLE-STRUCK Q;;;; 211B;SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;SCRIPT R;;;; 211C;BLACK-LETTER CAPITAL R;Lu;0;L; 0052;;;;N;BLACK-LETTER R;;;; 211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L; 0052;;;;N;DOUBLE-STRUCK R;;;; 211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; 211F;RESPONSE;So;0;ON;;;;;N;;;;; 2120;SERVICE MARK;So;0;ON; 0053 004D;;;;N;;;;; 2121;TELEPHONE SIGN;So;0;ON; 0054 0045 004C;;;;N;T E L SYMBOL;;;; 2122;TRADE MARK SIGN;So;0;ON; 0054 004D;;;;N;TRADEMARK;;;; 2123;VERSICLE;So;0;ON;;;;;N;;;;; 2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L; 005A;;;;N;DOUBLE-STRUCK Z;;;; 2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; 2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; 2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; 2128;BLACK-LETTER CAPITAL Z;Lu;0;L; 005A;;;;N;BLACK-LETTER Z;;;; 2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; 212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; 212C;SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;SCRIPT B;;;; 212D;BLACK-LETTER CAPITAL C;Lu;0;L; 0043;;;;N;BLACK-LETTER C;;;; 212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; 212F;SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 2130;SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;SCRIPT E;;;; 2131;SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;SCRIPT F;;;; 2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E; 2133;SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;SCRIPT M;;;; 2134;SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 2135;ALEF SYMBOL;Lo;0;L; 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; 2136;BET SYMBOL;Lo;0;L; 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; 2137;GIMEL SYMBOL;Lo;0;L; 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; 2138;DALET SYMBOL;Lo;0;L; 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; 2139;INFORMATION SOURCE;Ll;0;L; 0069;;;;N;;;;; 213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; 213B;FACSIMILE SIGN;So;0;ON; 0046 0041 0058;;;;N;;;;; 213C;DOUBLE-STRUCK SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON; 2211;;;;Y;;;;; 2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; 2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; 2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; 214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; 214C;PER SIGN;So;0;ON;;;;;N;;;;; 214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;; 214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132 214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;; 2150;VULGAR FRACTION ONE SEVENTH;No;0;ON; 0031 2044 0037;;;1/7;N;;;;; 2151;VULGAR FRACTION ONE NINTH;No;0;ON; 0031 2044 0039;;;1/9;N;;;;; 2152;VULGAR FRACTION ONE TENTH;No;0;ON; 0031 2044 0031 0030;;;1/10;N;;;;; 2153;VULGAR FRACTION ONE THIRD;No;0;ON; 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; 2154;VULGAR FRACTION TWO THIRDS;No;0;ON; 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; 2155;VULGAR FRACTION ONE FIFTH;No;0;ON; 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; 2156;VULGAR FRACTION TWO FIFTHS;No;0;ON; 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; 2157;VULGAR FRACTION THREE FIFTHS;No;0;ON; 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; 2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON; 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; 2159;VULGAR FRACTION ONE SIXTH;No;0;ON; 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; 215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON; 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; 215B;VULGAR FRACTION ONE EIGHTH;No;0;ON; 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; 215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON; 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; 215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON; 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; 215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON; 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; 215F;FRACTION NUMERATOR ONE;No;0;ON; 0031 2044;;;1;N;;;;; 2160;ROMAN NUMERAL ONE;Nl;0;L; 0049;;;1;N;;;;2170; 2161;ROMAN NUMERAL TWO;Nl;0;L; 0049 0049;;;2;N;;;;2171; 2162;ROMAN NUMERAL THREE;Nl;0;L; 0049 0049 0049;;;3;N;;;;2172; 2163;ROMAN NUMERAL FOUR;Nl;0;L; 0049 0056;;;4;N;;;;2173; 2164;ROMAN NUMERAL FIVE;Nl;0;L; 0056;;;5;N;;;;2174; 2165;ROMAN NUMERAL SIX;Nl;0;L; 0056 0049;;;6;N;;;;2175; 2166;ROMAN NUMERAL SEVEN;Nl;0;L; 0056 0049 0049;;;7;N;;;;2176; 2167;ROMAN NUMERAL EIGHT;Nl;0;L; 0056 0049 0049 0049;;;8;N;;;;2177; 2168;ROMAN NUMERAL NINE;Nl;0;L; 0049 0058;;;9;N;;;;2178; 2169;ROMAN NUMERAL TEN;Nl;0;L; 0058;;;10;N;;;;2179; 216A;ROMAN NUMERAL ELEVEN;Nl;0;L; 0058 0049;;;11;N;;;;217A; 216B;ROMAN NUMERAL TWELVE;Nl;0;L; 0058 0049 0049;;;12;N;;;;217B; 216C;ROMAN NUMERAL FIFTY;Nl;0;L; 004C;;;50;N;;;;217C; 216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0043;;;100;N;;;;217D; 216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0044;;;500;N;;;;217E; 216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 004D;;;1000;N;;;;217F; 2170;SMALL ROMAN NUMERAL ONE;Nl;0;L; 0069;;;1;N;;;2160;;2160 2171;SMALL ROMAN NUMERAL TWO;Nl;0;L; 0069 0069;;;2;N;;;2161;;2161 2172;SMALL ROMAN NUMERAL THREE;Nl;0;L; 0069 0069 0069;;;3;N;;;2162;;2162 2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L; 0069 0076;;;4;N;;;2163;;2163 2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L; 0076;;;5;N;;;2164;;2164 2175;SMALL ROMAN NUMERAL SIX;Nl;0;L; 0076 0069;;;6;N;;;2165;;2165 2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L; 0076 0069 0069;;;7;N;;;2166;;2166 2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L; 0076 0069 0069 0069;;;8;N;;;2167;;2167 2178;SMALL ROMAN NUMERAL NINE;Nl;0;L; 0069 0078;;;9;N;;;2168;;2168 2179;SMALL ROMAN NUMERAL TEN;Nl;0;L; 0078;;;10;N;;;2169;;2169 217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L; 0078 0069;;;11;N;;;216A;;216A 217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L; 0078 0069 0069;;;12;N;;;216B;;216B 217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L; 006C;;;50;N;;;216C;;216C 217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0063;;;100;N;;;216D;;216D 217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0064;;;500;N;;;216E;;216E 217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 006D;;;1000;N;;;216F;;216F 2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; 2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; 2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; 2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184; 2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183 2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;; 2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;; 2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;; 2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;; 2189;VULGAR FRACTION ZERO THIRDS;No;0;ON; 0030 2044 0033;;;0;N;;;;; 2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; 2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; 2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; 2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; 2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; 2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; 2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; 2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; 2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; 219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; 219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; 219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; 219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; 219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; 219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; 21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; 21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; 21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; 21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; 21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; 21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; 21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; 21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; 21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; 21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; 21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; 21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; 21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; 21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; 21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; 21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; 21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; 21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; 21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; 21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; 21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; 21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; 21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; 21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; 21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; 21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; 21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; 21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; 21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; 21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; 21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; 21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; 21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; 21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; 21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; 21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; 21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; 21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; 21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; 21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; 21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; 21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; 21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; 21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; 21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; 21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; 21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; 21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; 21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; 21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; 21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; 21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; 21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; 21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; 21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; 21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; 21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; 21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; 21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; 21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; 21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; 21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; 21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; 21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; 21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; 21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; 21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; 21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; 21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; 21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; 21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; 21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; 21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 2200;FOR ALL;Sm;0;ON;;;;;N;;;;; 2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; 2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; 2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; 2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; 2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; 2206;INCREMENT;Sm;0;ON;;;;;N;;;;; 2207;NABLA;Sm;0;ON;;;;;N;;;;; 2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; 220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; 220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; 220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; 2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; 2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; 2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;; 2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; 2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; 2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; 2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; 2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; 221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; 221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; 221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; 221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; 221E;INFINITY;Sm;0;ON;;;;;N;;;;; 221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; 2220;ANGLE;Sm;0;ON;;;;;Y;;;;; 2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; 2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; 2223;DIVIDES;Sm;0;ON;;;;;N;;;;; 2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; 2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; 2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; 2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; 222A;UNION;Sm;0;ON;;;;;N;;;;; 222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222C;DOUBLE INTEGRAL;Sm;0;ON; 222B 222B;;;;Y;;;;; 222D;TRIPLE INTEGRAL;Sm;0;ON; 222B 222B 222B;;;;Y;;;;; 222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222F;SURFACE INTEGRAL;Sm;0;ON; 222E 222E;;;;Y;;;;; 2230;VOLUME INTEGRAL;Sm;0;ON; 222E 222E 222E;;;;Y;;;;; 2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2234;THEREFORE;Sm;0;ON;;;;;N;;;;; 2235;BECAUSE;Sm;0;ON;;;;;N;;;;; 2236;RATIO;Sm;0;ON;;;;;N;;;;; 2237;PROPORTION;Sm;0;ON;;;;;N;;;;; 2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; 2239;EXCESS;Sm;0;ON;;;;;Y;;;;; 223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; 223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; 223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;; 223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; 223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; 2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; 2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; 2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; 2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; 2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; 2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; 224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; 224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; 2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; 2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; 2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; 2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; 2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; 2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; 2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; 2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; 225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; 225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; 225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; 225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; 225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; 225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; 2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; 2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; 2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; 2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; 2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; 2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; 2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; 2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; 226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; 226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; 226C;BETWEEN;Sm;0;ON;;;;;N;;;;; 226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;; 226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; 226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; 2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; 2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; 2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; 2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; 2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; 2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; 2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; 2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; 2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; 2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; 227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; 227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; 2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; 2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; 2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; 2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; 2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; 2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; 2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; 228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; 228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; 228C;MULTISET;Sm;0;ON;;;;;Y;;;;; 228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; 228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; 228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; 2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; 2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; 2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; 2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; 229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; 229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; 229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; 229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; 22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; 22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; 22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; 22A5;UP TACK;Sm;0;ON;;;;;N;;;;; 22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; 22A7;MODELS;Sm;0;ON;;;;;Y;;;;; 22A8;TRUE;Sm;0;ON;;;;;Y;;;;; 22A9;FORCES;Sm;0;ON;;;;;Y;;;;; 22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; 22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; 22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; 22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; 22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; 22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; 22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; 22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; 22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; 22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; 22BB;XOR;Sm;0;ON;;;;;N;;;;; 22BC;NAND;Sm;0;ON;;;;;N;;;;; 22BD;NOR;Sm;0;ON;;;;;N;;;;; 22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; 22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; 22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; 22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; 22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; 22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; 22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; 22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; 22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; 22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; 22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; 22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; 22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; 22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; 22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; 22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; 22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; 22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; 22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; 22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; 22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; 22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; 22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; 22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; 22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; 22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; 22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; 22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; 22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; 22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; 22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; 22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; 22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; 22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; 22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; 2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; 2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; 2302;HOUSE;So;0;ON;;;;;N;;;;; 2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; 2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; 2305;PROJECTIVE;So;0;ON;;;;;N;;;;; 2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; 2307;WAVY LINE;So;0;ON;;;;;N;;;;; 2308;LEFT CEILING;Sm;0;ON;;;;;Y;;;;; 2309;RIGHT CEILING;Sm;0;ON;;;;;Y;;;;; 230A;LEFT FLOOR;Sm;0;ON;;;;;Y;;;;; 230B;RIGHT FLOOR;Sm;0;ON;;;;;Y;;;;; 230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; 230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; 230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; 230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; 2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; 2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; 2312;ARC;So;0;ON;;;;;N;;;;; 2313;SEGMENT;So;0;ON;;;;;N;;;;; 2314;SECTOR;So;0;ON;;;;;N;;;;; 2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; 2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; 2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; 2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; 231A;WATCH;So;0;ON;;;;;N;;;;; 231B;HOURGLASS;So;0;ON;;;;;N;;;;; 231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; 231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; 231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; 231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; 2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2322;FROWN;So;0;ON;;;;;N;;;;; 2323;SMILE;So;0;ON;;;;;N;;;;; 2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; 2325;OPTION KEY;So;0;ON;;;;;N;;;;; 2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; 2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; 2328;KEYBOARD;So;0;ON;;;;;N;;;;; 2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; 232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; 232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; 232C;BENZENE RING;So;0;ON;;;;;N;;;;; 232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; 232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; 232F;SYMMETRY;So;0;ON;;;;;N;;;;; 2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; 2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; 2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; 2333;SLOPE;So;0;ON;;;;;N;;;;; 2334;COUNTERBORE;So;0;ON;;;;;N;;;;; 2335;COUNTERSINK;So;0;ON;;;;;N;;;;; 2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; 2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; 2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; 2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; 233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; 233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; 233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; 233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; 233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; 233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; 2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; 2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; 2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; 2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; 2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; 2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; 2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; 2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; 2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; 2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; 234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;; 234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; 234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; 234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; 234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;; 234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; 2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; 2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;; 2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; 2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; 2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; 2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;; 2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; 2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; 2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; 2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; 235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; 235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; 235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; 235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; 235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; 235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; 2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; 2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;; 2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; 2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; 2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; 2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; 2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; 2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; 2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; 2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; 236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; 236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; 236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; 236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; 236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; 236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; 2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; 2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; 2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; 2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; 2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; 2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; 2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; 2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; 2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; 2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; 237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; 237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; 237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; 237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; 237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; 237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; 2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; 2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; 2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; 2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; 2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; 2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; 2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;; 238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;; 238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;; 238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; 238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; 238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; 238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; 2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; 2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; 2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; 2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; 2398;NEXT PAGE;So;0;ON;;;;;N;;;;; 2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; 23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; 23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; 23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; 23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; 23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; 23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; 23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; 23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; 23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; 23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; 23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; 23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; 23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; 23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; 23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; 23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;; 23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;; 23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;; 23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;; 23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;; 23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;; 23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;; 23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;; 23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;; 23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;; 23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;; 23DA;EARTH GROUND;So;0;ON;;;;;N;;;;; 23DB;FUSE;So;0;ON;;;;;N;;;;; 23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;; 23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;; 23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;; 23E5;FLATNESS;So;0;ON;;;;;N;;;;; 23E6;AC CURRENT;So;0;ON;;;;;N;;;;; 23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; 23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; 2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; 2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; 2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; 2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; 2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; 2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; 2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; 240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; 240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; 240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; 240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; 240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; 240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; 2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; 2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; 2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; 2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; 2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; 2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; 2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; 2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; 2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; 2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; 241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; 241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; 241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; 241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; 241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; 241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; 2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; 2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; 2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; 2423;OPEN BOX;So;0;ON;;;;;N;;;;; 2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; 2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; 2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; 2440;OCR HOOK;So;0;ON;;;;;N;;;;; 2441;OCR CHAIR;So;0;ON;;;;;N;;;;; 2442;OCR FORK;So;0;ON;;;;;N;;;;; 2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; 2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; 2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; 2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; 2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; 2448;OCR DASH;So;0;ON;;;;;N;;;;; 2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; 244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; 2460;CIRCLED DIGIT ONE;No;0;ON; 0031;;1;1;N;;;;; 2461;CIRCLED DIGIT TWO;No;0;ON; 0032;;2;2;N;;;;; 2462;CIRCLED DIGIT THREE;No;0;ON; 0033;;3;3;N;;;;; 2463;CIRCLED DIGIT FOUR;No;0;ON; 0034;;4;4;N;;;;; 2464;CIRCLED DIGIT FIVE;No;0;ON; 0035;;5;5;N;;;;; 2465;CIRCLED DIGIT SIX;No;0;ON; 0036;;6;6;N;;;;; 2466;CIRCLED DIGIT SEVEN;No;0;ON; 0037;;7;7;N;;;;; 2467;CIRCLED DIGIT EIGHT;No;0;ON; 0038;;8;8;N;;;;; 2468;CIRCLED DIGIT NINE;No;0;ON; 0039;;9;9;N;;;;; 2469;CIRCLED NUMBER TEN;No;0;ON; 0031 0030;;;10;N;;;;; 246A;CIRCLED NUMBER ELEVEN;No;0;ON; 0031 0031;;;11;N;;;;; 246B;CIRCLED NUMBER TWELVE;No;0;ON; 0031 0032;;;12;N;;;;; 246C;CIRCLED NUMBER THIRTEEN;No;0;ON; 0031 0033;;;13;N;;;;; 246D;CIRCLED NUMBER FOURTEEN;No;0;ON; 0031 0034;;;14;N;;;;; 246E;CIRCLED NUMBER FIFTEEN;No;0;ON; 0031 0035;;;15;N;;;;; 246F;CIRCLED NUMBER SIXTEEN;No;0;ON; 0031 0036;;;16;N;;;;; 2470;CIRCLED NUMBER SEVENTEEN;No;0;ON; 0031 0037;;;17;N;;;;; 2471;CIRCLED NUMBER EIGHTEEN;No;0;ON; 0031 0038;;;18;N;;;;; 2472;CIRCLED NUMBER NINETEEN;No;0;ON; 0031 0039;;;19;N;;;;; 2473;CIRCLED NUMBER TWENTY;No;0;ON; 0032 0030;;;20;N;;;;; 2474;PARENTHESIZED DIGIT ONE;No;0;ON; 0028 0031 0029;;1;1;N;;;;; 2475;PARENTHESIZED DIGIT TWO;No;0;ON; 0028 0032 0029;;2;2;N;;;;; 2476;PARENTHESIZED DIGIT THREE;No;0;ON; 0028 0033 0029;;3;3;N;;;;; 2477;PARENTHESIZED DIGIT FOUR;No;0;ON; 0028 0034 0029;;4;4;N;;;;; 2478;PARENTHESIZED DIGIT FIVE;No;0;ON; 0028 0035 0029;;5;5;N;;;;; 2479;PARENTHESIZED DIGIT SIX;No;0;ON; 0028 0036 0029;;6;6;N;;;;; 247A;PARENTHESIZED DIGIT SEVEN;No;0;ON; 0028 0037 0029;;7;7;N;;;;; 247B;PARENTHESIZED DIGIT EIGHT;No;0;ON; 0028 0038 0029;;8;8;N;;;;; 247C;PARENTHESIZED DIGIT NINE;No;0;ON; 0028 0039 0029;;9;9;N;;;;; 247D;PARENTHESIZED NUMBER TEN;No;0;ON; 0028 0031 0030 0029;;;10;N;;;;; 247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON; 0028 0031 0031 0029;;;11;N;;;;; 247F;PARENTHESIZED NUMBER TWELVE;No;0;ON; 0028 0031 0032 0029;;;12;N;;;;; 2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON; 0028 0031 0033 0029;;;13;N;;;;; 2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON; 0028 0031 0034 0029;;;14;N;;;;; 2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON; 0028 0031 0035 0029;;;15;N;;;;; 2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON; 0028 0031 0036 0029;;;16;N;;;;; 2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON; 0028 0031 0037 0029;;;17;N;;;;; 2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON; 0028 0031 0038 0029;;;18;N;;;;; 2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON; 0028 0031 0039 0029;;;19;N;;;;; 2487;PARENTHESIZED NUMBER TWENTY;No;0;ON; 0028 0032 0030 0029;;;20;N;;;;; 2488;DIGIT ONE FULL STOP;No;0;EN; 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; 2489;DIGIT TWO FULL STOP;No;0;EN; 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; 248A;DIGIT THREE FULL STOP;No;0;EN; 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; 248B;DIGIT FOUR FULL STOP;No;0;EN; 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; 248C;DIGIT FIVE FULL STOP;No;0;EN; 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; 248D;DIGIT SIX FULL STOP;No;0;EN; 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; 248E;DIGIT SEVEN FULL STOP;No;0;EN; 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; 248F;DIGIT EIGHT FULL STOP;No;0;EN; 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; 2490;DIGIT NINE FULL STOP;No;0;EN; 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; 2491;NUMBER TEN FULL STOP;No;0;EN; 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; 2492;NUMBER ELEVEN FULL STOP;No;0;EN; 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; 2493;NUMBER TWELVE FULL STOP;No;0;EN; 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; 2494;NUMBER THIRTEEN FULL STOP;No;0;EN; 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; 2495;NUMBER FOURTEEN FULL STOP;No;0;EN; 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; 2496;NUMBER FIFTEEN FULL STOP;No;0;EN; 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; 2497;NUMBER SIXTEEN FULL STOP;No;0;EN; 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; 2498;NUMBER SEVENTEEN FULL STOP;No;0;EN; 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; 2499;NUMBER EIGHTEEN FULL STOP;No;0;EN; 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; 249A;NUMBER NINETEEN FULL STOP;No;0;EN; 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; 249B;NUMBER TWENTY FULL STOP;No;0;EN; 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; 249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L; 0028 0061 0029;;;;N;;;;; 249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L; 0028 0062 0029;;;;N;;;;; 249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L; 0028 0063 0029;;;;N;;;;; 249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L; 0028 0064 0029;;;;N;;;;; 24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L; 0028 0065 0029;;;;N;;;;; 24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L; 0028 0066 0029;;;;N;;;;; 24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L; 0028 0067 0029;;;;N;;;;; 24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L; 0028 0068 0029;;;;N;;;;; 24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L; 0028 0069 0029;;;;N;;;;; 24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L; 0028 006A 0029;;;;N;;;;; 24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L; 0028 006B 0029;;;;N;;;;; 24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L; 0028 006C 0029;;;;N;;;;; 24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L; 0028 006D 0029;;;;N;;;;; 24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L; 0028 006E 0029;;;;N;;;;; 24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L; 0028 006F 0029;;;;N;;;;; 24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L; 0028 0070 0029;;;;N;;;;; 24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L; 0028 0071 0029;;;;N;;;;; 24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L; 0028 0072 0029;;;;N;;;;; 24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L; 0028 0073 0029;;;;N;;;;; 24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L; 0028 0074 0029;;;;N;;;;; 24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L; 0028 0075 0029;;;;N;;;;; 24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L; 0028 0076 0029;;;;N;;;;; 24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L; 0028 0077 0029;;;;N;;;;; 24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L; 0028 0078 0029;;;;N;;;;; 24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L; 0028 0079 0029;;;;N;;;;; 24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L; 0028 007A 0029;;;;N;;;;; 24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;24D0; 24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;24D1; 24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;24D2; 24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;24D3; 24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;24D4; 24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;24D5; 24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;24D6; 24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;24D7; 24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;24D8; 24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;24D9; 24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;24DA; 24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;24DB; 24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;24DC; 24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;24DD; 24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;24DE; 24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;24DF; 24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;24E0; 24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;24E1; 24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;24E2; 24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;24E3; 24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;24E4; 24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;24E5; 24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;24E6; 24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;24E7; 24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;24E8; 24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;24E9; 24D0;CIRCLED LATIN SMALL LETTER A;So;0;L; 0061;;;;N;;;24B6;;24B6 24D1;CIRCLED LATIN SMALL LETTER B;So;0;L; 0062;;;;N;;;24B7;;24B7 24D2;CIRCLED LATIN SMALL LETTER C;So;0;L; 0063;;;;N;;;24B8;;24B8 24D3;CIRCLED LATIN SMALL LETTER D;So;0;L; 0064;;;;N;;;24B9;;24B9 24D4;CIRCLED LATIN SMALL LETTER E;So;0;L; 0065;;;;N;;;24BA;;24BA 24D5;CIRCLED LATIN SMALL LETTER F;So;0;L; 0066;;;;N;;;24BB;;24BB 24D6;CIRCLED LATIN SMALL LETTER G;So;0;L; 0067;;;;N;;;24BC;;24BC 24D7;CIRCLED LATIN SMALL LETTER H;So;0;L; 0068;;;;N;;;24BD;;24BD 24D8;CIRCLED LATIN SMALL LETTER I;So;0;L; 0069;;;;N;;;24BE;;24BE 24D9;CIRCLED LATIN SMALL LETTER J;So;0;L; 006A;;;;N;;;24BF;;24BF 24DA;CIRCLED LATIN SMALL LETTER K;So;0;L; 006B;;;;N;;;24C0;;24C0 24DB;CIRCLED LATIN SMALL LETTER L;So;0;L; 006C;;;;N;;;24C1;;24C1 24DC;CIRCLED LATIN SMALL LETTER M;So;0;L; 006D;;;;N;;;24C2;;24C2 24DD;CIRCLED LATIN SMALL LETTER N;So;0;L; 006E;;;;N;;;24C3;;24C3 24DE;CIRCLED LATIN SMALL LETTER O;So;0;L; 006F;;;;N;;;24C4;;24C4 24DF;CIRCLED LATIN SMALL LETTER P;So;0;L; 0070;;;;N;;;24C5;;24C5 24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L; 0071;;;;N;;;24C6;;24C6 24E1;CIRCLED LATIN SMALL LETTER R;So;0;L; 0072;;;;N;;;24C7;;24C7 24E2;CIRCLED LATIN SMALL LETTER S;So;0;L; 0073;;;;N;;;24C8;;24C8 24E3;CIRCLED LATIN SMALL LETTER T;So;0;L; 0074;;;;N;;;24C9;;24C9 24E4;CIRCLED LATIN SMALL LETTER U;So;0;L; 0075;;;;N;;;24CA;;24CA 24E5;CIRCLED LATIN SMALL LETTER V;So;0;L; 0076;;;;N;;;24CB;;24CB 24E6;CIRCLED LATIN SMALL LETTER W;So;0;L; 0077;;;;N;;;24CC;;24CC 24E7;CIRCLED LATIN SMALL LETTER X;So;0;L; 0078;;;;N;;;24CD;;24CD 24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L; 0079;;;;N;;;24CE;;24CE 24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L; 007A;;;;N;;;24CF;;24CF 24EA;CIRCLED DIGIT ZERO;No;0;ON; 0030;;0;0;N;;;;; 24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; 24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; 24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; 24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; 24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; 24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; 24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; 24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; 24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; 24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; 24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; 24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; 24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; 24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; 24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; 24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; 24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; 24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; 24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; 24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;; 2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; 2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; 2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; 2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; 2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; 2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; 2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; 2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; 2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; 2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; 250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; 250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; 250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; 250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; 250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; 250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; 2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; 2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; 2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; 2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; 2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; 2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; 2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; 2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; 2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; 2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; 251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; 251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; 251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; 251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; 251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; 251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; 2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; 2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; 2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; 2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; 2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; 2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; 2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; 2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; 2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; 2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; 252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; 252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; 252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; 252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; 252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; 252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; 2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; 2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; 2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; 2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; 2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; 2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; 2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; 2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; 2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; 2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; 253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; 253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; 253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; 253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; 253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; 253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; 2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; 2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; 2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; 2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; 2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; 2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; 2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; 2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; 2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; 2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; 254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; 254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; 254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; 254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; 254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; 254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; 2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; 2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; 2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; 2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; 2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; 2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; 2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; 2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; 2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; 2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; 255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; 255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; 255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; 255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; 255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; 255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; 2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; 2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; 2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; 2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; 2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; 2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; 2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; 2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; 2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; 2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; 256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; 256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; 256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; 256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; 256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; 256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; 2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; 2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; 2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; 2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; 2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; 2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; 2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; 2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; 2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; 2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; 257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; 257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; 257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; 257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; 257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; 257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; 2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; 2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; 2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; 2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2588;FULL BLOCK;So;0;ON;;;;;N;;;;; 2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; 258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; 258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; 2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; 2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; 2593;DARK SHADE;So;0;ON;;;;;N;;;;; 2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; 2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; 2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; 2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; 259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; 25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; 25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; 25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; 25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; 25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; 25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; 25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; 25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; 25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; 25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; 25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; 25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; 25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; 25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; 25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; 25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; 25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; 25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; 25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; 25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; 25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; 25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; 25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; 25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; 25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; 25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; 25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; 25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 25C9;FISHEYE;So;0;ON;;;;;N;;;;; 25CA;LOZENGE;So;0;ON;;;;;N;;;;; 25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; 25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25CE;BULLSEYE;So;0;ON;;;;;N;;;;; 25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; 25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; 25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; 25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; 25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; 25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; 25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; 25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; 25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; 25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; 2601;CLOUD;So;0;ON;;;;;N;;;;; 2602;UMBRELLA;So;0;ON;;;;;N;;;;; 2603;SNOWMAN;So;0;ON;;;;;N;;;;; 2604;COMET;So;0;ON;;;;;N;;;;; 2605;BLACK STAR;So;0;ON;;;;;N;;;;; 2606;WHITE STAR;So;0;ON;;;;;N;;;;; 2607;LIGHTNING;So;0;ON;;;;;N;;;;; 2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; 2609;SUN;So;0;ON;;;;;N;;;;; 260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; 260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; 260C;CONJUNCTION;So;0;ON;;;;;N;;;;; 260D;OPPOSITION;So;0;ON;;;;;N;;;;; 260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; 260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; 2610;BALLOT BOX;So;0;ON;;;;;N;;;;; 2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; 2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; 2613;SALTIRE;So;0;ON;;;;;N;;;;; 2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;; 2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;; 2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 2618;SHAMROCK;So;0;ON;;;;;N;;;;; 2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; 2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; 2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; 2624;CADUCEUS;So;0;ON;;;;;N;;;;; 2625;ANKH;So;0;ON;;;;;N;;;;; 2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; 2627;CHI RHO;So;0;ON;;;;;N;;;;; 2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; 2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; 262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; 262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; 262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; 262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; 262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; 262F;YIN YANG;So;0;ON;;;;;N;;;;; 2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; 2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; 2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; 2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; 2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; 2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; 2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; 2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; 2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; 263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; 263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; 263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; 263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; 263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; 263F;MERCURY;So;0;ON;;;;;N;;;;; 2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; 2641;EARTH;So;0;ON;;;;;N;;;;; 2642;MALE SIGN;So;0;ON;;;;;N;;;;; 2643;JUPITER;So;0;ON;;;;;N;;;;; 2644;SATURN;So;0;ON;;;;;N;;;;; 2645;URANUS;So;0;ON;;;;;N;;;;; 2646;NEPTUNE;So;0;ON;;;;;N;;;;; 2647;PLUTO;So;0;ON;;;;;N;;;;; 2648;ARIES;So;0;ON;;;;;N;;;;; 2649;TAURUS;So;0;ON;;;;;N;;;;; 264A;GEMINI;So;0;ON;;;;;N;;;;; 264B;CANCER;So;0;ON;;;;;N;;;;; 264C;LEO;So;0;ON;;;;;N;;;;; 264D;VIRGO;So;0;ON;;;;;N;;;;; 264E;LIBRA;So;0;ON;;;;;N;;;;; 264F;SCORPIUS;So;0;ON;;;;;N;;;;; 2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; 2651;CAPRICORN;So;0;ON;;;;;N;;;;; 2652;AQUARIUS;So;0;ON;;;;;N;;;;; 2653;PISCES;So;0;ON;;;;;N;;;;; 2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; 2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; 2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; 2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; 2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; 2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; 265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; 265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; 265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; 265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; 265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; 265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; 2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; 2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; 2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; 2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; 2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; 2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; 2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; 2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; 266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; 266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; 266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; 266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; 266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; 266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; 2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;; 2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;; 2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;; 2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;; 2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;; 2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;; 2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;; 267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; 267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;; 267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;; 2680;DIE FACE-1;So;0;ON;;;;;N;;;;; 2681;DIE FACE-2;So;0;ON;;;;;N;;;;; 2682;DIE FACE-3;So;0;ON;;;;;N;;;;; 2683;DIE FACE-4;So;0;ON;;;;;N;;;;; 2684;DIE FACE-5;So;0;ON;;;;;N;;;;; 2685;DIE FACE-6;So;0;ON;;;;;N;;;;; 2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; 2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; 2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; 2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; 268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;; 268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;; 268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;; 268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;; 268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;; 268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;; 2690;WHITE FLAG;So;0;ON;;;;;N;;;;; 2691;BLACK FLAG;So;0;ON;;;;;N;;;;; 2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;; 2693;ANCHOR;So;0;ON;;;;;N;;;;; 2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;; 2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;; 2696;SCALES;So;0;ON;;;;;N;;;;; 2697;ALEMBIC;So;0;ON;;;;;N;;;;; 2698;FLOWER;So;0;ON;;;;;N;;;;; 2699;GEAR;So;0;ON;;;;;N;;;;; 269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;; 269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;; 269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;; 269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;; 269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;; 26A0;WARNING SIGN;So;0;ON;;;;;N;;;;; 26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;; 26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;; 26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;; 26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;; 26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;; 26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;; 26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;; 26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;; 26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;; 26B0;COFFIN;So;0;ON;;;;;N;;;;; 26B1;FUNERAL URN;So;0;ON;;;;;N;;;;; 26B2;NEUTER;So;0;ON;;;;;N;;;;; 26B3;CERES;So;0;ON;;;;;N;;;;; 26B4;PALLAS;So;0;ON;;;;;N;;;;; 26B5;JUNO;So;0;ON;;;;;N;;;;; 26B6;VESTA;So;0;ON;;;;;N;;;;; 26B7;CHIRON;So;0;ON;;;;;N;;;;; 26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;; 26B9;SEXTILE;So;0;ON;;;;;N;;;;; 26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;; 26BB;QUINCUNX;So;0;ON;;;;;N;;;;; 26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;; 26BD;SOCCER BALL;So;0;ON;;;;;N;;;;; 26BE;BASEBALL;So;0;ON;;;;;N;;;;; 26BF;SQUARED KEY;So;0;ON;;;;;N;;;;; 26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;; 26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; 26C6;RAIN;So;0;ON;;;;;N;;;;; 26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;; 26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;; 26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; 26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; 26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; 26CF;PICK;So;0;ON;;;;;N;;;;; 26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; 26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; 26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;; 26D3;CHAINS;So;0;ON;;;;;N;;;;; 26D4;NO ENTRY;So;0;ON;;;;;N;;;;; 26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;; 26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;; 26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;; 26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; 26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; 26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; 26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; 26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; 26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; 26EA;CHURCH;So;0;ON;;;;;N;;;;; 26EB;CASTLE;So;0;ON;;;;;N;;;;; 26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;; 26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;; 26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;; 26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;; 26F0;MOUNTAIN;So;0;ON;;;;;N;;;;; 26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;; 26F2;FOUNTAIN;So;0;ON;;;;;N;;;;; 26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;; 26F4;FERRY;So;0;ON;;;;;N;;;;; 26F5;SAILBOAT;So;0;ON;;;;;N;;;;; 26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;; 26F7;SKIER;So;0;ON;;;;;N;;;;; 26F8;ICE SKATE;So;0;ON;;;;;N;;;;; 26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;; 26FA;TENT;So;0;ON;;;;;N;;;;; 26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;; 26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;; 26FD;FUEL PUMP;So;0;ON;;;;;N;;;;; 26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;; 26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;; 2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; 2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; 2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; 2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; 2708;AIRPLANE;So;0;ON;;;;;N;;;;; 2709;ENVELOPE;So;0;ON;;;;;N;;;;; 270C;VICTORY HAND;So;0;ON;;;;;N;;;;; 270D;WRITING HAND;So;0;ON;;;;;N;;;;; 270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 270F;PENCIL;So;0;ON;;;;;N;;;;; 2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 2711;WHITE NIB;So;0;ON;;;;;N;;;;; 2712;BLACK NIB;So;0;ON;;;;;N;;;;; 2713;CHECK MARK;So;0;ON;;;;;N;;;;; 2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2717;BALLOT X;So;0;ON;;;;;N;;;;; 2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; 2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; 271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; 271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; 271D;LATIN CROSS;So;0;ON;;;;;N;;;;; 271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; 2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; 2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; 2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; 272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; 272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; 272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; 2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; 2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; 2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; 273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; 273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; 273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; 2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; 2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; 2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; 2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; 2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; 2747;SPARKLE;So;0;ON;;;;;N;;;;; 2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; 2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; 2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; 2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; 2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; 275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; 275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; 2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; 2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; 2766;FLORAL HEART;So;0;ON;;;;;N;;;;; 2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; 2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; 2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; 2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; 277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; 277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; 277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; 277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; 277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; 277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; 2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; 2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; 2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; 2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; 2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; 2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; 2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; 2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; 278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; 278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; 278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; 278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; 278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; 278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; 2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; 2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; 2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; 2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; 2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; 279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; 279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; 279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; 279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; 279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; 279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; 27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; 27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; 27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; 27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; 27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; 27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; 27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; 27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; 27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; 27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; 27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; 27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; 27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; 27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; 27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; 27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; 27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; 27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; 27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; 27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; 27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;; 27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;; 27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;; 27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;; 27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;; 27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;; 27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; 27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; 27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; 27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; 27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; 27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; 27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; 27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; 27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; 27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; 27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; 27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; 27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; 27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; 27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; 27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;; 2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;; 2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;; 2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;; 2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;; 2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;; 2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;; 2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;; 2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;; 2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;; 280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;; 280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;; 280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;; 280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;; 280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;; 280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;; 2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;; 2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;; 2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;; 2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;; 2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;; 2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;; 2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;; 2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;; 2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;; 2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;; 281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;; 281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;; 281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;; 281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;; 281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;; 281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;; 2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;; 2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;; 2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;; 2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;; 2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;; 2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;; 2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;; 2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;; 2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;; 2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;; 282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;; 282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;; 282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;; 282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;; 282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;; 282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;; 2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;; 2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;; 2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;; 2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;; 2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;; 2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;; 2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;; 2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;; 2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;; 2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;; 283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;; 283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;; 283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;; 283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;; 283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;; 283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;; 2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;; 2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;; 2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;; 2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;; 2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;; 2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;; 2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;; 2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;; 2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;; 2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;; 284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;; 284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;; 284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;; 284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;; 284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;; 284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;; 2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;; 2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;; 2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;; 2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;; 2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;; 2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;; 2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;; 2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;; 2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;; 2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;; 285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;; 285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;; 285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;; 285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;; 285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;; 285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;; 2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;; 2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;; 2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;; 2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;; 2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;; 2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;; 2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;; 2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;; 2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;; 2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;; 286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;; 286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;; 286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;; 286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;; 286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;; 286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;; 2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;; 2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;; 2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;; 2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;; 2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;; 2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;; 2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;; 2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;; 2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;; 2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;; 287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;; 287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;; 287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;; 287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;; 287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;; 287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;; 2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;; 2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;; 2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;; 2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;; 2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;; 2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;; 2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;; 2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;; 2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;; 2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;; 288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;; 288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;; 288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;; 288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;; 288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;; 288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;; 2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;; 2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;; 2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;; 2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;; 2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;; 2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;; 2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;; 2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;; 2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;; 2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;; 289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;; 289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;; 289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;; 289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;; 289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;; 289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;; 28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;; 28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;; 28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;; 28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;; 28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;; 28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;; 28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;; 28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;; 28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;; 28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;; 28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;; 28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;; 28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;; 28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;; 28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;; 28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;; 28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;; 28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;; 28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;; 28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;; 28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;; 28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;; 28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;; 28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;; 28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;; 28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;; 28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;; 28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;; 28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;; 28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;; 28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;; 28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;; 28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;; 28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;; 28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;; 28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;; 28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;; 28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;; 28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;; 28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;; 28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;; 28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;; 28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;; 28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;; 28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;; 28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;; 28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;; 28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;; 28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;; 28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;; 28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;; 28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;; 28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;; 28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;; 28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;; 28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;; 28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;; 28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;; 28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;; 28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;; 28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;; 28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;; 28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;; 28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;; 28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;; 28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;; 28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;; 28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;; 28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;; 28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;; 28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;; 28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;; 28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;; 28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;; 28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;; 28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;; 28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;; 28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;; 28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;; 28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;; 28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;; 28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;; 28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;; 28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;; 28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;; 28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;; 28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;; 28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;; 28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;; 28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;; 28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;; 28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;; 28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;; 28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;; 28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;; 28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;; 2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; 2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; 2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; 2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; 2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; 293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; 293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; 2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; 2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; 297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; 297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; 2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; 2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; 2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; 2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; 2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; 2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; 2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; 2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; 298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; 298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; 298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; 298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; 298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; 298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; 2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; 2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; 2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; 2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; 299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; 299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; 299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; 299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; 299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; 29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; 29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; 29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; 29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; 29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; 29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; 29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; 29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; 29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; 29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; 29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; 29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; 29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; 29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; 29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; 29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; 29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; 29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; 29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; 29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; 29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; 29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; 29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; 29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; 29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; 29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; 29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; 29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; 29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; 29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; 29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; 29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; 29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; 29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 29FE;TINY;Sm;0;ON;;;;;N;;;;; 29FF;MINY;Sm;0;ON;;;;;N;;;;; 2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; 2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; 2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; 2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; 2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; 2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; 2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON; 222B 222B 222B 222B;;;;Y;;;;; 2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; 2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; 2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; 2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; 2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; 2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; 2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; 2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; 2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; 2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2A1D;JOIN;Sm;0;ON;;;;;N;;;;; 2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; 2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; 2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; 2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; 2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; 2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; 2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; 2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; 2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; 2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; 2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; 2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; 2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; 2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; 2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; 2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; 2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; 2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; 2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; 2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; 2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A74;DOUBLE COLON EQUAL;Sm;0;ON; 003A 003A 003D;;;;Y;;;;; 2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D;;;;N;;;;; 2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D 003D;;;;N;;;;; 2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; 2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; 2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; 2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; 2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; 2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; 2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; 2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; 2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; 2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; 2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; 2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; 2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;; 2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;; 2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; 2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; 2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; 2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; 2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; 2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; 2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; 2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; 2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; 2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; 2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;; 2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;; 2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;; 2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;; 2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;; 2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;; 2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;; 2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;; 2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;; 2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;; 2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;; 2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;; 2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;; 2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;; 2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;; 2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30; 2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31; 2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32; 2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33; 2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34; 2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35; 2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36; 2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37; 2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38; 2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39; 2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A; 2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B; 2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C; 2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D; 2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E; 2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F; 2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40; 2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41; 2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42; 2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43; 2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44; 2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45; 2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46; 2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47; 2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48; 2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49; 2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A; 2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B; 2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C; 2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D; 2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E; 2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F; 2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50; 2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51; 2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52; 2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53; 2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54; 2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55; 2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56; 2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57; 2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58; 2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59; 2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A; 2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B; 2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; 2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; 2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; 2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03 2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04 2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05 2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06 2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07 2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08 2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09 2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A 2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B 2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C 2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D 2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E 2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F 2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10 2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11 2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12 2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13 2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14 2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15 2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16 2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17 2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18 2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19 2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A 2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B 2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C 2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D 2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E 2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F 2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20 2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21 2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22 2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23 2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24 2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25 2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26 2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27 2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28 2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29 2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A 2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B 2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C 2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D 2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E 2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; 2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; 2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D; 2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D; 2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A 2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E 2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68; 2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67 2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A; 2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69 2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C; 2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B 2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251; 2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271; 2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250; 2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252; 2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;; 2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73; 2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72 2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;; 2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76; 2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75 2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;; 2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;; 2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;; 2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;; 2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;; 2C7C;LATIN SUBSCRIPT SMALL LETTER J;Ll;0;L; 006A;;;;N;;;;; 2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L; 0056;;;;N;;;;; 2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F; 2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240; 2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81; 2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80 2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83; 2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82 2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85; 2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84 2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87; 2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86 2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89; 2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88 2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B; 2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A 2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D; 2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C 2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F; 2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E 2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91; 2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90 2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93; 2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92 2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95; 2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94 2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97; 2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96 2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99; 2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98 2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B; 2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A 2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D; 2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C 2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F; 2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E 2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1; 2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0 2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3; 2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2 2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5; 2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4 2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7; 2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6 2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9; 2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8 2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB; 2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA 2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD; 2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC 2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF; 2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE 2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1; 2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0 2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3; 2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2 2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5; 2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4 2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7; 2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6 2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9; 2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8 2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB; 2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA 2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD; 2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC 2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF; 2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE 2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1; 2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0 2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3; 2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2 2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5; 2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4 2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7; 2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6 2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9; 2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8 2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB; 2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA 2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD; 2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC 2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF; 2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE 2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1; 2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0 2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3; 2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2 2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5; 2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4 2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7; 2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6 2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9; 2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8 2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB; 2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA 2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD; 2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC 2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF; 2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE 2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1; 2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0 2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3; 2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2 2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;; 2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;; 2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;; 2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;; 2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;; 2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;; 2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;; 2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC; 2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB 2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE; 2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED 2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;; 2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;; 2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;; 2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;; 2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;; 2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;; 2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;; 2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;; 2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0 2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1 2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2 2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3 2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4 2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5 2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6 2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7 2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8 2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9 2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA 2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB 2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC 2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD 2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE 2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF 2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0 2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1 2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2 2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3 2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4 2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5 2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6 2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7 2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8 2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9 2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA 2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB 2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC 2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD 2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE 2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF 2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0 2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1 2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2 2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3 2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4 2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5 2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;; 2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;; 2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;; 2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;; 2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;; 2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;; 2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;; 2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;; 2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;; 2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;; 2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;; 2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;; 2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;; 2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;; 2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;; 2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;; 2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;; 2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;; 2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;; 2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;; 2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;; 2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;; 2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;; 2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;; 2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;; 2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;; 2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;; 2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;; 2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;; 2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;; 2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;; 2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;; 2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;; 2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;; 2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;; 2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;; 2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;; 2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;; 2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;; 2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;; 2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;; 2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;; 2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;; 2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;; 2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;; 2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;; 2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;; 2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;; 2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;; 2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;; 2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;; 2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;; 2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; 2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; 2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L; 2D61;;;;N;;;;; 2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; 2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; 2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; 2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;; 2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;; 2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;; 2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;; 2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;; 2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;; 2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;; 2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;; 2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;; 2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;; 2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;; 2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;; 2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;; 2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;; 2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;; 2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;; 2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;; 2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;; 2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;; 2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;; 2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;; 2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;; 2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;; 2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;; 2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;; 2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;; 2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;; 2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;; 2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;; 2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;; 2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;; 2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;; 2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;; 2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;; 2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; 2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; 2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; 2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;; 2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;; 2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; 2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; 2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;; 2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;; 2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;; 2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;; 2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;; 2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;; 2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;; 2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;; 2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;; 2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;; 2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;; 2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;; 2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;; 2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;; 2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;; 2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;; 2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;; 2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;; 2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;; 2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;; 2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;; 2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;; 2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;; 2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;; 2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;; 2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;; 2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;; 2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;; 2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;; 2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;; 2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;; 2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;; 2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;; 2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;; 2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;; 2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;; 2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;; 2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;; 2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;; 2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;; 2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;; 2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;; 2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;; 2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;; 2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;; 2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;; 2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;; 2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;; 2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;; 2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;; 2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;; 2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;; 2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;; 2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; 2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;; 2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; 2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;; 2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;; 2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;; 2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;; 2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;; 2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;; 2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;; 2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;; 2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;; 2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; 2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;; 2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;; 2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;; 2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;; 2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;; 2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;; 2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;; 2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;; 2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;; 2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;; 2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;; 2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;; 2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;; 2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;; 2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;; 2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;; 2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;; 2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;; 2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;; 2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;; 2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;; 2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;; 2E30;RING POINT;Po;0;ON;;;;;N;;;;; 2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; 2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; 2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; 2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; 2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; 2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; 2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; 2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; 2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; 2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; 2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; 2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; 2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; 2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; 2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; 2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; 2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; 2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; 2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; 2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; 2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; 2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; 2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; 2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; 2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; 2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; 2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; 2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; 2E9F;CJK RADICAL MOTHER;So;0;ON; 6BCD;;;;N;;;;; 2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; 2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; 2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; 2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; 2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; 2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; 2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; 2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; 2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; 2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; 2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; 2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; 2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; 2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; 2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; 2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; 2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; 2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; 2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; 2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; 2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; 2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; 2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; 2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; 2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; 2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; 2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; 2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; 2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; 2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; 2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; 2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; 2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; 2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; 2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; 2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; 2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; 2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; 2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; 2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; 2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; 2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; 2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; 2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; 2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; 2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; 2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; 2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; 2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; 2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; 2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; 2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; 2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; 2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; 2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; 2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; 2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; 2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; 2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; 2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; 2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; 2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; 2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; 2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; 2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; 2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; 2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; 2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; 2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; 2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; 2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; 2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; 2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; 2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; 2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; 2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; 2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; 2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON; 9F9F;;;;N;;;;; 2F00;KANGXI RADICAL ONE;So;0;ON; 4E00;;;;N;;;;; 2F01;KANGXI RADICAL LINE;So;0;ON; 4E28;;;;N;;;;; 2F02;KANGXI RADICAL DOT;So;0;ON; 4E36;;;;N;;;;; 2F03;KANGXI RADICAL SLASH;So;0;ON; 4E3F;;;;N;;;;; 2F04;KANGXI RADICAL SECOND;So;0;ON; 4E59;;;;N;;;;; 2F05;KANGXI RADICAL HOOK;So;0;ON; 4E85;;;;N;;;;; 2F06;KANGXI RADICAL TWO;So;0;ON; 4E8C;;;;N;;;;; 2F07;KANGXI RADICAL LID;So;0;ON; 4EA0;;;;N;;;;; 2F08;KANGXI RADICAL MAN;So;0;ON; 4EBA;;;;N;;;;; 2F09;KANGXI RADICAL LEGS;So;0;ON; 513F;;;;N;;;;; 2F0A;KANGXI RADICAL ENTER;So;0;ON; 5165;;;;N;;;;; 2F0B;KANGXI RADICAL EIGHT;So;0;ON; 516B;;;;N;;;;; 2F0C;KANGXI RADICAL DOWN BOX;So;0;ON; 5182;;;;N;;;;; 2F0D;KANGXI RADICAL COVER;So;0;ON; 5196;;;;N;;;;; 2F0E;KANGXI RADICAL ICE;So;0;ON; 51AB;;;;N;;;;; 2F0F;KANGXI RADICAL TABLE;So;0;ON; 51E0;;;;N;;;;; 2F10;KANGXI RADICAL OPEN BOX;So;0;ON; 51F5;;;;N;;;;; 2F11;KANGXI RADICAL KNIFE;So;0;ON; 5200;;;;N;;;;; 2F12;KANGXI RADICAL POWER;So;0;ON; 529B;;;;N;;;;; 2F13;KANGXI RADICAL WRAP;So;0;ON; 52F9;;;;N;;;;; 2F14;KANGXI RADICAL SPOON;So;0;ON; 5315;;;;N;;;;; 2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON; 531A;;;;N;;;;; 2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON; 5338;;;;N;;;;; 2F17;KANGXI RADICAL TEN;So;0;ON; 5341;;;;N;;;;; 2F18;KANGXI RADICAL DIVINATION;So;0;ON; 535C;;;;N;;;;; 2F19;KANGXI RADICAL SEAL;So;0;ON; 5369;;;;N;;;;; 2F1A;KANGXI RADICAL CLIFF;So;0;ON; 5382;;;;N;;;;; 2F1B;KANGXI RADICAL PRIVATE;So;0;ON; 53B6;;;;N;;;;; 2F1C;KANGXI RADICAL AGAIN;So;0;ON; 53C8;;;;N;;;;; 2F1D;KANGXI RADICAL MOUTH;So;0;ON; 53E3;;;;N;;;;; 2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON; 56D7;;;;N;;;;; 2F1F;KANGXI RADICAL EARTH;So;0;ON; 571F;;;;N;;;;; 2F20;KANGXI RADICAL SCHOLAR;So;0;ON; 58EB;;;;N;;;;; 2F21;KANGXI RADICAL GO;So;0;ON; 5902;;;;N;;;;; 2F22;KANGXI RADICAL GO SLOWLY;So;0;ON; 590A;;;;N;;;;; 2F23;KANGXI RADICAL EVENING;So;0;ON; 5915;;;;N;;;;; 2F24;KANGXI RADICAL BIG;So;0;ON; 5927;;;;N;;;;; 2F25;KANGXI RADICAL WOMAN;So;0;ON; 5973;;;;N;;;;; 2F26;KANGXI RADICAL CHILD;So;0;ON; 5B50;;;;N;;;;; 2F27;KANGXI RADICAL ROOF;So;0;ON; 5B80;;;;N;;;;; 2F28;KANGXI RADICAL INCH;So;0;ON; 5BF8;;;;N;;;;; 2F29;KANGXI RADICAL SMALL;So;0;ON; 5C0F;;;;N;;;;; 2F2A;KANGXI RADICAL LAME;So;0;ON; 5C22;;;;N;;;;; 2F2B;KANGXI RADICAL CORPSE;So;0;ON; 5C38;;;;N;;;;; 2F2C;KANGXI RADICAL SPROUT;So;0;ON; 5C6E;;;;N;;;;; 2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON; 5C71;;;;N;;;;; 2F2E;KANGXI RADICAL RIVER;So;0;ON; 5DDB;;;;N;;;;; 2F2F;KANGXI RADICAL WORK;So;0;ON; 5DE5;;;;N;;;;; 2F30;KANGXI RADICAL ONESELF;So;0;ON; 5DF1;;;;N;;;;; 2F31;KANGXI RADICAL TURBAN;So;0;ON; 5DFE;;;;N;;;;; 2F32;KANGXI RADICAL DRY;So;0;ON; 5E72;;;;N;;;;; 2F33;KANGXI RADICAL SHORT THREAD;So;0;ON; 5E7A;;;;N;;;;; 2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON; 5E7F;;;;N;;;;; 2F35;KANGXI RADICAL LONG STRIDE;So;0;ON; 5EF4;;;;N;;;;; 2F36;KANGXI RADICAL TWO HANDS;So;0;ON; 5EFE;;;;N;;;;; 2F37;KANGXI RADICAL SHOOT;So;0;ON; 5F0B;;;;N;;;;; 2F38;KANGXI RADICAL BOW;So;0;ON; 5F13;;;;N;;;;; 2F39;KANGXI RADICAL SNOUT;So;0;ON; 5F50;;;;N;;;;; 2F3A;KANGXI RADICAL BRISTLE;So;0;ON; 5F61;;;;N;;;;; 2F3B;KANGXI RADICAL STEP;So;0;ON; 5F73;;;;N;;;;; 2F3C;KANGXI RADICAL HEART;So;0;ON; 5FC3;;;;N;;;;; 2F3D;KANGXI RADICAL HALBERD;So;0;ON; 6208;;;;N;;;;; 2F3E;KANGXI RADICAL DOOR;So;0;ON; 6236;;;;N;;;;; 2F3F;KANGXI RADICAL HAND;So;0;ON; 624B;;;;N;;;;; 2F40;KANGXI RADICAL BRANCH;So;0;ON; 652F;;;;N;;;;; 2F41;KANGXI RADICAL RAP;So;0;ON; 6534;;;;N;;;;; 2F42;KANGXI RADICAL SCRIPT;So;0;ON; 6587;;;;N;;;;; 2F43;KANGXI RADICAL DIPPER;So;0;ON; 6597;;;;N;;;;; 2F44;KANGXI RADICAL AXE;So;0;ON; 65A4;;;;N;;;;; 2F45;KANGXI RADICAL SQUARE;So;0;ON; 65B9;;;;N;;;;; 2F46;KANGXI RADICAL NOT;So;0;ON; 65E0;;;;N;;;;; 2F47;KANGXI RADICAL SUN;So;0;ON; 65E5;;;;N;;;;; 2F48;KANGXI RADICAL SAY;So;0;ON; 66F0;;;;N;;;;; 2F49;KANGXI RADICAL MOON;So;0;ON; 6708;;;;N;;;;; 2F4A;KANGXI RADICAL TREE;So;0;ON; 6728;;;;N;;;;; 2F4B;KANGXI RADICAL LACK;So;0;ON; 6B20;;;;N;;;;; 2F4C;KANGXI RADICAL STOP;So;0;ON; 6B62;;;;N;;;;; 2F4D;KANGXI RADICAL DEATH;So;0;ON; 6B79;;;;N;;;;; 2F4E;KANGXI RADICAL WEAPON;So;0;ON; 6BB3;;;;N;;;;; 2F4F;KANGXI RADICAL DO NOT;So;0;ON; 6BCB;;;;N;;;;; 2F50;KANGXI RADICAL COMPARE;So;0;ON; 6BD4;;;;N;;;;; 2F51;KANGXI RADICAL FUR;So;0;ON; 6BDB;;;;N;;;;; 2F52;KANGXI RADICAL CLAN;So;0;ON; 6C0F;;;;N;;;;; 2F53;KANGXI RADICAL STEAM;So;0;ON; 6C14;;;;N;;;;; 2F54;KANGXI RADICAL WATER;So;0;ON; 6C34;;;;N;;;;; 2F55;KANGXI RADICAL FIRE;So;0;ON; 706B;;;;N;;;;; 2F56;KANGXI RADICAL CLAW;So;0;ON; 722A;;;;N;;;;; 2F57;KANGXI RADICAL FATHER;So;0;ON; 7236;;;;N;;;;; 2F58;KANGXI RADICAL DOUBLE X;So;0;ON; 723B;;;;N;;;;; 2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON; 723F;;;;N;;;;; 2F5A;KANGXI RADICAL SLICE;So;0;ON; 7247;;;;N;;;;; 2F5B;KANGXI RADICAL FANG;So;0;ON; 7259;;;;N;;;;; 2F5C;KANGXI RADICAL COW;So;0;ON; 725B;;;;N;;;;; 2F5D;KANGXI RADICAL DOG;So;0;ON; 72AC;;;;N;;;;; 2F5E;KANGXI RADICAL PROFOUND;So;0;ON; 7384;;;;N;;;;; 2F5F;KANGXI RADICAL JADE;So;0;ON; 7389;;;;N;;;;; 2F60;KANGXI RADICAL MELON;So;0;ON; 74DC;;;;N;;;;; 2F61;KANGXI RADICAL TILE;So;0;ON; 74E6;;;;N;;;;; 2F62;KANGXI RADICAL SWEET;So;0;ON; 7518;;;;N;;;;; 2F63;KANGXI RADICAL LIFE;So;0;ON; 751F;;;;N;;;;; 2F64;KANGXI RADICAL USE;So;0;ON; 7528;;;;N;;;;; 2F65;KANGXI RADICAL FIELD;So;0;ON; 7530;;;;N;;;;; 2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON; 758B;;;;N;;;;; 2F67;KANGXI RADICAL SICKNESS;So;0;ON; 7592;;;;N;;;;; 2F68;KANGXI RADICAL DOTTED TENT;So;0;ON; 7676;;;;N;;;;; 2F69;KANGXI RADICAL WHITE;So;0;ON; 767D;;;;N;;;;; 2F6A;KANGXI RADICAL SKIN;So;0;ON; 76AE;;;;N;;;;; 2F6B;KANGXI RADICAL DISH;So;0;ON; 76BF;;;;N;;;;; 2F6C;KANGXI RADICAL EYE;So;0;ON; 76EE;;;;N;;;;; 2F6D;KANGXI RADICAL SPEAR;So;0;ON; 77DB;;;;N;;;;; 2F6E;KANGXI RADICAL ARROW;So;0;ON; 77E2;;;;N;;;;; 2F6F;KANGXI RADICAL STONE;So;0;ON; 77F3;;;;N;;;;; 2F70;KANGXI RADICAL SPIRIT;So;0;ON; 793A;;;;N;;;;; 2F71;KANGXI RADICAL TRACK;So;0;ON; 79B8;;;;N;;;;; 2F72;KANGXI RADICAL GRAIN;So;0;ON; 79BE;;;;N;;;;; 2F73;KANGXI RADICAL CAVE;So;0;ON; 7A74;;;;N;;;;; 2F74;KANGXI RADICAL STAND;So;0;ON; 7ACB;;;;N;;;;; 2F75;KANGXI RADICAL BAMBOO;So;0;ON; 7AF9;;;;N;;;;; 2F76;KANGXI RADICAL RICE;So;0;ON; 7C73;;;;N;;;;; 2F77;KANGXI RADICAL SILK;So;0;ON; 7CF8;;;;N;;;;; 2F78;KANGXI RADICAL JAR;So;0;ON; 7F36;;;;N;;;;; 2F79;KANGXI RADICAL NET;So;0;ON; 7F51;;;;N;;;;; 2F7A;KANGXI RADICAL SHEEP;So;0;ON; 7F8A;;;;N;;;;; 2F7B;KANGXI RADICAL FEATHER;So;0;ON; 7FBD;;;;N;;;;; 2F7C;KANGXI RADICAL OLD;So;0;ON; 8001;;;;N;;;;; 2F7D;KANGXI RADICAL AND;So;0;ON; 800C;;;;N;;;;; 2F7E;KANGXI RADICAL PLOW;So;0;ON; 8012;;;;N;;;;; 2F7F;KANGXI RADICAL EAR;So;0;ON; 8033;;;;N;;;;; 2F80;KANGXI RADICAL BRUSH;So;0;ON; 807F;;;;N;;;;; 2F81;KANGXI RADICAL MEAT;So;0;ON; 8089;;;;N;;;;; 2F82;KANGXI RADICAL MINISTER;So;0;ON; 81E3;;;;N;;;;; 2F83;KANGXI RADICAL SELF;So;0;ON; 81EA;;;;N;;;;; 2F84;KANGXI RADICAL ARRIVE;So;0;ON; 81F3;;;;N;;;;; 2F85;KANGXI RADICAL MORTAR;So;0;ON; 81FC;;;;N;;;;; 2F86;KANGXI RADICAL TONGUE;So;0;ON; 820C;;;;N;;;;; 2F87;KANGXI RADICAL OPPOSE;So;0;ON; 821B;;;;N;;;;; 2F88;KANGXI RADICAL BOAT;So;0;ON; 821F;;;;N;;;;; 2F89;KANGXI RADICAL STOPPING;So;0;ON; 826E;;;;N;;;;; 2F8A;KANGXI RADICAL COLOR;So;0;ON; 8272;;;;N;;;;; 2F8B;KANGXI RADICAL GRASS;So;0;ON; 8278;;;;N;;;;; 2F8C;KANGXI RADICAL TIGER;So;0;ON; 864D;;;;N;;;;; 2F8D;KANGXI RADICAL INSECT;So;0;ON; 866B;;;;N;;;;; 2F8E;KANGXI RADICAL BLOOD;So;0;ON; 8840;;;;N;;;;; 2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON; 884C;;;;N;;;;; 2F90;KANGXI RADICAL CLOTHES;So;0;ON; 8863;;;;N;;;;; 2F91;KANGXI RADICAL WEST;So;0;ON; 897E;;;;N;;;;; 2F92;KANGXI RADICAL SEE;So;0;ON; 898B;;;;N;;;;; 2F93;KANGXI RADICAL HORN;So;0;ON; 89D2;;;;N;;;;; 2F94;KANGXI RADICAL SPEECH;So;0;ON; 8A00;;;;N;;;;; 2F95;KANGXI RADICAL VALLEY;So;0;ON; 8C37;;;;N;;;;; 2F96;KANGXI RADICAL BEAN;So;0;ON; 8C46;;;;N;;;;; 2F97;KANGXI RADICAL PIG;So;0;ON; 8C55;;;;N;;;;; 2F98;KANGXI RADICAL BADGER;So;0;ON; 8C78;;;;N;;;;; 2F99;KANGXI RADICAL SHELL;So;0;ON; 8C9D;;;;N;;;;; 2F9A;KANGXI RADICAL RED;So;0;ON; 8D64;;;;N;;;;; 2F9B;KANGXI RADICAL RUN;So;0;ON; 8D70;;;;N;;;;; 2F9C;KANGXI RADICAL FOOT;So;0;ON; 8DB3;;;;N;;;;; 2F9D;KANGXI RADICAL BODY;So;0;ON; 8EAB;;;;N;;;;; 2F9E;KANGXI RADICAL CART;So;0;ON; 8ECA;;;;N;;;;; 2F9F;KANGXI RADICAL BITTER;So;0;ON; 8F9B;;;;N;;;;; 2FA0;KANGXI RADICAL MORNING;So;0;ON; 8FB0;;;;N;;;;; 2FA1;KANGXI RADICAL WALK;So;0;ON; 8FB5;;;;N;;;;; 2FA2;KANGXI RADICAL CITY;So;0;ON; 9091;;;;N;;;;; 2FA3;KANGXI RADICAL WINE;So;0;ON; 9149;;;;N;;;;; 2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON; 91C6;;;;N;;;;; 2FA5;KANGXI RADICAL VILLAGE;So;0;ON; 91CC;;;;N;;;;; 2FA6;KANGXI RADICAL GOLD;So;0;ON; 91D1;;;;N;;;;; 2FA7;KANGXI RADICAL LONG;So;0;ON; 9577;;;;N;;;;; 2FA8;KANGXI RADICAL GATE;So;0;ON; 9580;;;;N;;;;; 2FA9;KANGXI RADICAL MOUND;So;0;ON; 961C;;;;N;;;;; 2FAA;KANGXI RADICAL SLAVE;So;0;ON; 96B6;;;;N;;;;; 2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON; 96B9;;;;N;;;;; 2FAC;KANGXI RADICAL RAIN;So;0;ON; 96E8;;;;N;;;;; 2FAD;KANGXI RADICAL BLUE;So;0;ON; 9751;;;;N;;;;; 2FAE;KANGXI RADICAL WRONG;So;0;ON; 975E;;;;N;;;;; 2FAF;KANGXI RADICAL FACE;So;0;ON; 9762;;;;N;;;;; 2FB0;KANGXI RADICAL LEATHER;So;0;ON; 9769;;;;N;;;;; 2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON; 97CB;;;;N;;;;; 2FB2;KANGXI RADICAL LEEK;So;0;ON; 97ED;;;;N;;;;; 2FB3;KANGXI RADICAL SOUND;So;0;ON; 97F3;;;;N;;;;; 2FB4;KANGXI RADICAL LEAF;So;0;ON; 9801;;;;N;;;;; 2FB5;KANGXI RADICAL WIND;So;0;ON; 98A8;;;;N;;;;; 2FB6;KANGXI RADICAL FLY;So;0;ON; 98DB;;;;N;;;;; 2FB7;KANGXI RADICAL EAT;So;0;ON; 98DF;;;;N;;;;; 2FB8;KANGXI RADICAL HEAD;So;0;ON; 9996;;;;N;;;;; 2FB9;KANGXI RADICAL FRAGRANT;So;0;ON; 9999;;;;N;;;;; 2FBA;KANGXI RADICAL HORSE;So;0;ON; 99AC;;;;N;;;;; 2FBB;KANGXI RADICAL BONE;So;0;ON; 9AA8;;;;N;;;;; 2FBC;KANGXI RADICAL TALL;So;0;ON; 9AD8;;;;N;;;;; 2FBD;KANGXI RADICAL HAIR;So;0;ON; 9ADF;;;;N;;;;; 2FBE;KANGXI RADICAL FIGHT;So;0;ON; 9B25;;;;N;;;;; 2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON; 9B2F;;;;N;;;;; 2FC0;KANGXI RADICAL CAULDRON;So;0;ON; 9B32;;;;N;;;;; 2FC1;KANGXI RADICAL GHOST;So;0;ON; 9B3C;;;;N;;;;; 2FC2;KANGXI RADICAL FISH;So;0;ON; 9B5A;;;;N;;;;; 2FC3;KANGXI RADICAL BIRD;So;0;ON; 9CE5;;;;N;;;;; 2FC4;KANGXI RADICAL SALT;So;0;ON; 9E75;;;;N;;;;; 2FC5;KANGXI RADICAL DEER;So;0;ON; 9E7F;;;;N;;;;; 2FC6;KANGXI RADICAL WHEAT;So;0;ON; 9EA5;;;;N;;;;; 2FC7;KANGXI RADICAL HEMP;So;0;ON; 9EBB;;;;N;;;;; 2FC8;KANGXI RADICAL YELLOW;So;0;ON; 9EC3;;;;N;;;;; 2FC9;KANGXI RADICAL MILLET;So;0;ON; 9ECD;;;;N;;;;; 2FCA;KANGXI RADICAL BLACK;So;0;ON; 9ED1;;;;N;;;;; 2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON; 9EF9;;;;N;;;;; 2FCC;KANGXI RADICAL FROG;So;0;ON; 9EFD;;;;N;;;;; 2FCD;KANGXI RADICAL TRIPOD;So;0;ON; 9F0E;;;;N;;;;; 2FCE;KANGXI RADICAL DRUM;So;0;ON; 9F13;;;;N;;;;; 2FCF;KANGXI RADICAL RAT;So;0;ON; 9F20;;;;N;;;;; 2FD0;KANGXI RADICAL NOSE;So;0;ON; 9F3B;;;;N;;;;; 2FD1;KANGXI RADICAL EVEN;So;0;ON; 9F4A;;;;N;;;;; 2FD2;KANGXI RADICAL TOOTH;So;0;ON; 9F52;;;;N;;;;; 2FD3;KANGXI RADICAL DRAGON;So;0;ON; 9F8D;;;;N;;;;; 2FD4;KANGXI RADICAL TURTLE;So;0;ON; 9F9C;;;;N;;;;; 2FD5;KANGXI RADICAL FLUTE;So;0;ON; 9FA0;;;;N;;;;; 2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; 2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; 2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; 2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; 2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; 2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; 2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; 2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; 2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; 2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; 2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; 2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; 3000;IDEOGRAPHIC SPACE;Zs;0;WS; 0020;;;;N;;;;; 3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; 3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; 3003;DITTO MARK;Po;0;ON;;;;;N;;;;; 3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; 3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; 3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; 3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; 3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; 300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; 300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; 300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; 300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; 300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; 300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; 3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; 3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; 3012;POSTAL MARK;So;0;ON;;;;;N;;;;; 3013;GETA MARK;So;0;ON;;;;;N;;;;; 3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; 3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; 3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; 3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; 3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; 3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; 301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; 301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; 301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; 301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; 3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; 3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; 3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; 3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; 3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; 3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; 3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; 3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; 3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; 302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; 302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; 302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; 302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; 302E;HANGUL SINGLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;; 302F;HANGUL DOUBLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;; 3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; 3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; 3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; 3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; 3036;CIRCLED POSTAL MARK;So;0;ON; 3012;;;;N;;;;; 3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; 3038;HANGZHOU NUMERAL TEN;Nl;0;L; 5341;;;10;N;;;;; 3039;HANGZHOU NUMERAL TWENTY;Nl;0;L; 5344;;;20;N;;;;; 303A;HANGZHOU NUMERAL THIRTY;Nl;0;L; 5345;;;30;N;;;;; 303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 303C;MASU MARK;Lo;0;L;;;;;N;;;;; 303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; 303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; 303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; 3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; 3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; 3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; 3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; 3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; 304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; 304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; 304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; 304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; 304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; 3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; 3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; 3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; 3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; 3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; 3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; 3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; 3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; 3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; 3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; 305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; 305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; 305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; 305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; 305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; 305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; 3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; 3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; 3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; 3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; 3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; 3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; 3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; 3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; 3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; 306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; 306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; 306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; 306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; 306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; 306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; 3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; 3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; 3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; 3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; 3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; 3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; 3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; 3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; 3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; 3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; 307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; 307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; 307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; 307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; 307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; 307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; 3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; 3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; 3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; 3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; 3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; 3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; 3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; 308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; 308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; 308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; 308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; 308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; 3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; 3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; 3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; 3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; 3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; 3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; 309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; 309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON; 0020 3099;;;;N;;;;; 309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON; 0020 309A;;;;N;;;;; 309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; 309F;HIRAGANA DIGRAPH YORI;Lo;0;L; 3088 308A;;;;N;;;;; 30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; 30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; 30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; 30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; 30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; 30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; 30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; 30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; 30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; 30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; 30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; 30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; 30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; 30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; 30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; 30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; 30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; 30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; 30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; 30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; 30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; 30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; 30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; 30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; 30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; 30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; 30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; 30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; 30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; 30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; 30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; 30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; 30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; 30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; 30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; 30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; 30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; 30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; 30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; 30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; 30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; 30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; 30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; 30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; 30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; 30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; 30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; 30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; 30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; 30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; 30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; 30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; 30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; 30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; 30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; 30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; 30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; 30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; 30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; 30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; 30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; 30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; 30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; 30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; 30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; 30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; 30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; 30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; 30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; 30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; 30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; 30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; 30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; 30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; 30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; 30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; 30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; 30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; 30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;; 30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; 30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; 30FF;KATAKANA DIGRAPH KOTO;Lo;0;L; 30B3 30C8;;;;N;;;;; 3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; 3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; 3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; 3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; 3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; 310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; 310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; 310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; 310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; 310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; 310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; 3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; 3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; 3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; 3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; 3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; 3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; 3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; 3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; 3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; 3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; 311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; 311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; 311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; 311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; 311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; 311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; 3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; 3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; 3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; 3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; 3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; 3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; 3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; 3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; 3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; 3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; 312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L; 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L; 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; 3134;HANGUL LETTER NIEUN;Lo;0;L; 1102;;;;N;;;;; 3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; 3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; 3137;HANGUL LETTER TIKEUT;Lo;0;L; 1103;;;;N;HANGUL LETTER DIGEUD;;;; 3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L; 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; 3139;HANGUL LETTER RIEUL;Lo;0;L; 1105;;;;N;HANGUL LETTER LIEUL;;;; 313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; 313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; 313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; 313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L; 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; 313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; 313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; 3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; 3141;HANGUL LETTER MIEUM;Lo;0;L; 1106;;;;N;;;;; 3142;HANGUL LETTER PIEUP;Lo;0;L; 1107;;;;N;HANGUL LETTER BIEUB;;;; 3143;HANGUL LETTER SSANGPIEUP;Lo;0;L; 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; 3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L; 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; 3145;HANGUL LETTER SIOS;Lo;0;L; 1109;;;;N;;;;; 3146;HANGUL LETTER SSANGSIOS;Lo;0;L; 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; 3147;HANGUL LETTER IEUNG;Lo;0;L; 110B;;;;N;;;;; 3148;HANGUL LETTER CIEUC;Lo;0;L; 110C;;;;N;HANGUL LETTER JIEUJ;;;; 3149;HANGUL LETTER SSANGCIEUC;Lo;0;L; 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; 314A;HANGUL LETTER CHIEUCH;Lo;0;L; 110E;;;;N;HANGUL LETTER CIEUC;;;; 314B;HANGUL LETTER KHIEUKH;Lo;0;L; 110F;;;;N;HANGUL LETTER KIYEOK;;;; 314C;HANGUL LETTER THIEUTH;Lo;0;L; 1110;;;;N;HANGUL LETTER TIEUT;;;; 314D;HANGUL LETTER PHIEUPH;Lo;0;L; 1111;;;;N;HANGUL LETTER PIEUP;;;; 314E;HANGUL LETTER HIEUH;Lo;0;L; 1112;;;;N;;;;; 314F;HANGUL LETTER A;Lo;0;L; 1161;;;;N;;;;; 3150;HANGUL LETTER AE;Lo;0;L; 1162;;;;N;;;;; 3151;HANGUL LETTER YA;Lo;0;L; 1163;;;;N;;;;; 3152;HANGUL LETTER YAE;Lo;0;L; 1164;;;;N;;;;; 3153;HANGUL LETTER EO;Lo;0;L; 1165;;;;N;;;;; 3154;HANGUL LETTER E;Lo;0;L; 1166;;;;N;;;;; 3155;HANGUL LETTER YEO;Lo;0;L; 1167;;;;N;;;;; 3156;HANGUL LETTER YE;Lo;0;L; 1168;;;;N;;;;; 3157;HANGUL LETTER O;Lo;0;L; 1169;;;;N;;;;; 3158;HANGUL LETTER WA;Lo;0;L; 116A;;;;N;;;;; 3159;HANGUL LETTER WAE;Lo;0;L; 116B;;;;N;;;;; 315A;HANGUL LETTER OE;Lo;0;L; 116C;;;;N;;;;; 315B;HANGUL LETTER YO;Lo;0;L; 116D;;;;N;;;;; 315C;HANGUL LETTER U;Lo;0;L; 116E;;;;N;;;;; 315D;HANGUL LETTER WEO;Lo;0;L; 116F;;;;N;;;;; 315E;HANGUL LETTER WE;Lo;0;L; 1170;;;;N;;;;; 315F;HANGUL LETTER WI;Lo;0;L; 1171;;;;N;;;;; 3160;HANGUL LETTER YU;Lo;0;L; 1172;;;;N;;;;; 3161;HANGUL LETTER EU;Lo;0;L; 1173;;;;N;;;;; 3162;HANGUL LETTER YI;Lo;0;L; 1174;;;;N;;;;; 3163;HANGUL LETTER I;Lo;0;L; 1175;;;;N;;;;; 3164;HANGUL FILLER;Lo;0;L; 1160;;;;N;HANGUL CAE OM;;;; 3165;HANGUL LETTER SSANGNIEUN;Lo;0;L; 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; 3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L; 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; 3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L; 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; 3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L; 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; 3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L; 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; 316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L; 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; 316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L; 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; 316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L; 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; 316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L; 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; 316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L; 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; 316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L; 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; 3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L; 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; 3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L; 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; 3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L; 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; 3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L; 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; 3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L; 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; 3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L; 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; 3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L; 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; 3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L; 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; 3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L; 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; 3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L; 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; 317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L; 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; 317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L; 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; 317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L; 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; 317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L; 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; 317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L; 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; 317F;HANGUL LETTER PANSIOS;Lo;0;L; 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; 3180;HANGUL LETTER SSANGIEUNG;Lo;0;L; 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; 3181;HANGUL LETTER YESIEUNG;Lo;0;L; 114C;;;;N;HANGUL LETTER NGIEUNG;;;; 3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L; 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; 3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L; 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; 3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L; 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; 3185;HANGUL LETTER SSANGHIEUH;Lo;0;L; 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; 3186;HANGUL LETTER YEORINHIEUH;Lo;0;L; 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; 3187;HANGUL LETTER YO-YA;Lo;0;L; 1184;;;;N;HANGUL LETTER YOYA;;;; 3188;HANGUL LETTER YO-YAE;Lo;0;L; 1185;;;;N;HANGUL LETTER YOYAE;;;; 3189;HANGUL LETTER YO-I;Lo;0;L; 1188;;;;N;HANGUL LETTER YOI;;;; 318A;HANGUL LETTER YU-YEO;Lo;0;L; 1191;;;;N;HANGUL LETTER YUYEO;;;; 318B;HANGUL LETTER YU-YE;Lo;0;L; 1192;;;;N;HANGUL LETTER YUYE;;;; 318C;HANGUL LETTER YU-I;Lo;0;L; 1194;;;;N;HANGUL LETTER YUI;;;; 318D;HANGUL LETTER ARAEA;Lo;0;L; 119E;;;;N;HANGUL LETTER ALAE A;;;; 318E;HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; 3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;; 3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;; 3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L; 4E00;;;1;N;KAERITEN ITI;;;; 3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L; 4E8C;;;2;N;KAERITEN NI;;;; 3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L; 4E09;;;3;N;KAERITEN SAN;;;; 3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L; 56DB;;;4;N;KAERITEN SI;;;; 3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L; 4E0A;;;;N;KAERITEN ZYOU;;;; 3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L; 4E2D;;;;N;KAERITEN TYUU;;;; 3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L; 4E0B;;;;N;KAERITEN GE;;;; 3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L; 7532;;;;N;KAERITEN KOU;;;; 319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L; 4E59;;;;N;KAERITEN OTU;;;; 319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L; 4E19;;;;N;KAERITEN HEI;;;; 319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L; 4E01;;;;N;KAERITEN TEI;;;; 319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L; 5929;;;;N;KAERITEN TEN;;;; 319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L; 5730;;;;N;KAERITEN TI;;;; 319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L; 4EBA;;;;N;KAERITEN ZIN;;;; 31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; 31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; 31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; 31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; 31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; 31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; 31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; 31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; 31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; 31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; 31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; 31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; 31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; 31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; 31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; 31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; 31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; 31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; 31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; 31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; 31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; 31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; 31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; 31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; 31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; 31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; 31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; 31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;; 31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;; 31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;; 31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;; 31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;; 31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;; 31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;; 31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;; 31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;; 31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;; 31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;; 31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;; 31CF;CJK STROKE N;So;0;ON;;;;;N;;;;; 31D0;CJK STROKE H;So;0;ON;;;;;N;;;;; 31D1;CJK STROKE S;So;0;ON;;;;;N;;;;; 31D2;CJK STROKE P;So;0;ON;;;;;N;;;;; 31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;; 31D4;CJK STROKE D;So;0;ON;;;;;N;;;;; 31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;; 31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;; 31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;; 31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;; 31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;; 31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;; 31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;; 31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;; 31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;; 31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;; 31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;; 31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;; 31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;; 31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;; 31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;; 31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; 31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; 31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; 31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; 31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; 31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; 31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; 31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; 31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; 31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; 31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; 31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; 31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; 31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; 31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; 31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; 3200;PARENTHESIZED HANGUL KIYEOK;So;0;L; 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; 3201;PARENTHESIZED HANGUL NIEUN;So;0;L; 0028 1102 0029;;;;N;;;;; 3202;PARENTHESIZED HANGUL TIKEUT;So;0;L; 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; 3203;PARENTHESIZED HANGUL RIEUL;So;0;L; 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; 3204;PARENTHESIZED HANGUL MIEUM;So;0;L; 0028 1106 0029;;;;N;;;;; 3205;PARENTHESIZED HANGUL PIEUP;So;0;L; 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; 3206;PARENTHESIZED HANGUL SIOS;So;0;L; 0028 1109 0029;;;;N;;;;; 3207;PARENTHESIZED HANGUL IEUNG;So;0;L; 0028 110B 0029;;;;N;;;;; 3208;PARENTHESIZED HANGUL CIEUC;So;0;L; 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; 3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L; 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; 320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L; 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; 320B;PARENTHESIZED HANGUL THIEUTH;So;0;L; 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; 320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L; 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; 320D;PARENTHESIZED HANGUL HIEUH;So;0;L; 0028 1112 0029;;;;N;;;;; 320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L; 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; 320F;PARENTHESIZED HANGUL NIEUN A;So;0;L; 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; 3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L; 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; 3211;PARENTHESIZED HANGUL RIEUL A;So;0;L; 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; 3212;PARENTHESIZED HANGUL MIEUM A;So;0;L; 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; 3213;PARENTHESIZED HANGUL PIEUP A;So;0;L; 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; 3214;PARENTHESIZED HANGUL SIOS A;So;0;L; 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; 3215;PARENTHESIZED HANGUL IEUNG A;So;0;L; 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; 3216;PARENTHESIZED HANGUL CIEUC A;So;0;L; 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; 3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L; 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; 3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L; 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; 3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L; 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; 321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L; 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; 321B;PARENTHESIZED HANGUL HIEUH A;So;0;L; 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; 321C;PARENTHESIZED HANGUL CIEUC U;So;0;L; 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; 321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON; 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;; 321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON; 0028 110B 1169 1112 116E 0029;;;;N;;;;; 3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L; 0028 4E00 0029;;;1;N;;;;; 3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L; 0028 4E8C 0029;;;2;N;;;;; 3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L; 0028 4E09 0029;;;3;N;;;;; 3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L; 0028 56DB 0029;;;4;N;;;;; 3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L; 0028 4E94 0029;;;5;N;;;;; 3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L; 0028 516D 0029;;;6;N;;;;; 3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L; 0028 4E03 0029;;;7;N;;;;; 3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L; 0028 516B 0029;;;8;N;;;;; 3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L; 0028 4E5D 0029;;;9;N;;;;; 3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L; 0028 5341 0029;;;10;N;;;;; 322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L; 0028 6708 0029;;;;N;;;;; 322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L; 0028 706B 0029;;;;N;;;;; 322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L; 0028 6C34 0029;;;;N;;;;; 322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L; 0028 6728 0029;;;;N;;;;; 322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L; 0028 91D1 0029;;;;N;;;;; 322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L; 0028 571F 0029;;;;N;;;;; 3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L; 0028 65E5 0029;;;;N;;;;; 3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L; 0028 682A 0029;;;;N;;;;; 3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L; 0028 6709 0029;;;;N;;;;; 3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L; 0028 793E 0029;;;;N;;;;; 3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L; 0028 540D 0029;;;;N;;;;; 3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L; 0028 7279 0029;;;;N;;;;; 3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L; 0028 8CA1 0029;;;;N;;;;; 3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L; 0028 795D 0029;;;;N;;;;; 3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L; 0028 52B4 0029;;;;N;;;;; 3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L; 0028 4EE3 0029;;;;N;;;;; 323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L; 0028 547C 0029;;;;N;;;;; 323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L; 0028 5B66 0029;;;;N;;;;; 323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L; 0028 76E3 0029;;;;N;;;;; 323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L; 0028 4F01 0029;;;;N;;;;; 323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L; 0028 8CC7 0029;;;;N;;;;; 323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L; 0028 5354 0029;;;;N;;;;; 3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L; 0028 796D 0029;;;;N;;;;; 3241;PARENTHESIZED IDEOGRAPH REST;So;0;L; 0028 4F11 0029;;;;N;;;;; 3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L; 0028 81EA 0029;;;;N;;;;; 3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L; 0028 81F3 0029;;;;N;;;;; 3244;CIRCLED IDEOGRAPH QUESTION;So;0;L; 554F;;;;N;;;;; 3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L; 5E7C;;;;N;;;;; 3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L; 6587;;;;N;;;;; 3247;CIRCLED IDEOGRAPH KOTO;So;0;L; 7B8F;;;;N;;;;; 3248;CIRCLED NUMBER TEN ON BLACK SQUARE;So;0;L;;;;;N;;;;; 3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;So;0;L;;;;;N;;;;; 3250;PARTNERSHIP SIGN;So;0;ON; 0050 0054 0045;;;;N;;;;; 3251;CIRCLED NUMBER TWENTY ONE;No;0;ON; 0032 0031;;;21;N;;;;; 3252;CIRCLED NUMBER TWENTY TWO;No;0;ON; 0032 0032;;;22;N;;;;; 3253;CIRCLED NUMBER TWENTY THREE;No;0;ON; 0032 0033;;;23;N;;;;; 3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON; 0032 0034;;;24;N;;;;; 3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON; 0032 0035;;;25;N;;;;; 3256;CIRCLED NUMBER TWENTY SIX;No;0;ON; 0032 0036;;;26;N;;;;; 3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON; 0032 0037;;;27;N;;;;; 3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON; 0032 0038;;;28;N;;;;; 3259;CIRCLED NUMBER TWENTY NINE;No;0;ON; 0032 0039;;;29;N;;;;; 325A;CIRCLED NUMBER THIRTY;No;0;ON; 0033 0030;;;30;N;;;;; 325B;CIRCLED NUMBER THIRTY ONE;No;0;ON; 0033 0031;;;31;N;;;;; 325C;CIRCLED NUMBER THIRTY TWO;No;0;ON; 0033 0032;;;32;N;;;;; 325D;CIRCLED NUMBER THIRTY THREE;No;0;ON; 0033 0033;;;33;N;;;;; 325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON; 0033 0034;;;34;N;;;;; 325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON; 0033 0035;;;35;N;;;;; 3260;CIRCLED HANGUL KIYEOK;So;0;L; 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; 3261;CIRCLED HANGUL NIEUN;So;0;L; 1102;;;;N;;;;; 3262;CIRCLED HANGUL TIKEUT;So;0;L; 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; 3263;CIRCLED HANGUL RIEUL;So;0;L; 1105;;;;N;CIRCLED HANGUL LIEUL;;;; 3264;CIRCLED HANGUL MIEUM;So;0;L; 1106;;;;N;;;;; 3265;CIRCLED HANGUL PIEUP;So;0;L; 1107;;;;N;CIRCLED HANGUL BIEUB;;;; 3266;CIRCLED HANGUL SIOS;So;0;L; 1109;;;;N;;;;; 3267;CIRCLED HANGUL IEUNG;So;0;L; 110B;;;;N;;;;; 3268;CIRCLED HANGUL CIEUC;So;0;L; 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; 3269;CIRCLED HANGUL CHIEUCH;So;0;L; 110E;;;;N;CIRCLED HANGUL CIEUC;;;; 326A;CIRCLED HANGUL KHIEUKH;So;0;L; 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; 326B;CIRCLED HANGUL THIEUTH;So;0;L; 1110;;;;N;CIRCLED HANGUL TIEUT;;;; 326C;CIRCLED HANGUL PHIEUPH;So;0;L; 1111;;;;N;CIRCLED HANGUL PIEUP;;;; 326D;CIRCLED HANGUL HIEUH;So;0;L; 1112;;;;N;;;;; 326E;CIRCLED HANGUL KIYEOK A;So;0;L; 1100 1161;;;;N;CIRCLED HANGUL GA;;;; 326F;CIRCLED HANGUL NIEUN A;So;0;L; 1102 1161;;;;N;CIRCLED HANGUL NA;;;; 3270;CIRCLED HANGUL TIKEUT A;So;0;L; 1103 1161;;;;N;CIRCLED HANGUL DA;;;; 3271;CIRCLED HANGUL RIEUL A;So;0;L; 1105 1161;;;;N;CIRCLED HANGUL LA;;;; 3272;CIRCLED HANGUL MIEUM A;So;0;L; 1106 1161;;;;N;CIRCLED HANGUL MA;;;; 3273;CIRCLED HANGUL PIEUP A;So;0;L; 1107 1161;;;;N;CIRCLED HANGUL BA;;;; 3274;CIRCLED HANGUL SIOS A;So;0;L; 1109 1161;;;;N;CIRCLED HANGUL SA;;;; 3275;CIRCLED HANGUL IEUNG A;So;0;L; 110B 1161;;;;N;CIRCLED HANGUL A;;;; 3276;CIRCLED HANGUL CIEUC A;So;0;L; 110C 1161;;;;N;CIRCLED HANGUL JA;;;; 3277;CIRCLED HANGUL CHIEUCH A;So;0;L; 110E 1161;;;;N;CIRCLED HANGUL CA;;;; 3278;CIRCLED HANGUL KHIEUKH A;So;0;L; 110F 1161;;;;N;CIRCLED HANGUL KA;;;; 3279;CIRCLED HANGUL THIEUTH A;So;0;L; 1110 1161;;;;N;CIRCLED HANGUL TA;;;; 327A;CIRCLED HANGUL PHIEUPH A;So;0;L; 1111 1161;;;;N;CIRCLED HANGUL PA;;;; 327B;CIRCLED HANGUL HIEUH A;So;0;L; 1112 1161;;;;N;CIRCLED HANGUL HA;;;; 327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON; 110E 1161 11B7 1100 1169;;;;N;;;;; 327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON; 110C 116E 110B 1174;;;;N;;;;; 327E;CIRCLED HANGUL IEUNG U;So;0;ON; 110B 116E;;;;N;;;;; 327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; 3280;CIRCLED IDEOGRAPH ONE;No;0;L; 4E00;;;1;N;;;;; 3281;CIRCLED IDEOGRAPH TWO;No;0;L; 4E8C;;;2;N;;;;; 3282;CIRCLED IDEOGRAPH THREE;No;0;L; 4E09;;;3;N;;;;; 3283;CIRCLED IDEOGRAPH FOUR;No;0;L; 56DB;;;4;N;;;;; 3284;CIRCLED IDEOGRAPH FIVE;No;0;L; 4E94;;;5;N;;;;; 3285;CIRCLED IDEOGRAPH SIX;No;0;L; 516D;;;6;N;;;;; 3286;CIRCLED IDEOGRAPH SEVEN;No;0;L; 4E03;;;7;N;;;;; 3287;CIRCLED IDEOGRAPH EIGHT;No;0;L; 516B;;;8;N;;;;; 3288;CIRCLED IDEOGRAPH NINE;No;0;L; 4E5D;;;9;N;;;;; 3289;CIRCLED IDEOGRAPH TEN;No;0;L; 5341;;;10;N;;;;; 328A;CIRCLED IDEOGRAPH MOON;So;0;L; 6708;;;;N;;;;; 328B;CIRCLED IDEOGRAPH FIRE;So;0;L; 706B;;;;N;;;;; 328C;CIRCLED IDEOGRAPH WATER;So;0;L; 6C34;;;;N;;;;; 328D;CIRCLED IDEOGRAPH WOOD;So;0;L; 6728;;;;N;;;;; 328E;CIRCLED IDEOGRAPH METAL;So;0;L; 91D1;;;;N;;;;; 328F;CIRCLED IDEOGRAPH EARTH;So;0;L; 571F;;;;N;;;;; 3290;CIRCLED IDEOGRAPH SUN;So;0;L; 65E5;;;;N;;;;; 3291;CIRCLED IDEOGRAPH STOCK;So;0;L; 682A;;;;N;;;;; 3292;CIRCLED IDEOGRAPH HAVE;So;0;L; 6709;;;;N;;;;; 3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L; 793E;;;;N;;;;; 3294;CIRCLED IDEOGRAPH NAME;So;0;L; 540D;;;;N;;;;; 3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L; 7279;;;;N;;;;; 3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L; 8CA1;;;;N;;;;; 3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L; 795D;;;;N;;;;; 3298;CIRCLED IDEOGRAPH LABOR;So;0;L; 52B4;;;;N;;;;; 3299;CIRCLED IDEOGRAPH SECRET;So;0;L; 79D8;;;;N;;;;; 329A;CIRCLED IDEOGRAPH MALE;So;0;L; 7537;;;;N;;;;; 329B;CIRCLED IDEOGRAPH FEMALE;So;0;L; 5973;;;;N;;;;; 329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L; 9069;;;;N;;;;; 329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L; 512A;;;;N;;;;; 329E;CIRCLED IDEOGRAPH PRINT;So;0;L; 5370;;;;N;;;;; 329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L; 6CE8;;;;N;;;;; 32A0;CIRCLED IDEOGRAPH ITEM;So;0;L; 9805;;;;N;;;;; 32A1;CIRCLED IDEOGRAPH REST;So;0;L; 4F11;;;;N;;;;; 32A2;CIRCLED IDEOGRAPH COPY;So;0;L; 5199;;;;N;;;;; 32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L; 6B63;;;;N;;;;; 32A4;CIRCLED IDEOGRAPH HIGH;So;0;L; 4E0A;;;;N;;;;; 32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L; 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; 32A6;CIRCLED IDEOGRAPH LOW;So;0;L; 4E0B;;;;N;;;;; 32A7;CIRCLED IDEOGRAPH LEFT;So;0;L; 5DE6;;;;N;;;;; 32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L; 53F3;;;;N;;;;; 32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L; 533B;;;;N;;;;; 32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L; 5B97;;;;N;;;;; 32AB;CIRCLED IDEOGRAPH STUDY;So;0;L; 5B66;;;;N;;;;; 32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L; 76E3;;;;N;;;;; 32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L; 4F01;;;;N;;;;; 32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L; 8CC7;;;;N;;;;; 32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L; 5354;;;;N;;;;; 32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L; 591C;;;;N;;;;; 32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON; 0033 0036;;;36;N;;;;; 32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON; 0033 0037;;;37;N;;;;; 32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON; 0033 0038;;;38;N;;;;; 32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON; 0033 0039;;;39;N;;;;; 32B5;CIRCLED NUMBER FORTY;No;0;ON; 0034 0030;;;40;N;;;;; 32B6;CIRCLED NUMBER FORTY ONE;No;0;ON; 0034 0031;;;41;N;;;;; 32B7;CIRCLED NUMBER FORTY TWO;No;0;ON; 0034 0032;;;42;N;;;;; 32B8;CIRCLED NUMBER FORTY THREE;No;0;ON; 0034 0033;;;43;N;;;;; 32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON; 0034 0034;;;44;N;;;;; 32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON; 0034 0035;;;45;N;;;;; 32BB;CIRCLED NUMBER FORTY SIX;No;0;ON; 0034 0036;;;46;N;;;;; 32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON; 0034 0037;;;47;N;;;;; 32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON; 0034 0038;;;48;N;;;;; 32BE;CIRCLED NUMBER FORTY NINE;No;0;ON; 0034 0039;;;49;N;;;;; 32BF;CIRCLED NUMBER FIFTY;No;0;ON; 0035 0030;;;50;N;;;;; 32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L; 0031 6708;;;;N;;;;; 32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L; 0032 6708;;;;N;;;;; 32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L; 0033 6708;;;;N;;;;; 32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L; 0034 6708;;;;N;;;;; 32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L; 0035 6708;;;;N;;;;; 32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L; 0036 6708;;;;N;;;;; 32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L; 0037 6708;;;;N;;;;; 32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L; 0038 6708;;;;N;;;;; 32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L; 0039 6708;;;;N;;;;; 32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L; 0031 0030 6708;;;;N;;;;; 32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L; 0031 0031 6708;;;;N;;;;; 32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L; 0031 0032 6708;;;;N;;;;; 32CC;SQUARE HG;So;0;ON; 0048 0067;;;;N;;;;; 32CD;SQUARE ERG;So;0;ON; 0065 0072 0067;;;;N;;;;; 32CE;SQUARE EV;So;0;ON; 0065 0056;;;;N;;;;; 32CF;LIMITED LIABILITY SIGN;So;0;ON; 004C 0054 0044;;;;N;;;;; 32D0;CIRCLED KATAKANA A;So;0;L; 30A2;;;;N;;;;; 32D1;CIRCLED KATAKANA I;So;0;L; 30A4;;;;N;;;;; 32D2;CIRCLED KATAKANA U;So;0;L; 30A6;;;;N;;;;; 32D3;CIRCLED KATAKANA E;So;0;L; 30A8;;;;N;;;;; 32D4;CIRCLED KATAKANA O;So;0;L; 30AA;;;;N;;;;; 32D5;CIRCLED KATAKANA KA;So;0;L; 30AB;;;;N;;;;; 32D6;CIRCLED KATAKANA KI;So;0;L; 30AD;;;;N;;;;; 32D7;CIRCLED KATAKANA KU;So;0;L; 30AF;;;;N;;;;; 32D8;CIRCLED KATAKANA KE;So;0;L; 30B1;;;;N;;;;; 32D9;CIRCLED KATAKANA KO;So;0;L; 30B3;;;;N;;;;; 32DA;CIRCLED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; 32DB;CIRCLED KATAKANA SI;So;0;L; 30B7;;;;N;;;;; 32DC;CIRCLED KATAKANA SU;So;0;L; 30B9;;;;N;;;;; 32DD;CIRCLED KATAKANA SE;So;0;L; 30BB;;;;N;;;;; 32DE;CIRCLED KATAKANA SO;So;0;L; 30BD;;;;N;;;;; 32DF;CIRCLED KATAKANA TA;So;0;L; 30BF;;;;N;;;;; 32E0;CIRCLED KATAKANA TI;So;0;L; 30C1;;;;N;;;;; 32E1;CIRCLED KATAKANA TU;So;0;L; 30C4;;;;N;;;;; 32E2;CIRCLED KATAKANA TE;So;0;L; 30C6;;;;N;;;;; 32E3;CIRCLED KATAKANA TO;So;0;L; 30C8;;;;N;;;;; 32E4;CIRCLED KATAKANA NA;So;0;L; 30CA;;;;N;;;;; 32E5;CIRCLED KATAKANA NI;So;0;L; 30CB;;;;N;;;;; 32E6;CIRCLED KATAKANA NU;So;0;L; 30CC;;;;N;;;;; 32E7;CIRCLED KATAKANA NE;So;0;L; 30CD;;;;N;;;;; 32E8;CIRCLED KATAKANA NO;So;0;L; 30CE;;;;N;;;;; 32E9;CIRCLED KATAKANA HA;So;0;L; 30CF;;;;N;;;;; 32EA;CIRCLED KATAKANA HI;So;0;L; 30D2;;;;N;;;;; 32EB;CIRCLED KATAKANA HU;So;0;L; 30D5;;;;N;;;;; 32EC;CIRCLED KATAKANA HE;So;0;L; 30D8;;;;N;;;;; 32ED;CIRCLED KATAKANA HO;So;0;L; 30DB;;;;N;;;;; 32EE;CIRCLED KATAKANA MA;So;0;L; 30DE;;;;N;;;;; 32EF;CIRCLED KATAKANA MI;So;0;L; 30DF;;;;N;;;;; 32F0;CIRCLED KATAKANA MU;So;0;L; 30E0;;;;N;;;;; 32F1;CIRCLED KATAKANA ME;So;0;L; 30E1;;;;N;;;;; 32F2;CIRCLED KATAKANA MO;So;0;L; 30E2;;;;N;;;;; 32F3;CIRCLED KATAKANA YA;So;0;L; 30E4;;;;N;;;;; 32F4;CIRCLED KATAKANA YU;So;0;L; 30E6;;;;N;;;;; 32F5;CIRCLED KATAKANA YO;So;0;L; 30E8;;;;N;;;;; 32F6;CIRCLED KATAKANA RA;So;0;L; 30E9;;;;N;;;;; 32F7;CIRCLED KATAKANA RI;So;0;L; 30EA;;;;N;;;;; 32F8;CIRCLED KATAKANA RU;So;0;L; 30EB;;;;N;;;;; 32F9;CIRCLED KATAKANA RE;So;0;L; 30EC;;;;N;;;;; 32FA;CIRCLED KATAKANA RO;So;0;L; 30ED;;;;N;;;;; 32FB;CIRCLED KATAKANA WA;So;0;L; 30EF;;;;N;;;;; 32FC;CIRCLED KATAKANA WI;So;0;L; 30F0;;;;N;;;;; 32FD;CIRCLED KATAKANA WE;So;0;L; 30F1;;;;N;;;;; 32FE;CIRCLED KATAKANA WO;So;0;L; 30F2;;;;N;;;;; 3300;SQUARE APAATO;So;0;L; 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; 3301;SQUARE ARUHUA;So;0;L; 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; 3302;SQUARE ANPEA;So;0;L; 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; 3303;SQUARE AARU;So;0;L; 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; 3304;SQUARE ININGU;So;0;L; 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; 3305;SQUARE INTI;So;0;L; 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; 3306;SQUARE UON;So;0;L; 30A6 30A9 30F3;;;;N;SQUARED UON;;;; 3307;SQUARE ESUKUUDO;So;0;L; 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; 3308;SQUARE EEKAA;So;0;L; 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; 3309;SQUARE ONSU;So;0;L; 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; 330A;SQUARE OOMU;So;0;L; 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; 330B;SQUARE KAIRI;So;0;L; 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; 330C;SQUARE KARATTO;So;0;L; 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; 330D;SQUARE KARORII;So;0;L; 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; 330E;SQUARE GARON;So;0;L; 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; 330F;SQUARE GANMA;So;0;L; 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; 3310;SQUARE GIGA;So;0;L; 30AE 30AC;;;;N;SQUARED GIGA;;;; 3311;SQUARE GINII;So;0;L; 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; 3312;SQUARE KYURII;So;0;L; 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; 3313;SQUARE GIRUDAA;So;0;L; 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; 3314;SQUARE KIRO;So;0;L; 30AD 30ED;;;;N;SQUARED KIRO;;;; 3315;SQUARE KIROGURAMU;So;0;L; 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; 3316;SQUARE KIROMEETORU;So;0;L; 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; 3317;SQUARE KIROWATTO;So;0;L; 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; 3318;SQUARE GURAMU;So;0;L; 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; 3319;SQUARE GURAMUTON;So;0;L; 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; 331A;SQUARE KURUZEIRO;So;0;L; 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; 331B;SQUARE KUROONE;So;0;L; 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; 331C;SQUARE KEESU;So;0;L; 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; 331D;SQUARE KORUNA;So;0;L; 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; 331E;SQUARE KOOPO;So;0;L; 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; 331F;SQUARE SAIKURU;So;0;L; 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; 3320;SQUARE SANTIIMU;So;0;L; 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; 3321;SQUARE SIRINGU;So;0;L; 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; 3322;SQUARE SENTI;So;0;L; 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; 3323;SQUARE SENTO;So;0;L; 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; 3324;SQUARE DAASU;So;0;L; 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; 3325;SQUARE DESI;So;0;L; 30C7 30B7;;;;N;SQUARED DESI;;;; 3326;SQUARE DORU;So;0;L; 30C9 30EB;;;;N;SQUARED DORU;;;; 3327;SQUARE TON;So;0;L; 30C8 30F3;;;;N;SQUARED TON;;;; 3328;SQUARE NANO;So;0;L; 30CA 30CE;;;;N;SQUARED NANO;;;; 3329;SQUARE NOTTO;So;0;L; 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; 332A;SQUARE HAITU;So;0;L; 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; 332B;SQUARE PAASENTO;So;0;L; 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; 332C;SQUARE PAATU;So;0;L; 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; 332D;SQUARE BAARERU;So;0;L; 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; 332E;SQUARE PIASUTORU;So;0;L; 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; 332F;SQUARE PIKURU;So;0;L; 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; 3330;SQUARE PIKO;So;0;L; 30D4 30B3;;;;N;SQUARED PIKO;;;; 3331;SQUARE BIRU;So;0;L; 30D3 30EB;;;;N;SQUARED BIRU;;;; 3332;SQUARE HUARADDO;So;0;L; 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; 3333;SQUARE HUIITO;So;0;L; 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; 3334;SQUARE BUSSYERU;So;0;L; 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; 3335;SQUARE HURAN;So;0;L; 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; 3336;SQUARE HEKUTAARU;So;0;L; 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; 3337;SQUARE PESO;So;0;L; 30DA 30BD;;;;N;SQUARED PESO;;;; 3338;SQUARE PENIHI;So;0;L; 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; 3339;SQUARE HERUTU;So;0;L; 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; 333A;SQUARE PENSU;So;0;L; 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; 333B;SQUARE PEEZI;So;0;L; 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; 333C;SQUARE BEETA;So;0;L; 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; 333D;SQUARE POINTO;So;0;L; 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; 333E;SQUARE BORUTO;So;0;L; 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; 333F;SQUARE HON;So;0;L; 30DB 30F3;;;;N;SQUARED HON;;;; 3340;SQUARE PONDO;So;0;L; 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; 3341;SQUARE HOORU;So;0;L; 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; 3342;SQUARE HOON;So;0;L; 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; 3343;SQUARE MAIKURO;So;0;L; 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; 3344;SQUARE MAIRU;So;0;L; 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; 3345;SQUARE MAHHA;So;0;L; 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; 3346;SQUARE MARUKU;So;0;L; 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; 3347;SQUARE MANSYON;So;0;L; 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; 3348;SQUARE MIKURON;So;0;L; 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; 3349;SQUARE MIRI;So;0;L; 30DF 30EA;;;;N;SQUARED MIRI;;;; 334A;SQUARE MIRIBAARU;So;0;L; 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; 334B;SQUARE MEGA;So;0;L; 30E1 30AC;;;;N;SQUARED MEGA;;;; 334C;SQUARE MEGATON;So;0;L; 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; 334D;SQUARE MEETORU;So;0;L; 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; 334E;SQUARE YAADO;So;0;L; 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; 334F;SQUARE YAARU;So;0;L; 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; 3350;SQUARE YUAN;So;0;L; 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; 3351;SQUARE RITTORU;So;0;L; 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; 3352;SQUARE RIRA;So;0;L; 30EA 30E9;;;;N;SQUARED RIRA;;;; 3353;SQUARE RUPII;So;0;L; 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; 3354;SQUARE RUUBURU;So;0;L; 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; 3355;SQUARE REMU;So;0;L; 30EC 30E0;;;;N;SQUARED REMU;;;; 3356;SQUARE RENTOGEN;So;0;L; 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; 3357;SQUARE WATTO;So;0;L; 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; 3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L; 0030 70B9;;;;N;;;;; 3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L; 0031 70B9;;;;N;;;;; 335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L; 0032 70B9;;;;N;;;;; 335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L; 0033 70B9;;;;N;;;;; 335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L; 0034 70B9;;;;N;;;;; 335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L; 0035 70B9;;;;N;;;;; 335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L; 0036 70B9;;;;N;;;;; 335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L; 0037 70B9;;;;N;;;;; 3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L; 0038 70B9;;;;N;;;;; 3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L; 0039 70B9;;;;N;;;;; 3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L; 0031 0030 70B9;;;;N;;;;; 3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L; 0031 0031 70B9;;;;N;;;;; 3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L; 0031 0032 70B9;;;;N;;;;; 3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L; 0031 0033 70B9;;;;N;;;;; 3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L; 0031 0034 70B9;;;;N;;;;; 3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L; 0031 0035 70B9;;;;N;;;;; 3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L; 0031 0036 70B9;;;;N;;;;; 3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L; 0031 0037 70B9;;;;N;;;;; 336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L; 0031 0038 70B9;;;;N;;;;; 336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L; 0031 0039 70B9;;;;N;;;;; 336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L; 0032 0030 70B9;;;;N;;;;; 336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L; 0032 0031 70B9;;;;N;;;;; 336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L; 0032 0032 70B9;;;;N;;;;; 336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L; 0032 0033 70B9;;;;N;;;;; 3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L; 0032 0034 70B9;;;;N;;;;; 3371;SQUARE HPA;So;0;L; 0068 0050 0061;;;;N;;;;; 3372;SQUARE DA;So;0;L; 0064 0061;;;;N;;;;; 3373;SQUARE AU;So;0;L; 0041 0055;;;;N;;;;; 3374;SQUARE BAR;So;0;L; 0062 0061 0072;;;;N;;;;; 3375;SQUARE OV;So;0;L; 006F 0056;;;;N;;;;; 3376;SQUARE PC;So;0;L; 0070 0063;;;;N;;;;; 3377;SQUARE DM;So;0;ON; 0064 006D;;;;N;;;;; 3378;SQUARE DM SQUARED;So;0;ON; 0064 006D 00B2;;;;N;;;;; 3379;SQUARE DM CUBED;So;0;ON; 0064 006D 00B3;;;;N;;;;; 337A;SQUARE IU;So;0;ON; 0049 0055;;;;N;;;;; 337B;SQUARE ERA NAME HEISEI;So;0;L; 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; 337C;SQUARE ERA NAME SYOUWA;So;0;L; 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; 337D;SQUARE ERA NAME TAISYOU;So;0;L; 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; 337E;SQUARE ERA NAME MEIZI;So;0;L; 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; 337F;SQUARE CORPORATION;So;0;L; 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; 3380;SQUARE PA AMPS;So;0;L; 0070 0041;;;;N;SQUARED PA AMPS;;;; 3381;SQUARE NA;So;0;L; 006E 0041;;;;N;SQUARED NA;;;; 3382;SQUARE MU A;So;0;L; 03BC 0041;;;;N;SQUARED MU A;;;; 3383;SQUARE MA;So;0;L; 006D 0041;;;;N;SQUARED MA;;;; 3384;SQUARE KA;So;0;L; 006B 0041;;;;N;SQUARED KA;;;; 3385;SQUARE KB;So;0;L; 004B 0042;;;;N;SQUARED KB;;;; 3386;SQUARE MB;So;0;L; 004D 0042;;;;N;SQUARED MB;;;; 3387;SQUARE GB;So;0;L; 0047 0042;;;;N;SQUARED GB;;;; 3388;SQUARE CAL;So;0;L; 0063 0061 006C;;;;N;SQUARED CAL;;;; 3389;SQUARE KCAL;So;0;L; 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; 338A;SQUARE PF;So;0;L; 0070 0046;;;;N;SQUARED PF;;;; 338B;SQUARE NF;So;0;L; 006E 0046;;;;N;SQUARED NF;;;; 338C;SQUARE MU F;So;0;L; 03BC 0046;;;;N;SQUARED MU F;;;; 338D;SQUARE MU G;So;0;L; 03BC 0067;;;;N;SQUARED MU G;;;; 338E;SQUARE MG;So;0;L; 006D 0067;;;;N;SQUARED MG;;;; 338F;SQUARE KG;So;0;L; 006B 0067;;;;N;SQUARED KG;;;; 3390;SQUARE HZ;So;0;L; 0048 007A;;;;N;SQUARED HZ;;;; 3391;SQUARE KHZ;So;0;L; 006B 0048 007A;;;;N;SQUARED KHZ;;;; 3392;SQUARE MHZ;So;0;L; 004D 0048 007A;;;;N;SQUARED MHZ;;;; 3393;SQUARE GHZ;So;0;L; 0047 0048 007A;;;;N;SQUARED GHZ;;;; 3394;SQUARE THZ;So;0;L; 0054 0048 007A;;;;N;SQUARED THZ;;;; 3395;SQUARE MU L;So;0;L; 03BC 2113;;;;N;SQUARED MU L;;;; 3396;SQUARE ML;So;0;L; 006D 2113;;;;N;SQUARED ML;;;; 3397;SQUARE DL;So;0;L; 0064 2113;;;;N;SQUARED DL;;;; 3398;SQUARE KL;So;0;L; 006B 2113;;;;N;SQUARED KL;;;; 3399;SQUARE FM;So;0;L; 0066 006D;;;;N;SQUARED FM;;;; 339A;SQUARE NM;So;0;L; 006E 006D;;;;N;SQUARED NM;;;; 339B;SQUARE MU M;So;0;L; 03BC 006D;;;;N;SQUARED MU M;;;; 339C;SQUARE MM;So;0;L; 006D 006D;;;;N;SQUARED MM;;;; 339D;SQUARE CM;So;0;L; 0063 006D;;;;N;SQUARED CM;;;; 339E;SQUARE KM;So;0;L; 006B 006D;;;;N;SQUARED KM;;;; 339F;SQUARE MM SQUARED;So;0;L; 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; 33A0;SQUARE CM SQUARED;So;0;L; 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; 33A1;SQUARE M SQUARED;So;0;L; 006D 00B2;;;;N;SQUARED M SQUARED;;;; 33A2;SQUARE KM SQUARED;So;0;L; 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; 33A3;SQUARE MM CUBED;So;0;L; 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; 33A4;SQUARE CM CUBED;So;0;L; 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; 33A5;SQUARE M CUBED;So;0;L; 006D 00B3;;;;N;SQUARED M CUBED;;;; 33A6;SQUARE KM CUBED;So;0;L; 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; 33A7;SQUARE M OVER S;So;0;L; 006D 2215 0073;;;;N;SQUARED M OVER S;;;; 33A8;SQUARE M OVER S SQUARED;So;0;L; 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; 33A9;SQUARE PA;So;0;L; 0050 0061;;;;N;SQUARED PA;;;; 33AA;SQUARE KPA;So;0;L; 006B 0050 0061;;;;N;SQUARED KPA;;;; 33AB;SQUARE MPA;So;0;L; 004D 0050 0061;;;;N;SQUARED MPA;;;; 33AC;SQUARE GPA;So;0;L; 0047 0050 0061;;;;N;SQUARED GPA;;;; 33AD;SQUARE RAD;So;0;L; 0072 0061 0064;;;;N;SQUARED RAD;;;; 33AE;SQUARE RAD OVER S;So;0;L; 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; 33AF;SQUARE RAD OVER S SQUARED;So;0;L; 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; 33B0;SQUARE PS;So;0;L; 0070 0073;;;;N;SQUARED PS;;;; 33B1;SQUARE NS;So;0;L; 006E 0073;;;;N;SQUARED NS;;;; 33B2;SQUARE MU S;So;0;L; 03BC 0073;;;;N;SQUARED MU S;;;; 33B3;SQUARE MS;So;0;L; 006D 0073;;;;N;SQUARED MS;;;; 33B4;SQUARE PV;So;0;L; 0070 0056;;;;N;SQUARED PV;;;; 33B5;SQUARE NV;So;0;L; 006E 0056;;;;N;SQUARED NV;;;; 33B6;SQUARE MU V;So;0;L; 03BC 0056;;;;N;SQUARED MU V;;;; 33B7;SQUARE MV;So;0;L; 006D 0056;;;;N;SQUARED MV;;;; 33B8;SQUARE KV;So;0;L; 006B 0056;;;;N;SQUARED KV;;;; 33B9;SQUARE MV MEGA;So;0;L; 004D 0056;;;;N;SQUARED MV MEGA;;;; 33BA;SQUARE PW;So;0;L; 0070 0057;;;;N;SQUARED PW;;;; 33BB;SQUARE NW;So;0;L; 006E 0057;;;;N;SQUARED NW;;;; 33BC;SQUARE MU W;So;0;L; 03BC 0057;;;;N;SQUARED MU W;;;; 33BD;SQUARE MW;So;0;L; 006D 0057;;;;N;SQUARED MW;;;; 33BE;SQUARE KW;So;0;L; 006B 0057;;;;N;SQUARED KW;;;; 33BF;SQUARE MW MEGA;So;0;L; 004D 0057;;;;N;SQUARED MW MEGA;;;; 33C0;SQUARE K OHM;So;0;L; 006B 03A9;;;;N;SQUARED K OHM;;;; 33C1;SQUARE M OHM;So;0;L; 004D 03A9;;;;N;SQUARED M OHM;;;; 33C2;SQUARE AM;So;0;L; 0061 002E 006D 002E;;;;N;SQUARED AM;;;; 33C3;SQUARE BQ;So;0;L; 0042 0071;;;;N;SQUARED BQ;;;; 33C4;SQUARE CC;So;0;L; 0063 0063;;;;N;SQUARED CC;;;; 33C5;SQUARE CD;So;0;L; 0063 0064;;;;N;SQUARED CD;;;; 33C6;SQUARE C OVER KG;So;0;L; 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; 33C7;SQUARE CO;So;0;L; 0043 006F 002E;;;;N;SQUARED CO;;;; 33C8;SQUARE DB;So;0;L; 0064 0042;;;;N;SQUARED DB;;;; 33C9;SQUARE GY;So;0;L; 0047 0079;;;;N;SQUARED GY;;;; 33CA;SQUARE HA;So;0;L; 0068 0061;;;;N;SQUARED HA;;;; 33CB;SQUARE HP;So;0;L; 0048 0050;;;;N;SQUARED HP;;;; 33CC;SQUARE IN;So;0;L; 0069 006E;;;;N;SQUARED IN;;;; 33CD;SQUARE KK;So;0;L; 004B 004B;;;;N;SQUARED KK;;;; 33CE;SQUARE KM CAPITAL;So;0;L; 004B 004D;;;;N;SQUARED KM CAPITAL;;;; 33CF;SQUARE KT;So;0;L; 006B 0074;;;;N;SQUARED KT;;;; 33D0;SQUARE LM;So;0;L; 006C 006D;;;;N;SQUARED LM;;;; 33D1;SQUARE LN;So;0;L; 006C 006E;;;;N;SQUARED LN;;;; 33D2;SQUARE LOG;So;0;L; 006C 006F 0067;;;;N;SQUARED LOG;;;; 33D3;SQUARE LX;So;0;L; 006C 0078;;;;N;SQUARED LX;;;; 33D4;SQUARE MB SMALL;So;0;L; 006D 0062;;;;N;SQUARED MB SMALL;;;; 33D5;SQUARE MIL;So;0;L; 006D 0069 006C;;;;N;SQUARED MIL;;;; 33D6;SQUARE MOL;So;0;L; 006D 006F 006C;;;;N;SQUARED MOL;;;; 33D7;SQUARE PH;So;0;L; 0050 0048;;;;N;SQUARED PH;;;; 33D8;SQUARE PM;So;0;L; 0070 002E 006D 002E;;;;N;SQUARED PM;;;; 33D9;SQUARE PPM;So;0;L; 0050 0050 004D;;;;N;SQUARED PPM;;;; 33DA;SQUARE PR;So;0;L; 0050 0052;;;;N;SQUARED PR;;;; 33DB;SQUARE SR;So;0;L; 0073 0072;;;;N;SQUARED SR;;;; 33DC;SQUARE SV;So;0;L; 0053 0076;;;;N;SQUARED SV;;;; 33DD;SQUARE WB;So;0;L; 0057 0062;;;;N;SQUARED WB;;;; 33DE;SQUARE V OVER M;So;0;ON; 0056 2215 006D;;;;N;;;;; 33DF;SQUARE A OVER M;So;0;ON; 0041 2215 006D;;;;N;;;;; 33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L; 0031 65E5;;;;N;;;;; 33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L; 0032 65E5;;;;N;;;;; 33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L; 0033 65E5;;;;N;;;;; 33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L; 0034 65E5;;;;N;;;;; 33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L; 0035 65E5;;;;N;;;;; 33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L; 0036 65E5;;;;N;;;;; 33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L; 0037 65E5;;;;N;;;;; 33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L; 0038 65E5;;;;N;;;;; 33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L; 0039 65E5;;;;N;;;;; 33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L; 0031 0030 65E5;;;;N;;;;; 33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L; 0031 0031 65E5;;;;N;;;;; 33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L; 0031 0032 65E5;;;;N;;;;; 33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L; 0031 0033 65E5;;;;N;;;;; 33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L; 0031 0034 65E5;;;;N;;;;; 33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L; 0031 0035 65E5;;;;N;;;;; 33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L; 0031 0036 65E5;;;;N;;;;; 33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L; 0031 0037 65E5;;;;N;;;;; 33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L; 0031 0038 65E5;;;;N;;;;; 33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L; 0031 0039 65E5;;;;N;;;;; 33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L; 0032 0030 65E5;;;;N;;;;; 33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L; 0032 0031 65E5;;;;N;;;;; 33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L; 0032 0032 65E5;;;;N;;;;; 33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L; 0032 0033 65E5;;;;N;;;;; 33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L; 0032 0034 65E5;;;;N;;;;; 33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L; 0032 0035 65E5;;;;N;;;;; 33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L; 0032 0036 65E5;;;;N;;;;; 33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L; 0032 0037 65E5;;;;N;;;;; 33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L; 0032 0038 65E5;;;;N;;;;; 33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L; 0032 0039 65E5;;;;N;;;;; 33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L; 0033 0030 65E5;;;;N;;;;; 33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L; 0033 0031 65E5;;;;N;;;;; 33FF;SQUARE GAL;So;0;ON; 0067 0061 006C;;;;N;;;;; 3400;;Lo;0;L;;;;;N;;;;; 4DB5;;Lo;0;L;;;;;N;;;;; 4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;; 4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;; 4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;; 4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;; 4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;; 4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;; 4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;; 4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;; 4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;; 4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;; 4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;; 4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;; 4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;; 4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;; 4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;; 4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;; 4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;; 4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;; 4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;; 4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;; 4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;; 4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;; 4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;; 4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;; 4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;; 4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;; 4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;; 4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;; 4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;; 4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;; 4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;; 4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;; 4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;; 4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;; 4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;; 4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;; 4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;; 4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;; 4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;; 4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;; 4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;; 4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;; 4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;; 4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;; 4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;; 4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;; 4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;; 4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;; 4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;; 4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;; 4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;; 4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;; 4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;; 4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;; 4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;; 4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;; 4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;;Lo;0;L;;;;;N;;;;; 9FCB;;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;; A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;; A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;; A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;; A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;; A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;; A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;; A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;; A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;; A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;; A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;; A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;; A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;; A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;; A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;; A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;; A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;; A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;; A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;; A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;; A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;; A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;; A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;; A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;; A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;; A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;; A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;; A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;; A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;; A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;; A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;; A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;; A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;; A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;; A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;; A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;; A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;; A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;; A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;; A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;; A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;; A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;; A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;; A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;; A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;; A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;; A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;; A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;; A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;; A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;; A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;; A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;; A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;; A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;; A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;; A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;; A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;; A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;; A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;; A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;; A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;; A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;; A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;; A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;; A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;; A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;; A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;; A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;; A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;; A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;; A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;; A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;; A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;; A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;; A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;; A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;; A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;; A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;; A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;; A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;; A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;; A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;; A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;; A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;; A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;; A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;; A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;; A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;; A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;; A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;; A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;; A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;; A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;; A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;; A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;; A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;; A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;; A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;; A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;; A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;; A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;; A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;; A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;; A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;; A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;; A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;; A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;; A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;; A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;; A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;; A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;; A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;; A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;; A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;; A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;; A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;; A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;; A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;; A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;; A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;; A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;; A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;; A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;; A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;; A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;; A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;; A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;; A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;; A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;; A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;; A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;; A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;; A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;; A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;; A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;; A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;; A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;; A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;; A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;; A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;; A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;; A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;; A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;; A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;; A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;; A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;; A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;; A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;; A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;; A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;; A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;; A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;; A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;; A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;; A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;; A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;; A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;; A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;; A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;; A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;; A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;; A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;; A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;; A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;; A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;; A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;; A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;; A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;; A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;; A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;; A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;; A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;; A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;; A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;; A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;; A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;; A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;; A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;; A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;; A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;; A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;; A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;; A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;; A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;; A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;; A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;; A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;; A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;; A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;; A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;; A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;; A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;; A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;; A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;; A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;; A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;; A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;; A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;; A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;; A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;; A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;; A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;; A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;; A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;; A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;; A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;; A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;; A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;; A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;; A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;; A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; A60D;VAI COMMA;Po;0;ON;;;;;N;;;;; A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;; A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;; A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;; A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;; A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;; A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;; A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;; A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;; A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;; A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;; A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;; A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;; A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;; A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;; A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;; A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;; A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;; A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;; A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;; A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;; A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643; A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642 A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645; A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644 A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647; A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646 A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649; A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648 A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B; A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D; A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651; A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650 A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653; A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652 A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655; A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654 A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657; A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656 A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659; A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658 A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B; A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664 A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667; A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666 A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669; A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668 A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B; A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D; A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;; A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;; A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;; A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;; A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;; A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;; A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;; A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681; A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680 A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683; A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682 A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685; A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684 A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687; A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686 A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689; A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688 A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B; A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D; A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F; A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691; A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690 A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693; A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692 A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695; A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694 A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697; A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696 A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;; A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;; A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;; A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;; A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;; A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;; A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;; A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;; A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;; A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;; A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;; A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;; A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;; A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;; A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;; A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;; A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;; A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;; A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;; A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;; A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;; A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;; A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;; A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;; A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;; A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;; A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;; A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;; A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;; A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;; A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;; A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;; A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;; A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;; A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;; A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;; A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;; A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;; A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;; A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;; A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;; A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;; A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;; A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;; A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;; A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;; A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;; A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;; A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;; A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;; A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;; A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;; A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;; A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;; A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;; A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;; A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;; A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;; A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;; A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;; A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;; A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;; A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;; A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;; A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;; A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;; A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;; A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;; A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;; A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;; A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;; A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;; A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;; A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;; A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;; A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;; A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;; A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;; A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;; A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;; A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;; A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;; A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;; A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;; A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;; A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;; A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;; A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;; A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;; A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;; A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;; A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;; A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;; A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;; A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;; A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;; A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;; A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;; A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;; A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;; A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;; A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;; A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;; A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;; A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723; A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722 A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725; A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724 A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727; A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726 A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729; A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728 A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B; A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D; A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F; A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;; A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;; A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733; A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732 A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735; A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734 A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737; A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736 A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739; A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738 A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B; A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D; A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F; A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741; A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740 A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743; A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742 A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745; A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744 A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747; A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746 A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749; A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748 A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B; A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D; A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F; A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751; A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750 A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753; A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752 A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755; A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754 A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757; A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756 A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759; A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758 A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B; A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D; A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F; A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761; A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760 A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763; A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762 A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765; A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764 A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767; A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766 A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769; A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768 A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B; A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D; A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F; A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E A770;MODIFIER LETTER US;Lm;0;L; A76F;;;;N;;;;; A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;; A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;; A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;; A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;; A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;; A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;; A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;; A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;; A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A; A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779 A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C; A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79; A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F; A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781; A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780 A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783; A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782 A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785; A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784 A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787; A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786 A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;; A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;; A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;; A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;; A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;; A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;; A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;; A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;; A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;; A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;; A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;; A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;; A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;; A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;; A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;; A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;; A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;; A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;; A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;; A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;; A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;; A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;; A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;; A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;; A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;; A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;; A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;; A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;; A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;; A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;; A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;; A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;; A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;; A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;; A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;; A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;; A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;; A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;; A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;; A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;; A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;; A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;; A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;; A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;; A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;; A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;; A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;; A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;; A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;; A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;; A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;; A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;; A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;; A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;; A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;; A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;; A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;; A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;; A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;; A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;; A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;; A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;; A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;; A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;; A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;; A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;; A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;; A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;; A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;; A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;; A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;; A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;; A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;; A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;; A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;; A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;; A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;; A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;; A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;; A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;; A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;; A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;; A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;; A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;; A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;; A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;; A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;; A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;; A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;; A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;; A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;; A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;; A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;; A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;; A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;; A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;; A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;; A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;; A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;; A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;; A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;; A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;; A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;; A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;; A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;; A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;; A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;; A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;; A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;; A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;; A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;; A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;; A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;; A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;; A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;; A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;; A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;; A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;; A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;; A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;; A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;; A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;; A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;; A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;; A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;; A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;; A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;; A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;; A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;; A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;; A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;; A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;; A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;; A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;; A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;; A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;; A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;; A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;; A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;; A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;; A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;; A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;; A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;; A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;; A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;; A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;; A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;; A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;; A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;; A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;; A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;; A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;; A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;; A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;; A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;; A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;; A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;; A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;; A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;; A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;; A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;; A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;; A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;; A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;; A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;; A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;; A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;; A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;; A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;; A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;; A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;; A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;; A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;; A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;; A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;; A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;; A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;; A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;; A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;; A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;; A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;; A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;; A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;; A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;; A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;; A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;; A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;; A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;; A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;; A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;; A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;; A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;; A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;; A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;; A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;; A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;; A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;; A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;; A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;; A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;; A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;; A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;; A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;; A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;; A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;; A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;; A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;; A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;; A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;; A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;; A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;; A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;; A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;; A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;; A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;; A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;; A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;; A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;; A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;; A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;; A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;; A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;; A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;; A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;; A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;; A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;; A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;; A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;; A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;; A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;; A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;; A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;; A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;; A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;; A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;; A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;; A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;; A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;; A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;; A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;; A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;; A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;; A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;; A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;; A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;; A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;; A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;; A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;; A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;; A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;; A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;; A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;; A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;; A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;; A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;; A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;; A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;; A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;; A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;; A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;; A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;; A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;; A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;; A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;; A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;; A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;; A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;; A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;; A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;; A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;; A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;; A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;; A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;; A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;; A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;; A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;; A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;; A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;; A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;; A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;; A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;; A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;; A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;; A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;; A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;; A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;; A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;; A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;; A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;; A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;; A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;; A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;; A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;; A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;; A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;; A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;; A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;; A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;; A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;; A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;; A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;; A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;; A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;; A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;; A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;; A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;; A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;; A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;; A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;; A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;; A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;; A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;; A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;; A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;; A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;; A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;; A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;; A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;; A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;; A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;; A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;; A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;; AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;; AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;; AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;; AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;; AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;; AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;; AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;; AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;; AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;; AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;; AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;; AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;; AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;; AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;; AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;; AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;; AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;; AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;; AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;; AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;; AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;; AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;; AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;; AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;; AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;; AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;; AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;; AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;; AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;; AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;; AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;; AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;; AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;; AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;; AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;; AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;; AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;; AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;; AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;; AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;; AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;; AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;; AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;; AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;; AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;; AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;; AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;; AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;; AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;; AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;; AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;; AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;; AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;; AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;; AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;; AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;; AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;; AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;; AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;; AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;; AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;; AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;; AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;; AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;; AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;; AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;; AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;; AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;; AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;; AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;; AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;; AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;; AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;; AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;; AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;; AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;; AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;; AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;; AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;; AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;; AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;; AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;; AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;; AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;; AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;; AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;; AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;; AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;; AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;; AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;; AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;; AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;; AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;; AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;; AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;; AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;; AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;; AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;; AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;; AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;; AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;; AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;; AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;; AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;; AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;; AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;; AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;; AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;; AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;; AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;; AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;; AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;; AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;; AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;; AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;; AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;; AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;; AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;; AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;; AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;; AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;; AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;; AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;; AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;; AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;; AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;; AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;; AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;; AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;; AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;; AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;; AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;; AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;; AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;; AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;; AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;; AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;; AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;; AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;; AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;; AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;; AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;; AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;; AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;; AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;; AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;; AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;; AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;; AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;; AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;; AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;; AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;; AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;; AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;; AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;; AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;; AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;; AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;; AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;; ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;; ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;; ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;; ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;; ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;; ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;; ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;; ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;; ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;; ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;; ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;; ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;; ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;; ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;; ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;; ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;; ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;; ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;; ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;; ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;; ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;; ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;; ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;; ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;; ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;; ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;; ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;; ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;; ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;; ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;; ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;; ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;; ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;; ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;; ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;; ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;; ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;; ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;; ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;; ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;; ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;; ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;; ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AC00;;Lo;0;L;;;;;N;;;;; D7A3;;Lo;0;L;;;;;N;;;;; D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;; D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;; D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;; D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;; D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;; D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;; D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;; D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;; D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;; D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;; D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;; D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;; D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;; D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;; D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;; D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;; D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;; D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;; D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;; D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;; D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;; D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;; D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;; D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;; D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;; D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;; D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;; D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;; D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;; D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;; D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;; D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;; D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;; D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;; D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;; D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;; D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;; D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;; D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;; D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;; D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;; D800;;Cs;0;L;;;;;N;;;;; DB7F;;Cs;0;L;;;;;N;;;;; DB80;;Cs;0;L;;;;;N;;;;; DBFF;;Cs;0;L;;;;;N;;;;; DC00;;Cs;0;L;;;;;N;;;;; DFFF;;Cs;0;L;;;;;N;;;;; E000;;Co;0;L;;;;;N;;;;; F8FF;;Co;0;L;;;;;N;;;;; F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;; F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;; F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;; F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;; F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;; F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;; F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;; F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;; FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;; FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;; FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;; FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;; FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;; FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;; FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;; FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;; FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;; FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;; FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;; FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;; FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;; FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;; FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;; FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;; FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;; FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;; FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;; FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;; FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;; FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;; FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;; FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;; FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;; FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;; FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;; FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;; FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;; FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;; FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;; FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;; FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;; FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;; FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;; FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;; FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;; FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;; FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;; FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;; FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;; FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;; FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;; FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;; FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;; FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;; FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;; FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;; FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;; FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;; FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;; FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;; FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;; FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;; FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;; FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;; FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;; FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;; FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;; FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;; FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;; FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;; FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;; FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;; FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;; FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;; FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;; FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;; FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;; FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;; FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;; FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;; FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;; FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;; FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;; FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;; FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;; FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;; FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;; FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;; FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;; FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;; FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;; FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;; FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;; FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;; FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;; FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;; FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;; FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;; FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;; FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;; FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;; FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;; FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;; FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;; FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;; FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;; FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;; FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;; FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;; FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;; FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;; FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;; FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;; FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;; FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;; FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;; FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;; FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;; FB00;LATIN SMALL LIGATURE FF;Ll;0;L; 0066 0066;;;;N;;;;; FB01;LATIN SMALL LIGATURE FI;Ll;0;L; 0066 0069;;;;N;;;;; FB02;LATIN SMALL LIGATURE FL;Ll;0;L; 0066 006C;;;;N;;;;; FB03;LATIN SMALL LIGATURE FFI;Ll;0;L; 0066 0066 0069;;;;N;;;;; FB04;LATIN SMALL LIGATURE FFL;Ll;0;L; 0066 0066 006C;;;;N;;;;; FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L; 017F 0074;;;;N;;;;; FB06;LATIN SMALL LIGATURE ST;Ll;0;L; 0073 0074;;;;N;;;;; FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L; 0574 0576;;;;N;;;;; FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L; 0574 0565;;;;N;;;;; FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L; 0574 056B;;;;N;;;;; FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L; 057E 0576;;;;N;;;;; FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L; 0574 056D;;;;N;;;;; FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R; 05E2;;;;N;;;;; FB21;HEBREW LETTER WIDE ALEF;Lo;0;R; 05D0;;;;N;;;;; FB22;HEBREW LETTER WIDE DALET;Lo;0;R; 05D3;;;;N;;;;; FB23;HEBREW LETTER WIDE HE;Lo;0;R; 05D4;;;;N;;;;; FB24;HEBREW LETTER WIDE KAF;Lo;0;R; 05DB;;;;N;;;;; FB25;HEBREW LETTER WIDE LAMED;Lo;0;R; 05DC;;;;N;;;;; FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R; 05DD;;;;N;;;;; FB27;HEBREW LETTER WIDE RESH;Lo;0;R; 05E8;;;;N;;;;; FB28;HEBREW LETTER WIDE TAV;Lo;0;R; 05EA;;;;N;;;;; FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R; 05D0 05DC;;;;N;;;;; FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL; 0671;;;;N;;;;; FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL; 0671;;;;N;;;;; FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL; 067B;;;;N;;;;; FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL; 067E;;;;N;;;;; FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL; 0680;;;;N;;;;; FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL; 067A;;;;N;;;;; FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL; 067F;;;;N;;;;; FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL; 0679;;;;N;;;;; FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL; 06A6;;;;N;;;;; FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL; 0684;;;;N;;;;; FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL; 0683;;;;N;;;;; FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL; 0686;;;;N;;;;; FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL; 0687;;;;N;;;;; FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL; 068D;;;;N;;;;; FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL; 068D;;;;N;;;;; FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL; 068C;;;;N;;;;; FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL; 068C;;;;N;;;;; FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL; 068E;;;;N;;;;; FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL; 068E;;;;N;;;;; FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL; 0688;;;;N;;;;; FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL; 0688;;;;N;;;;; FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL; 0698;;;;N;;;;; FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL; 0698;;;;N;;;;; FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL; 0691;;;;N;;;;; FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL; 0691;;;;N;;;;; FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL; 06A9;;;;N;;;;; FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL; 06AF;;;;N;;;;; FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL; 06B3;;;;N;;;;; FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL; 06BA;;;;N;;;;; FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL; 06BA;;;;N;;;;; FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL; 06D2;;;;N;;;;; FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL; 06D2;;;;N;;;;; FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 06D3;;;;N;;;;; FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 06D3;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0677;;;;N;;;;; FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL; 06CB;;;;N;;;;; FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL; 06CB;;;;N;;;;; FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062B 062C;;;;N;;;;; FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL; 062E 062D;;;;N;;;;; FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0645 0649;;;;N;;;;; FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL; 0645 064A;;;;N;;;;; FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0647 0649;;;;N;;;;; FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL; 0647 064A;;;;N;;;;; FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0630 0670;;;;N;;;;; FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0631 0670;;;;N;;;;; FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C 0651;;;;N;;;;; FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D 0651;;;;N;;;;; FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL; 0020 064E 0651;;;;N;;;;; FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F 0651;;;;N;;;;; FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL; 0020 0650 0651;;;;N;;;;; FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0020 0651 0670;;;;N;;;;; FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL; 0626 0631;;;;N;;;;; FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL; 0626 0632;;;;N;;;;; FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL; 0626 0646;;;;N;;;;; FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL; 0628 0631;;;;N;;;;; FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL; 0628 0632;;;;N;;;;; FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL; 0628 0646;;;;N;;;;; FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL; 062A 0631;;;;N;;;;; FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL; 062A 0632;;;;N;;;;; FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL; 062A 0646;;;;N;;;;; FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL; 062B 0631;;;;N;;;;; FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL; 062B 0632;;;;N;;;;; FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL; 062B 0646;;;;N;;;;; FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL; 0645 0627;;;;N;;;;; FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL; 0646 0631;;;;N;;;;; FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL; 0646 0632;;;;N;;;;; FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL; 0646 0646;;;;N;;;;; FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL; 064A 0631;;;;N;;;;; FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL; 064A 0632;;;;N;;;;; FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL; 064A 0646;;;;N;;;;; FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL; 0626 062E;;;;N;;;;; FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL; 0635 062E;;;;N;;;;; FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL; 0644 0647;;;;N;;;;; FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL; 0647 0670;;;;N;;;;; FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL; 062B 0647;;;;N;;;;; FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL; 0640 064E 0651;;;;N;;;;; FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F 0651;;;;N;;;;; FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL; 0640 0650 0651;;;;N;;;;; FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3E;ORNATE LEFT PARENTHESIS;Ps;0;ON;;;;;N;;;;; FD3F;ORNATE RIGHT PARENTHESIS;Pe;0;ON;;;;;N;;;;; FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062C 0645;;;;N;;;;; FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062D 0645;;;;N;;;;; FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062E 0645;;;;N;;;;; FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 062A 0645 062C;;;;N;;;;; FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062A 0645 062D;;;;N;;;;; FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 062A 0645 062E;;;;N;;;;; FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 0645 064A;;;;N;;;;; FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0645 0649;;;;N;;;;; FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062D 062C;;;;N;;;;; FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 062C 062D;;;;N;;;;; FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062C 0649;;;;N;;;;; FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0633 0645 062C;;;;N;;;;; FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0634 062C 064A;;;;N;;;;; FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 062D 0649;;;;N;;;;; FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645 0645;;;;N;;;;; FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0637 0645 064A;;;;N;;;;; FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0645 0649;;;;N;;;;; FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 063A 0645 0645;;;;N;;;;; FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 063A 0645 064A;;;;N;;;;; FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0645 0649;;;;N;;;;; FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0642 0645 0645;;;;N;;;;; FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0644 062D 064A;;;;N;;;;; FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 062D 0649;;;;N;;;;; FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062D 062C;;;;N;;;;; FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062D 0645;;;;N;;;;; FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062D 064A;;;;N;;;;; FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062C 062D;;;;N;;;;; FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062C 0645;;;;N;;;;; FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062E 062C;;;;N;;;;; FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062E 0645;;;;N;;;;; FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062C 062E;;;;N;;;;; FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0647 0645 062C;;;;N;;;;; FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645 0645;;;;N;;;;; FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062D 0645;;;;N;;;;; FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062D 0649;;;;N;;;;; FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062C 0649;;;;N;;;;; FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 0645 064A;;;;N;;;;; FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0645 0649;;;;N;;;;; FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062E 064A;;;;N;;;;; FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 062C 064A;;;;N;;;;; FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062C 0649;;;;N;;;;; FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 062A 062E 064A;;;;N;;;;; FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062E 0649;;;;N;;;;; FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 0645 064A;;;;N;;;;; FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0645 0649;;;;N;;;;; FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 0645 064A;;;;N;;;;; FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 062D 0649;;;;N;;;;; FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0645 0649;;;;N;;;;; FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062E 0649;;;;N;;;;; FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0635 062D 064A;;;;N;;;;; FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0634 062D 064A;;;;N;;;;; FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0636 062D 064A;;;;N;;;;; FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 062C 064A;;;;N;;;;; FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 0645 064A;;;;N;;;;; FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 064A 062D 064A;;;;N;;;;; FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 062C 064A;;;;N;;;;; FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 0645 064A;;;;N;;;;; FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 0645 064A;;;;N;;;;; FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0642 0645 064A;;;;N;;;;; FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0646 062D 064A;;;;N;;;;; FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0639 0645 064A;;;;N;;;;; FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0643 0645 064A;;;;N;;;;; FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062E 064A;;;;N;;;;; FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 062C 062D 064A;;;;N;;;;; FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 062C 064A;;;;N;;;;; FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 062C 064A;;;;N;;;;; FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0641 0645 064A;;;;N;;;;; FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062D 064A;;;;N;;;;; FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0633 062E 064A;;;;N;;;;; FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 062C 064A;;;;N;;;;; FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0635 0644 06D2;;;;N;;;;; FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0642 0644 06D2;;;;N;;;;; FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL; 0627 0644 0644 0647;;;;N;;;;; FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL; 0627 0643 0628 0631;;;;N;;;;; FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL; 0645 062D 0645 062F;;;;N;;;;; FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL; 0635 0644 0639 0645;;;;N;;;;; FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL; 0631 0633 0648 0644;;;;N;;;;; FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL; 0639 0644 064A 0647;;;;N;;;;; FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL; 0648 0633 0644 0645;;;;N;;;;; FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL; 0635 0644 0649;;;;N;;;;; FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL; 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL; 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; FDFC;RIAL SIGN;Sc;0;AL; 0631 06CC 0627 0644;;;;N;;;;; FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON; 002C;;;;N;;;;; FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;;;;; FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON; 003A;;;;N;;;;; FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON; 3016;;;;N;;;;; FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON; 3017;;;;N;;;;; FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON; 2026;;;;N;;;;; FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;; FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON; 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON; 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON; 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON; 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON; 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON; 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON; 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON; 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON; 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON; 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON; 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;N;;;;; FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;N;;;;; FE49;DASHED OVERLINE;Po;0;ON; 203E;;;;N;SPACING DASHED OVERSCORE;;;; FE4A;CENTRELINE OVERLINE;Po;0;ON; 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; FE4B;WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING WAVY OVERSCORE;;;; FE4C;DOUBLE WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; FE4D;DASHED LOW LINE;Pc;0;ON; 005F;;;;N;SPACING DASHED UNDERSCORE;;;; FE4E;CENTRELINE LOW LINE;Pc;0;ON; 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; FE4F;WAVY LOW LINE;Pc;0;ON; 005F;;;;N;SPACING WAVY UNDERSCORE;;;; FE50;SMALL COMMA;Po;0;CS; 002C;;;;N;;;;; FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FE52;SMALL FULL STOP;Po;0;CS; 002E;;;;N;SMALL PERIOD;;;; FE54;SMALL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FE55;SMALL COLON;Po;0;CS; 003A;;;;N;;;;; FE56;SMALL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FE57;SMALL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FE58;SMALL EM DASH;Pd;0;ON; 2014;;;;N;;;;; FE59;SMALL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SMALL OPENING PARENTHESIS;;;; FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;; FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;; FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;; FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;; FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;; FE5F;SMALL NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FE60;SMALL AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FE61;SMALL ASTERISK;Po;0;ON; 002A;;;;N;;;;; FE62;SMALL PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FE63;SMALL HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; FE64;SMALL LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; FE65;SMALL GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; FE66;SMALL EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FE68;SMALL REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;SMALL BACKSLASH;;;; FE69;SMALL DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FE6A;SMALL PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FE6B;SMALL COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL; 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL; 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL; 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL; 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL; 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL; 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL; 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL; 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL; 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL; 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL; 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FF02;FULLWIDTH QUOTATION MARK;Po;0;ON; 0022;;;;N;;;;; FF03;FULLWIDTH NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FF05;FULLWIDTH PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FF06;FULLWIDTH AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FF07;FULLWIDTH APOSTROPHE;Po;0;ON; 0027;;;;N;;;;; FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; FF0A;FULLWIDTH ASTERISK;Po;0;ON; 002A;;;;N;;;;; FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FF0C;FULLWIDTH COMMA;Po;0;CS; 002C;;;;N;;;;; FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; FF0E;FULLWIDTH FULL STOP;Po;0;CS; 002E;;;;N;FULLWIDTH PERIOD;;;; FF0F;FULLWIDTH SOLIDUS;Po;0;CS; 002F;;;;N;FULLWIDTH SLASH;;;; FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; FF11;FULLWIDTH DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; FF12;FULLWIDTH DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; FF13;FULLWIDTH DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; FF16;FULLWIDTH DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; FF19;FULLWIDTH DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; FF1A;FULLWIDTH COLON;Po;0;CS; 003A;;;;N;;;;; FF1B;FULLWIDTH SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; FF1F;FULLWIDTH QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L; 0041;;;;N;;;;FF41; FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L; 0042;;;;N;;;;FF42; FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L; 0043;;;;N;;;;FF43; FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L; 0044;;;;N;;;;FF44; FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L; 0045;;;;N;;;;FF45; FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L; 0046;;;;N;;;;FF46; FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L; 0047;;;;N;;;;FF47; FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L; 0048;;;;N;;;;FF48; FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L; 0049;;;;N;;;;FF49; FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L; 004A;;;;N;;;;FF4A; FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L; 004B;;;;N;;;;FF4B; FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L; 004C;;;;N;;;;FF4C; FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L; 004D;;;;N;;;;FF4D; FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L; 004E;;;;N;;;;FF4E; FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L; 004F;;;;N;;;;FF4F; FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L; 0050;;;;N;;;;FF50; FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L; 0051;;;;N;;;;FF51; FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L; 0052;;;;N;;;;FF52; FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L; 0053;;;;N;;;;FF53; FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L; 0054;;;;N;;;;FF54; FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L; 0055;;;;N;;;;FF55; FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L; 0056;;;;N;;;;FF56; FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L; 0057;;;;N;;;;FF57; FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L; 0058;;;;N;;;;FF58; FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L; 0059;;;;N;;;;FF59; FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L; 005A;;;;N;;;;FF5A; FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;FULLWIDTH BACKSLASH;;;; FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON; 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; FF3F;FULLWIDTH LOW LINE;Pc;0;ON; 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON; 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L; 0061;;;;N;;;FF21;;FF21 FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L; 0062;;;;N;;;FF22;;FF22 FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L; 0063;;;;N;;;FF23;;FF23 FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L; 0064;;;;N;;;FF24;;FF24 FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L; 0065;;;;N;;;FF25;;FF25 FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L; 0066;;;;N;;;FF26;;FF26 FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L; 0067;;;;N;;;FF27;;FF27 FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L; 0068;;;;N;;;FF28;;FF28 FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L; 0069;;;;N;;;FF29;;FF29 FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L; 006A;;;;N;;;FF2A;;FF2A FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L; 006B;;;;N;;;FF2B;;FF2B FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L; 006C;;;;N;;;FF2C;;FF2C FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L; 006D;;;;N;;;FF2D;;FF2D FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L; 006E;;;;N;;;FF2E;;FF2E FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L; 006F;;;;N;;;FF2F;;FF2F FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L; 0070;;;;N;;;FF30;;FF30 FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L; 0071;;;;N;;;FF31;;FF31 FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L; 0072;;;;N;;;FF32;;FF32 FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L; 0073;;;;N;;;FF33;;FF33 FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L; 0074;;;;N;;;FF34;;FF34 FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L; 0075;;;;N;;;FF35;;FF35 FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L; 0076;;;;N;;;FF36;;FF36 FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L; 0077;;;;N;;;FF37;;FF37 FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L; 0078;;;;N;;;FF38;;FF38 FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L; 0079;;;;N;;;FF39;;FF39 FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L; 007A;;;;N;;;FF3A;;FF3A FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON; 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; FF5E;FULLWIDTH TILDE;Sm;0;ON; 007E;;;;N;FULLWIDTH SPACING TILDE;;;; FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON; 2985;;;;Y;;;;; FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON; 2986;;;;Y;;;;; FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON; 30FB;;;;N;;;;; FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L; 30F2;;;;N;;;;; FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L; 30A1;;;;N;;;;; FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L; 30A3;;;;N;;;;; FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L; 30A5;;;;N;;;;; FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L; 30A7;;;;N;;;;; FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L; 30A9;;;;N;;;;; FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L; 30E3;;;;N;;;;; FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L; 30E5;;;;N;;;;; FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L; 30E7;;;;N;;;;; FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L; 30C3;;;;N;;;;; FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L; 30FC;;;;N;;;;; FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L; 30A2;;;;N;;;;; FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L; 30A4;;;;N;;;;; FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L; 30A6;;;;N;;;;; FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L; 30A8;;;;N;;;;; FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L; 30AA;;;;N;;;;; FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L; 30AB;;;;N;;;;; FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L; 30AD;;;;N;;;;; FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L; 30AF;;;;N;;;;; FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L; 30B1;;;;N;;;;; FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L; 30B3;;;;N;;;;; FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L; 30B5;;;;N;;;;; FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L; 30B7;;;;N;;;;; FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L; 30B9;;;;N;;;;; FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L; 30BB;;;;N;;;;; FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L; 30BD;;;;N;;;;; FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L; 30BF;;;;N;;;;; FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L; 30C1;;;;N;;;;; FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L; 30C4;;;;N;;;;; FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L; 30C6;;;;N;;;;; FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L; 30C8;;;;N;;;;; FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L; 30CA;;;;N;;;;; FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L; 30CB;;;;N;;;;; FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L; 30CC;;;;N;;;;; FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L; 30CD;;;;N;;;;; FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L; 30CE;;;;N;;;;; FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L; 30CF;;;;N;;;;; FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L; 30D2;;;;N;;;;; FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L; 30D5;;;;N;;;;; FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L; 30D8;;;;N;;;;; FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L; 30DB;;;;N;;;;; FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L; 30DE;;;;N;;;;; FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L; 30DF;;;;N;;;;; FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L; 30E0;;;;N;;;;; FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L; 30E1;;;;N;;;;; FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L; 30E2;;;;N;;;;; FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L; 30E4;;;;N;;;;; FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L; 30E6;;;;N;;;;; FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L; 30E8;;;;N;;;;; FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L; 30E9;;;;N;;;;; FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L; 30EA;;;;N;;;;; FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L; 30EB;;;;N;;;;; FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L; 30EC;;;;N;;;;; FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L; 30ED;;;;N;;;;; FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L; 30EF;;;;N;;;;; FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L; 30F3;;;;N;;;;; FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L; 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L; 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L; 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L; 3134;;;;N;;;;; FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L; 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L; 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L; 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L; 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L; 3141;;;;N;;;;; FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L; 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L; 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L; 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L; 3145;;;;N;;;;; FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L; 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L; 3147;;;;N;;;;; FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L; 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L; 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L; 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L; 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L; 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L; 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L; 314E;;;;N;;;;; FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L; 314F;;;;N;;;;; FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L; 3150;;;;N;;;;; FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L; 3151;;;;N;;;;; FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L; 3152;;;;N;;;;; FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L; 3153;;;;N;;;;; FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L; 3154;;;;N;;;;; FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L; 3155;;;;N;;;;; FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L; 3156;;;;N;;;;; FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L; 3157;;;;N;;;;; FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L; 3158;;;;N;;;;; FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L; 3159;;;;N;;;;; FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L; 315A;;;;N;;;;; FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L; 315B;;;;N;;;;; FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L; 315C;;;;N;;;;; FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L; 315D;;;;N;;;;; FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L; 315E;;;;N;;;;; FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L; 315F;;;;N;;;;; FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L; 3160;;;;N;;;;; FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L; 3161;;;;N;;;;; FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L; 3162;;;;N;;;;; FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; FFE0;FULLWIDTH CENT SIGN;Sc;0;ET; 00A2;;;;N;;;;; FFE1;FULLWIDTH POUND SIGN;Sc;0;ET; 00A3;;;;N;;;;; FFE2;FULLWIDTH NOT SIGN;Sm;0;ON; 00AC;;;;N;;;;; FFE3;FULLWIDTH MACRON;Sk;0;ON; 00AF;;;;N;FULLWIDTH SPACING MACRON;;;; FFE4;FULLWIDTH BROKEN BAR;So;0;ON; 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; FFE5;FULLWIDTH YEN SIGN;Sc;0;ET; 00A5;;;;N;;;;; FFE6;FULLWIDTH WON SIGN;Sc;0;ET; 20A9;;;;N;;;;; FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON; 2502;;;;N;;;;; FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON; 2190;;;;N;;;;; FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON; 2191;;;;N;;;;; FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON; 2192;;;;N;;;;; FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON; 2193;;;;N;;;;; FFED;HALFWIDTH BLACK SQUARE;So;0;ON; 25A0;;;;N;;;;; FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON; 25CB;;;;N;;;;; FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;; FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;; FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;; FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;; 10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;; 10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;; 10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;; 10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;; 10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;; 10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;; 10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;; 10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;; 10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;; 1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;; 1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;; 1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;; 1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;; 1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;; 10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;; 10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;; 10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;; 10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;; 10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;; 10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;; 10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;; 10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;; 10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;; 10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;; 1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;; 1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;; 1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;; 1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;; 1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;; 1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;; 10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;; 10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;; 10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;; 10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;; 10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;; 10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;; 10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;; 10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;; 10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;; 1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;; 1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;; 1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;; 1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;; 1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;; 1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;; 10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;; 10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;; 10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;; 10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;; 10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;; 10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;; 10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;; 10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;; 10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;; 10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;; 1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;; 1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;; 1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;; 1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;; 10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;; 10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;; 10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;; 10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;; 10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;; 10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;; 10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;; 10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;; 10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;; 10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;; 1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;; 1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;; 1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;; 1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;; 10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;; 10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;; 10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;; 10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;; 10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;; 10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;; 10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;; 10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;; 10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;; 10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;; 1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;; 1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;; 1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;; 1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;; 10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;; 10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;; 10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;; 10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;; 10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;; 10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;; 10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;; 10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;; 10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;; 10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;; 1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;; 1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;; 1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;; 1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;; 1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;; 1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;; 10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;; 10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;; 10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;; 10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;; 10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;; 10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;; 10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;; 10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;; 10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;; 10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;; 1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;; 1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;; 1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;; 1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;; 1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;; 1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;; 100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;; 100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;; 100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;; 100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;; 100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;; 100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;; 100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;; 100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;; 100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;; 100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;; 100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;; 100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;; 100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;; 100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;; 100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;; 100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;; 100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;; 100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;; 100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;; 100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;; 100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;; 100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;; 100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;; 100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;; 100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;; 100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;; 100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;; 100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;; 100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;; 100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;; 100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;; 100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;; 100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;; 100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;; 100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;; 100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;; 100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;; 100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;; 100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;; 100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;; 100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;; 100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;; 100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;; 100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;; 100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;; 100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;; 100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;; 100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;; 100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;; 100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;; 100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;; 100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;; 100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;; 100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;; 100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;; 100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;; 100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;; 100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;; 100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;; 100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;; 100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;; 100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;; 100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;; 100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;; 100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;; 100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;; 100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;; 100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;; 100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;; 100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;; 100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;; 100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;; 100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;; 100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;; 100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;; 100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;; 100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;; 100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;; 100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;; 100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;; 100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;; 100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;; 100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;; 100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;; 100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;; 100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;; 100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;; 100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;; 100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;; 100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;; 100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;; 10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;; 10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;; 10102;AEGEAN CHECK MARK;So;0;L;;;;;N;;;;; 10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;; 10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;; 10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;; 1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;; 1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;; 1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;; 1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;; 1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;; 1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;; 10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;; 10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;; 10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;; 10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;; 10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;; 10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;; 10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;; 10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;; 1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;; 1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;; 1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;; 1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;; 1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;; 10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;; 10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;; 10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;; 10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;; 10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;; 10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;; 10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;; 10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;; 10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;; 1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;; 1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;; 1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;; 1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;; 1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;; 10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;; 10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;; 10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;; 10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;; 10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;; 10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;; 10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;; 1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;; 1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;; 10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;; 10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;; 10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;; 10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;; 10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;; 10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;; 10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;; 10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;; 1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;; 1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;; 1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;; 1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;; 1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;; 1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;; 10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;; 10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;; 10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;; 10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;; 10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;; 10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;; 10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;; 10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;; 10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;; 10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;; 1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;; 1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;; 10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;; 10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;; 10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;; 10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;; 10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;; 10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;; 1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;; 1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;; 10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;; 10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;; 10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;; 10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;; 10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;; 10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;; 10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;; 1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;; 1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;; 1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;; 1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;; 10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;; 10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;; 10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;; 10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;; 10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;; 10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;; 10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;; 10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;; 10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;; 10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;; 1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; 10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; 10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; 10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; 10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;; 10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;; 10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;; 10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;; 10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;; 1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;; 1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;; 101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;; 101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;; 101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;; 101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;; 101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;; 101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;; 101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;; 101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;; 101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;; 101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;; 101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;; 101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;; 101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;; 101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;; 101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;; 101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;; 101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;; 101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;; 101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;; 101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;; 101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;; 101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;; 101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;; 101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;; 101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;; 101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;; 101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;; 101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;; 101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;; 101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;; 101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;; 101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;; 101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;; 101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;; 101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;; 101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;; 101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;; 101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;; 101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;; 101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;; 101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;; 101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;; 101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;; 101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;; 101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;; 101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;; 10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;; 10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;; 10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;; 10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;; 10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;; 10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;; 10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;; 10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;; 10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;; 10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;; 1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;; 1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;; 1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;; 1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;; 1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;; 1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;; 10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;; 10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;; 10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;; 10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;; 10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;; 10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;; 10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;; 10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;; 10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;; 10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;; 1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;; 1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;; 1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;; 102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;; 102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;; 102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;; 102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;; 102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;; 102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;; 102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;; 102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;; 102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;; 102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;; 102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;; 102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;; 102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;; 102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;; 102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;; 102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;; 102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;; 102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;; 102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;; 102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;; 102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;; 102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;; 102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;; 102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;; 102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;; 102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;; 102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;; 102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;; 102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;; 102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;; 102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;; 102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;; 102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;; 102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;; 102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;; 102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;; 102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;; 102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;; 102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;; 102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;; 102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;; 102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;; 102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;; 102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;; 102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;; 102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;; 102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;; 102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;; 102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;; 10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; 10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; 10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; 10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; 10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; 10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; 10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; 10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; 10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; 10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; 1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; 1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; 1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; 1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; 1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; 1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;; 10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; 10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; 10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; 10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; 10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; 10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; 10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; 10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;; 10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; 10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; 1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; 1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;; 1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;; 1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;; 1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;; 10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; 10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; 10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; 10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; 10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; 10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; 10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; 10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; 1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; 1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; 1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; 1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; 1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; 1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; 10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; 10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;; 10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; 10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; 10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; 10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; 10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; 10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; 10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; 10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; 1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;; 10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;; 10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;; 10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;; 10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;; 10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;; 10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;; 10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;; 10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;; 10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;; 10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;; 1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;; 1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;; 1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;; 1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;; 1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;; 1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;; 10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;; 10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;; 10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;; 10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;; 10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;; 10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;; 10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;; 10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;; 10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;; 10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;; 1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;; 1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;; 1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;; 1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;; 1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;; 103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;; 103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;; 103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;; 103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;; 103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;; 103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;; 103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;; 103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;; 103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;; 103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;; 103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;; 103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;; 103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;; 103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;; 103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;; 103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;; 103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;; 103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;; 103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;; 103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;; 103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;; 103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;; 103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;; 103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;; 103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;; 103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;; 103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;; 103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;; 103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;; 103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;; 103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;; 103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;; 103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;; 103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;; 103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;; 103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;; 103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;; 103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;; 103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;; 103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;; 103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;; 103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;; 103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;; 103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;; 103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;; 103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;; 103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;; 103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;; 103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;; 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; 10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; 10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; 10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; 10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; 10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; 10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; 10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; 10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; 10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; 1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; 1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; 1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; 1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; 1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; 1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; 10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; 10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; 10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; 10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; 10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; 10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; 10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; 10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; 10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; 10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; 1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; 1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; 1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; 1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; 1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; 1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; 10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; 10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; 10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; 10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; 10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; 10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; 10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E; 10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A 10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B 10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C 10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D 10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E 10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F 10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A 10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B 10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C 10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D 10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E 10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F 10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426 1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; 10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;; 10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;; 10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;; 10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;; 10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;; 10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;; 10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;; 10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;; 10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;; 1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;; 1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;; 1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;; 1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;; 1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;; 1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;; 10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;; 10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;; 10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;; 10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;; 10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;; 10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;; 10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;; 10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;; 10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;; 10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;; 1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;; 1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;; 1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;; 1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;; 1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;; 1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;; 10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;; 10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;; 10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;; 10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;; 10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;; 10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;; 10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;; 10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;; 10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;; 10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;; 1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;; 1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;; 1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;; 1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;; 1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;; 1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;; 10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;; 10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;; 10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;; 10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;; 10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;; 10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;; 10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;; 10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;; 10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;; 10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;; 1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;; 1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;; 1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;; 1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;; 1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;; 1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;; 10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;; 10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;; 10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;; 10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;; 10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;; 10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;; 10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;; 10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;; 10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;; 10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;; 1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;; 1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;; 1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;; 1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;; 104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; 10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; 10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; 10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;; 10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;; 10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;; 10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;; 1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;; 1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;; 1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;; 1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;; 1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;; 1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;; 10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;; 10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;; 10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;; 10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;; 10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;; 10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;; 10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;; 10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;; 10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;; 10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;; 1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;; 1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;; 1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;; 1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;; 1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;; 1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;; 10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;; 10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;; 10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;; 10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;; 10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;; 10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;; 10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;; 10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;; 10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;; 10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;; 1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;; 1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;; 1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;; 1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;; 1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;; 1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;; 10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;; 10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;; 10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;; 10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;; 10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;; 10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;; 10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;; 10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;; 1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;; 1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;; 10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; 10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; 10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;; 10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; 10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; 10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; 10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; 1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; 1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; 1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; 1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; 10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;; 10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; 10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; 10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; 10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; 10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; 10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;; 10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;; 10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;; 1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;; 1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;; 1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;; 1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; 10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;; 10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;; 10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;; 10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;; 10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;; 10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;; 10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;; 10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;; 10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;; 1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;; 1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;; 1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;; 1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;; 10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;; 10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;; 10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;; 10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;; 10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;; 10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;; 10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;; 10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;; 10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;; 10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;; 10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;; 10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;; 10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;; 10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;; 10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;; 1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;; 1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;; 1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;; 1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;; 1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;; 1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;; 10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;; 10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;; 10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;; 10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;; 10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;; 10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;; 10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;; 10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;; 10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;; 10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;; 1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;; 10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;; 10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; 10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;; 10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;; 10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;; 10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;; 10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;; 10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;; 10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;; 10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;; 10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;; 10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;; 10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;; 10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;; 10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;; 10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;; 10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;; 10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;; 10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;; 10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;; 10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;; 10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;; 10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;; 10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;; 10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;; 10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;; 10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;; 10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;; 10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;; 10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;; 10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;; 10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;; 10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;; 10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;; 10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;; 10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;; 10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;; 10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;; 10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;; 10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;; 10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;; 10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;; 10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;; 10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;; 10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;; 10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;; 10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;; 10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;; 10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;; 10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;; 10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;; 10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;; 10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;; 10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;; 10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;; 10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;; 10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; 10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;; 10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;; 10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;; 10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; 10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;; 10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;; 10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;; 10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; 10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;; 10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;; 10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;; 10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;; 10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;; 10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;; 10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;; 10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;; 10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;; 10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;; 10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;; 10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;; 10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;; 10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;; 10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;; 10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;; 10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;; 10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;; 10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;; 10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;; 10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;; 10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;; 10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;; 10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;; 10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;; 10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;; 10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;; 10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;; 10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;; 10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;; 10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;; 10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;; 10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;; 10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;; 10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;; 10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;; 10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;; 10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;; 10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;; 10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;; 10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;; 10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;; 10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;; 10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;; 10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;; 10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;; 10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;; 10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;; 10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;; 10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;; 10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;; 10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;; 10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;; 10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;; 10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; 10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; 10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; 10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; 10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;; 10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; 10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; 10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; 10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; 10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; 10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; 10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; 10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; 10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; 10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;; 10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;; 10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;; 10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;; 10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;; 10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;; 10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;; 10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;; 10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;; 10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;; 10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;; 10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;; 10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;; 10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;; 10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;; 10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;; 10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;; 10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;; 10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;; 10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;; 10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;; 10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;; 10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;; 10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;; 10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;; 10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;; 10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;; 10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;; 10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;; 10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;; 10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;; 10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;; 10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;; 10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;; 10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;; 10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;; 10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;; 10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;; 10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;; 10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;; 10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;; 10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;; 10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;; 10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;; 10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;; 10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;; 10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;; 10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;; 10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;; 10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;; 10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;; 10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;; 10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;; 10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;; 10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;; 10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;; 10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;; 10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;; 10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;; 10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;; 10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;; 10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;; 10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;; 10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;; 10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;; 10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;; 10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;; 10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;; 10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;; 10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;; 10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;; 10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;; 10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;; 10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;; 10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;; 10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;; 10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;; 10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;; 10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;; 10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;; 10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;; 10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;; 10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;; 10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;; 10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;; 10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;; 10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;; 10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;; 10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;; 10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;; 10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;; 10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;; 10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;; 10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;; 10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;; 10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;; 10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;; 10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;; 10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;; 10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;; 10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;; 10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; 10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; 10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; 11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;; 11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;; 11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;; 11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;; 11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;; 11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;; 11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;; 1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;; 1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;; 1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;; 1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;; 1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;; 1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;; 11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;; 11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;; 11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;; 11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;; 11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;; 11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;; 11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;; 11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;; 11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;; 1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;; 1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;; 1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;; 1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;; 1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;; 110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;; 110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;; 110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;; 110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;; 110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;; 110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;; 110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;; 110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;; 110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;; 110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;; 110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;; 110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;; 110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;; 110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;; 110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;; 110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;; 110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;; 110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;; 110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;; 110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; 110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; 12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;; 12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;; 12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;; 12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;; 12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;; 12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;; 1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;; 1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;; 1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;; 1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;; 12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;; 12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;; 12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;; 12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;; 12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;; 12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;; 1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;; 1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;; 1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;; 1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;; 12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;; 12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;; 12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;; 12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;; 12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;; 12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;; 12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;; 12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;; 12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;; 12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;; 1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;; 1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;; 1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;; 1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;; 1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;; 1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;; 12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;; 12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;; 12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;; 12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;; 12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;; 12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;; 12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;; 12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;; 12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;; 12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;; 1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;; 1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;; 1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;; 12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;; 12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;; 12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;; 12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;; 12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;; 12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;; 12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;; 12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;; 12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;; 12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;; 1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;; 1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;; 1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;; 1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;; 1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;; 12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;; 12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;; 12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;; 12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;; 12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;; 12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;; 12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;; 12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;; 12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;; 12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;; 1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;; 1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;; 1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;; 1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;; 1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;; 12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;; 12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;; 12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;; 12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;; 12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;; 12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;; 12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;; 12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;; 12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;; 12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; 1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;; 1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;; 1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;; 1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;; 1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;; 12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;; 12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;; 12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;; 12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;; 12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;; 12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;; 12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;; 12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;; 12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;; 1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;; 1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;; 1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;; 1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;; 1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;; 1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;; 12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;; 12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;; 12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;; 12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;; 12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;; 12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;; 12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;; 12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;; 12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;; 1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;; 1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;; 1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;; 1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;; 1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;; 12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;; 12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;; 12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;; 12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;; 12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;; 12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;; 12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;; 12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;; 12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;; 12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;; 1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;; 1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;; 1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;; 1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;; 1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;; 120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;; 120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;; 120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;; 120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;; 120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;; 120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;; 120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;; 120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;; 120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;; 120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;; 120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;; 120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;; 120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;; 120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;; 120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;; 120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;; 120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;; 120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;; 120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;; 120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;; 120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;; 120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;; 120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;; 120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;; 120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;; 120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;; 120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;; 120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;; 120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;; 120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;; 120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;; 120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;; 120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;; 120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;; 120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;; 120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;; 120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;; 120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;; 120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;; 120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;; 120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;; 120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;; 120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;; 120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;; 120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;; 120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;; 120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;; 120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;; 120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;; 120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;; 120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;; 120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;; 120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;; 120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;; 120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;; 120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;; 120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;; 120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;; 120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;; 120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;; 120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;; 120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;; 120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;; 120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;; 120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;; 120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;; 120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;; 120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;; 120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;; 120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;; 120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;; 120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;; 120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;; 120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;; 12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;; 12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;; 12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;; 12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;; 12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;; 12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;; 12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;; 12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;; 12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;; 12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;; 1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;; 1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;; 1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;; 1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;; 12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;; 12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;; 12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;; 12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;; 12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;; 12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;; 12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;; 12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;; 1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;; 1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;; 1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;; 1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;; 12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;; 12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;; 12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;; 12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;; 12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;; 12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;; 12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;; 12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;; 12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;; 12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;; 1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;; 1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;; 1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;; 1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;; 1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;; 1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;; 12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;; 12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;; 12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;; 12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;; 12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;; 12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;; 12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;; 12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;; 1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;; 1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;; 1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;; 1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;; 1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;; 12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;; 12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;; 12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;; 12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;; 12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;; 12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;; 12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;; 12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;; 12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;; 12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;; 1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;; 1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;; 1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;; 1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;; 1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;; 12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;; 12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;; 12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;; 12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;; 12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;; 12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;; 12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;; 12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;; 12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;; 12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;; 1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;; 1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;; 1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;; 1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;; 1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;; 1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;; 12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;; 12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;; 12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;; 12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;; 12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;; 12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;; 12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;; 12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;; 12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;; 1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;; 1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;; 1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;; 1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;; 1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;; 12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;; 12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;; 12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;; 12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;; 12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;; 12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;; 12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;; 12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;; 12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;; 12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;; 1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;; 1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;; 1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;; 1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;; 1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;; 1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;; 12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;; 12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;; 12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;; 12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;; 12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;; 12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;; 12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;; 12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;; 12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;; 12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;; 1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;; 1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;; 1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;; 1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;; 1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;; 12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;; 12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;; 12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;; 12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;; 12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;; 12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;; 12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;; 12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;; 12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;; 1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;; 1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;; 1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;; 1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;; 121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;; 121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;; 121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;; 121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;; 121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;; 121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;; 121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;; 121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;; 121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;; 121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;; 121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;; 121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;; 121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;; 121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;; 121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;; 121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;; 121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;; 121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;; 121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;; 121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;; 121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;; 121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;; 121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;; 121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;; 121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;; 121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;; 121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;; 121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;; 121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;; 121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;; 121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;; 121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;; 121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;; 121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;; 121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;; 121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;; 121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;; 121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;; 121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;; 121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;; 121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;; 121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;; 121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;; 121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;; 121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;; 121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;; 121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;; 121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;; 121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;; 121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;; 121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;; 121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;; 121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;; 121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;; 121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;; 121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;; 121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;; 121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;; 121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;; 121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;; 121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;; 121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;; 121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;; 121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;; 121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;; 121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;; 121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;; 121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;; 121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;; 121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;; 121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;; 121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;; 121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;; 121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;; 121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;; 121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;; 121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;; 121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;; 121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;; 121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;; 121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;; 121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;; 12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;; 12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;; 12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;; 12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;; 12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;; 12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;; 12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;; 1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;; 1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;; 1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;; 1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;; 12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;; 12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;; 12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;; 12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;; 12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;; 12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;; 12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;; 12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;; 12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;; 12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;; 1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;; 1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;; 1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;; 1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;; 1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;; 1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;; 12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;; 12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;; 12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;; 12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;; 12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;; 12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;; 12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;; 12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;; 12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;; 1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;; 1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;; 1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;; 1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;; 1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;; 1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;; 12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;; 12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;; 12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;; 12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;; 12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;; 12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;; 12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;; 12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;; 12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;; 1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;; 1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;; 1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;; 1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;; 1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;; 1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;; 12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;; 12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;; 12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;; 12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;; 12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;; 12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;; 12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;; 12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;; 12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;; 12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;; 1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;; 1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;; 1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;; 1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;; 1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;; 1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;; 12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;; 12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;; 12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;; 12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;; 1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;; 1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;; 12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;; 12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;; 12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;; 12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;; 12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;; 12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;; 12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;; 12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;; 1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;; 1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;; 1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;; 1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;; 12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;; 12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;; 12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;; 12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;; 12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;; 12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;; 1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;; 1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;; 1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;; 1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;; 1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;; 1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;; 12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;; 12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;; 12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;; 12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;; 12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;; 12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;; 12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;; 12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;; 12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;; 12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;; 1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;; 1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;; 1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;; 1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;; 1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;; 1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;; 12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;; 12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;; 12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;; 12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;; 12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;; 12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;; 12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;; 12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;; 12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;; 12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;; 1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;; 1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;; 1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;; 1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;; 1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;; 1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;; 122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;; 122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;; 122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;; 122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;; 122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;; 122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;; 122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;; 122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;; 122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;; 122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;; 122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;; 122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;; 122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;; 122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;; 122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;; 122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;; 122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;; 122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;; 122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;; 122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;; 122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;; 122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;; 122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;; 122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;; 122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;; 122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;; 122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;; 122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;; 122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;; 122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;; 122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;; 122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;; 122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;; 122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;; 122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;; 122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;; 122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;; 122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;; 122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;; 122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;; 122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;; 122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;; 122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;; 122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;; 122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;; 122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;; 122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;; 122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;; 122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;; 122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;; 122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;; 122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;; 122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;; 122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;; 122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;; 122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;; 122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;; 122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;; 122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;; 122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;; 122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;; 122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;; 122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;; 122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;; 122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;; 122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;; 122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;; 122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;; 122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;; 122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;; 122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;; 122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;; 122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;; 122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;; 122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;; 122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;; 122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;; 122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;; 122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;; 122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;; 122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;; 122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;; 122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;; 122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;; 122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;; 122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;; 122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;; 122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;; 122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;; 122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;; 122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;; 122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;; 12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;; 12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;; 12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;; 12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;; 12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;; 12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;; 12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;; 12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;; 12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;; 1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;; 1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;; 1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;; 1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;; 1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;; 1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;; 12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;; 12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;; 12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;; 12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;; 12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;; 12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;; 12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;; 12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;; 12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;; 1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;; 1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; 1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;; 1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;; 1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;; 12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;; 12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;; 12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;; 12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;; 12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;; 12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;; 12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;; 12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;; 12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;; 1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;; 1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;; 1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;; 1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;; 12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;; 12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;; 12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;; 12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;; 12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;; 12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;; 12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;; 12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;; 12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;; 1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;; 1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;; 1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;; 1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;; 12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;; 12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;; 12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;; 12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;; 12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;; 12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;; 12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;; 12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;; 12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;; 12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;; 1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;; 1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;; 1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;; 1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;; 1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;; 1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;; 12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;; 12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;; 12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;; 12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;; 12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;; 12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;; 12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;; 12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;; 12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;; 1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;; 1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;; 1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;; 1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;; 1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;; 12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;; 12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;; 12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;; 12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;; 12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;; 12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;; 12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;; 12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;; 12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;; 12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;; 1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;; 1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;; 1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;; 1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;; 1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;; 12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;; 12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;; 12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;; 12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;; 12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;; 12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;; 12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;; 12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;; 12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;; 12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;; 1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;; 1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;; 1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;; 1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;; 1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;; 1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;; 12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;; 12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;; 12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;; 12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;; 12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;; 12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;; 12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;; 12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;; 12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;; 12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;; 1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;; 1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;; 1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;; 1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;; 1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;; 1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;; 12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;; 12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;; 12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;; 12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;; 12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;; 12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;; 12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;; 12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;; 12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;; 1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;; 1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;; 1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;; 1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;; 1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;; 1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;; 12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;; 12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;;N;;;;; 12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;;N;;;;; 12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;; 12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;; 12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;; 12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;; 12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;; 1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;; 1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;; 1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;; 1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;; 1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;; 1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;; 12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;; 12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;; 12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;; 12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;; 12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;; 12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;; 12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;; 12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;; 12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;; 12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;; 1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;; 1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;; 1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;; 1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;; 1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;; 1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;; 12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;; 12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;; 12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;; 12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;; 12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;; 12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;; 12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;;N;;;;; 12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;;N;;;;; 12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;; 12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;; 1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;; 1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;; 1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;; 1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;; 1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;; 1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;; 12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;; 12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;; 12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;; 12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;; 12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;; 12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;; 13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; 13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; 13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; 13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; 13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; 13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;; 13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; 13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;; 13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;; 13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; 1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; 1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; 1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; 1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; 1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; 1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; 13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; 13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;; 13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; 13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; 13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; 13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;; 13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; 13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; 13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; 13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; 1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; 1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; 1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; 1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; 1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; 1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; 13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; 13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; 13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; 13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; 13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; 13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;; 13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; 13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; 13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; 13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; 1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; 1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; 1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; 1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; 1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;; 1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; 13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; 13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;; 13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; 13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;; 13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; 13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; 13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; 13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; 13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; 13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; 1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; 1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; 1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; 1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; 1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; 1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; 13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; 13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; 13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; 13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; 13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; 13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; 13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; 13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; 13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; 13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; 1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; 1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; 1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; 1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; 1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; 1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; 13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;; 13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;; 13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;; 13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;; 13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;; 13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;; 13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;; 13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;; 13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;; 13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;; 1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;; 1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;; 1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;; 1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;; 1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;; 1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;; 13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;; 13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;; 13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;; 13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;; 13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;; 13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;; 13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;; 13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;; 13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;; 13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;; 1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;; 1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;; 1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;; 1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;; 1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;; 1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;; 13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;; 13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;; 13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;; 13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;; 13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;; 13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;; 13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;; 13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;; 13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;; 13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;; 1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;; 1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;; 1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;; 1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;; 1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;; 1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;; 13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;; 13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;; 13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;; 13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;; 13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;; 13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;; 13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;; 13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;; 13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;; 13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;; 1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;; 1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;; 1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;; 1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;; 1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;; 1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;; 13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;; 13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;; 13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;; 13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;; 13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;; 13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;; 13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;; 13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;; 13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;; 13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;; 1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;; 1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;; 1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;; 1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;; 1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;; 1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;; 130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;; 130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;; 130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;; 130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;; 130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;; 130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;; 130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;; 130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;; 130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;; 130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;; 130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;; 130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;; 130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;; 130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;; 130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;; 130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;; 130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;; 130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;; 130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;; 130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;; 130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;; 130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;; 130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;; 130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;; 130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;; 130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;; 130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;; 130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;; 130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;; 130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;; 130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;; 130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;; 130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;; 130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;; 130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;; 130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;; 130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;; 130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;; 130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;; 130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;; 130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;; 130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;; 130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;; 130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;; 130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;; 130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;; 130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;; 130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;; 130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;; 130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;; 130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;; 130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;; 130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;; 130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;; 130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;; 130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;; 130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;; 130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;; 130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;; 130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;; 130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;; 130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;; 130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;; 130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;; 130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;; 130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;; 130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;; 130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;; 130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;; 130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;; 130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;; 130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;; 130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;; 130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;; 130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;; 130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;; 130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;; 130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;; 130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;; 130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;; 130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;; 130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;; 130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;; 130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;; 130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;; 130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;; 130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;; 130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;; 130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;; 130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;; 130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;; 130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;; 130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;; 130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;; 130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;; 130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;; 13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;; 13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;; 13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;; 13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;; 13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;; 13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;; 13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;; 13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;; 13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;; 13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;; 1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;; 1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;; 1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;; 1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;; 1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;; 1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;; 13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;; 13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;; 13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;; 13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;; 13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;; 13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;; 13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;; 13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;; 13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;; 13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;; 1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;; 1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;; 1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;; 1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;; 1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;; 1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;; 13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;; 13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;; 13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;; 13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;; 13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;; 13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;; 13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;; 13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;; 13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;; 13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;; 1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;; 1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;; 1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;; 1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;; 1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;; 1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;; 13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;; 13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;; 13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;; 13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;; 13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;; 13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;; 13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;; 13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;; 13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;; 13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;; 1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;; 1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;; 1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;; 1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;; 1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;; 1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;; 13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;; 13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;; 13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;; 13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;; 13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;; 13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;; 13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;; 13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;; 13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;; 13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;; 1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;; 1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;; 1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;; 1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;; 1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;; 1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;; 13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;; 13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;; 13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;; 13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;; 13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;; 13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;; 13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;; 13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;; 13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;; 13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;; 1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;; 1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;; 1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;; 1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;; 1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;; 1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;; 13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;; 13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;; 13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;; 13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;; 13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;; 13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;; 13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;; 13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;; 13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;; 13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;; 1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;; 1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;; 1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;; 1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;; 1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;; 1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;; 13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;; 13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;; 13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;; 13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;; 13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;; 13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;; 13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;; 13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;; 13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;; 13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;; 1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;; 1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;; 1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;; 1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;; 1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;; 1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;; 13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;; 13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;; 13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;; 13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;; 13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;; 13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;; 13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;; 13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;; 13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;; 13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;; 1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;; 1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;; 1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;; 1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;; 1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;; 1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;; 13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;; 13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;; 13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;; 13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;; 13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;; 13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;; 13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;; 13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;; 13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;; 13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;; 1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;; 1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;; 1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;; 1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;; 1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;; 1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;; 131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;; 131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;; 131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;; 131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;; 131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;; 131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;; 131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;; 131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;; 131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;; 131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;; 131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;; 131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;; 131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;; 131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;; 131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;; 131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;; 131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;; 131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;; 131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;; 131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;; 131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;; 131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;; 131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;; 131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;; 131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;; 131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;; 131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;; 131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;; 131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;; 131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;; 131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;; 131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;; 131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;; 131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;; 131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;; 131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;; 131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;; 131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;; 131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;; 131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;; 131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;; 131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;; 131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;; 131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;; 131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;; 131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;; 131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;; 131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;; 131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;; 131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;; 131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;; 131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;; 131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;; 131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;; 131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;; 131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;; 131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;; 131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;; 131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;; 131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;; 131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;; 131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;; 131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;; 131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;; 131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;; 131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;; 131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;; 131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;; 131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;; 131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;; 131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;; 131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;; 131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;; 131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;; 131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;; 131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;; 131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;; 131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;; 131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;; 131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;; 131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;; 131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;; 131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;; 131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;; 131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;; 131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;; 131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;; 131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;; 131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;; 131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;; 131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;; 131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;; 131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;; 131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;; 131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;; 131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;; 13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;; 13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;; 13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;; 13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;; 13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;; 13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;; 13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;; 13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;; 13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;; 13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;; 1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;; 1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;; 1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;; 1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;; 1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;; 1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;; 13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;; 13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;; 13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;; 13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;; 13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;; 13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;; 13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;; 13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;; 13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;; 13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;; 1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;; 1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;; 1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;; 1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;; 1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;; 1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;; 13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;; 13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;; 13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;; 13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;; 13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;; 13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;; 13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;; 13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;; 13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;; 13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;; 1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;; 1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;; 1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;; 1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;; 1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;; 1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;; 13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;; 13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;; 13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;; 13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;; 13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;; 13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;; 13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;; 13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;; 13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;; 13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;; 1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;; 1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;; 1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;; 1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;; 1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;; 1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;; 13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;; 13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;; 13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;; 13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;; 13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;; 13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;; 13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;; 13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;; 13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;; 13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;; 1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;; 1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;; 1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;; 1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;; 1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;; 1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;; 13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;; 13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;; 13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;; 13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;; 13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;; 13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;; 13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;; 13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;; 13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;; 13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;; 1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;; 1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;; 1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;; 1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;; 1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;; 1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;; 13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;; 13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;; 13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;; 13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;; 13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;; 13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;; 13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;; 13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;; 13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;; 13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;; 1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;; 1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;; 1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;; 1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;; 1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;; 1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;; 13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;; 13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;; 13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;; 13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;; 13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;; 13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;; 13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;; 13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;; 13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;; 13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;; 1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;; 1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;; 1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;; 1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;; 1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;; 1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;; 13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;; 13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;; 13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;; 13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;; 13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;; 13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;; 13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;; 13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;; 13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;; 13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;; 1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;; 1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;; 1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;; 1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;; 1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;; 1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;; 13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;; 13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;; 13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;; 13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;; 13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;; 13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;; 13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;; 13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;; 13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;; 13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;; 1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;; 1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;; 1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;; 1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;; 1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;; 1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;; 132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;; 132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;; 132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;; 132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;; 132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;; 132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;; 132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;; 132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;; 132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;; 132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;; 132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;; 132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;; 132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;; 132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;; 132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;; 132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;; 132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;; 132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;; 132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;; 132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;; 132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;; 132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;; 132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;; 132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;; 132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;; 132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;; 132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;; 132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;; 132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;; 132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;; 132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;; 132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;; 132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;; 132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;; 132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;; 132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;; 132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;; 132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;; 132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;; 132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;; 132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;; 132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;; 132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;; 132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;; 132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;; 132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;; 132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;; 132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;; 132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;; 132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;; 132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;; 132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;; 132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;; 132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;; 132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;; 132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;; 132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;; 132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;; 132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;; 132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;; 132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;; 132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;; 132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;; 132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;; 132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;; 132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;; 132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;; 132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;; 132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;; 132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;; 132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;; 132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;; 132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;; 132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;; 132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;; 132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;; 132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;; 132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;; 132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;; 132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;; 132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;; 132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;; 132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;; 132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;; 132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;; 132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;; 132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;; 132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;; 132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;; 132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;; 132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;; 132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;; 132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;; 132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;; 132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;; 132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;; 13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;; 13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;; 13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;; 13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;; 13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;; 13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;; 13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;; 13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;; 13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;; 13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;; 1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;; 1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;; 1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;; 1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;; 1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;; 1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;; 13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;; 13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;; 13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;; 13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;; 13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;; 13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;; 13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;; 13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;; 13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;; 13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;; 1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;; 1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;; 1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;; 1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;; 1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;; 1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;; 13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;; 13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;; 13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;; 13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;; 13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;; 13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;; 13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;; 13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;; 13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;; 13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;; 1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;; 1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;; 1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;; 1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;; 1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;; 1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;; 13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;; 13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;; 13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;; 13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;; 13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;; 13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;; 13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;; 13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;; 13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;; 13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;; 1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;; 1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;; 1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;; 1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;; 1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;; 1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;; 13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;; 13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;; 13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;; 13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;; 13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;; 13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;; 13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;; 13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;; 13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;; 13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;; 1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;; 1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;; 1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;; 1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;; 1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;; 1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;; 13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;; 13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;; 13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;; 13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;; 13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;; 13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;; 13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;; 13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;; 13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;; 13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;; 1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;; 1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;; 1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;; 1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;; 1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;; 1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;; 13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;; 13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;; 13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;; 13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;; 13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;; 13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;; 13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;; 13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;; 13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;; 13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;; 1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;; 1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;; 1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;; 1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;; 1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;; 1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;; 13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;; 13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;; 13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;; 13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;; 13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;; 13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;; 13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;; 13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;; 13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;; 13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;; 1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;; 1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;; 1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;; 1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;; 1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;; 1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;; 13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;; 13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;; 13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;; 13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;; 13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;; 13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;; 13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;; 13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;; 13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;; 13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;; 1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;; 1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;; 1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;; 1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;; 1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;; 1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;; 13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;; 13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;; 13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;; 13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;; 13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;; 13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;; 13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;; 13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;; 13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;; 13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;; 1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;; 1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;; 1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;; 1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;; 1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;; 1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;; 133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;; 133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;; 133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;; 133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;; 133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;; 133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;; 133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;; 133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;; 133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;; 133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;; 133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;; 133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;; 133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;; 133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;; 133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;; 133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;; 133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;; 133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;; 133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;; 133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;; 133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;; 133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;; 133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;; 133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;; 133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;; 133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;; 133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;; 133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;; 133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;; 133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;; 133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;; 133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;; 133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;; 133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;; 133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;; 133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;; 133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;; 133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;; 133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;; 133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;; 133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;; 133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;; 133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;; 133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;; 133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;; 133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;; 133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;; 133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;; 133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;; 133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;; 133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;; 133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;; 133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;; 133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;; 133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;; 133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;; 133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;; 133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;; 133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;; 133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;; 133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;; 133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;; 133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;; 133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;; 133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;; 133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;; 133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;; 133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;; 133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;; 133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;; 133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;; 133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;; 133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;; 133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;; 133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;; 133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;; 133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;; 133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;; 133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;; 133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;; 133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;; 133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;; 133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;; 133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;; 133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;; 133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;; 133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;; 133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;; 133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;; 133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;; 133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;; 133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;; 133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;; 133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;; 133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;; 133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;; 13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;; 13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;; 13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;; 13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;; 13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;; 13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;; 13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;; 13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;; 13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;; 13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;; 1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;; 1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;; 1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;; 1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;; 1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;; 1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;; 13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;; 13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;; 13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;; 13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;; 13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;; 13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;; 13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;; 13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;; 13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;; 13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;; 1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;; 1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;; 1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;; 1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;; 1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;; 1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;; 13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;; 13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;; 13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;; 13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;; 13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;; 13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;; 13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;; 13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;; 13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;; 13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;; 1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;; 1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;; 1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; 1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; 1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; 1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; 1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; 1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; 1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; 1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; 1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; 1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; 1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; 1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; 1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; 1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; 1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; 1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; 1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; 1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; 1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; 1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; 1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; 1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; 1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; 1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; 1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; 1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; 1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; 1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; 1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; 1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; 1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; 1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; 1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; 1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; 1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; 1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; 1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; 1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; 1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; 1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; 1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; 1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; 1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; 1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; 1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; 1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; 1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; 1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; 1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; 1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; 1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; 1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; 1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; 1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; 1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; 1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; 1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; 1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; 1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; 1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; 1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; 1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; 1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; 1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; 1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; 1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; 1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; 1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; 1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; 1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; 1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; 1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; 1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; 1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; 1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; 1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; 1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; 1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; 1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; 1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; 1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; 1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; 1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; 1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; 1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; 1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; 1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; 1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; 1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; 1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; 1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; 1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; 1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; 1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; 1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; 1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; 1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; 1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; 1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; 1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; 1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; 1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; 1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; 1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; 1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; 1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; 1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; 1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; 1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; 1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; 1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; 1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; 1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; 1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; 1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; 1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; 1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; 1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; 1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; 1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; 1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; 1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; 1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; 1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; 1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; 1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; 1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; 1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; 1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; 1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; 1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; 1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; 1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; 1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; 1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; 1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; 1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; 1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; 1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; 1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; 1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; 1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; 1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; 1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; 1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; 1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; 1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; 1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; 1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; 1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; 1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; 1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; 1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; 1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; 1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; 1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; 1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; 1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; 1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; 1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; 1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; 1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; 1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; 1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; 1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; 1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; 1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; 1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; 1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; 1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; 1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; 1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; 1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; 1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; 1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; 1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; 1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; 1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; 1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; 1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; 1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; 1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; 1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; 1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; 1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; 1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; 1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; 1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; 1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; 1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; 1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; 1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; 1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; 1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; 1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; 1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; 1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; 1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; 1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; 1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; 1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; 1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; 1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; 1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; 1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; 1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; 1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; 1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; 1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; 1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; 1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; 1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; 1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; 1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; 1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; 1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; 1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; 1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; 1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; 1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; 1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; 1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; 1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; 1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; 1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; 1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; 1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; 1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; 1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; 1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; 1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; 1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; 1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; 1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; 1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; 1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; 1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; 1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; 1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; 1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;; 1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; 1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; 1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; 1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; 1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; 1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; 1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; 1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; 1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; 1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; 1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; 1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; 1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; 1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; 1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; 1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; 1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; 1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; 1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; 1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; 1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; 1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; 1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; 1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; 1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; 1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; 1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; 1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; 1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; 1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; 1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; 1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; 1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; 1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; 1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; 1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; 1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; 1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; 1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; 1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; 1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; 1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; 1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; 1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; 1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; 1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; 1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; 1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; 1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; 1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; 1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; 1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; 1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; 1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; 1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; 1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; 1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; 1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; 1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; 1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; 1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; 1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; 1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; 1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; 1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; 1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; 1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; 1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; 1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; 1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; 1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; 1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; 1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; 1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; 1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; 1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; 1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; 1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; 1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; 1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; 1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; 1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; 1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; 1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; 1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; 1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; 1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; 1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; 1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; 1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; 1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; 1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; 1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; 1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; 1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; 1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; 1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; 1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; 1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; 1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; 1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; 1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; 1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; 1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; 1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; 1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; 1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; 1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; 1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; 1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; 1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; 1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; 1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; 1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; 1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; 1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; 1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; 1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; 1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; 1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; 1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; 1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; 1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; 1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; 1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; 1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; 1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; 1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; 1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; 1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; 1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; 1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; 1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; 1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; 1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; 1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; 1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; 1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; 1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; 1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; 1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; 1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; 1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; 1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; 1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; 1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; 1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; 1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; 1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; 1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; 1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; 1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; 1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; 1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; 1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; 1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; 1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;; 1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;; 1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;; 1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;; 1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;; 1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;; 1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;; 1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;; 1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;; 1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;; 1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;; 1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;; 1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;; 1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;; 1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;; 1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;; 1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;; 1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;; 1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;; 1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;; 1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;; 1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;; 1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;; 1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;; 1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;; 1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;; 1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;; 1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;; 1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;; 1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;; 1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;; 1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;; 1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;; 1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;; 1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;; 1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;; 1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;; 1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;; 1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;; 1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;; 1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;; 1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;; 1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;; 1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;; 1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;; 1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;; 1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;; 1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;; 1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;; 1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;; 1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;; 1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;; 1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;; 1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;; 1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;; 1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;; 1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;; 1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;; 1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;; 1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;; 1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;; 1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;; 1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;; 1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;; 1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;; 1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;; 1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;; 1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;; 1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;; 1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;; 1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;; 1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;; 1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;; 1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;; 1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;; 1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;; 1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;; 1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;; 1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;; 1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;; 1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;; 1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;; 1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;; 1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;; 1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;; 1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;; 1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;; 1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;; 1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;; 1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;; 1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;; 1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;; 1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;; 1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;; 1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;; 1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;; 1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;; 1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;; 1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;; 1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;; 1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;; 1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;; 1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;; 1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;; 1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;; 1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;; 1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;; 1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;; 1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;; 1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;; 1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;; 1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;; 1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;; 1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;; 1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;; 1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;; 1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;; 1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;; 1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;; 1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;; 1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;; 1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;; 1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;; 1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;; 1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;; 1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;; 1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;; 1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;; 1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L; 0131;;;;N;;;;; 1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L; 0237;;;;N;;;;; 1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L; 03DC;;;;N;;;;; 1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L; 03DD;;;;N;;;;; 1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;; 1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;; 1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;; 1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;; 1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;; 1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;; 1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;; 1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;; 1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;; 1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;; 1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;; 1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;; 1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;; 1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;; 1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;; 1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;; 1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;; 1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;; 1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;; 1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;; 1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;; 1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;; 1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;; 1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;; 1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;; 1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;; 1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;; 1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;; 1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;; 1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;; 1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;; 1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;; 1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;; 1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;; 1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;; 1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;; 1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;; 1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;; 1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;; 1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;; 1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;; 1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;; 1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;; 1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;; 1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;; 1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;; 1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;; 1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;; 1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;; 1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;; 1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;; 1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;; 1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;; 1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;; 1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;; 1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;; 1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;; 1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;; 1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;; 1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;; 1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;; 1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;; 1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;; 1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;; 1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;; 1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;; 1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;; 1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;; 1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;; 1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;; 1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;; 1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;; 1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;; 1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;; 1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;; 1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;; 1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;; 1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;; 1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;; 1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;; 1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;; 1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;; 1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;; 1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;; 1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;; 1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;; 1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;; 1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;; 1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;; 1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;; 1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;; 1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;; 1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;; 1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;; 1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;; 1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;; 1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;; 1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;; 1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;; 1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;; 1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;; 1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;; 1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;; 1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;; 1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;; 1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;; 1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;; 1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;; 1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;; 1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;; 1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;; 1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;; 1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;; 1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;; 1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;; 1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;; 1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; 1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; 1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; 1F100;DIGIT ZERO FULL STOP;No;0;EN; 0030 002E;;0;0;N;;;;; 1F101;DIGIT ZERO COMMA;No;0;EN; 0030 002C;;0;0;N;;;;; 1F102;DIGIT ONE COMMA;No;0;EN; 0031 002C;;1;1;N;;;;; 1F103;DIGIT TWO COMMA;No;0;EN; 0032 002C;;2;2;N;;;;; 1F104;DIGIT THREE COMMA;No;0;EN; 0033 002C;;3;3;N;;;;; 1F105;DIGIT FOUR COMMA;No;0;EN; 0034 002C;;4;4;N;;;;; 1F106;DIGIT FIVE COMMA;No;0;EN; 0035 002C;;5;5;N;;;;; 1F107;DIGIT SIX COMMA;No;0;EN; 0036 002C;;6;6;N;;;;; 1F108;DIGIT SEVEN COMMA;No;0;EN; 0037 002C;;7;7;N;;;;; 1F109;DIGIT EIGHT COMMA;No;0;EN; 0038 002C;;8;8;N;;;;; 1F10A;DIGIT NINE COMMA;No;0;EN; 0039 002C;;9;9;N;;;;; 1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L; 0028 0041 0029;;;;N;;;;; 1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L; 0028 0042 0029;;;;N;;;;; 1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L; 0028 0043 0029;;;;N;;;;; 1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L; 0028 0044 0029;;;;N;;;;; 1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L; 0028 0045 0029;;;;N;;;;; 1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L; 0028 0046 0029;;;;N;;;;; 1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L; 0028 0047 0029;;;;N;;;;; 1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L; 0028 0048 0029;;;;N;;;;; 1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L; 0028 0049 0029;;;;N;;;;; 1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L; 0028 004A 0029;;;;N;;;;; 1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L; 0028 004B 0029;;;;N;;;;; 1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L; 0028 004C 0029;;;;N;;;;; 1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L; 0028 004D 0029;;;;N;;;;; 1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L; 0028 004E 0029;;;;N;;;;; 1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L; 0028 004F 0029;;;;N;;;;; 1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L; 0028 0050 0029;;;;N;;;;; 1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L; 0028 0051 0029;;;;N;;;;; 1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L; 0028 0052 0029;;;;N;;;;; 1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L; 0028 0053 0029;;;;N;;;;; 1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L; 0028 0054 0029;;;;N;;;;; 1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L; 0028 0055 0029;;;;N;;;;; 1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L; 0028 0056 0029;;;;N;;;;; 1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L; 0028 0057 0029;;;;N;;;;; 1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L; 0028 0058 0029;;;;N;;;;; 1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L; 0028 0059 0029;;;;N;;;;; 1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L; 0028 005A 0029;;;;N;;;;; 1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L; 3014 0053 3015;;;;N;;;;; 1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; 1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; 1F12D;CIRCLED CD;So;0;L; 0043 0044;;;;N;;;;; 1F12E;CIRCLED WZ;So;0;L; 0057 005A;;;;N;;;;; 1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;; 1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;; 1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;; 1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;; 1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;; 1F14A;SQUARED HV;So;0;L; 0048 0056;;;;N;;;;; 1F14B;SQUARED MV;So;0;L; 004D 0056;;;;N;;;;; 1F14C;SQUARED SD;So;0;L; 0053 0044;;;;N;;;;; 1F14D;SQUARED SS;So;0;L; 0053 0053;;;;N;;;;; 1F14E;SQUARED PPV;So;0;L; 0050 0050 0056;;;;N;;;;; 1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; 1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; 1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; 1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; 1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; 1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; 1F190;SQUARE DJ;So;0;L; 0044 004A;;;;N;;;;; 1F200;SQUARE HIRAGANA HOKA;So;0;L; 307B 304B;;;;N;;;;; 1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L; 624B;;;;N;;;;; 1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L; 5B57;;;;N;;;;; 1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L; 53CC;;;;N;;;;; 1F213;SQUARED KATAKANA DE;So;0;L; 30C7;;;;N;;;;; 1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 4E8C;;;;N;;;;; 1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L; 591A;;;;N;;;;; 1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L; 89E3;;;;N;;;;; 1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L; 5929;;;;N;;;;; 1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L; 4EA4;;;;N;;;;; 1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L; 6620;;;;N;;;;; 1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L; 7121;;;;N;;;;; 1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L; 6599;;;;N;;;;; 1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L; 524D;;;;N;;;;; 1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L; 5F8C;;;;N;;;;; 1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L; 518D;;;;N;;;;; 1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L; 65B0;;;;N;;;;; 1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L; 521D;;;;N;;;;; 1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L; 7D42;;;;N;;;;; 1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L; 751F;;;;N;;;;; 1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L; 8CA9;;;;N;;;;; 1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L; 58F0;;;;N;;;;; 1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L; 5439;;;;N;;;;; 1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L; 6F14;;;;N;;;;; 1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L; 6295;;;;N;;;;; 1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L; 6355;;;;N;;;;; 1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L; 4E00;;;;N;;;;; 1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 4E09;;;;N;;;;; 1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L; 904A;;;;N;;;;; 1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L; 5DE6;;;;N;;;;; 1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L; 4E2D;;;;N;;;;; 1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L; 53F3;;;;N;;;;; 1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L; 6307;;;;N;;;;; 1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L; 8D70;;;;N;;;;; 1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 6253;;;;N;;;;; 1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L; 3014 672C 3015;;;;N;;;;; 1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 3014 4E09 3015;;;;N;;;;; 1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 3014 4E8C 3015;;;;N;;;;; 1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L; 3014 5B89 3015;;;;N;;;;; 1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L; 3014 70B9 3015;;;;N;;;;; 1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 3014 6253 3015;;;;N;;;;; 1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L; 3014 76D7 3015;;;;N;;;;; 1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L; 3014 52DD 3015;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L; 3014 6557 3015;;;;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; 2A6D6;;Lo;0;L;;;;;N;;;;; 2A700;;Lo;0;L;;;;;N;;;;; 2B734;;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; 2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; 2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; 2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; 2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; 2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; 2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; 2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; 2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; 2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; 2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; 2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; 2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; 2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; 2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; 2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; 2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; 2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; 2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; 2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; 2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; 2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; 2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; 2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; 2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; 2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; 2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; 2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; 2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; 2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; 2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; 2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; 2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; 2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; 2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; 2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; 2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; 2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; 2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; 2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; 2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; 2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; 2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; 2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; 2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; 2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; 2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; 2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; 2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; 2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; 2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; 2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; 2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; 2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; 2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; 2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; 2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; 2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; 2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; 2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; 2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; 2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; 2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; 2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; 2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; 2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; 2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; 2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; 2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; 2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; 2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; 2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; 2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; 2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; 2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; 2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; 2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; 2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; 2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; 2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; 2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; 2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; 2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; 2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; 2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; 2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; 2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; 2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; 2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; 2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; 2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; 2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; 2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; 2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; 2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; 2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; 2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; 2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; 2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; 2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; 2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; 2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; 2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;; 2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; 2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; 2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; 2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; 2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; 2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; 2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; 2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; 2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; 2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; 2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; 2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;; 2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; 2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; 2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; 2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; 2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; 2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; 2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; 2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; 2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; 2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; 2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; 2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; 2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; 2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; 2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; 2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; 2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; 2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; 2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; 2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; 2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; 2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; 2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; 2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; 2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; 2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; 2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; 2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;; 2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; 2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; 2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; 2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; 2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; 2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; 2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; 2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; 2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; 2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; 2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; 2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; 2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; 2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; 2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; 2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; 2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; 2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; 2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; 2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; 2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; 2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; 2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; 2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; 2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; 2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; 2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; 2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; 2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; 2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; 2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; 2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; 2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; 2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; 2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; 2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; 2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; 2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; 2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; 2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; 2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; 2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; 2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; 2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; 2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; 2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; 2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; 2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; 2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; 2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; 2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; 2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; 2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; 2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; 2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; 2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; 2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; 2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; 2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; 2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; 2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; 2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; 2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; 2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; 2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; 2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; 2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; 2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; 2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; 2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; 2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; 2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; 2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; 2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; 2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; 2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; 2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; 2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; 2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; 2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; 2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; 2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; 2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; 2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; 2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; 2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; 2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; 2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; 2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; 2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; 2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; 2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; 2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; 2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; 2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; 2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; 2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; 2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; 2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; 2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; 2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; 2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; 2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; 2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; 2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; 2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; 2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; 2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; 2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; 2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; 2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; 2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; 2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; 2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; 2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; 2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; 2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; 2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; 2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; 2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; 2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; 2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; 2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; 2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; 2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; 2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; 2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; 2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; 2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; 2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; 2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; 2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; 2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; 2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; 2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; 2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; 2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; 2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; 2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; 2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; 2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; 2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; 2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;; 2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; 2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; 2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; 2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; 2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; 2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; 2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; 2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; 2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; 2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; 2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; 2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; 2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; 2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; 2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; 2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; 2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; 2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; 2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; 2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; 2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; 2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; 2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; 2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; 2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; 2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; 2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; 2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; 2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; 2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; 2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; 2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; 2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; 2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; 2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; 2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; 2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; 2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; 2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; 2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; 2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; 2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; 2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; 2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; 2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; 2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; 2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; 2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; 2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; 2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; 2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; 2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; 2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; 2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; 2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; 2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; 2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; 2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; 2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; 2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; 2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; 2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; 2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; 2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;; 2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; 2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; 2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; 2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; 2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; 2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; 2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; 2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; 2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; 2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; 2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; 2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; 2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; 2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; 2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; 2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; 2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; 2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; 2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; 2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; 2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; 2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; 2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; 2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; 2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; 2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; 2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; 2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; 2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; 2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; 2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; 2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; 2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; 2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; 2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; 2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; 2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; 2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; 2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; 2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; 2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; 2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; 2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; 2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; 2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; 2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; 2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; 2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; 2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; 2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; 2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; 2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; 2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; 2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; 2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; 2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; 2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; 2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; 2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; 2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; 2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; 2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; 2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; 2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; 2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; 2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; 2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; 2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; 2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; 2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; 2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; 2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; 2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; 2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; 2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; 2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; 2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; 2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; 2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; 2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; 2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; 2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; 2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; 2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; 2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; 2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; 2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; 2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; 2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; 2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; 2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; 2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; 2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; 2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; 2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; 2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;; 2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; 2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; 2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; 2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; 2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; 2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; 2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; 2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; 2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; 2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; 2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; 2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; 2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; 2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; 2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; 2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; 2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; 2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; 2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; 2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; 2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; 2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; 2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; 2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; 2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; 2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; 2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; 2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; 2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; 2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; 2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; 2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; 2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; 2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; 2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; 2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; 2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; 2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; 2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; 2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; 2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; 2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; 2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; 2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; 2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; 2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; 2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; 2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; 2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; 2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; 2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; 2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; 2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; 2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; 2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; 2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; 2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; 2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; 2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; 2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; 2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; 2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; 2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; 2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; 2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; 2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; 2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; 2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; 2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; 2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; 2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; 2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; 2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; 2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; 2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; 2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; 2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; 2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; 2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; 2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; 2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; 2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; 2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; 2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; 2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; 2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; 2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; 2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; 2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; 2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; 2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; 2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; 2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; 2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;; E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;; E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;; E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;; E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;; E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;; E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;; E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;; E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;; E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;; E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;; E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;; E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;; E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;; E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;; E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;; E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;; E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;; E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;; E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;; E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;; E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;; E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;; E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;; E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;; E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;; E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;; E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;; E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;; E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;; E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;; E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;; E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;; E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;; E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;; E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;; E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;; E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;; E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;; E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;; E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;; E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;; E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;; E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;; E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;; E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;; E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;; E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;; E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;; E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;; E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;; E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;; E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;; E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;; E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;; E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;; E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;; E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;; E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;; E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;; E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;; E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;; E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;; E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;; E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;; E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;; E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;; E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;; E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;; E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;; E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;; E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;; E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;; E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;; E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;; E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;; E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;; E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;; E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;; E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;; E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;; E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;; E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;; E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;; E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;; E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;; E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;; E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;; E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;; E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;; E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;; E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;; E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;; E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;; E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;; E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;; E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;; E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;; E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;; E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;; E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;; E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;; E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;; E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;; E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;; E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;; E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;; E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;; E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;; E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;; E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;; E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;; E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;; E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;; E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;; E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;; E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;; E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;; E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;; E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;; E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;; E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;; E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;; E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;; E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;; E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;; E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;; E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;; E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;; E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;; E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;; E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;; E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;; E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;; E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;; E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;; E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;; E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;; E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;; E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;; E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;; E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;; E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;; E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;; E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;; E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;; E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;; E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;; E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;; E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;; E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;; E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;; E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;; E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;; E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;; E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;; E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;; E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;; E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;; E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;; E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;; E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;; E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;; E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;; E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;; E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;; E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;; E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;; E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;; E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;; E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;; E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;; E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;; E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;; E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;; E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;; E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;; E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;; E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;; E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;; E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;; E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;; E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;; E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;; E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;; E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;; E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;; E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;; E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;; E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;; E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;; E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;; E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;; E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;; E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;; E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;; E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;; E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;; E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;; E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;; E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;; E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;; E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;; E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;; E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;; E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;; E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;; E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;; E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;; E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;; E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;; E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;; E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;; E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;; E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;; E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;; E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;; E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;; E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;; E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;; E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;; E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;; E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;; E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;; E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;; E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;; E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;; E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;; E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;; E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;; E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;; E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;; E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;; E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;; E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;; E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;; E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;; E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;; E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;; E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;; F0000;;Co;0;L;;;;;N;;;;; FFFFD;;Co;0;L;;;;;N;;;;; 100000;;Co;0;L;;;;;N;;;;; 10FFFD;;Co;0;L;;;;;N;;;;; openocd-0.9.0/jimtcl/stdlib.tcl0000644000175000017500000001110712516456444013352 00000000000000# Implements script-based standard commands for Jim Tcl # Creates an anonymous procedure proc lambda {arglist args} { tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args } proc lambda.finalizer {name val} { rename $name {} } # Like alias, but creates and returns an anonyous procedure proc curry {args} { alias [ref {} function lambda.finalizer] {*}$args } # Returns the given argument. # Useful with 'local' as follows: # proc a {} {...} # local function a # # set x [lambda ...] # local function $x # proc function {value} { return $value } # Returns a live stack trace as a list of proc filename line ... # with 3 entries for each stack frame (proc), # (deepest level first) proc stacktrace {{skip 0}} { set trace {} incr skip foreach level [range $skip [info level]] { lappend trace {*}[info frame -$level] } return $trace } # Returns a human-readable version of a stack trace proc stackdump {stacktrace} { set lines {} foreach {l f p} [lreverse $stacktrace] { set line {} if {$p ne ""} { append line "in procedure '$p' " if {$f ne ""} { append line "called " } } if {$f ne ""} { append line "at file \"$f\", line $l" } if {$line ne ""} { lappend lines $line } } join $lines \n } # Sort of replacement for $::errorInfo # Usage: errorInfo error ?stacktrace? proc errorInfo {msg {stacktrace ""}} { if {$stacktrace eq ""} { # By default add the stack backtrace and the live stacktrace set stacktrace [info stacktrace] # omit the procedure 'errorInfo' from the stack lappend stacktrace {*}[stacktrace 1] } lassign $stacktrace p f l if {$f ne ""} { set result "$f:$l: Error: " } append result "$msg\n" append result [stackdump $stacktrace] # Remove the trailing newline string trim $result } # Needs to be set up by the container app (e.g. jimsh) # Returns the empty string if unknown proc {info nameofexecutable} {} { if {[exists ::jim::exe]} { return $::jim::exe } } # Script-based implementation of 'dict with' proc {dict with} {&dictVar {args key} script} { set keys {} foreach {n v} [dict get $dictVar {*}$key] { upvar $n var_$n set var_$n $v lappend keys $n } catch {uplevel 1 $script} msg opts if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} { foreach n $keys { if {[info exists var_$n]} { dict set dictVar {*}$key $n [set var_$n] } else { dict unset dictVar {*}$key $n } } } return {*}$opts $msg } # Script-based implementation of 'dict update' proc {dict update} {&varName args script} { set keys {} foreach {n v} $args { upvar $v var_$v if {[dict exists $varName $n]} { set var_$v [dict get $varName $n] } } catch {uplevel 1 $script} msg opts if {[info exists varName]} { foreach {n v} $args { if {[info exists var_$v]} { dict set varName $n [set var_$v] } else { dict unset varName $n } } } return {*}$opts $msg } # Script-based implementation of 'dict merge' # This won't get called in the trivial case of no args proc {dict merge} {dict args} { foreach d $args { # Check for a valid dict dict size $d foreach {k v} $d { dict set dict $k $v } } return $dict } proc {dict replace} {dictionary {args {key value}}} { if {[llength ${key value}] % 2} { tailcall {dict replace} } tailcall dict merge $dictionary ${key value} } # Script-based implementation of 'dict lappend' proc {dict lappend} {varName key {args value}} { upvar $varName dict if {[exists dict] && [dict exists $dict $key]} { set list [dict get $dict $key] } lappend list {*}$value dict set dict $key $list } # Script-based implementation of 'dict append' proc {dict append} {varName key {args value}} { upvar $varName dict if {[exists dict] && [dict exists $dict $key]} { set str [dict get $dict $key] } append str {*}$value dict set dict $key $str } # Script-based implementation of 'dict incr' proc {dict incr} {varName key {increment 1}} { upvar $varName dict if {[exists dict] && [dict exists $dict $key]} { set value [dict get $dict $key] } incr value $increment dict set dict $key $value } # Script-based implementation of 'dict remove' proc {dict remove} {dictionary {args key}} { foreach k $key { dict unset dictionary $k } return $dictionary } # Script-based implementation of 'dict values' proc {dict values} {dictionary {pattern *}} { dict keys [lreverse $dictionary] $pattern } # Script-based implementation of 'dict for' proc {dict for} {vars dictionary script} { if {[llength $vars] != 2} { return -code error "must have exactly two variable names" } dict size $dictionary tailcall foreach $vars $dictionary $script } openocd-0.9.0/jimtcl/jim-array.c0000644000175000017500000001757312516456444013441 00000000000000/* * Implements the array command for jim * * (c) 2008 Steve Bennett * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. * * Based on code originally from Tcl 6.7: * * Copyright 1987-1991 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include #include #include #include #include #include static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* Just a regular [info exists] */ Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); return JIM_OK; } static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); Jim_Obj *patternObj; if (!objPtr) { return JIM_OK; } patternObj = (argc == 1) ? NULL : argv[1]; /* Optimise the "all" case */ if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { /* A list with an even number of elements */ Jim_SetResult(interp, objPtr); return JIM_OK; } } /* Return a list of keys and values where the keys match the pattern */ return Jim_DictValues(interp, objPtr, patternObj); } static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (!objPtr) { return JIM_OK; } return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); } static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; int len; Jim_Obj *resultObj; Jim_Obj *objPtr; Jim_Obj **dictValuesObj; if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { /* Unset the whole array */ Jim_UnsetVariable(interp, argv[0], JIM_NONE); return JIM_OK; } objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (objPtr == NULL) { /* Doesn't exist, so nothing to do */ return JIM_OK; } if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { return JIM_ERR; } /* Create a new object with the values which don't match */ resultObj = Jim_NewDictObj(interp, NULL, 0); for (i = 0; i < len; i += 2) { if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); } } Jim_Free(dictValuesObj); Jim_SetVariable(interp, argv[0], resultObj); return JIM_OK; } static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr; int len = 0; /* Not found means zero length */ objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (objPtr) { len = Jim_DictSize(interp, objPtr); if (len < 0) { return JIM_ERR; } } Jim_SetResultInt(interp, len); return JIM_OK; } static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (objPtr) { return Jim_DictInfo(interp, objPtr); } Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL); return JIM_ERR; } static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; int len; Jim_Obj *listObj = argv[1]; Jim_Obj *dictObj; len = Jim_ListLength(interp, listObj); if (len % 2) { Jim_SetResultString(interp, "list must have an even number of elements", -1); return JIM_ERR; } dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); if (!dictObj) { /* Doesn't exist, so just set the list directly */ return Jim_SetVariable(interp, argv[0], listObj); } else if (Jim_DictSize(interp, dictObj) < 0) { return JIM_ERR; } if (Jim_IsShared(dictObj)) { dictObj = Jim_DuplicateObj(interp, dictObj); } for (i = 0; i < len; i += 2) { Jim_Obj *nameObj; Jim_Obj *valueObj; Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE); Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE); Jim_DictAddElement(interp, dictObj, nameObj, valueObj); } return Jim_SetVariable(interp, argv[0], dictObj); } static const jim_subcmd_type array_command_table[] = { { "exists", "arrayName", array_cmd_exists, 1, 1, /* Description: Does array exist? */ }, { "get", "arrayName ?pattern?", array_cmd_get, 1, 2, /* Description: Array contents as name value list */ }, { "names", "arrayName ?pattern?", array_cmd_names, 1, 2, /* Description: Array keys as a list */ }, { "set", "arrayName list", array_cmd_set, 2, 2, /* Description: Set array from list */ }, { "size", "arrayName", array_cmd_size, 1, 1, /* Description: Number of elements in array */ }, { "stat", "arrayName", array_cmd_stat, 1, 1, /* Description: Print statistics about an array */ }, { "unset", "arrayName ?pattern?", array_cmd_unset, 1, 2, /* Description: Unset elements of an array */ }, { NULL } }; int Jim_arrayInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG)) return JIM_ERR; Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL); return JIM_OK; } openocd-0.9.0/jimtcl/configure.ac0000644000175000017500000000005412315602574013644 00000000000000# Dummy configure.ac to make automake happy openocd-0.9.0/jimtcl/jim-syslog.c0000644000175000017500000001164212516456444013632 00000000000000/* Syslog interface for tcl * Copyright Victor Wagner at * http://www.ice.ru/~vitus/works/tcl.html#syslog * * Slightly modified by Steve Bennett * Ported to Jim by Steve Bennett */ #include #include #include typedef struct { int logOpened; int facility; int options; char ident[32]; } SyslogInfo; #ifndef LOG_AUTHPRIV # define LOG_AUTHPRIV LOG_AUTH #endif static const char * const facilities[] = { [LOG_AUTHPRIV] = "authpriv", [LOG_CRON] = "cron", [LOG_DAEMON] = "daemon", [LOG_KERN] = "kernel", [LOG_LPR] = "lpr", [LOG_MAIL] = "mail", [LOG_NEWS] = "news", [LOG_SYSLOG] = "syslog", [LOG_USER] = "user", [LOG_UUCP] = "uucp", [LOG_LOCAL0] = "local0", [LOG_LOCAL1] = "local1", [LOG_LOCAL2] = "local2", [LOG_LOCAL3] = "local3", [LOG_LOCAL4] = "local4", [LOG_LOCAL5] = "local5", [LOG_LOCAL6] = "local6", [LOG_LOCAL7] = "local7", }; static const char * const priorities[] = { [LOG_EMERG] = "emerg", [LOG_ALERT] = "alert", [LOG_CRIT] = "crit", [LOG_ERR] = "error", [LOG_WARNING] = "warning", [LOG_NOTICE] = "notice", [LOG_INFO] = "info", [LOG_DEBUG] = "debug", }; /** * Deletes the syslog command. */ static void Jim_SyslogCmdDelete(Jim_Interp *interp, void *privData) { SyslogInfo *info = (SyslogInfo *) privData; if (info->logOpened) { closelog(); } Jim_Free(info); } /* Syslog_Log - * implements syslog tcl command. General format: syslog ?options? level text * options -facility -ident -options * * syslog ?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? text */ int Jim_SyslogCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int priority = LOG_INFO; int i = 1; SyslogInfo *info = Jim_CmdPrivData(interp); if (argc <= 1) { wrongargs: Jim_WrongNumArgs(interp, 1, argv, "?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? message"); return JIM_ERR; } while (i < argc - 1) { if (Jim_CompareStringImmediate(interp, argv[i], "-facility")) { int entry = Jim_FindByName(Jim_String(argv[i + 1]), facilities, sizeof(facilities) / sizeof(*facilities)); if (entry < 0) { Jim_SetResultString(interp, "Unknown facility", -1); return JIM_ERR; } if (info->facility != entry) { info->facility = entry; if (info->logOpened) { closelog(); info->logOpened = 0; } } } else if (Jim_CompareStringImmediate(interp, argv[i], "-options")) { long tmp; if (Jim_GetLong(interp, argv[i + 1], &tmp) == JIM_ERR) { return JIM_ERR; } info->options = tmp; if (info->logOpened) { closelog(); info->logOpened = 0; } } else if (Jim_CompareStringImmediate(interp, argv[i], "-ident")) { strncpy(info->ident, Jim_String(argv[i + 1]), sizeof(info->ident)); info->ident[sizeof(info->ident) - 1] = 0; if (info->logOpened) { closelog(); info->logOpened = 0; } } else { break; } i += 2; } /* There should be either 0, 1 or 2 args left */ if (i == argc) { /* No args, but they have set some options, so OK */ return JIM_OK; } if (i < argc - 1) { priority = Jim_FindByName(Jim_String(argv[i]), priorities, sizeof(priorities) / sizeof(*priorities)); if (priority < 0) { Jim_SetResultString(interp, "Unknown priority", -1); return JIM_ERR; } i++; } if (i != argc - 1) { goto wrongargs; } if (!info->logOpened) { if (!info->ident[0]) { Jim_Obj *argv0 = Jim_GetGlobalVariableStr(interp, "argv0", JIM_NONE); if (argv0) { strncpy(info->ident, Jim_String(argv0), sizeof(info->ident)); } else { strcpy(info->ident, "Tcl script"); } info->ident[sizeof(info->ident) - 1] = 0; } openlog(info->ident, info->options, info->facility); info->logOpened = 1; } syslog(priority, "%s", Jim_String(argv[i])); return JIM_OK; } int Jim_syslogInit(Jim_Interp *interp) { SyslogInfo *info; if (Jim_PackageProvide(interp, "syslog", "1.0", JIM_ERRMSG)) return JIM_ERR; info = Jim_Alloc(sizeof(*info)); info->logOpened = 0; info->options = 0; info->facility = LOG_USER; info->ident[0] = 0; Jim_CreateCommand(interp, "syslog", Jim_SyslogCmd, info, Jim_SyslogCmdDelete); return JIM_OK; } openocd-0.9.0/jimtcl/initjimsh.tcl0000644000175000017500000000221312516456444014065 00000000000000# This pseudo-package is loaded from jimsh to add additional # paths to $auto_path and to source ~/.jimrc proc _jimsh_init {} { rename _jimsh_init {} global jim::exe jim::argv0 tcl_interactive auto_path tcl_platform # Stash the result of [info nameofexecutable] now, before a possible [cd] if {[exists jim::argv0]} { if {[string match "*/*" $jim::argv0]} { set jim::exe [file join [pwd] $jim::argv0] } else { foreach path [split [env PATH ""] $tcl_platform(pathSeparator)] { set exec [file join [pwd] [string map {\\ /} $path] $jim::argv0] if {[file executable $exec]} { set jim::exe $exec break } } } } # Add to the standard auto_path lappend p {*}[split [env JIMLIB {}] $tcl_platform(pathSeparator)] if {[exists jim::exe]} { lappend p [file dirname $jim::exe] } lappend p {*}$auto_path set auto_path $p if {$tcl_interactive && [env HOME {}] ne ""} { foreach src {.jimrc jimrc.tcl} { if {[file exists [env HOME]/$src]} { uplevel #0 source [env HOME]/$src break } } } return "" } if {$tcl_platform(platform) eq "windows"} { set jim::argv0 [string map {\\ /} $jim::argv0] } _jimsh_init openocd-0.9.0/jimtcl/make-c-ext.tcl0000644000175000017500000000210712315602574014016 00000000000000#!/usr/bin/env tclsh # Usage: make-c-ext.tcl source.tcl >jim-source.c # Converts a Tcl source file into C source suitable # for loading as a static extension. lassign $argv source if {![string match *.tcl $source]} { error "Source $source is not a .tcl file" } # Read the Tcl source and convert to C # Note that no lines are removed in order to preserve line numbering set sourcelines {} set f [open $source] while {[gets $f buf] >= 0} { # Remove comment lines regsub {^[ \t]*#.*$} $buf "" buf # Escape quotes and backlashes set buf [string map [list \\ \\\\ \" \\"] $buf] lappend sourcelines \"$buf\\n\" } close $f lappend lines {/* autogenerated - do not edit */} lappend lines {#include } set basename [file tail $source] set pkgname [file rootname $basename] lappend lines "int Jim_${pkgname}Init(Jim_Interp *interp)" lappend lines "\{" lappend lines "\tif (Jim_PackageProvide(interp, \"$pkgname\", \"1.0\", JIM_ERRMSG)) return JIM_ERR;" lappend lines "\treturn Jim_EvalSource(interp, \"$basename\", 1, [join $sourcelines \n]);" lappend lines "\}" puts [join $lines \n] openocd-0.9.0/jimtcl/make-bootstrap-jim0000755000175000017500000000575112516456444015030 00000000000000#!/bin/sh # This script writes to stdout, a single source file (e.g. jimsh0.c) # which can be compiled to provide a bootstrap version of jimsh. # e.g. cc -o jimsh0 jimsh0.c makeext() { source="$1" basename=`basename "$source" .tcl` cat < * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. * * Based on code originally from Tcl 6.7: * * Copyright 1987-1991 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include #include #include #include #include #include "jim.h" #include "jimautoconf.h" #include "jim-subcmd.h" /* ----------------------------------------------------------------------------- * Namespace support * ---------------------------------------------------------------------------*/ /** * nsObj is a canonical namespace name (.e.g. "" for root, "abc" for ::abc) * * The given name is appended to the namespace name to produce a complete canonical name. * * e.g. "" "abc" => abc * "" "::abc" => abc * "" "abc::def" => abc::def * "abc" "def" => abc::def * "abc" "::def" => def * */ Jim_Obj *JimCanonicalNamespace(Jim_Interp *interp, Jim_Obj *nsObj, Jim_Obj *nameObj) { Jim_Obj *objPtr; const char *name = Jim_String(nameObj); assert(nameObj->refCount != 0); assert(nsObj->refCount != 0); if (name[0] == ':' && name[1] == ':') { /* Absolute namespace */ while (*++name == ':') { } return Jim_NewStringObj(interp, name, -1); } if (Jim_Length(nsObj) == 0) { /* Relative to the global namespace */ return nameObj; } /* Relative to non-global namespace */ objPtr = Jim_DuplicateObj(interp, nsObj); Jim_AppendString(interp, objPtr, "::", 2); Jim_AppendObj(interp, objPtr, nameObj); return objPtr; } int Jim_CreateNamespaceVariable(Jim_Interp *interp, Jim_Obj *varNameObj, Jim_Obj *targetNameObj) { int rc; Jim_IncrRefCount(varNameObj); Jim_IncrRefCount(targetNameObj); /* push non-namespace vars if in namespace eval? */ rc = Jim_SetVariableLink(interp, varNameObj, targetNameObj, interp->topFramePtr); if (rc == JIM_ERR) { /* This is the only reason the link can fail */ Jim_SetResultFormatted(interp, "can't define \"%#s\": name refers to an element in an array", varNameObj); } Jim_DecrRefCount(interp, varNameObj); Jim_DecrRefCount(interp, targetNameObj); return rc; } /** * Returns the parent of the given namespace. * * ::bob::tom => ::bob * bob::tom => bob * ::bob => :: * bob => "" * :: => "" * "" => "" */ Jim_Obj *Jim_NamespaceQualifiers(Jim_Interp *interp, Jim_Obj *ns) { const char *name = Jim_String(ns); const char *pt = strrchr(name, ':'); if (pt && pt != name && pt[-1] == ':') { return Jim_NewStringObj(interp, name, pt - name - 1); } else { return interp->emptyObj; } } Jim_Obj *Jim_NamespaceTail(Jim_Interp *interp, Jim_Obj *ns) { const char *name = Jim_String(ns); const char *pt = strrchr(name, ':'); if (pt && pt != name && pt[-1] == ':') { return Jim_NewStringObj(interp, pt + 1, -1); } else { return ns; } } static Jim_Obj *JimNamespaceCurrent(Jim_Interp *interp) { Jim_Obj *objPtr = Jim_NewStringObj(interp, "::", 2); Jim_AppendObj(interp, objPtr, interp->framePtr->nsObj); return objPtr; } static int JimVariableCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retcode = JIM_OK; if (argc > 3) { Jim_WrongNumArgs(interp, 1, argv, "name ?value?"); return JIM_ERR; } if (argc > 1) { Jim_Obj *targetNameObj; Jim_Obj *localNameObj; targetNameObj = JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[1]); localNameObj = Jim_NamespaceTail(interp, argv[1]); Jim_IncrRefCount(localNameObj); if (interp->framePtr->level != 0 || Jim_Length(interp->framePtr->nsObj) != 0) { retcode = Jim_CreateNamespaceVariable(interp, localNameObj, targetNameObj); } /* Set the variable via the local name */ if (retcode == JIM_OK && argc > 2) { retcode = Jim_SetVariable(interp, localNameObj, argv[2]); } Jim_DecrRefCount(interp, localNameObj); } return retcode; } /* Used to invoke script-based helpers. * It would be ideal if ensembles were supported in the core */ static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) { Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1); Jim_AppendString(interp, prefixObj, " ", 1); Jim_AppendString(interp, prefixObj, subcmd, -1); return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); } static int JimNamespaceCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *nsObj; Jim_Obj *objPtr; int option; static const char * const options[] = { "eval", "current", "canonical", "qualifiers", "parent", "tail", "delete", "origin", "code", "inscope", "import", "export", "which", "upvar", NULL }; enum { OPT_EVAL, OPT_CURRENT, OPT_CANONICAL, OPT_QUALIFIERS, OPT_PARENT, OPT_TAIL, OPT_DELETE, OPT_ORIGIN, OPT_CODE, OPT_INSCOPE, OPT_IMPORT, OPT_EXPORT, OPT_WHICH, OPT_UPVAR, }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_EVAL: if (argc < 4) { Jim_WrongNumArgs(interp, 2, argv, "name arg ?arg...?"); return JIM_ERR; } if (argc == 4) { objPtr = argv[3]; } else { objPtr = Jim_ConcatObj(interp, argc - 3, argv + 3); } nsObj = JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2]); return Jim_EvalNamespace(interp, objPtr, nsObj); case OPT_CURRENT: if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, JimNamespaceCurrent(interp)); return JIM_OK; case OPT_CANONICAL: if (argc > 4) { Jim_WrongNumArgs(interp, 2, argv, "?current? ?name?"); return JIM_ERR; } if (argc == 2) { Jim_SetResult(interp, interp->framePtr->nsObj); } else if (argc == 3) { Jim_SetResult(interp, JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2])); } else { Jim_SetResult(interp, JimCanonicalNamespace(interp, argv[2], argv[3])); } return JIM_OK; case OPT_QUALIFIERS: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } Jim_SetResult(interp, Jim_NamespaceQualifiers(interp, argv[2])); return JIM_OK; case OPT_EXPORT: return JIM_OK; case OPT_TAIL: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } Jim_SetResult(interp, Jim_NamespaceTail(interp, argv[2])); return JIM_OK; case OPT_PARENT: if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?name?"); return JIM_ERR; } else { const char *name; if (argc == 3) { objPtr = argv[2]; } else { objPtr = interp->framePtr->nsObj; } if (Jim_Length(objPtr) == 0 || Jim_CompareStringImmediate(interp, objPtr, "::")) { return JIM_OK; } objPtr = Jim_NamespaceQualifiers(interp, objPtr); name = Jim_String(objPtr); if (name[0] != ':' || name[1] != ':') { /* Make it fully scoped */ Jim_SetResultString(interp, "::", 2); Jim_AppendObj(interp, Jim_GetResult(interp), objPtr); Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); } else { Jim_SetResult(interp, objPtr); } } return JIM_OK; } /* Implemented as a Tcl helper proc. * Note that calling a proc will change the current namespace, * so helper procs must call [uplevel namespace canon] to get the callers * namespace. */ return Jim_EvalEnsemble(interp, "namespace", options[option], argc - 2, argv + 2); } int Jim_namespaceInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "namespace", "1.0", JIM_ERRMSG)) return JIM_ERR; Jim_CreateCommand(interp, "namespace", JimNamespaceCmd, NULL, NULL); Jim_CreateCommand(interp, "variable", JimVariableCmd, NULL, NULL); return JIM_OK; } openocd-0.9.0/jimtcl/jim-win32.c0000644000175000017500000003272612315602574013254 00000000000000/* * WIN32 extension * * Copyright (C) 2005 Pat Thoyts * * 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. * * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``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 * JIM TCL PROJECT 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. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. */ #include /* Apparently windows.h and cygwin don't mix, but we seem to get * away with it here. Use at your own risk under cygwin */ #if defined(__CYGWIN__) #define WIN32_LEAN_AND_MEAN #include #endif #include #include #include #include #if _MSC_VER >= 1000 #pragma comment(lib, "shell32") #pragma comment(lib, "user32") #pragma comment(lib, "advapi32") #pragma comment(lib, "psapi") #endif /* _MSC_VER >= 1000 */ static Jim_Obj * Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError) { Jim_Obj *msgObj = NULL; char * lpBuffer = NULL; DWORD dwLen = 0; dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL, (char *)&lpBuffer, 0, NULL); if (dwLen < 1) { dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "code 0x%1!08X!%n", 0, LANG_NEUTRAL, (char *)&lpBuffer, 0, (va_list *)&dwError); } msgObj = Jim_NewStringObj(interp, szPrefix, -1); if (dwLen > 0) { char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */ for ( ; p && *p && isspace(UCHAR(*p)); p--) ; *++p = 0; Jim_AppendString(interp, msgObj, ": ", 2); Jim_AppendString(interp, msgObj, lpBuffer, -1); } LocalFree((HLOCAL)lpBuffer); return msgObj; } /* win32.ShellExecute verb file args */ static int Win32_ShellExecute(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { int r; const char *verb, *file, *parm = NULL; char cwd[MAX_PATH + 1]; if (objc < 3 || objc > 4) { Jim_WrongNumArgs(interp, 1, objv, "verb path ?parameters?"); return JIM_ERR; } verb = Jim_String(objv[1]); file = Jim_String(objv[2]); GetCurrentDirectoryA(MAX_PATH + 1, cwd); if (objc == 4) parm = Jim_String(objv[3]); r = (int)ShellExecuteA(NULL, verb, file, parm, cwd, SW_SHOWNORMAL); if (r < 33) Jim_SetResult(interp, Win32ErrorObj(interp, "ShellExecute", GetLastError())); return (r < 33) ? JIM_ERR : JIM_OK; } /* win32.FindWindow title ?class? */ static int Win32_FindWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { const char *title = NULL, *class = NULL; HWND hwnd = NULL; int r = JIM_OK; if (objc < 2 || objc > 3) { Jim_WrongNumArgs(interp, 1, objv, "title ?class?"); return JIM_ERR; } title = Jim_String(objv[1]); if (objc == 3) class = Jim_String(objv[2]); hwnd = FindWindowA(class, title); if (hwnd == NULL) { Jim_SetResult(interp, Win32ErrorObj(interp, "FindWindow", GetLastError())); r = JIM_ERR; } else { Jim_SetResult(interp, Jim_NewIntObj(interp, (long)hwnd)); } return r; } /* win32.CloseWindow windowHandle */ static int Win32_CloseWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { long hwnd; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?"); return JIM_ERR; } if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK) return JIM_ERR; if (!CloseWindow((HWND)hwnd)) { Jim_SetResult(interp, Win32ErrorObj(interp, "CloseWindow", GetLastError())); return JIM_ERR; } return JIM_OK; } static int Win32_GetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)GetActiveWindow())); return JIM_OK; } static int Win32_SetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HWND hwnd, old; int r = JIM_OK; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "windowHandle"); return JIM_ERR; } r = Jim_GetLong(interp, objv[1], (long *)&hwnd); if (r == JIM_OK) { old = SetActiveWindow(hwnd); if (old == NULL) { Jim_SetResult(interp, Win32ErrorObj(interp, "SetActiveWindow", GetLastError())); r = JIM_ERR; } else { Jim_SetResult(interp, Jim_NewIntObj(interp, (long)old)); } } return r; } static int Win32_SetForegroundWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HWND hwnd; int r = JIM_OK; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "windowHandle"); return JIM_ERR; } r = Jim_GetLong(interp, objv[1], (long *)&hwnd); if (r == JIM_OK) { if (!SetForegroundWindow(hwnd)) { Jim_SetResult(interp, Win32ErrorObj(interp, "SetForegroundWindow", GetLastError())); r = JIM_ERR; } } return r; } static int Win32_Beep(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { long freq, duration; int r = JIM_OK; if (objc != 3) { Jim_WrongNumArgs(interp, 1, objv, "freq duration"); return JIM_ERR; } r = Jim_GetLong(interp, objv[1], &freq); if (r == JIM_OK) r = Jim_GetLong(interp, objv[2], &duration); if (freq < 0x25) freq = 0x25; if (freq > 0x7fff) freq = 0x7fff; if (r == JIM_OK) { if (!Beep(freq, duration)) { Jim_SetResult(interp, Win32ErrorObj(interp, "Beep", GetLastError())); r = JIM_ERR; } } return r; } static int Win32_GetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { char name[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = MAX_COMPUTERNAME_LENGTH; int r = JIM_OK; if (objc != 1) { Jim_WrongNumArgs(interp, 1, objv, ""); return JIM_ERR; } if (GetComputerNameA(name, &size)) { Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size); Jim_SetResult(interp, nameObj); } else { Jim_SetResult(interp, Win32ErrorObj(interp, "GetComputerName", GetLastError())); r = JIM_ERR; } return r; } static int Win32_GetUserName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { char name[UNLEN + 1]; DWORD size = UNLEN; int r = JIM_OK; if (objc != 1) { Jim_WrongNumArgs(interp, 1, objv, ""); return JIM_ERR; } if (GetUserNameA(name, &size)) { Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size); Jim_SetResult(interp, nameObj); } else { Jim_SetResult(interp, Win32ErrorObj(interp, "GetUserName", GetLastError())); r = JIM_ERR; } return r; } static int Win32_GetModuleFileName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HMODULE hModule = NULL; char path[MAX_PATH]; DWORD len = 0; if (objc > 2) { Jim_WrongNumArgs(interp, 1, objv, "?moduleid?"); return JIM_ERR; } if (objc == 2) { if (Jim_GetLong(interp, objv[1], (long *)&hModule) != JIM_OK) { return JIM_ERR; } } len = GetModuleFileNameA(hModule, path, MAX_PATH); if (len != 0) { Jim_Obj *pathObj = Jim_NewStringObj(interp, path, len); Jim_SetResult(interp, pathObj); } else { Jim_SetResult(interp, Win32ErrorObj(interp, "GetModuleFileName", GetLastError())); return JIM_ERR; } return JIM_OK; } static int Win32_GetVersion(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { Jim_SetResult(interp, Jim_NewIntObj(interp, GetVersion())); return JIM_OK; } static int Win32_GetTickCount(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { Jim_SetResult(interp, Jim_NewIntObj(interp, GetTickCount())); return JIM_OK; } static int Win32_GetSystemTime(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { Jim_Obj *a[16]; size_t n = 0; SYSTEMTIME t; GetSystemTime(&t); #define JIMADD(name) \ a[n++] = Jim_NewStringObj(interp, #name, -1); \ a[n++] = Jim_NewIntObj(interp, t.w ## name ) JIMADD(Year); JIMADD(Month); JIMADD(DayOfWeek); JIMADD(Day); JIMADD(Hour); JIMADD(Minute); JIMADD(Second); JIMADD(Milliseconds); #undef JIMADD Jim_SetResult(interp, Jim_NewListObj(interp, a, n)); return JIM_OK; } /* function not available on mingw or cygwin */ #if !defined(__MINGW32__) && !defined(__CYGWIN__) // FIX ME: win2k+ so should do version checks really. static int Win32_GetPerformanceInfo(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { Jim_Obj *a[26]; size_t n = 0; PERFORMANCE_INFORMATION pi; if (!GetPerformanceInfo(&pi, sizeof(pi))) { Jim_SetResult(interp, Win32ErrorObj(interp, "GetPerformanceInfo", GetLastError())); return JIM_ERR; } #define JIMADD(name) \ a[n++] = Jim_NewStringObj(interp, #name, -1); \ a[n++] = Jim_NewIntObj(interp, pi. name ) JIMADD(CommitTotal); JIMADD(CommitLimit); JIMADD(CommitPeak); JIMADD(PhysicalTotal); JIMADD(PhysicalAvailable); JIMADD(SystemCache); JIMADD(KernelTotal); JIMADD(KernelPaged); JIMADD(KernelNonpaged); JIMADD(PageSize); JIMADD(HandleCount); JIMADD(ProcessCount); JIMADD(ThreadCount); #undef JIMADD Jim_SetResult(interp, Jim_NewListObj(interp, a, n)); return JIM_OK; } #endif static int Win32_SetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { int r = JIM_OK; const char *name; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "computername"); return JIM_ERR; } name = Jim_String(objv[1]); if (!SetComputerNameA(name)) { Jim_SetResult(interp, Win32ErrorObj(interp, "SetComputerName", GetLastError())); r = JIM_ERR; } return r; } static int Win32_GetModuleHandle(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HMODULE hModule = NULL; const char *name = NULL; if (objc < 1 || objc > 2) { Jim_WrongNumArgs(interp, 1, objv, "?name?"); return JIM_ERR; } if (objc == 2) name = Jim_String(objv[1]); hModule = GetModuleHandleA(name); if (hModule == NULL) { Jim_SetResult(interp, Win32ErrorObj(interp, "GetModuleHandle", GetLastError())); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hModule)); return JIM_OK; } static int Win32_LoadLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HMODULE hLib = NULL; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "path"); return JIM_ERR; } hLib = LoadLibraryA(Jim_String(objv[1])); if (hLib == NULL) { Jim_SetResult(interp, Win32ErrorObj(interp, "LoadLibrary", GetLastError())); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hLib)); return JIM_OK; } static int Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv) { HMODULE hModule = NULL; int r = JIM_OK; if (objc != 2) { Jim_WrongNumArgs(interp, 1, objv, "hmodule"); return JIM_ERR; } r = Jim_GetLong(interp, objv[1], (long *)&hModule); if (r == JIM_OK) { if (!FreeLibrary(hModule)) { Jim_SetResult(interp, Win32ErrorObj(interp, "FreeLibrary", GetLastError())); r = JIM_ERR; } } return r; } /* ---------------------------------------------------------------------- */ int Jim_win32Init(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG)) return JIM_ERR; #define CMD(name) \ Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL) CMD(ShellExecute); CMD(FindWindow); CMD(CloseWindow); CMD(GetActiveWindow); CMD(SetActiveWindow); CMD(SetForegroundWindow); CMD(Beep); CMD(GetComputerName); CMD(SetComputerName); CMD(GetUserName); CMD(GetModuleFileName); CMD(GetVersion); CMD(GetTickCount); CMD(GetSystemTime); #if !defined(__MINGW32__) && !defined(__CYGWIN__) CMD(GetPerformanceInfo); #endif CMD(GetModuleHandle); CMD(LoadLibrary); CMD(FreeLibrary); return JIM_OK; } openocd-0.9.0/jimtcl/sqlite3/0000755000175000017500000000000012526202231013011 500000000000000openocd-0.9.0/jimtcl/sqlite3/Makefile0000644000175000017500000000077212315602574014411 00000000000000# Builds the full sqlite3 extension for Jim Tcl with the sqlite3 amalgamation all: sqlite3.so SQLITE3_OPTS := -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 \ -DSQLITE_ENABLE_STAT3 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_OMIT_INCRBLOB sqlite3.so: jim-sqlite3.c sqlite3.c ./build-ext -Wall -o $@ -I.. -L.. $(SQLITE3_OPTS) $(BUILDOPTS) $^ clean: rm -f *.o *.so # Note that this will only work when not cross compiling test: sqlite3.so ../jimsh test-sqlite3.tcl openocd-0.9.0/jimtcl/sqlite3/README0000644000175000017500000000266112315602574013630 00000000000000Full sqlite3 Extension for Jim Tcl ================================== Author: Steve Bennett Date: Thu 24 Nov 2011 This directory builds a Jim Tcl extension containing a complete sqlite3 implementation and binding. Building -------- Ensure that you have configured and built jim in the source directory, then: $ make ./build-ext -o sqlite3.so -I.. -L.. -DSQLITE_OMIT_LOAD_EXTENSION=1 ... jim-sqlite3.c sqlite3.c Building sqlite3.so from jim-sqlite3.c sqlite3.c Warning: libjim is static. Dynamic module may not work on some platforms. Compile: jim-sqlite3.o Compile: sqlite3.o Link: sqlite3.so Success! Testing ------- $ make test Installing ---------- Copy sqlite3.so to your jim library directory, typically /usr/local/lib/jim or where $JIMLIB points to. Using ----- In your Jim Tcl code, ensure that sqlite3.so is in a directory on $auto_path. Then: package require sqlite3 sqlite3 db test.db ...etc.. Documentation ------------- The Jim Tcl binding is almost exactly identical to the Tcl binding. See http://www.sqlite.org/tclsqlite.html for documentation. Differences: - INCRBLOB is not supported as Jim Tcl does not support channels - No attempt is made to change encoding between Jim Tcl and sqlite - Jim Tcl doesn't differentiate between binary data (bytearray) and string, so only the @field syntax causes a fieldsto be bound as a blob rather than text. - Jim Tcl doesn't have a boolean type openocd-0.9.0/jimtcl/sqlite3/sqlite3.c0000644000175000017500002157041312315602575014511 00000000000000/****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.7.9. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other ** programs, you need this file and the "sqlite3.h" header file that defines ** the programming interface to the SQLite library. (If you do not have ** the "sqlite3.h" header file at hand, you will find a copy embedded within ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif #ifndef SQLITE_API # define SQLITE_API #endif /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any ** system #includes. Hence, this block of code must be the very first ** code in all source files. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: Red Hat 7.2) but you want your code to work ** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in Red Hat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. ** ** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #ifdef _HAVE_SQLITE_CONFIG_H #include "config.h" #endif /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ /************** Begin file sqliteLimit.h *************************************/ /* ** 2007 May 7 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. */ /* ** The maximum length of a TEXT or BLOB in bytes. This also ** limits the size of a row in a table or index. ** ** The hard limit is the ability of a 32-bit signed integer ** to count the size: 2^31-1 or 2147483647. */ #ifndef SQLITE_MAX_LENGTH # define SQLITE_MAX_LENGTH 1000000000 #endif /* ** This is the maximum number of ** ** * Columns in a table ** * Columns in an index ** * Columns in a view ** * Terms in the SET clause of an UPDATE statement ** * Terms in the result set of a SELECT statement ** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. ** * Terms in the VALUES clause of an INSERT statement ** ** The hard upper limit here is 32676. Most database people will ** tell you that in a well-normalized database, you usually should ** not have more than a dozen or so columns in any table. And if ** that is the case, there is no point in having more than a few ** dozen values in any of the other situations described above. */ #ifndef SQLITE_MAX_COLUMN # define SQLITE_MAX_COLUMN 2000 #endif /* ** The maximum length of a single SQL statement in bytes. ** ** It used to be the case that setting this value to zero would ** turn the limit off. That is no longer true. It is not possible ** to turn this limit off. */ #ifndef SQLITE_MAX_SQL_LENGTH # define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* ** The maximum depth of an expression tree. This is limited to ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might ** want to place more severe limits on the complexity of an ** expression. ** ** A value of 0 used to mean that the limit was not enforced. ** But that is no longer true. The limit is now strictly enforced ** at all times. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 #endif /* ** The maximum number of terms in a compound SELECT statement. ** The code generator for compound SELECT statements does one ** level of recursion for each term. A stack overflow can result ** if the number of terms is too large. In practice, most SQL ** never has more than 3 or 4 terms. Use a value of 0 to disable ** any limit on the number of terms in a compount SELECT. */ #ifndef SQLITE_MAX_COMPOUND_SELECT # define SQLITE_MAX_COMPOUND_SELECT 500 #endif /* ** The maximum number of opcodes in a VDBE program. ** Not currently enforced. */ #ifndef SQLITE_MAX_VDBE_OP # define SQLITE_MAX_VDBE_OP 25000 #endif /* ** The maximum number of arguments to an SQL function. */ #ifndef SQLITE_MAX_FUNCTION_ARG # define SQLITE_MAX_FUNCTION_ARG 127 #endif /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE */ #ifndef SQLITE_DEFAULT_CACHE_SIZE # define SQLITE_DEFAULT_CACHE_SIZE 2000 #endif #ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE # define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 #endif /* ** The default number of frames to accumulate in the log file before ** checkpointing the database in WAL mode. */ #ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT # define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 #endif /* ** The maximum number of attached databases. This must be between 0 ** and 62. The upper bound on 62 is because a 64-bit integer bitmap ** is used internally to track attached databases. */ #ifndef SQLITE_MAX_ATTACHED # define SQLITE_MAX_ATTACHED 10 #endif /* ** The maximum value of a ?nnn wildcard that the parser will accept. */ #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 65536. This a limit ** imposed by the use of 16-bit offsets within each page. ** ** Earlier versions of SQLite allowed the user to change this value at ** compile time. This is no longer permitted, on the grounds that it creates ** a library that is technically incompatible with an SQLite library ** compiled with a different limit. If a process operating on a database ** with a page-size of 65536 bytes crashes, then an instance of SQLite ** compiled with the default page-size limit will not be able to rollback ** the aborted transaction. This could lead to database corruption. */ #ifdef SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_PAGE_SIZE #endif #define SQLITE_MAX_PAGE_SIZE 65536 /* ** The default size of a database page. */ #ifndef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE 1024 #endif #if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE # undef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE #endif /* ** Ordinarily, if no value is explicitly provided, SQLite creates databases ** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain ** device characteristics (sector-size and atomic write() support), ** SQLite may choose a larger value. This constant is the maximum value ** SQLite will choose on its own. */ #ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE # define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 #endif #if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_DEFAULT_PAGE_SIZE # define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE #endif /* ** Maximum number of pages in one database file. ** ** This is really just the default value for the max_page_count pragma. ** This value can be lowered (or raised) at run-time using that the ** max_page_count macro. */ #ifndef SQLITE_MAX_PAGE_COUNT # define SQLITE_MAX_PAGE_COUNT 1073741823 #endif /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH # define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 #endif /* ** Maximum depth of recursion for triggers. ** ** A value of 1 means that a trigger program will not be able to itself ** fire any triggers. A value of 0 means that no trigger programs at all ** may be executed. */ #ifndef SQLITE_MAX_TRIGGER_DEPTH # define SQLITE_MAX_TRIGGER_DEPTH 1000 #endif /************** End of sqliteLimit.h *****************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /* Disable nuisance warnings on Borland compilers */ #if defined(__BORLANDC__) #pragma warn -rch /* unreachable code */ #pragma warn -ccc /* Condition is always true or false */ #pragma warn -aus /* Assigned value is never used */ #pragma warn -csu /* Comparing signed and unsigned */ #pragma warn -spa /* Suspicious pointer arithmetic */ #endif /* Needed for various definitions... */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif /* ** Include standard header files as necessary */ #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif /* ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. ** ** The correct "ANSI" way to do this is to use the intptr_t type. ** Unfortunately, that typedef is not available on all compilers, or ** if it is available, it requires an #include of specific headers ** that vary from one machine to the next. ** ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). ** So we have to define the macros in different ways depending on the ** compiler. */ #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) #elif !defined(__GNUC__) /* Works for compilers other than LLVM */ # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ # define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never ** threadsafe. 1 means the library is serialized which is the highest ** level of threadsafety. 2 means the libary is multithreaded - multiple ** threads can use SQLite as long as no two threads try to use the same ** database connection at the same time. ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. */ #if !defined(SQLITE_THREADSAFE) #if defined(THREADSAFE) # define SQLITE_THREADSAFE THREADSAFE #else # define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ #endif #endif /* ** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. ** It determines whether or not the features related to ** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can ** be overridden at runtime using the sqlite3_config() API. */ #if !defined(SQLITE_DEFAULT_MEMSTATUS) # define SQLITE_DEFAULT_MEMSTATUS 1 #endif /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_WIN32_MALLOC // Use Win32 native heap API ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the ** assert() macro is enabled, each call into the Win32 native heap subsystem ** will cause HeapValidate to be called. If heap validation should fail, an ** assertion will be triggered. ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these three.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1 # error "At most one of the following compile-time configuration options\ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG" #endif #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ #if !defined(SQLITE_MALLOC_SOFT_LIMIT) # define SQLITE_MALLOC_SOFT_LIMIT 1024 #endif /* ** We need to define _XOPEN_SOURCE as follows in order to enable ** recursive mutexes on most Unix systems. But Mac OS X is different. ** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, ** so it is omitted there. See ticket #2673. ** ** Later we learn that _XOPEN_SOURCE is poorly or incorrectly ** implemented on some systems. So we avoid defining it at all ** if it is already defined or if it is unneeded because we are ** not doing a threadsafe build. Ticket #2681. ** ** See also ticket #2741. */ #if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE # define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ #endif /* ** The TCL headers are only needed when compiling the TCL bindings. */ #if defined(SQLITE_TCL) || defined(TCLSH) # include #endif /* ** Many people are failing to set -DNDEBUG=1 when compiling SQLite. ** Setting NDEBUG makes the code smaller and run faster. So the following ** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 ** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out ** feature. */ #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif /* ** The testcase() macro is used to aid in coverage testing. When ** doing coverage testing, the condition inside the argument to ** testcase() must be evaluated both true and false in order to ** get full branch coverage. The testcase() macro is inserted ** to help ensure adequate test coverage in places where simple ** condition/decision coverage is inadequate. For example, testcase() ** can be used to make sure boundary values are tested. For ** bitmask tests, testcase() can be used to make sure each bit ** is significant and used at least once. On switch statements ** where multiple cases go to the same block of code, testcase() ** can insure that all cases are evaluated. ** */ #ifdef SQLITE_COVERAGE_TEST SQLITE_PRIVATE void sqlite3Coverage(int); # define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } #else # define testcase(X) #endif /* ** The TESTONLY macro is used to enclose variable declarations or ** other bits of code that are needed to support the arguments ** within testcase() and assert() macros. */ #if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) # define TESTONLY(X) X #else # define TESTONLY(X) #endif /* ** Sometimes we need a small amount of code such as a variable initialization ** to setup for a later assert() statement. We do not want this code to ** appear when assert() is disabled. The following macro is therefore ** used to contain that setup code. The "VVA" acronym stands for ** "Verification, Validation, and Accreditation". In other words, the ** code within VVA_ONLY() will only run during verification processes. */ #ifndef NDEBUG # define VVA_ONLY(X) X #else # define VVA_ONLY(X) #endif /* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience ** of SQLite to unexpected behavior - to make the code "self-healing" ** or "ductile" rather than being "brittle" and crashing at the first ** hint of unplanned behavior. ** ** In other words, ALWAYS and NEVER are added for defensive code. ** ** When doing coverage testing ALWAYS and NEVER are hard-coded to ** be true and false so that the unreachable code then specify will ** not be counted as untested code. */ #if defined(SQLITE_COVERAGE_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif /* ** Return true (non-zero) if the input is a integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() ** macros to verify that we have tested SQLite for large-file support. */ #define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds ** a boolean expression that is usually true. GCC is able to ** use these hints to generate better code, sometimes. */ #if defined(__GNUC__) && 0 # define likely(X) __builtin_expect((X),1) # define unlikely(X) __builtin_expect((X),0) #else # define likely(X) !!(X) # define unlikely(X) !!(X) #endif /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. If a C-function, structure, datatype, ** or constant definition does not appear in this file, then it is ** not a published API of SQLite, is subject to change without ** notice, and should not be referenced by programs that use SQLite. ** ** Some of the definitions that are in this file are marked as ** "experimental". Experimental interfaces are normally new ** features recently added to SQLite. We do not anticipate changes ** to experimental interfaces but reserve the right to make minor changes ** if experience from use "in the wild" suggest such changes are prudent. ** ** The official C-language API documentation for SQLite is derived ** from comments in this file. This file is the authoritative source ** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. */ #if 0 extern "C" { #endif /* ** Add the ability to override 'extern' */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif #ifndef SQLITE_API # define SQLITE_API #endif /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications ** should not use deprecated interfaces - they are support for backwards ** compatibility only. Application writers should be aware that ** experimental interfaces are subject to change in point releases. ** ** These macros used to resolve to various kinds of compiler magic that ** would generate warning messages when they were used. But that ** compiler magic ended up generating such a flurry of bug reports ** that we have taken it all out and gone back to using simple ** noop macros. */ #define SQLITE_DEPRECATED #define SQLITE_EXPERIMENTAL /* ** Ensure these symbols were not defined by some previous header file. */ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif /* ** CAPI3REF: Compile-Time Library Version Numbers ** ** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header ** evaluates to a string literal that is the SQLite version in the ** format "X.Y.Z" where X is the major version number (always 3 for ** SQLite3) and Y is the minor version number and Z is the release number.)^ ** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer ** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same ** numbers used in [SQLITE_VERSION].)^ ** The SQLITE_VERSION_NUMBER for any given release of SQLite will also ** be larger than the release from which it is derived. Either Y will ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** ** Since version 3.6.18, SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite ** within its configuration management system. ^The SQLITE_SOURCE_ID ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.9" #define SQLITE_VERSION_NUMBER 3007009 #define SQLITE_SOURCE_ID "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to ** verify that values returned by these interfaces match the macros in ** the header, and thus insure that the application is ** compiled with matching library and header files. ** **
** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
** 
)^ ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; SQLITE_API const char *sqlite3_libversion(void); SQLITE_API const char *sqlite3_sourceid(void); SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** ** ^The sqlite3_compileoption_used() function returns 0 or 1 ** indicating whether the specified option was defined at ** compile time. ^The SQLITE_ prefix may be omitted from the ** option name passed to sqlite3_compileoption_used(). ** ** ^The sqlite3_compileoption_get() function allows iterating ** over the list of options that were defined at compile time by ** returning the N-th compile time option string. ^If N is out of range, ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ ** prefix is omitted from any strings returned by ** sqlite3_compileoption_get(). ** ** ^Support for the diagnostic functions sqlite3_compileoption_used() ** and sqlite3_compileoption_get() may be omitted by specifying the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** ** ^The sqlite3_threadsafe() function returns zero if and only if ** SQLite was compiled mutexing code omitted due to the ** [SQLITE_THREADSAFE] compile-time option being set to 0. ** ** SQLite can be compiled with or without mutexes. When ** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes ** are enabled and SQLite is threadsafe. When the ** [SQLITE_THREADSAFE] macro is 0, ** the mutexes are omitted. Without the mutexes, it is not safe ** to use SQLite concurrently from more than one thread. ** ** Enabling mutexes incurs a measurable performance penalty. ** So if speed is of utmost importance, it makes sense to disable ** the mutexes. But for maximum safety, mutexes should be enabled. ** ^The default behavior is for mutexes to be enabled. ** ** This interface can be used by an application to make sure that the ** version of SQLite that it is linking against was compiled with ** the desired setting of the [SQLITE_THREADSAFE] macro. ** ** This interface only reports on the compile-time mutex setting ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but ** can be fully or partially disabled using a call to [sqlite3_config()] ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the ** sqlite3_threadsafe() function shows only the compile-time setting of ** thread safety, not any run-time changes to that setting made by ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() ** is unchanged by calls to sqlite3_config().)^ ** ** See the [threading mode] documentation for additional information. */ SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle ** KEYWORDS: {database connection} {database connections} ** ** Each open SQLite database is represented by a pointer to an instance of ** the opaque structure named "sqlite3". It is useful to think of an sqlite3 ** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] ** is its destructor. There are many other interfaces (such as ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and ** [sqlite3_busy_timeout()] to name but three) that are methods on an ** sqlite3 object. */ typedef struct sqlite3 sqlite3; /* ** CAPI3REF: 64-Bit Integer Types ** KEYWORDS: sqlite_int64 sqlite_uint64 ** ** Because there is no cross-platform way to specify 64-bit integer types ** SQLite includes typedefs for 64-bit signed and unsigned integers. ** ** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. ** The sqlite_int64 and sqlite_uint64 types are supported for backwards ** compatibility only. ** ** ^The sqlite3_int64 and sqlite_int64 types can store integer values ** between -9223372036854775808 and +9223372036854775807 inclusive. ^The ** sqlite3_uint64 and sqlite_uint64 types can store integer values ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE typedef SQLITE_INT64_TYPE sqlite_int64; typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; #elif defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; #else typedef long long int sqlite_int64; typedef unsigned long long int sqlite_uint64; #endif typedef sqlite_int64 sqlite3_int64; typedef sqlite_uint64 sqlite3_uint64; /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point. */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite3_int64 #endif /* ** CAPI3REF: Closing A Database Connection ** ** ^The sqlite3_close() routine is the destructor for the [sqlite3] object. ** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is ** successfully destroyed and all associated resources are deallocated. ** ** Applications must [sqlite3_finalize | finalize] all [prepared statements] ** and [sqlite3_blob_close | close] all [BLOB handles] associated with ** the [sqlite3] object prior to attempting to close the object. ^If ** sqlite3_close() is called on a [database connection] that still has ** outstanding [prepared statements] or [BLOB handles], then it returns ** SQLITE_BUSY. ** ** ^If [sqlite3_close()] is invoked while a transaction is open, ** the transaction is automatically rolled back. ** ** The C parameter to [sqlite3_close(C)] must be either a NULL ** pointer or an [sqlite3] object pointer obtained ** from [sqlite3_open()], [sqlite3_open16()], or ** [sqlite3_open_v2()], and not previously closed. ** ^Calling sqlite3_close() with a NULL pointer argument is a ** harmless no-op. */ SQLITE_API int sqlite3_close(sqlite3 *); /* ** The type for a callback function. ** This is legacy and deprecated. It is included for historical ** compatibility and is not documented. */ typedef int (*sqlite3_callback)(void*,int,char**, char**); /* ** CAPI3REF: One-Step Query Execution Interface ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], ** that allows an application to run multiple statements of SQL ** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, ** semicolon-separate SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to ** sqlite3_exec() is not NULL, then it is invoked for each result row ** coming out of the evaluated SQL statements. ^The 4th argument to ** sqlite3_exec() is relayed through to the 1st argument of each ** callback invocation. ^If the callback pointer to sqlite3_exec() ** is NULL, then no callback is ever invoked and result rows are ** ignored. ** ** ^If an error occurs while evaluating the SQL statements passed into ** sqlite3_exec(), then execution of the current statement stops and ** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() ** is not NULL then any error message is written into memory obtained ** from [sqlite3_malloc()] and passed back through the 5th parameter. ** To avoid memory leaks, the application should invoke [sqlite3_free()] ** on error message strings returned through the 5th parameter of ** of sqlite3_exec() after the error message string is no longer needed. ** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors ** occur, then sqlite3_exec() sets the pointer in its 5th parameter to ** NULL before returning. ** ** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() ** routine returns SQLITE_ABORT without invoking the callback again and ** without running any subsequent SQL statements. ** ** ^The 2nd argument to the sqlite3_exec() callback function is the ** number of columns in the result. ^The 3rd argument to the sqlite3_exec() ** callback is an array of pointers to strings obtained as if from ** [sqlite3_column_text()], one for each column. ^If an element of a ** result row is NULL then the corresponding string pointer for the ** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the ** sqlite3_exec() callback is an array of pointers to strings where each ** entry represents the name of corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer ** to an empty string, or a pointer that contains only whitespace and/or ** SQL comments, then no SQL statements are evaluated and the database ** is not changed. ** ** Restrictions: ** **
    **
  • The application must insure that the 1st parameter to sqlite3_exec() ** is a valid and open [database connection]. **
  • The application must not close [database connection] specified by ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. **
  • The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. **
*/ SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *, /* 1st argument to callback */ char **errmsg /* Error msg written here */ ); /* ** CAPI3REF: Result Codes ** KEYWORDS: SQLITE_OK {error code} {error codes} ** KEYWORDS: {result code} {result codes} ** ** Many SQLite functions return an integer result code from the set shown ** here in order to indicates success or failure. ** ** New error codes may be added in future versions of SQLite. ** ** See also: [SQLITE_IOERR_READ | extended result codes], ** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes]. */ #define SQLITE_OK 0 /* Successful result */ /* beginning-of-error-codes */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* Database is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */ /* ** CAPI3REF: Extended Result Codes ** KEYWORDS: {extended error code} {extended error codes} ** KEYWORDS: {extended result code} {extended result codes} ** ** In its default configuration, SQLite API routines return one of 26 integer ** [SQLITE_OK | result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to ** address this, newer versions of SQLite (version 3.3.8 and later) include ** support for additional result codes that provide more detailed information ** about errors. The extended result codes are enabled or disabled ** on a per database connection basis using the ** [sqlite3_extended_result_codes()] API. ** ** Some of the available extended result codes are listed here. ** One may expect the number of extended result codes will be expand ** over time. Software that uses extended result codes should expect ** to see new result codes in future releases of SQLite. ** ** The SQLITE_OK result code will never be extended. It will always ** be exactly zero. */ #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) #define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) #define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) #define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) #define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) #define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) #define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) #define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) #define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) #define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) #define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) #define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ #define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ /* Reserved: 0x00F00000 */ /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] ** object returns an integer which is a vector of the these ** bit values expressing I/O characteristics of the mass storage ** device that holds the file that the [sqlite3_io_methods] ** refers to. ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and ** are aligned to an address which is an integer multiple of ** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means ** that when data is appended to a file, the data is appended ** first then the size of the file is extended, never the other ** way around. The SQLITE_IOCAP_SEQUENTIAL property means that ** information is written to disk in the same order as calls ** to xWrite(). */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC1K 0x00000004 #define SQLITE_IOCAP_ATOMIC2K 0x00000008 #define SQLITE_IOCAP_ATOMIC4K 0x00000010 #define SQLITE_IOCAP_ATOMIC8K 0x00000020 #define SQLITE_IOCAP_ATOMIC16K 0x00000040 #define SQLITE_IOCAP_ATOMIC32K 0x00000080 #define SQLITE_IOCAP_ATOMIC64K 0x00000100 #define SQLITE_IOCAP_SAFE_APPEND 0x00000200 #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods ** of an [sqlite3_io_methods] object. */ #define SQLITE_LOCK_NONE 0 #define SQLITE_LOCK_SHARED 1 #define SQLITE_LOCK_RESERVED 2 #define SQLITE_LOCK_PENDING 3 #define SQLITE_LOCK_EXCLUSIVE 4 /* ** CAPI3REF: Synchronization Type Flags ** ** When SQLite invokes the xSync() method of an ** [sqlite3_io_methods] object it uses a combination of ** these integer values as the second argument. ** ** When the SQLITE_SYNC_DATAONLY flag is used, it means that the ** sync operation only needs to flush data to mass storage. Inode ** information need not be flushed. If the lower four bits of the flag ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. ** If the lower four bits equal SQLITE_SYNC_FULL, that means ** to use Mac OS X style fullsync instead of fsync(). ** ** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags ** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL ** settings. The [synchronous pragma] determines when calls to the ** xSync VFS method occur and applies uniformly across all platforms. ** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how ** energetic or rigorous or forceful the sync operations are and ** only make a difference on Mac OSX for the default SQLite code. ** (Third-party VFS implementations might also make the distinction ** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the ** operating systems natively supported by SQLite, only Mac OSX ** cares about the difference.) */ #define SQLITE_SYNC_NORMAL 0x00002 #define SQLITE_SYNC_FULL 0x00003 #define SQLITE_SYNC_DATAONLY 0x00010 /* ** CAPI3REF: OS Interface Open File Handle ** ** An [sqlite3_file] object represents an open file in the ** [sqlite3_vfs | OS interface layer]. Individual OS interface ** implementations will ** want to subclass this object by appending additional fields ** for their own use. The pMethods entry is a pointer to an ** [sqlite3_io_methods] object that defines methods for performing ** I/O operations on the open file. */ typedef struct sqlite3_file sqlite3_file; struct sqlite3_file { const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ }; /* ** CAPI3REF: OS Interface File Virtual Methods Object ** ** Every file opened by the [sqlite3_vfs.xOpen] method populates an ** [sqlite3_file] object (or, more commonly, a subclass of the ** [sqlite3_file] object) with a pointer to an instance of this object. ** This object defines the methods used to perform various operations ** against the open file represented by the [sqlite3_file] object. ** ** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] ** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element ** to NULL. ** ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] ** flag may be ORed in to indicate that only the data of the file ** and not its inode needs to be synced. ** ** The integer values to xLock() and xUnlock() are one of **
    **
  • [SQLITE_LOCK_NONE], **
  • [SQLITE_LOCK_SHARED], **
  • [SQLITE_LOCK_RESERVED], **
  • [SQLITE_LOCK_PENDING], or **
  • [SQLITE_LOCK_EXCLUSIVE]. **
** xLock() increases the lock. xUnlock() decreases the lock. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, ** PENDING, or EXCLUSIVE lock on the file. It returns true ** if such a lock exists and false otherwise. ** ** The xFileControl() method is a generic interface that allows custom ** VFS implementations to directly control an open file using the ** [sqlite3_file_control()] interface. The second "op" argument is an ** integer opcode. The third argument is a generic pointer intended to ** point to a structure that may contain arguments or space in which to ** write return values. Potential uses for xFileControl() might be ** functions to enable blocking locks with timeouts, to change the ** locking strategy (for example to use dot-file locks), to inquire ** about the status of a lock, or to break stale locks. The SQLite ** core reserves all opcodes less than 100 for its own use. ** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. ** Applications that define a custom xFileControl method should use opcodes ** greater than 100 to avoid conflicts. VFS implementations should ** return [SQLITE_NOTFOUND] for file control opcodes that they do not ** recognize. ** ** The xSectorSize() method returns the sector size of the ** device that underlies the file. The sector size is the ** minimum write that can be performed without disturbing ** other bytes in the file. The xDeviceCharacteristics() ** method returns a bit vector describing behaviors of the ** underlying device: ** **
    **
  • [SQLITE_IOCAP_ATOMIC] **
  • [SQLITE_IOCAP_ATOMIC512] **
  • [SQLITE_IOCAP_ATOMIC1K] **
  • [SQLITE_IOCAP_ATOMIC2K] **
  • [SQLITE_IOCAP_ATOMIC4K] **
  • [SQLITE_IOCAP_ATOMIC8K] **
  • [SQLITE_IOCAP_ATOMIC16K] **
  • [SQLITE_IOCAP_ATOMIC32K] **
  • [SQLITE_IOCAP_ATOMIC64K] **
  • [SQLITE_IOCAP_SAFE_APPEND] **
  • [SQLITE_IOCAP_SEQUENTIAL] **
** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and ** are aligned to an address which is an integer multiple of ** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means ** that when data is appended to a file, the data is appended ** first then the size of the file is extended, never the other ** way around. The SQLITE_IOCAP_SEQUENTIAL property means that ** information is written to disk in the same order as calls ** to xWrite(). ** ** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill ** in the unread portions of the buffer with zeros. A VFS that ** fails to zero-fill short reads might seem to work. However, ** failure to zero-fill short reads will eventually lead to ** database corruption. */ typedef struct sqlite3_io_methods sqlite3_io_methods; struct sqlite3_io_methods { int iVersion; int (*xClose)(sqlite3_file*); int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); int (*xSync)(sqlite3_file*, int flags); int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); int (*xLock)(sqlite3_file*, int); int (*xUnlock)(sqlite3_file*, int); int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); int (*xFileControl)(sqlite3_file*, int op, void *pArg); int (*xSectorSize)(sqlite3_file*); int (*xDeviceCharacteristics)(sqlite3_file*); /* Methods above are valid for version 1 */ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ /* Additional methods may be added in future releases */ }; /* ** CAPI3REF: Standard File Control Opcodes ** ** These integer constants are opcodes for the xFileControl method ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** interface. ** ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) ** into an integer that the pArg argument points to. This capability ** is used during testing and only needs to be supported when SQLITE_TEST ** is defined. ** ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the ** current transaction. This hint is not guaranteed to be accurate but it ** is often close. The underlying VFS might choose to preallocate database ** file space based on this hint in order to help writes to the database ** file run faster. ** ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS ** extends and truncates the database file in chunks of a size specified ** by the user. The fourth argument to [sqlite3_file_control()] should ** point to an integer (type int) containing the new chunk-size to use ** for the nominated database. Allocating database file space in large ** chunks (say 1MB at a time), may reduce file-system fragmentation and ** improve performance on some systems. ** ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer ** to the [sqlite3_file] object associated with a particular database ** connection. See the [sqlite3_file_control()] documentation for ** additional information. ** ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by ** SQLite and sent to all VFSes in place of a call to the xSync method ** when the database connection has [PRAGMA synchronous] set to OFF.)^ ** Some specialized VFSes need this signal in order to operate correctly ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most ** VFSes do not need this signal and should silently ignore this opcode. ** Applications should not call [sqlite3_file_control()] with this ** opcode as doing so may disrupt the operation of the specialized VFSes ** that do require it. ** ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to work to provide robustness against ** anti-virus programs. By default, the windows VFS will retry file read, ** file write, and file delete opertions up to 10 times, with a delay ** of 25 milliseconds before the first retry and with the delay increasing ** by an additional 25 milliseconds with each subsequent retry. This ** opcode allows those to values (10 retries and 25 milliseconds of delay) ** to be adjusted. The values are changed for all database connections ** within the same process. The argument is a pointer to an array of two ** integers where the first integer i the new retry count and the second ** integer is the delay. If either integer is negative, then the setting ** is not changed but instead the prior value of that setting is written ** into the array entry, allowing the current retry settings to be ** interrogated. The zDbName parameter is ignored. ** ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary ** write ahead log and shared memory files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after ** close. Persisting the files is useful when other processes that do not ** have write permission on the directory containing the database file want ** to read the database file, as the WAL and shared memory files must exist ** in order for the database to be readable. The fourth parameter to ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent ** WAL mode. If the integer is -1, then it is overwritten with the current ** WAL persistence setting. ** ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some ** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 #define SQLITE_FCNTL_OVERWRITE 11 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only ** deals with pointers to the [sqlite3_mutex] object. ** ** Mutexes are created using [sqlite3_mutex_alloc()]. */ typedef struct sqlite3_mutex sqlite3_mutex; /* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between ** the SQLite core and the underlying operating system. The "vfs" ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. ** ** The value of the iVersion field is initially 1 but may be larger in ** future versions of SQLite. Additional fields may be appended to this ** object when the iVersion value is increased. Note that the structure ** of the sqlite3_vfs object changes in the transaction between ** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not ** modified. ** ** The szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of ** a pathname in this VFS. ** ** Registered sqlite3_vfs objects are kept on a linked list formed by ** the pNext pointer. The [sqlite3_vfs_register()] ** and [sqlite3_vfs_unregister()] interfaces manage this list ** in a thread-safe way. The [sqlite3_vfs_find()] interface ** searches the list. Neither the application code nor the VFS ** implementation should use the pNext pointer. ** ** The pNext field is the only field in the sqlite3_vfs ** structure that SQLite will ever modify. SQLite will only access ** or modify this field while holding a particular static mutex. ** The application should never modify anything within the sqlite3_vfs ** object once the object has been registered. ** ** The zName field holds the name of the VFS module. The name must ** be unique across all VFS modules. ** ** [[sqlite3_vfs.xOpen]] ** ^SQLite guarantees that the zFilename parameter to xOpen ** is either a NULL pointer or string obtained ** from xFullPathname() with an optional suffix added. ** ^If a suffix is added to the zFilename parameter, it will ** consist of a single "-" character followed by no more than ** 10 alphanumeric and/or "-" characters. ** ^SQLite further guarantees that ** the string will be valid and unchanged until xClose() is ** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. ** If the zFilename parameter to xOpen is a NULL pointer then xOpen ** must invent its own temporary name for the file. ^Whenever the ** xFilename parameter is NULL it will also be the case that the ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. ** ** The flags argument to xOpen() includes all bits set in ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] ** or [sqlite3_open16()] is used, then flags includes at least ** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. ** If xOpen() opens a file read-only then it sets *pOutFlags to ** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. ** ** ^(SQLite will also add one of the following flags to the xOpen() ** call, depending on the object being opened: ** **
    **
  • [SQLITE_OPEN_MAIN_DB] **
  • [SQLITE_OPEN_MAIN_JOURNAL] **
  • [SQLITE_OPEN_TEMP_DB] **
  • [SQLITE_OPEN_TEMP_JOURNAL] **
  • [SQLITE_OPEN_TRANSIENT_DB] **
  • [SQLITE_OPEN_SUBJOURNAL] **
  • [SQLITE_OPEN_MASTER_JOURNAL] **
  • [SQLITE_OPEN_WAL] **
)^ ** ** The file I/O implementation can use the object type flags to ** change the way it deals with files. For example, an application ** that does not care about crash recovery or rollback might make ** the open of a journal file a no-op. Writes to this journal would ** also be no-ops, and any attempt to read the journal would return ** SQLITE_IOERR. Or the implementation might recognize that a database ** file will be doing page-aligned sector reads and writes in a random ** order and set up its I/O subsystem accordingly. ** ** SQLite might also add one of the following flags to the xOpen method: ** **
    **
  • [SQLITE_OPEN_DELETEONCLOSE] **
  • [SQLITE_OPEN_EXCLUSIVE] **
** ** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be ** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] ** will be set for TEMP databases and their journals, transient ** databases, and subjournals. ** ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction ** with the [SQLITE_OPEN_CREATE] flag, which are both directly ** analogous to the O_EXCL and O_CREAT flags of the POSIX open() ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the ** SQLITE_OPEN_CREATE, is used to indicate that file should always ** be created, and that it is an error if it already exists. ** It is not used to indicate the file should be opened ** for exclusive access. ** ** ^At least szOsFile bytes of memory are allocated by SQLite ** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to ** allocate the structure; it should just fill it in. Note that ** the xOpen method must set the sqlite3_file.pMethods to either ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods ** element will be valid after xOpen returns regardless of the success ** or failure of the xOpen call. ** ** [[sqlite3_vfs.xAccess]] ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] ** to test whether a file is at least readable. The file can be a ** directory. ** ** ^SQLite will always allocate at least mxPathname+1 bytes for the ** output buffer xFullPathname. The exact size of the output buffer ** is also passed as a parameter to both methods. If the output buffer ** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is ** handled as a fatal error by SQLite, vfs implementations should endeavor ** to prevent this by setting mxPathname to a sufficiently large value. ** ** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() ** interfaces are not strictly a part of the filesystem, but they are ** included in the VFS structure for completeness. ** The xRandomness() function attempts to return nBytes bytes ** of good-quality randomness into zOut. The return value is ** the actual number of bytes of randomness obtained. ** The xSleep() method causes the calling thread to sleep for at ** least the number of microseconds given. ^The xCurrentTime() ** method returns a Julian Day Number for the current date and time as ** a floating point value. ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian ** Day Number multiplied by 86400000 (the number of milliseconds in ** a 24-hour day). ** ^SQLite will use the xCurrentTimeInt64() method to get the current ** date and time if that method is available (if iVersion is 2 or ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** ** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided ** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can ** simulate faults and error conditions that would otherwise be difficult ** or impossible to induce. The set of system calls that can be overridden ** varies from one VFS to another, and from one version of the same VFS to the ** next. Applications that use these interfaces must be prepared for any ** or all of these interfaces to be NULL or for their behavior to change ** from one release to the next. Applications must not attempt to access ** any of these methods if the iVersion of the VFS is less than 3. */ typedef struct sqlite3_vfs sqlite3_vfs; typedef void (*sqlite3_syscall_ptr)(void); struct sqlite3_vfs { int iVersion; /* Structure version number (currently 3) */ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); void (*xDlClose)(sqlite3_vfs*, void*); int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); int (*xSleep)(sqlite3_vfs*, int microseconds); int (*xCurrentTime)(sqlite3_vfs*, double*); int (*xGetLastError)(sqlite3_vfs*, int, char *); /* ** The methods above are in version 1 of the sqlite_vfs object ** definition. Those that follow are added in version 2 or later */ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); /* ** The methods above are in versions 1 and 2 of the sqlite_vfs object. ** Those below are for version 3 and greater. */ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in figure versions. The iVersion ** value will increment whenever this happens. */ }; /* ** CAPI3REF: Flags for the xAccess VFS method ** ** These integer constants can be used as the third parameter to ** the xAccess method of an [sqlite3_vfs] object. They determine ** what kind of permissions the xAccess method is looking for. ** With SQLITE_ACCESS_EXISTS, the xAccess method ** simply checks whether the file exists. ** With SQLITE_ACCESS_READWRITE, the xAccess method ** checks whether the named directory is both readable and writable ** (in other words, if files can be added, removed, and renamed within ** the directory). ** The SQLITE_ACCESS_READWRITE constant is currently used only by the ** [temp_store_directory pragma], though this could change in a future ** release of SQLite. ** With SQLITE_ACCESS_READ, the xAccess method ** checks whether the file is readable. The SQLITE_ACCESS_READ constant is ** currently unused, though it might be used in a future release of ** SQLite. */ #define SQLITE_ACCESS_EXISTS 0 #define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ #define SQLITE_ACCESS_READ 2 /* Unused */ /* ** CAPI3REF: Flags for the xShmLock VFS method ** ** These integer constants define the various locking operations ** allowed by the xShmLock method of [sqlite3_io_methods]. The ** following are the only legal combinations of flags to the ** xShmLock method: ** **
    **
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED **
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE **
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED **
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE **
** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as ** was given no the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED ** and EXCLUSIVE. */ #define SQLITE_SHM_UNLOCK 1 #define SQLITE_SHM_LOCK 2 #define SQLITE_SHM_SHARED 4 #define SQLITE_SHM_EXCLUSIVE 8 /* ** CAPI3REF: Maximum xShmLock index ** ** The xShmLock method on [sqlite3_io_methods] may use values ** between 0 and this upper bound as its "offset" argument. ** The SQLite core will never attempt to acquire or release a ** lock outside of this range */ #define SQLITE_SHM_NLOCK 8 /* ** CAPI3REF: Initialize The SQLite Library ** ** ^The sqlite3_initialize() routine initializes the ** SQLite library. ^The sqlite3_shutdown() routine ** deallocates any resources that were allocated by sqlite3_initialize(). ** These routines are designed to aid in process initialization and ** shutdown on embedded systems. Workstation applications using ** SQLite normally do not need to invoke either of these routines. ** ** A call to sqlite3_initialize() is an "effective" call if it is ** the first time sqlite3_initialize() is invoked during the lifetime of ** the process, or if it is the first time sqlite3_initialize() is invoked ** following a call to sqlite3_shutdown(). ^(Only an effective call ** of sqlite3_initialize() does any initialization. All other calls ** are harmless no-ops.)^ ** ** A call to sqlite3_shutdown() is an "effective" call if it is the first ** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only ** an effective call to sqlite3_shutdown() does any deinitialization. ** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ ** ** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() ** is not. The sqlite3_shutdown() interface must only be called from a ** single thread. All open [database connections] must be closed and all ** other SQLite resources must be deallocated prior to invoking ** sqlite3_shutdown(). ** ** Among other things, ^sqlite3_initialize() will invoke ** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() ** will invoke sqlite3_os_end(). ** ** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. ** ^If for some reason, sqlite3_initialize() is unable to initialize ** the library (perhaps it is unable to allocate a needed resource such ** as a mutex) it returns an [error code] other than [SQLITE_OK]. ** ** ^The sqlite3_initialize() routine is called internally by many other ** SQLite interfaces so that an application usually does not need to ** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] ** calls sqlite3_initialize() so the SQLite library will be automatically ** initialized when [sqlite3_open()] is called if it has not be initialized ** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] ** compile-time option, then the automatic calls to sqlite3_initialize() ** are omitted and the application must call sqlite3_initialize() directly ** prior to using any other SQLite interface. For maximum portability, ** it is recommended that applications always invoke sqlite3_initialize() ** directly prior to using any other SQLite interface. Future releases ** of SQLite may require this. In other words, the behavior exhibited ** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the ** default behavior in some future release of SQLite. ** ** The sqlite3_os_init() routine does operating-system specific ** initialization of the SQLite library. The sqlite3_os_end() ** routine undoes the effect of sqlite3_os_init(). Typical tasks ** performed by these routines include allocation or deallocation ** of static resources, initialization of global variables, ** setting up a default [sqlite3_vfs] module, or setting up ** a default configuration using [sqlite3_config()]. ** ** The application should never invoke either sqlite3_os_init() ** or sqlite3_os_end() directly. The application should only invoke ** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() ** interface is called automatically by sqlite3_initialize() and ** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate ** implementations for sqlite3_os_init() and sqlite3_os_end() ** are built into SQLite when it is compiled for Unix, Windows, or OS/2. ** When [custom builds | built for other platforms] ** (using the [SQLITE_OS_OTHER=1] compile-time ** option) the application must supply a suitable implementation for ** sqlite3_os_init() and sqlite3_os_end(). An application-supplied ** implementation of sqlite3_os_init() or sqlite3_os_end() ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ SQLITE_API int sqlite3_initialize(void); SQLITE_API int sqlite3_shutdown(void); SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() interface is used to make global configuration ** changes to SQLite in order to tune SQLite to the specific needs of ** the application. The default configuration is recommended for most ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** ** The sqlite3_config() interface is not threadsafe. The application ** must insure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running. Furthermore, sqlite3_config() ** may only be invoked prior to library initialization using ** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. ** ^If sqlite3_config() is called after [sqlite3_initialize()] and before ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. ** Note, however, that ^sqlite3_config() can be called as part of the ** implementation of an application-defined [sqlite3_os_init()]. ** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to ** [sqlite3_config()] except that the changes apply to a single ** [database connection] (specified in the first argument). ** ** The second argument to sqlite3_db_config(D,V,...) is the ** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code ** that indicates what aspect of the [database connection] is being configured. ** Subsequent arguments vary depending on the configuration verb. ** ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines ** ** An instance of this object defines the interface between SQLite ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to ** [sqlite3_config()] when the configuration option is ** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. ** By creating an instance of this object ** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) ** during configuration, an application can specify an alternative ** memory allocation subsystem for SQLite to use for all of its ** dynamic memory needs. ** ** Note that SQLite comes with several [built-in memory allocators] ** that are perfectly adequate for the overwhelming majority of applications ** and that this object is only useful to a tiny minority of applications ** with specialized memory allocation requirements. This object is ** also used during testing of SQLite in order to specify an alternative ** memory allocator that simulates memory out-of-memory conditions in ** order to verify that SQLite recovers gracefully from such ** conditions. ** ** The xMalloc, xRealloc, and xFree methods must work like the ** malloc(), realloc() and free() functions from the standard C library. ** ^SQLite guarantees that the second argument to ** xRealloc is always a value returned by a prior call to xRoundup. ** ** xSize should return the allocated size of a memory allocation ** previously obtained from xMalloc or xRealloc. The allocated size ** is always at least as big as the requested size but may be larger. ** ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. ** Every memory allocation request coming in through [sqlite3_malloc()] ** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, ** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. (For example, ** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. ** ** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ** xShutdown method is only called from [sqlite3_shutdown()] so it does ** not need to be threadsafe either. For all other methods, SQLite ** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the ** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which ** it is by default) and so the methods are automatically serialized. ** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other ** methods must be threadsafe or else make their own arrangements for ** serialization. ** ** SQLite will never invoke xInit() more than once without an intervening ** call to xShutdown(). */ typedef struct sqlite3_mem_methods sqlite3_mem_methods; struct sqlite3_mem_methods { void *(*xMalloc)(int); /* Memory allocation function */ void (*xFree)(void*); /* Free a prior allocation */ void *(*xRealloc)(void*,int); /* Resize an allocation */ int (*xSize)(void*); /* Return the size of an allocation */ int (*xRoundup)(int); /* Round up request size to allocation size */ int (*xInit)(void*); /* Initialize the memory allocator */ void (*xShutdown)(void*); /* Deinitialize the memory allocator */ void *pAppData; /* Argument to xInit() and xShutdown() */ }; /* ** CAPI3REF: Configuration Options ** KEYWORDS: {configuration option} ** ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. ** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_config()] to make sure that ** the call worked. The [sqlite3_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** **
** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
**
There are no arguments to this option. ^This option sets the ** [threading mode] to Single-thread. In other words, it disables ** all mutexing and puts SQLite into a mode where it can only be used ** by a single thread. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to change the [threading mode] from its default ** value of Single-thread and so [sqlite3_config()] will return ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD ** configuration option.
** ** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
**
There are no arguments to this option. ^This option sets the ** [threading mode] to Multi-thread. In other words, it disables ** mutexing on [database connection] and [prepared statement] objects. ** The application is responsible for serializing access to ** [database connections] and [prepared statements]. But other mutexes ** are enabled so that SQLite will be safe to use in a multi-threaded ** environment as long as no two threads attempt to use the same ** [database connection] at the same time. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to set the Multi-thread [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_MULTITHREAD configuration option.
** ** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
**
There are no arguments to this option. ^This option sets the ** [threading mode] to Serialized. In other words, this option enables ** all mutexes including the recursive ** mutexes on [database connection] and [prepared statement] objects. ** In this mode (which is the default when SQLite is compiled with ** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access ** to [database connections] and [prepared statements] so that the ** application is free to use the same [database connection] or the ** same [prepared statement] in different threads at the same time. ** ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to set the Serialized [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_SERIALIZED configuration option.
** ** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
**
^(This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mem_methods] structure. The argument specifies ** alternative low-level memory allocation routines to be used in place of ** the memory allocation routines built into SQLite.)^ ^SQLite makes ** its own private copy of the content of the [sqlite3_mem_methods] structure ** before the [sqlite3_config()] call returns.
** ** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
**
^(This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example.
** ** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
**
^This option takes single argument of type int, interpreted as a ** boolean, which enables or disables the collection of memory allocation ** statistics. ^(When memory allocation statistics are disabled, the ** following SQLite interfaces become non-operational: **
    **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] **
  • [sqlite3_soft_heap_limit64()] **
  • [sqlite3_status()] **
)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ** allocation statistics are disabled by default. **
** ** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
**
^This option specifies a static memory buffer that SQLite can use for ** scratch memory. There are three arguments: A pointer an 8-byte ** aligned memory buffer from which the scratch allocations will be ** drawn, the size of each scratch allocation (sz), ** and the maximum number of scratch allocations (N). The sz ** argument must be a multiple of 16. ** The first argument must be a pointer to an 8-byte aligned buffer ** of at least sz*N bytes of memory. ** ^SQLite will use no more than two scratch buffers per thread. So ** N should be set to twice the expected maximum number of threads. ** ^SQLite will never require a scratch buffer that is more than 6 ** times the database page size. ^If SQLite needs needs additional ** scratch memory beyond what is provided by this configuration option, then ** [sqlite3_malloc()] will be used to obtain the memory needed.
** ** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
**
^This option specifies a static memory buffer that SQLite can use for ** the database page cache with the default page cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. ** There are three arguments to this option: A pointer to 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 32768) plus a little extra for each ** page header. ^The page header size is 20 to 40 bytes depending on ** the host architecture. ^It is harmless, apart from the wasted memory, ** to make sz a little too large. The first ** argument should point to an allocation of at least sz*N bytes of memory. ** ^SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. ^If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space. ** The pointer in the first argument must ** be aligned to an 8-byte boundary or subsequent behavior of SQLite ** will be undefined.
** ** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
**
^This option specifies a static memory buffer that SQLite will use ** for all of its dynamic memory allocation needs beyond those provided ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. ** There are three arguments: An 8-byte aligned pointer to the memory, ** the number of bytes in the memory buffer, and the minimum allocation size. ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the ** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or ** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory ** allocator is engaged to handle all of SQLites memory allocation needs. ** The first pointer (the memory pointer) must be aligned to an 8-byte ** boundary or subsequent behavior of SQLite will be undefined. ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.
** ** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
**
^(This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mutex_methods] structure. The argument specifies ** alternative low-level mutex routines to be used in place ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the ** content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will ** return [SQLITE_ERROR].
** ** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
**
^(This option takes a single argument which is a pointer to an ** instance of the [sqlite3_mutex_methods] structure. The ** [sqlite3_mutex_methods] ** structure is filled with the currently defined mutex routines.)^ ** This option can be used to overload the default mutex allocation ** routines with a wrapper used to track mutex usage for performance ** profiling or testing, for example. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will ** return [SQLITE_ERROR].
** ** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
**
^(This option takes two arguments that determine the default ** memory allocation for the lookaside memory allocator on each ** [database connection]. The first argument is the ** size of each lookaside buffer slot and the second is the number of ** slots allocated to each database connection.)^ ^(This option sets the ** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] ** verb to [sqlite3_db_config()] can be used to change the lookaside ** configuration on individual connections.)^
** ** [[SQLITE_CONFIG_PCACHE]]
SQLITE_CONFIG_PCACHE
**
^(This option takes a single argument which is a pointer to ** an [sqlite3_pcache_methods] object. This object specifies the interface ** to a custom page cache implementation.)^ ^SQLite makes a copy of the ** object and uses it for page cache memory allocations.
** ** [[SQLITE_CONFIG_GETPCACHE]]
SQLITE_CONFIG_GETPCACHE
**
^(This option takes a single argument which is a pointer to an ** [sqlite3_pcache_methods] object. SQLite copies of the current ** page cache implementation into that object.)^
** ** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
**
^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger ** function whenever that function is invoked. ^The second parameter to ** the logger function is a copy of the first parameter to the corresponding ** [sqlite3_log()] call and is intended to be a [result code] or an ** [extended result code]. ^The third parameter passed to the logger is ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe.
** ** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI **
This option takes a single argument of type int. If non-zero, then ** URI handling is globally enabled. If the parameter is zero, then URI handling ** is globally disabled. If URI handling is globally enabled, all filenames ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. **
*/ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_db_config()] to make sure that ** the call worked. ^The [sqlite3_db_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** **
**
SQLITE_DBCONFIG_LOOKASIDE
**
^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. ** ^The first argument (the third parameter to [sqlite3_db_config()] is a ** pointer to a memory buffer to use for lookaside memory. ** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb ** may be NULL in which case SQLite will allocate the ** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the ** size of each lookaside buffer slot. ^The third argument is the number of ** slots. The size of the buffer in the first argument must be greater than ** or equal to the product of the second and third arguments. The buffer ** must be aligned to an 8-byte boundary. ^If the second argument to ** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally ** rounded down to the next smaller multiple of 8. ^(The lookaside memory ** configuration for a database connection can only be changed when that ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by ** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^
** **
SQLITE_DBCONFIG_ENABLE_FKEY
**
^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. ** The first argument is an integer which is 0 to disable FK enforcement, ** positive to enable FK enforcement or negative to leave FK enforcement ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether FK enforcement is off or on ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back.
** **
SQLITE_DBCONFIG_ENABLE_TRIGGER
**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back.
** **
*/ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid ** ** ^Each entry in an SQLite table has a unique 64-bit signed ** integer key called the [ROWID | "rowid"]. ^The rowid is always available ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those ** names are not also used by explicitly declared columns. ^If ** the table has a column of type [INTEGER PRIMARY KEY] then that column ** is another alias for the rowid. ** ** ^This routine returns the [rowid] of the most recent ** successful [INSERT] into the database from the [database connection] ** in the first argument. ^As of SQLite version 3.7.7, this routines ** records the last insert rowid of both ordinary tables and [virtual tables]. ** ^If no successful [INSERT]s ** have ever occurred on that database connection, zero is returned. ** ** ^(If an [INSERT] occurs within a trigger or within a [virtual table] ** method, then this routine will return the [rowid] of the inserted ** row as long as the trigger or virtual table method is running. ** But once the trigger or virtual table method ends, the value returned ** by this routine reverts to what it was before the trigger or virtual ** table method began.)^ ** ** ^An [INSERT] that fails due to a constraint violation is not a ** successful [INSERT] and does not change the value returned by this ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, ** and INSERT OR ABORT make no changes to the return value of this ** routine when their insertion fails. ^(When INSERT OR REPLACE ** encounters a constraint violation, it does not fail. The ** INSERT continues to completion after deleting rows that caused ** the constraint problem so INSERT OR REPLACE will always change ** the return value of this interface.)^ ** ** ^For the purposes of this routine, an [INSERT] is considered to ** be successful even if it is subsequently rolled back. ** ** This function is accessible to SQL statements via the ** [last_insert_rowid() SQL function]. ** ** If a separate thread performs a new [INSERT] on the same ** database connection while the [sqlite3_last_insert_rowid()] ** function is running and thus changes the last insert [rowid], ** then the value returned by [sqlite3_last_insert_rowid()] is ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified ** ** ^This function returns the number of database rows that were changed ** or inserted or deleted by the most recently completed SQL statement ** on the [database connection] specified by the first parameter. ** ^(Only changes that are directly specified by the [INSERT], [UPDATE], ** or [DELETE] statement are counted. Auxiliary changes caused by ** triggers or [foreign key actions] are not counted.)^ Use the ** [sqlite3_total_changes()] function to find the total number of changes ** including changes caused by triggers and foreign key actions. ** ** ^Changes to a view that are simulated by an [INSTEAD OF trigger] ** are not counted. Only real table changes are counted. ** ** ^(A "row change" is a change to a single row of a single table ** caused by an INSERT, DELETE, or UPDATE statement. Rows that ** are changed as side effects of [REPLACE] constraint resolution, ** rollback, ABORT processing, [DROP TABLE], or by any other ** mechanisms do not count as direct row changes.)^ ** ** A "trigger context" is a scope of execution that begins and ** ends with the script of a [CREATE TRIGGER | trigger]. ** Most SQL statements are ** evaluated outside of any trigger. This is the "top level" ** trigger context. If a trigger fires from the top level, a ** new trigger context is entered for the duration of that one ** trigger. Subtriggers create subcontexts for their duration. ** ** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does ** not create a new trigger context. ** ** ^This function returns the number of direct row changes in the ** most recent INSERT, UPDATE, or DELETE statement within the same ** trigger context. ** ** ^Thus, when called from the top level, this function returns the ** number of changes in the most recent INSERT, UPDATE, or DELETE ** that also occurred at the top level. ^(Within the body of a trigger, ** the sqlite3_changes() interface can be called to find the number of ** changes in the most recently completed INSERT, UPDATE, or DELETE ** statement within the body of the same trigger. ** However, the number returned does not include changes ** caused by subtriggers since those have their own context.)^ ** ** See also the [sqlite3_total_changes()] interface, the ** [count_changes pragma], and the [changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** ** ^This function returns the number of row changes caused by [INSERT], ** [UPDATE] or [DELETE] statements since the [database connection] was opened. ** ^(The count returned by sqlite3_total_changes() includes all changes ** from all [CREATE TRIGGER | trigger] contexts and changes made by ** [foreign key actions]. However, ** the count does not include changes used to implement [REPLACE] constraints, ** do rollbacks or ABORT processing, or [DROP TABLE] processing. The ** count does not include rows of views that fire an [INSTEAD OF trigger], ** though if the INSTEAD OF trigger makes changes of its own, those changes ** are counted.)^ ** ^The sqlite3_total_changes() function counts the changes as soon as ** the statement that makes them is completed (when the statement handle ** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). ** ** See also the [sqlite3_changes()] interface, the ** [count_changes pragma], and the [total_changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically ** called in response to a user action such as pressing "Cancel" ** or Ctrl-C where the user wants a long query operation to halt ** immediately. ** ** ^It is safe to call this routine from a thread different from the ** thread that is currently running the database operation. But it ** is not safe to call this routine with a [database connection] that ** is closed or might close before sqlite3_interrupt() returns. ** ** ^If an SQL operation is very nearly finished at the time when ** sqlite3_interrupt() is called, then it might not have an opportunity ** to be interrupted and might continue to completion. ** ** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. ** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** ** ^The sqlite3_interrupt(D) call is in effect until all currently running ** SQL statements on [database connection] D complete. ^Any new SQL statements ** that are started after the sqlite3_interrupt() call and before the ** running statements reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns. ** ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete ** ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into ** SQLite for parsing. ^These routines return 1 if the input string ** appears to be a complete SQL statement. ^A statement is judged to be ** complete if it ends with a semicolon token and is not a prefix of a ** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within ** string literals or quoted identifier names or comments are not ** independent tokens (they are part of the token in which they are ** embedded) and thus do not count as a statement terminator. ^Whitespace ** and comments that follow the final semicolon are ignored. ** ** ^These routines return 0 if the statement is incomplete. ^If a ** memory allocation fails, then SQLITE_NOMEM is returned. ** ** ^These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. ** ** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked ** automatically by sqlite3_complete16(). If that initialization fails, ** then the return value from sqlite3_complete16() will be non-zero ** regardless of whether or not the input SQL is complete.)^ ** ** The input to [sqlite3_complete()] must be a zero-terminated ** UTF-8 string. ** ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ SQLITE_API int sqlite3_complete(const char *sql); SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** ** ^This routine sets a callback function that might be invoked whenever ** an attempt is made to open a database table that another thread ** or process has locked. ** ** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] ** is returned immediately upon encountering the lock. ^If the busy callback ** is not NULL, then the callback might be invoked with two arguments. ** ** ^The first argument to the busy handler is a copy of the void* pointer which ** is the third argument to sqlite3_busy_handler(). ^The second argument to ** the busy handler callback is the number of times that the busy handler has ** been invoked for this locking event. ^If the ** busy callback returns 0, then no additional attempts are made to ** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. ** ^If the callback returns non-zero, then another attempt ** is made to open the database for reading and the cycle repeats. ** ** The presence of a busy handler does not guarantee that it will be invoked ** when there is lock contention. ^If SQLite determines that invoking the busy ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] ** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. ** Consider a scenario where one process is holding a read lock that ** it is trying to promote to a reserved lock and ** a second process is holding a reserved lock that it is trying ** to promote to an exclusive lock. The first process cannot proceed ** because it is blocked by the second and the second process cannot ** proceed because it is blocked by the first. If both processes ** invoke the busy handlers, neither will make any progress. Therefore, ** SQLite returns [SQLITE_BUSY] for the first process, hoping that this ** will induce the first process to release its read lock and allow ** the second process to proceed. ** ** ^The default busy callback is NULL. ** ** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] ** when SQLite is in the middle of a large transaction where all the ** changes will not fit into the in-memory cache. SQLite will ** already hold a RESERVED lock on the database file, but it needs ** to promote this lock to EXCLUSIVE so that it can spill cache ** pages into the database file without harm to concurrent ** readers. ^If it is unable to promote the lock, then the in-memory ** cache will be left in an inconsistent state and so the error ** code is promoted from the relatively benign [SQLITE_BUSY] to ** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion ** forces an automatic rollback of the changes. See the ** ** CorruptionFollowingBusyError wiki page for a discussion of why ** this is important. ** ** ^(There can only be a single busy handler defined for each ** [database connection]. Setting a new busy handler clears any ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] ** will also set or clear the busy handler. ** ** The busy callback should not take any actions which modify the ** database connection that invoked the busy handler. Any such actions ** result in undefined behavior. ** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler ** will sleep multiple times until at least "ms" milliseconds of sleeping ** have accumulated. ^After at least "ms" milliseconds of sleeping, ** the handler returns 0 which causes [sqlite3_step()] to return ** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. ** ** ^Calling this routine with an argument less than or equal to zero ** turns off all busy handlers. ** ** ^(There can only be a single busy handler for a particular ** [database connection] any any given moment. If another busy handler ** was defined (using [sqlite3_busy_handler()]) prior to calling ** this routine, that other busy handler is cleared.)^ */ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. ** ** Definition: A result table is memory data structure created by the ** [sqlite3_get_table()] interface. A result table records the ** complete query results from one or more queries. ** ** The table conceptually has a number of rows and columns. But ** these numbers are not part of the result table itself. These ** numbers are obtained separately. Let N be the number of rows ** and M be the number of columns. ** ** A result table is an array of pointers to zero-terminated UTF-8 strings. ** There are (N+1)*M elements in the array. The first M pointers point ** to zero-terminated strings that contain the names of the columns. ** The remaining entries all point to query results. NULL values result ** in NULL pointers. All other values are in their UTF-8 zero-terminated ** string representation as returned by [sqlite3_column_text()]. ** ** A result table might consist of one or more memory allocations. ** It is not safe to pass a result table directly to [sqlite3_free()]. ** A result table should be deallocated using [sqlite3_free_table()]. ** ** ^(As an example of the result table format, suppose a query result ** is as follows: ** **
**        Name        | Age
**        -----------------------
**        Alice       | 43
**        Bob         | 28
**        Cindy       | 21
** 
** ** There are two column (M==2) and three rows (N==3). Thus the ** result table has 8 entries. Suppose the result table is stored ** in an array names azResult. Then azResult holds this content: ** **
**        azResult[0] = "Name";
**        azResult[1] = "Age";
**        azResult[2] = "Alice";
**        azResult[3] = "43";
**        azResult[4] = "Bob";
**        azResult[5] = "28";
**        azResult[6] = "Cindy";
**        azResult[7] = "21";
** 
)^ ** ** ^The sqlite3_get_table() function evaluates one or more ** semicolon-separated SQL statements in the zero-terminated UTF-8 ** string of its 2nd parameter and returns a result table to the ** pointer given in its 3rd parameter. ** ** After the application has finished with the result from sqlite3_get_table(), ** it must pass the result table pointer to sqlite3_free_table() in order to ** release the memory that was malloced. Because of the way the ** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling ** function must not try to call [sqlite3_free()] directly. Only ** [sqlite3_free_table()] is able to release the memory properly and safely. ** ** The sqlite3_get_table() interface is implemented as a wrapper around ** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access ** to any internal data structures of SQLite. It uses only the public ** interface defined here. As a consequence, errors that occur in the ** wrapper layer outside of the internal [sqlite3_exec()] call are not ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ int *pnRow, /* Number of result rows written here */ int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. ** The strings returned by these two routines should be ** released by [sqlite3_free()]. ^Both routines return a ** NULL pointer if [sqlite3_malloc()] is unable to allocate enough ** memory to hold the resulting string. ** ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from ** the standard C library. The result is written into the ** buffer supplied as the second parameter whose size is given by ** the first parameter. Note that the order of the ** first two parameters is reversed from snprintf().)^ This is an ** historical accident that cannot be fixed without breaking ** backwards compatibility. ^(Note also that sqlite3_snprintf() ** returns a pointer to its buffer instead of the number of ** characters actually written into the buffer.)^ We admit that ** the number of characters written would be a more useful return ** value but we cannot change the implementation of sqlite3_snprintf() ** now without breaking compatibility. ** ** ^As long as the buffer size is greater than zero, sqlite3_snprintf() ** guarantees that the buffer is always zero-terminated. ^The first ** parameter "n" is the total size of the buffer, including space for ** the zero terminator. So the longest string that can be completely ** written will be n-1 characters. ** ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). ** ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf() formatting options apply. In addition, there ** is are "%q", "%Q", and "%z" options. ** ** ^(The %q option works like %s in that it substitutes a null-terminated ** string from the argument list. But %q also doubles every '\'' character. ** %q is designed for use inside a string literal.)^ By doubling each '\'' ** character it escapes that character and allows it to be inserted into ** the string. ** ** For example, assume the string variable zText contains text as follows: ** **
**  char *zText = "It's a happy day!";
** 
** ** One can use this text in an SQL statement as follows: ** **
**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
**  sqlite3_exec(db, zSQL, 0, 0, 0);
**  sqlite3_free(zSQL);
** 
** ** Because the %q format string is used, the '\'' character in zText ** is escaped and the SQL generated is as follows: ** **
**  INSERT INTO table1 VALUES('It''s a happy day!')
** 
** ** This is correct. Had we used %s instead of %q, the generated SQL ** would have looked like this: ** **
**  INSERT INTO table1 VALUES('It's a happy day!');
** 
** ** This second example is an SQL syntax error. As a general rule you should ** always use %q instead of %s when inserting text into a string literal. ** ** ^(The %Q option works like %q except it also adds single quotes around ** the outside of the total string. Additionally, if the parameter in the ** argument list is a NULL pointer, %Q substitutes the text "NULL" (without ** single quotes).)^ So, for example, one could say: ** **
**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
**  sqlite3_exec(db, zSQL, 0, 0, 0);
**  sqlite3_free(zSQL);
** 
** ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. ** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence ** does not include operating-system specific VFS implementation. The ** Windows VFS uses native malloc() and free() for some operations. ** ** ^The sqlite3_malloc() routine returns a pointer to a block ** of memory at least N bytes in length, where N is the parameter. ** ^If sqlite3_malloc() is unable to obtain sufficient free ** memory, it returns a NULL pointer. ^If the parameter N to ** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns ** a NULL pointer. ** ** ^Calling sqlite3_free() with a pointer previously returned ** by sqlite3_malloc() or sqlite3_realloc() releases that memory so ** that it might be reused. ^The sqlite3_free() routine is ** a no-op if is called with a NULL pointer. Passing a NULL pointer ** to sqlite3_free() is harmless. After being freed, memory ** should neither be read nor written. Even reading previously freed ** memory might result in a segmentation fault or other severe error. ** Memory corruption, a segmentation fault, or other severe error ** might result if sqlite3_free() is called with a non-NULL pointer that ** was not obtained from sqlite3_malloc() or sqlite3_realloc(). ** ** ^(The sqlite3_realloc() interface attempts to resize a ** prior memory allocation to be at least N bytes, where N is the ** second parameter. The memory allocation to be resized is the first ** parameter.)^ ^ If the first parameter to sqlite3_realloc() ** is a NULL pointer then its behavior is identical to calling ** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). ** ^If the second parameter to sqlite3_realloc() is zero or ** negative then the behavior is exactly the same as calling ** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). ** ^sqlite3_realloc() returns a pointer to a memory allocation ** of at least N bytes in size or NULL if sufficient memory is unavailable. ** ^If M is the size of the prior allocation, then min(N,M) bytes ** of the prior allocation are copied into the beginning of buffer returned ** by sqlite3_realloc() and the prior allocation is freed. ** ^If sqlite3_realloc() returns NULL, then the prior allocation ** is not freed. ** ** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. ** ** In SQLite version 3.5.0 and 3.5.1, it was possible to define ** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in ** implementation of these routines to be omitted. That capability ** is no longer provided. Only built-in memory allocators can be used. ** ** The Windows OS interface layer calls ** the system malloc() and free() directly when converting ** filenames between the UTF-8 encoding used by SQLite ** and whatever filename encoding is used by the particular Windows ** installation. Memory allocation errors are detected, but ** they are reported back as [SQLITE_CANTOPEN] or ** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] ** must be either NULL or else pointers obtained from a prior ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. ** ** The application must not read or write any part of ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ SQLITE_API void *sqlite3_malloc(int); SQLITE_API void *sqlite3_realloc(void*, int); SQLITE_API void sqlite3_free(void*); /* ** CAPI3REF: Memory Allocator Statistics ** ** SQLite provides these two interfaces for reporting on the status ** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] ** routines, which form the built-in memory allocation subsystem. ** ** ^The [sqlite3_memory_used()] routine returns the number of bytes ** of memory currently outstanding (malloced but not freed). ** ^The [sqlite3_memory_highwater()] routine returns the maximum ** value of [sqlite3_memory_used()] since the high-water mark ** was last reset. ^The values returned by [sqlite3_memory_used()] and ** [sqlite3_memory_highwater()] include any overhead ** added by SQLite in its implementation of [sqlite3_malloc()], ** but not overhead added by the any underlying system library ** routines that [sqlite3_malloc()] may call. ** ** ^The memory high-water mark is reset to the current value of ** [sqlite3_memory_used()] if and only if the parameter to ** [sqlite3_memory_highwater()] is true. ^The value returned ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ SQLITE_API sqlite3_int64 sqlite3_memory_used(void); SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for ** the build-in random() and randomblob() SQL functions. This interface allows ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. ** ** ^The first time this routine is invoked (either internally or by ** the application) the PRNG is seeded using randomness obtained ** from the xRandomness method of the default [sqlite3_vfs] object. ** ^On all subsequent invocations, the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. ** ^The authorizer callback is invoked as SQL statements are being compiled ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], ** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various ** points during the compilation process, as logic is being created ** to perform various actions, the authorizer callback is invoked to ** see if those actions are allowed. ^The authorizer callback should ** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the ** specific action but allow the SQL statement to continue to be ** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be ** rejected with an error. ^If the authorizer callback returns ** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] ** then the [sqlite3_prepare_v2()] or equivalent call that triggered ** the authorizer will fail with an error message. ** ** When the callback returns [SQLITE_OK], that means the operation ** requested is ok. ^When the callback returns [SQLITE_DENY], the ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that ** access is denied. ** ** ^The first parameter to the authorizer callback is a copy of the third ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter ** to the callback is an integer [SQLITE_COPY | action code] that specifies ** the particular action to be authorized. ^The third through sixth parameters ** to the callback are zero-terminated strings that contain additional ** details about the action to be authorized. ** ** ^If the action code is [SQLITE_READ] ** and the callback returns [SQLITE_IGNORE] then the ** [prepared statement] statement is constructed to substitute ** a NULL value in place of the table column that would have ** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] ** return can be used to deny an untrusted user access to individual ** columns of a table. ** ^If the action code is [SQLITE_DELETE] and the callback returns ** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the ** [truncate optimization] is disabled and all rows are deleted individually. ** ** An authorizer is used when [sqlite3_prepare | preparing] ** SQL statements from an untrusted source, to ensure that the SQL statements ** do not try to access data they are not allowed to see, or that they do not ** try to execute malicious statements that damage the database. For ** example, an application may allow a user to enter arbitrary ** SQL queries for evaluation by a database. But the application does ** not want the user to be able to make arbitrary changes to the ** database. An authorizer could then be put in place while the ** user-entered SQL is being [sqlite3_prepare | prepared] that ** disallows everything except [SELECT] statements. ** ** Applications that need to process SQL from untrusted sources ** might also consider lowering resource limits using [sqlite3_limit()] ** and limiting database size using the [max_page_count] [PRAGMA] ** in addition to using an authorizer. ** ** ^(Only a single authorizer can be in place on a database connection ** at a time. Each call to sqlite3_set_authorizer overrides the ** previous call.)^ ^Disable the authorizer by installing a NULL callback. ** The authorizer is disabled by default. ** ** The authorizer callback must not do anything that will modify ** the database connection that invoked the authorizer callback. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the ** statement might be re-prepared during [sqlite3_step()] due to a ** schema change. Hence, the application should ensure that the ** correct authorizer callback remains in place during the [sqlite3_step()]. ** ** ^Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not ** performed during statement evaluation in [sqlite3_step()], unless ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData ); /* ** CAPI3REF: Authorizer Return Codes ** ** The [sqlite3_set_authorizer | authorizer callback function] must ** return either [SQLITE_OK] or one of these two constants in order ** to signal SQLite whether or not the action is permitted. See the ** [sqlite3_set_authorizer | authorizer documentation] for additional ** information. ** ** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] ** from the [sqlite3_vtab_on_conflict()] interface. */ #define SQLITE_DENY 1 /* Abort the SQL statement with an error */ #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ /* ** CAPI3REF: Authorizer Action Codes ** ** The [sqlite3_set_authorizer()] interface registers a callback function ** that is invoked to authorize certain SQL statement actions. The ** second parameter to the callback is an integer code that specifies ** what action is being authorized. These are the integer action codes that ** the authorizer callback may be passed. ** ** These action code values signify what kind of operation is to be ** authorized. The 3rd and 4th parameters to the authorization ** callback function will be parameters or NULL depending on which of these ** codes is used as the second parameter. ^(The 5th parameter to the ** authorizer callback is the name of the database ("main", "temp", ** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback ** is the name of the inner-most trigger or view that is responsible for ** the access attempt or NULL if this access attempt is directly from ** top-level SQL code. */ /******************************************* 3rd ************ 4th ***********/ #define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ #define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ #define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ #define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ #define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ #define SQLITE_CREATE_VIEW 8 /* View Name NULL */ #define SQLITE_DELETE 9 /* Table Name NULL */ #define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ #define SQLITE_DROP_TABLE 11 /* Table Name NULL */ #define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ #define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ #define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ #define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ #define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ #define SQLITE_DROP_VIEW 17 /* View Name NULL */ #define SQLITE_INSERT 18 /* Table Name NULL */ #define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ #define SQLITE_READ 20 /* Table Name Column Name */ #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* Operation NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ #define SQLITE_ATTACH 24 /* Filename NULL */ #define SQLITE_DETACH 25 /* Database Name NULL */ #define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ #define SQLITE_REINDEX 27 /* Index Name NULL */ #define SQLITE_ANALYZE 28 /* Table Name NULL */ #define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ /* ** CAPI3REF: Tracing And Profiling Functions ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** ** ^The callback function registered by sqlite3_trace() is invoked at ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite ** might provide greater resolution on the profiler callback. The ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: Query Progress Callbacks ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the ** callback function X. ^The parameter N is the number of ** [virtual machine instructions] that are evaluated between successive ** invocations of the callback X. ** ** ^Only a single progress handler may be defined at one time per ** [database connection]; setting a new progress handler cancels the ** old one. ^Setting parameter X to NULL disables the progress handler. ** ^The progress handler is also disabled by setting N to a value less ** than 1. ** ** ^If the progress callback returns non-zero, the operation is ** interrupted. This feature can be used to implement a ** "Cancel" button on a GUI progress dialog box. ** ** The progress handler callback must not do anything that will modify ** the database connection that invoked the progress handler. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** */ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte ** order for sqlite3_open16(). ^(A [database connection] handle is usually ** returned in *ppDb, even if an error occurs. The only exception is that ** if SQLite is unable to allocate memory to hold the [sqlite3] object, ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] ** object.)^ ^(If the database is opened (and/or created) successfully, then ** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The ** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** ** ^The default encoding for the database will be UTF-8 if ** sqlite3_open() or sqlite3_open_v2() is called and ** UTF-16 in the native byte order if sqlite3_open16() is used. ** ** Whether or not an error occurs when it is opened, resources ** associated with the [database connection] handle should be released by ** passing it to [sqlite3_close()] when it is no longer required. ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. ^(The flags parameter to ** sqlite3_open_v2() can take one of ** the following three values, optionally combined with the ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], ** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ ** **
** ^(
[SQLITE_OPEN_READONLY]
**
The database is opened in read-only mode. If the database does not ** already exist, an error is returned.
)^ ** ** ^(
[SQLITE_OPEN_READWRITE]
**
The database is opened for reading and writing if possible, or reading ** only if the file is write protected by the operating system. In either ** case the database must already exist, otherwise an error is returned.
)^ ** ** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
**
The database is opened for reading and writing, and is created if ** it does not already exist. This is the behavior that is always used for ** sqlite3_open() and sqlite3_open16().
)^ **
** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection ** opens in the multi-thread [threading mode] as long as the single-thread ** mode has not been set at compile-time or start-time. ^If the ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens ** in the serialized [threading mode] unless single-thread was ** previously selected at compile-time or start-time. ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be ** eligible to use [shared cache mode], regardless of whether or not shared ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not ** participate in [shared cache mode] even if it is enabled. ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database ** is created for the connection. ^This in-memory database will vanish when ** the database connection is closed. Future versions of SQLite might ** make use of additional special filenames that begin with the ":" character. ** It is recommended that when a database filename actually does begin with ** a ":" character you should prefix the filename with a pathname such as ** "./" to avoid ambiguity. ** ** ^If the filename is an empty string, then a private, temporary ** on-disk database will be created. ^This private database will be ** automatically deleted as soon as the database connection is closed. ** ** [[URI filenames in sqlite3_open()]]

URI Filenames

** ** ^If [URI filename] interpretation is enabled, and the filename argument ** begins with "file:", then the filename is interpreted as a URI. ^URI ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is ** set in the fourth argument to sqlite3_open_v2(), or if it has ** been enabled globally using the [SQLITE_CONFIG_URI] option with the ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. ** As of SQLite version 3.7.7, URI filename interpretation is turned off ** by default, but future releases of SQLite might enable URI filename ** interpretation by default. See "[URI filenames]" for additional ** information. ** ** URI filenames are parsed according to RFC 3986. ^If the URI contains an ** authority, then it must be either an empty string or the string ** "localhost". ^If the authority is not an empty string or "localhost", an ** error is returned to the caller. ^The fragment component of a URI, if ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file ** which contains the database. ^If the path begins with a '/' character, ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. ** ^On windows, the first component of an absolute path ** is a drive specification (e.g. "C:"). ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. ** SQLite interprets the following three query parameters: ** **
    **
  • vfs: ^The "vfs" parameter may be used to specify the name of ** a VFS object that provides the operating system interface that should ** be used to access the database file on disk. ^If this option is set to ** an empty string the default VFS object is used. ^Specifying an unknown ** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is ** present, then the VFS specified by the option takes precedence over ** the value passed as the fourth parameter to sqlite3_open_v2(). ** **
  • mode: ^(The mode parameter may be set to either "ro", "rw" or ** "rwc". Attempting to set it to any other value is an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the ** third argument to sqlite3_prepare_v2(). ^If the mode option is set to ** "rw", then the database is opened for read-write (but not create) ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had ** been set. ^Value "rwc" is equivalent to setting both ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is ** used, it is an error to specify a value for the mode parameter that is ** less restrictive than that specified by the flags passed as the third ** parameter. ** **
  • cache: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behaviour requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. **
** ** ^Specifying an unknown parameter in the query component of a URI is not an ** error. Future versions of SQLite might understand additional query ** parameters. See "[query parameters with special meaning to SQLite]" for ** additional information. ** ** [[URI filename examples]]

URI filename examples

** ** **
URI filenames Results **
file:data.db ** Open the file "data.db" in the current directory. **
file:/home/fred/data.db
** file:///home/fred/data.db
** file://localhost/home/fred/data.db
** Open the database file "/home/fred/data.db". **
file://darkstar/home/fred/data.db ** An error. "darkstar" is not a recognized authority. **
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db ** Windows only: Open the file "data.db" on fred's desktop on drive ** C:. Note that the %20 escaping in this example is not strictly ** necessary - space characters can be used literally ** in URI filenames. **
file:data.db?mode=ro&cache=private ** Open file "data.db" in the current directory for read-only access. ** Regardless of whether or not shared-cache mode is enabled by ** default, use a private cache. **
file:/home/fred/data.db?vfs=unix-nolock ** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". **
file:data.db?mode=readonly ** An error. "readonly" is not a valid option for the "mode" parameter. **
** ** ^URI hexadecimal escape sequences (%HH) are supported within the path and ** query components of a URI. A hexadecimal escape sequence consists of a ** percent sign - "%" - followed by exactly two hexadecimal digits ** specifying an octet value. ^Before the path or query components of a ** URI filename are interpreted, they are encoded using UTF-8 and all ** hexadecimal escape sequences replaced by a single byte containing the ** corresponding octet. If this process generates an invalid UTF-8 encoding, ** the results are undefined. ** ** Note to Windows users: The encoding used for the filename argument ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever ** codepage is currently defined. Filenames containing international ** characters must be converted to UTF-8 prior to passing them into ** sqlite3_open() or sqlite3_open_v2(). */ SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); /* ** CAPI3REF: Obtain Values For URI Parameters ** ** This is a utility routine, useful to VFS implementations, that checks ** to see if a database file was a URI that contained a specific query ** parameter, and if so obtains the value of the query parameter. ** ** The zFilename argument is the filename pointer passed into the xOpen() ** method of a VFS implementation. The zParam argument is the name of the ** query parameter we seek. This routine returns the value of the zParam ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. ** ** If the zFilename argument to this function is not a pointer that SQLite ** passed into the xOpen VFS method, then the behavior of this routine ** is undefined and probably undesirable. */ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); /* ** CAPI3REF: Error Codes And Messages ** ** ^The sqlite3_errcode() interface returns the numeric [result code] or ** [extended result code] for the most recent failed sqlite3_* API call ** associated with a [database connection]. If a prior API call failed ** but the most recent API call succeeded, the return value from ** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() ** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these ** interfaces always report the most recent result. To avoid ** this, each thread can obtain exclusive use of the [database connection] D ** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning ** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after ** all calls to the interfaces listed here are completed. ** ** If an interface fails with SQLITE_MISUSE, that means the interface ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ SQLITE_API int sqlite3_errcode(sqlite3 *db); SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*); /* ** CAPI3REF: SQL Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement. ** This object is variously known as a "prepared statement" or a ** "compiled SQL statement" or simply as a "statement". ** ** The life of a statement object goes something like this: ** **
    **
  1. Create the object using [sqlite3_prepare_v2()] or a related ** function. **
  2. Bind values to [host parameters] using the sqlite3_bind_*() ** interfaces. **
  3. Run the SQL by calling [sqlite3_step()] one or more times. **
  4. Reset the statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. **
  5. Destroy the object using [sqlite3_finalize()]. **
** ** Refer to documentation on individual methods above for additional ** information. */ typedef struct sqlite3_stmt sqlite3_stmt; /* ** CAPI3REF: Run-time Limits ** ** ^(This interface allows the size of various constructs to be limited ** on a connection by connection basis. The first parameter is the ** [database connection] whose limit is to be set or queried. The ** second parameter is one of the [limit categories] that define a ** class of constructs to be size limited. The third parameter is the ** new limit for that construct.)^ ** ** ^If the new limit is a negative number, the limit is unchanged. ** ^(For each limit category SQLITE_LIMIT_NAME there is a ** [limits | hard upper bound] ** set at compile-time by a C preprocessor macro called ** [limits | SQLITE_MAX_NAME]. ** (The "_LIMIT_" in the name is changed to "_MAX_".))^ ** ^Attempts to increase a limit above its hard upper bound are ** silently truncated to the hard upper bound. ** ** ^Regardless of whether or not the limit was changed, the ** [sqlite3_limit()] interface returns the prior value of the limit. ** ^Hence, to find the current value of a limit without changing it, ** simply invoke this interface with the third parameter set to -1. ** ** Run-time limits are intended for use in applications that manage ** both their own internal database and also databases that are controlled ** by untrusted external sources. An example application might be a ** web browser that has its own databases for storing history and ** separate databases controlled by JavaScript applications downloaded ** off the Internet. The internal databases can be given the ** large, default limits. Databases managed by external sources can ** be given much smaller limits designed to prevent a denial of service ** attack. Developers might also want to use the [sqlite3_set_authorizer()] ** interface to further control untrusted SQL. The size of the database ** created by an untrusted script can be contained using the ** [max_page_count] [PRAGMA]. ** ** New run-time limit categories may be added in future releases. */ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories ** KEYWORDS: {limit category} {*limit categories} ** ** These constants define various performance limits ** that can be lowered at run-time using [sqlite3_limit()]. ** The synopsis of the meanings of the various limits is shown below. ** Additional information is available at [limits | Limits in SQLite]. ** **
** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
**
The maximum size of any string or BLOB or table row, in bytes.
)^ ** ** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
**
The maximum length of an SQL statement, in bytes.
)^ ** ** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
**
The maximum number of columns in a table definition or in the ** result set of a [SELECT] or the maximum number of columns in an index ** or in an ORDER BY or GROUP BY clause.
)^ ** ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
**
The maximum depth of the parse tree on any expression.
)^ ** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
**
The maximum number of terms in a compound SELECT statement.
)^ ** ** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
**
The maximum number of instructions in a virtual machine program ** used to implement an SQL statement. This limit is not currently ** enforced, though that might be added in some future release of ** SQLite.
)^ ** ** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
**
The maximum number of arguments on a function.
)^ ** ** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
**
The maximum number of [ATTACH | attached databases].)^
** ** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] ** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
**
The maximum length of the pattern argument to the [LIKE] or ** [GLOB] operators.
)^ ** ** [[SQLITE_LIMIT_VARIABLE_NUMBER]] ** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
**
The maximum index number of any [parameter] in an SQL statement.)^ ** ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
**
The maximum depth of recursion for triggers.
)^ **
*/ #define SQLITE_LIMIT_LENGTH 0 #define SQLITE_LIMIT_SQL_LENGTH 1 #define SQLITE_LIMIT_COLUMN 2 #define SQLITE_LIMIT_EXPR_DEPTH 3 #define SQLITE_LIMIT_COMPOUND_SELECT 4 #define SQLITE_LIMIT_VDBE_OP 5 #define SQLITE_LIMIT_FUNCTION_ARG 6 #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. ** ** The first argument, "db", is a [database connection] obtained from a ** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or ** [sqlite3_open16()]. The database connection must not have been closed. ** ** The second argument, "zSql", is the statement to be compiled, encoded ** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() ** use UTF-16. ** ** ^If the nByte argument is less than zero, then zSql is read up to the ** first zero terminator. ^If nByte is non-negative, then it is the maximum ** number of bytes read from zSql. ^When nByte is non-negative, the ** zSql string ends at either the first '\000' or '\u0000' character or ** the nByte-th byte, whichever comes first. If the caller knows ** that the supplied string is nul-terminated, then there is a small ** performance advantage to be gained by passing an nByte parameter that ** is equal to the number of bytes in the input string including ** the nul-terminator bytes as this saves SQLite from having to ** make a copy of the input string. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only ** compile the first statement in zSql, so *pzTail is left pointing to ** what remains uncompiled. ** ** ^*ppStmt is left pointing to a compiled [prepared statement] that can be ** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set ** to NULL. ^If the input text contains no SQL (if the input is an empty ** string or a comment) then *ppStmt is set to NULL. ** The calling procedure is responsible for deleting the compiled ** SQL statement using [sqlite3_finalize()] after it has finished with it. ** ppStmt may not be NULL. ** ** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; ** otherwise an [error code] is returned. ** ** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are ** recommended for all new programs. The two older interfaces are retained ** for backwards compatibility, but their use is discouraged. ** ^In the "v2" interfaces, the prepared statement ** that is returned (the [sqlite3_stmt] object) contains a copy of the ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: ** **
    **
  1. ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL ** statement and try to run it again. **
  2. ** **
  3. ** ^When an error occurs, [sqlite3_step()] will return one of the detailed ** [error codes] or [extended error codes]. ^The legacy behavior was that ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code ** and the application would have to make a second call to [sqlite3_reset()] ** in order to find the underlying cause of the problem. With the "v2" prepare ** interfaces, the underlying reason for the error is returned immediately. **
  4. ** **
  5. ** ^If the specific value bound to [parameter | host parameter] in the ** WHERE clause might influence the choice of query plan for a statement, ** then the statement will be automatically recompiled, as if there had been ** a schema change, on the first [sqlite3_step()] call following any change ** to the [sqlite3_bind_text | bindings] of that [parameter]. ** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. ** the **
  6. **
*/ SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* ** CAPI3REF: Retrieving Statement SQL ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was ** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to ** the content of the database file. ** ** Note that [application-defined SQL functions] or ** [virtual tables] might change the database indirectly as a side effect. ** ^(For example, if an application defines a function "eval()" that ** calls [sqlite3_exec()], then the following SQL statement would ** change the database file through side-effects: ** **
**    SELECT eval('DELETE FROM t1') FROM t2;
** 
** ** But because the [SELECT] statement does not change the database file ** directly, sqlite3_stmt_readonly() would still return true.)^ ** ** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, ** since the statements themselves do not actually modify the database but ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Dynamically Typed Value Object ** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} ** ** SQLite uses the sqlite3_value object to represent all values ** that can be stored in a database table. SQLite uses dynamic typing ** for the values it stores. ^Values stored in sqlite3_value objects ** can be integers, floating point values, strings, BLOBs, or NULL. ** ** An sqlite3_value object may be either "protected" or "unprotected". ** Some interfaces require a protected sqlite3_value. Other interfaces ** will accept either a protected or an unprotected sqlite3_value. ** Every interface that accepts sqlite3_value arguments specifies ** whether or not it requires a protected sqlite3_value. ** ** The terms "protected" and "unprotected" refer to whether or not ** a mutex is held. An internal mutex is held for a protected ** sqlite3_value object but no mutex is held for an unprotected ** sqlite3_value object. If SQLite is compiled to be single-threaded ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) ** or if SQLite is run in one of reduced mutex modes ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] ** then there is no distinction between protected and unprotected ** sqlite3_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite3_value objects even when not strictly required. ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used with ** [sqlite3_result_value()] and [sqlite3_bind_value()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. */ typedef struct Mem sqlite3_value; /* ** CAPI3REF: SQL Function Context Object ** ** The context in which an SQL function executes is stored in an ** sqlite3_context object. ^A pointer to an sqlite3_context object ** is always first parameter to [application-defined SQL functions]. ** The application-defined SQL function implementation will pass this ** pointer through into calls to [sqlite3_result_int | sqlite3_result()], ** [sqlite3_aggregate_context()], [sqlite3_user_data()], ** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], ** and/or [sqlite3_set_auxdata()]. */ typedef struct sqlite3_context sqlite3_context; /* ** CAPI3REF: Binding Values To Prepared Statements ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} ** ** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, ** literals may be replaced by a [parameter] that matches one of following ** templates: ** **
    **
  • ? **
  • ?NNN **
  • :VVV **
  • @VVV **
  • $VVV **
** ** In the templates above, NNN represents an integer literal, ** and VVV represents an alphanumeric identifier.)^ ^The values of these ** parameters (also called "host parameter names" or "SQL parameters") ** can be set using the sqlite3_bind_*() routines defined here. ** ** ^The first argument to the sqlite3_bind_*() routines is always ** a pointer to the [sqlite3_stmt] object returned from ** [sqlite3_prepare_v2()] or its variants. ** ** ^The second argument is the index of the SQL parameter to be set. ** ^The leftmost SQL parameter has an index of 1. ^When the same named ** SQL parameter is used more than once, second and subsequent ** occurrences have the same index as the first occurrence. ** ^The index for named parameters can be looked up using the ** [sqlite3_bind_parameter_index()] API if desired. ^The index ** for "?NNN" parameters is the value of NNN. ** ^The NNN value must be between 1 and the [sqlite3_limit()] ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of bytes in the value, not the number of characters.)^ ** ^If the fourth parameter is negative, the length of the string is ** the number of bytes up to the first zero terminator. ** If a non-negative fourth parameter is provided to sqlite3_bind_text() ** or sqlite3_bind_text16() then that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called ** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), ** sqlite3_bind_text(), or sqlite3_bind_text16() fails. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. ** ^If the fifth argument has the value [SQLITE_TRANSIENT], then ** SQLite makes its own private copy of the data immediately, before ** the sqlite3_bind_*() routine returns. ** ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that ** is filled with zeroes. ^A zeroblob uses a fixed amount of memory ** (just an integer to hold its size) while it is being processed. ** Zeroblobs are intended to serve as placeholders for BLOBs whose ** content is later written using ** [sqlite3_blob_open | incremental BLOB I/O] routines. ** ^A negative value for the zeroblob results in a zero-length BLOB. ** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() ** routine is passed a [prepared statement] that has been finalized, the ** result is undefined and probably harmful. ** ** ^Bindings are not cleared by the [sqlite3_reset()] routine. ** ^Unbound parameters are interpreted as NULL. ** ** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an ** [error code] if anything goes wrong. ** ^[SQLITE_RANGE] is returned if the parameter ** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. ** ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the ** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as ** placeholders for values that are [sqlite3_bind_blob | bound] ** to the parameters at a later time. ** ** ^(This routine actually returns the index of the largest (rightmost) ** parameter. For all forms except ?NNN, this will correspond to the ** number of unique parameters. If parameters of the ?NNN form are used, ** there may be gaps in the list.)^ ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter ** ** ^The sqlite3_bind_parameter_name(P,N) interface returns ** the name of the N-th [SQL parameter] in the [prepared statement] P. ** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" ** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" ** respectively. ** In other words, the initial ":" or "$" or "@" or "?" ** is included as part of the name.)^ ** ^Parameters of the form "?" without a following integer have no name ** and are referred to as "nameless" or "anonymous parameters". ** ** ^The first host parameter has an index of 1, not 0. ** ** ^If the value N is out of range or if the N-th parameter is ** nameless, then NULL is returned. ^The returned string is ** always in UTF-8 encoding even if the named parameter was ** originally specified as UTF-16 in [sqlite3_prepare16()] or ** [sqlite3_prepare16_v2()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second ** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero ** is returned if no matching parameter is found. ^The parameter ** name must be given in UTF-8 even if the original statement ** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL ** statement that does not return data (for example an [UPDATE]). ** ** See also: [sqlite3_data_count()] */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() ** interface returns a pointer to a zero-terminated UTF-8 string ** and sqlite3_column_name16() returns a pointer to a zero-terminated ** UTF-16 string. ^The first parameter is the [prepared statement] ** that implements the [SELECT] statement. ^The second parameter is the ** column number. ^The leftmost column is number 0. ** ** ^The returned string pointer is valid until either the [prepared statement] ** is destroyed by [sqlite3_finalize()] or until the statement is automatically ** reprepared by the first call to [sqlite3_step()] for a particular run ** or until the next call to ** sqlite3_column_name() or sqlite3_column_name16() on the same column. ** ** ^If sqlite3_malloc() fails during the processing of either routine ** (for example during a conversion from UTF-8 to UTF-16) then a ** NULL pointer is returned. ** ** ^The name of a result column is the value of the "AS" clause for ** that column, if there is an AS clause. If there is no AS clause ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in ** [SELECT] statement. ** ^The name of the database or table or column can be returned as ** either a UTF-8 or UTF-16 string. ^The _database_ routines return ** the database name, the _table_ routines return the table name, and ** the origin_ routines return the column name. ** ^The returned string is valid until the [prepared statement] is destroyed ** using [sqlite3_finalize()] or until the statement is automatically ** reprepared by the first call to [sqlite3_step()] for a particular run ** or until the same information is requested ** again in a different encoding. ** ** ^The names returned are the original un-aliased names of the ** database, table, and column. ** ** ^The first argument to these interfaces is a [prepared statement]. ** ^These functions return information about the Nth result column returned by ** the statement, where N is the second function argument. ** ^The left-most column is column 0 for these routines. ** ** ^If the Nth column returned by the statement is an expression or ** subquery and is not a column value, then all of these functions return ** NULL. ^These routine might also return NULL if a memory allocation error ** occurs. ^Otherwise, they return the name of the attached database, table, ** or column that query result column was extracted from. ** ** ^As with all other SQLite APIs, those whose names end with "16" return ** UTF-16 encoded strings and the other functions return UTF-8. ** ** ^These APIs are only available if the library was compiled with the ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. ** ** If two or more threads call one or more of these routines against the same ** prepared statement and column at the same time then the results are ** undefined. ** ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the ** returned result set of that [SELECT] is a table column (not an ** expression or subquery) then the declared type of the table ** column is returned.)^ ^If the Nth column of the result set is an ** expression or subquery, then a NULL pointer is returned. ** ^The returned string is always UTF-8 encoded. ** ** ^(For example, given the database schema: ** ** CREATE TABLE t1(c1 VARIANT); ** ** and the following statement to be compiled: ** ** SELECT c1 + 1, c1 FROM t1; ** ** this routine would return the string "VARIANT" for the second result ** column (i==1), and a NULL pointer for the first result column (i==0).)^ ** ** ^SQLite uses dynamic run-time typing. ^So just because a column ** is declared to contain a particular type does not mean that the ** data stored in that column is of the declared type. SQLite is ** strongly typed, but the typing is dynamic not static. ^Type ** is associated with individual values, not with the containers ** used to hold those values. */ SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy ** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function ** must be called one or more times to evaluate the statement. ** ** The details of the behavior of the sqlite3_step() interface depend ** on whether the statement was prepared using the newer "v2" interface ** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy ** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the ** new "v2" interface is recommended for new applications but the legacy ** interface will continue to be supported. ** ** ^In the legacy interface, the return value will be either [SQLITE_BUSY], ** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. ** ^With the "v2" interface, any of the other [result codes] or ** [extended result codes] might be returned as well. ** ** ^[SQLITE_BUSY] means that the database engine was unable to acquire the ** database locks it needs to do its job. ^If the statement is a [COMMIT] ** or occurs outside of an explicit transaction, then you can retry the ** statement. If the statement is not a [COMMIT] and occurs within an ** explicit transaction then you should rollback the transaction before ** continuing. ** ** ^[SQLITE_DONE] means that the statement has finished executing ** successfully. sqlite3_step() should not be called again on this virtual ** machine without first calling [sqlite3_reset()] to reset the virtual ** machine back to its initial state. ** ** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] ** is returned each time a new row of data is ready for processing by the ** caller. The values may be accessed using the [column access functions]. ** sqlite3_step() is called again to retrieve the next row of data. ** ** ^[SQLITE_ERROR] means that a run-time error (such as a constraint ** violation) has occurred. sqlite3_step() should not be called again on ** the VM. More information may be found by calling [sqlite3_errmsg()]. ** ^With the legacy interface, a more specific error code (for example, ** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) ** can be obtained by calling [sqlite3_reset()] on the ** [prepared statement]. ^In the "v2" interface, ** the more specific error code is returned directly by sqlite3_step(). ** ** [SQLITE_MISUSE] means that the this routine was called inappropriately. ** Perhaps it was called on a [prepared statement] that has ** already been [sqlite3_finalize | finalized] or on one that had ** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could ** be the case that the same database connection is being used by two or ** more threads at the same moment in time. ** ** For all versions of SQLite up to and including 3.6.23.1, a call to ** [sqlite3_reset()] was required after sqlite3_step() returned anything ** other than [SQLITE_ROW] before any subsequent invocation of ** sqlite3_step(). Failure to reset the prepared statement using ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from ** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began ** calling [sqlite3_reset()] automatically in this circumstance rather ** than returning [SQLITE_MISUSE]. This is not considered a compatibility ** break because any application that ever receives an SQLITE_MISUSE error ** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option ** can be used to restore the legacy behavior. ** ** Goofy Interface Alert: In the legacy interface, the sqlite3_step() ** API always returns a generic error code, [SQLITE_ERROR], following any ** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call ** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the ** specific [error codes] that better describes the error. ** We admit that this is a goofy design. The problem has been fixed ** with the "v2" interface. If you prepare all of your SQL statements ** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead ** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. ** ^If prepared statement P does not have results ready to return ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of ** interfaces) then sqlite3_data_count(P) returns 0. ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to ** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) ** will return non-zero if previous call to [sqlite3_step](P) returned ** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] ** where it always returns zero since each step of that multi-step ** pragma returns 0 columns of data. ** ** See also: [sqlite3_column_count()] */ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes ** KEYWORDS: SQLITE_TEXT ** ** ^(Every value in SQLite has one of five fundamental datatypes: ** **
    **
  • 64-bit signed integer **
  • 64-bit IEEE floating point number **
  • string **
  • BLOB **
  • NULL **
)^ ** ** These constants are codes for each of those types. ** ** Note that the SQLITE_TEXT constant was also used in SQLite version 2 ** for a completely different meaning. Software that links against both ** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not ** SQLITE_TEXT. */ #define SQLITE_INTEGER 1 #define SQLITE_FLOAT 2 #define SQLITE_BLOB 4 #define SQLITE_NULL 5 #ifdef SQLITE_TEXT # undef SQLITE_TEXT #else # define SQLITE_TEXT 3 #endif #define SQLITE3_TEXT 3 /* ** CAPI3REF: Result Values From A Query ** KEYWORDS: {column access functions} ** ** These routines form the "result set" interface. ** ** ^These routines return information about a single column of the current ** result row of a query. ^In every case the first argument is a pointer ** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] ** that was returned from [sqlite3_prepare_v2()] or one of its variants) ** and the second argument is the index of the column for which information ** should be returned. ^The leftmost column of the result set has the index 0. ** ^The number of columns in the result can be determined using ** [sqlite3_column_count()]. ** ** If the SQL statement does not currently point to a valid row, or if the ** column index is out of range, the result is undefined. ** These routines may only be called when the most recent call to ** [sqlite3_step()] has returned [SQLITE_ROW] and neither ** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. ** If any of these routines are called after [sqlite3_reset()] or ** [sqlite3_finalize()] or after [sqlite3_step()] has returned ** something other than [SQLITE_ROW], the results are undefined. ** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] ** are called from a different thread while any of these routines ** are pending, then the results are undefined. ** ** ^The sqlite3_column_type() routine returns the ** [SQLITE_INTEGER | datatype code] for the initial data type ** of the result column. ^The returned value is one of [SQLITE_INTEGER], ** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value ** returned by sqlite3_column_type() is only meaningful if no type ** conversions have occurred as described below. After a type conversion, ** the value returned by sqlite3_column_type() is undefined. Future ** versions of SQLite may change the behavior of sqlite3_column_type() ** following a type conversion. ** ** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() ** routine returns the number of bytes in that BLOB or string. ** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts ** the string to UTF-8 and then returns the number of bytes. ** ^If the result is a numeric value then sqlite3_column_bytes() uses ** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns ** the number of bytes in that string. ** ^If the result is NULL, then sqlite3_column_bytes() returns zero. ** ** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() ** routine returns the number of bytes in that BLOB or string. ** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts ** the string to UTF-16 and then returns the number of bytes. ** ^If the result is a numeric value then sqlite3_column_bytes16() uses ** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns ** the number of bytes in that string. ** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. ** ** ^The values returned by [sqlite3_column_bytes()] and ** [sqlite3_column_bytes16()] do not include the zero terminators at the end ** of the string. ^For clarity: the values returned by ** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of ** bytes in the string, not the number of characters. ** ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), ** even empty strings, are always zero terminated. ^The return ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. ** ** ^The object returned by [sqlite3_column_value()] is an ** [unprotected sqlite3_value] object. An unprotected sqlite3_value object ** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. ** If the [unprotected sqlite3_value] object returned by ** [sqlite3_column_value()] is used in any other way, including calls ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ** or [sqlite3_value_bytes()], then the behavior is undefined. ** ** These routines attempt to convert the value where appropriate. ^For ** example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to perform the ** conversion automatically. ^(The following table details the conversions ** that are applied: ** **
** **
Internal
Type
Requested
Type
Conversion ** **
NULL INTEGER Result is 0 **
NULL FLOAT Result is 0.0 **
NULL TEXT Result is NULL pointer **
NULL BLOB Result is NULL pointer **
INTEGER FLOAT Convert from integer to float **
INTEGER TEXT ASCII rendering of the integer **
INTEGER BLOB Same as INTEGER->TEXT **
FLOAT INTEGER Convert from float to integer **
FLOAT TEXT ASCII rendering of the float **
FLOAT BLOB Same as FLOAT->TEXT **
TEXT INTEGER Use atoi() **
TEXT FLOAT Use atof() **
TEXT BLOB No change **
BLOB INTEGER Convert to TEXT then use atoi() **
BLOB FLOAT Convert to TEXT then use atof() **
BLOB TEXT Add a zero terminator if needed **
**
)^ ** ** The table above makes reference to standard C library functions atoi() ** and atof(). SQLite does not really use these functions. It has its ** own equivalent internal routines. The atoi() and atof() names are ** used in the table for brevity and because they are familiar to most ** C programmers. ** ** Note that when type conversions occur, pointers returned by prior ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or ** sqlite3_column_text16() may be invalidated. ** Type conversions and pointer invalidations might occur ** in the following cases: ** **
    **
  • The initial content is a BLOB and sqlite3_column_text() or ** sqlite3_column_text16() is called. A zero-terminator might ** need to be added to the string.
  • **
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or ** sqlite3_column_text16() is called. The content must be converted ** to UTF-16.
  • **
  • The initial content is UTF-16 text and sqlite3_column_bytes() or ** sqlite3_column_text() is called. The content must be converted ** to UTF-8.
  • **
** ** ^Conversions between UTF-16be and UTF-16le are always done in place and do ** not invalidate a prior pointer, though of course the content of the buffer ** that the prior pointer references will have been modified. Other kinds ** of conversion are done in place when it is possible, but sometimes they ** are not possible and in those cases prior pointers are invalidated. ** ** The safest and easiest to remember policy is to invoke these routines ** in one of the following ways: ** **
    **
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • **
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • **
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • **
** ** In other words, you should call sqlite3_column_text(), ** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result ** into the desired format, then invoke sqlite3_column_bytes() or ** sqlite3_column_bytes16() to find the size of the result. Do not mix calls ** to sqlite3_column_text() or sqlite3_column_blob() with calls to ** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() ** with calls to sqlite3_column_bytes(). ** ** ^The pointers returned are valid until a type conversion occurs as ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or ** [sqlite3_finalize()] is called. ^The memory space used to hold strings ** and BLOBs is freed automatically. Do not pass the pointers returned ** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** ** ^(If a memory allocation error occurs during the evaluation of any ** of these routines, a default value is returned. The default value ** is either the integer 0, the floating point number 0.0, or a NULL ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors ** or if the statement is never been evaluated, then sqlite3_finalize() returns ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then ** sqlite3_finalize(S) returns the appropriate [error code] or ** [extended error code]. ** ** ^The sqlite3_finalize(S) routine can be called at any point during ** the life cycle of [prepared statement] S: ** before statement S is ever evaluated, after ** one or more calls to [sqlite3_reset()], or after any call ** to [sqlite3_step()] regardless of whether or not the statement has ** completed execution. ** ** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. ** ** The application must finalize every [prepared statement] in order to avoid ** resource leaks. It is a grievous error for the application to try to use ** a prepared statement after it has been finalized. Any use of a prepared ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. ** ^Any SQL statement variables that had values bound to them using ** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. ** Use [sqlite3_clear_bindings()] to reset the bindings. ** ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], ** or if [sqlite3_step(S)] has never before been called on S, ** then [sqlite3_reset(S)] returns [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior ** of existing SQL functions or aggregates. The only differences between ** these routines are the text encoding expected for ** the second parameter (the name of the function being created) ** and the presence or absence of a destructor callback for ** the application data pointer. ** ** ^The first parameter is the [database connection] to which the SQL ** function is to be added. ^If an application uses more than one database ** connection then application-defined SQL functions must be added ** to each database connection separately. ** ** ^The second parameter is the name of the SQL function to be created or ** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 ** representation, exclusive of the zero-terminator. ^Note that the name ** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. ** ^Any attempt to create a function with a longer name ** will result in [SQLITE_MISUSE] being returned. ** ** ^The third parameter (nArg) ** is the number of arguments that the SQL function or ** aggregate takes. ^If this parameter is -1, then the SQL function or ** aggregate may take any number of arguments between 0 and the limit ** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third ** parameter is less than -1 or greater than 127 then the behavior is ** undefined. ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for ** its parameters. Every SQL function implementation must be able to work ** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be ** more efficient with one encoding than another. ^An application may ** invoke sqlite3_create_function() or sqlite3_create_function16() multiple ** times with the same function but with different values of eTextRep. ** ^When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. ** If there is only a single implementation which does not care what text ** encoding is used, then the fourth argument should be [SQLITE_ANY]. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ** aggregate. ^A scalar SQL function requires an implementation of the xFunc ** callback only; NULL pointers must be passed as the xStep and xFinal ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, ** then it is destructor for the application data pointer. ** The destructor is invoked when the function is deleted, either by being ** overloaded or when the database connection closes.)^ ** ^The destructor is also invoked if the call to ** sqlite3_create_function_v2() fails. ** ^When the destructor callback of the tenth parameter is invoked, it ** is passed a single argument which is a copy of the application data ** pointer which was the fifth parameter to sqlite3_create_function_v2(). ** ** ^It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. ^SQLite will use ** the implementation that most closely matches the way in which the ** SQL function is used. ^A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with ** a negative nArg. ^A function where the preferred text encoding ** matches the database encoding is a better ** match than a function where the encoding is different. ** ^A function where the encoding difference is between UTF16le and UTF16be ** is a closer match than a function where the encoding difference is ** between UTF8 and UTF16. ** ** ^Built-in functions may be overloaded by new application-defined functions. ** ** ^An application-defined function is permitted to call other ** SQLite interfaces. However, such calls must not ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void(*xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various ** text encodings supported by SQLite. */ #define SQLITE_UTF8 1 #define SQLITE_UTF16LE 2 #define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* sqlite3_create_function only */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid ** the use of these functions. To help encourage people to avoid ** using these functions, we are not going to tell you what they do. */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on ** the function or aggregate. ** ** The xFunc (for scalar functions) or xStep (for aggregates) parameters ** to [sqlite3_create_function()] and [sqlite3_create_function16()] ** define callbacks that implement the SQL functions and aggregates. ** The 3rd parameter to these callbacks is an array of pointers to ** [protected sqlite3_value] objects. There is one [sqlite3_value] object for ** each parameter to the SQL function. These routines are used to ** extract values from the [sqlite3_value] objects. ** ** These routines work only with [protected sqlite3_value] objects. ** Any attempt to use these routines on an [unprotected sqlite3_value] ** object results in undefined behavior. ** ** ^These routines work just like the corresponding [column access functions] ** except that these routines take a single [protected sqlite3_value] object ** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. ** ** ^The sqlite3_value_text16() interface extracts a UTF-16 string ** in the native byte-order of the host machine. ^The ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces ** extract UTF-16 strings as big-endian and little-endian respectively. ** ** ^(The sqlite3_value_numeric_type() interface attempts to apply ** numeric affinity to the value. This means that an attempt is ** made to convert the value to an integer or floating point. If ** such a conversion is possible without loss of information (in other ** words, if the value is a string that looks like a number) ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); SQLITE_API int sqlite3_value_bytes(sqlite3_value*); SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API double sqlite3_value_double(sqlite3_value*); SQLITE_API int sqlite3_value_int(sqlite3_value*); SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** ** ^The first time the sqlite3_aggregate_context(C,N) routine is called ** for a particular aggregate function, SQLite ** allocates N of memory, zeroes out that memory, and returns a pointer ** to the new memory. ^On second and subsequent calls to ** sqlite3_aggregate_context() for the same aggregate function instance, ** the same buffer is returned. Sqlite3_aggregate_context() is normally ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is ** less than or equal to zero or if a memory allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ** ** The first parameter must be a copy of the ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate ** function. ** ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) ** of the [sqlite3_create_function()] ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. ** ** This routine must be called from the same thread in which ** the application-defined function is running. */ SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) ** of the [sqlite3_create_function()] ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data ** ** The following two functions may be used by scalar SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under ** some circumstances the associated metadata may be preserved. This may ** be used, for example, to add a regular-expression matching scalar ** function. The compiled version of the regular expression is stored as ** metadata associated with the SQL value passed as the regular expression ** pattern. The compiled regular expression can be reused on multiple ** invocations of the same function so that the original pattern string ** does not need to be recompiled on each invocation. ** ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata ** associated by the sqlite3_set_auxdata() function with the Nth argument ** value to the application-defined function. ^If no metadata has been ever ** been set for the Nth argument of the function, or if the corresponding ** function parameter has changed since the meta-data was set, ** then sqlite3_get_auxdata() returns a NULL pointer. ** ** ^The sqlite3_set_auxdata() interface saves the metadata ** pointed to by its 3rd parameter as the metadata for the N-th ** argument of the application-defined function. Subsequent ** calls to sqlite3_get_auxdata() might return this data, if it has ** not been destroyed. ** ^If it is not NULL, SQLite will invoke the destructor ** function given by the 4th parameter to sqlite3_set_auxdata() on ** the metadata when the corresponding function parameter changes ** or when the SQL statement completes, whichever comes first. ** ** SQLite is free to call the destructor and drop metadata on any ** parameter of any function at any time. ^The only guarantee is that ** the destructor will be called before the metadata is dropped. ** ** ^(In practice, metadata is preserved between function calls for ** expressions that are constant at compile time. This includes literal ** values and [parameters].)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior ** ** These are special values for the destructor that is passed in as the ** final argument to routines like [sqlite3_result_blob()]. ^If the destructor ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain ** C++ compilers. See ticket #2191. */ typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) /* ** CAPI3REF: Setting The Result Of An SQL Function ** ** These routines are used by the xFunc or xFinal callbacks that ** implement SQL functions and aggregates. See ** [sqlite3_create_function()] and [sqlite3_create_function16()] ** for additional information. ** ** These functions work very much like the [parameter binding] family of ** functions used to bind values to host parameters in prepared statements. ** Refer to the [SQL parameter] documentation for additional information. ** ** ^The sqlite3_result_blob() interface sets the result from ** an application-defined function to be the BLOB whose content is pointed ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** ** ^The sqlite3_result_zeroblob() interfaces set the result of ** the application-defined function to be a BLOB containing all zero ** bytes and N bytes in size, where N is the value of the 2nd parameter. ** ** ^The sqlite3_result_double() interface sets the result from ** an application-defined function to be a floating point value specified ** by its 2nd argument. ** ** ^The sqlite3_result_error() and sqlite3_result_error16() functions ** cause the implemented SQL function to throw an exception. ** ^SQLite uses the string pointed to by the ** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() ** as the text of an error message. ^SQLite interprets the error ** message string from sqlite3_result_error() as UTF-8. ^SQLite ** interprets the string from sqlite3_result_error16() as UTF-16 in native ** byte order. ^If the third parameter to sqlite3_result_error() ** or sqlite3_result_error16() is negative then SQLite takes as the error ** message all text up through the first zero character. ** ^If the third parameter to sqlite3_result_error() or ** sqlite3_result_error16() is non-negative then SQLite takes that many ** bytes (not characters) from the 2nd parameter as the error message. ** ^The sqlite3_result_error() and sqlite3_result_error16() ** routines make a private copy of the error message text before ** they return. Hence, the calling function can deallocate or ** modify the text after they return without harm. ** ^The sqlite3_result_error_code() function changes the error code ** returned by SQLite as a result of an error in a function. ^By default, ** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** ** ^The sqlite3_result_toobig() interface causes SQLite to throw an error ** indicating that a string or BLOB is too long to represent. ** ** ^The sqlite3_result_nomem() interface causes SQLite to throw an error ** indicating that a memory allocation failed. ** ** ^The sqlite3_result_int() interface sets the return value ** of the application-defined function to be the 32-bit signed integer ** value given in the 2nd argument. ** ^The sqlite3_result_int64() interface sets the return value ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. ** ** ^The sqlite3_result_null() interface sets the return value ** of the application-defined function to be NULL. ** ** ^The sqlite3_result_text(), sqlite3_result_text16(), ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is negative, then SQLite takes result text from the 2nd parameter ** through the first zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined ** function result. If the 3rd parameter is non-negative, then it ** must be the byte offset into the string where the NUL terminator would ** appear if the string where NUL terminated. If any NUL characters occur ** in the string at a byte offset that is less than the value of the 3rd ** parameter, then the resulting string will contain embedded NULs and the ** result of expressions operating on strings with embedded NULs is undefined. ** ^If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that ** function as the destructor on the text or BLOB result when it has ** finished using that result. ** ^If the 4th parameter to the sqlite3_result_text* interfaces or to ** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite ** assumes that the text or BLOB result is in constant space and does not ** copy the content of the parameter nor call a destructor on the content ** when it has finished using that result. ** ^If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT ** then SQLite makes a copy of the result into space obtained from ** from [sqlite3_malloc()] before it returns. ** ** ^The sqlite3_result_value() interface sets the result of ** the application-defined function to be a copy the ** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that the [sqlite3_value] specified in the parameter may change or ** be deallocated after sqlite3_result_value() returns without harm. ** ^A [protected sqlite3_value] object may always be used where an ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** ** If these routines are called from within the different thread ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_double(sqlite3_context*, double); SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); SQLITE_API void sqlite3_result_int(sqlite3_context*, int); SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. ** ** ^The name of the collation is a UTF-8 string ** for sqlite3_create_collation() and sqlite3_create_collation_v2() ** and a UTF-16 string in native byte order for sqlite3_create_collation16(). ** ^Collation names that compare equal according to [sqlite3_strnicmp()] are ** considered to be the same name. ** ** ^(The third argument (eTextRep) must be one of the constants: **
    **
  • [SQLITE_UTF8], **
  • [SQLITE_UTF16LE], **
  • [SQLITE_UTF16BE], **
  • [SQLITE_UTF16], or **
  • [SQLITE_UTF16_ALIGNED]. **
)^ ** ^The eTextRep argument determines the encoding of strings passed ** to the collating function callback, xCallback. ** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep ** force strings to be UTF16 with native byte order. ** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin ** on an even byte address. ** ** ^The fourth argument, pArg, is an application data pointer that is passed ** through as the first argument to the collating function callback. ** ** ^The fifth argument, xCallback, is a pointer to the collating function. ** ^Multiple collating functions can be registered using the same name but ** with different eTextRep parameters and SQLite will use whichever ** function requires the least amount of data transformation. ** ^If the xCallback argument is NULL then the collating function is ** deleted. ^When all collating functions having the same name are deleted, ** that collation is no longer usable. ** ** ^The collating function callback is invoked with a copy of the pArg ** application data pointer and with two strings in the encoding specified ** by the eTextRep argument. The collating function must return an ** integer that is negative, zero, or positive ** if the first string is less than, equal to, or greater than the second, ** respectively. A collating function must always return the same answer ** given the same inputs. If two or more collating functions are registered ** to the same collation name (using different eTextRep values) then all ** must give an equivalent answer when invoked with equivalent strings. ** The collating function must obey the following properties for all ** strings A, B, and C: ** **
    **
  1. If A==B then B==A. **
  2. If A==B and B==C then A==C. **
  3. If A<B THEN B>A. **
  4. If A<B and B<C then A<C. **
** ** If a collating function fails any of the above constraints and that ** collating function is registered and used, then the behavior of SQLite ** is undefined. ** ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() ** with the addition that the xDestroy callback is invoked on pArg when ** the collating function is deleted. ** ^Collating functions are deleted when they are overridden by later ** calls to the collation creation functions or when the ** [database connection] is closed using [sqlite3_close()]. ** ** ^The xDestroy callback is not called if the ** sqlite3_create_collation_v2() function fails. Applications that invoke ** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should ** check the return code and dispose of the application data pointer ** themselves rather than expecting SQLite to deal with it for them. ** This is different from every other SQLite interface. The inconsistency ** is unfortunate but cannot be changed without breaking backwards ** compatibility. ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); /* ** CAPI3REF: Collation Needed Callbacks ** ** ^To avoid having to register all collation sequences before a database ** can be used, a single callback function may be registered with the ** [database connection] to be invoked whenever an undefined collation ** sequence is required. ** ** ^If the function is registered using the sqlite3_collation_needed() API, ** then it is passed the names of undefined collation sequences as strings ** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, ** the names are passed as UTF-16 in machine native byte order. ** ^A call to either function replaces the existing collation-needed callback. ** ** ^(When the callback is invoked, the first argument passed is a copy ** of the second argument to sqlite3_collation_needed() or ** sqlite3_collation_needed16(). The second argument is the database ** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], ** or [SQLITE_UTF16LE], indicating the most desirable form of the collation ** sequence function required. The fourth parameter is the name of the ** required collation sequence.)^ ** ** The callback function should register the desired collation using ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); #ifdef SQLITE_HAS_CODEC /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); /* ** Change the key on an open database. If the current database is not ** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the ** database is decrypted. ** ** The code to implement this API is not available in the public release ** of SQLite. */ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif #ifdef SQLITE_ENABLE_CEROD /* ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif /* ** CAPI3REF: Suspend Execution For A Short Time ** ** The sqlite3_sleep() function causes the current thread to suspend execution ** for at least a number of milliseconds specified in its parameter. ** ** If the operating system does not support sleep requests with ** millisecond time resolution, then the time will be rounded up to ** the nearest second. The number of milliseconds of sleep actually ** requested from the operating system is returned. ** ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files ** ** ^(If this global variable is made to point to a string which is ** the name of a folder (a.k.a. directory), then all temporary files ** created by SQLite when using a built-in [sqlite3_vfs | VFS] ** will be placed in that directory.)^ ^If this variable ** is a NULL pointer, then SQLite performs a search for an appropriate ** temporary file directory. ** ** It is not safe to read or modify this variable in more than one ** thread at a time. It is not safe to read or modify this variable ** if a [database connection] is being used at the same time in a separate ** thread. ** It is intended that this variable be set once ** as part of process initialization and before any SQLite interface ** routines have been called and that this variable remain unchanged ** thereafter. ** ** ^The [temp_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, ** the [temp_store_directory pragma] always assumes that any string ** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided. */ SQLITE_API char *sqlite3_temp_directory; /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} ** ** ^The sqlite3_get_autocommit() interface returns non-zero or ** zero if the given database connection is or is not in autocommit mode, ** respectively. ^Autocommit mode is on by default. ** ^Autocommit mode is disabled by a [BEGIN] statement. ** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. ** ** If certain kinds of errors occur on a statement within a multi-statement ** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], ** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the ** transaction might be rolled back automatically. The only way to ** find out whether SQLite automatically rolled back the transaction after ** an error is to use this function. ** ** If another thread changes the autocommit status of the database ** connection while this routine is running, then the return value ** is undefined. */ SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Find the next prepared statement ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL ** then this interface returns a pointer to the first prepared statement ** associated with the database connection pDb. ^If no prepared statement ** satisfies the conditions of this routine, it returns NULL. ** ** The [database connection] pointer D in a call to ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. ** ^Any callback set by a previous call to sqlite3_commit_hook() ** for the same database connection is overridden. ** ^The sqlite3_rollback_hook() interface registers a callback ** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. ** ^Any callback set by a previous call to sqlite3_rollback_hook() ** for the same database connection is overridden. ** ^The pArg argument is passed through to the callback. ** ^If the callback on a commit hook function returns non-zero, ** then the commit is converted into a rollback. ** ** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions ** return the P argument from the previous call of the same function ** on the same [database connection] D, or NULL for ** the first call for each function on D. ** ** The callback implementation must not do anything that will modify ** the database connection that invoked the callback. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the commit ** or rollback hook in the first place. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** ^Registering a NULL function disables the callback. ** ** ^When the commit hook callback routine returns zero, the [COMMIT] ** operation is allowed to continue normally. ^If the commit hook ** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. ** ^The rollback hook is invoked on a rollback that results from a commit ** hook returning non-zero, just as it would be with any other rollback. ** ** ^For the purposes of this API, a transaction is said to have been ** rolled back if an explicit "ROLLBACK" statement is executed, or ** an error or constraint causes an implicit rollback to occur. ** ^The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument ** to be invoked whenever a row is updated, inserted or deleted. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** ** ^The second argument is a pointer to the function to invoke when a ** row is updated, inserted or deleted. ** ^The first argument to the callback is a copy of the third argument ** to sqlite3_update_hook(). ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], ** or [SQLITE_UPDATE], depending on the operation that caused the callback ** to be invoked. ** ^The third and fourth arguments to the callback contain pointers to the ** database and table name containing the affected row. ** ^The final callback parameter is the [rowid] of the row. ** ^In the case of an update, this is the [rowid] after the update takes place. ** ** ^(The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence).)^ ** ** ^In the current implementation, the update hook ** is not invoked when duplication rows are deleted because of an ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook ** invoked when rows are deleted using the [truncate optimization]. ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** ^The sqlite3_update_hook(D,C,P) function ** returns the P argument from the previous call ** on the same [database connection] D, or NULL for ** the first call on D. ** ** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] ** interfaces. */ SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* ); /* ** CAPI3REF: Enable Or Disable Shared Pager Cache ** KEYWORDS: {shared cache} ** ** ^(This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false.)^ ** ** ^Cache sharing is enabled and disabled for an entire process. ** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent ** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. ** Existing database connections continue use the sharing mode ** that was in effect at the time they were opened.)^ ** ** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled ** successfully. An [error code] is returned otherwise.)^ ** ** ^Shared cache is disabled by default. But this might change in ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** ** See Also: [SQLite Shared-Cache Mode] */ SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory ** ** ^The sqlite3_release_memory() interface attempts to free N bytes ** of heap memory by deallocating non-essential memory allocations ** held by the database library. Memory used to cache database ** pages to improve performance is an example of non-essential memory. ** ^sqlite3_release_memory() returns the number of bytes actually freed, ** which might be more or less than the amount requested. ** ^The sqlite3_release_memory() routine is a no-op returning zero ** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. */ SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay ** below the limit, it will exceed the limit rather than generate ** an [SQLITE_NOMEM] error. In other words, the soft heap limit ** is advisory only. ** ** ^The return value from sqlite3_soft_heap_limit64() is the size of ** the soft heap limit prior to the call. ^If the argument N is negative ** then no change is made to the soft heap limit. Hence, the current ** size of the soft heap limit can be determined by invoking ** sqlite3_soft_heap_limit64() with a negative argument. ** ** ^If the argument N is zero then the soft heap limit is disabled. ** ** ^(The soft heap limit is not enforced in the current implementation ** if one or more of following conditions are true: ** **
    **
  • The soft heap limit is set to zero. **
  • Memory accounting is disabled using a combination of the ** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and ** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. **
  • An alternative page cache implementation is specified using ** [sqlite3_config]([SQLITE_CONFIG_PCACHE],...). **
  • The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. **
)^ ** ** Beginning with SQLite version 3.7.3, the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without ** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced ** when memory is allocated by the page cache. Testing suggests that because ** the page cache is the predominate memory user in SQLite, most ** applications will achieve adequate soft heap limit enforcement without ** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. ** ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** ** This is a deprecated version of the [sqlite3_soft_heap_limit64()] ** interface. This routine is provided for historical compatibility ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table ** ** ^This routine returns metadata about a specific column of a specific ** database table accessible using the [database connection] handle ** passed as the first function argument. ** ** ^The column is identified by the second, third and fourth parameters to ** this function. ^The second parameter is either the name of the database ** (i.e. "main", "temp", or an attached database) containing the specified ** table or NULL. ^If it is NULL, then all attached databases are searched ** for the table using the same algorithm used by the database engine to ** resolve unqualified table references. ** ** ^The third and fourth parameters to this function are the table and column ** name of the desired column, respectively. Neither of these parameters ** may be NULL. ** ** ^Metadata is returned by writing to the memory locations passed as the 5th ** and subsequent parameters to this function. ^Any of these arguments may be ** NULL, in which case the corresponding element of metadata is omitted. ** ** ^(
** **
Parameter Output
Type
Description ** **
5th const char* Data type **
6th const char* Name of default collation sequence **
7th int True if column has a NOT NULL constraint **
8th int True if column is part of the PRIMARY KEY **
9th int True if column is [AUTOINCREMENT] **
**
)^ ** ** ^The memory pointed to by the character pointers returned for the ** declaration type and collation sequence is valid only until the next ** call to any SQLite API function. ** ** ^If the specified table is actually a view, an [error code] is returned. ** ** ^If the specified column is "rowid", "oid" or "_rowid_" and an ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output ** parameters are set for the explicitly declared column. ^(If there is no ** explicitly declared [INTEGER PRIMARY KEY] column, then the output ** parameters are set as follows: ** **
**     data type: "INTEGER"
**     collation sequence: "BINARY"
**     not null: 0
**     primary key: 1
**     auto increment: 0
** 
)^ ** ** ^(This function may load one or more schemas from database files. If an ** error occurs during this process, or if the requested table or column ** cannot be found, an [error code] is returned and an error message left ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ ** ** ^This API is only available if the library was compiled with the ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. */ SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ const char *zColumnName, /* Column name */ char const **pzDataType, /* OUTPUT: Declared data type */ char const **pzCollSeq, /* OUTPUT: Collation sequence name */ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ int *pPrimaryKey, /* OUTPUT: True if column part of PK */ int *pAutoinc /* OUTPUT: True if column is auto-increment */ ); /* ** CAPI3REF: Load An Extension ** ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an ** SQLite extension library contained in the file zFile. ** ** ^The entry point is zProc. ** ^zProc may be 0, in which case the name of the entry point ** defaults to "sqlite3_extension_init". ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory ** obtained from [sqlite3_malloc()]. The calling function ** should free this memory by calling [sqlite3_free()]. ** ** ^Extension loading must be enabled using ** [sqlite3_enable_load_extension()] prior to calling this API, ** otherwise an error will be returned. ** ** See also the [load_extension() SQL function]. */ SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with extension loading, and as a means of disabling ** extension loading while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. ** ** ^Extension loading is off by default. See ticket #1863. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked SQLite extension ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects and integer result as if the signature of the ** entry point where as follows: ** **
**    int xEntryPoint(
**      sqlite3 *db,
**      const char **pzErrMsg,
**      const struct sqlite3_api_routines *pThunk
**    );
** 
)^ ** ** If the xEntryPoint routine encounters an error, it should make *pzErrMsg ** point to an appropriate error message (obtained from [sqlite3_mprintf()]) ** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg ** is NULL before calling the xEntryPoint(). ^SQLite will invoke ** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any ** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], ** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. ** ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** ** See also: [sqlite3_reset_auto_extension()]. */ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading ** ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered ** to be experimental. The interface might change in incompatible ways. ** If this is a problem for you, do not use the interface at this time. ** ** When the virtual-table mechanism stabilizes, we will declare the ** interface fixed, support it indefinitely, and remove this comment. */ /* ** Structures used by the virtual table interface */ typedef struct sqlite3_vtab sqlite3_vtab; typedef struct sqlite3_index_info sqlite3_index_info; typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; typedef struct sqlite3_module sqlite3_module; /* ** CAPI3REF: Virtual Table Object ** KEYWORDS: sqlite3_module {virtual table module} ** ** This structure, sometimes called a "virtual table module", ** defines the implementation of a [virtual tables]. ** This structure consists mostly of methods for the module. ** ** ^A virtual table module is created by filling in a persistent ** instance of this structure and passing a pointer to that instance ** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. ** ^The registration remains valid until it is replaced by a different ** module or until the [database connection] closes. The content ** of this structure must not change while it is registered with ** any database connection. */ struct sqlite3_module { int iVersion; int (*xCreate)(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**); int (*xConnect)(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**); int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); int (*xDisconnect)(sqlite3_vtab *pVTab); int (*xDestroy)(sqlite3_vtab *pVTab); int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); int (*xClose)(sqlite3_vtab_cursor*); int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv); int (*xNext)(sqlite3_vtab_cursor*); int (*xEof)(sqlite3_vtab_cursor*); int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); int (*xBegin)(sqlite3_vtab *pVTab); int (*xSync)(sqlite3_vtab *pVTab); int (*xCommit)(sqlite3_vtab *pVTab); int (*xRollback)(sqlite3_vtab *pVTab); int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg); int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info ** ** The sqlite3_index_info structure and its substructures is used as part ** of the [virtual table] interface to ** pass information into and receive the reply from the [xBestIndex] ** method of a [virtual table module]. The fields under **Inputs** are the ** inputs to xBestIndex and are read-only. xBestIndex inserts its ** results into the **Outputs** fields. ** ** ^(The aConstraint[] array records WHERE clause constraints of the form: ** **
column OP expr
** ** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is ** stored in aConstraint[].op using one of the ** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ ** ^(The index of the column is stored in ** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the ** expr on the right-hand side can be evaluated (and thus the constraint ** is usable) and false if it cannot.)^ ** ** ^The optimizer automatically inverts terms of the form "expr OP column" ** and makes other simplifications to the WHERE clause in an attempt to ** get as many WHERE clause terms into the form shown above as possible. ** ^The aConstraint[] array only reports WHERE clause terms that are ** relevant to the particular virtual table being queried. ** ** ^Information about the ORDER BY clause is stored in aOrderBy[]. ** ^Each term of aOrderBy records a column of the ORDER BY clause. ** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and is not checked again by SQLite.)^ ** ** ^The idxNum and idxPtr values are recorded and passed into the ** [xFilter] method. ** ^[sqlite3_free()] is used to free idxPtr if and only if ** needToFreeIdxPtr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate ** sorting step is required. ** ** ^The estimatedCost value is an estimate of the cost of doing the ** particular lookup. A full scan of a table with N entries should have ** a cost of N. A binary search of a table of N entries should have a ** cost of approximately log(N). */ struct sqlite3_index_info { /* Inputs */ int nConstraint; /* Number of entries in aConstraint */ struct sqlite3_index_constraint { int iColumn; /* Column on left-hand side of constraint */ unsigned char op; /* Constraint operator */ unsigned char usable; /* True if this constraint is usable */ int iTermOffset; /* Used internally - xBestIndex should ignore */ } *aConstraint; /* Table of WHERE clause constraints */ int nOrderBy; /* Number of terms in the ORDER BY clause */ struct sqlite3_index_orderby { int iColumn; /* Column number */ unsigned char desc; /* True for DESC. False for ASC. */ } *aOrderBy; /* The ORDER BY clause */ /* Outputs */ struct sqlite3_index_constraint_usage { int argvIndex; /* if >0, constraint is part of argv to xFilter */ unsigned char omit; /* Do not code a test for this constraint */ } *aConstraintUsage; int idxNum; /* Number used to identify the index */ char *idxStr; /* String, possibly obtained from sqlite3_malloc */ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ int orderByConsumed; /* True if output is already ordered */ double estimatedCost; /* Estimated cost of using this index */ }; /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros defined the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT 16 #define SQLITE_INDEX_CONSTRAINT_GE 32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 /* ** CAPI3REF: Register A Virtual Table Implementation ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before ** creating a new [virtual table] using the module and before using a ** preexisting [virtual table] for the module. ** ** ^The module name is registered on the [database connection] specified ** by the first parameter. ^The name of the module is given by the ** second parameter. ^The third parameter is a pointer to ** the implementation of the [virtual table module]. ^The fourth ** parameter is an arbitrary client data pointer that is passed through ** into the [xCreate] and [xConnect] methods of the virtual table module ** when a new virtual table is be being created or reinitialized. ** ** ^The sqlite3_create_module_v2() interface has a fifth parameter which ** is a pointer to a destructor for the pClientData. ^SQLite will ** invoke the destructor function (if it is not NULL) when SQLite ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ); /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab ** ** Every [virtual table module] implementation uses a subclass ** of this object to describe a particular instance ** of the [virtual table]. Each subclass will ** be tailored to the specific needs of the module implementation. ** The purpose of this superclass is to define certain fields that are ** common to all module implementations. ** ** ^Virtual tables methods can set an error message by assigning a ** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should ** take care that any prior string is freed by a call to [sqlite3_free()] ** prior to assigning a new string to zErrMsg. ^After the error message ** is delivered up to the client application, the string will be automatically ** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ int nRef; /* NO LONGER USED */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; /* ** CAPI3REF: Virtual Table Cursor Object ** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} ** ** Every [virtual table module] implementation uses a subclass of the ** following structure to describe cursors that point into the ** [virtual table] and are used ** to loop through the virtual table. Cursors are created using the ** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed ** by the [sqlite3_module.xClose | xClose] method. Cursors are used ** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods ** of the module. Each module implementation will define ** the content of a cursor structure to suit its own needs. ** ** This superclass exists in order to define fields of the cursor that ** are common to all implementations. */ struct sqlite3_vtab_cursor { sqlite3_vtab *pVtab; /* Virtual table of this cursor */ /* Virtual table implementations will typically add additional fields */ }; /* ** CAPI3REF: Declare The Schema Of A Virtual Table ** ** ^The [xCreate] and [xConnect] methods of a ** [virtual table module] call this interface ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. ** But global versions of those functions ** must exist in order to be overloaded.)^ ** ** ^(This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists ** before this API is called, a new function is created.)^ ^The implementation ** of the new function always causes an exception to be thrown. So ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up ** to a comment remarkably similar to this one) is currently considered ** to be experimental. The interface might change in incompatible ways. ** If this is a problem for you, do not use the interface at this time. ** ** When the virtual-table mechanism stabilizes, we will declare the ** interface fixed, support it indefinitely, and remove this comment. */ /* ** CAPI3REF: A Handle To An Open BLOB ** KEYWORDS: {BLOB handle} {BLOB handles} ** ** An instance of this object represents an open BLOB on which ** [sqlite3_blob_open | incremental BLOB I/O] can be performed. ** ^Objects of this type are created by [sqlite3_blob_open()] ** and destroyed by [sqlite3_blob_close()]. ** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces ** can be used to read or write small subsections of the BLOB. ** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. */ typedef struct sqlite3_blob sqlite3_blob; /* ** CAPI3REF: Open A BLOB For Incremental I/O ** ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; ** in other words, the same BLOB that would be selected by: ** **
**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
** 
)^ ** ** ^If the flags parameter is non-zero, then the BLOB is opened for read ** and write access. ^If it is zero, the BLOB is opened for read access. ** ^It is not possible to open a column that is part of an index or primary ** key for writing. ^If [foreign key constraints] are enabled, it is ** not possible to open a column that is part of a [child key] for writing. ** ** ^Note that the database name is not the filename that contains ** the database but rather the symbolic name of the database that ** appears after the AS keyword when the database is connected using [ATTACH]. ** ^For the main database file, the database name is "main". ** ^For TEMP tables, the database name is "temp". ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written ** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set ** to be a null pointer.)^ ** ^This function sets the [database connection] error code and message ** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related ** functions. ^Note that the *ppBlob variable is always initialized in a ** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob ** regardless of the success or failure of this routine. ** ** ^(If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column ** other than the one the BLOB handle is open on.)^ ** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for ** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. ** ^(Changes written into a BLOB prior to the BLOB expiring are not ** rolled back by the expiration of the BLOB. Such changes will eventually ** commit if the transaction continues to completion.)^ ** ** ^Use the [sqlite3_blob_bytes()] interface to determine the size of ** the opened blob. ^The size of a blob may not be changed by this ** interface. Use the [UPDATE] SQL command to change the size of a ** blob. ** ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces ** and the built-in [zeroblob] SQL function can be used, if desired, ** to create an empty, zero-filled blob in which to read or write using ** this interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, const char *zColumn, sqlite3_int64 iRow, int flags, sqlite3_blob **ppBlob ); /* ** CAPI3REF: Move a BLOB Handle to a New Row ** ** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified ** by the rowid value passed as the second argument. Only the row can be ** changed. ^The database, table and column on which the blob handle is open ** remain the same. Moving an existing blob handle to a new row can be ** faster than closing the existing handle and opening a new one. ** ** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - ** it must exist and there must be either a blob or text value stored in ** the nominated column.)^ ^If the new row is not present in the table, or if ** it does not contain a blob or text value, or if another error occurs, an ** SQLite error code is returned and the blob handle is considered aborted. ** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or ** [sqlite3_blob_reopen()] on an aborted blob handle immediately return ** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle ** always returns zero. ** ** ^This function sets the database handle error code and message. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle ** ** ^Closes an open [BLOB handle]. ** ** ^Closing a BLOB shall cause the current transaction to commit ** if there are no other BLOBs, no pending prepared statements, and the ** database connection is in [autocommit mode]. ** ^If any writes were made to the BLOB, they might be held in cache ** until the close operation if they will fit. ** ** ^(Closing the BLOB often forces the changes ** out to disk and so if any I/O errors occur, they will likely occur ** at the time when the BLOB is closed. Any errors that occur during ** closing are reported as a non-zero return value.)^ ** ** ^(The BLOB is closed unconditionally. Even if this routine returns ** an error code, the BLOB is still closed.)^ ** ** ^Calling this routine with a null pointer (such as would be returned ** by a failed call to [sqlite3_blob_open()]) is a harmless no-op. */ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The ** incremental blob I/O routines can only read or overwriting existing ** blob content; they cannot change the size of a blob. ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z ** from the open BLOB, starting at offset iOffset.)^ ** ** ^If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is ** less than zero, [SQLITE_ERROR] is returned and no data is read. ** ^The size of the blob (and hence the maximum value of N+iOffset) ** can be determined using the [sqlite3_blob_bytes()] interface. ** ** ^An attempt to read from an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ** ** ^(On success, sqlite3_blob_read() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_write()]. */ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** ** ^This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. ^N bytes of data are copied from the buffer Z ** into the open BLOB, starting at offset iOffset. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** ** ^This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is written. ^If N is ** less than zero [SQLITE_ERROR] is returned and no data is written. ** The size of the BLOB (and hence the maximum value of N+iOffset) ** can be determined using the [sqlite3_blob_bytes()] interface. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the ** expiration of the handle, though of course those changes might ** have been overwritten by the statement that expired the BLOB handle ** or by other independent statements. ** ** ^(On success, sqlite3_blob_write() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_read()]. */ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects ** ** A virtual filesystem (VFS) is an [sqlite3_vfs] object ** that SQLite uses to interact ** with the underlying operating system. Most SQLite builds come with a ** single default VFS that is appropriate for the host computer. ** New VFSes can be registered and existing VFSes can be unregistered. ** The following interfaces are provided. ** ** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. ** ^Names are case sensitive. ** ^Names are zero-terminated UTF-8 strings. ** ^If there is no match, a NULL pointer is returned. ** ^If zVfsName is NULL then the default VFS is returned. ** ** ^New VFSes are registered with sqlite3_vfs_register(). ** ^Each new VFS becomes the default VFS if the makeDflt flag is set. ** ^The same VFS can be registered multiple times without injury. ** ^To make an existing VFS into the default VFS, register it again ** with the makeDflt flag set. If two different VFSes with the ** same name are registered, the behavior is undefined. If a ** VFS is registered with a name that is NULL or an empty string, ** then the behavior is undefined. ** ** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes ** ** The SQLite core uses these routines for thread ** synchronization. Though they are intended for internal ** use by SQLite, code that links against SQLite is ** permitted to use any of these routines. ** ** The SQLite source code contains multiple implementations ** of these mutex routines. An appropriate implementation ** is selected automatically at compile-time. ^(The following ** implementations are available in the SQLite core: ** **
    **
  • SQLITE_MUTEX_OS2 **
  • SQLITE_MUTEX_PTHREAD **
  • SQLITE_MUTEX_W32 **
  • SQLITE_MUTEX_NOOP **
)^ ** ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines ** that does no real locking and is appropriate for use in ** a single-threaded application. ^The SQLITE_MUTEX_OS2, ** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations ** are appropriate for use on OS/2, Unix, and Windows. ** ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex ** implementation is included with the library. In this case the ** application must supply a custom mutex implementation using the ** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function ** before calling sqlite3_initialize() or any other public sqlite3_ ** function that calls sqlite3_initialize().)^ ** ** ^The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. ^If it returns NULL ** that means that a mutex could not be allocated. ^SQLite ** will unwind its stack and return an error. ^(The argument ** to sqlite3_mutex_alloc() is one of these integer constants: ** **
    **
  • SQLITE_MUTEX_FAST **
  • SQLITE_MUTEX_RECURSIVE **
  • SQLITE_MUTEX_STATIC_MASTER **
  • SQLITE_MUTEX_STATIC_MEM **
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU **
  • SQLITE_MUTEX_STATIC_LRU2 **
)^ ** ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) ** cause sqlite3_mutex_alloc() to create ** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. ** The mutex implementation does not need to make a distinction ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does ** not want to. ^SQLite will only request a recursive mutex in ** cases where it really needs one. ^If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other ** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return ** a pointer to a static preexisting mutex. ^Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. ** ** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() ** returns a different mutex on every call. ^But for the static ** mutex types, the same mutex is returned on every call that has ** the same type number. ** ** ^The sqlite3_mutex_free() routine deallocates a previously ** allocated dynamic mutex. ^SQLite is careful to deallocate every ** dynamic mutex that it allocates. The dynamic mutexes must not be in ** use when they are deallocated. Attempting to deallocate a static ** mutex results in undefined behavior. ^SQLite never deallocates ** a static mutex. ** ** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt ** to enter a mutex. ^If another thread is already within the mutex, ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return ** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] ** upon successful entry. ^(Mutexes created using ** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. ** In such cases the, ** mutex must be exited an equal number of times before another thread ** can enter.)^ ^(If the same thread tries to enter any other ** kind of mutex more than once, the behavior is undefined. ** SQLite will never exhibit ** such behavior in its own use of mutexes.)^ ** ** ^(Some systems (for example, Windows 95) do not support the operation ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() ** will always return SQLITE_BUSY. The SQLite core only ever uses ** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. ^(The behavior ** is undefined if the mutex is not currently entered by the ** calling thread or is not currently allocated. SQLite will ** never do either.)^ ** ** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or ** sqlite3_mutex_leave() is a NULL pointer, then all three routines ** behave as no-ops. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object ** ** An instance of this structure defines the low-level routines ** used to allocate and use mutexes. ** ** Usually, the default mutex implementations provided by SQLite are ** sufficient, however the user has the option of substituting a custom ** implementation for specialized deployments or systems for which SQLite ** does not provide a suitable implementation. In this case, the user ** creates and populates an instance of this structure to pass ** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. ** Additionally, an instance of this structure can be used as an ** output variable when querying the system for the current mutex ** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. ** ** ^The xMutexInit method defined by this structure is invoked as ** part of system initialization by the sqlite3_initialize() function. ** ^The xMutexInit routine is called by SQLite exactly once for each ** effective call to [sqlite3_initialize()]. ** ** ^The xMutexEnd method defined by this structure is invoked as ** part of system shutdown by the sqlite3_shutdown() function. The ** implementation of this method is expected to release all outstanding ** resources obtained by the mutex methods implementation, especially ** those obtained by the xMutexInit method. ^The xMutexEnd() ** interface is invoked exactly once for each call to [sqlite3_shutdown()]. ** ** ^(The remaining seven methods defined by this structure (xMutexAlloc, ** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and ** xMutexNotheld) implement the following interfaces (respectively): ** **
    **
  • [sqlite3_mutex_alloc()]
  • **
  • [sqlite3_mutex_free()]
  • **
  • [sqlite3_mutex_enter()]
  • **
  • [sqlite3_mutex_try()]
  • **
  • [sqlite3_mutex_leave()]
  • **
  • [sqlite3_mutex_held()]
  • **
  • [sqlite3_mutex_notheld()]
  • **
)^ ** ** The only difference is that the public sqlite3_XXX functions enumerated ** above silently ignore any invocations that pass a NULL pointer instead ** of a valid mutex handle. The implementations of the methods defined ** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** ** The xMutexInit() method must be threadsafe. ^It must be harmless to ** invoke xMutexInit() multiple times within the same process and without ** intervening calls to xMutexEnd(). Second and subsequent calls to ** xMutexInit() must be no-ops. ** ** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] ** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory ** allocation for a static mutex. ^However xMutexAlloc() may use SQLite ** memory allocation for a fast or recursive mutex. ** ** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is ** called, but only if the prior call to xMutexInit returned SQLITE_OK. ** If xMutexInit fails in any way, it is expected to clean up after itself ** prior to returning. */ typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; struct sqlite3_mutex_methods { int (*xMutexInit)(void); int (*xMutexEnd)(void); sqlite3_mutex *(*xMutexAlloc)(int); void (*xMutexFree)(sqlite3_mutex *); void (*xMutexEnter)(sqlite3_mutex *); int (*xMutexTry)(sqlite3_mutex *); void (*xMutexLeave)(sqlite3_mutex *); int (*xMutexHeld)(sqlite3_mutex *); int (*xMutexNotheld)(sqlite3_mutex *); }; /* ** CAPI3REF: Mutex Verification Routines ** ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines ** are intended for use inside assert() statements. ^The SQLite core ** never uses these routines except inside an assert() and applications ** are advised to follow the lead of the core. ^The SQLite core only ** provides implementations for these routines when it is compiled ** with the SQLITE_DEBUG flag. ^External mutex implementations ** are only required to provide these routines if SQLITE_DEBUG is ** defined and if NDEBUG is not defined. ** ** ^These routines should return true if the mutex in their argument ** is held or not held, respectively, by the calling thread. ** ** ^The implementation is not required to provided versions of these ** routines that actually work. If the implementation does not provide working ** versions of these routines, it should at least provide stubs that always ** return true so that one does not get spurious assertion failures. ** ** ^If the argument to sqlite3_mutex_held() is a NULL pointer then ** the routine should return 1. This seems counter-intuitive since ** clearly the mutex cannot be held if it does not exist. But ** the reason the mutex does not exist is because the build is not ** using mutexes. And we do not want the assert() containing the ** call to sqlite3_mutex_held() to fail, so a non-zero return is ** the appropriate thing to do. ^The sqlite3_mutex_notheld() ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* ** CAPI3REF: Mutex Types ** ** The [sqlite3_mutex_alloc()] interface takes a single argument ** which is one of these integer constants. ** ** The set of static mutexes may change from one SQLite release to the ** next. Applications that override the built-in mutex logic must be ** prepared to accommodate additional static mutexes. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 #define SQLITE_MUTEX_STATIC_MASTER 2 #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ /* ** CAPI3REF: Retrieve the mutex for a database connection ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated ** with a particular database identified by the second argument. ^The ** name of the database is "main" for the main database or "temp" for the ** TEMP database, or the name that appears after the AS keyword for ** databases that are added using the [ATTACH] SQL command. ** ^A NULL pointer can be used in place of "main" to refer to the ** main database file. ** ^The third and fourth parameters to this routine ** are passed directly through to the second and third parameters of ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** ** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes ** a pointer to the underlying [sqlite3_file] object to be written into ** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER ** case is a short-circuit path which does not actually invoke the ** underlying sqlite3_io_methods.xFileControl method. ** ** ^If the second parameter (zDbName) does not match the name of any ** open database file, then SQLITE_ERROR is returned. ^This error ** code is not remembered and will not be recalled by [sqlite3_errcode()] ** or [sqlite3_errmsg()]. The underlying xFileControl method might ** also return SQLITE_ERROR. There is no way to distinguish between ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface ** ** ^The sqlite3_test_control() interface is used to read out internal ** state of SQLite and to inject faults into SQLite for testing ** purposes. ^The first parameter is an operation code that determines ** the number, meaning, and operation of all subsequent parameters. ** ** This interface is not for use by applications. It exists solely ** for verifying the correct operation of the SQLite library. Depending ** on how the SQLite library is compiled, this interface might not exist. ** ** The details of the operation codes, their meanings, the parameters ** they take, and what they do are all subject to change without notice. ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ SQLITE_API int sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes ** ** These constants are the valid operation code parameters used ** as the first argument to [sqlite3_test_control()]. ** ** These parameters and their meanings are subject to change ** without notice. These values are for testing purposes only. ** Applications should not use any of these parameters or the ** [sqlite3_test_control()] interface. */ #define SQLITE_TESTCTRL_FIRST 5 #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 #define SQLITE_TESTCTRL_PRNG_RESET 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_PGHDRSZ 17 #define SQLITE_TESTCTRL_SCRATCHMALLOC 18 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 19 #define SQLITE_TESTCTRL_LAST 19 /* ** CAPI3REF: SQLite Runtime Status ** ** ^This interface is used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes ** are of the form [status parameters | SQLITE_STATUS_...].)^ ** ^The current value of the parameter is returned into *pCurrent. ** ^The highest recorded value is returned in *pHighwater. ^If the ** resetFlag is true, then the highest record value is reset after ** *pHighwater is written. ^(Some parameters do not record the highest ** value. For those parameters ** nothing is written into *pHighwater and the resetFlag is ignored.)^ ** ^(Other parameters record only the highwater mark and not the current ** value. For these latter parameters nothing is written into *pCurrent.)^ ** ** ^The sqlite3_status() routine returns SQLITE_OK on success and a ** non-zero [error code] on failure. ** ** This routine is threadsafe but is not atomic. This routine can be ** called while other threads are running the same or different SQLite ** interfaces. However the values returned in *pCurrent and ** *pHighwater reflect the status of SQLite at different points in time ** and it is possible that another thread might change the parameter ** in between the times when *pCurrent and *pHighwater are written. ** ** See also: [sqlite3_db_status()] */ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); /* ** CAPI3REF: Status Parameters ** KEYWORDS: {status parameters} ** ** These integer constants designate various run-time status parameters ** that can be returned by [sqlite3_status()]. ** **
** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
**
This parameter is the current amount of memory checked out ** using [sqlite3_malloc()], either directly or indirectly. The ** figure includes calls made to [sqlite3_malloc()] by the application ** and internal memory usage by the SQLite library. Scratch memory ** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in ** this parameter. The amount returned is the sum of the allocation ** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ ** ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
**
This parameter records the largest memory allocation request ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their ** internal equivalents). Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
)^ ** ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
**
This parameter records the number of separate memory allocations ** currently checked out.
)^ ** ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
**
This parameter returns the number of pages used out of the ** [pagecache memory allocator] that was configured using ** [SQLITE_CONFIG_PAGECACHE]. The ** value returned is in pages, not in bytes.
)^ ** ** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] ** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
**
This parameter returns the number of bytes of page cache ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] ** buffer and where forced to overflow to [sqlite3_malloc()]. The ** returned value includes allocations that overflowed because they ** where too large (they were larger than the "sz" parameter to ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.
)^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
**
This parameter records the largest memory allocation request ** handed to [pagecache memory allocator]. Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
)^ ** ** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
**
This parameter returns the number of allocations used out of the ** [scratch memory allocator] configured using ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not ** in bytes. Since a single thread may only have one scratch allocation ** outstanding at time, this parameter also reports the number of threads ** using scratch memory at the same time.
)^ ** ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
**
This parameter returns the number of bytes of scratch memory ** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] ** buffer and where forced to overflow to [sqlite3_malloc()]. The values ** returned include overflows because the requested allocation was too ** larger (that is, because the requested allocation was larger than the ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer ** slots were available. **
)^ ** ** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
**
This parameter records the largest memory allocation request ** handed to [scratch memory allocator]. Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
)^ ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
**
This parameter records the deepest parser stack. It is only ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ **
** ** New status parameters may be added from time to time. */ #define SQLITE_STATUS_MEMORY_USED 0 #define SQLITE_STATUS_PAGECACHE_USED 1 #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 #define SQLITE_STATUS_SCRATCH_USED 3 #define SQLITE_STATUS_SCRATCH_OVERFLOW 4 #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 #define SQLITE_STATUS_PAGECACHE_SIZE 7 #define SQLITE_STATUS_SCRATCH_SIZE 8 #define SQLITE_STATUS_MALLOC_COUNT 9 /* ** CAPI3REF: Database Connection Status ** ** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the ** database connection object to be interrogated. ^The second argument ** is an integer constant, taken from the set of ** [SQLITE_DBSTATUS options], that ** determines the parameter to interrogate. The set of ** [SQLITE_DBSTATUS options] is likely ** to grow in future releases of SQLite. ** ** ^The current value of the requested parameter is written into *pCur ** and the highest instantaneous value is written into *pHiwtr. ^If ** the resetFlg is true, then the highest instantaneous value is ** reset back down to the current value. ** ** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a ** non-zero [error code] on failure. ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections ** KEYWORDS: {SQLITE_DBSTATUS options} ** ** These constants are the available integer "verbs" that can be passed as ** the second argument to the [sqlite3_db_status()] interface. ** ** New verbs may be added in future releases of SQLite. Existing verbs ** might be discontinued. Applications should check the return code from ** [sqlite3_db_status()] to make sure that the call worked. ** The [sqlite3_db_status()] interface will return a non-zero error code ** if a discontinued or unsupported verb is invoked. ** **
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
**
This parameter returns the number of lookaside memory slots currently ** checked out.
)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
**
This parameter returns the number malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
**
This parameter returns the number malloc attempts that might have ** been satisfied using lookaside memory but failed due to the amount of ** memory requested being larger than the lookaside slot size. ** Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] ** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
**
This parameter returns the number malloc attempts that might have ** been satisfied using lookaside memory but failed due to all lookaside ** memory already being in use. ** Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
**
This parameter returns the approximate number of of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
**
This parameter returns the approximate number of of bytes of heap ** memory used to store the schema for all databases associated ** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. ** ** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
**
This parameter returns the approximate number of of bytes of heap ** and lookaside memory used by all prepared statements associated with ** the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. **
** ** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
**
This parameter returns the number of pager cache hits that have ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT ** is always 0. **
** ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
**
This parameter returns the number of pager cache misses that have ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. **
**
*/ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number ** of times it has performed specific operations.)^ These counters can ** be used to monitor the performance characteristics of the prepared ** statements. For example, if the number of table steps greatly exceeds ** the number of table searches or result rows, that would tend to indicate ** that the prepared statement is using a full table scan rather than ** an index. ** ** ^(This interface is used to retrieve and reset counter values from ** a [prepared statement]. The first argument is the prepared statement ** object to be interrogated. The second argument ** is an integer code for a specific [SQLITE_STMTSTATUS counter] ** to be interrogated.)^ ** ^The current value of the requested counter is returned. ** ^If the resetFlg is true, then the counter is reset to zero after this ** interface call returns. ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements ** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} ** ** These preprocessor macros define integer codes that name counter ** values associated with the [sqlite3_stmt_status()] interface. ** The meanings of the various counters are as follows: ** **
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
**
^This is the number of times that SQLite has stepped forward in ** a table as part of a full table scan. Large numbers for this counter ** may indicate opportunities for performance improvement through ** careful use of indices.
** ** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
**
^This is the number of sort operations that have occurred. ** A non-zero value in this counter may indicate an opportunity to ** improvement performance through careful use of indices.
** ** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
**
^This is the number of rows inserted into transient indices that ** were created automatically in order to help joins run faster. ** A non-zero value in this counter may indicate an opportunity to ** improvement performance by adding permanent indices that do not ** need to be reinitialized each time the statement is run.
**
*/ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of ** its size or internal structure and never deals with the ** sqlite3_pcache object except by holding and passing pointers ** to the object. ** ** See [sqlite3_pcache_methods] for additional information. */ typedef struct sqlite3_pcache sqlite3_pcache; /* ** CAPI3REF: Application Defined Page Cache. ** KEYWORDS: {page cache} ** ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can ** register an alternative page cache implementation by passing in an ** instance of the sqlite3_pcache_methods structure.)^ ** In many applications, most of the heap memory allocated by ** SQLite is used for the page cache. ** By implementing a ** custom page cache using this API, an application can better control ** the amount of memory consumed by SQLite, the way in which ** that memory is allocated and released, and the policies used to ** determine exactly which parts of a database file are cached and for ** how long. ** ** The alternative page cache mechanism is an ** extreme measure that is only needed by the most demanding applications. ** The built-in page cache is recommended for most uses. ** ** ^(The contents of the sqlite3_pcache_methods structure are copied to an ** internal buffer by SQLite within the call to [sqlite3_config]. Hence ** the application may discard the parameter after the call to ** [sqlite3_config()] returns.)^ ** ** [[the xInit() page cache method]] ** ^(The xInit() method is called once for each effective ** call to [sqlite3_initialize()])^ ** (usually only once during the lifetime of the process). ^(The xInit() ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^ ** The intent of the xInit() method is to set up global data structures ** required by the custom page cache implementation. ** ^(If the xInit() method is NULL, then the ** built-in default page cache is used instead of the application defined ** page cache.)^ ** ** [[the xShutdown() page cache method]] ** ^The xShutdown() method is called by [sqlite3_shutdown()]. ** It can be used to clean up ** any outstanding resources before process shutdown, if required. ** ^The xShutdown() method may be NULL. ** ** ^SQLite automatically serializes calls to the xInit method, ** so the xInit method need not be threadsafe. ^The ** xShutdown method is only called from [sqlite3_shutdown()] so it does ** not need to be threadsafe either. All other methods must be threadsafe ** in multithreaded applications. ** ** ^SQLite will never invoke xInit() more than once without an intervening ** call to xShutdown(). ** ** [[the xCreate() page cache methods]] ** ^SQLite invokes the xCreate() method to construct a new cache instance. ** SQLite will typically create one cache instance for each open database file, ** though this is not guaranteed. ^The ** first parameter, szPage, is the size in bytes of the pages that must ** be allocated by the cache. ^szPage will not be a power of two. ^szPage ** will the page size of the database file that is to be cached plus an ** increment (here called "R") of less than 250. SQLite will use the ** extra R bytes on each page to store metadata about the underlying ** database page on disk. The value of R depends ** on the SQLite version, the target platform, and how SQLite was compiled. ** ^(R is constant for a particular build of SQLite. Except, there are two ** distinct values of R when SQLite is compiled with the proprietary ** ZIPVFS extension.)^ ^The second argument to ** xCreate(), bPurgeable, is true if the cache being created will ** be used to cache database pages of a file stored on disk, or ** false if it is used for an in-memory database. The cache implementation ** does not have to do anything special based with the value of bPurgeable; ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will ** never invoke xUnpin() except to deliberately delete a page. ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to ** false will always have the "discard" flag set to true. ** ^Hence, a cache created with bPurgeable false will ** never contain any unpinned pages. ** ** [[the xCachesize() page cache method]] ** ^(The xCachesize() method may be called at any time by SQLite to set the ** suggested maximum cache-size (number of pages stored by) the cache ** instance passed as the first argument. This is the value configured using ** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable ** parameter, the implementation is not required to do anything with this ** value; it is advisory only. ** ** [[the xPagecount() page cache methods]] ** The xPagecount() method must return the number of pages currently ** stored in the cache, both pinned and unpinned. ** ** [[the xFetch() page cache methods]] ** The xFetch() method locates a page in the cache and returns a pointer to ** the page, or a NULL pointer. ** A "page", in this context, means a buffer of szPage bytes aligned at an ** 8-byte boundary. The page to be fetched is determined by the key. ^The ** minimum key value is 1. After it has been retrieved using xFetch, the page ** is considered to be "pinned". ** ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the ** cache implementation should use the value of the createFlag ** parameter to help it determined what action to take: ** ** **
createFlag Behaviour when page is not already in cache **
0 Do not allocate a new page. Return NULL. **
1 Allocate a new page if it easy and convenient to do so. ** Otherwise return NULL. **
2 Make every effort to allocate a new page. Only return ** NULL if allocating a new page is effectively impossible. **
** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 ** failed.)^ In between the to xFetch() calls, SQLite may ** attempt to unpin one or more cache pages by spilling the content of ** pinned pages to disk and synching the operating system disk cache. ** ** [[the xUnpin() page cache method]] ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page ** as its second argument. If the third parameter, discard, is non-zero, ** then the page must be evicted from the cache. ** ^If the discard parameter is ** zero, then the page may be discarded or retained at the discretion of ** page cache implementation. ^The page cache implementation ** may choose to evict unpinned pages at any time. ** ** The cache must not perform any reference counting. A single ** call to xUnpin() unpins the page regardless of the number of prior calls ** to xFetch(). ** ** [[the xRekey() page cache methods]] ** The xRekey() method is used to change the key value associated with the ** page passed as the second argument. If the cache ** previously contains an entry associated with newKey, it must be ** discarded. ^Any prior cache entry associated with newKey is guaranteed not ** to be pinned. ** ** When SQLite calls the xTruncate() method, the cache must discard all ** existing cache entries with page numbers (keys) greater than or equal ** to the value of the iLimit parameter passed to xTruncate(). If any ** of these pages are pinned, they are implicitly unpinned, meaning that ** they can be safely discarded. ** ** [[the xDestroy() page cache method]] ** ^The xDestroy() method is used to delete a cache allocated by xCreate(). ** All resources associated with the specified cache should be freed. ^After ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] ** handle invalid, and will not use it with any other sqlite3_pcache_methods ** functions. */ typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; struct sqlite3_pcache_methods { void *pArg; int (*xInit)(void*); void (*xShutdown)(void*); sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); void (*xCachesize)(sqlite3_pcache*, int nCachesize); int (*xPagecount)(sqlite3_pcache*); void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); void (*xUnpin)(sqlite3_pcache*, void*, int discard); void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); void (*xDestroy)(sqlite3_pcache*); }; /* ** CAPI3REF: Online Backup Object ** ** The sqlite3_backup object records state information about an ongoing ** online backup operation. ^The sqlite3_backup object is created by ** a call to [sqlite3_backup_init()] and is destroyed by a call to ** [sqlite3_backup_finish()]. ** ** See Also: [Using the SQLite Online Backup API] */ typedef struct sqlite3_backup sqlite3_backup; /* ** CAPI3REF: Online Backup API. ** ** The backup API copies the content of one database into another. ** It is useful either for creating backups of databases or ** for copying in-memory databases to or from persistent files. ** ** See Also: [Using the SQLite Online Backup API] ** ** ^SQLite holds a write transaction open on the destination database file ** for the duration of the backup operation. ** ^The source database is read-locked only while it is being read; ** it is not locked continuously for the entire backup operation. ** ^Thus, the backup may be performed on a live source database without ** preventing other database connections from ** reading or writing to the source database while the backup is underway. ** ** ^(To perform a backup operation: **
    **
  1. sqlite3_backup_init() is called once to initialize the ** backup, **
  2. sqlite3_backup_step() is called one or more times to transfer ** the data between the two databases, and finally **
  3. sqlite3_backup_finish() is called to release all resources ** associated with the backup operation. **
)^ ** There should be exactly one call to sqlite3_backup_finish() for each ** successful call to sqlite3_backup_init(). ** ** [[sqlite3_backup_init()]] sqlite3_backup_init() ** ** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the ** [database connection] associated with the destination database ** and the database name, respectively. ** ^The database name is "main" for the main database, "temp" for the ** temporary database, or the name specified after the AS keyword in ** an [ATTACH] statement for an attached database. ** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. ** ^The error code and message for the failed call to sqlite3_backup_init() ** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or ** [sqlite3_errmsg16()] functions. ** ^A successful call to sqlite3_backup_init() returns a pointer to an ** [sqlite3_backup] object. ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and ** sqlite3_backup_finish() functions to perform the specified backup ** operation. ** ** [[sqlite3_backup_step()]] sqlite3_backup_step() ** ** ^Function sqlite3_backup_step(B,N) will copy up to N pages between ** the source and destination databases specified by [sqlite3_backup] object B. ** ^If N is negative, all remaining source pages are copied. ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there ** are still more pages to be copied, then the function returns [SQLITE_OK]. ** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages ** from source to destination, then it returns [SQLITE_DONE]. ** ^If an error occurs while running sqlite3_backup_step(B,N), ** then an [error code] is returned. ^As well as [SQLITE_OK] and ** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], ** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an ** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. ** ** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if **
    **
  1. the destination database was opened read-only, or **
  2. the destination database is using write-ahead-log journaling ** and the destination and source page sizes differ, or **
  3. the destination database is an in-memory database and the ** destination and source page sizes differ. **
)^ ** ** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then ** the [sqlite3_busy_handler | busy-handler function] ** is invoked (if one is specified). ^If the ** busy-handler returns non-zero before the lock is available, then ** [SQLITE_BUSY] is returned to the caller. ^In this case the call to ** sqlite3_backup_step() can be retried later. ^If the source ** [database connection] ** is being used to write to the source database when sqlite3_backup_step() ** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this ** case the call to sqlite3_backup_step() can be retried later on. ^(If ** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or ** [SQLITE_READONLY] is returned, then ** there is no point in retrying the call to sqlite3_backup_step(). These ** errors are considered fatal.)^ The application must accept ** that the backup operation has failed and pass the backup operation handle ** to the sqlite3_backup_finish() to release associated resources. ** ** ^The first call to sqlite3_backup_step() obtains an exclusive lock ** on the destination file. ^The exclusive lock is not released until either ** sqlite3_backup_finish() is called or the backup operation is complete ** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to ** sqlite3_backup_step() obtains a [shared lock] on the source database that ** lasts for the duration of the sqlite3_backup_step() call. ** ^Because the source database is not locked between calls to ** sqlite3_backup_step(), the source database may be modified mid-way ** through the backup process. ^If the source database is modified by an ** external process or via a database connection other than the one being ** used by the backup operation, then the backup will be automatically ** restarted by the next call to sqlite3_backup_step(). ^If the source ** database is modified by the using the same database connection as is used ** by the backup operation, then the backup database is automatically ** updated at the same time. ** ** [[sqlite3_backup_finish()]] sqlite3_backup_finish() ** ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the ** application wishes to abandon the backup operation, the application ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). ** ^The sqlite3_backup_finish() interfaces releases all ** resources associated with the [sqlite3_backup] object. ** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any ** active write-transaction on the destination database is rolled back. ** The [sqlite3_backup] object is invalid ** and may not be used following a call to sqlite3_backup_finish(). ** ** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no ** sqlite3_backup_step() errors occurred, regardless or whether or not ** sqlite3_backup_step() completed. ** ^If an out-of-memory condition or IO error occurred during any prior ** sqlite3_backup_step() call on the same [sqlite3_backup] object, then ** sqlite3_backup_finish() returns the corresponding [error code]. ** ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() ** is not a permanent error and does not affect the return value of ** sqlite3_backup_finish(). ** ** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] ** sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** ** ^Each call to sqlite3_backup_step() sets two values inside ** the [sqlite3_backup] object: the number of pages still to be backed ** up and the total number of pages in the source database file. ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces ** retrieve these two values, respectively. ** ** ^The values returned by these functions are only updated by ** sqlite3_backup_step(). ^If the source database is modified during a backup ** operation, then the values are not updated to account for any extra ** pages that need to be updated or the size of the source database file ** changing. ** ** Concurrent Usage of Database Handles ** ** ^The source [database connection] may be used by the application for other ** purposes while a backup operation is underway or being initialized. ** ^If SQLite is compiled and configured to support threadsafe database ** connections, then the source database connection may be used concurrently ** from within other threads. ** ** However, the application must guarantee that the destination ** [database connection] is not passed to any other API (by any thread) after ** sqlite3_backup_init() is called and before the corresponding call to ** sqlite3_backup_finish(). SQLite does not currently check to see ** if the application incorrectly accesses the destination [database connection] ** and so no error code is reported, but the operations may malfunction ** nevertheless. Use of the destination database connection while a ** backup is in progress might also also cause a mutex deadlock. ** ** If running in [shared cache mode], the application must ** guarantee that the shared cache used by the destination database ** is not accessed while the backup is running. In practice this means ** that the application must guarantee that the disk file being ** backed up to is not accessed by any connection within the process, ** not just the specific connection that was passed to sqlite3_backup_init(). ** ** The [sqlite3_backup] object itself is partially threadsafe. Multiple ** threads may safely make multiple concurrent calls to sqlite3_backup_step(). ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or ** individual tables within the shared-cache cannot be obtained. See ** [SQLite Shared-Cache Mode] for a description of shared-cache locking. ** ^This API may be used to register a callback that SQLite will invoke ** when the connection currently holding the required lock relinquishes it. ** ^This API is only available if the library was compiled with the ** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. ** ** See Also: [Using the SQLite Unlock Notification Feature]. ** ** ^Shared-cache locks are released when a database connection concludes ** its current transaction, either by committing it or rolling it back. ** ** ^When a connection (known as the blocked connection) fails to obtain a ** shared-cache lock and SQLITE_LOCKED is returned to the caller, the ** identity of the database connection (the blocking connection) that ** has locked the required resource is stored internally. ^After an ** application receives an SQLITE_LOCKED error, it may call the ** sqlite3_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite3_step] or [sqlite3_close] ** call that concludes the blocking connections transaction. ** ** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite3_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite3_unlock_notify().)^ ** ** ^If the blocked connection is attempting to obtain a write-lock on a ** shared-cache table, and more than one other connection currently holds ** a read-lock on the same table, then SQLite arbitrarily selects one of ** the other connections to use as the blocking connection. ** ** ^(There may be at most one unlock-notify callback registered by a ** blocked connection. If sqlite3_unlock_notify() is called when the ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing ** unlock-notify callback is canceled. ^The blocked connections ** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes ** any sqlite3_xxx API functions from within an unlock-notify callback, a ** crash or deadlock may be the result. ** ** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always ** returns SQLITE_OK. ** ** Callback Invocation Details ** ** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** ** When a blocking connections transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. ** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ** ** Deadlock Detection ** ** Assuming that after registering for an unlock-notify callback a ** database waits for the callback to be issued before taking any further ** action (a reasonable assumption), then using this API may cause the ** application to deadlock. For example, if connection X is waiting for ** connection Y's transaction to be concluded, and similarly connection ** Y is waiting on connection X's transaction, then neither connection ** will proceed and the system may remain deadlocked indefinitely. ** ** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock ** detection. ^If a given call to sqlite3_unlock_notify() would put the ** system in a deadlocked state, then SQLITE_LOCKED is returned and no ** unlock-notify callback is registered. The system is said to be in ** a deadlocked state if connection A has registered for an unlock-notify ** callback on the conclusion of connection B's transaction, and connection ** B has itself registered for an unlock-notify callback when connection ** A's transaction is concluded. ^Indirect deadlock is also detected, so ** the system is also considered to be deadlocked if connection B has ** registered for an unlock-notify callback on the conclusion of connection ** C's transaction, where connection C is waiting on connection A. ^Any ** number of levels of indirection are allowed. ** ** The "DROP TABLE" Exception ** ** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost ** always appropriate to call sqlite3_unlock_notify(). There is however, ** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, ** SQLite checks if there are any currently executing SELECT statements ** that belong to the same connection. If there are, SQLITE_LOCKED is ** returned. In this case there is no "blocking connection", so invoking ** sqlite3_unlock_notify() results in the unlock-notify callback being ** invoked immediately. If the application then re-attempts the "DROP TABLE" ** or "DROP INDEX" query, an infinite loop might be the result. ** ** One way around this problem is to check the extended error code returned ** by an sqlite3_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ ); /* ** CAPI3REF: String Comparison ** ** ^The [sqlite3_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-independent fashion, using the same definition of case independence ** that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: Error Logging Interface ** ** ^The [sqlite3_log()] interface writes a message into the error log ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** used with [sqlite3_snprintf()] to generate the final output string. ** ** The sqlite3_log() interface is intended for use by extensions such as ** virtual tables, collating functions, and SQL functions. While there is ** nothing to prevent an application from calling sqlite3_log(), doing so ** is considered bad form. ** ** The zFormat string must not be NULL. ** ** To avoid deadlocks and other threading problems, the sqlite3_log() routine ** will not use dynamically allocated memory. The log message is stored in ** a fixed-length buffer on the stack. If the log message is longer than ** a few hundred characters, it will be truncated to the length of the ** buffer. */ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** will be invoked each time a database connection commits data to a ** [write-ahead log] (i.e. whenever a transaction is committed in ** [journal_mode | journal_mode=WAL mode]). ** ** ^The callback is invoked by SQLite after the commit has taken place and ** the associated write-lock on the database released, so the implementation ** may read, write or [checkpoint] the database as required. ** ** ^The first parameter passed to the callback function when it is invoked ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. ^The second is a copy of the database handle. ** ^The third parameter is the name of the database that was written to - ** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter ** is the number of pages currently in the write-ahead log file, ** including those that were just committed. ** ** The callback function should normally return [SQLITE_OK]. ^If an error ** code is returned, that error will propagate back up through the ** SQLite code base to cause the statement that provoked the callback ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** previously registered write-ahead log callback. ^Note that the ** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** those overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* ); /* ** CAPI3REF: Configure an auto-checkpoint ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D ** to automatically [checkpoint] ** after committing a transaction if there are N or ** more frames in the [write-ahead log] file. ^Passing zero or ** a negative value as the nFrame parameter disables automatic ** checkpoints entirely. ** ** ^The callback registered by this function replaces any existing callback ** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism ** configured by this function. ** ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface ** from SQL. ** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] ** pages. The use of this interface ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database ** ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X ** on [database connection] D to be [checkpointed]. ^If X is NULL or an ** empty string, then a checkpoint is run on all databases of ** connection D. ^If the database connection D is not in ** [WAL | write-ahead log mode] then this interface is a harmless no-op. ** ** ^The [wal_checkpoint pragma] can be used to invoke this interface ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] can be used to cause this interface to be ** run whenever the WAL reaches a certain size threshold. ** ** See also: [sqlite3_wal_checkpoint_v2()] */ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database ** ** Run a checkpoint operation on WAL database zDb attached to database ** handle db. The specific operation is determined by the value of the ** eMode parameter: ** **
**
SQLITE_CHECKPOINT_PASSIVE
** Checkpoint as many frames as possible without waiting for any database ** readers or writers to finish. Sync the db file if all frames in the log ** are checkpointed. This mode is the same as calling ** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. ** **
SQLITE_CHECKPOINT_FULL
** This mode blocks (calls the busy-handler callback) until there is no ** database writer and all readers are reading from the most recent database ** snapshot. It then checkpoints all frames in the log file and syncs the ** database file. This call blocks database writers while it is running, ** but not database readers. ** **
SQLITE_CHECKPOINT_RESTART
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after ** checkpointing the log file it blocks (calls the busy-handler callback) ** until all readers are reading from the database file only. This ensures ** that the next client to write to the database file restarts the log file ** from the beginning. This call blocks database writers while it is running, ** but not database readers. **
** ** If pnLog is not NULL, then *pnLog is set to the total number of frames in ** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to ** the total number of checkpointed frames (including any that were already ** checkpointed when this function is called). *pnLog and *pnCkpt may be ** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. ** If no values are available because of an error, they are both set to -1 ** before returning to communicate this to the caller. ** ** All calls obtain an exclusive "checkpoint" lock on the database file. If ** any other process is running a checkpoint operation at the same time, the ** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a ** busy-handler configured, it will not be invoked in this case. ** ** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive ** "writer" lock on the database file. If the writer lock cannot be obtained ** immediately, and a busy-handler is configured, it is invoked and the writer ** lock retried until either the busy-handler returns 0 or the lock is ** successfully obtained. The busy-handler is also invoked while waiting for ** database readers as described above. If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the ** checkpoint operation proceeds from that point in the same way as ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible ** without blocking any further. SQLITE_BUSY is returned in this case. ** ** If parameter zDb is NULL or points to a zero length string, then the ** specified operation is attempted on all WAL databases. In this case the ** values written to output parameters *pnLog and *pnCkpt are undefined. If ** an SQLITE_BUSY error is encountered when processing one or more of the ** attached WAL databases, the operation is still attempted on any remaining ** attached databases and SQLITE_BUSY is returned to the caller. If any other ** error occurs while processing an attached database, processing is abandoned ** and the error code returned to the caller immediately. If no error ** (SQLITE_BUSY or otherwise) is encountered while processing the attached ** databases, SQLITE_OK is returned. ** ** If database zDb is the name of an attached database that is not in WAL ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If ** zDb is not NULL (or a zero length string) and is not the name of any ** attached database, SQLITE_ERROR is returned to the caller. */ SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ int *pnLog, /* OUT: Size of WAL log in frames */ int *pnCkpt /* OUT: Total number of frames checkpointed */ ); /* ** CAPI3REF: Checkpoint operation parameters ** ** These constants can be used as the 3rd parameter to ** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] ** documentation for additional information about the meaning and use of ** each of these values. */ #define SQLITE_CHECKPOINT_PASSIVE 0 #define SQLITE_CHECKPOINT_FULL 1 #define SQLITE_CHECKPOINT_RESTART 2 /* ** CAPI3REF: Virtual Table Interface Configuration ** ** This function may be called by either the [xConnect] or [xCreate] method ** of a [virtual table] implementation to configure ** various facets of the virtual table interface. ** ** If this interface is invoked outside the context of an xConnect or ** xCreate virtual table method then the behavior is undefined. ** ** At present, there is only one option that may be configured using ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** **
**
SQLITE_VTAB_CONSTRAINT_SUPPORT **
Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire ** statement is rolled back as if [ON CONFLICT | OR ABORT] had been ** specified as part of the users SQL statement, regardless of the actual ** ON CONFLICT mode specified. ** ** If X is non-zero, then the virtual table implementation guarantees ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before ** any modifications to internal or persistent data structures have been made. ** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite ** is able to roll back a statement or database transaction, and abandon ** or continue processing the current SQL statement as appropriate. ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode ** had been ABORT. ** ** Virtual table implementations that are required to handle OR REPLACE ** must do so within the [xUpdate] method. If a call to the ** [sqlite3_vtab_on_conflict()] function indicates that the current ON ** CONFLICT policy is REPLACE, the virtual table implementation should ** silently replace the appropriate rows within the xUpdate callback and ** return SQLITE_OK. Or, if this is not possible, it may return ** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT ** constraint handling. **
*/ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], ** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to ** inform a [virtual table] implementation what the [ON CONFLICT] mode ** is for the SQL statement being evaluated. ** ** Note that the [SQLITE_IGNORE] constant is also used as a potential ** return value from the [sqlite3_set_authorizer()] callback and that ** [SQLITE_ABORT] is also a [result code]. */ #define SQLITE_ROLLBACK 1 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ #define SQLITE_FAIL 3 /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #if 0 } /* End of the 'extern "C"' block */ #endif #endif /* ** 2010 August 30 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* */ #ifndef _SQLITE3RTREE_H_ #define _SQLITE3RTREE_H_ #if 0 extern "C" { #endif typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; /* ** Register a geometry callback named zGeom that can be used as part of an ** R-Tree geometry query as follows: ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), void *pContext ); /* ** A pointer to a structure of the following type is passed as the first ** argument to callbacks registered using rtree_geometry_callback(). */ struct sqlite3_rtree_geometry { void *pContext; /* Copy of pContext passed to s_r_g_c() */ int nParam; /* Size of array aParam[] */ double *aParam; /* Parameters passed to SQL geom function */ void *pUser; /* Callback implementation user data */ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; #if 0 } /* end of the 'extern "C"' block */ #endif #endif /* ifndef _SQLITE3RTREE_H_ */ /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include hash.h in the middle of sqliteInt.h ******************/ /************** Begin file hash.h ********************************************/ /* ** 2001 September 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; typedef struct HashElem HashElem; /* A complete hash table is an instance of the following structure. ** The internals of this structure are intended to be opaque -- client ** code should not attempt to access or modify the fields of this structure ** directly. Change this structure only by using the routines below. ** However, some of the "procedures" and "functions" for modifying and ** accessing this structure are really macros, so we can't really make ** this structure opaque. ** ** All elements of the hash table are on a single doubly-linked list. ** Hash.first points to the head of this list. ** ** There are Hash.htsize buckets. Each bucket points to a spot in ** the global doubly-linked list. The contents of the bucket are the ** element pointed to plus the next _ht.count-1 elements in the list. ** ** Hash.htsize and Hash.ht may be zero. In that case lookup is done ** by a linear search of the global list. For small tables, the ** Hash.ht table is never allocated because if there are few elements ** in the table, it is faster to do a linear search than to manage ** the hash table. */ struct Hash { unsigned int htsize; /* Number of buckets in the hash table */ unsigned int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ struct _ht { /* the hash table */ int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; /* Each element in the hash table is an instance of the following ** structure. All elements are stored on a single doubly-linked list. ** ** Again, this structure is intended to be opaque, but it can't really ** be opaque because it is used by macros. */ struct HashElem { HashElem *next, *prev; /* Next and previous elements in the table */ void *data; /* Data associated with this element */ const char *pKey; int nKey; /* Key associated with this element */ }; /* ** Access routines. To delete, insert a NULL pointer. */ SQLITE_PRIVATE void sqlite3HashInit(Hash*); SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); SQLITE_PRIVATE void sqlite3HashClear(Hash*); /* ** Macros for looping over all elements of a hash table. The idiom is ** like this: ** ** Hash h; ** HashElem *p; ** ... ** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ ** SomeStructure *pData = sqliteHashData(p); ** // do something with pData ** } */ #define sqliteHashFirst(H) ((H)->first) #define sqliteHashNext(E) ((E)->next) #define sqliteHashData(E) ((E)->data) /* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ /* #define sqliteHashCount(H) ((H)->count) // NOT USED */ #endif /* _SQLITE_HASH_H_ */ /************** End of hash.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include parse.h in the middle of sqliteInt.h *****************/ /************** Begin file parse.h *******************************************/ #define TK_SEMI 1 #define TK_EXPLAIN 2 #define TK_QUERY 3 #define TK_PLAN 4 #define TK_BEGIN 5 #define TK_TRANSACTION 6 #define TK_DEFERRED 7 #define TK_IMMEDIATE 8 #define TK_EXCLUSIVE 9 #define TK_COMMIT 10 #define TK_END 11 #define TK_ROLLBACK 12 #define TK_SAVEPOINT 13 #define TK_RELEASE 14 #define TK_TO 15 #define TK_TABLE 16 #define TK_CREATE 17 #define TK_IF 18 #define TK_NOT 19 #define TK_EXISTS 20 #define TK_TEMP 21 #define TK_LP 22 #define TK_RP 23 #define TK_AS 24 #define TK_COMMA 25 #define TK_ID 26 #define TK_INDEXED 27 #define TK_ABORT 28 #define TK_ACTION 29 #define TK_AFTER 30 #define TK_ANALYZE 31 #define TK_ASC 32 #define TK_ATTACH 33 #define TK_BEFORE 34 #define TK_BY 35 #define TK_CASCADE 36 #define TK_CAST 37 #define TK_COLUMNKW 38 #define TK_CONFLICT 39 #define TK_DATABASE 40 #define TK_DESC 41 #define TK_DETACH 42 #define TK_EACH 43 #define TK_FAIL 44 #define TK_FOR 45 #define TK_IGNORE 46 #define TK_INITIALLY 47 #define TK_INSTEAD 48 #define TK_LIKE_KW 49 #define TK_MATCH 50 #define TK_NO 51 #define TK_KEY 52 #define TK_OF 53 #define TK_OFFSET 54 #define TK_PRAGMA 55 #define TK_RAISE 56 #define TK_REPLACE 57 #define TK_RESTRICT 58 #define TK_ROW 59 #define TK_TRIGGER 60 #define TK_VACUUM 61 #define TK_VIEW 62 #define TK_VIRTUAL 63 #define TK_REINDEX 64 #define TK_RENAME 65 #define TK_CTIME_KW 66 #define TK_ANY 67 #define TK_OR 68 #define TK_AND 69 #define TK_IS 70 #define TK_BETWEEN 71 #define TK_IN 72 #define TK_ISNULL 73 #define TK_NOTNULL 74 #define TK_NE 75 #define TK_EQ 76 #define TK_GT 77 #define TK_LE 78 #define TK_LT 79 #define TK_GE 80 #define TK_ESCAPE 81 #define TK_BITAND 82 #define TK_BITOR 83 #define TK_LSHIFT 84 #define TK_RSHIFT 85 #define TK_PLUS 86 #define TK_MINUS 87 #define TK_STAR 88 #define TK_SLASH 89 #define TK_REM 90 #define TK_CONCAT 91 #define TK_COLLATE 92 #define TK_BITNOT 93 #define TK_STRING 94 #define TK_JOIN_KW 95 #define TK_CONSTRAINT 96 #define TK_DEFAULT 97 #define TK_NULL 98 #define TK_PRIMARY 99 #define TK_UNIQUE 100 #define TK_CHECK 101 #define TK_REFERENCES 102 #define TK_AUTOINCR 103 #define TK_ON 104 #define TK_INSERT 105 #define TK_DELETE 106 #define TK_UPDATE 107 #define TK_SET 108 #define TK_DEFERRABLE 109 #define TK_FOREIGN 110 #define TK_DROP 111 #define TK_UNION 112 #define TK_ALL 113 #define TK_EXCEPT 114 #define TK_INTERSECT 115 #define TK_SELECT 116 #define TK_DISTINCT 117 #define TK_DOT 118 #define TK_FROM 119 #define TK_JOIN 120 #define TK_USING 121 #define TK_ORDER 122 #define TK_GROUP 123 #define TK_HAVING 124 #define TK_LIMIT 125 #define TK_WHERE 126 #define TK_INTO 127 #define TK_VALUES 128 #define TK_INTEGER 129 #define TK_FLOAT 130 #define TK_BLOB 131 #define TK_REGISTER 132 #define TK_VARIABLE 133 #define TK_CASE 134 #define TK_WHEN 135 #define TK_THEN 136 #define TK_ELSE 137 #define TK_INDEX 138 #define TK_ALTER 139 #define TK_ADD 140 #define TK_TO_TEXT 141 #define TK_TO_BLOB 142 #define TK_TO_NUMERIC 143 #define TK_TO_INT 144 #define TK_TO_REAL 145 #define TK_ISNOT 146 #define TK_END_OF_FILE 147 #define TK_ILLEGAL 148 #define TK_SPACE 149 #define TK_UNCLOSED_STRING 150 #define TK_FUNCTION 151 #define TK_COLUMN 152 #define TK_AGG_FUNCTION 153 #define TK_AGG_COLUMN 154 #define TK_CONST_FUNC 155 #define TK_UMINUS 156 #define TK_UPLUS 157 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ #include #include #include #include #include /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define float sqlite_int64 # define LONGDOUBLE_TYPE sqlite_int64 # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif # define SQLITE_OMIT_DATETIME_FUNCS 1 # define SQLITE_OMIT_TRACE 1 # undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT # undef SQLITE_HAVE_ISNAN #endif #ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (1e99) #endif /* ** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 ** afterward. Having this macro allows us to cause the C compiler ** to omit code used by TEMP tables without messy #ifndef statements. */ #ifdef SQLITE_OMIT_TEMPDB #define OMIT_TEMPDB 1 #else #define OMIT_TEMPDB 0 #endif /* ** The "file format" number is an integer that is incremented whenever ** the VDBE-level file format changes. The following macros define the ** the default file format for new databases and the maximum file format ** that the library can read. */ #define SQLITE_MAX_FILE_FORMAT 4 #ifndef SQLITE_DEFAULT_FILE_FORMAT # define SQLITE_DEFAULT_FILE_FORMAT 1 #endif /* ** Determine whether triggers are recursive by default. This can be ** changed at run-time using a pragma. */ #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 #endif /* ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) */ #if 'A' == '\301' # define SQLITE_EBCDIC 1 #else # define SQLITE_ASCII 1 #endif /* ** Integers of known sizes. These typedefs might change for architectures ** where the sizes very. Preprocessor macros are available so that the ** types can be conveniently redefined at compile-type. Like this: ** ** cc '-DUINTPTR_TYPE=long long int' ... */ #ifndef UINT32_TYPE # ifdef HAVE_UINT32_T # define UINT32_TYPE uint32_t # else # define UINT32_TYPE unsigned int # endif #endif #ifndef UINT16_TYPE # ifdef HAVE_UINT16_T # define UINT16_TYPE uint16_t # else # define UINT16_TYPE unsigned short int # endif #endif #ifndef INT16_TYPE # ifdef HAVE_INT16_T # define INT16_TYPE int16_t # else # define INT16_TYPE short int # endif #endif #ifndef UINT8_TYPE # ifdef HAVE_UINT8_T # define UINT8_TYPE uint8_t # else # define UINT8_TYPE unsigned char # endif #endif #ifndef INT8_TYPE # ifdef HAVE_INT8_T # define INT8_TYPE int8_t # else # define INT8_TYPE signed char # endif #endif #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif typedef sqlite_int64 i64; /* 8-byte signed integer */ typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef INT8_TYPE i8; /* 1-byte signed integer */ /* ** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value ** that can be stored in a u32 without loss of data. The value ** is 0x00000000ffffffff. But because of quirks of some compilers, we ** have to specify the value in the less intuitive manner shown: */ #define SQLITE_MAX_U32 ((((u64)1)<<32)-1) /* ** The datatype used to store estimates of the number of rows in a ** table or index. This is an unsigned integer type. For 99.9% of ** the world, a 32-bit integer is sufficient. But a 64-bit integer ** can be used at compile-time if desired. */ #ifdef SQLITE_64BIT_STATS typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ #else typedef u32 tRowcnt; /* 32-bit is the default */ #endif /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ #ifdef SQLITE_AMALGAMATION SQLITE_PRIVATE const int sqlite3one = 1; #else SQLITE_PRIVATE const int sqlite3one; #endif #if defined(i386) || defined(__i386__) || defined(_M_IX86)\ || defined(__x86_64) || defined(__x86_64__) # define SQLITE_BIGENDIAN 0 # define SQLITE_LITTLEENDIAN 1 # define SQLITE_UTF16NATIVE SQLITE_UTF16LE #else # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) # define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) #endif /* ** Constants for the largest and smallest possible 64-bit signed integers. ** These macros are designed to work correctly on both 32-bit and 64-bit ** compilers. */ #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. */ #define ROUND8(x) (((x)+7)&~7) /* ** Round down to the nearest multiple of 8 */ #define ROUNDDOWN8(x) ((x)&~7) /* ** Assert that the pointer X is aligned to an 8-byte boundary. This ** macro is used only within assert() to verify that the code gets ** all alignment restrictions correct. ** ** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the ** underlying malloc() implemention might return us 4-byte aligned ** pointers. In that case, only verify 4-byte alignment. */ #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) #else # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) #endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { int (*xFunc)(void *,int); /* The busy callback */ void *pArg; /* First arg to busy callback */ int nBusy; /* Incremented with each busy call */ }; /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ #define MASTER_NAME "sqlite_master" #define TEMP_MASTER_NAME "sqlite_temp_master" /* ** The root-page of the master database table. */ #define MASTER_ROOT 1 /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** The following value as a destructor means to use sqlite3DbFree(). ** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. */ #define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does ** not support Writable Static Data (WSD) such as global and static variables. ** All variables must either be on the stack or dynamically allocated from ** the heap. When WSD is unsupported, the variable declarations scattered ** throughout the SQLite code must become constants instead. The SQLITE_WSD ** macro is used for this purpose. And instead of referencing the variable ** directly, we use its constant as a key to lookup the run-time allocated ** buffer that holds real variable. The constant is also the initializer ** for the run-time allocated buffer. ** ** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL ** macros become no-ops and have zero performance impact. */ #ifdef SQLITE_OMIT_WSD #define SQLITE_WSD const #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) SQLITE_API int sqlite3_wsd_init(int N, int J); SQLITE_API void *sqlite3_wsd_find(void *K, int L); #else #define SQLITE_WSD #define GLOBAL(t,v) v #define sqlite3GlobalConfig sqlite3Config #endif /* ** The following macros are used to suppress compiler warnings and to ** make it clear to human readers when a function parameter is deliberately ** left unused within the body of a function. This usually happens when ** a function is called via a function pointer. For example the ** implementation of an SQL aggregate step callback may not use the ** parameter indicating the number of arguments passed to the aggregate, ** if it knows that this is enforced elsewhere. ** ** When a function parameter is not used at all within the body of a function, ** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. ** However, these macros may also be used to suppress warnings related to ** parameters that may or may not be used depending on compilation options. ** For example those parameters only used in assert() statements. In these ** cases the parameters are named as per the usual conventions. */ #define UNUSED_PARAMETER(x) (void)(x) #define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WherePlan WherePlan; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque ** pointer types (i.e. FuncDef) defined above. */ /************** Include btree.h in the middle of sqliteInt.h *****************/ /************** Begin file btree.h *******************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ #define SQLITE_N_BTREE_META 10 /* ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". */ #ifndef SQLITE_DEFAULT_AUTOVACUUM #define SQLITE_DEFAULT_AUTOVACUUM 0 #endif #define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ #define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ #define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ const char *zFilename, /* Name of database file to open */ sqlite3 *db, /* Associated database connection */ Btree **ppBtree, /* Return open Btree* here */ int flags, /* Flags */ int vfsFlags /* Flags passed through to VFS open */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the ** following values. ** ** NOTE: These values must match the corresponding PAGER_ values in ** pager.h. */ #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ #define BTREE_MEMORY 4 /* This is an in-memory DB */ #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR ** of the flags shown below. ** ** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. ** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data ** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With ** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored ** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL ** indices.) */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** ** offset = 36 + (idx * 4) ** ** For example, the free-page-count field is located at byte offset 36 of ** the database file header. The incr-vacuum-flag field is located at ** byte offset 64 (== 36+4*7). */ #define BTREE_FREE_PAGE_COUNT 0 #define BTREE_SCHEMA_VERSION 1 #define BTREE_FILE_FORMAT 2 #define BTREE_DEFAULT_CACHE_SIZE 3 #define BTREE_LARGEST_ROOT_PAGE 4 #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( BtCursor*, UnpackedRecord *pUnKey, i64 intKey, int bias, int *pRes ); SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, int nZero, int bias, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *); SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); #ifndef NDEBUG SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); #endif #ifndef SQLITE_OMIT_BTREECOUNT SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); #endif #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); #endif #ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); #endif /* ** If we are not using shared cache, then there is no need to ** use mutexes to access the BtShared structures. So make the ** Enter and Leave procedures no-ops. */ #ifndef SQLITE_OMIT_SHARED_CACHE SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); #else # define sqlite3BtreeEnter(X) # define sqlite3BtreeEnterAll(X) #endif #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); #ifndef NDEBUG /* These routines are used inside assert() statements only. */ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); #endif #else # define sqlite3BtreeSharable(X) 0 # define sqlite3BtreeLeave(X) # define sqlite3BtreeEnterCursor(X) # define sqlite3BtreeLeaveCursor(X) # define sqlite3BtreeLeaveAll(X) # define sqlite3BtreeHoldsMutex(X) 1 # define sqlite3BtreeHoldsAllMutexes(X) 1 # define sqlite3SchemaMutexHeld(X,Y,Z) 1 #endif #endif /* _BTREE_H_ */ /************** End of btree.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include vdbe.h in the middle of sqliteInt.h ******************/ /************** Begin file vdbe.h ********************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ /* #include */ /* ** A single VDBE is an opaque structure named "Vdbe". Only routines ** in the source file sqliteVdbe.c are allowed to see the insides ** of this structure. */ typedef struct Vdbe Vdbe; /* ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; typedef struct SubProgram SubProgram; /* ** A single instruction of the virtual machine has an opcode ** and as many as three operands. The instruction is recorded ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */ u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ void *p; /* Generic pointer */ char *z; /* Pointer to data for string (char array) types */ i64 *pI64; /* Used when p4type is P4_INT64 */ double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ int (*xAdvance)(BtCursor *, int *); } p4; #ifdef SQLITE_DEBUG char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE int cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif }; typedef struct VdbeOp VdbeOp; /* ** A sub-routine used to implement a trigger program. */ struct SubProgram { VdbeOp *aOp; /* Array of opcodes for sub-program */ int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ void *token; /* id that may be used to recursive triggers */ SubProgram *pNext; /* Next sub-program already visited */ }; /* ** A smaller version of VdbeOp used for the VdbeAddOpList() function because ** it takes up less space. */ struct VdbeOpList { u8 opcode; /* What operation to perform */ signed char p1; /* First operand */ signed char p2; /* Second parameter (often the jump destination) */ signed char p3; /* Third parameter */ }; typedef struct VdbeOpList VdbeOpList; /* ** Allowed values of VdbeOp.p4type */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ #define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ #define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still ** gets freed when the Vdbe is finalized so it still should be obtained ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. */ #define P4_KEYINFO_HANDOFF (-16) #define P4_KEYINFO_STATIC (-17) /* ** The Vdbe.aColName array contains 5n Mem structures, where n is the ** number of columns of data returned by the statement. */ #define COLNAME_NAME 0 #define COLNAME_DECLTYPE 1 #define COLNAME_DATABASE 2 #define COLNAME_TABLE 3 #define COLNAME_COLUMN 4 #ifdef SQLITE_ENABLE_COLUMN_METADATA # define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ #else # ifdef SQLITE_OMIT_DECLTYPE # define COLNAME_N 1 /* Store only the name */ # else # define COLNAME_N 2 /* Store the name and decltype */ # endif #endif /* ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqlite3VdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ #define ADDR(X) (-1-(X)) /* ** The makefile scans the vdbe.c source file and creates the "opcodes.h" ** header file that defines a number for each opcode used by the VDBE. */ /************** Include opcodes.h in the middle of vdbe.h ********************/ /************** Begin file opcodes.h *****************************************/ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_Goto 1 #define OP_Gosub 2 #define OP_Return 3 #define OP_Yield 4 #define OP_HaltIfNull 5 #define OP_Halt 6 #define OP_Integer 7 #define OP_Int64 8 #define OP_Real 130 /* same as TK_FLOAT */ #define OP_String8 94 /* same as TK_STRING */ #define OP_String 9 #define OP_Null 10 #define OP_Blob 11 #define OP_Variable 12 #define OP_Move 13 #define OP_Copy 14 #define OP_SCopy 15 #define OP_ResultRow 16 #define OP_Concat 91 /* same as TK_CONCAT */ #define OP_Add 86 /* same as TK_PLUS */ #define OP_Subtract 87 /* same as TK_MINUS */ #define OP_Multiply 88 /* same as TK_STAR */ #define OP_Divide 89 /* same as TK_SLASH */ #define OP_Remainder 90 /* same as TK_REM */ #define OP_CollSeq 17 #define OP_Function 18 #define OP_BitAnd 82 /* same as TK_BITAND */ #define OP_BitOr 83 /* same as TK_BITOR */ #define OP_ShiftLeft 84 /* same as TK_LSHIFT */ #define OP_ShiftRight 85 /* same as TK_RSHIFT */ #define OP_AddImm 20 #define OP_MustBeInt 21 #define OP_RealAffinity 22 #define OP_ToText 141 /* same as TK_TO_TEXT */ #define OP_ToBlob 142 /* same as TK_TO_BLOB */ #define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ #define OP_ToInt 144 /* same as TK_TO_INT */ #define OP_ToReal 145 /* same as TK_TO_REAL */ #define OP_Eq 76 /* same as TK_EQ */ #define OP_Ne 75 /* same as TK_NE */ #define OP_Lt 79 /* same as TK_LT */ #define OP_Le 78 /* same as TK_LE */ #define OP_Gt 77 /* same as TK_GT */ #define OP_Ge 80 /* same as TK_GE */ #define OP_Permutation 23 #define OP_Compare 24 #define OP_Jump 25 #define OP_And 69 /* same as TK_AND */ #define OP_Or 68 /* same as TK_OR */ #define OP_Not 19 /* same as TK_NOT */ #define OP_BitNot 93 /* same as TK_BITNOT */ #define OP_Once 26 #define OP_If 27 #define OP_IfNot 28 #define OP_IsNull 73 /* same as TK_ISNULL */ #define OP_NotNull 74 /* same as TK_NOTNULL */ #define OP_Column 29 #define OP_Affinity 30 #define OP_MakeRecord 31 #define OP_Count 32 #define OP_Savepoint 33 #define OP_AutoCommit 34 #define OP_Transaction 35 #define OP_ReadCookie 36 #define OP_SetCookie 37 #define OP_VerifyCookie 38 #define OP_OpenRead 39 #define OP_OpenWrite 40 #define OP_OpenAutoindex 41 #define OP_OpenEphemeral 42 #define OP_SorterOpen 43 #define OP_OpenPseudo 44 #define OP_Close 45 #define OP_SeekLt 46 #define OP_SeekLe 47 #define OP_SeekGe 48 #define OP_SeekGt 49 #define OP_Seek 50 #define OP_NotFound 51 #define OP_Found 52 #define OP_IsUnique 53 #define OP_NotExists 54 #define OP_Sequence 55 #define OP_NewRowid 56 #define OP_Insert 57 #define OP_InsertInt 58 #define OP_Delete 59 #define OP_ResetCount 60 #define OP_SorterCompare 61 #define OP_SorterData 62 #define OP_RowKey 63 #define OP_RowData 64 #define OP_Rowid 65 #define OP_NullRow 66 #define OP_Last 67 #define OP_SorterSort 70 #define OP_Sort 71 #define OP_Rewind 72 #define OP_SorterNext 81 #define OP_Prev 92 #define OP_Next 95 #define OP_SorterInsert 96 #define OP_IdxInsert 97 #define OP_IdxDelete 98 #define OP_IdxRowid 99 #define OP_IdxLT 100 #define OP_IdxGE 101 #define OP_Destroy 102 #define OP_Clear 103 #define OP_CreateIndex 104 #define OP_CreateTable 105 #define OP_ParseSchema 106 #define OP_LoadAnalysis 107 #define OP_DropTable 108 #define OP_DropIndex 109 #define OP_DropTrigger 110 #define OP_IntegrityCk 111 #define OP_RowSetAdd 112 #define OP_RowSetRead 113 #define OP_RowSetTest 114 #define OP_Program 115 #define OP_Param 116 #define OP_FkCounter 117 #define OP_FkIfZero 118 #define OP_MemMax 119 #define OP_IfPos 120 #define OP_IfNeg 121 #define OP_IfZero 122 #define OP_AggStep 123 #define OP_AggFinal 124 #define OP_Checkpoint 125 #define OP_JournalMode 126 #define OP_Vacuum 127 #define OP_IncrVacuum 128 #define OP_Expire 129 #define OP_TableLock 131 #define OP_VBegin 132 #define OP_VCreate 133 #define OP_VDestroy 134 #define OP_VOpen 135 #define OP_VFilter 136 #define OP_VColumn 137 #define OP_VNext 138 #define OP_VRename 139 #define OP_VUpdate 140 #define OP_Pagecount 146 #define OP_MaxPgcnt 147 #define OP_Trace 148 #define OP_Noop 149 #define OP_Explain 150 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c ** are encoded into bitvectors as follows: */ #define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ #define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ #define OPFLG_IN1 0x0004 /* in1: P1 is an input */ #define OPFLG_IN2 0x0008 /* in2: P2 is an input */ #define OPFLG_IN3 0x0010 /* in3: P3 is an input */ #define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ #define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\ /* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\ /* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\ /* 24 */ 0x00, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\ /* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\ /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\ /* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\ /* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\ /* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ /* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\ /* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\ /* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\ /* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\ /* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\ /* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*); SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); #endif SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif #ifndef NDEBUG SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite3VdbeComment X SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); # define VdbeNoopComment(X) sqlite3VdbeNoopComment X #else # define VdbeComment(X) # define VdbeNoopComment(X) #endif #endif /************** End of vdbe.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include pager.h in the middle of sqliteInt.h *****************/ /************** Begin file pager.h *******************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. */ #ifndef _PAGER_H_ #define _PAGER_H_ /* ** Default maximum size for persistent journal files. A negative ** value means no limit. This value may be overridden using the ** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". */ #ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 #endif /* ** The type used to represent a page number. The first page in a file ** is called page 1. 0 is used to represent "not a page". */ typedef u32 Pgno; /* ** Each open file is managed by a separate instance of the "Pager" structure. */ typedef struct Pager Pager; /* ** Handle type for pages. */ typedef struct PgHdr DbPage; /* ** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is ** reserved for working around a windows/posix incompatibility). It is ** used in the journal to signify that the remainder of the journal file ** is devoted to storing a master journal name - there are no more pages to ** roll back. See comments for function writeMasterJournal() in pager.c ** for details. */ #define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) /* ** Allowed values for the flags parameter to sqlite3PagerOpen(). ** ** NOTE: These values must match the corresponding BTREE_ values in btree.h. */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ #define PAGER_MEMORY 0x0004 /* In-memory database */ /* ** Valid values for the second argument to sqlite3PagerLockingMode(). */ #define PAGER_LOCKINGMODE_QUERY -1 #define PAGER_LOCKINGMODE_NORMAL 0 #define PAGER_LOCKINGMODE_EXCLUSIVE 1 /* ** Numeric constants that encode the journalmode. */ #define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ #define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ #define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ #define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ #define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ #define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ /* ** The remainder of this file contains the declarations of the functions ** that make up the Pager sub-system API. See source code comments for ** a detailed description of each routine. */ /* Open and close a Pager connection. */ SQLITE_PRIVATE int sqlite3PagerOpen( sqlite3_vfs*, Pager **ppPager, const char*, int, int, int, void(*)(DbPage*) ); SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); /* Functions used to obtain and release page references. */ SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); /* Operations on page references. */ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); /* Functions used to manage pager transactions and savepoints. */ SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); /* Functions used to query pager state and configuration. */ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*); SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *); /* Functions used to truncate the database file. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); #endif /* Functions to support testing and debugging. */ #if !defined(NDEBUG) || defined(SQLITE_TEST) SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); #endif #ifdef SQLITE_TEST SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); void disable_simulated_io_errors(void); void enable_simulated_io_errors(void); #else # define disable_simulated_io_errors() # define enable_simulated_io_errors() #endif #endif /* _PAGER_H_ */ /************** End of pager.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include pcache.h in the middle of sqliteInt.h ****************/ /************** Begin file pcache.h ******************************************/ /* ** 2008 August 05 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. */ #ifndef _PCACHE_H_ typedef struct PgHdr PgHdr; typedef struct PCache PCache; /* ** Every page in the cache is controlled by an instance of the following ** structure. */ struct PgHdr { void *pData; /* Content of this page */ void *pExtra; /* Extra content */ PgHdr *pDirty; /* Transient list of dirty pages */ Pgno pgno; /* Page number for this page */ Pager *pPager; /* The pager this page is part of */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; /* Hash of page content */ #endif u16 flags; /* PGHDR flags defined below */ /********************************************************************** ** Elements above are public. All that follows is private to pcache.c ** and should not be accessed by other modules. */ i16 nRef; /* Number of users of this page */ PCache *pCache; /* Cache that owns this page */ PgHdr *pDirtyNext; /* Next element in list of dirty pages */ PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ }; /* Bit values for PgHdr.flags */ #define PGHDR_DIRTY 0x002 /* Page has changed */ #define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before ** writing this page to the database */ #define PGHDR_NEED_READ 0x008 /* Content is unread */ #define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ /* Initialize and shutdown the page cache subsystem */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void); SQLITE_PRIVATE void sqlite3PcacheShutdown(void); /* Page cache buffer management: ** These routines implement SQLITE_CONFIG_PAGECACHE. */ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); /* Create a new pager cache. ** Under memory stress, invoke xStress to try to make pages clean. ** Only clean and unpinned pages can be reclaimed. */ SQLITE_PRIVATE void sqlite3PcacheOpen( int szPage, /* Size of every page */ int szExtra, /* Extra space associated with each page */ int bPurgeable, /* True if pages are on backing store */ int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ void *pStress, /* Argument to xStress */ PCache *pToInit /* Preallocated space for the PCache */ ); /* Modify the page-size after the cache has been created. */ SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int); /* Return the size in bytes of a PCache object. Used to preallocate ** storage space. */ SQLITE_PRIVATE int sqlite3PcacheSize(void); /* One release per successful fetch. Page is pinned until released. ** Reference counted. */ SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**); SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ /* Change a page number. Used by incr-vacuum. */ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); /* Remove all pages with pgno>x. Reset the cache if x==0 */ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); /* Get a list of all dirty pages in the cache, sorted by page number */ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); /* Reset and close the cache object */ SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); /* Clear flags from pages of the page cache */ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); /* Discard the contents of the cache */ SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); /* Return the total number of outstanding page references */ SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); /* Increment the reference count of an existing page */ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); /* Return the total number of pages stored in the cache */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* Iterate through all dirty pages currently stored in the cache. This ** interface is only available if SQLITE_CHECK_PAGES is defined when the ** library is built. */ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); #endif /* Set and get the suggested cache-size for the specified pager-cache. ** ** If no global maximum is configured, then the system attempts to limit ** the total number of pages cached by purgeable pager-caches to the sum ** of the suggested cache-sizes. */ SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); #endif #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* Try to return memory used by the pcache module to the main memory heap */ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); #endif #ifdef SQLITE_TEST SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); #endif SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); #endif /* _PCACHE_H_ */ /************** End of pcache.h **********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include os.h in the middle of sqliteInt.h ********************/ /************** Begin file os.h **********************************************/ /* ** 2001 September 16 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file (together with is companion C source-code file ** "os.c") attempt to abstract the underlying operating system so that ** the SQLite library will work on both POSIX and windows systems. ** ** This header file is #include-ed by sqliteInt.h and thus ends up ** being included by every source file. */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. After the following block of preprocess macros, ** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER ** will defined to either 1 or 0. One of the four will be 1. The other ** three will be 0. */ #if defined(SQLITE_OS_OTHER) # if SQLITE_OS_OTHER==1 # undef SQLITE_OS_UNIX # define SQLITE_OS_UNIX 0 # undef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # undef SQLITE_OS_OS2 # define SQLITE_OS_OS2 0 # else # undef SQLITE_OS_OTHER # endif #endif #if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) # define SQLITE_OS_OTHER 0 # ifndef SQLITE_OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) # define SQLITE_OS_WIN 1 # define SQLITE_OS_UNIX 0 # define SQLITE_OS_OS2 0 # elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) # define SQLITE_OS_WIN 0 # define SQLITE_OS_UNIX 0 # define SQLITE_OS_OS2 1 # else # define SQLITE_OS_WIN 0 # define SQLITE_OS_UNIX 1 # define SQLITE_OS_OS2 0 # endif # else # define SQLITE_OS_UNIX 0 # define SQLITE_OS_OS2 0 # endif #else # ifndef SQLITE_OS_WIN # define SQLITE_OS_WIN 0 # endif #endif /* ** Determine if we are dealing with WindowsCE - which has a much ** reduced API. */ #if defined(_WIN32_WCE) # define SQLITE_OS_WINCE 1 #else # define SQLITE_OS_WINCE 0 #endif /* ** Define the maximum size of a temporary filename */ #if SQLITE_OS_WIN # include # define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) #elif SQLITE_OS_OS2 # if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) # include /* has to be included before os2.h for linking to work */ # endif # define INCL_DOSDATETIME # define INCL_DOSFILEMGR # define INCL_DOSERRORS # define INCL_DOSMISC # define INCL_DOSPROCESS # define INCL_DOSMODULEMGR # define INCL_DOSSEMAPHORES # include # include # define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) #else # define SQLITE_TEMPNAME_SIZE 200 #endif /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ #ifndef SET_FULLSYNC # define SET_FULLSYNC(x,y) #endif /* ** The default size of a disk sector */ #ifndef SQLITE_DEFAULT_SECTOR_SIZE # define SQLITE_DEFAULT_SECTOR_SIZE 512 #endif /* ** Temporary files are named starting with this prefix followed by 16 random ** alphanumeric characters, and no file extension. They are stored in the ** OS's standard temporary file directory, and are deleted prior to exit. ** If sqlite is being embedded in another program, you may wish to change the ** prefix to reflect your program's name, so that if your program exits ** prematurely, old temporary files can be easily identified. This can be done ** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. ** ** 2006-10-31: The default prefix used to be "sqlite_". But then ** Mcafee started using SQLite in their anti-virus product and it ** started putting files with the "sqlite" name in the c:/temp folder. ** This annoyed many windows users. Those users would then do a ** Google search for "sqlite", find the telephone numbers of the ** developers and call to wake them up at night and complain. ** For this reason, the default name prefix is changed to be "sqlite" ** spelled backwards. So the temp files are still identified, but ** anybody smart enough to figure out the code is also likely smart ** enough to know that calling the developer will not help get rid ** of the file. */ #ifndef SQLITE_TEMP_FILE_PREFIX # define SQLITE_TEMP_FILE_PREFIX "etilqs_" #endif /* ** The following values may be passed as the second argument to ** sqlite3OsLock(). The various locks exhibit the following semantics: ** ** SHARED: Any number of processes may hold a SHARED lock simultaneously. ** RESERVED: A single process may hold a RESERVED lock on a file at ** any time. Other processes may hold and obtain new SHARED locks. ** PENDING: A single process may hold a PENDING lock on a file at ** any one time. Existing SHARED locks may persist, but no new ** SHARED locks may be obtained by other processes. ** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. ** ** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a ** process that requests an EXCLUSIVE lock may actually obtain a PENDING ** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to ** sqlite3OsLock(). */ #define NO_LOCK 0 #define SHARED_LOCK 1 #define RESERVED_LOCK 2 #define PENDING_LOCK 3 #define EXCLUSIVE_LOCK 4 /* ** File Locking Notes: (Mostly about windows but also some info for Unix) ** ** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because ** those functions are not available. So we use only LockFile() and ** UnlockFile(). ** ** LockFile() prevents not just writing but also reading by other processes. ** A SHARED_LOCK is obtained by locking a single randomly-chosen ** byte out of a specific range of bytes. The lock byte is obtained at ** random so two separate readers can probably access the file at the ** same time, unless they are unlucky and choose the same lock byte. ** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. ** There can only be one writer. A RESERVED_LOCK is obtained by locking ** a single byte of the file that is designated as the reserved lock byte. ** A PENDING_LOCK is obtained by locking a designated byte different from ** the RESERVED_LOCK byte. ** ** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, ** which means we can use reader/writer locks. When reader/writer locks ** are used, the lock is placed on the same range of bytes that is used ** for probabilistic locking in Win95/98/ME. Hence, the locking scheme ** will support two or more Win95 readers or two or more WinNT readers. ** But a single Win95 reader will lock out all WinNT readers and a single ** WinNT reader will lock out all other Win95 readers. ** ** The following #defines specify the range of bytes used for locking. ** SHARED_SIZE is the number of bytes available in the pool from which ** a random byte is selected for a shared lock. The pool of bytes for ** shared locks begins at SHARED_FIRST. ** ** The same locking strategy and ** byte ranges are used for Unix. This leaves open the possiblity of having ** clients on win95, winNT, and unix all talking to the same shared file ** and all locking correctly. To do so would require that samba (or whatever ** tool is being used for file sharing) implements locks correctly between ** windows and unix. I'm guessing that isn't likely to happen, but by ** using the same locking range we are at least open to the possibility. ** ** Locking in windows is manditory. For this reason, we cannot store ** actual data in the bytes used for locking. The pager never allocates ** the pages involved in locking therefore. SHARED_SIZE is selected so ** that all locks will fit on a single page even at the minimum page size. ** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE ** is set high so that we don't have to allocate an unused page except ** for very large databases. But one should test the page skipping logic ** by setting PENDING_BYTE low and running the entire regression suite. ** ** Changing the value of PENDING_BYTE results in a subtly incompatible ** file format. Depending on how it is changed, you might not notice ** the incompatibility right away, even running a full regression test. ** The default location of PENDING_BYTE is the first byte past the ** 1GB boundary. ** */ #ifdef SQLITE_OMIT_WSD # define PENDING_BYTE (0x40000000) #else # define PENDING_BYTE sqlite3PendingByte #endif #define RESERVED_BYTE (PENDING_BYTE+1) #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 /* ** Wrapper around OS specific sqlite3_os_init() function. */ SQLITE_PRIVATE int sqlite3OsInit(void); /* ** Functions for accessing sqlite3_file methods */ SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); /* ** Functions for accessing sqlite3_vfs methods */ SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); #endif /* SQLITE_OMIT_LOAD_EXTENSION */ SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); /* ** Convenience functions for opening and closing files using ** sqlite3_malloc() to obtain space for the file-handle structure. */ SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); #endif /* _SQLITE_OS_H_ */ /************** End of os.h **************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include mutex.h in the middle of sqliteInt.h *****************/ /************** Begin file mutex.h *******************************************/ /* ** 2007 August 28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains the common header for all mutex implementations. ** The sqliteInt.h header #includes this file so that it is available ** to all source files. We break it out in an effort to keep the code ** better organized. ** ** NOTE: source files should *not* #include this header file directly. ** Source files should #include the sqliteInt.h file and let that file ** include this one indirectly. */ /* ** Figure out what version of the code to use. The choices are ** ** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The ** mutexes implemention cannot be overridden ** at start-time. ** ** SQLITE_MUTEX_NOOP For single-threaded applications. No ** mutual exclusion is provided. But this ** implementation can be overridden at ** start-time. ** ** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. ** ** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. ** ** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. */ #if !SQLITE_THREADSAFE # define SQLITE_MUTEX_OMIT #endif #if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) # if SQLITE_OS_UNIX # define SQLITE_MUTEX_PTHREADS # elif SQLITE_OS_WIN # define SQLITE_MUTEX_W32 # elif SQLITE_OS_OS2 # define SQLITE_MUTEX_OS2 # else # define SQLITE_MUTEX_NOOP # endif #endif #ifdef SQLITE_MUTEX_OMIT /* ** If this is a no-op implementation, implement everything as macros. */ #define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) #define sqlite3_mutex_free(X) #define sqlite3_mutex_enter(X) #define sqlite3_mutex_try(X) SQLITE_OK #define sqlite3_mutex_leave(X) #define sqlite3_mutex_held(X) ((void)(X),1) #define sqlite3_mutex_notheld(X) ((void)(X),1) #define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) #define sqlite3MutexInit() SQLITE_OK #define sqlite3MutexEnd() #define MUTEX_LOGIC(X) #else #define MUTEX_LOGIC(X) X #endif /* defined(SQLITE_MUTEX_OMIT) */ /************** End of mutex.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /* ** Each database file to be accessed by the system is an instance ** of the following structure. There are normally two of these structures ** in the sqlite.aDb[] array. aDb[0] is the main database file and ** aDb[1] is the database file used to hold temporary tables. Additional ** databases may be attached. */ struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at syncing data to disk */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; /* ** An instance of the following structure stores a database schema. ** ** Most Schema objects are associated with a Btree. The exception is ** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. ** In shared cache mode, a single Schema object can be shared by multiple ** Btrees that refer to the same underlying BtShared object. ** ** Schema objects are automatically deallocated when the last Btree that ** references them is destroyed. The TEMP Schema is manually freed by ** sqlite3_close(). * ** A thread must be holding a mutex on the corresponding Btree in order ** to access Schema content. This implies that the thread must also be ** holding a mutex on the sqlite3 connection pointer that owns the Btree. ** For a TEMP Schema, only the connection mutex is required. */ struct Schema { int schema_cookie; /* Database schema version number for this file */ int iGeneration; /* Generation counter. Incremented with each change */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash fkeyHash; /* All foreign keys by referenced table name */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ u8 file_format; /* Schema format version for this file */ u8 enc; /* Text encoding used by this database */ u16 flags; /* Flags associated with this schema */ int cache_size; /* Number of pages to use in the cache */ }; /* ** These macros can be used to test, set, or clear bits in the ** Db.pSchema->flags field. */ #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) /* ** Allowed values for the DB.pSchema->flags field. ** ** The DB_SchemaLoaded flag is set after the database schema has been ** read into internal hash tables. ** ** DB_UnresetViews means that one or more views have column names that ** have been filled out. If the schema changes, these column names might ** changes and so the view will need to be reset. */ #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ #define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ /* ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ #define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used ** to satisfy small transient memory allocation requests for objects ** associated with a particular database connection. The use of ** lookaside malloc provides a significant performance enhancement ** (approx 10%) by avoiding numerous malloc/free requests while parsing ** SQL statements. ** ** The Lookaside structure holds configuration information about the ** lookaside malloc subsystem. Each available memory allocation in ** the lookaside subsystem is stored on a linked list of LookasideSlot ** objects. ** ** Lookaside allocations are only allowed for objects that are associated ** with a particular database connection. Hence, schema information cannot ** be stored in lookaside because in shared cache mode the schema information ** is shared by multiple database connections. Therefore, while parsing ** schema information, the Lookaside.bEnabled flag is cleared so that ** lookaside allocations are not used to construct the schema objects. */ struct Lookaside { u16 sz; /* Size of each buffer in bytes */ u8 bEnabled; /* False to disable new lookaside allocations */ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ int nOut; /* Number of buffers currently checked out */ int mxOut; /* Highwater mark for nOut */ int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ LookasideSlot *pFree; /* List of available buffers */ void *pStart; /* First byte of available memory space */ void *pEnd; /* First byte past end of available space */ }; struct LookasideSlot { LookasideSlot *pNext; /* Next buffer in the list of free buffers */ }; /* ** A hash table for function definitions. ** ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. ** Collisions are on the FuncDef.pHash chain. */ struct FuncDefHash { FuncDef *a[23]; /* Hash table for functions */ }; /* ** Each database connection is an instance of the following structure. ** ** The sqlite.lastRowid records the last insert rowid generated by an ** insert statement. Inserts on views do not affect its value. Each ** trigger has its own context, so that lastRowid can be updated inside ** triggers as usual. The previous value will be restored once the trigger ** exits. Upon entering a before or instead of trigger, lastRowid is no ** longer (since after version 2.8.12) reset to -1. ** ** The sqlite.nChange does not count changes within triggers and keeps no ** context. It is reset at start of sqlite3_exec. ** The sqlite.lsChange represents the number of changes made by the last ** insert, update, or delete statement. It remains constant throughout the ** length of a statement and is then updated by OP_SetCounts. It keeps a ** context stack just like lastRowid so that the count of changes ** within a trigger is not seen outside the trigger. Changes to views do not ** affect the value of lsChange. ** The sqlite.csChange keeps track of the number of current changes (since ** the last statement) and is used to update sqlite_lsChange. ** ** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 ** store the most recent error code and, if applicable, string. The ** internal function sqlite3Error() is used to set these variables ** consistently. */ struct sqlite3 { sqlite3_vfs *pVfs; /* OS Interface */ int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ int flags; /* Miscellaneous flags. See below */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ sqlite3_mutex *mutex; /* Connection mutex */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of VDBEs currently executing */ int writeVdbeCnt; /* Number of active VDBEs that are writing */ int vdbeExecCnt; /* Number of nested calls to VdbeExec() */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*); /* Invoked at every commit. */ void *pRollbackArg; /* Argument to xRollbackCallback() */ void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; #endif void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pErr; /* Most recent error message */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ union { volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ double notUsed1; /* Spacer */ } u1; Lookaside lookaside; /* Lookaside malloc configuration */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ int nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE Hash aModule; /* populated by sqlite3_create_module() */ VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ VTable **aVTrans; /* Virtual tables with open transactions */ int nVTrans; /* Allocated size of aVTrans */ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ #endif FuncDefHash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ int busyTimeout; /* Busy handler timeout, in msec */ Db aDbStatic[2]; /* Static space for the 2 default backends */ Savepoint *pSavepoint; /* List of active savepoints */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MASTER ** mutex, not by sqlite3.mutex. They are used by code in notify.c. ** ** When X.pUnlockConnection==Y, that means that X is waiting for Y to ** unlock so that it can proceed. ** ** When X.pBlockingConnection==Y, that means that something that X tried ** tried to do recently failed with an SQLITE_LOCKED error due to locks ** held by Y. */ sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ void *pUnlockArg; /* Argument to xUnlockNotify */ void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ #endif }; /* ** A macro to discover the encoding of a database. */ #define ENC(db) ((db)->aDb[0].pSchema->enc) /* ** Possible values for the sqlite3.flags. */ #define SQLITE_VdbeTrace 0x00000100 /* True to trace VDBE execution */ #define SQLITE_InternChanges 0x00000200 /* Uncommitted Hash table changes */ #define SQLITE_FullColNames 0x00000400 /* Show full column names on SELECT */ #define SQLITE_ShortColNames 0x00000800 /* Show short columns names */ #define SQLITE_CountRows 0x00001000 /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00002000 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */ #define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when ** accessing read-only databases */ #define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00400000 /* Use full fsync for checkpoint */ #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x20000000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x40000000 /* True to enable triggers */ /* ** Bits of the sqlite3.flags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ #define SQLITE_ColumnCache 0x02 /* Disable the column cache */ #define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */ #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */ #define SQLITE_IndexCover 0x10 /* Disable index covering table */ #define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */ #define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */ #define SQLITE_OptMask 0xff /* Mask of all disablable opts */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ #define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ #define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ #define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ #define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { i16 nArg; /* Number of arguments. -1 means unlimited */ u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ u8 flags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ char *zName; /* SQL name of the function. */ FuncDef *pHash; /* Next with a different name but the same hash */ FuncDestructor *pDestructor; /* Reference counted destructor function */ }; /* ** This structure encapsulates a user-function destructor callback (as ** configured using create_function_v2()) and a reference counter. When ** create_function_v2() is called to create a function with a destructor, ** a single object of this type is allocated. FuncDestructor.nRef is set to ** the number of FuncDef objects created (either 1 or 3, depending on whether ** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor ** member of each of the new FuncDef objects is set to point to the allocated ** FuncDestructor. ** ** Thereafter, when one of the FuncDef objects is deleted, the reference ** count on this object is decremented. When it reaches 0, the destructor ** is invoked and the FuncDestructor structure freed. */ struct FuncDestructor { int nRef; void (*xDestroy)(void *); void *pUserData; }; /* ** Possible values for FuncDef.flags */ #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ #define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ #define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ #define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */ #define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */ #define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** ** FUNCTION(zName, nArg, iArg, bNC, xFunc) ** Used to create a scalar function definition of a function zName ** implemented by C function xFunc that accepts nArg arguments. The ** value passed as iArg is cast to a (void*) and made available ** as the user-data (sqlite3_user_data()) for the function. If ** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** ** LIKEFUNC(zName, nArg, pArg, flags) ** Used to create a scalar function definition of a function zName ** that accepts nArg arguments and is implemented by a call to C ** function likeFunc. Argument pArg is cast to a (void *) and made ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ pArg, 0, xFunc, 0, 0, #zName, 0, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently ** opened savepoint. Savepoints are added to the list by the vdbe ** OP_Savepoint instruction. */ struct Savepoint { char *zName; /* Savepoint name (nul-terminated) */ i64 nDeferredCons; /* Number of deferred fk violations */ Savepoint *pNext; /* Parent savepoint (if any) */ }; /* ** The following are used as the second parameter to sqlite3Savepoint(), ** and as the P1 argument to the OP_Savepoint instruction. */ #define SAVEPOINT_BEGIN 0 #define SAVEPOINT_RELEASE 1 #define SAVEPOINT_ROLLBACK 2 /* ** Each SQLite module (virtual table definition) is defined by an ** instance of the following structure, stored in the sqlite3.aModule ** hash table. */ struct Module { const sqlite3_module *pModule; /* Callback pointers */ const char *zName; /* Name passed to create_module() */ void *pAux; /* pAux passed to create_module() */ void (*xDestroy)(void *); /* Module destructor function */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE_AFF_... values */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 isHidden; /* True if this column is 'hidden' */ #endif }; /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** There may two separate implementations of the collation function, one ** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine ** native byte order. When a collation sequence is invoked, SQLite selects ** the version that will require the least expensive encoding ** translations, if any. ** ** The CollSeq.pUser member variable is an extra parameter that passed in ** as the first argument to the UTF-8 comparison function, xCmp. ** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, ** xCmp16. ** ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ u8 type; /* One of the SQLITE_COLL_... values below */ void *pUser; /* First argument to xCmp() */ int (*xCmp)(void*,int, const void*, int, const void*); void (*xDel)(void*); /* Destructor for pUser */ }; /* ** Allowed values of CollSeq.type: */ #define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ #define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ #define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ #define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ /* ** A sort order can be either ASC or DESC. */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */ /* ** Column affinity types. ** ** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and ** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve ** the speed a little by numbering the values consecutively. ** ** But rather than start with 0 or 1, we begin with 'a'. That way, ** when multiple affinity types are concatenated into a string and ** used as the P4 operand, they will be more readable. ** ** Note also that the numeric types are grouped together so that testing ** for a numeric type is a single comparison. */ #define SQLITE_AFF_TEXT 'a' #define SQLITE_AFF_NONE 'b' #define SQLITE_AFF_NUMERIC 'c' #define SQLITE_AFF_INTEGER 'd' #define SQLITE_AFF_REAL 'e' #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** The SQLITE_AFF_MASK values masks off the significant bits of an ** affinity value. */ #define SQLITE_AFF_MASK 0x67 /* ** Additional bit values that can be ORed with an affinity without ** changing the affinity. */ #define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ /* ** An object of this type is created for each virtual table present in ** the database schema. ** ** If the database schema is shared, then there is one instance of this ** structure for each database connection (sqlite3*) that uses the shared ** schema. This is because each database connection requires its own unique ** instance of the sqlite3_vtab* handle used to access the virtual table ** implementation. sqlite3_vtab* handles can not be shared between ** database connections, even when the rest of the in-memory database ** schema is shared, as the implementation often stores the database ** connection handle passed to it via the xConnect() or xCreate() method ** during initialization internally. This database connection handle may ** then be used by the virtual table implementation to access real tables ** within the database. So that they appear as part of the callers ** transaction, these accesses need to be made via the same database ** connection as that used to execute SQL operations on the virtual table. ** ** All VTable objects that correspond to a single table in a shared ** database schema are initially stored in a linked-list pointed to by ** the Table.pVTable member variable of the corresponding Table object. ** When an sqlite3_prepare() operation is required to access the virtual ** table, it searches the list for the VTable that corresponds to the ** database connection doing the preparing so as to use the correct ** sqlite3_vtab* handle in the compiled query. ** ** When an in-memory Table object is deleted (for example when the ** schema is being reloaded for some reason), the VTable objects are not ** deleted and the sqlite3_vtab* handles are not xDisconnect()ed ** immediately. Instead, they are moved from the Table.pVTable list to ** another linked list headed by the sqlite3.pDisconnect member of the ** corresponding sqlite3 structure. They are then deleted/xDisconnected ** next time a statement is prepared using said sqlite3*. This is done ** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. ** Refer to comments above function sqlite3VtabUnlockList() for an ** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect ** list without holding the corresponding sqlite3.mutex mutex. ** ** The memory for objects of this type is always allocated by ** sqlite3DbMalloc(), using the connection handle stored in VTable.db as ** the first argument. */ struct VTable { sqlite3 *db; /* Database connection associated with this table */ Module *pMod; /* Pointer to module implementation */ sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ int iSavepoint; /* Depth of the SAVEPOINT stack */ VTable *pNext; /* Next in linked list (see above) */ }; /* ** Each SQL table is represented in memory by an instance of the ** following structure. ** ** Table.zName is the name of the table. The case of the original ** CREATE TABLE statement is stored, but case is not significant for ** comparisons. ** ** Table.nCol is the number of columns in this table. Table.aCol is a ** pointer to an array of Column structures, one for each column. ** ** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of ** the column that is that key. Otherwise Table.iPKey is negative. Note ** that the datatype of the PRIMARY KEY must be INTEGER for this field to ** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of ** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid ** is generated for each row of the table. TF_HasPrimaryKey is set if ** the table has any PRIMARY KEY, INTEGER or otherwise. ** ** Table.tnum is the page number for the root BTree page of the table in the ** database file. If Table.iDb is the index of the database table backend ** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that ** holds temporary tables and indices. If TF_Ephemeral is set ** then the table is stored in a file that is automatically deleted ** when the VDBE cursor to the table is closed. In this case Table.tnum ** refers VDBE cursor number that holds the table open, not to the root ** page number. Transient tables are used to hold the results of a ** sub-query that appears instead of a real table name in the FROM clause ** of a SELECT statement. */ struct Table { char *zName; /* Name of the table or view */ int iPKey; /* If not negative, use aCol[iPKey] as the primary key */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Root BTree node for this table (see note above) */ tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ u16 nRef; /* Number of pointers to this Table */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_CHECK Expr *pCheck; /* The AND of all CHECK constraints */ #endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE VTable *pVTable; /* List of VTable objects. */ int nModuleArg; /* Number of arguments to the module */ char **azModuleArg; /* Text of all module args. [0] is module name */ #endif Trigger *pTrigger; /* List of triggers stored in pSchema */ Schema *pSchema; /* Schema that contains this table */ Table *pNextZombie; /* Next on the Parse.pZombieTab list */ }; /* ** Allowed values for Tabe.tabFlags. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ #define TF_HasPrimaryKey 0x04 /* Table has a primary key */ #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ #define TF_Virtual 0x10 /* Is a virtual table */ #define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */ /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) # define IsHiddenColumn(X) ((X)->isHidden) #else # define IsVirtual(X) 0 # define IsHiddenColumn(X) 0 #endif /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign ** key. The "to" table is the table that is named in the REFERENCES clause. ** Consider this example: ** ** CREATE TABLE ex1( ** a INTEGER PRIMARY KEY, ** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) ** ); ** ** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". ** ** Each REFERENCES clause generates an instance of the following structure ** which is attached to the from-table. The to-table need not exist when ** the from-table is created. The existence of the to-table is not checked. */ struct FKey { Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ FKey *pNextFrom; /* Next foreign key in pFrom */ char *zTo; /* Name of table that the key points to (aka: Parent) */ FKey *pNextTo; /* Next foreign key on table named zTo */ FKey *pPrevTo; /* Previous foreign key on table named zTo */ int nCol; /* Number of columns in this key */ /* EV: R-30323-21917 */ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ Trigger *apTrigger[2]; /* Triggers for aAction[] actions */ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ int iFrom; /* Index of column in pFrom */ char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ } aCol[1]; /* One entry for each of nCol column s */ }; /* ** SQLite supports many different ways to resolve a constraint ** error. ROLLBACK processing means that a constraint violation ** causes the operation in process to fail and for the current transaction ** to be rolled back. ABORT processing means the operation in process ** fails and any prior changes from that one operation are backed out, ** but the transaction is not rolled back. FAIL processing means that ** the operation in progress stops and returns an error code. But prior ** changes due to the same operation are not backed out and no rollback ** occurs. IGNORE means that the particular row that caused the constraint ** error is not inserted or updated. Processing continues and no error ** is returned. REPLACE means that preexisting database rows that caused ** a UNIQUE constraint violation are removed so that the new insert or ** update can proceed. Processing continues and no error is reported. ** ** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. ** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the ** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign ** key is set to NULL. CASCADE means that a DELETE or UPDATE of the ** referenced table row is propagated into the row that holds the ** foreign key. ** ** The following symbolic values are used to record which type ** of action to take. */ #define OE_None 0 /* There is no constraint to check */ #define OE_Rollback 1 /* Fail the operation and rollback the transaction */ #define OE_Abort 2 /* Back out changes but do no rollback transaction */ #define OE_Fail 3 /* Stop the operation but leave all prior changes */ #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ #define OE_SetNull 7 /* Set the foreign key value to NULL */ #define OE_SetDflt 8 /* Set the foreign key value to its default */ #define OE_Cascade 9 /* Cascade the changes */ #define OE_Default 99 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nField; /* Number of entries in aColl[] */ u8 *aSortOrder; /* Sort order for each column. May be NULL */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; /* ** An instance of the following structure holds information about a ** single index record that has already been parsed out into individual ** values. ** ** A record is an object that contains one or more fields of data. ** Records are used to store the content of a table row and to store ** the key of an index. A blob encoding of a record is created by ** the OP_MakeRecord opcode of the VDBE and is disassembled by the ** OP_Column opcode. ** ** This structure holds a record that has already been disassembled ** into its constituent fields. */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ u16 flags; /* Boolean settings. UNPACKED_... below */ i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */ Mem *aMem; /* Values */ }; /* ** Allowed values of UnpackedRecord.flags */ #define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */ #define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */ #define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */ #define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */ #define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */ #define UNPACKED_PREFIX_SEARCH 0x0020 /* A prefix match is considered OK */ /* ** Each SQL index is represented in memory by an ** instance of the following structure. ** ** The columns of the table that are to be indexed are described ** by the aiColumn[] field of this structure. For example, suppose ** we have the following table and index: ** ** CREATE TABLE Ex1(c1 int, c2 int, c3 text); ** CREATE INDEX Ex2 ON Ex1(c3,c1); ** ** In the Table structure describing Ex1, nCol==3 because there are ** three columns in the table. In the Index structure describing ** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. ** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the ** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. ** The second column to be indexed (c1) has an index of 0 in ** Ex1.aCol[], hence Ex2.aiColumn[1]==0. ** ** The Index.onError field determines whether or not the indexed columns ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ u8 bUnordered; /* Use this index for == or IN queries only */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ #ifdef SQLITE_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; /* ** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ struct IndexSample { union { char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ double r; /* Value if eType is SQLITE_FLOAT */ i64 i; /* Value if eType is SQLITE_INTEGER */ } u; u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ int nByte; /* Size in byte of text or blob. */ tRowcnt nEq; /* Est. number of rows where the key equals this sample */ tRowcnt nLt; /* Est. number of rows where key is less than this sample */ tRowcnt nDLt; /* Est. number of distinct keys less than this sample */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** Note if Token.z==0 then Token.dyn and Token.n are undefined and ** may contain random values. Do not make any assumptions about Token.dyn ** and Token.n when Token.z==0. */ struct Token { const char *z; /* Text of the token. Not NULL-terminated! */ unsigned int n; /* Number of characters in this token */ }; /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. ** ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a ** pointer to this structure. The Expr.iColumn field is the index in ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate ** code for that node. ** ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the ** original Select structure that describes the SELECT statement. These ** fields do not need to be freed when deallocating the AggInfo structure. */ struct AggInfo { u8 directMode; /* Direct rendering mode means take data directly ** from source tables rather than from accumulators */ u8 useSortingIdx; /* In direct mode, reference the sorting index rather ** than the source table */ int sortingIdx; /* Cursor number of the sorting index */ int sortingIdxPTab; /* Cursor number of pseudo-table */ ExprList *pGroupBy; /* The group by clause */ int nSortingColumn; /* Number of columns in the sorting index */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ int iTable; /* Cursor number of the source table */ int iColumn; /* Column number within the source table */ int iSorterColumn; /* Column number in the sorting index */ int iMem; /* Memory location that acts as accumulator */ Expr *pExpr; /* The original expression */ } *aCol; int nColumn; /* Number of used entries in aCol[] */ int nColumnAlloc; /* Number of slots allocated for aCol[] */ int nAccumulator; /* Number of columns that show through to the output. ** Additional columns are used only as parameters to ** aggregate functions */ struct AggInfo_func { /* For each aggregate function */ Expr *pExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ int iMem; /* Memory location that acts as accumulator */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ int nFuncAlloc; /* Number of slots allocated for aFunc[] */ }; /* ** The datatype ynVar is a signed integer, either 16-bit or 32-bit. ** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater ** than 32767 we have to make it 32-bit. 16-bit is preferred because ** it uses less memory in the Expr object, which is a big memory user ** in systems with lots of prepared statements. And few applications ** need more than about 10 or 20 variables. But some extreme users want ** to have prepared statements with over 32767 variables, and for them ** the option is available (at compile-time). */ #if SQLITE_MAX_VARIABLE_NUMBER<=32767 typedef i16 ynVar; #else typedef int ynVar; #endif /* ** Each node of an expression in the parse tree is an instance ** of this structure. ** ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** ** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, ** or TK_STRING), then Expr.token contains the text of the SQL literal. If ** the expression is a variable (TK_VARIABLE), then Expr.token contains the ** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), ** then Expr.token contains the name of the function. ** ** Expr.pRight and Expr.pLeft are the left and right subexpressions of a ** binary operator. Either or both may be NULL. ** ** Expr.x.pList is a list of arguments if the expression is an SQL function, ** a CASE expression or an IN expression of the form " IN (, ...)". ** Expr.x.pSelect is used if the expression is a sub-select or an expression of ** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the ** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is ** valid. ** ** An expression of the form ID or ID.ID refers to a column in a table. ** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is ** the integer cursor number of a VDBE cursor pointing to that table and ** Expr.iColumn is the column number for the specific column. If the ** expression is used as a result in an aggregate SELECT, then the ** value is also stored in the Expr.iAgg column in the aggregate so that ** it can be accessed after all aggregates are computed. ** ** If the expression is an unbound variable marker (a question mark ** character '?' in the original SQL) then the Expr.iTable holds the index ** number for that variable. ** ** If the expression is a subquery then Expr.iColumn holds an integer ** register number containing the result of the subquery. If the ** subquery gives a constant result, then iTable is -1. If the subquery ** gives a different answer at different times during statement processing ** then iTable is the address of a subroutine that computes the subquery. ** ** If the Expr is of type OP_Column, and the table it is selecting from ** is a disk table or the "old.*" pseudo-table, then pTab points to the ** corresponding table definition. ** ** ALLOCATION NOTES: ** ** Expr objects can use a lot of memory space in database schema. To ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, ** together with Expr.zToken strings. ** ** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all ** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees ** are contained within the same memory allocation. Note, however, that ** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately ** allocated, regardless of whether or not EP_Reduced is set. */ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ u16 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ } u; /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { ExprList *pList; /* Function arguments or in " IN ( IN (